Changes in kernel/genarch/src/fb/fb.c [a71c158:19490ce] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
kernel/genarch/src/fb/fb.c
ra71c158 r19490ce 53 53 #include <byteorder.h> 54 54 55 SPINLOCK_INITIALIZE(fb_lock); 56 57 static uint8_t *fb_addr; 58 static uint16_t *backbuf; 59 static uint8_t *glyphs; 60 static uint8_t *bgscan; 61 62 static unsigned int xres; 63 static unsigned int yres; 64 65 static unsigned int ylogo; 66 static unsigned int ytrim; 67 static unsigned int rowtrim; 68 69 static unsigned int scanline; 70 static unsigned int glyphscanline; 71 72 static unsigned int pixelbytes; 73 static unsigned int glyphbytes; 74 static unsigned int bgscanbytes; 75 76 static unsigned int cols; 77 static unsigned int rows; 78 static unsigned int position = 0; 79 55 80 #define BG_COLOR 0x000080 56 81 #define FG_COLOR 0xffff00 57 82 #define INV_COLOR 0xaaaaaa 58 83 59 #define RED(x, bits) (((x) >> (8 + 8 + 8 - (bits))) & ((1 << (bits)) - 1)) 60 #define GREEN(x, bits) (((x) >> (8 + 8 - (bits))) & ((1 << (bits)) - 1)) 61 #define BLUE(x, bits) (((x) >> (8 - (bits))) & ((1 << (bits)) - 1)) 62 63 #define COL2X(col) ((col) * FONT_WIDTH) 64 #define ROW2Y(row) ((row) * FONT_SCANLINES) 65 66 #define X2COL(x) ((x) / FONT_WIDTH) 67 #define Y2ROW(y) ((y) / FONT_SCANLINES) 68 69 #define FB_POS(instance, x, y) \ 70 ((y) * (instance)->scanline + (x) * (instance)->pixelbytes) 71 72 #define BB_POS(instance, col, row) \ 73 ((row) * (instance)->cols + (col)) 74 75 #define GLYPH_POS(instance, glyph, y) \ 76 ((glyph) * (instance)->glyphbytes + (y) * (instance)->glyphscanline) 77 78 typedef void (* rgb_conv_t)(void *, uint32_t); 79 80 typedef struct { 81 SPINLOCK_DECLARE(lock); 82 83 uint8_t *addr; 84 uint16_t *backbuf; 85 uint8_t *glyphs; 86 uint8_t *bgscan; 87 88 rgb_conv_t rgb_conv; 89 90 unsigned int xres; 91 unsigned int yres; 92 93 unsigned int ylogo; 94 unsigned int ytrim; 95 unsigned int rowtrim; 96 97 unsigned int scanline; 98 unsigned int glyphscanline; 99 100 unsigned int pixelbytes; 101 unsigned int glyphbytes; 102 unsigned int bgscanbytes; 103 104 unsigned int cols; 105 unsigned int rows; 106 107 unsigned int position; 108 } fb_instance_t; 109 110 static void fb_putchar(outdev_t *dev, wchar_t ch, bool silent); 111 static void fb_redraw_internal(fb_instance_t *instance); 112 static void fb_redraw(outdev_t *dev); 113 114 static outdev_operations_t fbdev_ops = { 115 .write = fb_putchar, 116 .redraw = fb_redraw 117 }; 84 #define RED(x, bits) (((x) >> (8 + 8 + 8 - (bits))) & ((1 << (bits)) - 1)) 85 #define GREEN(x, bits) (((x) >> (8 + 8 - (bits))) & ((1 << (bits)) - 1)) 86 #define BLUE(x, bits) (((x) >> (8 - (bits))) & ((1 << (bits)) - 1)) 87 88 #define COL2X(col) ((col) * FONT_WIDTH) 89 #define ROW2Y(row) ((row) * FONT_SCANLINES) 90 91 #define X2COL(x) ((x) / FONT_WIDTH) 92 #define Y2ROW(y) ((y) / FONT_SCANLINES) 93 94 #define FB_POS(x, y) ((y) * scanline + (x) * pixelbytes) 95 #define BB_POS(col, row) ((row) * cols + (col)) 96 #define GLYPH_POS(glyph, y) ((glyph) * glyphbytes + (y) * glyphscanline) 97 98 99 static void (*rgb_conv)(void *, uint32_t); 118 100 119 101 /* … … 187 169 GREEN(rgb, 6) << 5 | BLUE(rgb, 5)); 188 170 } 171 189 172 190 173 /** BGR 3:2:3 … … 196 179 * and setting it to simulate the 8-bit truecolor. 197 180 * 198 * Currently we set the palette on the ia32, amd64 , ppc32and sparc64 port.181 * Currently we set the palette on the ia32, amd64 and sparc64 port. 199 182 * 200 183 * Note that the byte is being inverted by this function. The reason is … … 211 194 } 212 195 196 213 197 /** Hide logo and refresh screen 214 198 * 215 199 */ 216 static void logo_hide(fb_instance_t *instance, bool silent) 217 { 218 instance->ylogo = 0; 219 instance->ytrim = instance->yres; 220 instance->rowtrim = instance->rows; 221 200 static void logo_hide(bool silent) 201 { 202 ylogo = 0; 203 ytrim = yres; 204 rowtrim = rows; 222 205 if (!silent) 223 fb_redraw_internal(instance); 224 } 206 fb_redraw(); 207 } 208 225 209 226 210 /** Draw character at given position 227 211 * 228 212 */ 229 static void glyph_draw(fb_instance_t *instance, uint16_t glyph, 230 unsigned int col, unsigned int row, bool silent, bool overlay) 213 static void glyph_draw(uint16_t glyph, unsigned int col, unsigned int row, bool silent, bool overlay) 231 214 { 232 215 unsigned int x = COL2X(col); … … 234 217 unsigned int yd; 235 218 236 if (y >= instance->ytrim)237 logo_hide( instance,silent);219 if (y >= ytrim) 220 logo_hide(silent); 238 221 239 222 if (!overlay) 240 instance->backbuf[BB_POS(instance,col, row)] = glyph;223 backbuf[BB_POS(col, row)] = glyph; 241 224 242 225 if (!silent) { 243 226 for (yd = 0; yd < FONT_SCANLINES; yd++) 244 memcpy(& instance->addr[FB_POS(instance, x, y + yd + instance->ylogo)],245 & instance->glyphs[GLYPH_POS(instance, glyph, yd)],246 instance->glyphscanline);247 248 } 227 memcpy(&fb_addr[FB_POS(x, y + yd + ylogo)], 228 &glyphs[GLYPH_POS(glyph, yd)], glyphscanline); 229 } 230 } 231 249 232 250 233 /** Scroll screen down by one row … … 252 235 * 253 236 */ 254 static void screen_scroll( fb_instance_t *instance,bool silent)255 { 256 if ( instance->ylogo > 0) {257 logo_hide( instance,silent);237 static void screen_scroll(bool silent) 238 { 239 if (ylogo > 0) { 240 logo_hide(silent); 258 241 return; 259 242 } … … 262 245 unsigned int row; 263 246 264 for (row = 0; row < instance->rows; row++) {247 for (row = 0; row < rows; row++) { 265 248 unsigned int y = ROW2Y(row); 266 249 unsigned int yd; … … 270 253 unsigned int col; 271 254 272 for (col = 0, x = 0; col < instance->cols;273 col++,x += FONT_WIDTH) {255 for (col = 0, x = 0; col < cols; col++, 256 x += FONT_WIDTH) { 274 257 uint16_t glyph; 275 258 276 if (row < instance->rows - 1) {277 if ( instance->backbuf[BB_POS(instance,col, row)] ==278 instance->backbuf[BB_POS(instance,col, row + 1)])259 if (row < rows - 1) { 260 if (backbuf[BB_POS(col, row)] == 261 backbuf[BB_POS(col, row + 1)]) 279 262 continue; 280 263 281 glyph = instance->backbuf[BB_POS(instance,col, row + 1)];264 glyph = backbuf[BB_POS(col, row + 1)]; 282 265 } else 283 266 glyph = 0; 284 267 285 memcpy(& instance->addr[FB_POS(instance,x, y + yd)],286 & instance->glyphs[GLYPH_POS(instance,glyph, yd)],287 instance->glyphscanline);268 memcpy(&fb_addr[FB_POS(x, y + yd)], 269 &glyphs[GLYPH_POS(glyph, yd)], 270 glyphscanline); 288 271 } 289 272 } … … 291 274 } 292 275 293 memmove(instance->backbuf, &instance->backbuf[BB_POS(instance, 0, 1)], 294 instance->cols * (instance->rows - 1) * sizeof(uint16_t)); 295 memsetw(&instance->backbuf[BB_POS(instance, 0, instance->rows - 1)], 296 instance->cols, 0); 297 } 298 299 static void cursor_put(fb_instance_t *instance, bool silent) 300 { 301 unsigned int col = instance->position % instance->cols; 302 unsigned int row = instance->position / instance->cols; 303 304 glyph_draw(instance, fb_font_glyph(U_CURSOR), col, row, silent, true); 305 } 306 307 static void cursor_remove(fb_instance_t *instance, bool silent) 308 { 309 unsigned int col = instance->position % instance->cols; 310 unsigned int row = instance->position / instance->cols; 311 312 glyph_draw(instance, instance->backbuf[BB_POS(instance, col, row)], 313 col, row, silent, true); 314 } 276 memmove(backbuf, &backbuf[BB_POS(0, 1)], cols * (rows - 1) * sizeof(uint16_t)); 277 memsetw(&backbuf[BB_POS(0, rows - 1)], cols, 0); 278 } 279 280 281 static void cursor_put(bool silent) 282 { 283 unsigned int col = position % cols; 284 unsigned int row = position / cols; 285 286 glyph_draw(fb_font_glyph(U_CURSOR), col, row, silent, true); 287 } 288 289 290 static void cursor_remove(bool silent) 291 { 292 unsigned int col = position % cols; 293 unsigned int row = position / cols; 294 295 glyph_draw(backbuf[BB_POS(col, row)], col, row, silent, true); 296 } 297 298 299 /** Print character to screen 300 * 301 * Emulate basic terminal commands. 302 * 303 */ 304 static void fb_putchar(outdev_t *dev, wchar_t ch, bool silent) 305 { 306 spinlock_lock(&fb_lock); 307 308 switch (ch) { 309 case '\n': 310 cursor_remove(silent); 311 position += cols; 312 position -= position % cols; 313 break; 314 case '\r': 315 cursor_remove(silent); 316 position -= position % cols; 317 break; 318 case '\b': 319 cursor_remove(silent); 320 if (position % cols) 321 position--; 322 break; 323 case '\t': 324 cursor_remove(silent); 325 do { 326 glyph_draw(fb_font_glyph(' '), position % cols, 327 position / cols, silent, false); 328 position++; 329 } while ((position % 8) && (position < cols * rows)); 330 break; 331 default: 332 glyph_draw(fb_font_glyph(ch), position % cols, 333 position / cols, silent, false); 334 position++; 335 } 336 337 if (position >= cols * rows) { 338 position -= cols; 339 screen_scroll(silent); 340 } 341 342 cursor_put(silent); 343 344 spinlock_unlock(&fb_lock); 345 } 346 347 static outdev_t fb_console; 348 static outdev_operations_t fb_ops = { 349 .write = fb_putchar 350 }; 351 315 352 316 353 /** Render glyphs … … 320 357 * 321 358 */ 322 static void glyphs_render( fb_instance_t *instance)359 static void glyphs_render(void) 323 360 { 324 361 /* Prerender glyphs */ … … 339 376 340 377 for (x = 0; x < FONT_WIDTH; x++) { 341 void *dst = 342 &instance->glyphs[GLYPH_POS(instance, glyph, y) + 343 x * instance->pixelbytes]; 378 void *dst = &glyphs[GLYPH_POS(glyph, y) + 379 x * pixelbytes]; 344 380 uint32_t rgb = (fb_font[glyph][y] & 345 381 (1 << (7 - x))) ? fg_color : BG_COLOR; 346 instance->rgb_conv(dst, rgb);382 rgb_conv(dst, rgb); 347 383 } 348 384 } … … 352 388 unsigned int x; 353 389 354 for (x = 0; x < instance->xres; x++) 355 instance->rgb_conv(&instance->bgscan[x * instance->pixelbytes], BG_COLOR); 356 } 357 358 /** Print character to screen 359 * 360 * Emulate basic terminal commands. 361 * 362 */ 363 static void fb_putchar(outdev_t *dev, wchar_t ch, bool silent) 364 { 365 fb_instance_t *instance = (fb_instance_t *) dev->data; 366 spinlock_lock(&instance->lock); 367 368 switch (ch) { 369 case '\n': 370 cursor_remove(instance, silent); 371 instance->position += instance->cols; 372 instance->position -= instance->position % instance->cols; 373 break; 374 case '\r': 375 cursor_remove(instance, silent); 376 instance->position -= instance->position % instance->cols; 377 break; 378 case '\b': 379 cursor_remove(instance, silent); 380 if (instance->position % instance->cols) 381 instance->position--; 382 break; 383 case '\t': 384 cursor_remove(instance, silent); 385 do { 386 glyph_draw(instance, fb_font_glyph(' '), 387 instance->position % instance->cols, 388 instance->position / instance->cols, silent, false); 389 instance->position++; 390 } while ((instance->position % 8) 391 && (instance->position < instance->cols * instance->rows)); 392 break; 393 default: 394 glyph_draw(instance, fb_font_glyph(ch), 395 instance->position % instance->cols, 396 instance->position / instance->cols, silent, false); 397 instance->position++; 398 } 399 400 if (instance->position >= instance->cols * instance->rows) { 401 instance->position -= instance->cols; 402 screen_scroll(instance, silent); 403 } 404 405 cursor_put(instance, silent); 406 407 spinlock_unlock(&instance->lock); 408 } 409 410 static void fb_redraw_internal(fb_instance_t *instance) 411 { 412 if (instance->ylogo > 0) { 390 for (x = 0; x < xres; x++) 391 rgb_conv(&bgscan[x * pixelbytes], BG_COLOR); 392 } 393 394 395 /** Refresh the screen 396 * 397 */ 398 void fb_redraw(void) 399 { 400 if (ylogo > 0) { 413 401 unsigned int y; 414 402 … … 416 404 unsigned int x; 417 405 418 for (x = 0; x < instance->xres; x++)419 instance->rgb_conv(&instance->addr[FB_POS(instance,x, y)],406 for (x = 0; x < xres; x++) 407 rgb_conv(&fb_addr[FB_POS(x, y)], 420 408 (x < LOGO_WIDTH) ? 421 409 fb_logo[y * LOGO_WIDTH + x] : … … 426 414 unsigned int row; 427 415 428 for (row = 0; row < instance->rowtrim; row++) {429 unsigned int y = instance->ylogo + ROW2Y(row);416 for (row = 0; row < rowtrim; row++) { 417 unsigned int y = ylogo + ROW2Y(row); 430 418 unsigned int yd; 431 419 … … 434 422 unsigned int col; 435 423 436 for (col = 0, x = 0; col < instance->cols;424 for (col = 0, x = 0; col < cols; 437 425 col++, x += FONT_WIDTH) { 438 uint16_t glyph = 439 instance->backbuf[BB_POS(instance, col, row)]; 440 void *dst = &instance->addr[FB_POS(instance, x, y + yd)]; 441 void *src = &instance->glyphs[GLYPH_POS(instance, glyph, yd)]; 442 memcpy(dst, src, instance->glyphscanline); 426 uint16_t glyph = backbuf[BB_POS(col, row)]; 427 void *dst = &fb_addr[FB_POS(x, y + yd)]; 428 void *src = &glyphs[GLYPH_POS(glyph, yd)]; 429 memcpy(dst, src, glyphscanline); 443 430 } 444 431 } 445 432 } 446 433 447 if (COL2X( instance->cols) < instance->xres) {434 if (COL2X(cols) < xres) { 448 435 unsigned int y; 449 unsigned int size = 450 (instance->xres - COL2X(instance->cols)) * instance->pixelbytes; 451 452 for (y = instance->ylogo; y < instance->yres; y++) 453 memcpy(&instance->addr[FB_POS(instance, COL2X(instance->cols), y)], 454 instance->bgscan, size); 455 } 456 457 if (ROW2Y(instance->rowtrim) + instance->ylogo < instance->yres) { 436 unsigned int size = (xres - COL2X(cols)) * pixelbytes; 437 438 for (y = ylogo; y < yres; y++) 439 memcpy(&fb_addr[FB_POS(COL2X(cols), y)], bgscan, size); 440 } 441 442 if (ROW2Y(rowtrim) + ylogo < yres) { 458 443 unsigned int y; 459 444 460 for (y = ROW2Y(instance->rowtrim) + instance->ylogo; 461 y < instance->yres; y++) 462 memcpy(&instance->addr[FB_POS(instance, 0, y)], 463 instance->bgscan, instance->bgscanbytes); 464 } 465 } 466 467 /** Refresh the screen 468 * 469 */ 470 static void fb_redraw(outdev_t *dev) 471 { 472 fb_instance_t *instance = (fb_instance_t *) dev->data; 473 474 spinlock_lock(&instance->lock); 475 fb_redraw_internal(instance); 476 spinlock_unlock(&instance->lock); 477 } 445 for (y = ROW2Y(rowtrim) + ylogo; y < yres; y++) 446 memcpy(&fb_addr[FB_POS(0, y)], bgscan, bgscanbytes); 447 } 448 } 449 478 450 479 451 /** Initialize framebuffer as a output character device 480 452 * 481 */ 482 outdev_t *fb_init(fb_properties_t *props) 483 { 484 ASSERT(props); 485 ASSERT(props->x > 0); 486 ASSERT(props->y > 0); 487 ASSERT(props->scan > 0); 488 489 rgb_conv_t rgb_conv; 490 unsigned int pixelbytes; 491 453 * @param addr Physical address of the framebuffer 454 * @param x Screen width in pixels 455 * @param y Screen height in pixels 456 * @param scan Bytes per one scanline 457 * @param visual Color model 458 * 459 */ 460 void fb_init(fb_properties_t *props) 461 { 492 462 switch (props->visual) { 493 463 case VISUAL_INDIRECT_8: … … 536 506 break; 537 507 default: 538 LOG("Unsupported visual."); 539 return NULL; 540 } 541 542 outdev_t *fbdev = malloc(sizeof(outdev_t), FRAME_ATOMIC); 543 if (!fbdev) 544 return NULL; 545 546 fb_instance_t *instance = malloc(sizeof(fb_instance_t), FRAME_ATOMIC); 547 if (!instance) { 548 free(fbdev); 549 return NULL; 550 } 551 552 outdev_initialize("fbdev", fbdev, &fbdev_ops); 553 fbdev->data = instance; 554 555 spinlock_initialize(&instance->lock, "*fb_lock"); 556 instance->rgb_conv = rgb_conv; 557 instance->pixelbytes = pixelbytes; 558 instance->xres = props->x; 559 instance->yres = props->y; 560 instance->scanline = props->scan; 561 instance->position = 0; 562 563 instance->cols = X2COL(instance->xres); 564 instance->rows = Y2ROW(instance->yres); 565 566 if (instance->yres > LOGO_HEIGHT) { 567 instance->ylogo = LOGO_HEIGHT; 568 instance->rowtrim = instance->rows - Y2ROW(instance->ylogo); 569 if (instance->ylogo % FONT_SCANLINES > 0) 570 instance->rowtrim--; 571 instance->ytrim = ROW2Y(instance->rowtrim); 508 panic("Unsupported visual."); 509 } 510 511 xres = props->x; 512 yres = props->y; 513 scanline = props->scan; 514 515 cols = X2COL(xres); 516 rows = Y2ROW(yres); 517 518 if (yres > ylogo) { 519 ylogo = LOGO_HEIGHT; 520 rowtrim = rows - Y2ROW(ylogo); 521 if (ylogo % FONT_SCANLINES > 0) 522 rowtrim--; 523 ytrim = ROW2Y(rowtrim); 572 524 } else { 573 instance->ylogo = 0; 574 instance->ytrim = instance->yres; 575 instance->rowtrim = instance->rows; 576 } 577 578 instance->glyphscanline = FONT_WIDTH * instance->pixelbytes; 579 instance->glyphbytes = ROW2Y(instance->glyphscanline); 580 instance->bgscanbytes = instance->xres * instance->pixelbytes; 581 582 size_t fbsize = instance->scanline * instance->yres; 583 size_t bbsize = instance->cols * instance->rows * sizeof(uint16_t); 584 size_t glyphsize = FONT_GLYPHS * instance->glyphbytes; 585 586 instance->addr = (uint8_t *) hw_map((uintptr_t) props->addr, fbsize); 587 if (!instance->addr) { 588 LOG("Unable to map framebuffer."); 589 free(instance); 590 free(fbdev); 591 return NULL; 592 } 593 594 instance->backbuf = (uint16_t *) malloc(bbsize, 0); 595 if (!instance->backbuf) { 596 LOG("Unable to allocate backbuffer."); 597 free(instance); 598 free(fbdev); 599 return NULL; 600 } 601 602 instance->glyphs = (uint8_t *) malloc(glyphsize, 0); 603 if (!instance->glyphs) { 604 LOG("Unable to allocate glyphs."); 605 free(instance->backbuf); 606 free(instance); 607 free(fbdev); 608 return NULL; 609 } 610 611 instance->bgscan = malloc(instance->bgscanbytes, 0); 612 if (!instance->bgscan) { 613 LOG("Unable to allocate background pixel."); 614 free(instance->glyphs); 615 free(instance->backbuf); 616 free(instance); 617 free(fbdev); 618 return NULL; 619 } 620 621 memsetw(instance->backbuf, instance->cols * instance->rows, 0); 622 glyphs_render(instance); 623 624 if (!fb_exported) { 625 /* 626 * This is the necessary evil until the userspace driver is entirely 627 * self-sufficient. 628 */ 629 sysinfo_set_item_val("fb", NULL, true); 630 sysinfo_set_item_val("fb.kind", NULL, 1); 631 sysinfo_set_item_val("fb.width", NULL, instance->xres); 632 sysinfo_set_item_val("fb.height", NULL, instance->yres); 633 sysinfo_set_item_val("fb.scanline", NULL, instance->scanline); 634 sysinfo_set_item_val("fb.visual", NULL, props->visual); 635 sysinfo_set_item_val("fb.address.physical", NULL, props->addr); 636 637 fb_exported = true; 638 } 639 640 fb_redraw(fbdev); 641 return fbdev; 525 ylogo = 0; 526 ytrim = yres; 527 rowtrim = rows; 528 } 529 530 glyphscanline = FONT_WIDTH * pixelbytes; 531 glyphbytes = ROW2Y(glyphscanline); 532 bgscanbytes = xres * pixelbytes; 533 534 size_t fbsize = scanline * yres; 535 size_t bbsize = cols * rows * sizeof(uint16_t); 536 size_t glyphsize = FONT_GLYPHS * glyphbytes; 537 538 backbuf = (uint16_t *) malloc(bbsize, 0); 539 if (!backbuf) 540 panic("Unable to allocate backbuffer."); 541 542 glyphs = (uint8_t *) malloc(glyphsize, 0); 543 if (!glyphs) 544 panic("Unable to allocate glyphs."); 545 546 bgscan = malloc(bgscanbytes, 0); 547 if (!bgscan) 548 panic("Unable to allocate background pixel."); 549 550 memsetw(backbuf, cols * rows, 0); 551 552 glyphs_render(); 553 554 fb_addr = (uint8_t *) hw_map((uintptr_t) props->addr, fbsize); 555 556 sysinfo_set_item_val("fb", NULL, true); 557 sysinfo_set_item_val("fb.kind", NULL, 1); 558 sysinfo_set_item_val("fb.width", NULL, xres); 559 sysinfo_set_item_val("fb.height", NULL, yres); 560 sysinfo_set_item_val("fb.scanline", NULL, scanline); 561 sysinfo_set_item_val("fb.visual", NULL, props->visual); 562 sysinfo_set_item_val("fb.address.physical", NULL, props->addr); 563 564 fb_redraw(); 565 566 outdev_initialize("fb", &fb_console, &fb_ops); 567 stdout = &fb_console; 642 568 } 643 569
Note:
See TracChangeset
for help on using the changeset viewer.