2 * Copyright (c) 2014 Imre Vadász <imre@vdsz.com>
5 * This code is derived from software contributed to The DragonFly Project
6 * by Sascha Wildner <saw@online.de>.
8 * Simple font scaling code by Sascha Wildner and Matthew Dillon
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer as
15 * the first lines of this file unmodified.
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.
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include "opt_syscons.h"
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
37 #include <sys/thread.h>
38 #include <sys/thread2.h>
40 #include <machine/console.h>
42 #include <dev/drm/include/linux/fb.h>
46 #include <bus/isa/isareg.h>
48 static vr_draw_border_t kms_draw_border;
49 static vr_draw_t kms_draw;
50 static vr_draw_cursor_t kms_cursor;
51 static vr_blink_cursor_t kms_blink;
52 #ifndef SC_NO_CUTPASTE
53 static vr_draw_mouse_t kms_mouse;
56 static void kms_nop(scr_stat *scp, ...);
58 static sc_rndr_sw_t kmsrndrsw = {
61 (vr_set_cursor_t *)kms_nop,
64 #ifndef SC_NO_CUTPASTE
67 (vr_draw_mouse_t *)kms_nop,
70 RENDERER(kms, V_INFO_MM_TEXT, kmsrndrsw, kms_set);
72 #ifndef SC_NO_MODE_CHANGE
73 static sc_rndr_sw_t grrndrsw = {
74 (vr_draw_border_t *)kms_nop,
76 (vr_set_cursor_t *)kms_nop,
77 (vr_draw_cursor_t *)kms_nop,
78 (vr_blink_cursor_t *)kms_nop,
79 (vr_draw_mouse_t *)kms_nop,
81 RENDERER(kms, V_INFO_MM_OTHER, grrndrsw, kms_set);
82 #endif /* SC_NO_MODE_CHANGE */
84 RENDERER_MODULE(kms, kms_set);
86 static uint32_t colormap[16] = {
87 0x00000000, /* BLACK */
88 0x000000aa, /* BLUE */
89 0x0000aa00, /* GREEN */
90 0x0000aaaa, /* CYAN */
92 0x00aa00aa, /* MAGENTA */
93 0x00aa5500, /* BROWN */
94 0x00aaaaaa, /* WHITE */
95 0x00555555, /* HIGHLIGHT BLACK */
96 0x005555ff, /* HIGHLIGHT BLUE */
97 0x0055ff55, /* HIGHLIGHT GREEN */
98 0x0055ffff, /* HIGHLIGHT CYAN */
99 0x00ff5555, /* HIGHLIGHT RED */
100 0x00ff55ff, /* HIGHLIGHT MAGENTA */
101 0x00ffff55, /* HIGHLIGHT BROWN */
102 0x00ffffff, /* HIGHLIGHT WHITE */
105 #ifndef SC_NO_CUTPASTE
106 static u_short mouse_and_mask[16] = {
107 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00, 0xff80,
108 0xfe00, 0x1e00, 0x1f00, 0x0f00, 0x0f00, 0x0000, 0x0000, 0x0000
110 static u_short mouse_or_mask[16] = {
111 0x0000, 0x4000, 0x6000, 0x7000, 0x7800, 0x7c00, 0x7e00, 0x6800,
112 0x0c00, 0x0c00, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, 0x0000
117 kms_nop(scr_stat *scp, ...)
122 * Scaled font rendering. Simple blit blitter copy operation with bitmap
123 * scaling. Scales the bitmap char_data(sw x sh) to the output bitmap
126 * This function does not do fractional scaling.
128 * SET - Sets both the fg and bg pen
130 * MASK - Sets only the fg pen based on the source mask and leaves
131 * the background untouched.
137 blit_blk(scr_stat *scp, u_char *char_data, int sw, int sh,
138 vm_offset_t draw_pos, int pixel_size, int dw, int dh,
139 int line_width, uint32_t fg, uint32_t bg, int how)
143 int x; /* destination iterator (whole pixels) */
145 int sx, sx_inc; /* source iterator (fractional) */
150 * Calculate fractional iterator for source
153 sx_inc = (sw << 16) / dw;
158 sy_inc = (sh << 16) / dh;
166 * For each pixel row in the target
168 for (y = 0; y < dh; ++y) {
173 * Render all pixel columns in the target by calculating
174 * which bit in the source is applicable.
178 for (x = 0; x < dw; ++x) {
179 if ((sx & 0x00070000) == 0)
180 c = char_data[sx >> 19];
181 pos = ~(sx >> 16) & 7;
182 writel(p, (c & (1 << pos) ? fg : bg));
188 for (x = 0; x < dw; ++x) {
189 if ((sx & 0x00070000) == 0)
190 c = char_data[sx >> 19];
191 pos = ~(sx >> 16) & 7;
199 draw_pos += line_width;
202 char_data += (sy >> 16) * (sw >> 3);
209 fill_rect(scr_stat *scp, vm_offset_t draw_pos, int pixel_size,
210 int width, int height, int line_width, uint32_t fg)
214 for (i = 0; i < height; i++) {
215 for (j = 0; j < width; j++)
216 writel(draw_pos + j * pixel_size, fg);
217 draw_pos += line_width;
224 kms_draw_border(scr_stat *scp, int color)
226 sc_softc_t *sc = scp->sc;
227 int line_width, pixel_size;
228 int rightpixel, bottompixel;
230 vm_offset_t draw_pos;
232 fg = colormap[color];
233 line_width = sc->fbi->stride;
235 rightpixel = sc->fbi->width - scp->xsize * scp->blk_width;
236 bottompixel = sc->fbi->height - scp->ysize * scp->blk_height;
238 if (sc->fbi->vaddr == 0)
241 draw_pos = sc->fbi->vaddr + scp->blk_width * pixel_size * scp->xsize;
242 fill_rect(scp, draw_pos, pixel_size, rightpixel,
243 scp->blk_height * scp->ysize, line_width, fg);
245 draw_pos = sc->fbi->vaddr + scp->blk_height * scp->ysize * line_width;
246 fill_rect(scp, draw_pos, pixel_size, sc->fbi->width,
247 sc->fbi->height - scp->blk_height * scp->ysize, line_width, fg);
251 kms_draw(scr_stat *scp, int from, int count, int flip)
253 sc_softc_t *sc = scp->sc;
257 vm_offset_t draw_pos, p;
258 int line_width, pixel_size;
260 line_width = sc->fbi->stride;
263 if (sc->fbi->vaddr == 0)
266 draw_pos = sc->fbi->vaddr +
267 scp->blk_height * line_width * (from / scp->xsize);
269 if (from + count > scp->xsize * scp->ysize)
270 count = scp->xsize * scp->ysize - from;
272 p = draw_pos + scp->blk_width * pixel_size * (from % scp->xsize);
273 for (i = from; count-- > 0; i++) {
274 char_data = &(scp->font[sc_vtb_getc(&scp->vtb, i) *
277 a = sc_vtb_geta(&scp->vtb, i);
279 fg = colormap[((a & 0xf000) >> 4) >> 8];
280 bg = colormap[(a & 0x0f00) >> 8];
282 fg = colormap[(a & 0x0f00) >> 8];
283 bg = colormap[((a & 0xf000) >> 4) >> 8];
285 blit_blk(scp, char_data, scp->font_width, scp->font_height,
286 p, pixel_size, scp->blk_width, scp->blk_height,
287 line_width, fg, bg, BLIT_SET);
288 p += scp->blk_width * pixel_size;
289 if ((i % scp->xsize) == scp->xsize - 1) {
290 draw_pos += scp->blk_height * line_width;
297 draw_kmscursor(scr_stat *scp, int at, int on, int flip)
299 sc_softc_t *sc = scp->sc;
300 int line_width, pixel_size;
305 unsigned char *char_data;
306 vm_offset_t draw_pos;
308 line_width = sc->fbi->stride;
310 cursor_base = /* scp->font_height - */ scp->cursor_base;
311 blk_base = scp->blk_height * cursor_base / scp->font_height;
313 if (sc->fbi->vaddr == 0)
316 draw_pos = sc->fbi->vaddr +
317 scp->blk_width * pixel_size * (at % scp->xsize) +
318 scp->blk_height * line_width * (at / scp->xsize) +
319 blk_base * line_width;
321 a = sc_vtb_geta(&scp->vtb, at);
323 fg = colormap[((on) ? (a & 0x0f00) :
324 ((a & 0xf000) >> 4)) >> 8];
325 bg = colormap[((on) ? ((a & 0xf000) >> 4) :
328 fg = colormap[((on) ? ((a & 0xf000) >> 4) :
330 bg = colormap[((on) ? (a & 0x0f00) :
331 ((a & 0xf000) >> 4)) >> 8];
334 char_data = &scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_height];
335 char_data += cursor_base;
337 blit_blk(scp, char_data,
338 scp->font_width, scp->font_height - cursor_base,
339 draw_pos, pixel_size,
340 scp->blk_width, scp->blk_height - blk_base,
341 line_width, fg, bg, BLIT_SET);
344 static int pxlblinkrate = 0;
347 kms_cursor(scr_stat *scp, int at, int blink, int on, int flip)
349 if (scp->cursor_height <= 0) /* the text cursor is disabled */
354 scp->status |= VR_CURSOR_ON;
355 draw_kmscursor(scp, at, on, flip);
356 } else if (++pxlblinkrate & 4) {
358 scp->status ^= VR_CURSOR_ON;
359 draw_kmscursor(scp, at,
360 scp->status & VR_CURSOR_ON, flip);
363 if (scp->status & VR_CURSOR_ON)
364 draw_kmscursor(scp, at, on, flip);
365 scp->status &= ~VR_CURSOR_ON;
368 scp->status |= VR_CURSOR_BLINK;
370 scp->status &= ~VR_CURSOR_BLINK;
374 kms_blink(scr_stat *scp, int at, int flip)
376 if (!(scp->status & VR_CURSOR_BLINK))
378 if (!(++pxlblinkrate & 4))
381 scp->status ^= VR_CURSOR_ON;
382 draw_kmscursor(scp, at, scp->status & VR_CURSOR_ON, flip);
385 #ifndef SC_NO_CUTPASTE
388 draw_kmsmouse(scr_stat *scp, int x, int y)
390 sc_softc_t *sc = scp->sc;
391 int line_width, pixel_size;
392 int blk_width, blk_height;
393 vm_offset_t draw_pos;
395 line_width = sc->fbi->stride;
398 if (sc->fbi->vaddr == 0)
401 if (x + scp->font_width < scp->font_width * scp->xsize)
402 blk_width = scp->blk_width;
404 blk_width = scp->font_width * scp->xsize - x;
406 if (y + scp->font_height < scp->font_height * scp->ysize)
407 blk_height = scp->blk_height;
409 blk_height = scp->font_height * scp->ysize - y;
411 draw_pos = sc->fbi->vaddr + y * scp->blk_height / scp->font_height *
413 x * scp->blk_width / scp->font_width * pixel_size;
414 blit_blk(scp, (unsigned char *)mouse_and_mask, 16, 16,
415 draw_pos, pixel_size, blk_width, blk_height,
416 line_width, colormap[0], 0, BLIT_MASK);
417 blit_blk(scp, (unsigned char *)mouse_or_mask, 16, 16,
418 draw_pos, pixel_size, blk_width, blk_height,
419 line_width, colormap[15], 0, BLIT_MASK);
423 remove_kmsmouse(scr_stat *scp, int x, int y)
429 /* erase the mouse cursor image */
430 col = x / scp->font_width - scp->xoff;
431 row = y / scp->font_height - scp->yoff;
432 pos = row * scp->xsize + col;
433 i = (col < scp->xsize - 1) ? 2 : 1;
434 (*scp->rndr->draw)(scp, pos, i, FALSE);
435 if (row < scp->ysize - 1)
436 (*scp->rndr->draw)(scp, pos + scp->xsize, i, FALSE);
440 kms_mouse(scr_stat *scp, int x, int y, int on)
443 draw_kmsmouse(scp, x, y);
445 remove_kmsmouse(scp, x, y);
448 #endif /* SC_NO_CUTPASTE */