]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/syscons/scgfbrndr.c
Merge libc++ trunk r338150 (just before the 7.0.0 branch point), and
[FreeBSD/FreeBSD.git] / sys / dev / syscons / scgfbrndr.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer as
12  *    the first lines of this file unmodified.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  * Copyright (c) 2000 Andrew Miklic
29  */
30
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33
34 #include "opt_syscons.h"
35 #include "opt_gfb.h"
36 #ifdef __powerpc__
37 #include "opt_ofwfb.h"
38 #endif
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/kernel.h>
43 #include <sys/fbio.h>
44 #include <sys/consio.h>
45
46 #include <machine/bus.h>
47
48 #include <dev/fb/fbreg.h>
49 #include <dev/syscons/syscons.h>
50
51 #ifndef SC_RENDER_DEBUG
52 #define SC_RENDER_DEBUG         0
53 #endif
54
55 static vr_clear_t               gfb_clear;
56 static vr_draw_border_t         gfb_border;
57 static vr_draw_t                gfb_draw;
58 static vr_set_cursor_t          gfb_cursor_shape;
59 static vr_draw_cursor_t         gfb_cursor;
60 static vr_blink_cursor_t        gfb_blink;
61 #ifndef SC_NO_CUTPASTE
62 static vr_draw_mouse_t          gfb_mouse;
63 #else
64 #define gfb_mouse               (vr_draw_mouse_t *)gfb_nop
65 #endif
66
67 static void                     gfb_nop(scr_stat *scp);
68
69 sc_rndr_sw_t txtrndrsw = {
70         (vr_init_t *)gfb_nop,
71         gfb_clear,
72         gfb_border,
73         gfb_draw,       
74         gfb_cursor_shape,
75         gfb_cursor,
76         gfb_blink,
77         (vr_set_mouse_t *)gfb_nop,
78         gfb_mouse,
79 };
80
81 #ifdef SC_PIXEL_MODE
82 sc_rndr_sw_t gfbrndrsw = {
83         (vr_init_t *)gfb_nop,
84         gfb_clear,
85         gfb_border,
86         gfb_draw,
87         gfb_cursor_shape,
88         gfb_cursor,
89         gfb_blink,
90         (vr_set_mouse_t *)gfb_nop,
91         gfb_mouse,
92 };
93 #endif /* SC_PIXEL_MODE */
94
95 #ifndef SC_NO_MODE_CHANGE
96 sc_rndr_sw_t grrndrsw = {
97         (vr_init_t *)gfb_nop,
98         (vr_clear_t *)gfb_nop,
99         gfb_border,
100         (vr_draw_t *)gfb_nop,
101         (vr_set_cursor_t *)gfb_nop,
102         (vr_draw_cursor_t *)gfb_nop,
103         (vr_blink_cursor_t *)gfb_nop,
104         (vr_set_mouse_t *)gfb_nop,
105         (vr_draw_mouse_t *)gfb_nop,
106 };
107 #endif /* SC_NO_MODE_CHANGE */
108
109 #ifndef SC_NO_CUTPASTE
110 #ifdef __sparc64__
111 static u_char mouse_pointer[22 * 2] = {
112         0x00, 0x00,     /* ............ */
113         0x80, 0x00,     /* *........... */
114         0xc0, 0x00,     /* **.......... */
115         0xe0, 0x00,     /* ***......... */
116         0xf0, 0x00,     /* ****........ */
117         0xf8, 0x00,     /* *****....... */
118         0xfc, 0x00,     /* ******...... */
119         0xfe, 0x00,     /* *******..... */
120         0xff, 0x00,     /* ********.... */
121         0xff, 0x80,     /* *********... */
122         0xfc, 0xc0,     /* ******..**.. */
123         0xdc, 0x00,     /* **.***...... */
124         0x8e, 0x00,     /* *...***..... */
125         0x0e, 0x00,     /* ....***..... */
126         0x07, 0x00,     /* .....***.... */
127         0x04, 0x00,     /* .....*...... */
128         0x00, 0x00,     /* ............ */
129         0x00, 0x00,     /* ............ */
130         0x00, 0x00,     /* ............ */
131         0x00, 0x00,     /* ............ */
132         0x00, 0x00,     /* ............ */
133         0x00, 0x00      /* ............ */
134 };
135 #else
136 static u_char mouse_pointer[16] = {
137         0x00, 0x40, 0x60, 0x70, 0x78, 0x7c, 0x7e, 0x68,
138         0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00
139 };
140 #endif
141 #endif
142
143 static void
144 gfb_nop(scr_stat *scp)
145 {
146 }
147
148 /* text mode renderer */
149
150 static void
151 gfb_clear(scr_stat *scp, int c, int attr)
152 {
153         vidd_clear(scp->sc->adp);
154 }
155
156 static void
157 gfb_border(scr_stat *scp, int color)
158 {
159         vidd_set_border(scp->sc->adp, color);
160 }
161
162 static void
163 gfb_draw(scr_stat *scp, int from, int count, int flip)
164 {
165         int c;
166         int a;
167         int i, n;
168         video_adapter_t *adp;
169
170         adp = scp->sc->adp;
171
172         /*
173            Determine if we need to scroll based on the offset
174            and the number of characters to be displayed...
175          */
176         if (from + count > scp->xsize*scp->ysize) {
177
178                 /*
179                    Calculate the number of characters past the end of the
180                    visible screen...
181                 */
182                 count = (from + count) -
183                     (adp->va_info.vi_width * adp->va_info.vi_height);
184
185                 /*
186                    Calculate the number of rows past the end of the visible
187                    screen...
188                 */
189                 n = (count / adp->va_info.vi_width) + 1;
190
191                 /* Scroll to make room for new text rows... */
192                 vidd_copy(adp, n, 0, n);
193 #if 0
194                 vidd_clear(adp, n);
195 #endif
196
197                 /* Display new text rows... */
198                 vidd_puts(adp, from,
199                     (u_int16_t *)sc_vtb_pointer(&scp->vtb, from), count);
200         }
201
202         /*
203            We don't need to scroll, so we can just put the characters
204            all-at-once...
205         */
206         else {
207
208                 /*
209                    Determine the method by which we are to display characters
210                    (are we going to print forwards or backwards?
211                    do we need to do a character-by-character copy, then?)...
212                 */
213                 if (flip)
214                         for (i = count; i-- > 0; ++from) {
215                                 c = sc_vtb_getc(&scp->vtb, from);
216                                 a = sc_vtb_geta(&scp->vtb, from) >> 8;
217                                 vidd_putc(adp, from, c,
218                                     (a >> 4) | ((a & 0xf) << 4));
219                         }
220                 else {
221                         vidd_puts(adp, from,
222                             (u_int16_t *)sc_vtb_pointer(&scp->vtb, from),
223                             count);
224                 }
225         }
226 }
227
228 static void 
229 gfb_cursor_shape(scr_stat *scp, int base, int height, int blink)
230 {
231         if (base < 0 || base >= scp->font_size)
232                 return;
233         /* the caller may set height <= 0 in order to disable the cursor */
234 #if 0
235         scp->cursor_base = base;
236         scp->cursor_height = height;
237 #endif
238         vidd_set_hw_cursor_shape(scp->sc->adp, base, height, scp->font_size,
239             blink);
240 }
241
242 static int pxlblinkrate = 0;
243
244 #if defined(__sparc64__) || defined(SC_OFWFB)
245 static void
246 gfb_cursor(scr_stat *scp, int at, int blink, int on, int flip)
247 {
248         video_adapter_t *adp;
249         int a, c;
250
251         if (scp->curs_attr.height <= 0) /* the text cursor is disabled */
252                 return;
253
254         adp = scp->sc->adp;
255         if(blink) {
256                 scp->status |= VR_CURSOR_BLINK;
257                 if (on) {
258                         scp->status |= VR_CURSOR_ON;
259                         vidd_set_hw_cursor(adp, at%scp->xsize, at/scp->xsize);
260                 } else {
261                         if (scp->status & VR_CURSOR_ON)
262                                 vidd_set_hw_cursor(adp, -1, -1);
263                         scp->status &= ~VR_CURSOR_ON;
264                 }
265         } else {
266                 scp->status &= ~VR_CURSOR_BLINK;
267                 if(on) {
268                         scp->status |= VR_CURSOR_ON;
269                         vidd_putc(scp->sc->adp, scp->cursor_oldpos,
270                             sc_vtb_getc(&scp->vtb, scp->cursor_oldpos),
271                             sc_vtb_geta(&scp->vtb, scp->cursor_oldpos) >> 8);
272                         a = sc_vtb_geta(&scp->vtb, at) >> 8;
273                         c = sc_vtb_getc(&scp->vtb, at);
274                         vidd_putc(scp->sc->adp, at, c,
275                             (a >> 4) | ((a & 0xf) << 4));
276                 } else {
277                         if (scp->status & VR_CURSOR_ON)
278                                 vidd_putc(scp->sc->adp, at,
279                                     sc_vtb_getc(&scp->vtb, at),
280                                     sc_vtb_geta(&scp->vtb, at) >> 8);
281                         scp->status &= ~VR_CURSOR_ON;
282                 }
283         }
284 }
285 #else
286 static void 
287 gfb_cursor(scr_stat *scp, int at, int blink, int on, int flip)
288 {
289         video_adapter_t *adp;
290
291         adp = scp->sc->adp;
292         if (scp->curs_attr.height <= 0) 
293                 /* the text cursor is disabled */
294                 return;
295
296         if (on) {
297                 if (!blink) {
298                         scp->status |= VR_CURSOR_ON;
299                         vidd_set_hw_cursor(adp, at%scp->xsize, at/scp->xsize);
300                 } else if (++pxlblinkrate & 4) {
301                         pxlblinkrate = 0;
302                         scp->status ^= VR_CURSOR_ON;
303                         if(scp->status & VR_CURSOR_ON)
304                                 vidd_set_hw_cursor(adp, at%scp->xsize,
305                                     at/scp->xsize);
306                         else
307                                 vidd_set_hw_cursor(adp, -1, -1);
308                 }
309         } else {
310                 if (scp->status & VR_CURSOR_ON)
311                         vidd_set_hw_cursor(adp, at%scp->xsize, at/scp->xsize);
312                 scp->status &= ~VR_CURSOR_ON;
313         }
314         if (blink)
315                 scp->status |= VR_CURSOR_BLINK;
316         else
317                 scp->status &= ~VR_CURSOR_BLINK;
318 }
319 #endif
320
321 static void
322 gfb_blink(scr_stat *scp, int at, int flip)
323 {
324         if (!(scp->status & VR_CURSOR_BLINK))
325                 return;
326         if (!(++pxlblinkrate & 4))
327                 return;
328         pxlblinkrate = 0;
329         scp->status ^= VR_CURSOR_ON;
330         gfb_cursor(scp, at, scp->status & VR_CURSOR_BLINK,
331             scp->status & VR_CURSOR_ON, flip);
332 }
333
334 #ifndef SC_NO_CUTPASTE
335
336 static void 
337 gfb_mouse(scr_stat *scp, int x, int y, int on)
338 {
339 #ifdef __sparc64__
340         vidd_putm(scp->sc->adp, x, y, mouse_pointer,
341             on ? 0xffffffff : 0x0, 22, 12);
342 #else
343         if (on) {
344                 vidd_putm(scp->sc->adp, x, y, mouse_pointer,
345                     0xffffffff, 16, 8);
346         } else {
347                 /* XXX: removal is incomplete for h/w cursors and borders. */
348         }
349 #endif
350 }
351
352 #endif /* SC_NO_CUTPASTE */