1 /* $OpenBSD: rasops1.c,v 1.13 2023/01/18 11:08:49 nicm Exp $ */
2 /* $NetBSD: rasops1.c,v 1.11 2000/04/12 14:22:29 pk Exp $ */
3
4 /*-
5 * Copyright (c) 1999 The NetBSD Foundation, Inc.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to The NetBSD Foundation
9 * by Andrew Doran.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33 #include <sys/param.h>
34 #include <sys/systm.h>
35 #include <sys/time.h>
36 #include <sys/endian.h>
37
38 #include <dev/wscons/wsdisplayvar.h>
39 #include <dev/wscons/wsconsio.h>
40 #include <dev/rasops/rasops.h>
41 #include <dev/rasops/rasops_masks.h>
42
43 int rasops1_copycols(void *, int, int, int, int);
44 int rasops1_erasecols(void *, int, int, int, uint32_t);
45 int rasops1_do_cursor(struct rasops_info *);
46 int rasops1_putchar(void *, int, int col, u_int, uint32_t);
47 #if !defined(RASOPS_SMALL) && BYTE_ORDER == BIG_ENDIAN
48 int rasops1_putchar8(void *, int, int col, u_int, uint32_t);
49 int rasops1_putchar16(void *, int, int col, u_int, uint32_t);
50 #endif
51
52 /*
53 * Initialize rasops_info struct for this colordepth.
54 */
55 void
rasops1_init(struct rasops_info * ri)56 rasops1_init(struct rasops_info *ri)
57 {
58 rasops_masks_init();
59
60 switch (ri->ri_font->fontwidth) {
61 #if !defined(RASOPS_SMALL) && BYTE_ORDER == BIG_ENDIAN
62 case 8:
63 ri->ri_ops.putchar = rasops1_putchar8;
64 break;
65 case 16:
66 ri->ri_ops.putchar = rasops1_putchar16;
67 break;
68 #endif
69 default:
70 ri->ri_ops.putchar = rasops1_putchar;
71 break;
72 }
73
74 if ((ri->ri_font->fontwidth & 7) != 0) {
75 ri->ri_ops.erasecols = rasops1_erasecols;
76 ri->ri_ops.copycols = rasops1_copycols;
77 ri->ri_do_cursor = rasops1_do_cursor;
78 }
79 }
80
81 /*
82 * Paint a single character. This is the generic version, this is ugly.
83 */
84 int
rasops1_putchar(void * cookie,int row,int col,u_int uc,uint32_t attr)85 rasops1_putchar(void *cookie, int row, int col, u_int uc, uint32_t attr)
86 {
87 u_int fs, rs, fb, bg, fg, lmask, rmask;
88 u_int32_t height, width;
89 struct rasops_info *ri;
90 int32_t *rp;
91 u_char *fr;
92
93 ri = (struct rasops_info *)cookie;
94
95 #ifdef RASOPS_CLIPPING
96 /* Catches 'row < 0' case too */
97 if ((unsigned)row >= (unsigned)ri->ri_rows)
98 return 0;
99
100 if ((unsigned)col >= (unsigned)ri->ri_cols)
101 return 0;
102 #endif
103
104 col *= ri->ri_font->fontwidth;
105 rp = (int32_t *)(ri->ri_bits + row * ri->ri_yscale + ((col >> 3) & ~3));
106 height = ri->ri_font->fontheight;
107 width = ri->ri_font->fontwidth;
108 col = col & 31;
109 rs = ri->ri_stride;
110
111 bg = (attr & 0x000f0000) ? ri->ri_devcmap[1] : ri->ri_devcmap[0];
112 fg = (attr & 0x0f000000) ? ri->ri_devcmap[1] : ri->ri_devcmap[0];
113
114 /* If fg and bg match this becomes a space character */
115 if (fg == bg || uc == ' ') {
116 uc = (u_int)-1;
117 fr = 0; /* shutup gcc */
118 fs = 0; /* shutup gcc */
119 } else {
120 uc -= ri->ri_font->firstchar;
121 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
122 fs = ri->ri_font->stride;
123 }
124
125 /* Single word, one mask */
126 if ((col + width) <= 32) {
127 rmask = rasops_pmask[col][width];
128 lmask = ~rmask;
129
130 if (uc == (u_int)-1) {
131 bg &= rmask;
132
133 while (height--) {
134 *rp = (*rp & lmask) | bg;
135 DELTA(rp, rs, int32_t *);
136 }
137 } else {
138 /* NOT fontbits if bg is white */
139 if (bg) {
140 while (height--) {
141 fb = ~(fr[3] | (fr[2] << 8) |
142 (fr[1] << 16) | (fr[0] << 24));
143 *rp = (*rp & lmask)
144 | (MBE(fb >> col) & rmask);
145
146 fr += fs;
147 DELTA(rp, rs, int32_t *);
148 }
149 } else {
150 while (height--) {
151 fb = (fr[3] | (fr[2] << 8) |
152 (fr[1] << 16) | (fr[0] << 24));
153 *rp = (*rp & lmask)
154 | (MBE(fb >> col) & rmask);
155
156 fr += fs;
157 DELTA(rp, rs, int32_t *);
158 }
159 }
160 }
161
162 /* Do underline */
163 if ((attr & WSATTR_UNDERLINE) != 0) {
164 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
165 *rp = (*rp & lmask) | (fg & rmask);
166 }
167 } else {
168 lmask = ~rasops_lmask[col];
169 rmask = ~rasops_rmask[(col + width) & 31];
170
171 if (uc == (u_int)-1) {
172 width = bg & ~rmask;
173 bg = bg & ~lmask;
174
175 while (height--) {
176 rp[0] = (rp[0] & lmask) | bg;
177 rp[1] = (rp[1] & rmask) | width;
178 DELTA(rp, rs, int32_t *);
179 }
180 } else {
181 width = 32 - col;
182
183 /* NOT fontbits if bg is white */
184 if (bg) {
185 while (height--) {
186 fb = ~(fr[3] | (fr[2] << 8) |
187 (fr[1] << 16) | (fr[0] << 24));
188
189 rp[0] = (rp[0] & lmask)
190 | MBE((u_int)fb >> col);
191
192 rp[1] = (rp[1] & rmask)
193 | (MBE((u_int)fb << width) & ~rmask);
194
195 fr += fs;
196 DELTA(rp, rs, int32_t *);
197 }
198 } else {
199 while (height--) {
200 fb = (fr[3] | (fr[2] << 8) |
201 (fr[1] << 16) | (fr[0] << 24));
202
203 rp[0] = (rp[0] & lmask)
204 | MBE(fb >> col);
205
206 rp[1] = (rp[1] & rmask)
207 | (MBE(fb << width) & ~rmask);
208
209 fr += fs;
210 DELTA(rp, rs, int32_t *);
211 }
212 }
213 }
214
215 /* Do underline */
216 if ((attr & WSATTR_UNDERLINE) != 0) {
217 DELTA(rp, -(ri->ri_stride << 1), int32_t *);
218 rp[0] = (rp[0] & lmask) | (fg & ~lmask);
219 rp[1] = (rp[1] & rmask) | (fg & ~rmask);
220 }
221 }
222
223 return 0;
224 }
225
226 #if !defined(RASOPS_SMALL) && BYTE_ORDER == BIG_ENDIAN
227 /*
228 * Paint a single character. This is for 8-pixel wide fonts.
229 */
230 int
rasops1_putchar8(void * cookie,int row,int col,u_int uc,uint32_t attr)231 rasops1_putchar8(void *cookie, int row, int col, u_int uc, uint32_t attr)
232 {
233 int height, fs, rs, bg, fg;
234 struct rasops_info *ri;
235 u_char *fr, *rp;
236
237 ri = (struct rasops_info *)cookie;
238
239 #ifdef RASOPS_CLIPPING
240 /* Catches 'row < 0' case too */
241 if ((unsigned)row >= (unsigned)ri->ri_rows)
242 return 0;
243
244 if ((unsigned)col >= (unsigned)ri->ri_cols)
245 return 0;
246 #endif
247
248 rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
249 height = ri->ri_font->fontheight;
250 rs = ri->ri_stride;
251
252 bg = (attr & 0x000f0000) ? ri->ri_devcmap[1] : ri->ri_devcmap[0];
253 fg = (attr & 0x0f000000) ? ri->ri_devcmap[1] : ri->ri_devcmap[0];
254
255 /* If fg and bg match this becomes a space character */
256 if (fg == bg || uc == ' ') {
257 while (height--) {
258 *rp = bg;
259 rp += rs;
260 }
261 } else {
262 uc -= ri->ri_font->firstchar;
263 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
264 fs = ri->ri_font->stride;
265
266 /* NOT fontbits if bg is white */
267 if (bg) {
268 while (height--) {
269 *rp = ~*fr;
270 fr += fs;
271 rp += rs;
272 }
273 } else {
274 while (height--) {
275 *rp = *fr;
276 fr += fs;
277 rp += rs;
278 }
279 }
280
281 }
282
283 /* Do underline */
284 if ((attr & WSATTR_UNDERLINE) != 0)
285 rp[-(ri->ri_stride << 1)] = fg;
286
287 return 0;
288 }
289
290 /*
291 * Paint a single character. This is for 16-pixel wide fonts.
292 */
293 int
rasops1_putchar16(void * cookie,int row,int col,u_int uc,uint32_t attr)294 rasops1_putchar16(void *cookie, int row, int col, u_int uc, uint32_t attr)
295 {
296 int height, fs, rs, bg, fg;
297 struct rasops_info *ri;
298 u_char *fr, *rp;
299
300 ri = (struct rasops_info *)cookie;
301
302 #ifdef RASOPS_CLIPPING
303 /* Catches 'row < 0' case too */
304 if ((unsigned)row >= (unsigned)ri->ri_rows)
305 return 0;
306
307 if ((unsigned)col >= (unsigned)ri->ri_cols)
308 return 0;
309 #endif
310
311 rp = ri->ri_bits + row * ri->ri_yscale + col * ri->ri_xscale;
312 height = ri->ri_font->fontheight;
313 rs = ri->ri_stride;
314
315 bg = (attr & 0x000f0000) ? ri->ri_devcmap[1] : ri->ri_devcmap[0];
316 fg = (attr & 0x0f000000) ? ri->ri_devcmap[1] : ri->ri_devcmap[0];
317
318 /* If fg and bg match this becomes a space character */
319 if (fg == bg || uc == ' ') {
320 while (height--) {
321 *(int16_t *)rp = bg;
322 rp += rs;
323 }
324 } else {
325 uc -= ri->ri_font->firstchar;
326 fr = (u_char *)ri->ri_font->data + uc * ri->ri_fontscale;
327 fs = ri->ri_font->stride;
328
329 /* NOT fontbits if bg is white */
330 if (bg) {
331 while (height--) {
332 rp[0] = ~fr[0];
333 rp[1] = ~fr[1];
334 fr += fs;
335 rp += rs;
336 }
337 } else {
338 while (height--) {
339 rp[0] = fr[0];
340 rp[1] = fr[1];
341 fr += fs;
342 rp += rs;
343 }
344 }
345 }
346
347 /* Do underline */
348 if ((attr & WSATTR_UNDERLINE) != 0)
349 *(int16_t *)(rp - (ri->ri_stride << 1)) = fg;
350
351 return 0;
352 }
353 #endif /* !defined(RASOPS_SMALL) && BYTE_ORDER == BIG_ENDIAN */
354
355 /*
356 * Grab routines common to depths where (bpp < 8)
357 */
358 #define NAME(ident) rasops1_##ident
359 #define PIXEL_SHIFT 0
360
361 #include <dev/rasops/rasops_bitops.h>
362