scgfbrndr.c revision 174985
1117395Skan/*- 2169689Skan * Copyright (c) 1999 Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp> 3117395Skan * All rights reserved. 4117395Skan * 5117395Skan * Redistribution and use in source and binary forms, with or without 6117395Skan * modification, are permitted provided that the following conditions 7117395Skan * are met: 8117395Skan * 1. Redistributions of source code must retain the above copyright 9117395Skan * notice, this list of conditions and the following disclaimer as 10117395Skan * the first lines of this file unmodified. 11117395Skan * 2. Redistributions in binary form must reproduce the above copyright 12117395Skan * notice, this list of conditions and the following disclaimer in the 13117395Skan * documentation and/or other materials provided with the distribution. 14117395Skan * 15117395Skan * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR 16117395Skan * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17117395Skan * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18117395Skan * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT, INDIRECT, 19117395Skan * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20117395Skan * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21117395Skan * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22117395Skan * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23117395Skan * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24117395Skan * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25117395Skan * 26117395Skan * Copyright (c) 2000 Andrew Miklic 27169689Skan */ 28169689Skan 29117395Skan#include <sys/cdefs.h> 30117395Skan__FBSDID("$FreeBSD: head/sys/dev/syscons/scgfbrndr.c 174985 2007-12-29 23:26:59Z wkoszek $"); 31117395Skan 32117395Skan#include "opt_syscons.h" 33117395Skan#include "opt_gfb.h" 34117395Skan#ifdef __powerpc__ 35117395Skan#include "opt_ofwfb.h" 36117395Skan#endif 37169689Skan 38169689Skan#include <sys/param.h> 39169689Skan#include <sys/systm.h> 40169689Skan#include <sys/kernel.h> 41169689Skan#include <sys/fbio.h> 42117395Skan#include <sys/consio.h> 43117395Skan 44117395Skan#include <machine/bus.h> 45117395Skan 46117395Skan#include <dev/fb/fbreg.h> 47117395Skan#include <dev/syscons/syscons.h> 48117395Skan 49117395Skan#ifndef SC_RENDER_DEBUG 50117395Skan#define SC_RENDER_DEBUG 0 51117395Skan#endif 52117395Skan 53117395Skanstatic vr_clear_t gfb_clear; 54117395Skanstatic vr_draw_border_t gfb_border; 55117395Skanstatic vr_draw_t gfb_draw; 56117395Skanstatic vr_set_cursor_t gfb_cursor_shape; 57117395Skanstatic vr_draw_cursor_t gfb_cursor; 58117395Skanstatic vr_blink_cursor_t gfb_blink; 59117395Skan#ifndef SC_NO_CUTPASTE 60117395Skanstatic vr_draw_mouse_t gfb_mouse; 61117395Skan#else 62117395Skan#define gfb_mouse (vr_draw_mouse_t *)gfb_nop 63117395Skan#endif 64117395Skan 65117395Skanstatic void gfb_nop(scr_stat *scp); 66117395Skan 67117395Skansc_rndr_sw_t txtrndrsw = { 68117395Skan (vr_init_t *)gfb_nop, 69117395Skan gfb_clear, 70117395Skan gfb_border, 71117395Skan gfb_draw, 72117395Skan gfb_cursor_shape, 73117395Skan gfb_cursor, 74117395Skan gfb_blink, 75117395Skan (vr_set_mouse_t *)gfb_nop, 76117395Skan gfb_mouse, 77117395Skan}; 78117395Skan 79117395Skan#ifdef SC_PIXEL_MODE 80117395Skansc_rndr_sw_t gfbrndrsw = { 81117395Skan (vr_init_t *)gfb_nop, 82117395Skan gfb_clear, 83117395Skan gfb_border, 84117395Skan gfb_draw, 85117395Skan gfb_cursor_shape, 86117395Skan gfb_cursor, 87117395Skan gfb_blink, 88117395Skan (vr_set_mouse_t *)gfb_nop, 89117395Skan gfb_mouse, 90117395Skan}; 91117395Skan#endif /* SC_PIXEL_MODE */ 92117395Skan 93117395Skan#ifndef SC_NO_MODE_CHANGE 94117395Skansc_rndr_sw_t grrndrsw = { 95117395Skan (vr_init_t *)gfb_nop, 96117395Skan (vr_clear_t *)gfb_nop, 97117395Skan gfb_border, 98117395Skan (vr_draw_t *)gfb_nop, 99117395Skan (vr_set_cursor_t *)gfb_nop, 100117395Skan (vr_draw_cursor_t *)gfb_nop, 101117395Skan (vr_blink_cursor_t *)gfb_nop, 102117395Skan (vr_set_mouse_t *)gfb_nop, 103117395Skan (vr_draw_mouse_t *)gfb_nop, 104117395Skan}; 105117395Skan#endif /* SC_NO_MODE_CHANGE */ 106117395Skan 107117395Skan#ifndef SC_NO_CUTPASTE 108117395Skan#ifdef __sparc64__ 109117395Skanstatic u_char mouse_pointer[22 * 2] = { 110117395Skan 0x00, 0x00, /* ............ */ 111117395Skan 0x80, 0x00, /* *........... */ 112117395Skan 0xc0, 0x00, /* **.......... */ 113117395Skan 0xe0, 0x00, /* ***......... */ 114117395Skan 0xf0, 0x00, /* ****........ */ 115117395Skan 0xf8, 0x00, /* *****....... */ 116117395Skan 0xfc, 0x00, /* ******...... */ 117117395Skan 0xfe, 0x00, /* *******..... */ 118117395Skan 0xff, 0x00, /* ********.... */ 119117395Skan 0xff, 0x80, /* *********... */ 120117395Skan 0xfc, 0xc0, /* ******..**.. */ 121117395Skan 0xdc, 0x00, /* **.***...... */ 122117395Skan 0x8e, 0x00, /* *...***..... */ 123117395Skan 0x0e, 0x00, /* ....***..... */ 124117395Skan 0x07, 0x00, /* .....***.... */ 125117395Skan 0x04, 0x00, /* .....*...... */ 126117395Skan 0x00, 0x00, /* ............ */ 127117395Skan 0x00, 0x00, /* ............ */ 128117395Skan 0x00, 0x00, /* ............ */ 129117395Skan 0x00, 0x00, /* ............ */ 130117395Skan 0x00, 0x00, /* ............ */ 131117395Skan 0x00, 0x00 /* ............ */ 132117395Skan}; 133117395Skan#else 134117395Skanstatic u_char mouse_pointer[16] = { 135117395Skan 0x00, 0x40, 0x60, 0x70, 0x78, 0x7c, 0x7e, 0x68, 136117395Skan 0x0c, 0x0c, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00 137117395Skan}; 138117395Skan#endif 139117395Skan#endif 140117395Skan 141117395Skanstatic void 142117395Skangfb_nop(scr_stat *scp) 143117395Skan{ 144117395Skan} 145117395Skan 146117395Skan/* text mode renderer */ 147117395Skan 148117395Skanstatic void 149117395Skangfb_clear(scr_stat *scp, int c, int attr) 150117395Skan{ 151117395Skan vidd_clear(scp->sc->adp); 152117395Skan} 153117395Skan 154117395Skanstatic void 155117395Skangfb_border(scr_stat *scp, int color) 156117395Skan{ 157169689Skan vidd_set_border(scp->sc->adp, color); 158169689Skan} 159 160static void 161gfb_draw(scr_stat *scp, int from, int count, int flip) 162{ 163 int c; 164 int a; 165 int i, n; 166 video_adapter_t *adp; 167 168 adp = scp->sc->adp; 169 170 /* 171 Determine if we need to scroll based on the offset 172 and the number of characters to be displayed... 173 */ 174 if (from + count > scp->xsize*scp->ysize) { 175 176 /* 177 Calculate the number of characters past the end of the 178 visible screen... 179 */ 180 count = (from + count) - 181 (adp->va_info.vi_width * adp->va_info.vi_height); 182 183 /* 184 Calculate the number of rows past the end of the visible 185 screen... 186 */ 187 n = (count / adp->va_info.vi_width) + 1; 188 189 /* Scroll to make room for new text rows... */ 190 vidd_copy(adp, n, 0, n); 191#if 0 192 vidd_clear(adp, n); 193#endif 194 195 /* Display new text rows... */ 196 vidd_puts(adp, from, 197 (u_int16_t *)sc_vtb_pointer(&scp->vtb, from), count); 198 } 199 200 /* 201 We don't need to scroll, so we can just put the characters 202 all-at-once... 203 */ 204 else { 205 206 /* 207 Determine the method by which we are to display characters 208 (are we going to print forwards or backwards? 209 do we need to do a character-by-character copy, then?)... 210 */ 211 if (flip) 212 for (i = count; i-- > 0; ++from) { 213 c = sc_vtb_getc(&scp->vtb, from); 214 a = sc_vtb_geta(&scp->vtb, from) >> 8; 215 vidd_putc(adp, from, c, 216 (a >> 4) | ((a & 0xf) << 4)); 217 } 218 else { 219 vidd_puts(adp, from, 220 (u_int16_t *)sc_vtb_pointer(&scp->vtb, from), 221 count); 222 } 223 } 224} 225 226static void 227gfb_cursor_shape(scr_stat *scp, int base, int height, int blink) 228{ 229 if (base < 0 || base >= scp->font_size) 230 return; 231 /* the caller may set height <= 0 in order to disable the cursor */ 232#if 0 233 scp->cursor_base = base; 234 scp->cursor_height = height; 235#endif 236 vidd_set_hw_cursor_shape(scp->sc->adp, base, height, scp->font_size, 237 blink); 238} 239 240static int pxlblinkrate = 0; 241 242#if defined(__sparc64__) || defined(SC_OFWFB) 243static void 244gfb_cursor(scr_stat *scp, int at, int blink, int on, int flip) 245{ 246 video_adapter_t *adp; 247 int a, c; 248 249 if (scp->curs_attr.height <= 0) /* the text cursor is disabled */ 250 return; 251 252 adp = scp->sc->adp; 253 if(blink) { 254 scp->status |= VR_CURSOR_BLINK; 255 if (on) { 256 scp->status |= VR_CURSOR_ON; 257 vidd_set_hw_cursor(adp, at%scp->xsize, at/scp->xsize); 258 } else { 259 if (scp->status & VR_CURSOR_ON) 260 vidd_set_hw_cursor(adp, -1, -1); 261 scp->status &= ~VR_CURSOR_ON; 262 } 263 } else { 264 scp->status &= ~VR_CURSOR_BLINK; 265 if(on) { 266 scp->status |= VR_CURSOR_ON; 267 vidd_putc(scp->sc->adp, scp->cursor_oldpos, 268 sc_vtb_getc(&scp->vtb, scp->cursor_oldpos), 269 sc_vtb_geta(&scp->vtb, scp->cursor_oldpos) >> 8); 270 a = sc_vtb_geta(&scp->vtb, at) >> 8; 271 c = sc_vtb_getc(&scp->vtb, at); 272 vidd_putc(scp->sc->adp, at, c, 273 (a >> 4) | ((a & 0xf) << 4)); 274 scp->cursor_saveunder_attr = a; 275 scp->cursor_saveunder_char = c; 276 } else { 277 if (scp->status & VR_CURSOR_ON) 278 vidd_putc(scp->sc->adp, at, 279 scp->cursor_saveunder_char, 280 scp->cursor_saveunder_attr); 281 scp->status &= ~VR_CURSOR_ON; 282 } 283 } 284} 285#else 286static void 287gfb_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 321static void 322gfb_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 336static void 337gfb_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 int i, pos; 344 345 if (on) { 346 347 /* Display the mouse pointer image... */ 348 vidd_putm(scp->sc->adp, x, y, mouse_pointer, 349 0xffffffff, 16, 8); 350 } else { 351 352 /* 353 Erase the mouse cursor image by redrawing the text 354 underneath it... 355 */ 356 return; 357 pos = x*scp->xsize + y; 358 i = (y < scp->xsize - 1) ? 2 : 1; 359 (*scp->rndr->draw)(scp, pos, i, FALSE); 360 if (x < scp->ysize - 1) 361 (*scp->rndr->draw)(scp, pos + scp->xsize, i, FALSE); 362 } 363#endif 364} 365 366#endif /* SC_NO_CUTPASTE */ 367