xref: /dflybsd-src/sys/dev/misc/syscons/sckmsrndr.c (revision fcf6efefc03a35111797b109fa4994034ebe39ba)
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