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