1 /* Copyright (C) 2007-2008 The Android Open Source Project 2 ** 3 ** This software is licensed under the terms of the GNU General Public 4 ** License version 2, as published by the Free Software Foundation, and 5 ** may be copied, distributed, and modified under those terms. 6 ** 7 ** This program is distributed in the hope that it will be useful, 8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 ** GNU General Public License for more details. 11 */ 12 #include "cpu.h" 13 #include "migration/qemu-file.h" 14 #include "android/android.h" 15 #include "android/utils/debug.h" 16 #include "android/utils/duff.h" 17 #include "hw/android/goldfish/device.h" 18 #include "hw/hw.h" 19 #include "ui/console.h" 20 21 /* These values *must* match the platform definitions found under 22 * hardware/libhardware/include/hardware/hardware.h 23 */ 24 enum { 25 HAL_PIXEL_FORMAT_RGBA_8888 = 1, 26 HAL_PIXEL_FORMAT_RGBX_8888 = 2, 27 HAL_PIXEL_FORMAT_RGB_888 = 3, 28 HAL_PIXEL_FORMAT_RGB_565 = 4, 29 HAL_PIXEL_FORMAT_BGRA_8888 = 5, 30 HAL_PIXEL_FORMAT_RGBA_5551 = 6, 31 HAL_PIXEL_FORMAT_RGBA_4444 = 7, 32 }; 33 34 enum { 35 FB_GET_WIDTH = 0x00, 36 FB_GET_HEIGHT = 0x04, 37 FB_INT_STATUS = 0x08, 38 FB_INT_ENABLE = 0x0c, 39 FB_SET_BASE = 0x10, 40 FB_SET_ROTATION = 0x14, 41 FB_SET_BLANK = 0x18, 42 FB_GET_PHYS_WIDTH = 0x1c, 43 FB_GET_PHYS_HEIGHT = 0x20, 44 FB_GET_FORMAT = 0x24, 45 46 FB_INT_VSYNC = 1U << 0, 47 FB_INT_BASE_UPDATE_DONE = 1U << 1 48 }; 49 50 struct goldfish_fb_state { 51 struct goldfish_device dev; 52 DisplayState* ds; 53 int pixel_format; 54 int bytes_per_pixel; 55 uint32_t fb_base; 56 uint32_t base_valid : 1; 57 uint32_t need_update : 1; 58 uint32_t need_int : 1; 59 uint32_t set_rotation : 2; 60 uint32_t blank : 1; 61 uint32_t int_status; 62 uint32_t int_enable; 63 int rotation; /* 0, 1, 2 or 3 */ 64 int dpi; 65 }; 66 67 #define GOLDFISH_FB_SAVE_VERSION 2 68 69 static void goldfish_fb_save(QEMUFile* f, void* opaque) 70 { 71 struct goldfish_fb_state* s = opaque; 72 73 DisplayState* ds = s->ds; 74 75 qemu_put_be32(f, ds->surface->width); 76 qemu_put_be32(f, ds->surface->height); 77 qemu_put_be32(f, ds->surface->linesize); 78 qemu_put_byte(f, 0); 79 80 qemu_put_be32(f, s->fb_base); 81 qemu_put_byte(f, s->base_valid); 82 qemu_put_byte(f, s->need_update); 83 qemu_put_byte(f, s->need_int); 84 qemu_put_byte(f, s->set_rotation); 85 qemu_put_byte(f, s->blank); 86 qemu_put_be32(f, s->int_status); 87 qemu_put_be32(f, s->int_enable); 88 qemu_put_be32(f, s->rotation); 89 qemu_put_be32(f, s->dpi); 90 } 91 92 static int goldfish_fb_load(QEMUFile* f, void* opaque, int version_id) 93 { 94 struct goldfish_fb_state* s = opaque; 95 int ret = -1; 96 int ds_w, ds_h, ds_pitch, ds_rot; 97 98 if (version_id != GOLDFISH_FB_SAVE_VERSION) 99 goto Exit; 100 101 ds_w = qemu_get_be32(f); 102 ds_h = qemu_get_be32(f); 103 ds_pitch = qemu_get_be32(f); 104 ds_rot = qemu_get_byte(f); 105 106 DisplayState* ds = s->ds; 107 108 if (ds->surface->width != ds_w || 109 ds->surface->height != ds_h || 110 ds->surface->linesize != ds_pitch || 111 ds_rot != 0) 112 { 113 /* XXX: We should be able to force a resize/rotation from here ? */ 114 fprintf(stderr, "%s: framebuffer dimensions mismatch\n", __FUNCTION__); 115 goto Exit; 116 } 117 118 s->fb_base = qemu_get_be32(f); 119 s->base_valid = qemu_get_byte(f); 120 s->need_update = qemu_get_byte(f); 121 s->need_int = qemu_get_byte(f); 122 s->set_rotation = qemu_get_byte(f); 123 s->blank = qemu_get_byte(f); 124 s->int_status = qemu_get_be32(f); 125 s->int_enable = qemu_get_be32(f); 126 s->rotation = qemu_get_be32(f); 127 s->dpi = qemu_get_be32(f); 128 129 /* force a refresh */ 130 s->need_update = 1; 131 132 ret = 0; 133 Exit: 134 return ret; 135 } 136 137 /* Type used to record a mapping from display surface pixel format to 138 * HAL pixel format */ 139 typedef struct { 140 int pixel_format; /* HAL pixel format */ 141 uint8_t bits; 142 uint8_t bytes; 143 uint32_t rmask, gmask, bmask, amask; 144 } FbConfig; 145 146 147 /* Return the pixel format of the current framebuffer, based on 148 * the current display surface's pixel format. 149 * 150 * Note that you should not call this function from the device initialization 151 * function, because the display surface will change format before the kernel 152 * start. 153 */ 154 static int goldfish_fb_get_pixel_format(struct goldfish_fb_state *s) 155 { 156 if (s->pixel_format >= 0) { 157 return s->pixel_format; 158 } 159 static const FbConfig fb_configs[] = { 160 { HAL_PIXEL_FORMAT_RGB_565, 16, 2, 0xf800, 0x7e0, 0x1f, 0x0 }, 161 { HAL_PIXEL_FORMAT_RGBX_8888, 32, 4, 0xff0000, 0xff00, 0xff, 0x0 }, 162 { HAL_PIXEL_FORMAT_RGBA_8888, 32, 4, 0xff0000, 0xff00, 0xff, 0xff000000 }, 163 { -1, } 164 }; 165 166 /* Determine HAL pixel format value based on s->ds */ 167 struct PixelFormat* pf = &s->ds->surface->pf; 168 if (VERBOSE_CHECK(init)) { 169 printf("%s:%d: display surface,pixel format:\n", __FUNCTION__, __LINE__); 170 printf(" bits/pixel: %d\n", pf->bits_per_pixel); 171 printf(" bytes/pixel: %d\n", pf->bytes_per_pixel); 172 printf(" depth: %d\n", pf->depth); 173 printf(" red: bits=%d mask=0x%x shift=%d max=0x%x\n", 174 pf->rbits, pf->rmask, pf->rshift, pf->rmax); 175 printf(" green: bits=%d mask=0x%x shift=%d max=0x%x\n", 176 pf->gbits, pf->gmask, pf->gshift, pf->gmax); 177 printf(" blue: bits=%d mask=0x%x shift=%d max=0x%x\n", 178 pf->bbits, pf->bmask, pf->bshift, pf->bmax); 179 printf(" alpha: bits=%d mask=0x%x shift=%d max=0x%x\n", 180 pf->abits, pf->amask, pf->ashift, pf->amax); 181 } 182 183 s->bytes_per_pixel = pf->bytes_per_pixel; 184 int nn; 185 for (nn = 0; fb_configs[nn].pixel_format >= 0; nn++) { 186 const FbConfig* fbc = &fb_configs[nn]; 187 if (pf->bits_per_pixel == fbc->bits && 188 pf->bytes_per_pixel == fbc->bytes && 189 pf->rmask == fbc->rmask && 190 pf->gmask == fbc->gmask && 191 pf->bmask == fbc->bmask && 192 pf->amask == fbc->amask) { 193 /* We found it */ 194 s->pixel_format = fbc->pixel_format; 195 return s->pixel_format; 196 } 197 } 198 fprintf(stderr, "%s:%d: Unsupported display pixel format (depth=%d, bytespp=%d, bitspp=%d)\n", 199 __FUNCTION__, __LINE__, 200 pf->depth, 201 pf->bytes_per_pixel, 202 pf->bits_per_pixel); 203 exit(1); 204 return -1; 205 } 206 207 static int goldfish_fb_get_bytes_per_pixel(struct goldfish_fb_state *s) 208 { 209 if (s->pixel_format < 0) { 210 (void) goldfish_fb_get_pixel_format(s); 211 } 212 return s->bytes_per_pixel; 213 } 214 215 static int 216 pixels_to_mm(int pixels, int dpi) 217 { 218 /* dpi = dots / inch 219 ** inch = dots / dpi 220 ** mm / 25.4 = dots / dpi 221 ** mm = (dots * 25.4)/dpi 222 */ 223 return (int)(0.5 + 25.4 * pixels / dpi); 224 } 225 226 227 #define STATS 0 228 229 #if STATS 230 static int stats_counter; 231 static long stats_total; 232 static int stats_full_updates; 233 static long stats_total_full_updates; 234 #endif 235 236 /* This structure is used to hold the inputs for 237 * compute_fb_update_rect_linear below. 238 * This corresponds to the source framebuffer and destination 239 * surface pixel buffers. 240 */ 241 typedef struct { 242 int width; 243 int height; 244 int bytes_per_pixel; 245 const uint8_t* src_pixels; 246 int src_pitch; 247 uint8_t* dst_pixels; 248 int dst_pitch; 249 } FbUpdateState; 250 251 /* This structure is used to hold the outputs for 252 * compute_fb_update_rect_linear below. 253 * This corresponds to the smalled bounding rectangle of the 254 * latest framebuffer update. 255 */ 256 typedef struct { 257 int xmin, ymin, xmax, ymax; 258 } FbUpdateRect; 259 260 /* Determine the smallest bounding rectangle of pixels which changed 261 * between the source (framebuffer) and destination (surface) pixel 262 * buffers. 263 * 264 * Return 0 if there was no change, otherwise, populate '*rect' 265 * and return 1. 266 * 267 * If 'dirty_base' is not 0, it is a physical address that will be 268 * used to speed-up the check using the VGA dirty bits. In practice 269 * this is only used if your kernel driver does not implement. 270 * 271 * This function assumes that the framebuffers are in linear memory. 272 * This may change later when we want to support larger framebuffers 273 * that exceed the max DMA aperture size though. 274 */ 275 static int 276 compute_fb_update_rect_linear(FbUpdateState* fbs, 277 uint32_t dirty_base, 278 FbUpdateRect* rect) 279 { 280 int yy; 281 int width = fbs->width; 282 const uint8_t* src_line = fbs->src_pixels; 283 uint8_t* dst_line = fbs->dst_pixels; 284 uint32_t dirty_addr = dirty_base; 285 rect->xmin = rect->ymin = INT_MAX; 286 rect->xmax = rect->ymax = INT_MIN; 287 for (yy = 0; yy < fbs->height; yy++) { 288 int xx1, xx2; 289 /* If dirty_addr is != 0, then use it as a physical address to 290 * use the VGA dirty bits table to speed up the detection of 291 * changed pixels. 292 */ 293 if (dirty_addr != 0) { 294 int dirty = 0; 295 int len = fbs->src_pitch; 296 297 while (len > 0) { 298 int len2 = TARGET_PAGE_SIZE - (dirty_addr & (TARGET_PAGE_SIZE-1)); 299 300 if (len2 > len) 301 len2 = len; 302 303 dirty |= cpu_physical_memory_get_dirty(dirty_addr, VGA_DIRTY_FLAG); 304 dirty_addr += len2; 305 len -= len2; 306 } 307 308 if (!dirty) { /* this line was not modified, skip to next one */ 309 goto NEXT_LINE; 310 } 311 } 312 313 /* Then compute actual bounds of the changed pixels, while 314 * copying them from 'src' to 'dst'. This depends on the pixel depth. 315 */ 316 switch (fbs->bytes_per_pixel) { 317 case 2: 318 { 319 const uint16_t* src = (const uint16_t*) src_line; 320 uint16_t* dst = (uint16_t*) dst_line; 321 322 xx1 = 0; 323 DUFF4(width, { 324 uint16_t spix = src[xx1]; 325 #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) 326 spix = (uint16_t)((spix << 8) | (spix >> 8)); 327 #endif 328 if (spix != dst[xx1]) 329 break; 330 xx1++; 331 }); 332 if (xx1 == width) { 333 break; 334 } 335 xx2 = width-1; 336 DUFF4(xx2-xx1, { 337 if (src[xx2] != dst[xx2]) 338 break; 339 xx2--; 340 }); 341 #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) 342 /* Convert the guest pixels into host ones */ 343 int xx = xx1; 344 DUFF4(xx2-xx1+1,{ 345 unsigned spix = src[xx]; 346 dst[xx] = (uint16_t)((spix << 8) | (spix >> 8)); 347 xx++; 348 }); 349 #else 350 memcpy( dst+xx1, src+xx1, (xx2-xx1+1)*2 ); 351 #endif 352 break; 353 } 354 355 case 3: 356 { 357 xx1 = 0; 358 DUFF4(width, { 359 int xx = xx1*3; 360 if (src_line[xx+0] != dst_line[xx+0] || 361 src_line[xx+1] != dst_line[xx+1] || 362 src_line[xx+2] != dst_line[xx+2]) { 363 break; 364 } 365 xx1 ++; 366 }); 367 if (xx1 == width) { 368 break; 369 } 370 xx2 = width-1; 371 DUFF4(xx2-xx1,{ 372 int xx = xx2*3; 373 if (src_line[xx+0] != dst_line[xx+0] || 374 src_line[xx+1] != dst_line[xx+1] || 375 src_line[xx+2] != dst_line[xx+2]) { 376 break; 377 } 378 xx2--; 379 }); 380 memcpy( dst_line+xx1*3, src_line+xx1*3, (xx2-xx1+1)*3 ); 381 break; 382 } 383 384 case 4: 385 { 386 const uint32_t* src = (const uint32_t*) src_line; 387 uint32_t* dst = (uint32_t*) dst_line; 388 389 xx1 = 0; 390 DUFF4(width, { 391 uint32_t spix = src[xx1]; 392 #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) 393 spix = (spix << 16) | (spix >> 16); 394 spix = ((spix << 8) & 0xff00ff00) | ((spix >> 8) & 0x00ff00ff); 395 #endif 396 if (spix != dst[xx1]) { 397 break; 398 } 399 xx1++; 400 }); 401 if (xx1 == width) { 402 break; 403 } 404 xx2 = width-1; 405 DUFF4(xx2-xx1,{ 406 if (src[xx2] != dst[xx2]) { 407 break; 408 } 409 xx2--; 410 }); 411 #if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) 412 /* Convert the guest pixels into host ones */ 413 int xx = xx1; 414 DUFF4(xx2-xx1+1,{ 415 uint32_t spix = src[xx]; 416 spix = (spix << 16) | (spix >> 16); 417 spix = ((spix << 8) & 0xff00ff00) | ((spix >> 8) & 0x00ff00ff); 418 dst[xx] = spix; 419 xx++; 420 }) 421 #else 422 memcpy( dst+xx1, src+xx1, (xx2-xx1+1)*4 ); 423 #endif 424 break; 425 } 426 default: 427 return 0; 428 } 429 /* Update bounds if pixels on this line were modified */ 430 if (xx1 < width) { 431 if (xx1 < rect->xmin) rect->xmin = xx1; 432 if (xx2 > rect->xmax) rect->xmax = xx2; 433 if (yy < rect->ymin) rect->ymin = yy; 434 if (yy > rect->ymax) rect->ymax = yy; 435 } 436 NEXT_LINE: 437 src_line += fbs->src_pitch; 438 dst_line += fbs->dst_pitch; 439 } 440 441 if (rect->ymin > rect->ymax) { /* nothing changed */ 442 return 0; 443 } 444 445 /* Always clear the dirty VGA bits */ 446 cpu_physical_memory_reset_dirty(dirty_base + rect->ymin * fbs->src_pitch, 447 dirty_base + (rect->ymax+1)* fbs->src_pitch, 448 VGA_DIRTY_FLAG); 449 return 1; 450 } 451 452 453 static void goldfish_fb_update_display(void *opaque) 454 { 455 struct goldfish_fb_state *s = (struct goldfish_fb_state *)opaque; 456 uint32_t base; 457 uint8_t* dst_line; 458 uint8_t* src_line; 459 int full_update = 0; 460 int width, height, pitch; 461 462 base = s->fb_base; 463 if(base == 0) 464 return; 465 466 if((s->int_enable & FB_INT_VSYNC) && !(s->int_status & FB_INT_VSYNC)) { 467 s->int_status |= FB_INT_VSYNC; 468 goldfish_device_set_irq(&s->dev, 0, 1); 469 } 470 471 if(s->need_update) { 472 full_update = 1; 473 if(s->need_int) { 474 s->int_status |= FB_INT_BASE_UPDATE_DONE; 475 if(s->int_enable & FB_INT_BASE_UPDATE_DONE) 476 goldfish_device_set_irq(&s->dev, 0, 1); 477 } 478 s->need_int = 0; 479 s->need_update = 0; 480 } 481 482 src_line = qemu_get_ram_ptr( base ); 483 484 dst_line = s->ds->surface->data; 485 pitch = s->ds->surface->linesize; 486 width = s->ds->surface->width; 487 height = s->ds->surface->height; 488 489 FbUpdateState fbs; 490 FbUpdateRect rect; 491 492 fbs.width = width; 493 fbs.height = height; 494 fbs.dst_pixels = dst_line; 495 fbs.dst_pitch = pitch; 496 fbs.bytes_per_pixel = goldfish_fb_get_bytes_per_pixel(s); 497 498 fbs.src_pixels = src_line; 499 fbs.src_pitch = width*s->ds->surface->pf.bytes_per_pixel; 500 501 502 #if STATS 503 if (full_update) 504 stats_full_updates += 1; 505 if (++stats_counter == 120) { 506 stats_total += stats_counter; 507 stats_total_full_updates += stats_full_updates; 508 509 printf( "full update stats: peak %.2f %% total %.2f %%\n", 510 stats_full_updates*100.0/stats_counter, 511 stats_total_full_updates*100.0/stats_total ); 512 513 stats_counter = 0; 514 stats_full_updates = 0; 515 } 516 #endif /* STATS */ 517 518 if (s->blank) 519 { 520 memset( dst_line, 0, height*pitch ); 521 rect.xmin = 0; 522 rect.ymin = 0; 523 rect.xmax = width-1; 524 rect.ymax = height-1; 525 } 526 else 527 { 528 if (full_update) { /* don't use dirty-bits optimization */ 529 base = 0; 530 } 531 if (compute_fb_update_rect_linear(&fbs, base, &rect) == 0) { 532 return; 533 } 534 } 535 536 rect.xmax += 1; 537 rect.ymax += 1; 538 #if 0 539 printf("goldfish_fb_update_display (y:%d,h:%d,x=%d,w=%d)\n", 540 rect.ymin, rect.ymax-rect.ymin, rect.xmin, rect.xmax-rect.xmin); 541 #endif 542 543 dpy_update(s->ds, rect.xmin, rect.ymin, rect.xmax-rect.xmin, rect.ymax-rect.ymin); 544 } 545 546 static void goldfish_fb_invalidate_display(void * opaque) 547 { 548 // is this called? 549 struct goldfish_fb_state *s = (struct goldfish_fb_state *)opaque; 550 s->need_update = 1; 551 } 552 553 static uint32_t goldfish_fb_read(void *opaque, hwaddr offset) 554 { 555 uint32_t ret; 556 struct goldfish_fb_state *s = opaque; 557 558 switch(offset) { 559 case FB_GET_WIDTH: 560 ret = ds_get_width(s->ds); 561 //printf("FB_GET_WIDTH => %d\n", ret); 562 return ret; 563 564 case FB_GET_HEIGHT: 565 ret = ds_get_height(s->ds); 566 //printf( "FB_GET_HEIGHT = %d\n", ret); 567 return ret; 568 569 case FB_INT_STATUS: 570 ret = s->int_status & s->int_enable; 571 if(ret) { 572 s->int_status &= ~ret; 573 goldfish_device_set_irq(&s->dev, 0, 0); 574 } 575 return ret; 576 577 case FB_GET_PHYS_WIDTH: 578 ret = pixels_to_mm( ds_get_width(s->ds), s->dpi ); 579 //printf( "FB_GET_PHYS_WIDTH => %d\n", ret ); 580 return ret; 581 582 case FB_GET_PHYS_HEIGHT: 583 ret = pixels_to_mm( ds_get_height(s->ds), s->dpi ); 584 //printf( "FB_GET_PHYS_HEIGHT => %d\n", ret ); 585 return ret; 586 587 case FB_GET_FORMAT: 588 return goldfish_fb_get_pixel_format(s); 589 590 default: 591 cpu_abort (cpu_single_env, "goldfish_fb_read: Bad offset %x\n", offset); 592 return 0; 593 } 594 } 595 596 static void goldfish_fb_write(void *opaque, hwaddr offset, 597 uint32_t val) 598 { 599 struct goldfish_fb_state *s = opaque; 600 601 switch(offset) { 602 case FB_INT_ENABLE: 603 s->int_enable = val; 604 goldfish_device_set_irq(&s->dev, 0, (s->int_status & s->int_enable)); 605 break; 606 case FB_SET_BASE: { 607 int need_resize = !s->base_valid; 608 s->fb_base = val; 609 s->int_status &= ~FB_INT_BASE_UPDATE_DONE; 610 s->need_update = 1; 611 s->need_int = 1; 612 s->base_valid = 1; 613 if(s->set_rotation != s->rotation) { 614 //printf("FB_SET_BASE: rotation : %d => %d\n", s->rotation, s->set_rotation); 615 s->rotation = s->set_rotation; 616 need_resize = 1; 617 } 618 goldfish_device_set_irq(&s->dev, 0, (s->int_status & s->int_enable)); 619 if (need_resize) { 620 //printf("FB_SET_BASE: need resize (rotation=%d)\n", s->rotation ); 621 dpy_resize(s->ds); 622 } 623 } break; 624 case FB_SET_ROTATION: 625 //printf( "FB_SET_ROTATION %d\n", val); 626 s->set_rotation = val; 627 break; 628 case FB_SET_BLANK: 629 s->blank = val; 630 s->need_update = 1; 631 break; 632 default: 633 cpu_abort (cpu_single_env, "goldfish_fb_write: Bad offset %x\n", offset); 634 } 635 } 636 637 static CPUReadMemoryFunc *goldfish_fb_readfn[] = { 638 goldfish_fb_read, 639 goldfish_fb_read, 640 goldfish_fb_read 641 }; 642 643 static CPUWriteMemoryFunc *goldfish_fb_writefn[] = { 644 goldfish_fb_write, 645 goldfish_fb_write, 646 goldfish_fb_write 647 }; 648 649 void goldfish_fb_init(int id) 650 { 651 struct goldfish_fb_state *s; 652 653 s = (struct goldfish_fb_state *)g_malloc0(sizeof(*s)); 654 s->dev.name = "goldfish_fb"; 655 s->dev.id = id; 656 s->dev.size = 0x1000; 657 s->dev.irq_count = 1; 658 659 s->ds = graphic_console_init(goldfish_fb_update_display, 660 goldfish_fb_invalidate_display, 661 NULL, 662 NULL, 663 s); 664 665 s->dpi = 165; /* XXX: Find better way to get actual value ! */ 666 667 /* IMPORTANT: DO NOT COMPUTE s->pixel_format and s->bytes_per_pixel 668 * here because the display surface is going to change later. 669 */ 670 s->bytes_per_pixel = 0; 671 s->pixel_format = -1; 672 673 goldfish_device_add(&s->dev, goldfish_fb_readfn, goldfish_fb_writefn, s); 674 675 register_savevm(NULL, 676 "goldfish_fb", 677 0, 678 GOLDFISH_FB_SAVE_VERSION, 679 goldfish_fb_save, 680 goldfish_fb_load, 681 s); 682 } 683