1 1.37 rin /* $NetBSD: rasops1.c,v 1.37 2019/08/10 01:24:17 rin Exp $ */ 2 1.1 ad 3 1.5 ad /*- 4 1.5 ad * Copyright (c) 1999 The NetBSD Foundation, Inc. 5 1.1 ad * All rights reserved. 6 1.1 ad * 7 1.5 ad * This code is derived from software contributed to The NetBSD Foundation 8 1.12 ad * by Andrew Doran. 9 1.5 ad * 10 1.1 ad * Redistribution and use in source and binary forms, with or without 11 1.1 ad * modification, are permitted provided that the following conditions 12 1.1 ad * are met: 13 1.1 ad * 1. Redistributions of source code must retain the above copyright 14 1.1 ad * notice, this list of conditions and the following disclaimer. 15 1.1 ad * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 ad * notice, this list of conditions and the following disclaimer in the 17 1.1 ad * documentation and/or other materials provided with the distribution. 18 1.1 ad * 19 1.5 ad * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.5 ad * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.5 ad * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.5 ad * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.5 ad * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.5 ad * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.5 ad * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.5 ad * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.5 ad * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.5 ad * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.5 ad * POSSIBILITY OF SUCH DAMAGE. 30 1.1 ad */ 31 1.2 ad 32 1.14 lukem #include <sys/cdefs.h> 33 1.37 rin __KERNEL_RCSID(0, "$NetBSD: rasops1.c,v 1.37 2019/08/10 01:24:17 rin Exp $"); 34 1.14 lukem 35 1.37 rin #ifdef _KERNEL_OPT 36 1.1 ad #include "opt_rasops.h" 37 1.37 rin #endif 38 1.1 ad 39 1.1 ad #include <sys/param.h> 40 1.37 rin 41 1.1 ad #include <machine/endian.h> 42 1.1 ad 43 1.1 ad #include <dev/wscons/wsdisplayvar.h> 44 1.3 ad #include <dev/wscons/wsconsio.h> 45 1.32 rin 46 1.32 rin #define _RASOPS_PRIVATE 47 1.34 rin #define RASOPS_DEPTH 1 48 1.1 ad #include <dev/rasops/rasops.h> 49 1.4 ad #include <dev/rasops/rasops_masks.h> 50 1.1 ad 51 1.16 perry static void rasops1_copycols(void *, int, int, int, int); 52 1.16 perry static void rasops1_erasecols(void *, int, int, int, long); 53 1.16 perry static void rasops1_do_cursor(struct rasops_info *); 54 1.16 perry static void rasops1_putchar(void *, int, int col, u_int, long); 55 1.10 ad #ifndef RASOPS_SMALL 56 1.16 perry static void rasops1_putchar8(void *, int, int col, u_int, long); 57 1.16 perry static void rasops1_putchar16(void *, int, int col, u_int, long); 58 1.10 ad #endif 59 1.1 ad 60 1.1 ad /* 61 1.13 wiz * Initialize rasops_info struct for this colordepth. 62 1.1 ad */ 63 1.1 ad void 64 1.19 dsl rasops1_init(struct rasops_info *ri) 65 1.1 ad { 66 1.1 ad 67 1.29 rin if ((ri->ri_font->fontwidth & 7) != 0) { 68 1.29 rin ri->ri_ops.erasecols = rasops1_erasecols; 69 1.29 rin ri->ri_ops.copycols = rasops1_copycols; 70 1.29 rin ri->ri_do_cursor = rasops1_do_cursor; 71 1.29 rin } 72 1.29 rin 73 1.1 ad switch (ri->ri_font->fontwidth) { 74 1.10 ad #ifndef RASOPS_SMALL 75 1.1 ad case 8: 76 1.1 ad ri->ri_ops.putchar = rasops1_putchar8; 77 1.1 ad break; 78 1.1 ad case 16: 79 1.1 ad ri->ri_ops.putchar = rasops1_putchar16; 80 1.1 ad break; 81 1.10 ad #endif 82 1.1 ad default: 83 1.1 ad ri->ri_ops.putchar = rasops1_putchar; 84 1.1 ad break; 85 1.1 ad } 86 1.1 ad } 87 1.1 ad 88 1.1 ad /* 89 1.4 ad * Paint a single character. This is the generic version, this is ugly. 90 1.1 ad */ 91 1.1 ad static void 92 1.20 dsl rasops1_putchar(void *cookie, int row, int col, u_int uc, long attr) 93 1.1 ad { 94 1.23 macallan struct rasops_info *ri = (struct rasops_info *)cookie; 95 1.23 macallan struct wsdisplay_font *font = PICK_FONT(ri, uc); 96 1.37 rin int height, width; 97 1.37 rin uint32_t bg, fg, lbg, rbg, fb, lmask, rmask, tmp, tmp0, tmp1; 98 1.37 rin uint32_t *rp, *hp; 99 1.25 rin uint8_t *fr; 100 1.29 rin bool space; 101 1.29 rin 102 1.31 rin hp = NULL; /* XXX GCC */ 103 1.11 pk 104 1.36 rin if (__predict_false(!CHAR_IN_FONT(uc, font))) 105 1.36 rin return; 106 1.36 rin 107 1.11 pk #ifdef RASOPS_CLIPPING 108 1.11 pk /* Catches 'row < 0' case too */ 109 1.4 ad if ((unsigned)row >= (unsigned)ri->ri_rows) 110 1.4 ad return; 111 1.4 ad 112 1.4 ad if ((unsigned)col >= (unsigned)ri->ri_cols) 113 1.4 ad return; 114 1.4 ad #endif 115 1.4 ad 116 1.37 rin height = font->fontheight; 117 1.37 rin width = font->fontwidth; 118 1.37 rin col *= width; 119 1.37 rin 120 1.26 rin rp = (uint32_t *)(ri->ri_bits + row * ri->ri_yscale + 121 1.26 rin ((col >> 3) & ~3)); 122 1.21 macallan if (ri->ri_hwbits) 123 1.31 rin hp = (uint32_t *)(ri->ri_hwbits + row * ri->ri_yscale + 124 1.21 macallan ((col >> 3) & ~3)); 125 1.37 rin 126 1.29 rin col &= 31; 127 1.11 pk 128 1.37 rin bg = ATTR_BG(ri, attr); 129 1.37 rin fg = ATTR_FG(ri, attr); 130 1.4 ad 131 1.4 ad /* If fg and bg match this becomes a space character */ 132 1.37 rin if (uc == ' ' || __predict_false(fg == bg)) { 133 1.29 rin space = true; 134 1.29 rin fr = NULL; /* XXX GCC */ 135 1.4 ad } else { 136 1.29 rin space = false; 137 1.28 rin fr = FONT_GLYPH(uc, font, ri); 138 1.4 ad } 139 1.11 pk 140 1.29 rin if (col + width <= 32) { 141 1.29 rin /* Single word, only one mask */ 142 1.33 rin rmask = rasops_pmask[col][width & 31]; 143 1.4 ad lmask = ~rmask; 144 1.11 pk 145 1.29 rin if (space) { 146 1.4 ad bg &= rmask; 147 1.4 ad while (height--) { 148 1.21 macallan tmp = (*rp & lmask) | bg; 149 1.21 macallan *rp = tmp; 150 1.21 macallan if (ri->ri_hwbits) { 151 1.31 rin *hp = tmp; 152 1.37 rin DELTA(hp, ri->ri_stride, uint32_t *); 153 1.21 macallan } 154 1.37 rin DELTA(rp, ri->ri_stride, uint32_t *); 155 1.4 ad } 156 1.4 ad } else { 157 1.29 rin while (height--) { 158 1.37 rin fb = rasops_be32uatoh(fr); 159 1.37 rin fr += font->stride; 160 1.29 rin if (bg) 161 1.29 rin fb = ~fb; 162 1.37 rin 163 1.37 rin tmp = *rp & lmask; 164 1.29 rin tmp |= (MBE(fb >> col) & rmask); 165 1.29 rin *rp = tmp; 166 1.37 rin 167 1.29 rin if (ri->ri_hwbits) { 168 1.31 rin *hp = tmp; 169 1.37 rin DELTA(hp, ri->ri_stride, uint32_t *); 170 1.4 ad } 171 1.37 rin 172 1.37 rin DELTA(rp, ri->ri_stride, uint32_t *); 173 1.4 ad } 174 1.4 ad } 175 1.11 pk 176 1.4 ad /* Do underline */ 177 1.24 mlelstv if ((attr & WSATTR_UNDERLINE) != 0) { 178 1.35 rin DELTA(rp, - ri->ri_stride * ri->ri_ul.off, uint32_t *); 179 1.35 rin if (ri->ri_hwbits) 180 1.35 rin DELTA(hp, - ri->ri_stride * ri->ri_ul.off, 181 1.35 rin uint32_t *); 182 1.37 rin 183 1.35 rin for (height = ri->ri_ul.height; height; height--) { 184 1.35 rin DELTA(rp, - ri->ri_stride, uint32_t *); 185 1.35 rin tmp = (*rp & lmask) | (fg & rmask); 186 1.35 rin *rp = tmp; 187 1.35 rin if (ri->ri_hwbits) { 188 1.35 rin DELTA(hp, - ri->ri_stride, uint32_t *); 189 1.35 rin *hp = tmp; 190 1.35 rin } 191 1.21 macallan } 192 1.4 ad } 193 1.4 ad } else { 194 1.29 rin /* Word boundary, two masks needed */ 195 1.4 ad lmask = ~rasops_lmask[col]; 196 1.4 ad rmask = ~rasops_rmask[(col + width) & 31]; 197 1.11 pk 198 1.29 rin if (space) { 199 1.37 rin lbg = bg & ~lmask; 200 1.37 rin rbg = bg & ~rmask; 201 1.37 rin 202 1.4 ad while (height--) { 203 1.37 rin tmp0 = (rp[0] & lmask) | lbg; 204 1.37 rin tmp1 = (rp[1] & rmask) | rbg; 205 1.37 rin 206 1.29 rin rp[0] = tmp0; 207 1.29 rin rp[1] = tmp1; 208 1.37 rin 209 1.21 macallan if (ri->ri_hwbits) { 210 1.31 rin hp[0] = tmp0; 211 1.31 rin hp[1] = tmp1; 212 1.37 rin DELTA(hp, ri->ri_stride, uint32_t *); 213 1.21 macallan } 214 1.37 rin 215 1.37 rin DELTA(rp, ri->ri_stride, uint32_t *); 216 1.4 ad } 217 1.4 ad } else { 218 1.4 ad width = 32 - col; 219 1.37 rin 220 1.29 rin while (height--) { 221 1.37 rin fb = rasops_be32uatoh(fr); 222 1.37 rin fr += font->stride; 223 1.29 rin if (bg) 224 1.29 rin fb = ~fb; 225 1.37 rin 226 1.37 rin tmp0 = rp[0] & lmask; 227 1.29 rin tmp0 |= MBE(fb >> col); 228 1.37 rin 229 1.37 rin tmp1 = rp[1] & rmask; 230 1.29 rin tmp1 |= (MBE(fb << width) & ~rmask); 231 1.37 rin 232 1.29 rin rp[0] = tmp0; 233 1.29 rin rp[1] = tmp1; 234 1.37 rin 235 1.29 rin if (ri->ri_hwbits) { 236 1.31 rin hp[0] = tmp0; 237 1.31 rin hp[1] = tmp1; 238 1.37 rin DELTA(hp, ri->ri_stride, uint32_t *); 239 1.4 ad } 240 1.37 rin 241 1.37 rin DELTA(rp, ri->ri_stride, uint32_t *); 242 1.4 ad } 243 1.4 ad } 244 1.1 ad 245 1.4 ad /* Do underline */ 246 1.24 mlelstv if ((attr & WSATTR_UNDERLINE) != 0) { 247 1.35 rin DELTA(rp, - ri->ri_stride * ri->ri_ul.off, uint32_t *); 248 1.35 rin if (ri->ri_hwbits) 249 1.35 rin DELTA(hp, - ri->ri_stride * ri->ri_ul.off, 250 1.35 rin uint32_t *); 251 1.37 rin 252 1.35 rin for (height = ri->ri_ul.height; height; height--) { 253 1.35 rin DELTA(rp, - ri->ri_stride, uint32_t *); 254 1.35 rin tmp0 = (rp[0] & lmask) | (fg & ~lmask); 255 1.35 rin tmp1 = (rp[1] & rmask) | (fg & ~rmask); 256 1.35 rin rp[0] = tmp0; 257 1.35 rin rp[1] = tmp1; 258 1.35 rin if (ri->ri_hwbits) { 259 1.35 rin DELTA(hp, - ri->ri_stride, uint32_t *); 260 1.35 rin hp[0] = tmp0; 261 1.35 rin hp[1] = tmp1; 262 1.35 rin } 263 1.21 macallan } 264 1.4 ad } 265 1.4 ad } 266 1.1 ad } 267 1.1 ad 268 1.10 ad #ifndef RASOPS_SMALL 269 1.37 rin /* 270 1.37 rin * Width-optimized putchar functions 271 1.37 rin */ 272 1.29 rin #define RASOPS_WIDTH 8 273 1.37 rin #include <dev/rasops/rasops1_putchar_width.h> 274 1.29 rin #undef RASOPS_WIDTH 275 1.29 rin 276 1.29 rin #define RASOPS_WIDTH 16 277 1.37 rin #include <dev/rasops/rasops1_putchar_width.h> 278 1.29 rin #undef RASOPS_WIDTH 279 1.1 ad 280 1.10 ad #endif /* !RASOPS_SMALL */ 281 1.1 ad 282 1.1 ad /* 283 1.4 ad * Grab routines common to depths where (bpp < 8) 284 1.1 ad */ 285 1.4 ad #include <dev/rasops/rasops_bitops.h> 286