kernel tree reorganization stage 1: Major cvs repository work (not logged as
[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.3 2003/08/07 21:16:59 dillon 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 #ifndef SC_RENDER_DEBUG
47 #define SC_RENDER_DEBUG         0
48 #endif
49
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;
58 #else
59 #define gfb_mouse               (vr_draw_mouse_t *)gfb_nop
60 #endif
61
62 static void                     gfb_nop(scr_stat *scp, ...);
63
64 sc_rndr_sw_t txtrndrsw = {
65         gfb_clear,
66         gfb_border,
67         gfb_draw,       
68         gfb_cursor_shape,
69         gfb_cursor,
70         gfb_blink,
71         (vr_set_mouse_t *)gfb_nop,
72         gfb_mouse,
73 };
74
75 #ifdef SC_PIXEL_MODE
76 sc_rndr_sw_t gfbrndrsw = {
77         gfb_clear,
78         gfb_border,
79         gfb_draw,
80         gfb_cursor_shape,
81         gfb_cursor,
82         gfb_blink,
83         (vr_set_mouse_t *)gfb_nop,
84         gfb_mouse,
85 };
86 #endif /* SC_PIXEL_MODE */
87
88 #ifndef SC_NO_MODE_CHANGE
89 sc_rndr_sw_t grrndrsw = {
90         (vr_clear_t *)gfb_nop,
91         gfb_border,
92         (vr_draw_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,
98 };
99 #endif /* SC_NO_MODE_CHANGE */
100
101 #ifndef SC_NO_CUTPASTE
102
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
106 };
107 #endif
108
109 static void
110 gfb_nop(scr_stat *scp, ...)
111 {
112 }
113
114 /* text mode renderer */
115
116 static void
117 gfb_clear(scr_stat *scp, int c, int attr)
118 {
119         (*vidsw[scp->sc->adapter]->clear)(scp->sc->adp);
120 }
121
122 static void
123 gfb_border(scr_stat *scp, int color)
124 {
125         (*vidsw[scp->sc->adapter]->set_border)(scp->sc->adp, color);
126 }
127
128 static void
129 gfb_draw(scr_stat *scp, int from, int count, int flip)
130 {
131         char c;
132         char a;
133         int i, n;
134         video_adapter_t *adp;
135
136         adp = scp->sc->adp;
137
138         /*
139            Determine if we need to scroll based on the offset
140            and the number of characters to be displayed...
141          */
142         if (from + count > scp->xsize*scp->ysize) {
143
144                 /*
145                    Calculate the number of characters past the end of the
146                    visible screen...
147                 */
148                 count = (from + count) -
149                     (adp->va_info.vi_width * adp->va_info.vi_height);
150
151                 /*
152                    Calculate the number of rows past the end of the visible
153                    screen...
154                 */
155                 n = (count / adp->va_info.vi_width) + 1;
156
157                 /* Scroll to make room for new text rows... */
158                 (*vidsw[scp->sc->adapter]->copy)(adp, n, 0, n);
159 #ifdef 0
160                 (*vidsw[scp->sc->adapter]->clear)(adp, n);
161 #endif
162
163                 /* Display new text rows... */
164                 (*vidsw[scp->sc->adapter]->puts)(adp, from,
165                     (u_int16_t *)sc_vtb_pointer(&scp->vtb, from), count);
166         }
167
168         /*
169            We don't need to scroll, so we can just put the characters
170            all-at-once...
171         */
172         else {
173
174                 /*
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?)...
178                 */
179                 if (flip)
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,
184                                     a);
185                         }
186                 else {
187                         (*vidsw[scp->sc->adapter]->puts)(adp, from,
188                             (u_int16_t *)sc_vtb_pointer(&scp->vtb, from),
189                             count);
190                 }
191         }
192 }
193
194 static void 
195 gfb_cursor_shape(scr_stat *scp, int base, int height, int blink)
196 {
197         if (base < 0 || base >= scp->font_size)
198                 return;
199         /* the caller may set height <= 0 in order to disable the cursor */
200 #if 0
201         scp->cursor_base = base;
202         scp->cursor_height = height;
203 #endif
204         (*vidsw[scp->sc->adapter]->set_hw_cursor_shape)(scp->sc->adp,
205             base, height, scp->font_size, blink);
206 }
207
208 static int pxlblinkrate = 0;
209
210 #ifdef 0
211 static void
212 gfb_cursor(scr_stat *scp, int at, int blink, int on, int flip)
213 {
214         video_adapter_t *adp;
215
216         if (scp->cursor_height <= 0)    /* the text cursor is disabled */
217                 return;
218
219         adp = scp->sc->adp;
220         if(blink) {
221                 scp->status |= VR_CURSOR_BLINK;
222                 if (on) {
223                         scp->status |= VR_CURSOR_ON;
224                         (*vidsw[adp->va_index]->set_hw_cursor)(adp,
225                             at%scp->xsize,
226                             at/scp->xsize);
227                 } else {
228                         if (scp->status & VR_CURSOR_ON)
229                                 (*vidsw[adp->va_index]->set_hw_cursor)(adp, -1,
230                                     -1);
231                         scp->status &= ~VR_CURSOR_ON;
232                 }
233         } else {
234                 scp->status &= ~VR_CURSOR_BLINK;
235                 if(on) {
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);
242                 } else {
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;
248                 }
249         }
250 }
251 #endif
252
253 static void 
254 gfb_cursor(scr_stat *scp, int at, int blink, int on, int flip)
255 {
256         video_adapter_t *adp;
257
258         adp = scp->sc->adp;
259         if (scp->cursor_height <= 0)    /* the text cursor is disabled */
260                 return;
261
262         if (on) {
263                 if (!blink) {
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) {
268                         pxlblinkrate = 0;
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);
273                         else
274                                 (*vidsw[adp->va_index]->set_hw_cursor)(adp, -1,
275                                     -1);
276                 }
277         } else {
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;
282         }
283         if (blink)
284                 scp->status |= VR_CURSOR_BLINK;
285         else
286                 scp->status &= ~VR_CURSOR_BLINK;
287 }
288
289 static void
290 gfb_blink(scr_stat *scp, int at, int flip)
291 {
292         if (!(scp->status & VR_CURSOR_BLINK))
293                 return;
294         if (!(++pxlblinkrate & 4))
295                 return;
296         pxlblinkrate = 0;
297         scp->status ^= VR_CURSOR_ON;
298         gfb_cursor(scp, at, scp->status & VR_CURSOR_BLINK,
299             scp->status & VR_CURSOR_ON, flip);
300 }
301
302 #ifndef SC_NO_CUTPASTE
303
304 static void 
305 gfb_mouse(scr_stat *scp, int x, int y, int on)
306 {
307         int i, pos;
308
309         if (on) {
310
311                 /* Display the mouse pointer image... */
312                 (*vidsw[scp->sc->adapter]->putm)(scp->sc->adp, x, y,
313                     mouse_pointer, 0xffffffff, 16);
314         } else {
315
316                 /*
317                    Erase the mouse cursor image by redrawing the text
318                    underneath it...
319                 */
320                 return;
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);
326         }
327 }
328
329 #endif /* SC_NO_CUTPASTE */