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