2 * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer as
10 * the first lines of this file unmodified.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 * Copyright (c) 2000 Andrew Miklic
28 * $FreeBSD: src/sys/dev/syscons/scgfbrndr.c,v 1.14.2.1 2001/11/01 08:33:15 obrien Exp $
29 * $DragonFly: src/sys/dev/misc/syscons/scgfbrndr.c,v 1.2 2003/06/17 04:28:31 dillon Exp $
32 #include "opt_syscons.h"
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
39 #include <sys/consio.h>
41 #include <machine/bus.h>
43 #include <dev/fb/fbreg.h>
44 #include <dev/syscons/syscons.h>
46 #ifndef SC_RENDER_DEBUG
47 #define SC_RENDER_DEBUG 0
50 static vr_clear_t gfb_clear;
51 static vr_draw_border_t gfb_border;
52 static vr_draw_t gfb_draw;
53 static vr_set_cursor_t gfb_cursor_shape;
54 static vr_draw_cursor_t gfb_cursor;
55 static vr_blink_cursor_t gfb_blink;
56 #ifndef SC_NO_CUTPASTE
57 static vr_draw_mouse_t gfb_mouse;
59 #define gfb_mouse (vr_draw_mouse_t *)gfb_nop
62 static void gfb_nop(scr_stat *scp, ...);
64 sc_rndr_sw_t txtrndrsw = {
71 (vr_set_mouse_t *)gfb_nop,
76 sc_rndr_sw_t gfbrndrsw = {
83 (vr_set_mouse_t *)gfb_nop,
86 #endif /* SC_PIXEL_MODE */
88 #ifndef SC_NO_MODE_CHANGE
89 sc_rndr_sw_t grrndrsw = {
90 (vr_clear_t *)gfb_nop,
93 (vr_set_cursor_t *)gfb_nop,
94 (vr_draw_cursor_t *)gfb_nop,
95 (vr_blink_cursor_t *)gfb_nop,
96 (vr_set_mouse_t *)gfb_nop,
97 (vr_draw_mouse_t *)gfb_nop,
99 #endif /* SC_NO_MODE_CHANGE */
101 #ifndef SC_NO_CUTPASTE
103 static u_char mouse_pointer[16] = {
104 0x00, 0x40, 0x60, 0x70, 0x78, 0x7c, 0x7e, 0x68,
105 0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00
110 gfb_nop(scr_stat *scp, ...)
114 /* text mode renderer */
117 gfb_clear(scr_stat *scp, int c, int attr)
119 (*vidsw[scp->sc->adapter]->clear)(scp->sc->adp);
123 gfb_border(scr_stat *scp, int color)
125 (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
129 gfb_draw(scr_stat *scp, int from, int count, int flip)
134 video_adapter_t *adp;
139 Determine if we need to scroll based on the offset
140 and the number of characters to be displayed...
142 if (from + count > scp->xsize*scp->ysize) {
145 Calculate the number of characters past the end of the
148 count = (from + count) -
149 (adp->va_info.vi_width * adp->va_info.vi_height);
152 Calculate the number of rows past the end of the visible
155 n = (count / adp->va_info.vi_width) + 1;
157 /* Scroll to make room for new text rows... */
158 (*vidsw[scp->sc->adapter]->copy)(adp, n, 0, n);
160 (*vidsw[scp->sc->adapter]->clear)(adp, n);
163 /* Display new text rows... */
164 (*vidsw[scp->sc->adapter]->puts)(adp, from,
165 (u_int16_t *)sc_vtb_pointer(&scp->vtb, from), count);
169 We don't need to scroll, so we can just put the characters
175 Determine the method by which we are to display characters
176 (are we going to print forwards or backwards?
177 do we need to do a character-by-character copy, then?)...
180 for (i = count; i-- > 0; ++from) {
181 c = sc_vtb_getc(&scp->vtb, from);
182 a = sc_vtb_geta(&scp->vtb, from) >> 8;
183 (*vidsw[scp->sc->adapter]->putc)(adp, from, c,
187 (*vidsw[scp->sc->adapter]->puts)(adp, from,
188 (u_int16_t *)sc_vtb_pointer(&scp->vtb, from),
195 gfb_cursor_shape(scr_stat *scp, int base, int height, int blink)
197 if (base < 0 || base >= scp->font_size)
199 /* the caller may set height <= 0 in order to disable the cursor */
201 scp->cursor_base = base;
202 scp->cursor_height = height;
204 (*vidsw[scp->sc->adapter]->set_hw_cursor_shape)(scp->sc->adp,
205 base, height, scp->font_size, blink);
208 static int pxlblinkrate = 0;
212 gfb_cursor(scr_stat *scp, int at, int blink, int on, int flip)
214 video_adapter_t *adp;
216 if (scp->cursor_height <= 0) /* the text cursor is disabled */
221 scp->status |= VR_CURSOR_BLINK;
223 scp->status |= VR_CURSOR_ON;
224 (*vidsw[adp->va_index]->set_hw_cursor)(adp,
228 if (scp->status & VR_CURSOR_ON)
229 (*vidsw[adp->va_index]->set_hw_cursor)(adp, -1,
231 scp->status &= ~VR_CURSOR_ON;
234 scp->status &= ~VR_CURSOR_BLINK;
236 scp->status |= VR_CURSOR_ON;
237 scp->cursor_saveunder_char = sc_vtb_getc(&scp->scr, at);
238 scp->cursor_saveunder_attr = sc_vtb_geta(&scp->scr, at);
239 (*vidsw[scp->sc->adapter]->putc)(scp->sc->adp, at,
240 scp->cursor_saveunder_char,
241 scp->cursor_saveunder_attr);
243 if (scp->status & VR_CURSOR_ON)
244 (*vidsw[scp->sc->adapter]->putc)(scp->sc->adp,
245 at, scp->cursor_saveunder_char,
246 scp->cursor_saveunder_attr);
247 scp->status &= ~VR_CURSOR_ON;
254 gfb_cursor(scr_stat *scp, int at, int blink, int on, int flip)
256 video_adapter_t *adp;
259 if (scp->cursor_height <= 0) /* the text cursor is disabled */
264 scp->status |= VR_CURSOR_ON;
265 (*vidsw[adp->va_index]->set_hw_cursor)(adp,
266 at%scp->xsize, at/scp->xsize);
267 } else if (++pxlblinkrate & 4) {
269 scp->status ^= VR_CURSOR_ON;
270 if(scp->status & VR_CURSOR_ON)
271 (*vidsw[adp->va_index]->set_hw_cursor)(adp,
272 at%scp->xsize, at/scp->xsize);
274 (*vidsw[adp->va_index]->set_hw_cursor)(adp, -1,
278 if (scp->status & VR_CURSOR_ON)
279 (*vidsw[adp->va_index]->set_hw_cursor)(adp,
280 at%scp->xsize, at/scp->xsize);
281 scp->status &= ~VR_CURSOR_ON;
284 scp->status |= VR_CURSOR_BLINK;
286 scp->status &= ~VR_CURSOR_BLINK;
290 gfb_blink(scr_stat *scp, int at, int flip)
292 if (!(scp->status & VR_CURSOR_BLINK))
294 if (!(++pxlblinkrate & 4))
297 scp->status ^= VR_CURSOR_ON;
298 gfb_cursor(scp, at, scp->status & VR_CURSOR_BLINK,
299 scp->status & VR_CURSOR_ON, flip);
302 #ifndef SC_NO_CUTPASTE
305 gfb_mouse(scr_stat *scp, int x, int y, int on)
311 /* Display the mouse pointer image... */
312 (*vidsw[scp->sc->adapter]->putm)(scp->sc->adp, x, y,
313 mouse_pointer, 0xffffffff, 16);
317 Erase the mouse cursor image by redrawing the text
321 pos = x*scp->xsize + y;
322 i = (y < scp->xsize - 1) ? 2 : 1;
323 (*scp->rndr->draw)(scp, pos, i, FALSE);
324 if (x < scp->ysize - 1)
325 (*scp->rndr->draw)(scp, pos + scp->xsize, i, FALSE);
329 #endif /* SC_NO_CUTPASTE */