xref: /openbsd/sys/arch/luna88k/dev/omrasops1.c (revision a6445c1d)
1 /*	$OpenBSD: omrasops1.c,v 1.2 2014/01/02 15:30:34 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 /* prototypes */
88 int om1_windowmove(struct rasops_info *, u_int16_t, u_int16_t,
89 	u_int16_t, u_int16_t, u_int16_t, u_int16_t, int16_t,
90 	int16_t /* ignored */);
91 int om4_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 
95 /*
96  * Block-move function - 1bpp version
97  */
98 int
99 om1_windowmove(struct rasops_info *ri, u_int16_t sx, u_int16_t sy,
100 	u_int16_t dx, u_int16_t dy, u_int16_t cx, u_int16_t cy, int16_t rop,
101 	int16_t planemask /* ignored */)
102 {
103 	int width;		/* add to get to same position in next line */
104 
105 	u_int32_t *psrcLine, *pdstLine;
106 				/* pointers to line with current src and dst */
107 	u_int32_t *psrc;	/* pointer to current src longword */
108 	u_int32_t *pdst;	/* pointer to current dst longword */
109 
110 				/* following used for looping through a line */
111 	u_int32_t startmask, endmask;  /* masks for writing ends of dst */
112 	int nlMiddle;		/* whole longwords in dst */
113 	int nl;			/* temp copy of nlMiddle */
114 	int xoffSrc;		/* offset (>= 0, < 32) from which to
115 				   fetch whole longwords fetched in src */
116 	int nstart;		/* number of ragged bits at start of dst */
117 	int nend;		/* number of ragged bits at end of dst */
118 	int srcStartOver;	/* pulling nstart bits from src
119 				   overflows into the next word? */
120 
121 	width = ri->ri_stride / 4;	/* convert to number in longword */
122 
123 	if (sy < dy) {	/* start at last scanline of rectangle */
124 		psrcLine = ((u_int32_t *)OMFB_FB_WADDR)
125 				 + ((sy + cy - 1) * width);
126 		pdstLine = ((u_int32_t *)OMFB_FB_WADDR)
127 				 + ((dy + cy - 1) * width);
128 		width = -width;
129 	} else {	/* start at first scanline */
130 		psrcLine = ((u_int32_t *)OMFB_FB_WADDR) + (sy * width);
131 		pdstLine = ((u_int32_t *)OMFB_FB_WADDR) + (dy * width);
132 	}
133 
134 	/* x direction doesn't matter for < 1 longword */
135 	if (cx <= 32) {
136 		int srcBit, dstBit;	/* bit offset of src and dst */
137 
138 		pdstLine += (dx >> 5);
139 		psrcLine += (sx >> 5);
140 		psrc = psrcLine;
141 		pdst = pdstLine;
142 
143 		srcBit = sx & 0x1f;
144 		dstBit = dx & 0x1f;
145 
146 		while (cy--) {
147 			getandputrop(R(psrc), srcBit, dstBit, cx, W(pdst), rop);
148 			pdst += width;
149 			psrc += width;
150 		}
151 	} else {
152 		maskbits(dx, cx, startmask, endmask, nlMiddle);
153 		if (startmask)
154 			nstart = 32 - (dx & 0x1f);
155 		else
156 			nstart = 0;
157 		if (endmask)
158 			nend = (dx + cx) & 0x1f;
159 		else
160 			nend = 0;
161 
162 		xoffSrc = ((sx & 0x1f) + nstart) & 0x1f;
163 		srcStartOver = ((sx & 0x1f) + nstart) > 31;
164 
165 		if (sx >= dx) {	/* move left to right */
166 			pdstLine += (dx >> 5);
167 			psrcLine += (sx >> 5);
168 
169 			while (cy--) {
170 				psrc = psrcLine;
171 				pdst = pdstLine;
172 
173 				if (startmask) {
174 					getandputrop(R(psrc), (sx & 0x1f),
175 					    (dx & 0x1f), nstart, W(pdst), rop);
176 					pdst++;
177 					if (srcStartOver)
178 						psrc++;
179 				}
180 
181 				/* special case for aligned operations */
182 				if (xoffSrc == 0) {
183 					nl = nlMiddle;
184 					while (nl--) {
185 						if (rop == RR_CLEAR)
186 							W(pdst) = 0;
187 						else
188 							W(pdst) = R(psrc);
189 						psrc++;
190 						pdst++;
191 					}
192 				} else {
193 					nl = nlMiddle + 1;
194 					while (--nl) {
195 						if (rop == RR_CLEAR)
196 							W(pdst) = 0;
197 						else
198 							getunalignedword(R(psrc),
199 							    xoffSrc, *W(pdst));
200 						pdst++;
201 						psrc++;
202 					}
203 				}
204 
205 				if (endmask) {
206 					getandputrop(R(psrc), xoffSrc, 0, nend,
207 					    W(pdst), rop);
208 				}
209 
210 				pdstLine += width;
211 				psrcLine += width;
212 			}
213 		} else {	/* move right to left */
214 			pdstLine += ((dx + cx) >> 5);
215 			psrcLine += ((sx + cx) >> 5);
216 			/*
217 			 * If fetch of last partial bits from source crosses
218 			 * a longword boundary, start at the previous longword
219 			 */
220 			if (xoffSrc + nend >= 32)
221 				--psrcLine;
222 
223 			while (cy--) {
224 				psrc = psrcLine;
225 				pdst = pdstLine;
226 
227 				if (endmask) {
228 					getandputrop(R(psrc), xoffSrc, 0, nend,
229 					    W(pdst), rop);
230 				}
231 
232 				nl = nlMiddle + 1;
233 				while (--nl) {
234 					--psrc;
235 					--pdst;
236 					if (rop == RR_CLEAR)
237 						W(pdst) = 0;
238 					else
239 						getunalignedword(R(psrc), xoffSrc,
240 						    *W(pdst));
241 				}
242 
243 				if (startmask) {
244 					if (srcStartOver)
245 						--psrc;
246 					--pdst;
247 					getandputrop(R(psrc), (sx & 0x1f),
248 					    (dx & 0x1f), nstart, W(pdst), rop);
249 				}
250 
251 				pdstLine += width;
252 				psrcLine += width;
253 			}
254 		}
255 	}
256 
257 	return (0);
258 }
259 
260 /*
261  * Block-move function - 4bpp version
262  */
263 int
264 om4_windowmove(struct rasops_info *ri, u_int16_t sx, u_int16_t sy,
265 	u_int16_t dx, u_int16_t dy, u_int16_t cx, u_int16_t cy, int16_t rop,
266 	int16_t planemask /* ignored */)
267 {
268 	int width;		/* add to get to same position in next line */
269 
270 	u_int32_t *psrcLine, *pdstLine;
271 				/* pointers to line with current src and dst */
272 	u_int32_t *psrc;	/* pointer to current src longword */
273 	u_int32_t *pdst;	/* pointer to current dst longword */
274 
275 				/* following used for looping through a line */
276 	u_int32_t startmask, endmask;  /* masks for writing ends of dst */
277 	int nlMiddle;		/* whole longwords in dst */
278 	int nl;			/* temp copy of nlMiddle */
279 	int xoffSrc;		/* offset (>= 0, < 32) from which to
280 				   fetch whole longwords fetched in src */
281 	int nstart;		/* number of ragged bits at start of dst */
282 	int nend;		/* number of ragged bits at end of dst */
283 	int srcStartOver;	/* pulling nstart bits from src
284 				   overflows into the next word? */
285 
286 	width = ri->ri_stride / 4;	/* convert to number in longword */
287 
288 	if (sy < dy) {	/* start at last scanline of rectangle */
289 		psrcLine = ((u_int32_t *)OMFB_FB_WADDR)
290 				 + ((sy + cy - 1) * width);
291 		pdstLine = ((u_int32_t *)OMFB_FB_WADDR)
292 				 + ((dy + cy - 1) * width);
293 		width = -width;
294 	} else {	/* start at first scanline */
295 		psrcLine = ((u_int32_t *)OMFB_FB_WADDR) + (sy * width);
296 		pdstLine = ((u_int32_t *)OMFB_FB_WADDR) + (dy * width);
297 	}
298 
299 	/* x direction doesn't matter for < 1 longword */
300 	if (cx <= 32) {
301 		int srcBit, dstBit;	/* bit offset of src and dst */
302 
303 		pdstLine += (dx >> 5);
304 		psrcLine += (sx >> 5);
305 		psrc = psrcLine;
306 		pdst = pdstLine;
307 
308 		srcBit = sx & 0x1f;
309 		dstBit = dx & 0x1f;
310 
311 		while (cy--) {
312 			getandputrop(P0(psrc), srcBit, dstBit, cx, P0(pdst), rop);
313 			getandputrop(P1(psrc), srcBit, dstBit, cx, P1(pdst), rop);
314 			getandputrop(P2(psrc), srcBit, dstBit, cx, P2(pdst), rop);
315 			getandputrop(P3(psrc), srcBit, dstBit, cx, P3(pdst), rop);
316 			pdst += width;
317 			psrc += width;
318 		}
319 	} else {
320 		maskbits(dx, cx, startmask, endmask, nlMiddle);
321 		if (startmask)
322 			nstart = 32 - (dx & 0x1f);
323 		else
324 			nstart = 0;
325 		if (endmask)
326 			nend = (dx + cx) & 0x1f;
327 		else
328 			nend = 0;
329 
330 		xoffSrc = ((sx & 0x1f) + nstart) & 0x1f;
331 		srcStartOver = ((sx & 0x1f) + nstart) > 31;
332 
333 		if (sx >= dx) {	/* move left to right */
334 			pdstLine += (dx >> 5);
335 			psrcLine += (sx >> 5);
336 
337 			while (cy--) {
338 				psrc = psrcLine;
339 				pdst = pdstLine;
340 
341 				if (startmask) {
342 					getandputrop(P0(psrc), (sx & 0x1f),
343 					    (dx & 0x1f), nstart, P0(pdst), rop);
344 					getandputrop(P1(psrc), (sx & 0x1f),
345 					    (dx & 0x1f), nstart, P1(pdst), rop);
346 					getandputrop(P2(psrc), (sx & 0x1f),
347 					    (dx & 0x1f), nstart, P2(pdst), rop);
348 					getandputrop(P3(psrc), (sx & 0x1f),
349 					    (dx & 0x1f), nstart, P3(pdst), rop);
350 					pdst++;
351 					if (srcStartOver)
352 						psrc++;
353 				}
354 
355 				/* special case for aligned operations */
356 				if (xoffSrc == 0) {
357 					nl = nlMiddle;
358 					while (nl--) {
359 						if (rop == RR_CLEAR) {
360 							*P0(pdst) = 0;
361 							*P1(pdst) = 0;
362 							*P2(pdst) = 0;
363 							*P3(pdst) = 0;
364 						} else {
365 							*P0(pdst) = *P0(psrc);
366 							*P1(pdst) = *P1(psrc);
367 							*P2(pdst) = *P2(psrc);
368 							*P3(pdst) = *P3(psrc);
369 						}
370 						psrc++;
371 						pdst++;
372 					}
373 				} else {
374 					nl = nlMiddle + 1;
375 					while (--nl) {
376 						if (rop == RR_CLEAR) {
377 							*P0(pdst) = 0;
378 							*P1(pdst) = 0;
379 							*P2(pdst) = 0;
380 							*P3(pdst) = 0;
381 						} else {
382 							getunalignedword(P0(psrc),
383 							    xoffSrc, *P0(pdst));
384 							getunalignedword(P1(psrc),
385 							    xoffSrc, *P1(pdst));
386 							getunalignedword(P2(psrc),
387 							    xoffSrc, *P2(pdst));
388 							getunalignedword(P3(psrc),
389 							    xoffSrc, *P3(pdst));
390 						}
391 						pdst++;
392 						psrc++;
393 					}
394 				}
395 
396 				if (endmask) {
397 					getandputrop(P0(psrc), xoffSrc, 0, nend,
398 					    P0(pdst), rop);
399 					getandputrop(P1(psrc), xoffSrc, 0, nend,
400 					    P1(pdst), rop);
401 					getandputrop(P2(psrc), xoffSrc, 0, nend,
402 					    P2(pdst), rop);
403 					getandputrop(P3(psrc), xoffSrc, 0, nend,
404 					    P3(pdst), rop);
405 				}
406 
407 				pdstLine += width;
408 				psrcLine += width;
409 			}
410 		} else {	/* move right to left */
411 			pdstLine += ((dx + cx) >> 5);
412 			psrcLine += ((sx + cx) >> 5);
413 			/*
414 			 * If fetch of last partial bits from source crosses
415 			 * a longword boundary, start at the previous longword
416 			 */
417 			if (xoffSrc + nend >= 32)
418 				--psrcLine;
419 
420 			while (cy--) {
421 				psrc = psrcLine;
422 				pdst = pdstLine;
423 
424 				if (endmask) {
425 					getandputrop(P0(psrc), xoffSrc, 0, nend,
426 					    P0(pdst), rop);
427 					getandputrop(P1(psrc), xoffSrc, 0, nend,
428 					    P1(pdst), rop);
429 					getandputrop(P2(psrc), xoffSrc, 0, nend,
430 					    P2(pdst), rop);
431 					getandputrop(P3(psrc), xoffSrc, 0, nend,
432 					    P3(pdst), rop);
433 				}
434 
435 				nl = nlMiddle + 1;
436 				while (--nl) {
437 					--psrc;
438 					--pdst;
439 					if (rop == RR_CLEAR) {
440 						*P0(pdst) = 0;
441 						*P1(pdst) = 0;
442 						*P2(pdst) = 0;
443 						*P3(pdst) = 0;
444 					} else {
445 						getunalignedword(P0(psrc),
446 						    xoffSrc, *P0(pdst));
447 						getunalignedword(P1(psrc),
448 						    xoffSrc, *P1(pdst));
449 						getunalignedword(P2(psrc),
450 						    xoffSrc, *P2(pdst));
451 						getunalignedword(P3(psrc),
452 						    xoffSrc, *P3(pdst));
453 					}
454 				}
455 
456 				if (startmask) {
457 					if (srcStartOver)
458 						--psrc;
459 					--pdst;
460 					getandputrop(P0(psrc), (sx & 0x1f),
461 					    (dx & 0x1f), nstart, P0(pdst), rop);
462 					getandputrop(P1(psrc), (sx & 0x1f),
463 					    (dx & 0x1f), nstart, P1(pdst), rop);
464 					getandputrop(P2(psrc), (sx & 0x1f),
465 					    (dx & 0x1f), nstart, P2(pdst), rop);
466 					getandputrop(P3(psrc), (sx & 0x1f),
467 					    (dx & 0x1f), nstart, P3(pdst), rop);
468 				}
469 
470 				pdstLine += width;
471 				psrcLine += width;
472 			}
473 		}
474 	}
475 
476 	return (0);
477 }
478