1717f4a47SSascha Wildner /*-
2717f4a47SSascha Wildner * Copyright (c) 2014 Imre Vadász <imre@vdsz.com>
3717f4a47SSascha Wildner * All rights reserved.
4717f4a47SSascha Wildner *
5219917caSSascha Wildner * This code is derived from software contributed to The DragonFly Project
6219917caSSascha Wildner * by Sascha Wildner <saw@online.de>.
7219917caSSascha Wildner *
8219917caSSascha Wildner * Simple font scaling code by Sascha Wildner and Matthew Dillon
9219917caSSascha Wildner *
10717f4a47SSascha Wildner * Redistribution and use in source and binary forms, with or without
11717f4a47SSascha Wildner * modification, are permitted provided that the following conditions
12717f4a47SSascha Wildner * are met:
13717f4a47SSascha Wildner * 1. Redistributions of source code must retain the above copyright
14717f4a47SSascha Wildner * notice, this list of conditions and the following disclaimer as
15717f4a47SSascha Wildner * the first lines of this file unmodified.
16717f4a47SSascha Wildner * 2. Redistributions in binary form must reproduce the above copyright
17717f4a47SSascha Wildner * notice, this list of conditions and the following disclaimer in the
18717f4a47SSascha Wildner * documentation and/or other materials provided with the distribution.
19717f4a47SSascha Wildner *
20717f4a47SSascha Wildner * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
21717f4a47SSascha Wildner * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22717f4a47SSascha Wildner * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23717f4a47SSascha Wildner * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24717f4a47SSascha Wildner * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25717f4a47SSascha Wildner * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26717f4a47SSascha Wildner * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27717f4a47SSascha Wildner * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28717f4a47SSascha Wildner * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29717f4a47SSascha Wildner * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30717f4a47SSascha Wildner */
31717f4a47SSascha Wildner
32717f4a47SSascha Wildner #include "opt_syscons.h"
33717f4a47SSascha Wildner
34717f4a47SSascha Wildner #include <sys/param.h>
35717f4a47SSascha Wildner #include <sys/systm.h>
36717f4a47SSascha Wildner #include <sys/kernel.h>
37717f4a47SSascha Wildner #include <sys/thread.h>
38717f4a47SSascha Wildner
39717f4a47SSascha Wildner #include <machine/console.h>
40233d54adSImre Vadász #include <machine/framebuffer.h>
41717f4a47SSascha Wildner
42717f4a47SSascha Wildner #include "syscons.h"
43717f4a47SSascha Wildner
44717f4a47SSascha Wildner #include <bus/isa/isareg.h>
45717f4a47SSascha Wildner
461d22c1f7SImre Vadász static vr_draw_border_t kms_draw_border;
47717f4a47SSascha Wildner static vr_draw_t kms_draw;
48717f4a47SSascha Wildner static vr_draw_cursor_t kms_cursor;
49717f4a47SSascha Wildner static vr_blink_cursor_t kms_blink;
50539fbd92SMatthew Dillon #ifndef SC_NO_CUTPASTE
51717f4a47SSascha Wildner static vr_draw_mouse_t kms_mouse;
52539fbd92SMatthew Dillon #endif
53717f4a47SSascha Wildner
54717f4a47SSascha Wildner static void kms_nop(scr_stat *scp, ...);
55717f4a47SSascha Wildner
56717f4a47SSascha Wildner static sc_rndr_sw_t kmsrndrsw = {
571d22c1f7SImre Vadász kms_draw_border,
58717f4a47SSascha Wildner kms_draw,
59717f4a47SSascha Wildner (vr_set_cursor_t *)kms_nop,
60717f4a47SSascha Wildner kms_cursor,
61717f4a47SSascha Wildner kms_blink,
62717f4a47SSascha Wildner #ifndef SC_NO_CUTPASTE
63717f4a47SSascha Wildner kms_mouse,
64717f4a47SSascha Wildner #else
65539fbd92SMatthew Dillon (vr_draw_mouse_t *)kms_nop,
66717f4a47SSascha Wildner #endif
67717f4a47SSascha Wildner };
68717f4a47SSascha Wildner RENDERER(kms, V_INFO_MM_TEXT, kmsrndrsw, kms_set);
69717f4a47SSascha Wildner
70717f4a47SSascha Wildner #ifndef SC_NO_MODE_CHANGE
71717f4a47SSascha Wildner static sc_rndr_sw_t grrndrsw = {
72717f4a47SSascha Wildner (vr_draw_border_t *)kms_nop,
73717f4a47SSascha Wildner (vr_draw_t *)kms_nop,
74717f4a47SSascha Wildner (vr_set_cursor_t *)kms_nop,
75717f4a47SSascha Wildner (vr_draw_cursor_t *)kms_nop,
76717f4a47SSascha Wildner (vr_blink_cursor_t *)kms_nop,
77717f4a47SSascha Wildner (vr_draw_mouse_t *)kms_nop,
78717f4a47SSascha Wildner };
79717f4a47SSascha Wildner RENDERER(kms, V_INFO_MM_OTHER, grrndrsw, kms_set);
80717f4a47SSascha Wildner #endif /* SC_NO_MODE_CHANGE */
81717f4a47SSascha Wildner
82717f4a47SSascha Wildner RENDERER_MODULE(kms, kms_set);
83717f4a47SSascha Wildner
84717f4a47SSascha Wildner static uint32_t colormap[16] = {
85717f4a47SSascha Wildner 0x00000000, /* BLACK */
86717f4a47SSascha Wildner 0x000000aa, /* BLUE */
87717f4a47SSascha Wildner 0x0000aa00, /* GREEN */
88717f4a47SSascha Wildner 0x0000aaaa, /* CYAN */
89717f4a47SSascha Wildner 0x00aa0000, /* RED */
90717f4a47SSascha Wildner 0x00aa00aa, /* MAGENTA */
91717f4a47SSascha Wildner 0x00aa5500, /* BROWN */
92717f4a47SSascha Wildner 0x00aaaaaa, /* WHITE */
93717f4a47SSascha Wildner 0x00555555, /* HIGHLIGHT BLACK */
94717f4a47SSascha Wildner 0x005555ff, /* HIGHLIGHT BLUE */
95717f4a47SSascha Wildner 0x0055ff55, /* HIGHLIGHT GREEN */
96717f4a47SSascha Wildner 0x0055ffff, /* HIGHLIGHT CYAN */
97717f4a47SSascha Wildner 0x00ff5555, /* HIGHLIGHT RED */
98717f4a47SSascha Wildner 0x00ff55ff, /* HIGHLIGHT MAGENTA */
99717f4a47SSascha Wildner 0x00ffff55, /* HIGHLIGHT BROWN */
100717f4a47SSascha Wildner 0x00ffffff, /* HIGHLIGHT WHITE */
101717f4a47SSascha Wildner };
102717f4a47SSascha Wildner
103717f4a47SSascha Wildner #ifndef SC_NO_CUTPASTE
104717f4a47SSascha Wildner static u_short mouse_and_mask[16] = {
105717f4a47SSascha Wildner 0xc000, 0xe000, 0xf000, 0xf800, 0xfc00, 0xfe00, 0xff00, 0xff80,
106717f4a47SSascha Wildner 0xfe00, 0x1e00, 0x1f00, 0x0f00, 0x0f00, 0x0000, 0x0000, 0x0000
107717f4a47SSascha Wildner };
108717f4a47SSascha Wildner static u_short mouse_or_mask[16] = {
109717f4a47SSascha Wildner 0x0000, 0x4000, 0x6000, 0x7000, 0x7800, 0x7c00, 0x7e00, 0x6800,
110717f4a47SSascha Wildner 0x0c00, 0x0c00, 0x0600, 0x0600, 0x0000, 0x0000, 0x0000, 0x0000
111717f4a47SSascha Wildner };
112717f4a47SSascha Wildner #endif
113717f4a47SSascha Wildner
114717f4a47SSascha Wildner static void
kms_nop(scr_stat * scp,...)115717f4a47SSascha Wildner kms_nop(scr_stat *scp, ...)
116717f4a47SSascha Wildner {
117717f4a47SSascha Wildner }
118717f4a47SSascha Wildner
119219917caSSascha Wildner /*
120219917caSSascha Wildner * Scaled font rendering. Simple blit blitter copy operation with bitmap
121219917caSSascha Wildner * scaling. Scales the bitmap char_data(sw x sh) to the output bitmap
122219917caSSascha Wildner * draw_pos(dw x dh).
123219917caSSascha Wildner *
124219917caSSascha Wildner * This function does not do fractional scaling.
125219917caSSascha Wildner *
126219917caSSascha Wildner * SET - Sets both the fg and bg pen
127219917caSSascha Wildner *
128219917caSSascha Wildner * MASK - Sets only the fg pen based on the source mask and leaves
129219917caSSascha Wildner * the background untouched.
130219917caSSascha Wildner */
131219917caSSascha Wildner #define BLIT_SET 0
132219917caSSascha Wildner #define BLIT_MASK 1
133219917caSSascha Wildner
134*a6dad826SImre Vadász static inline void
blit_blk32(scr_stat * scp,u_char * char_data,int sw,int sh,vm_offset_t draw_pos,int dw,int dh,int line_width,uint32_t fg,uint32_t bg,int how)135*a6dad826SImre Vadász blit_blk32(scr_stat *scp, u_char *char_data, int sw, int sh,
136*a6dad826SImre Vadász vm_offset_t draw_pos, int dw, int dh,
137219917caSSascha Wildner int line_width, uint32_t fg, uint32_t bg, int how)
138219917caSSascha Wildner {
139219917caSSascha Wildner vm_offset_t p;
140219917caSSascha Wildner int pos;
141219917caSSascha Wildner int x; /* destination iterator (whole pixels) */
142219917caSSascha Wildner int y;
143219917caSSascha Wildner int sx, sx_inc; /* source iterator (fractional) */
144219917caSSascha Wildner int sy, sy_inc;
145219917caSSascha Wildner uint8_t c;
146219917caSSascha Wildner
147219917caSSascha Wildner /*
148219917caSSascha Wildner * Calculate fractional iterator for source
149219917caSSascha Wildner */
150219917caSSascha Wildner if (dw)
151219917caSSascha Wildner sx_inc = (sw << 16) / dw;
152219917caSSascha Wildner else
153219917caSSascha Wildner sx_inc = 0;
154219917caSSascha Wildner
155219917caSSascha Wildner if (dh)
156219917caSSascha Wildner sy_inc = (sh << 16) / dh;
157219917caSSascha Wildner else
158219917caSSascha Wildner sy_inc = 0;
159219917caSSascha Wildner
160219917caSSascha Wildner sy = 0;
161219917caSSascha Wildner c = 0;
162219917caSSascha Wildner
163219917caSSascha Wildner /*
164219917caSSascha Wildner * For each pixel row in the target
165219917caSSascha Wildner */
166219917caSSascha Wildner for (y = 0; y < dh; ++y) {
167219917caSSascha Wildner sx = 0;
168219917caSSascha Wildner p = draw_pos;
169219917caSSascha Wildner
170219917caSSascha Wildner /*
171219917caSSascha Wildner * Render all pixel columns in the target by calculating
172219917caSSascha Wildner * which bit in the source is applicable.
173219917caSSascha Wildner */
174219917caSSascha Wildner switch(how) {
175219917caSSascha Wildner case BLIT_SET:
176219917caSSascha Wildner for (x = 0; x < dw; ++x) {
177219917caSSascha Wildner if ((sx & 0x00070000) == 0)
178219917caSSascha Wildner c = char_data[sx >> 19];
179219917caSSascha Wildner pos = ~(sx >> 16) & 7;
180*a6dad826SImre Vadász writel(p + x * 4, (c & (1 << pos) ? fg : bg));
181219917caSSascha Wildner sx += sx_inc;
182219917caSSascha Wildner }
183219917caSSascha Wildner break;
184219917caSSascha Wildner case BLIT_MASK:
185219917caSSascha Wildner for (x = 0; x < dw; ++x) {
186219917caSSascha Wildner if ((sx & 0x00070000) == 0)
187219917caSSascha Wildner c = char_data[sx >> 19];
188219917caSSascha Wildner pos = ~(sx >> 16) & 7;
189219917caSSascha Wildner if (c & (1 << pos))
190*a6dad826SImre Vadász writel(p + x * 4, fg);
191*a6dad826SImre Vadász sx += sx_inc;
192*a6dad826SImre Vadász }
193*a6dad826SImre Vadász break;
194*a6dad826SImre Vadász }
195*a6dad826SImre Vadász draw_pos += line_width;
196*a6dad826SImre Vadász sy += sy_inc;
197*a6dad826SImre Vadász if (sy >= 0x10000) {
198*a6dad826SImre Vadász char_data += (sy >> 16) * (sw >> 3);
199*a6dad826SImre Vadász sy &= 0x0FFFF;
200*a6dad826SImre Vadász }
201*a6dad826SImre Vadász }
202*a6dad826SImre Vadász }
203*a6dad826SImre Vadász
204*a6dad826SImre Vadász static inline void
blit_blk24(scr_stat * scp,u_char * char_data,int sw,int sh,vm_offset_t draw_pos,int dw,int dh,int line_width,uint32_t fg,uint32_t bg,int how)205*a6dad826SImre Vadász blit_blk24(scr_stat *scp, u_char *char_data, int sw, int sh,
206*a6dad826SImre Vadász vm_offset_t draw_pos, int dw, int dh,
207*a6dad826SImre Vadász int line_width, uint32_t fg, uint32_t bg, int how)
208*a6dad826SImre Vadász {
209*a6dad826SImre Vadász vm_offset_t p;
210*a6dad826SImre Vadász int pos;
211*a6dad826SImre Vadász int x; /* destination iterator (whole pixels) */
212*a6dad826SImre Vadász int y;
213*a6dad826SImre Vadász int sx, sx_inc; /* source iterator (fractional) */
214*a6dad826SImre Vadász int sy, sy_inc;
215*a6dad826SImre Vadász uint8_t c;
216*a6dad826SImre Vadász
217*a6dad826SImre Vadász /*
218*a6dad826SImre Vadász * Calculate fractional iterator for source
219*a6dad826SImre Vadász */
220*a6dad826SImre Vadász if (dw)
221*a6dad826SImre Vadász sx_inc = (sw << 16) / dw;
222*a6dad826SImre Vadász else
223*a6dad826SImre Vadász sx_inc = 0;
224*a6dad826SImre Vadász
225*a6dad826SImre Vadász if (dh)
226*a6dad826SImre Vadász sy_inc = (sh << 16) / dh;
227*a6dad826SImre Vadász else
228*a6dad826SImre Vadász sy_inc = 0;
229*a6dad826SImre Vadász
230*a6dad826SImre Vadász sy = 0;
231*a6dad826SImre Vadász c = 0;
232*a6dad826SImre Vadász
233*a6dad826SImre Vadász /*
234*a6dad826SImre Vadász * For each pixel row in the target
235*a6dad826SImre Vadász */
236*a6dad826SImre Vadász for (y = 0; y < dh; ++y) {
237*a6dad826SImre Vadász sx = 0;
238*a6dad826SImre Vadász p = draw_pos;
239*a6dad826SImre Vadász
240*a6dad826SImre Vadász /*
241*a6dad826SImre Vadász * Render all pixel columns in the target by calculating
242*a6dad826SImre Vadász * which bit in the source is applicable.
243*a6dad826SImre Vadász */
244*a6dad826SImre Vadász switch(how) {
245*a6dad826SImre Vadász case BLIT_SET:
246*a6dad826SImre Vadász for (x = 0; x < dw; ++x) {
247*a6dad826SImre Vadász if ((sx & 0x00070000) == 0)
248*a6dad826SImre Vadász c = char_data[sx >> 19];
249*a6dad826SImre Vadász pos = ~(sx >> 16) & 7;
250*a6dad826SImre Vadász uint32_t col = c & (1 << pos) ? fg : bg;
251*a6dad826SImre Vadász writeb(p, col >> 16);
252*a6dad826SImre Vadász writeb(p + 1, col >> 8);
253*a6dad826SImre Vadász writeb(p + 2, col >> 0);
254*a6dad826SImre Vadász p += 3;
255*a6dad826SImre Vadász sx += sx_inc;
256*a6dad826SImre Vadász }
257*a6dad826SImre Vadász break;
258*a6dad826SImre Vadász case BLIT_MASK:
259*a6dad826SImre Vadász for (x = 0; x < dw; ++x) {
260*a6dad826SImre Vadász if ((sx & 0x00070000) == 0)
261*a6dad826SImre Vadász c = char_data[sx >> 19];
262*a6dad826SImre Vadász pos = ~(sx >> 16) & 7;
263*a6dad826SImre Vadász if (c & (1 << pos)) {
264*a6dad826SImre Vadász writeb(p, fg >> 16);
265*a6dad826SImre Vadász writeb(p + 1, fg >> 8);
266*a6dad826SImre Vadász writeb(p + 2, fg >> 0);
267*a6dad826SImre Vadász }
268*a6dad826SImre Vadász p += 3;
269219917caSSascha Wildner sx += sx_inc;
270219917caSSascha Wildner }
271219917caSSascha Wildner break;
272219917caSSascha Wildner }
273219917caSSascha Wildner draw_pos += line_width;
274219917caSSascha Wildner sy += sy_inc;
275219917caSSascha Wildner if (sy >= 0x10000) {
276219917caSSascha Wildner char_data += (sy >> 16) * (sw >> 3);
277219917caSSascha Wildner sy &= 0x0FFFF;
278219917caSSascha Wildner }
279219917caSSascha Wildner }
280219917caSSascha Wildner }
281219917caSSascha Wildner
2821d22c1f7SImre Vadász static void
fill_rect32(scr_stat * scp,vm_offset_t draw_pos,int width,int height,int line_width,uint32_t fg)283*a6dad826SImre Vadász fill_rect32(scr_stat *scp, vm_offset_t draw_pos, int width, int height,
284*a6dad826SImre Vadász int line_width, uint32_t fg)
2851d22c1f7SImre Vadász {
2861d22c1f7SImre Vadász int i, j;
2871d22c1f7SImre Vadász
2881d22c1f7SImre Vadász for (i = 0; i < height; i++) {
2891d22c1f7SImre Vadász for (j = 0; j < width; j++)
290*a6dad826SImre Vadász writel(draw_pos + j * 4, fg);
2911d22c1f7SImre Vadász draw_pos += line_width;
2921d22c1f7SImre Vadász }
2931d22c1f7SImre Vadász }
2941d22c1f7SImre Vadász
295*a6dad826SImre Vadász static void
fill_rect24(scr_stat * scp,vm_offset_t draw_pos,int width,int height,int line_width,uint32_t fg)296*a6dad826SImre Vadász fill_rect24(scr_stat *scp, vm_offset_t draw_pos, int width, int height,
297*a6dad826SImre Vadász int line_width, uint32_t fg)
298*a6dad826SImre Vadász {
299*a6dad826SImre Vadász int i, j, d;
300*a6dad826SImre Vadász
301*a6dad826SImre Vadász d = line_width - width * 3;
302*a6dad826SImre Vadász KKASSERT(d >= 0);
303*a6dad826SImre Vadász
304*a6dad826SImre Vadász if ((draw_pos & 0x3) == 0 && (line_width & 0x3) == 0 &&
305*a6dad826SImre Vadász (width & 0x3) == 0) {
306*a6dad826SImre Vadász uint32_t fga = fg | (fg << 24);
307*a6dad826SImre Vadász uint32_t fgb = (fg << 16) | ((fg >> 8) & 0xffff);
308*a6dad826SImre Vadász uint32_t fgc = (fg << 8) | ((fg >> 16) & 0xff);
309*a6dad826SImre Vadász for (i = 0; i < height; i++) {
310*a6dad826SImre Vadász for (j = 0; j < width; j += 4) {
311*a6dad826SImre Vadász writel(draw_pos, fga);
312*a6dad826SImre Vadász writel(draw_pos + 4, fgb);
313*a6dad826SImre Vadász writel(draw_pos + 8, fgc);
314*a6dad826SImre Vadász draw_pos += 12;
315*a6dad826SImre Vadász }
316*a6dad826SImre Vadász draw_pos += d;
317*a6dad826SImre Vadász }
318*a6dad826SImre Vadász } else {
319*a6dad826SImre Vadász for (i = 0; i < height; i++) {
320*a6dad826SImre Vadász for (j = 0; j < width; j++) {
321*a6dad826SImre Vadász writeb(draw_pos, fg >> 16);
322*a6dad826SImre Vadász writeb(draw_pos + 1, fg >> 8);
323*a6dad826SImre Vadász writeb(draw_pos + 2, fg >> 0);
324*a6dad826SImre Vadász draw_pos += 3;
325*a6dad826SImre Vadász }
326*a6dad826SImre Vadász draw_pos += line_width;
327*a6dad826SImre Vadász }
328*a6dad826SImre Vadász }
329*a6dad826SImre Vadász }
330*a6dad826SImre Vadász
331717f4a47SSascha Wildner /* KMS renderer */
332717f4a47SSascha Wildner
333717f4a47SSascha Wildner static void
kms_draw_border(scr_stat * scp,int color)3341d22c1f7SImre Vadász kms_draw_border(scr_stat *scp, int color)
3351d22c1f7SImre Vadász {
3361d22c1f7SImre Vadász sc_softc_t *sc = scp->sc;
3371d22c1f7SImre Vadász int line_width, pixel_size;
3381d22c1f7SImre Vadász int rightpixel, bottompixel;
3391d22c1f7SImre Vadász uint32_t fg;
3401d22c1f7SImre Vadász vm_offset_t draw_pos;
3411d22c1f7SImre Vadász
3422b5f463dSImre Vadász if (sc->fbi->vaddr == 0)
3432b5f463dSImre Vadász return;
3442b5f463dSImre Vadász
345*a6dad826SImre Vadász fg = colormap[color];
346*a6dad826SImre Vadász line_width = sc->fbi->stride;
347*a6dad826SImre Vadász /* sc->fbi->depth may only be 24 or 32 */
348*a6dad826SImre Vadász pixel_size = sc->fbi->depth == 24 ? 3 : 4;
349*a6dad826SImre Vadász rightpixel = sc->fbi->width - scp->xsize * scp->blk_width;
350*a6dad826SImre Vadász bottompixel = sc->fbi->height - scp->ysize * scp->blk_height;
351*a6dad826SImre Vadász
3521d22c1f7SImre Vadász draw_pos = sc->fbi->vaddr + scp->blk_width * pixel_size * scp->xsize;
353*a6dad826SImre Vadász if (pixel_size == 3) {
354*a6dad826SImre Vadász fill_rect24(scp, draw_pos, rightpixel,
3551d22c1f7SImre Vadász scp->blk_height * scp->ysize, line_width, fg);
356*a6dad826SImre Vadász } else {
357*a6dad826SImre Vadász fill_rect32(scp, draw_pos, rightpixel,
358*a6dad826SImre Vadász scp->blk_height * scp->ysize, line_width, fg);
359*a6dad826SImre Vadász }
3601d22c1f7SImre Vadász
3611d22c1f7SImre Vadász draw_pos = sc->fbi->vaddr + scp->blk_height * scp->ysize * line_width;
362*a6dad826SImre Vadász if (pixel_size == 3) {
363*a6dad826SImre Vadász fill_rect24(scp, draw_pos, sc->fbi->width,
364*a6dad826SImre Vadász sc->fbi->height - scp->blk_height * scp->ysize, line_width,
365*a6dad826SImre Vadász fg);
366*a6dad826SImre Vadász } else {
367*a6dad826SImre Vadász fill_rect32(scp, draw_pos, sc->fbi->width,
368*a6dad826SImre Vadász sc->fbi->height - scp->blk_height * scp->ysize, line_width,
369*a6dad826SImre Vadász fg);
370*a6dad826SImre Vadász }
3711d22c1f7SImre Vadász }
3721d22c1f7SImre Vadász
3731d22c1f7SImre Vadász static void
kms_draw(scr_stat * scp,int from,int count,int flip)3747ae6dbf0SMatthew Dillon kms_draw(scr_stat *scp, int from, int count, int flip)
375717f4a47SSascha Wildner {
376717f4a47SSascha Wildner sc_softc_t *sc = scp->sc;
377717f4a47SSascha Wildner u_char *char_data;
378219917caSSascha Wildner int a, i;
379717f4a47SSascha Wildner uint32_t fg, bg;
380717f4a47SSascha Wildner vm_offset_t draw_pos, p;
381219917caSSascha Wildner int line_width, pixel_size;
382717f4a47SSascha Wildner
3832b5f463dSImre Vadász if (sc->fbi->vaddr == 0)
3842b5f463dSImre Vadász return;
3852b5f463dSImre Vadász
386*a6dad826SImre Vadász line_width = sc->fbi->stride;
387*a6dad826SImre Vadász /* sc->fbi->depth may only be 24 or 32 */
388*a6dad826SImre Vadász pixel_size = sc->fbi->depth == 24 ? 3 : 4;
389*a6dad826SImre Vadász
390717f4a47SSascha Wildner draw_pos = sc->fbi->vaddr +
391219917caSSascha Wildner scp->blk_height * line_width * (from / scp->xsize);
392717f4a47SSascha Wildner
393717f4a47SSascha Wildner if (from + count > scp->xsize * scp->ysize)
394717f4a47SSascha Wildner count = scp->xsize * scp->ysize - from;
395717f4a47SSascha Wildner
396104db078SImre Vadasz p = draw_pos + scp->blk_width * pixel_size * (from % scp->xsize);
3978453b73bSImre Vadász for (i = from; count-- > 0; i++) {
398717f4a47SSascha Wildner char_data = &(scp->font[sc_vtb_getc(&scp->vtb, i) *
399219917caSSascha Wildner scp->font_height]);
400717f4a47SSascha Wildner
401717f4a47SSascha Wildner a = sc_vtb_geta(&scp->vtb, i);
402717f4a47SSascha Wildner if (flip) {
403717f4a47SSascha Wildner fg = colormap[((a & 0xf000) >> 4) >> 8];
404717f4a47SSascha Wildner bg = colormap[(a & 0x0f00) >> 8];
405717f4a47SSascha Wildner } else {
406717f4a47SSascha Wildner fg = colormap[(a & 0x0f00) >> 8];
407717f4a47SSascha Wildner bg = colormap[((a & 0xf000) >> 4) >> 8];
408717f4a47SSascha Wildner }
409*a6dad826SImre Vadász if (pixel_size == 3) {
410*a6dad826SImre Vadász blit_blk24(scp, char_data, scp->font_width,
411*a6dad826SImre Vadász scp->font_height, p, scp->blk_width,
412*a6dad826SImre Vadász scp->blk_height, line_width, fg, bg,
413*a6dad826SImre Vadász BLIT_SET);
414*a6dad826SImre Vadász } else {
415*a6dad826SImre Vadász blit_blk32(scp, char_data, scp->font_width,
416*a6dad826SImre Vadász scp->font_height, p, scp->blk_width,
417*a6dad826SImre Vadász scp->blk_height, line_width, fg, bg,
418*a6dad826SImre Vadász BLIT_SET);
419*a6dad826SImre Vadász }
4208453b73bSImre Vadász p += scp->blk_width * pixel_size;
421717f4a47SSascha Wildner if ((i % scp->xsize) == scp->xsize - 1) {
4228453b73bSImre Vadász draw_pos += scp->blk_height * line_width;
4238453b73bSImre Vadász p = draw_pos;
424717f4a47SSascha Wildner }
425717f4a47SSascha Wildner }
426717f4a47SSascha Wildner }
427717f4a47SSascha Wildner
428717f4a47SSascha Wildner static void
draw_kmscursor(scr_stat * scp,int at,int on,int flip)429717f4a47SSascha Wildner draw_kmscursor(scr_stat *scp, int at, int on, int flip)
430717f4a47SSascha Wildner {
431717f4a47SSascha Wildner sc_softc_t *sc = scp->sc;
432219917caSSascha Wildner int line_width, pixel_size;
433219917caSSascha Wildner int cursor_base;
434219917caSSascha Wildner int blk_base;
435219917caSSascha Wildner int a;
436717f4a47SSascha Wildner uint32_t fg, bg;
437717f4a47SSascha Wildner unsigned char *char_data;
438717f4a47SSascha Wildner vm_offset_t draw_pos;
439717f4a47SSascha Wildner
4402b5f463dSImre Vadász if (sc->fbi->vaddr == 0)
4412b5f463dSImre Vadász return;
4422b5f463dSImre Vadász
443*a6dad826SImre Vadász line_width = sc->fbi->stride;
444*a6dad826SImre Vadász /* sc->fbi->depth may only be 24 or 32 */
445*a6dad826SImre Vadász pixel_size = sc->fbi->depth == 24 ? 3 : 4;
446*a6dad826SImre Vadász cursor_base = /* scp->font_height - */ scp->cursor_base;
447*a6dad826SImre Vadász blk_base = scp->blk_height * cursor_base / scp->font_height;
448*a6dad826SImre Vadász
449717f4a47SSascha Wildner draw_pos = sc->fbi->vaddr +
450219917caSSascha Wildner scp->blk_width * pixel_size * (at % scp->xsize) +
451219917caSSascha Wildner scp->blk_height * line_width * (at / scp->xsize) +
452219917caSSascha Wildner blk_base * line_width;
453717f4a47SSascha Wildner
454717f4a47SSascha Wildner a = sc_vtb_geta(&scp->vtb, at);
455717f4a47SSascha Wildner if (flip) {
456717f4a47SSascha Wildner fg = colormap[((on) ? (a & 0x0f00) :
457717f4a47SSascha Wildner ((a & 0xf000) >> 4)) >> 8];
458717f4a47SSascha Wildner bg = colormap[((on) ? ((a & 0xf000) >> 4) :
459717f4a47SSascha Wildner (a & 0x0f00)) >> 8];
460717f4a47SSascha Wildner } else {
461717f4a47SSascha Wildner fg = colormap[((on) ? ((a & 0xf000) >> 4) :
462717f4a47SSascha Wildner (a & 0x0f00)) >> 8];
463717f4a47SSascha Wildner bg = colormap[((on) ? (a & 0x0f00) :
464717f4a47SSascha Wildner ((a & 0xf000) >> 4)) >> 8];
465717f4a47SSascha Wildner }
466717f4a47SSascha Wildner
467219917caSSascha Wildner char_data = &scp->font[sc_vtb_getc(&scp->vtb, at) * scp->font_height];
468219917caSSascha Wildner char_data += cursor_base;
469717f4a47SSascha Wildner
470*a6dad826SImre Vadász if (pixel_size == 3) {
471*a6dad826SImre Vadász blit_blk24(scp, char_data,
472219917caSSascha Wildner scp->font_width, scp->font_height - cursor_base,
473*a6dad826SImre Vadász draw_pos, scp->blk_width, scp->blk_height - blk_base,
474219917caSSascha Wildner line_width, fg, bg, BLIT_SET);
475*a6dad826SImre Vadász } else {
476*a6dad826SImre Vadász blit_blk32(scp, char_data,
477*a6dad826SImre Vadász scp->font_width, scp->font_height - cursor_base,
478*a6dad826SImre Vadász draw_pos, scp->blk_width, scp->blk_height - blk_base,
479*a6dad826SImre Vadász line_width, fg, bg, BLIT_SET);
480*a6dad826SImre Vadász }
481717f4a47SSascha Wildner }
482717f4a47SSascha Wildner
483717f4a47SSascha Wildner static int pxlblinkrate = 0;
484717f4a47SSascha Wildner
485717f4a47SSascha Wildner static void
kms_cursor(scr_stat * scp,int at,int blink,int on,int flip)486717f4a47SSascha Wildner kms_cursor(scr_stat *scp, int at, int blink, int on, int flip)
487717f4a47SSascha Wildner {
488717f4a47SSascha Wildner if (scp->cursor_height <= 0) /* the text cursor is disabled */
489717f4a47SSascha Wildner return;
490717f4a47SSascha Wildner
491717f4a47SSascha Wildner if (on) {
492717f4a47SSascha Wildner if (!blink) {
493717f4a47SSascha Wildner scp->status |= VR_CURSOR_ON;
494717f4a47SSascha Wildner draw_kmscursor(scp, at, on, flip);
495717f4a47SSascha Wildner } else if (++pxlblinkrate & 4) {
496717f4a47SSascha Wildner pxlblinkrate = 0;
497717f4a47SSascha Wildner scp->status ^= VR_CURSOR_ON;
498717f4a47SSascha Wildner draw_kmscursor(scp, at,
499717f4a47SSascha Wildner scp->status & VR_CURSOR_ON, flip);
500717f4a47SSascha Wildner }
501717f4a47SSascha Wildner } else {
502717f4a47SSascha Wildner if (scp->status & VR_CURSOR_ON)
503717f4a47SSascha Wildner draw_kmscursor(scp, at, on, flip);
504717f4a47SSascha Wildner scp->status &= ~VR_CURSOR_ON;
505717f4a47SSascha Wildner }
506717f4a47SSascha Wildner if (blink)
507717f4a47SSascha Wildner scp->status |= VR_CURSOR_BLINK;
508717f4a47SSascha Wildner else
509717f4a47SSascha Wildner scp->status &= ~VR_CURSOR_BLINK;
510717f4a47SSascha Wildner }
511717f4a47SSascha Wildner
512717f4a47SSascha Wildner static void
kms_blink(scr_stat * scp,int at,int flip)513717f4a47SSascha Wildner kms_blink(scr_stat *scp, int at, int flip)
514717f4a47SSascha Wildner {
515717f4a47SSascha Wildner if (!(scp->status & VR_CURSOR_BLINK))
516717f4a47SSascha Wildner return;
517717f4a47SSascha Wildner if (!(++pxlblinkrate & 4))
518717f4a47SSascha Wildner return;
519717f4a47SSascha Wildner pxlblinkrate = 0;
520717f4a47SSascha Wildner scp->status ^= VR_CURSOR_ON;
521717f4a47SSascha Wildner draw_kmscursor(scp, at, scp->status & VR_CURSOR_ON, flip);
522717f4a47SSascha Wildner }
523717f4a47SSascha Wildner
524717f4a47SSascha Wildner #ifndef SC_NO_CUTPASTE
525717f4a47SSascha Wildner
526717f4a47SSascha Wildner static void
draw_kmsmouse(scr_stat * scp,int x,int y)527717f4a47SSascha Wildner draw_kmsmouse(scr_stat *scp, int x, int y)
528717f4a47SSascha Wildner {
529717f4a47SSascha Wildner sc_softc_t *sc = scp->sc;
530717f4a47SSascha Wildner int line_width, pixel_size;
531219917caSSascha Wildner int blk_width, blk_height;
532717f4a47SSascha Wildner vm_offset_t draw_pos;
533717f4a47SSascha Wildner
5342b5f463dSImre Vadász if (sc->fbi->vaddr == 0)
5352b5f463dSImre Vadász return;
5362b5f463dSImre Vadász
537*a6dad826SImre Vadász line_width = sc->fbi->stride;
538*a6dad826SImre Vadász /* sc->fbi->depth may only be 24 or 32 */
539*a6dad826SImre Vadász pixel_size = sc->fbi->depth == 24 ? 3 : 4;
540*a6dad826SImre Vadász
541219917caSSascha Wildner if (x + scp->font_width < scp->font_width * scp->xsize)
542219917caSSascha Wildner blk_width = scp->blk_width;
543219917caSSascha Wildner else
544219917caSSascha Wildner blk_width = scp->font_width * scp->xsize - x;
545717f4a47SSascha Wildner
546219917caSSascha Wildner if (y + scp->font_height < scp->font_height * scp->ysize)
547219917caSSascha Wildner blk_height = scp->blk_height;
548219917caSSascha Wildner else
549219917caSSascha Wildner blk_height = scp->font_height * scp->ysize - y;
550717f4a47SSascha Wildner
551219917caSSascha Wildner draw_pos = sc->fbi->vaddr + y * scp->blk_height / scp->font_height *
552219917caSSascha Wildner line_width +
553219917caSSascha Wildner x * scp->blk_width / scp->font_width * pixel_size;
554*a6dad826SImre Vadász if (pixel_size == 3) {
555*a6dad826SImre Vadász blit_blk24(scp, (unsigned char *)mouse_and_mask, 16, 16,
556*a6dad826SImre Vadász draw_pos, blk_width, blk_height, line_width,
557*a6dad826SImre Vadász colormap[0], 0, BLIT_MASK);
558*a6dad826SImre Vadász blit_blk24(scp, (unsigned char *)mouse_or_mask, 16, 16,
559*a6dad826SImre Vadász draw_pos, blk_width, blk_height, line_width,
560*a6dad826SImre Vadász colormap[15], 0, BLIT_MASK);
561*a6dad826SImre Vadász } else {
562*a6dad826SImre Vadász blit_blk32(scp, (unsigned char *)mouse_and_mask, 16, 16,
563*a6dad826SImre Vadász draw_pos, blk_width, blk_height, line_width,
564*a6dad826SImre Vadász colormap[0], 0, BLIT_MASK);
565*a6dad826SImre Vadász blit_blk32(scp, (unsigned char *)mouse_or_mask, 16, 16,
566*a6dad826SImre Vadász draw_pos, blk_width, blk_height, line_width,
567*a6dad826SImre Vadász colormap[15], 0, BLIT_MASK);
568*a6dad826SImre Vadász }
569717f4a47SSascha Wildner }
570717f4a47SSascha Wildner
571717f4a47SSascha Wildner static void
remove_kmsmouse(scr_stat * scp,int x,int y)572717f4a47SSascha Wildner remove_kmsmouse(scr_stat *scp, int x, int y)
573717f4a47SSascha Wildner {
574717f4a47SSascha Wildner int col, row;
575717f4a47SSascha Wildner int pos;
576717f4a47SSascha Wildner int i;
577717f4a47SSascha Wildner
578717f4a47SSascha Wildner /* erase the mouse cursor image */
579219917caSSascha Wildner col = x / scp->font_width - scp->xoff;
580219917caSSascha Wildner row = y / scp->font_height - scp->yoff;
581717f4a47SSascha Wildner pos = row * scp->xsize + col;
582717f4a47SSascha Wildner i = (col < scp->xsize - 1) ? 2 : 1;
5837ae6dbf0SMatthew Dillon (*scp->rndr->draw)(scp, pos, i, FALSE);
584717f4a47SSascha Wildner if (row < scp->ysize - 1)
5857ae6dbf0SMatthew Dillon (*scp->rndr->draw)(scp, pos + scp->xsize, i, FALSE);
586717f4a47SSascha Wildner }
587717f4a47SSascha Wildner
588717f4a47SSascha Wildner static void
kms_mouse(scr_stat * scp,int x,int y,int on)589717f4a47SSascha Wildner kms_mouse(scr_stat *scp, int x, int y, int on)
590717f4a47SSascha Wildner {
591717f4a47SSascha Wildner if (on)
592717f4a47SSascha Wildner draw_kmsmouse(scp, x, y);
593717f4a47SSascha Wildner else
594717f4a47SSascha Wildner remove_kmsmouse(scp, x, y);
595717f4a47SSascha Wildner }
596717f4a47SSascha Wildner
597717f4a47SSascha Wildner #endif /* SC_NO_CUTPASTE */
598