diff options
Diffstat (limited to 'hw/display/goldfish_fb.c')
-rw-r--r-- | hw/display/goldfish_fb.c | 71 |
1 files changed, 56 insertions, 15 deletions
diff --git a/hw/display/goldfish_fb.c b/hw/display/goldfish_fb.c index 136a15dec..f590bc1fd 100644 --- a/hw/display/goldfish_fb.c +++ b/hw/display/goldfish_fb.c @@ -157,7 +157,6 @@ 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; - int width, height, pitch; if (!s || !s->con || surface_bits_per_pixel(ds) == 0 || !s->fb_base) return; @@ -178,10 +177,9 @@ static void goldfish_fb_update_display(void *opaque) s->need_update = 0; } - pitch = surface_stride(ds); - width = surface_width(ds); - height = surface_height(ds); - + int dest_width = surface_width(ds); + int dest_height = surface_height(ds); + int dest_pitch = surface_stride(ds); int ymin, ymax; #if STATS @@ -202,19 +200,51 @@ static void goldfish_fb_update_display(void *opaque) if (s->blank) { void *dst_line = surface_data(ds); - memset( dst_line, 0, height*pitch ); + memset( dst_line, 0, dest_height*dest_pitch ); ymin = 0; - ymax = height-1; + ymax = dest_height-1; } else { SysBusDevice *dev = SYS_BUS_DEVICE(opaque); MemoryRegion *address_space = sysbus_address_space(dev); - int src_width = width * 2; - int dest_col_pitch = surface_bytes_per_pixel(ds); - int dest_row_pitch = surface_stride(ds); + 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(); + } + switch (surface_bits_per_pixel(ds)) { case 0: return; @@ -239,15 +269,26 @@ static void goldfish_fb_update_display(void *opaque) } ymin = 0; - framebuffer_update_display(ds, address_space, s->fb_base, width, height, - src_width, dest_row_pitch, dest_col_pitch, full_update, - fn, ds, &ymin, &ymax); + framebuffer_update_display(ds, address_space, s->fb_base, + src_width, src_height, + src_width * 2, + dest_row_pitch, dest_col_pitch, + full_update, + fn, ds, &ymin, &ymax); } ymax += 1; if (ymin >= 0) { - trace_goldfish_fb_update_display(ymin, ymax-ymin, 0, width); - dpy_gfx_update(s->con, 0, ymin, width, ymax-ymin); + 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); + } } } |