xref: /openbsd/sys/arch/luna88k/dev/omrasops1.c (revision 4b4ddd04)
1 /*	$OpenBSD: omrasops1.c,v 1.4 2021/07/31 05:22:36 aoyama Exp $	*/
2 
3 /*
4  * Copyright (c) 2005, Miodrag Vallat.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  *
28  */
29 /*
30  * Copyright (c) 1996 Jason R. Thorpe.  All rights reserved.
31  * Copyright (c) 1991 University of Utah.
32  * Copyright (c) 1990, 1993
33  *	The Regents of the University of California.  All rights reserved.
34  *
35  * This code is derived from software contributed to Berkeley by
36  * the Systems Programming Group of the University of Utah Computer
37  * Science Department and Mark Davies of the Department of Computer
38  * Science, Victoria University of Wellington, New Zealand.
39  *
40  * Redistribution and use in source and binary forms, with or without
41  * modification, are permitted provided that the following conditions
42  * are met:
43  * 1. Redistributions of source code must retain the above copyright
44  *    notice, this list of conditions and the following disclaimer.
45  * 2. Redistributions in binary form must reproduce the above copyright
46  *    notice, this list of conditions and the following disclaimer in the
47  *    documentation and/or other materials provided with the distribution.
48  * 3. Neither the name of the University nor the names of its contributors
49  *    may be used to endorse or promote products derived from this software
50  *    without specific prior written permission.
51  *
52  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
53  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
54  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
55  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
56  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
57  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
58  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
59  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
60  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
61  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
62  * SUCH DAMAGE.
63  *
64  * from: Utah $Hdr: grf_hy.c 1.2 93/08/13$
65  *
66  *	@(#)grf_hy.c	8.4 (Berkeley) 1/12/94
67  */
68 
69 /*
70  * Graphics routines for OMRON LUNA 1bpp and 4bpp frame buffer.
71  * On LUNA's frame buffer, pixels are not byte-addressed.
72  *
73  * Based on src/sys/arch/hp300/dev/diofb_mono.c
74  */
75 
76 #include <sys/param.h>
77 #include <sys/systm.h>
78 
79 #include <dev/wscons/wsconsio.h>
80 #include <dev/wscons/wsdisplayvar.h>
81 #include <dev/rasops/rasops.h>
82 #include <dev/rasops/rasops_masks.h>
83 
84 #include <luna88k/dev/maskbits.h>
85 #include <luna88k/dev/omrasops.h>
86 
87 #include <machine/board.h>
88 #define	OMFB_FB_WADDR	(BMAP_BMP + 8)	/* common plane */
89 
90 /* prototypes */
91 int om1_windowmove(struct rasops_info *, u_int16_t, u_int16_t,
92 	u_int16_t, u_int16_t, u_int16_t, u_int16_t, int16_t,
93 	int16_t /* ignored */);
94 int om4_windowmove(struct rasops_info *, u_int16_t, u_int16_t,
95 	u_int16_t, u_int16_t, u_int16_t, u_int16_t, int16_t,
96 	int16_t /* ignored */);
97 
98 /*
99  * Block-move function - 1bpp version
100  */
101 int
om1_windowmove(struct rasops_info * ri,u_int16_t sx,u_int16_t sy,u_int16_t dx,u_int16_t dy,u_int16_t cx,u_int16_t cy,int16_t rop,int16_t planemask)102 om1_windowmove(struct rasops_info *ri, u_int16_t sx, u_int16_t sy,
103 	u_int16_t dx, u_int16_t dy, u_int16_t cx, u_int16_t cy, int16_t rop,
104 	int16_t planemask /* ignored */)
105 {
106 	int width;		/* add to get to same position in next line */
107 
108 	u_int32_t *psrcLine, *pdstLine;
109 				/* pointers to line with current src and dst */
110 	u_int32_t *psrc;	/* pointer to current src longword */
111 	u_int32_t *pdst;	/* pointer to current dst longword */
112 
113 				/* following used for looping through a line */
114 	u_int32_t startmask, endmask;  /* masks for writing ends of dst */
115 	int nlMiddle;		/* whole longwords in dst */
116 	int nl;			/* temp copy of nlMiddle */
117 	int xoffSrc;		/* offset (>= 0, < 32) from which to
118 				   fetch whole longwords fetched in src */
119 	int nstart;		/* number of ragged bits at start of dst */
120 	int nend;		/* number of ragged bits at end of dst */
121 	int srcStartOver;	/* pulling nstart bits from src
122 				   overflows into the next word? */
123 
124 	width = ri->ri_stride / 4;	/* convert to number in longword */
125 
126 	if (sy < dy) {	/* start at last scanline of rectangle */
127 		psrcLine = ((u_int32_t *)OMFB_FB_WADDR)
128 				 + ((sy + cy - 1) * width);
129 		pdstLine = ((u_int32_t *)OMFB_FB_WADDR)
130 				 + ((dy + cy - 1) * width);
131 		width = -width;
132 	} else {	/* start at first scanline */
133 		psrcLine = ((u_int32_t *)OMFB_FB_WADDR) + (sy * width);
134 		pdstLine = ((u_int32_t *)OMFB_FB_WADDR) + (dy * width);
135 	}
136 
137 	/* x direction doesn't matter for < 1 longword */
138 	if (cx <= 32) {
139 		int srcBit, dstBit;	/* bit offset of src and dst */
140 
141 		pdstLine += (dx >> 5);
142 		psrcLine += (sx >> 5);
143 		psrc = psrcLine;
144 		pdst = pdstLine;
145 
146 		srcBit = sx & 0x1f;
147 		dstBit = dx & 0x1f;
148 
149 		while (cy--) {
150 			getandputrop(P0(psrc), srcBit, dstBit, cx, P0(pdst), rop);
151 			pdst += width;
152 			psrc += width;
153 		}
154 	} else {
155 		maskbits(dx, cx, startmask, endmask, nlMiddle);
156 		if (startmask)
157 			nstart = 32 - (dx & 0x1f);
158 		else
159 			nstart = 0;
160 		if (endmask)
161 			nend = (dx + cx) & 0x1f;
162 		else
163 			nend = 0;
164 
165 		xoffSrc = ((sx & 0x1f) + nstart) & 0x1f;
166 		srcStartOver = ((sx & 0x1f) + nstart) > 31;
167 
168 		if (sx >= dx) {	/* move left to right */
169 			pdstLine += (dx >> 5);
170 			psrcLine += (sx >> 5);
171 
172 			while (cy--) {
173 				psrc = psrcLine;
174 				pdst = pdstLine;
175 
176 				if (startmask) {
177 					getandputrop(P0(psrc), (sx & 0x1f),
178 					    (dx & 0x1f), nstart, P0(pdst), rop);
179 					pdst++;
180 					if (srcStartOver)
181 						psrc++;
182 				}
183 
184 				/* special case for aligned operations */
185 				if (xoffSrc == 0) {
186 					nl = nlMiddle;
187 					while (nl--) {
188 						if (rop == RR_CLEAR)
189 							*P0(pdst) = 0;
190 						else
191 							*P0(pdst) = *P0(psrc);
192 						psrc++;
193 						pdst++;
194 					}
195 				} else {
196 					nl = nlMiddle + 1;
197 					while (--nl) {
198 						if (rop == RR_CLEAR)
199 							*P0(pdst) = 0;
200 						else
201 							getunalignedword(P0(psrc),
202 							    xoffSrc, *P0(pdst));
203 						pdst++;
204 						psrc++;
205 					}
206 				}
207 
208 				if (endmask) {
209 					getandputrop(P0(psrc), xoffSrc, 0, nend,
210 					    P0(pdst), rop);
211 				}
212 
213 				pdstLine += width;
214 				psrcLine += width;
215 			}
216 		} else {	/* move right to left */
217 			pdstLine += ((dx + cx) >> 5);
218 			psrcLine += ((sx + cx) >> 5);
219 			/*
220 			 * If fetch of last partial bits from source crosses
221 			 * a longword boundary, start at the previous longword
222 			 */
223 			if (xoffSrc + nend >= 32)
224 				--psrcLine;
225 
226 			while (cy--) {
227 				psrc = psrcLine;
228 				pdst = pdstLine;
229 
230 				if (endmask) {
231 					getandputrop(P0(psrc), xoffSrc, 0, nend,
232 					    P0(pdst), rop);
233 				}
234 
235 				nl = nlMiddle + 1;
236 				while (--nl) {
237 					--psrc;
238 					--pdst;
239 					if (rop == RR_CLEAR)
240 						*P0(pdst) = 0;
241 					else
242 						getunalignedword(P0(psrc), xoffSrc,
243 						    *P0(pdst));
244 				}
245 
246 				if (startmask) {
247 					if (srcStartOver)
248 						--psrc;
249 					--pdst;
250 					getandputrop(P0(psrc), (sx & 0x1f),
251 					    (dx & 0x1f), nstart, P0(pdst), rop);
252 				}
253 
254 				pdstLine += width;
255 				psrcLine += width;
256 			}
257 		}
258 	}
259 
260 	return (0);
261 }
262 
263 /*
264  * Block-move function - 4bpp version
265  */
266 int
om4_windowmove(struct rasops_info * ri,u_int16_t sx,u_int16_t sy,u_int16_t dx,u_int16_t dy,u_int16_t cx,u_int16_t cy,int16_t rop,int16_t planemask)267 om4_windowmove(struct rasops_info *ri, u_int16_t sx, u_int16_t sy,
268 	u_int16_t dx, u_int16_t dy, u_int16_t cx, u_int16_t cy, int16_t rop,
269 	int16_t planemask /* ignored */)
270 {
271 	int width;		/* add to get to same position in next line */
272 
273 	u_int32_t *psrcLine, *pdstLine;
274 				/* pointers to line with current src and dst */
275 	u_int32_t *psrc;	/* pointer to current src longword */
276 	u_int32_t *pdst;	/* pointer to current dst longword */
277 
278 				/* following used for looping through a line */
279 	u_int32_t startmask, endmask;  /* masks for writing ends of dst */
280 	int nlMiddle;		/* whole longwords in dst */
281 	int nl;			/* temp copy of nlMiddle */
282 	int xoffSrc;		/* offset (>= 0, < 32) from which to
283 				   fetch whole longwords fetched in src */
284 	int nstart;		/* number of ragged bits at start of dst */
285 	int nend;		/* number of ragged bits at end of dst */
286 	int srcStartOver;	/* pulling nstart bits from src
287 				   overflows into the next word? */
288 
289 	width = ri->ri_stride / 4;	/* convert to number in longword */
290 
291 	if (sy < dy) {	/* start at last scanline of rectangle */
292 		psrcLine = ((u_int32_t *)OMFB_FB_WADDR)
293 				 + ((sy + cy - 1) * width);
294 		pdstLine = ((u_int32_t *)OMFB_FB_WADDR)
295 				 + ((dy + cy - 1) * width);
296 		width = -width;
297 	} else {	/* start at first scanline */
298 		psrcLine = ((u_int32_t *)OMFB_FB_WADDR) + (sy * width);
299 		pdstLine = ((u_int32_t *)OMFB_FB_WADDR) + (dy * width);
300 	}
301 
302 	/* x direction doesn't matter for < 1 longword */
303 	if (cx <= 32) {
304 		int srcBit, dstBit;	/* bit offset of src and dst */
305 
306 		pdstLine += (dx >> 5);
307 		psrcLine += (sx >> 5);
308 		psrc = psrcLine;
309 		pdst = pdstLine;
310 
311 		srcBit = sx & 0x1f;
312 		dstBit = dx & 0x1f;
313 
314 		while (cy--) {
315 			getandputrop(P0(psrc), srcBit, dstBit, cx, P0(pdst), rop);
316 			getandputrop(P1(psrc), srcBit, dstBit, cx, P1(pdst), rop);
317 			getandputrop(P2(psrc), srcBit, dstBit, cx, P2(pdst), rop);
318 			getandputrop(P3(psrc), srcBit, dstBit, cx, P3(pdst), rop);
319 			pdst += width;
320 			psrc += width;
321 		}
322 	} else {
323 		maskbits(dx, cx, startmask, endmask, nlMiddle);
324 		if (startmask)
325 			nstart = 32 - (dx & 0x1f);
326 		else
327 			nstart = 0;
328 		if (endmask)
329 			nend = (dx + cx) & 0x1f;
330 		else
331 			nend = 0;
332 
333 		xoffSrc = ((sx & 0x1f) + nstart) & 0x1f;
334 		srcStartOver = ((sx & 0x1f) + nstart) > 31;
335 
336 		if (sx >= dx) {	/* move left to right */
337 			pdstLine += (dx >> 5);
338 			psrcLine += (sx >> 5);
339 
340 			while (cy--) {
341 				psrc = psrcLine;
342 				pdst = pdstLine;
343 
344 				if (startmask) {
345 					getandputrop(P0(psrc), (sx & 0x1f),
346 					    (dx & 0x1f), nstart, P0(pdst), rop);
347 					getandputrop(P1(psrc), (sx & 0x1f),
348 					    (dx & 0x1f), nstart, P1(pdst), rop);
349 					getandputrop(P2(psrc), (sx & 0x1f),
350 					    (dx & 0x1f), nstart, P2(pdst), rop);
351 					getandputrop(P3(psrc), (sx & 0x1f),
352 					    (dx & 0x1f), nstart, P3(pdst), rop);
353 					pdst++;
354 					if (srcStartOver)
355 						psrc++;
356 				}
357 
358 				/* special case for aligned operations */
359 				if (xoffSrc == 0) {
360 					nl = nlMiddle;
361 					while (nl--) {
362 						if (rop == RR_CLEAR) {
363 							*P0(pdst) = 0;
364 							*P1(pdst) = 0;
365 							*P2(pdst) = 0;
366 							*P3(pdst) = 0;
367 						} else {
368 							*P0(pdst) = *P0(psrc);
369 							*P1(pdst) = *P1(psrc);
370 							*P2(pdst) = *P2(psrc);
371 							*P3(pdst) = *P3(psrc);
372 						}
373 						psrc++;
374 						pdst++;
375 					}
376 				} else {
377 					nl = nlMiddle + 1;
378 					while (--nl) {
379 						if (rop == RR_CLEAR) {
380 							*P0(pdst) = 0;
381 							*P1(pdst) = 0;
382 							*P2(pdst) = 0;
383 							*P3(pdst) = 0;
384 						} else {
385 							getunalignedword(P0(psrc),
386 							    xoffSrc, *P0(pdst));
387 							getunalignedword(P1(psrc),
388 							    xoffSrc, *P1(pdst));
389 							getunalignedword(P2(psrc),
390 							    xoffSrc, *P2(pdst));
391 							getunalignedword(P3(psrc),
392 							    xoffSrc, *P3(pdst));
393 						}
394 						pdst++;
395 						psrc++;
396 					}
397 				}
398 
399 				if (endmask) {
400 					getandputrop(P0(psrc), xoffSrc, 0, nend,
401 					    P0(pdst), rop);
402 					getandputrop(P1(psrc), xoffSrc, 0, nend,
403 					    P1(pdst), rop);
404 					getandputrop(P2(psrc), xoffSrc, 0, nend,
405 					    P2(pdst), rop);
406 					getandputrop(P3(psrc), xoffSrc, 0, nend,
407 					    P3(pdst), rop);
408 				}
409 
410 				pdstLine += width;
411 				psrcLine += width;
412 			}
413 		} else {	/* move right to left */
414 			pdstLine += ((dx + cx) >> 5);
415 			psrcLine += ((sx + cx) >> 5);
416 			/*
417 			 * If fetch of last partial bits from source crosses
418 			 * a longword boundary, start at the previous longword
419 			 */
420 			if (xoffSrc + nend >= 32)
421 				--psrcLine;
422 
423 			while (cy--) {
424 				psrc = psrcLine;
425 				pdst = pdstLine;
426 
427 				if (endmask) {
428 					getandputrop(P0(psrc), xoffSrc, 0, nend,
429 					    P0(pdst), rop);
430 					getandputrop(P1(psrc), xoffSrc, 0, nend,
431 					    P1(pdst), rop);
432 					getandputrop(P2(psrc), xoffSrc, 0, nend,
433 					    P2(pdst), rop);
434 					getandputrop(P3(psrc), xoffSrc, 0, nend,
435 					    P3(pdst), rop);
436 				}
437 
438 				nl = nlMiddle + 1;
439 				while (--nl) {
440 					--psrc;
441 					--pdst;
442 					if (rop == RR_CLEAR) {
443 						*P0(pdst) = 0;
444 						*P1(pdst) = 0;
445 						*P2(pdst) = 0;
446 						*P3(pdst) = 0;
447 					} else {
448 						getunalignedword(P0(psrc),
449 						    xoffSrc, *P0(pdst));
450 						getunalignedword(P1(psrc),
451 						    xoffSrc, *P1(pdst));
452 						getunalignedword(P2(psrc),
453 						    xoffSrc, *P2(pdst));
454 						getunalignedword(P3(psrc),
455 						    xoffSrc, *P3(pdst));
456 					}
457 				}
458 
459 				if (startmask) {
460 					if (srcStartOver)
461 						--psrc;
462 					--pdst;
463 					getandputrop(P0(psrc), (sx & 0x1f),
464 					    (dx & 0x1f), nstart, P0(pdst), rop);
465 					getandputrop(P1(psrc), (sx & 0x1f),
466 					    (dx & 0x1f), nstart, P1(pdst), rop);
467 					getandputrop(P2(psrc), (sx & 0x1f),
468 					    (dx & 0x1f), nstart, P2(pdst), rop);
469 					getandputrop(P3(psrc), (sx & 0x1f),
470 					    (dx & 0x1f), nstart, P3(pdst), rop);
471 				}
472 
473 				pdstLine += width;
474 				psrcLine += width;
475 			}
476 		}
477 	}
478 
479 	return (0);
480 }
481