static void sdl_switch(DisplayChangeListener *dcl, DisplaySurface *new_surface) { /* temporary hack: allows to call sdl_switch to handle scaling changes */ if (new_surface) { surface = new_surface; } if (!scaling_active) { do_sdl_resize(surface_width(surface), surface_height(surface), 0); } else if (real_screen->format->BitsPerPixel != surface_bits_per_pixel(surface)) { do_sdl_resize(real_screen->w, real_screen->h, surface_bits_per_pixel(surface)); } if (guest_screen != NULL) { SDL_FreeSurface(guest_screen); } guest_screen = SDL_CreateRGBSurfaceFrom (surface_data(surface), surface_width(surface), surface_height(surface), surface_bits_per_pixel(surface), surface_stride(surface), surface->pf.rmask, surface->pf.gmask, surface->pf.bmask, surface->pf.amask); }
static void sdl_switch(DisplayChangeListener *dcl, DisplaySurface *new_surface) { PixelFormat pf; /* temporary hack: allows to call sdl_switch to handle scaling changes */ if (new_surface) { surface = new_surface; } pf = qemu_pixelformat_from_pixman(surface->format); if (!scaling_active) { do_sdl_resize(surface_width(surface), surface_height(surface), 0); } else if (real_screen->format->BitsPerPixel != surface_bits_per_pixel(surface)) { do_sdl_resize(real_screen->w, real_screen->h, surface_bits_per_pixel(surface)); } if (guest_screen != NULL) { SDL_FreeSurface(guest_screen); } #ifdef DEBUG_SDL printf("SDL: Creating surface with masks: %08x %08x %08x %08x\n", pf.rmask, pf.gmask, pf.bmask, pf.amask); #endif guest_screen = SDL_CreateRGBSurfaceFrom (surface_data(surface), surface_width(surface), surface_height(surface), surface_bits_per_pixel(surface), surface_stride(surface), pf.rmask, pf.gmask, pf.bmask, pf.amask); }
static void tc6393xb_draw_graphic(TC6393xbState *s, int full_update) { DisplaySurface *surface = qemu_console_surface(s->con); switch (surface_bits_per_pixel(surface)) { case 8: tc6393xb_draw_graphic8(s); break; case 15: tc6393xb_draw_graphic15(s); break; case 16: tc6393xb_draw_graphic16(s); break; case 24: tc6393xb_draw_graphic24(s); break; case 32: tc6393xb_draw_graphic32(s); break; default: printf("tc6393xb: unknown depth %d\n", surface_bits_per_pixel(surface)); return; } dpy_gfx_update(s->con, 0, 0, s->scr_width, s->scr_height); }
static void g364fb_draw_graphic8(G364State *s) { DisplaySurface *surface = qemu_console_surface(s->con); int i, w; uint8_t *vram; uint8_t *data_display, *dd; ram_addr_t page, page_min, page_max; int x, y; int xmin, xmax; int ymin, ymax; int xcursor, ycursor; unsigned int (*rgb_to_pixel)(unsigned int r, unsigned int g, unsigned int b); switch (surface_bits_per_pixel(surface)) { case 8: rgb_to_pixel = rgb_to_pixel8; w = 1; break; case 15: rgb_to_pixel = rgb_to_pixel15; w = 2; break; case 16: rgb_to_pixel = rgb_to_pixel16; w = 2; break; case 32: rgb_to_pixel = rgb_to_pixel32; w = 4; break; default: hw_error("g364: unknown host depth %d", surface_bits_per_pixel(surface)); return; } page = 0; page_min = (ram_addr_t)-1; page_max = 0; x = y = 0; xmin = s->width; xmax = 0; ymin = s->height; ymax = 0; if (!(s->ctla & CTLA_NO_CURSOR)) { xcursor = s->cursor_position >> 12; ycursor = s->cursor_position & 0xfff; } else {
static void draw_vertical_line(DisplaySurface *ds, int posx, int posy1, int posy2, uint32_t color) { uint8_t *d; int y, bpp; bpp = (surface_bits_per_pixel(ds) + 7) >> 3; d = surface_data(ds) + surface_stride(ds) * posy1 + bpp * posx; switch(bpp) { case 1: for (y = posy1; y <= posy2; y++) { *((uint8_t *)d) = color; d += surface_stride(ds); } break; case 2: for (y = posy1; y <= posy2; y++) { *((uint16_t *)d) = color; d += surface_stride(ds); } break; case 4: for (y = posy1; y <= posy2; y++) { *((uint32_t *)d) = color; d += surface_stride(ds); } break; } }
static void draw_horizontal_line(DisplaySurface *ds, int posy, int posx1, int posx2, uint32_t color) { uint8_t *d; int x, bpp; bpp = (surface_bits_per_pixel(ds) + 7) >> 3; d = surface_data(ds) + surface_stride(ds) * posy + bpp * posx1; switch(bpp) { case 1: for (x = posx1; x <= posx2; x++) { *((uint8_t *)d) = color; d++; } break; case 2: for (x = posx1; x <= posx2; x++) { *((uint16_t *)d) = color; d += 2; } break; case 4: for (x = posx1; x <= posx2; x++) { *((uint32_t *)d) = color; d += 4; } break; } }
static void update_palette_entries(TCXState *s, int start, int end) { DisplaySurface *surface = qemu_console_surface(s->con); int i; for (i = start; i < end; i++) { switch (surface_bits_per_pixel(surface)) { default: case 8: s->palette[i] = rgb_to_pixel8(s->r[i], s->g[i], s->b[i]); break; case 15: s->palette[i] = rgb_to_pixel15(s->r[i], s->g[i], s->b[i]); break; case 16: s->palette[i] = rgb_to_pixel16(s->r[i], s->g[i], s->b[i]); break; case 32: if (is_surface_bgr(surface)) { s->palette[i] = rgb_to_pixel32bgr(s->r[i], s->g[i], s->b[i]); } else { s->palette[i] = rgb_to_pixel32(s->r[i], s->g[i], s->b[i]); } break; } } if (s->depth == 24) { tcx24_set_dirty(s); } else { tcx_set_dirty(s); } }
static void toggle_full_screen(void) { int width = surface_width(surface); int height = surface_height(surface); int bpp = surface_bits_per_pixel(surface); gui_fullscreen = !gui_fullscreen; if (gui_fullscreen) { gui_saved_width = real_screen->w; gui_saved_height = real_screen->h; gui_saved_scaling = scaling_active; do_sdl_resize(width, height, bpp); scaling_active = 0; gui_saved_grab = gui_grab; sdl_grab_start(); } else { if (gui_saved_scaling) { sdl_scale(gui_saved_width, gui_saved_height); } else { do_sdl_resize(width, height, 0); } if (!gui_saved_grab || !qemu_console_is_graphic(NULL)) { sdl_grab_end(); } } graphic_hw_invalidate(NULL); graphic_hw_update(NULL); }
static void vgafb_update_display(void *opaque) { MilkymistVgafbState *s = opaque; DisplaySurface *surface = qemu_console_surface(s->con); int first = 0; int last = 0; drawfn fn; if (!vgafb_enabled(s)) { return; } int dest_width = s->regs[R_HRES]; switch (surface_bits_per_pixel(surface)) { case 0: return; case 8: fn = draw_line_8; break; case 15: fn = draw_line_15; dest_width *= 2; break; case 16: fn = draw_line_16; dest_width *= 2; break; case 24: fn = draw_line_24; dest_width *= 3; break; case 32: fn = draw_line_32; dest_width *= 4; break; default: hw_error("milkymist_vgafb: bad color depth\n"); break; } framebuffer_update_display(surface, sysbus_address_space(&s->busdev), s->regs[R_BASEADDRESS] + s->fb_offset, s->regs[R_HRES], s->regs[R_VRES], s->regs[R_HRES] * 2, dest_width, 0, s->invalidate, fn, NULL, &first, &last); if (first >= 0) { dpy_gfx_update(s->con, 0, first, s->regs[R_HRES], last - first + 1); } s->invalidate = 0; }
static void sdl_switch(DisplayChangeListener *dcl, DisplaySurface *new_surface) { struct sdl2_state *scon = container_of(dcl, struct sdl2_state, dcl); int format = 0; int idx = scon->idx; DisplaySurface *old_surface = scon->surface; /* temporary hack: allows to call sdl_switch to handle scaling changes */ if (new_surface) { scon->surface = new_surface; } if (!new_surface && idx > 0) { scon->surface = NULL; } if (new_surface == NULL) { do_sdl_resize(scon, 0, 0, 0); } else { do_sdl_resize(scon, surface_width(scon->surface), surface_height(scon->surface), 0); } if (old_surface && scon->texture) { SDL_DestroyTexture(scon->texture); scon->texture = NULL; } if (new_surface) { if (!scon->texture) { if (surface_bits_per_pixel(scon->surface) == 16) { format = SDL_PIXELFORMAT_RGB565; } else if (surface_bits_per_pixel(scon->surface) == 32) { format = SDL_PIXELFORMAT_ARGB8888; } scon->texture = SDL_CreateTexture(scon->real_renderer, format, SDL_TEXTUREACCESS_STREAMING, surface_width(new_surface), surface_height(new_surface)); } } }
static void jazz_led_update_display(void *opaque) { LedState *s = opaque; DisplaySurface *surface = qemu_console_surface(s->con); uint8_t *d1; uint32_t color_segment, color_led; int y, bpp; if (s->state & REDRAW_BACKGROUND) { /* clear screen */ bpp = (surface_bits_per_pixel(surface) + 7) >> 3; d1 = surface_data(surface); for (y = 0; y < surface_height(surface); y++) { memset(d1, 0x00, surface_width(surface) * bpp); d1 += surface_stride(surface); } }
/* * This copies data from the guest framebuffer region, into QEMU's * displaysurface. qemu uses 16 or 32 bpp. In case the pv framebuffer * uses something else we must convert and copy, otherwise we can * supply the buffer directly and no thing here. */ static void xenfb_guest_copy(struct XenFB *xenfb, int x, int y, int w, int h) { DisplaySurface *surface = qemu_console_surface(xenfb->c.con); int line, oops = 0; int bpp = surface_bits_per_pixel(surface); int linesize = surface_stride(surface); uint8_t *data = surface_data(surface); if (!is_buffer_shared(surface)) { switch (xenfb->depth) { case 8: if (bpp == 16) { BLT(uint8_t, uint16_t, 3, 3, 2, 5, 6, 5); } else if (bpp == 32) { BLT(uint8_t, uint32_t, 3, 3, 2, 8, 8, 8); } else { oops = 1; } break; case 24: if (bpp == 16) { BLT(uint32_t, uint16_t, 8, 8, 8, 5, 6, 5); } else if (bpp == 32) { BLT(uint32_t, uint32_t, 8, 8, 8, 8, 8, 8); } else { oops = 1; } break; default: oops = 1; } } if (oops) /* should not happen */ xen_be_printf(&xenfb->c.xendev, 0, "%s: oops: convert %d -> %d bpp?\n", __FUNCTION__, xenfb->depth, bpp); dpy_gfx_update(xenfb->c.con, x, y, w, h); }
/* Load new palette for a given DMA channel, convert to internal format */ static void pxa2xx_palette_parse(PXA2xxLCDState *s, int ch, int bpp) { DisplaySurface *surface = qemu_console_surface(s->con); int i, n, format, r, g, b, alpha; uint32_t *dest; uint8_t *src; s->pal_for = LCCR4_PALFOR(s->control[4]); format = s->pal_for; switch (bpp) { case pxa_lcdc_2bpp: n = 4; break; case pxa_lcdc_4bpp: n = 16; break; case pxa_lcdc_8bpp: n = 256; break; default: format = 0; return; } src = (uint8_t *) s->dma_ch[ch].pbuffer; dest = (uint32_t *) s->dma_ch[ch].palette; alpha = r = g = b = 0; for (i = 0; i < n; i ++) { switch (format) { case 0: /* 16 bpp, no transparency */ alpha = 0; if (s->control[0] & LCCR0_CMS) { r = g = b = *(uint16_t *) src & 0xff; } else { r = (*(uint16_t *) src & 0xf800) >> 8; g = (*(uint16_t *) src & 0x07e0) >> 3; b = (*(uint16_t *) src & 0x001f) << 3; } src += 2; break; case 1: /* 16 bpp plus transparency */ alpha = *(uint32_t *) src & (1 << 24); if (s->control[0] & LCCR0_CMS) r = g = b = *(uint32_t *) src & 0xff; else { r = (*(uint32_t *) src & 0xf80000) >> 16; g = (*(uint32_t *) src & 0x00fc00) >> 8; b = (*(uint32_t *) src & 0x0000f8); } src += 4; break; case 2: /* 18 bpp plus transparency */ alpha = *(uint32_t *) src & (1 << 24); if (s->control[0] & LCCR0_CMS) r = g = b = *(uint32_t *) src & 0xff; else { r = (*(uint32_t *) src & 0xfc0000) >> 16; g = (*(uint32_t *) src & 0x00fc00) >> 8; b = (*(uint32_t *) src & 0x0000fc); } src += 4; break; case 3: /* 24 bpp plus transparency */ alpha = *(uint32_t *) src & (1 << 24); if (s->control[0] & LCCR0_CMS) r = g = b = *(uint32_t *) src & 0xff; else { r = (*(uint32_t *) src & 0xff0000) >> 16; g = (*(uint32_t *) src & 0x00ff00) >> 8; b = (*(uint32_t *) src & 0x0000ff); } src += 4; break; } switch (surface_bits_per_pixel(surface)) { case 8: *dest = rgb_to_pixel8(r, g, b) | alpha; break; case 15: *dest = rgb_to_pixel15(r, g, b) | alpha; break; case 16: *dest = rgb_to_pixel16(r, g, b) | alpha; break; case 24: *dest = rgb_to_pixel24(r, g, b) | alpha; break; case 32: *dest = rgb_to_pixel32(r, g, b) | alpha; break; } dest ++; } }
/* Fixed line length 1024 allows us to do nice tricks not possible on VGA... */ static void tcx_update_display(void *opaque) { TCXState *ts = opaque; DisplaySurface *surface = qemu_console_surface(ts->con); ram_addr_t page, page_min, page_max; int y, y_start, dd, ds; uint8_t *d, *s; void (*f)(TCXState *s1, uint8_t *dst, const uint8_t *src, int width); if (surface_bits_per_pixel(surface) == 0) { return; } page = 0; y_start = -1; page_min = -1; page_max = 0; d = surface_data(surface); s = ts->vram; dd = surface_stride(surface); ds = 1024; switch (surface_bits_per_pixel(surface)) { case 32: f = tcx_draw_line32; break; case 15: case 16: f = tcx_draw_line16; break; default: case 8: f = tcx_draw_line8; break; case 0: return; } for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE) { if (memory_region_get_dirty(&ts->vram_mem, page, TARGET_PAGE_SIZE, DIRTY_MEMORY_VGA)) { if (y_start < 0) y_start = y; if (page < page_min) page_min = page; if (page > page_max) page_max = page; f(ts, d, s, ts->width); d += dd; s += ds; f(ts, d, s, ts->width); d += dd; s += ds; f(ts, d, s, ts->width); d += dd; s += ds; f(ts, d, s, ts->width); d += dd; s += ds; } else { if (y_start >= 0) { /* flush to display */ dpy_gfx_update(ts->con, 0, y_start, ts->width, y - y_start); y_start = -1; } d += dd * 4; s += ds * 4; } } if (y_start >= 0) { /* flush to display */ dpy_gfx_update(ts->con, 0, y_start, ts->width, y - y_start); } /* reset modified pages */ if (page_max >= page_min) { memory_region_reset_dirty(&ts->vram_mem, page_min, (page_max - page_min) + TARGET_PAGE_SIZE, DIRTY_MEMORY_VGA); } }
static void tcx24_update_display(void *opaque) { TCXState *ts = opaque; DisplaySurface *surface = qemu_console_surface(ts->con); ram_addr_t page, page_min, page_max, cpage, page24; int y, y_start, dd, ds; uint8_t *d, *s; uint32_t *cptr, *s24; if (surface_bits_per_pixel(surface) != 32) { return; } page = 0; page24 = ts->vram24_offset; cpage = ts->cplane_offset; y_start = -1; page_min = -1; page_max = 0; d = surface_data(surface); s = ts->vram; s24 = ts->vram24; cptr = ts->cplane; dd = surface_stride(surface); ds = 1024; for(y = 0; y < ts->height; y += 4, page += TARGET_PAGE_SIZE, page24 += TARGET_PAGE_SIZE, cpage += TARGET_PAGE_SIZE) { if (check_dirty(ts, page, page24, cpage)) { if (y_start < 0) y_start = y; if (page < page_min) page_min = page; if (page > page_max) page_max = page; tcx24_draw_line32(ts, d, s, ts->width, cptr, s24); d += dd; s += ds; cptr += ds; s24 += ds; tcx24_draw_line32(ts, d, s, ts->width, cptr, s24); d += dd; s += ds; cptr += ds; s24 += ds; tcx24_draw_line32(ts, d, s, ts->width, cptr, s24); d += dd; s += ds; cptr += ds; s24 += ds; tcx24_draw_line32(ts, d, s, ts->width, cptr, s24); d += dd; s += ds; cptr += ds; s24 += ds; } else { if (y_start >= 0) { /* flush to display */ dpy_gfx_update(ts->con, 0, y_start, ts->width, y - y_start); y_start = -1; } d += dd * 4; s += ds * 4; cptr += ds * 4; s24 += ds * 4; } } if (y_start >= 0) { /* flush to display */ dpy_gfx_update(ts->con, 0, y_start, ts->width, y - y_start); } /* reset modified pages */ if (page_max >= page_min) { reset_dirty(ts, page_min, page_max, page24, cpage); } }
static void goldfish_fb_update_display(void *opaque) { struct goldfish_fb_state *s = (struct goldfish_fb_state *)opaque; DisplaySurface *ds = qemu_console_surface(s->con); int full_update = 0; if (!s || !s->con || surface_bits_per_pixel(ds) == 0 || !s->fb_base) return; if((s->int_enable & FB_INT_VSYNC) && !(s->int_status & FB_INT_VSYNC)) { s->int_status |= FB_INT_VSYNC; qemu_irq_raise(s->irq); } if(s->need_update) { full_update = 1; if(s->need_int) { s->int_status |= FB_INT_BASE_UPDATE_DONE; if(s->int_enable & FB_INT_BASE_UPDATE_DONE) qemu_irq_raise(s->irq); } s->need_int = 0; s->need_update = 0; } int dest_width = surface_width(ds); int dest_height = surface_height(ds); int dest_pitch = surface_stride(ds); int ymin, ymax; #if STATS if (full_update) stats_full_updates += 1; if (++stats_counter == 120) { stats_total += stats_counter; stats_total_full_updates += stats_full_updates; trace_goldfish_fb_update_stats(stats_full_updates*100.0/stats_counter, stats_total_full_updates*100.0/stats_total ); stats_counter = 0; stats_full_updates = 0; } #endif /* STATS */ if (s->blank) { void *dst_line = surface_data(ds); memset( dst_line, 0, dest_height*dest_pitch ); ymin = 0; ymax = dest_height-1; } else { SysBusDevice *dev = SYS_BUS_DEVICE(opaque); MemoryRegion *address_space = sysbus_address_space(dev); int src_width, src_height; int dest_row_pitch, dest_col_pitch; drawfn fn; /* The source framebuffer is always read in a linear fashion, * we achieve rotation by altering the destination * step-per-pixel. */ switch (s->rotation) { case 0: /* Normal, native landscape view */ src_width = dest_width; src_height = dest_height; dest_row_pitch = surface_stride(ds); dest_col_pitch = surface_bytes_per_pixel(ds); break; case 1: /* 90 degree, portrait view */ src_width = dest_height; src_height = dest_width; dest_row_pitch = -surface_bytes_per_pixel(ds); dest_col_pitch = surface_stride(ds); break; case 2: /* 180 degree, inverted landscape view */ src_width = dest_width; src_height = dest_height; dest_row_pitch = -surface_stride(ds); dest_col_pitch = -surface_bytes_per_pixel(ds); break; case 3: /* 270 degree, mirror portrait view */ src_width = dest_height; src_height = dest_width; dest_row_pitch = surface_bytes_per_pixel(ds); dest_col_pitch = -surface_stride(ds); break; default: g_assert_not_reached(); } int source_bytes_per_pixel = 2; switch (s->format) { /* source format */ case HAL_PIXEL_FORMAT_RGB_565: source_bytes_per_pixel = 2; switch (surface_bits_per_pixel(ds)) { /* dest format */ case 8: fn = draw_line_16_8; break; case 15: fn = draw_line_16_15; break; case 16: fn = draw_line_16_16; break; case 24: fn = draw_line_16_24; break; case 32: fn = draw_line_16_32; break; default: hw_error("goldfish_fb: bad dest color depth\n"); return; } break; case HAL_PIXEL_FORMAT_RGBX_8888: source_bytes_per_pixel = 4; switch (surface_bits_per_pixel(ds)) { /* dest format */ case 8: fn = draw_line_32_8; break; case 15: fn = draw_line_32_15; break; case 16: fn = draw_line_32_16; break; case 24: fn = draw_line_32_24; break; case 32: fn = draw_line_32_32; break; default: hw_error("goldfish_fb: bad dest color depth\n"); return; } break; default: hw_error("goldfish_fb: bad source color format\n"); return; } ymin = 0; framebuffer_update_display(ds, address_space, s->fb_base, src_width, src_height, src_width * source_bytes_per_pixel, dest_row_pitch, dest_col_pitch, full_update, fn, ds, &ymin, &ymax); } ymax += 1; if (ymin >= 0) { if (s->rotation % 2) { /* In portrait mode we are drawing "sideways" so always * need to update the whole screen */ trace_goldfish_fb_update_display(0, dest_height, 0, dest_width); dpy_gfx_update(s->con, 0, 0, dest_width, dest_height); } else { trace_goldfish_fb_update_display(ymin, ymax-ymin, 0, dest_width); dpy_gfx_update(s->con, 0, ymin, dest_width, ymax-ymin); } } }
static void sm_lcd_update_display(void *arg) { lcd_state *s = arg; uint8_t *d; uint32_t colour_on, colour_off, colour; int x, y, bpp; DisplaySurface *surface = qemu_console_surface(s->con); bpp = surface_bits_per_pixel(surface); d = surface_data(surface); // If vibrate is on, simply jiggle the display if (s->vibrate_on) { if (s->vibrate_offset == 0) { s->vibrate_offset = 2; } int bytes_per_pixel; switch (bpp) { case 8: bytes_per_pixel = 1; break; case 15: case 16: bytes_per_pixel = 2; break; case 32: bytes_per_pixel = 4; break; default: abort(); } int total_bytes = NUM_ROWS * NUM_COLS * bytes_per_pixel - abs(s->vibrate_offset) * bytes_per_pixel; if (s->vibrate_offset > 0) { memmove(d, d + s->vibrate_offset * bytes_per_pixel, total_bytes); } else { memmove(d - s->vibrate_offset * bytes_per_pixel, d, total_bytes); } s->vibrate_offset *= -1; dpy_gfx_update(s->con, 0, 0, NUM_COLS, NUM_ROWS); return; } if (!s->redraw) { return; } // Adjust the white level to compensate for the set brightness. // brightness = 0: 255 in maps to 170 out // brightness = 1.0: 255 in maps to 255 out float brightness = s->backlight_enabled ? s->brightness : 0.0; int max_val = 170 + (255 - 170) * brightness; /* set colours according to bpp */ switch (bpp) { case 8: colour_on = rgb_to_pixel8(max_val, max_val, max_val); colour_off = rgb_to_pixel8(0x00, 0x00, 0x00); break; case 15: colour_on = rgb_to_pixel15(max_val, max_val, max_val); colour_off = rgb_to_pixel15(0x00, 0x00, 0x00); break; case 16: colour_on = rgb_to_pixel16(max_val, max_val, max_val); colour_off = rgb_to_pixel16(0x00, 0x00, 0x00); case 24: colour_on = rgb_to_pixel24(max_val, max_val, max_val); colour_off = rgb_to_pixel24(0x00, 0x00, 0x00); break; case 32: colour_on = rgb_to_pixel32(max_val, max_val, max_val); colour_off = rgb_to_pixel32(0x00, 0x00, 0x00); break; default: return; } for (y = 0; y < NUM_ROWS; y++) { for (x = 0; x < NUM_COLS; x++) { /* Rotate display - installed 'upside-down' in pebble. */ int xr = NUM_COLS - 1 - x; int yr = NUM_ROWS - 1 - y; bool on = s->framebuffer[yr * NUM_COL_BYTES + xr / 8] & 1 << (xr % 8); colour = on ? colour_on : colour_off; switch(bpp) { case 8: *((uint8_t *)d) = colour; d++; break; case 15: case 16: *((uint16_t *)d) = colour; d += 2; break; case 24: abort(); case 32: *((uint32_t *)d) = colour; d += 4; break; } } } dpy_gfx_update(s->con, 0, 0, NUM_COLS, NUM_ROWS); s->redraw = false; }
static uint64_t goldfish_fb_read(void *opaque, hwaddr offset, unsigned size) { uint64_t ret = 0; struct goldfish_fb_state *s = opaque; DisplaySurface *ds = qemu_console_surface(s->con); #ifndef USE_ANDROID_EMU int android_display_bpp = surface_bits_per_pixel(ds); #endif switch(offset) { case FB_GET_WIDTH: ret = surface_width(ds); break; case FB_GET_HEIGHT: ret = surface_height(ds); break; case FB_INT_STATUS: ret = s->int_status & s->int_enable; if(ret) { s->int_status &= ~ret; qemu_irq_lower(s->irq); } break; case FB_GET_PHYS_WIDTH: ret = pixels_to_mm( surface_width(ds), s->dpi ); break; case FB_GET_PHYS_HEIGHT: ret = pixels_to_mm( surface_height(ds), s->dpi ); break; case FB_GET_FORMAT: /* A kernel making this query supports high color and true color */ switch (android_display_bpp) { /* hw.lcd.depth */ case 32: case 24: ret = HAL_PIXEL_FORMAT_RGBX_8888; break; case 16: ret = HAL_PIXEL_FORMAT_RGB_565; break; default: error_report("goldfish_fb_read: Bad android_display_bpp %d", android_display_bpp); break; } s->format = ret; break; default: error_report("goldfish_fb_read: Bad offset 0x" TARGET_FMT_plx, offset); break; } trace_goldfish_fb_memory_read(offset, ret); return ret; }
static void cg3_update_display(void *opaque) { CG3State *s = opaque; DisplaySurface *surface = qemu_console_surface(s->con); const uint8_t *pix; uint32_t *data; uint32_t dval; int x, y, y_start; unsigned int width, height; ram_addr_t page, page_min, page_max; if (surface_bits_per_pixel(surface) != 32) { return; } width = s->width; height = s->height; y_start = -1; page_min = -1; page_max = 0; page = 0; pix = memory_region_get_ram_ptr(&s->vram_mem); data = (uint32_t *)surface_data(surface); for (y = 0; y < height; y++) { int update = s->full_update; page = (y * width) & TARGET_PAGE_MASK; update |= memory_region_get_dirty(&s->vram_mem, page, page + width, DIRTY_MEMORY_VGA); if (update) { if (y_start < 0) { y_start = y; } if (page < page_min) { page_min = page; } if (page > page_max) { page_max = page; } for (x = 0; x < width; x++) { dval = *pix++; dval = (s->r[dval] << 16) | (s->g[dval] << 8) | s->b[dval]; *data++ = dval; } } else { if (y_start >= 0) { dpy_gfx_update(s->con, 0, y_start, s->width, y - y_start); y_start = -1; } pix += width; data += width; } } s->full_update = 0; if (y_start >= 0) { dpy_gfx_update(s->con, 0, y_start, s->width, y - y_start); } if (page_max >= page_min) { memory_region_reset_dirty(&s->vram_mem, page_min, page_max - page_min + TARGET_PAGE_SIZE, DIRTY_MEMORY_VGA); } /* vsync interrupt? */ if (s->regs[0] & CG3_CR_ENABLE_INTS) { s->regs[1] |= CG3_SR_PENDING_INT; qemu_irq_raise(s->irq); } }
static void cg3_update_display(void *opaque) { CG3State *s = opaque; DisplaySurface *surface = qemu_console_surface(s->con); const uint8_t *pix; uint32_t *data; uint32_t dval; int x, y, y_start; unsigned int width, height; ram_addr_t page; DirtyBitmapSnapshot *snap = NULL; if (surface_bits_per_pixel(surface) != 32) { return; } width = s->width; height = s->height; y_start = -1; pix = memory_region_get_ram_ptr(&s->vram_mem); data = (uint32_t *)surface_data(surface); if (!s->full_update) { memory_region_sync_dirty_bitmap(&s->vram_mem); snap = memory_region_snapshot_and_clear_dirty(&s->vram_mem, 0x0, memory_region_size(&s->vram_mem), DIRTY_MEMORY_VGA); } for (y = 0; y < height; y++) { int update; page = (ram_addr_t)y * width; if (s->full_update) { update = 1; } else { update = memory_region_snapshot_get_dirty(&s->vram_mem, snap, page, width); } if (update) { if (y_start < 0) { y_start = y; } for (x = 0; x < width; x++) { dval = *pix++; dval = (s->r[dval] << 16) | (s->g[dval] << 8) | s->b[dval]; *data++ = dval; } } else { if (y_start >= 0) { dpy_gfx_update(s->con, 0, y_start, width, y - y_start); y_start = -1; } pix += width; data += width; } } s->full_update = 0; if (y_start >= 0) { dpy_gfx_update(s->con, 0, y_start, width, y - y_start); } /* vsync interrupt? */ if (s->regs[0] & CG3_CR_ENABLE_INTS) { s->regs[1] |= CG3_SR_PENDING_INT; qemu_irq_raise(s->irq); } g_free(snap); }