1 /*        $NetBSD: rasops_bitops.h,v 1.25 2019/08/10 01:24:17 rin Exp $         */
2 
3 /*-
4  * Copyright (c) 1999 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by Andrew Doran.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions
12  * are met:
13  * 1. Redistributions of source code must retain the above copyright
14  *    notice, this list of conditions and the following disclaimer.
15  * 2. Redistributions in binary form must reproduce the above copyright
16  *    notice, this list of conditions and the following disclaimer in the
17  *    documentation and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #ifndef _RASOPS_BITOPS_H_
33 #define _RASOPS_BITOPS_H_ 1
34 
35 #if   RASOPS_DEPTH == 1
36 #define   PIXEL_SHIFT         0
37 #elif RASOPS_DEPTH == 2
38 #define   PIXEL_SHIFT         1
39 #elif RASOPS_DEPTH == 4
40 #define   PIXEL_SHIFT         2
41 #else
42 #error "Depth not supported"
43 #endif
44 
45 #define   NAME(name)                    NAME1(RASOPS_DEPTH, name)
46 #define   NAME1(depth, name)  NAME2(depth, name)
47 #define   NAME2(depth, name)  rasops ## depth ## _ ## name
48 
49 /*
50  * Erase columns.
51  */
52 static void
NAME(erasecols)53 NAME(erasecols)(void *cookie, int row, int col, int num, long attr)
54 {
55           struct rasops_info *ri = (struct rasops_info *)cookie;
56           int height, cnt;
57           uint32_t bg, lbg, rbg, lmask, rmask, tmp;
58           uint32_t *dp, *rp, *hp;
59 
60           hp = NULL;          /* XXX GCC */
61 
62 #ifdef RASOPS_CLIPPING
63           if ((unsigned)row >= (unsigned)ri->ri_rows)
64                     return;
65 
66           if (col < 0) {
67                     num += col;
68                     col = 0;
69           }
70 
71           if (col + num > ri->ri_cols)
72                     num = ri->ri_cols - col;
73 
74           if (num <= 0)
75                     return;
76 #endif
77 
78           height = ri->ri_font->fontheight;
79           col *= ri->ri_font->fontwidth << PIXEL_SHIFT;
80           num *= ri->ri_font->fontwidth << PIXEL_SHIFT;
81 
82           rp = (uint32_t *)(ri->ri_bits + row*ri->ri_yscale + ((col >> 3) & ~3));
83           if (ri->ri_hwbits)
84                     hp = (uint32_t *)(ri->ri_hwbits + row*ri->ri_yscale +
85                         ((col >> 3) & ~3));
86 
87           col &= 31;
88 
89           bg = ATTR_BG(ri, attr);
90 
91           if (col + num <= 32) {
92                     lmask = ~rasops_pmask[col][num & 31];
93                     bg &= ~lmask;
94 
95                     while (height--) {
96                               tmp = (*rp & lmask) | bg;
97                               *rp = tmp;
98 
99                               if (ri->ri_hwbits) {
100                                         *hp = tmp;
101                                         DELTA(hp, ri->ri_stride, uint32_t *);
102                               }
103 
104                               DELTA(rp, ri->ri_stride, uint32_t *);
105                     }
106           } else {
107                     lmask = rasops_rmask[col];
108                     rmask = rasops_lmask[(col + num) & 31];
109 
110                     if (lmask)
111                               num = (num - (32 - col)) >> 5;
112                     else
113                               num = num >> 5;
114 
115                     lbg = bg & ~lmask;
116                     rbg = bg & ~rmask;
117 
118                     while (height--) {
119                               dp = rp;
120 
121                               if (lmask) {
122                                         *dp = (*dp & lmask) | lbg;
123                                         dp++;
124                               }
125 
126                               for (cnt = num; cnt > 0; cnt--)
127                                         *dp++ = bg;
128 
129                               if (rmask)
130                                         *dp = (*dp & rmask) | rbg;
131 
132                               if (ri->ri_hwbits) {
133                                         memcpy(hp, rp, ((lmask != 0) + num +
134                                             (rmask != 0)) << 2);
135                                         DELTA(hp, ri->ri_stride, uint32_t *);
136                               }
137 
138                               DELTA(rp, ri->ri_stride, uint32_t *);
139                     }
140           }
141 }
142 
143 /*
144  * Actually paint the cursor.
145  */
146 static void
NAME(do_cursor)147 NAME(do_cursor)(struct rasops_info *ri)
148 {
149           int row, col, height, width, cnt;
150           uint32_t lmask, rmask, tmp;
151           uint32_t *dp, *rp, *hp;
152 
153           hp = NULL;          /* XXX GCC */
154 
155           row = ri->ri_crow;
156           col = ri->ri_ccol * ri->ri_font->fontwidth << PIXEL_SHIFT;
157 
158           height = ri->ri_font->fontheight;
159           width = ri->ri_font->fontwidth << PIXEL_SHIFT;
160 
161           rp = (uint32_t *)(ri->ri_bits + row * ri->ri_yscale +
162               ((col >> 3) & ~3));
163           if (ri->ri_hwbits)
164                     hp = (uint32_t *)(ri->ri_hwbits + row * ri->ri_yscale +
165                         ((col >> 3) & ~3));
166 
167           col &= 31;
168 
169           if (col + width <= 32) {
170                     lmask = rasops_pmask[col][width & 31];
171 
172                     while (height--) {
173                               tmp = *rp ^ lmask;
174                               *rp = tmp;
175                               if (ri->ri_hwbits) {
176                                         *hp = tmp;
177                                         DELTA(hp, ri->ri_stride, uint32_t *);
178                               }
179                               DELTA(rp, ri->ri_stride, uint32_t *);
180                     }
181           } else {
182                     lmask = ~rasops_rmask[col];
183                     rmask = ~rasops_lmask[(col + width) & 31];
184 
185                     if (lmask != -1)
186                               width = (width - (32 - col)) >> 5;
187                     else
188                               width = width >> 5;
189 
190                     while (height--) {
191                               dp = rp;
192 
193                               if (lmask != -1)
194                                         *dp++ ^= lmask;
195 
196                               for (cnt = width; cnt; cnt--) {
197                                         *dp = ~*dp;
198                                         dp++;
199                               }
200 
201                               if (rmask != -1)
202                                         *dp ^= rmask;
203 
204                               if (ri->ri_hwbits) {
205                                         memcpy(hp, rp, ((lmask != -1) + width +
206                                             (rmask != -1)) << 2);
207                                         DELTA(hp, ri->ri_stride, uint32_t *);
208                               }
209 
210                               DELTA(rp, ri->ri_stride, uint32_t *);
211                     }
212           }
213 }
214 
215 /*
216  * Copy columns. Ick!
217  */
218 static void
NAME(copycols)219 NAME(copycols)(void *cookie, int row, int src, int dst, int num)
220 {
221           struct rasops_info *ri = (struct rasops_info *)cookie;
222           int height, width, lnum, rnum, sb, db, full, cnt, sboff;
223           uint32_t lmask, rmask, tmp;
224           uint32_t *sp, *dp, *srp, *drp, *hp;
225           bool sbover;
226 
227           hp = NULL;          /* XXX GCC */
228 
229           if (__predict_false(dst == src))
230                     return;
231 
232 #ifdef RASOPS_CLIPPING
233           /* Catches < 0 case too */
234           if ((unsigned)row >= (unsigned)ri->ri_rows)
235                     return;
236 
237           if (src < 0) {
238                     num += src;
239                     src = 0;
240           }
241 
242           if (src + num > ri->ri_cols)
243                     num = ri->ri_cols - src;
244 
245           if (dst < 0) {
246                     num += dst;
247                     dst = 0;
248           }
249 
250           if (dst + num > ri->ri_cols)
251                     num = ri->ri_cols - dst;
252 
253           if (num <= 0)
254                     return;
255 #endif
256 
257           height = ri->ri_font->fontheight;
258           width = ri->ri_font->fontwidth << PIXEL_SHIFT;
259 
260           row *= ri->ri_yscale;
261 
262           src *= width;
263           dst *= width;
264           num *= width;
265 
266           sb = src & 31;
267           db = dst & 31;
268 
269           if (db + num <= 32) {
270                     /* Destination is contained within a single word */
271                     srp = (uint32_t *)(ri->ri_bits + row + ((src >> 3) & ~3));
272                     drp = (uint32_t *)(ri->ri_bits + row + ((dst >> 3) & ~3));
273                     if (ri->ri_hwbits)
274                               hp = (uint32_t *)(ri->ri_hwbits + row +
275                                   ((dst >> 3) & ~3));
276 
277                     while (height--) {
278                               GETBITS(srp, sb, num, tmp);
279                               PUTBITS(tmp, db, num, drp);
280                               if (ri->ri_hwbits) {
281                                         *hp = *drp;
282                                         DELTA(hp, ri->ri_stride, uint32_t *);
283                               }
284                               DELTA(srp, ri->ri_stride, uint32_t *);
285                               DELTA(drp, ri->ri_stride, uint32_t *);
286                     }
287 
288                     return;
289           }
290 
291           lmask = rasops_rmask[db];
292           rmask = rasops_lmask[(dst + num) & 31];
293           lnum = (32 - db) & 31;
294           rnum = (dst + num) & 31;
295 
296           if (lmask != 0)
297                     full = (num - lnum) >> 5;
298           else
299                     full = num >> 5;
300 
301           if (src < dst && src + num > dst) {
302                     /* Copy right-to-left */
303                     srp = (uint32_t *)(ri->ri_bits + row +
304                         (((src + num) >> 3) & ~3));
305                     drp = (uint32_t *)(ri->ri_bits + row +
306                         (((dst + num) >> 3) & ~3));
307                     if (ri->ri_hwbits) {
308                               hp = (uint32_t *)(ri->ri_hwbits + row +
309                                   (((dst + num) >> 3) & ~3));
310                               hp -= (lmask != 0) + full;
311                     }
312 
313                     sboff = (src + num) & 31;
314                     sbover = sb + lnum >= 32;
315                     if ((sboff -= rnum) < 0) {
316                               srp--;
317                               sboff += 32;
318                     }
319 
320                     while (height--) {
321                               sp = srp;
322                               dp = drp;
323 
324                               if (rmask != 0) {
325                                         GETBITS(sp, sboff, rnum, tmp);
326                                         PUTBITS(tmp, 0, rnum, dp);
327                               }
328 
329                               /* Now aligned to 32-bits wrt dp */
330                               for (cnt = full; cnt; cnt--) {
331                                         --dp;
332                                         --sp;
333                                         GETBITS(sp, sboff, 32, tmp);
334                                         *dp = tmp;
335                               }
336 
337                               if (lmask != 0) {
338                                         if (sbover)
339                                                   --sp;
340                                         --dp;
341                                         GETBITS(sp, sb, lnum, tmp);
342                                         PUTBITS(tmp, db, lnum, dp);
343                               }
344 
345                               if (ri->ri_hwbits) {
346                                         memcpy(hp, dp, ((lmask != 0) + full +
347                                             (rmask != 0)) << 2);
348                                         DELTA(hp, ri->ri_stride, uint32_t *);
349                               }
350 
351                               DELTA(srp, ri->ri_stride, uint32_t *);
352                               DELTA(drp, ri->ri_stride, uint32_t *);
353                     }
354           } else {
355                     /* Copy left-to-right */
356                     srp = (uint32_t *)(ri->ri_bits + row + ((src >> 3) & ~3));
357                     drp = (uint32_t *)(ri->ri_bits + row + ((dst >> 3) & ~3));
358                     if (ri->ri_hwbits)
359                               hp = (uint32_t *)(ri->ri_hwbits + row +
360                                   ((dst >> 3) & ~3));
361 
362                     while (height--) {
363                               sp = srp;
364                               dp = drp;
365 
366                               sboff = sb;
367 
368                               if (lmask != 0) {
369                                         GETBITS(sp, sboff, lnum, tmp);
370                                         PUTBITS(tmp, db, lnum, dp);
371                                         dp++;
372 
373                                         if ((sboff += lnum) > 31) {
374                                                   sp++;
375                                                   sboff -= 32;
376                                         }
377                               }
378 
379                               /* Now aligned to 32-bits wrt dp */
380                               for (cnt = full; cnt; cnt--, sp++) {
381                                         GETBITS(sp, sboff, 32, tmp);
382                                         *dp++ = tmp;
383                               }
384 
385                               if (rmask != 0) {
386                                         GETBITS(sp, sboff, rnum, tmp);
387                                         PUTBITS(tmp, 0, rnum, dp);
388                               }
389 
390                               if (ri->ri_hwbits) {
391                                         memcpy(hp, drp, ((lmask != 0) + full +
392                                             (rmask != 0)) << 2);
393                                         DELTA(hp, ri->ri_stride, uint32_t *);
394                               }
395 
396                               DELTA(srp, ri->ri_stride, uint32_t *);
397                               DELTA(drp, ri->ri_stride, uint32_t *);
398                     }
399           }
400 }
401 
402 #undef    PIXEL_SHIFT
403 
404 #undef    NAME
405 #undef    NAME1
406 #undef    NAME2
407 
408 #endif /* _RASOPS_BITOPS_H_ */
409