7b22167842115b77f738197fbfc7c03523070fff
[dragonfly.git] / sys / dev / misc / syscons / scgfbrndr.c
1 /*-
2  * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
14  *
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.
25  *
26  * Copyright (c) 2000 Andrew Miklic
27  *
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.5 2006/02/19 09:16:26 swildner Exp $
30  */
31
32 #include "opt_syscons.h"
33 #include "opt_gfb.h"
34
35 #include <sys/param.h>
36 #include <sys/systm.h>
37 #include <sys/kernel.h>
38 #include <sys/fbio.h>
39 #include <sys/consio.h>
40
41 #include <machine/bus.h>
42
43 #include <dev/fb/fbreg.h>
44 #include "syscons.h"
45
46 static vr_clear_t               gfb_clear;
47 static vr_draw_border_t         gfb_border;
48 static vr_draw_t                gfb_draw;
49 static vr_set_cursor_t          gfb_cursor_shape;
50 static vr_draw_cursor_t         gfb_cursor;
51 static vr_blink_cursor_t        gfb_blink;
52 #ifndef SC_NO_CUTPASTE
53 static vr_draw_mouse_t          gfb_mouse;
54 #else
55 #define gfb_mouse               (vr_draw_mouse_t *)gfb_nop
56 #endif
57
58 static void                     gfb_nop(scr_stat *scp, ...);
59
60 sc_rndr_sw_t txtrndrsw = {
61         gfb_clear,
62         gfb_border,
63         gfb_draw,       
64         gfb_cursor_shape,
65         gfb_cursor,
66         gfb_blink,
67         (vr_set_mouse_t *)gfb_nop,
68         gfb_mouse,
69 };
70
71 #ifdef SC_PIXEL_MODE
72 sc_rndr_sw_t gfbrndrsw = {
73         gfb_clear,
74         gfb_border,
75         gfb_draw,
76         gfb_cursor_shape,
77         gfb_cursor,
78         gfb_blink,
79         (vr_set_mouse_t *)gfb_nop,
80         gfb_mouse,
81 };
82 #endif /* SC_PIXEL_MODE */
83
84 #ifndef SC_NO_MODE_CHANGE
85 sc_rndr_sw_t grrndrsw = {
86         (vr_clear_t *)gfb_nop,
87         gfb_border,
88         (vr_draw_t *)gfb_nop,
89         (vr_set_cursor_t *)gfb_nop,
90         (vr_draw_cursor_t *)gfb_nop,
91         (vr_blink_cursor_t *)gfb_nop,
92         (vr_set_mouse_t *)gfb_nop,
93         (vr_draw_mouse_t *)gfb_nop,
94 };
95 #endif /* SC_NO_MODE_CHANGE */
96
97 #ifndef SC_NO_CUTPASTE
98
99 static u_char mouse_pointer[16] = {
100         0x00, 0x40, 0x60, 0x70, 0x78, 0x7c, 0x7e, 0x68,
101         0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00
102 };
103 #endif
104
105 static void
106 gfb_nop(scr_stat *scp, ...)
107 {
108 }
109
110 /* text mode renderer */
111
112 static void
113 gfb_clear(scr_stat *scp, int c, int attr)
114 {
115         (*vidsw[scp->sc->adapter]->clear)(scp->sc->adp);
116 }
117
118 static void
119 gfb_border(scr_stat *scp, int color)
120 {
121         (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
122 }
123
124 static void
125 gfb_draw(scr_stat *scp, int from, int count, int flip)
126 {
127         char c;
128         char a;
129         int i, n;
130         video_adapter_t *adp;
131
132         adp = scp->sc->adp;
133
134         /*
135            Determine if we need to scroll based on the offset
136            and the number of characters to be displayed...
137          */
138         if (from + count > scp->xsize*scp->ysize) {
139
140                 /*
141                    Calculate the number of characters past the end of the
142                    visible screen...
143                 */
144                 count = (from + count) -
145                     (adp->va_info.vi_width * adp->va_info.vi_height);
146
147                 /*
148                    Calculate the number of rows past the end of the visible
149                    screen...
150                 */
151                 n = (count / adp->va_info.vi_width) + 1;
152
153                 /* Scroll to make room for new text rows... */
154                 (*vidsw[scp->sc->adapter]->copy)(adp, n, 0, n);
155 #ifdef 0
156                 (*vidsw[scp->sc->adapter]->clear)(adp, n);
157 #endif
158
159                 /* Display new text rows... */
160                 (*vidsw[scp->sc->adapter]->puts)(adp, from,
161                     scp->vtb.vtb_buffer + from, count);
162         }
163
164         /*
165            We don't need to scroll, so we can just put the characters
166            all-at-once...
167         */
168         else {
169
170                 /*
171                    Determine the method by which we are to display characters
172                    (are we going to print forwards or backwards?
173                    do we need to do a character-by-character copy, then?)...
174                 */
175                 if (flip)
176                         for (i = count; i-- > 0; ++from) {
177                                 c = sc_vtb_getc(&scp->vtb, from);
178                                 a = sc_vtb_geta(&scp->vtb, from) >> 8;
179                                 (*vidsw[scp->sc->adapter]->putc)(adp, from, c,
180                                     a);
181                         }
182                 else {
183                         (*vidsw[scp->sc->adapter]->puts)(adp, from,
184                             scp->vtb.vtb_buffer + from, count);
185                 }
186         }
187 }
188
189 static void 
190 gfb_cursor_shape(scr_stat *scp, int base, int height, int blink)
191 {
192         if (base < 0 || base >= scp->font_size)
193                 return;
194         /* the caller may set height <= 0 in order to disable the cursor */
195 #if 0
196         scp->cursor_base = base;
197         scp->cursor_height = height;
198 #endif
199         (*vidsw[scp->sc->adapter]->set_hw_cursor_shape)(scp->sc->adp,
200             base, height, scp->font_size, blink);
201 }
202
203 static int pxlblinkrate = 0;
204
205 #ifdef 0
206 static void
207 gfb_cursor(scr_stat *scp, int at, int blink, int on, int flip)
208 {
209         video_adapter_t *adp;
210
211         if (scp->cursor_height <= 0)    /* the text cursor is disabled */
212                 return;
213
214         adp = scp->sc->adp;
215         if(blink) {
216                 scp->status |= VR_CURSOR_BLINK;
217                 if (on) {
218                         scp->status |= VR_CURSOR_ON;
219                         (*vidsw[adp->va_index]->set_hw_cursor)(adp,
220                             at%scp->xsize,
221                             at/scp->xsize);
222                 } else {
223                         if (scp->status & VR_CURSOR_ON)
224                                 (*vidsw[adp->va_index]->set_hw_cursor)(adp, -1,
225                                     -1);
226                         scp->status &= ~VR_CURSOR_ON;
227                 }
228         } else {
229                 scp->status &= ~VR_CURSOR_BLINK;
230                 if(on) {
231                         scp->status |= VR_CURSOR_ON;
232                         scp->cursor_saveunder_char = sc_vtb_getc(&scp->scr, at);
233                         scp->cursor_saveunder_attr = sc_vtb_geta(&scp->scr, at);
234                         (*vidsw[scp->sc->adapter]->putc)(scp->sc->adp, at,
235                             scp->cursor_saveunder_char,
236                             scp->cursor_saveunder_attr);
237                 } else {
238                         if (scp->status & VR_CURSOR_ON)
239                                 (*vidsw[scp->sc->adapter]->putc)(scp->sc->adp,
240                                     at, scp->cursor_saveunder_char,
241                                     scp->cursor_saveunder_attr);
242                         scp->status &= ~VR_CURSOR_ON;
243                 }
244         }
245 }
246 #endif
247
248 static void 
249 gfb_cursor(scr_stat *scp, int at, int blink, int on, int flip)
250 {
251         video_adapter_t *adp;
252
253         adp = scp->sc->adp;
254         if (scp->cursor_height <= 0)    /* the text cursor is disabled */
255                 return;
256
257         if (on) {
258                 if (!blink) {
259                         scp->status |= VR_CURSOR_ON;
260                         (*vidsw[adp->va_index]->set_hw_cursor)(adp,
261                             at%scp->xsize, at/scp->xsize);
262                 } else if (++pxlblinkrate & 4) {
263                         pxlblinkrate = 0;
264                         scp->status ^= VR_CURSOR_ON;
265                         if(scp->status & VR_CURSOR_ON)
266                                 (*vidsw[adp->va_index]->set_hw_cursor)(adp,
267                                     at%scp->xsize, at/scp->xsize);
268                         else
269                                 (*vidsw[adp->va_index]->set_hw_cursor)(adp, -1,
270                                     -1);
271                 }
272         } else {
273                 if (scp->status & VR_CURSOR_ON)
274                         (*vidsw[adp->va_index]->set_hw_cursor)(adp,
275                             at%scp->xsize, at/scp->xsize);
276                 scp->status &= ~VR_CURSOR_ON;
277         }
278         if (blink)
279                 scp->status |= VR_CURSOR_BLINK;
280         else
281                 scp->status &= ~VR_CURSOR_BLINK;
282 }
283
284 static void
285 gfb_blink(scr_stat *scp, int at, int flip)
286 {
287         if (!(scp->status & VR_CURSOR_BLINK))
288                 return;
289         if (!(++pxlblinkrate & 4))
290                 return;
291         pxlblinkrate = 0;
292         scp->status ^= VR_CURSOR_ON;
293         gfb_cursor(scp, at, scp->status & VR_CURSOR_BLINK,
294             scp->status & VR_CURSOR_ON, flip);
295 }
296
297 #ifndef SC_NO_CUTPASTE
298
299 static void 
300 gfb_mouse(scr_stat *scp, int x, int y, int on)
301 {
302         int i, pos;
303
304         if (on) {
305
306                 /* Display the mouse pointer image... */
307                 (*vidsw[scp->sc->adapter]->putm)(scp->sc->adp, x, y,
308                     mouse_pointer, 0xffffffff, 16);
309         } else {
310
311                 /*
312                    Erase the mouse cursor image by redrawing the text
313                    underneath it...
314                 */
315                 return;
316                 pos = x*scp->xsize + y;
317                 i = (y < scp->xsize - 1) ? 2 : 1;
318                 (*scp->rndr->draw)(scp, pos, i, FALSE);
319                 if (x < scp->ysize - 1)
320                         (*scp->rndr->draw)(scp, pos + scp->xsize, i, FALSE);
321         }
322 }
323
324 #endif /* SC_NO_CUTPASTE */