aboutsummaryrefslogtreecommitdiff
path: root/hw/display/bcm2835_fb.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/display/bcm2835_fb.c')
-rw-r--r--hw/display/bcm2835_fb.c28
1 files changed, 22 insertions, 6 deletions
diff --git a/hw/display/bcm2835_fb.c b/hw/display/bcm2835_fb.c
index a6c0a0cc94..76a10072b4 100644
--- a/hw/display/bcm2835_fb.c
+++ b/hw/display/bcm2835_fb.c
@@ -126,6 +126,18 @@ static void draw_line_src16(void *opaque, uint8_t *dst, const uint8_t *src,
}
}
+static bool fb_use_offsets(BCM2835FBConfig *config)
+{
+ /*
+ * Return true if we should use the viewport offsets.
+ * Experimentally, the hardware seems to do this only if the
+ * viewport size is larger than the physical screen. (It doesn't
+ * prevent the guest setting this silly viewport setting, though...)
+ */
+ return config->xres_virtual > config->xres &&
+ config->yres_virtual > config->yres;
+}
+
static void fb_update_display(void *opaque)
{
BCM2835FBState *s = opaque;
@@ -134,12 +146,18 @@ static void fb_update_display(void *opaque)
int last = 0;
int src_width = 0;
int dest_width = 0;
+ uint32_t xoff = 0, yoff = 0;
if (s->lock || !s->config.xres) {
return;
}
src_width = bcm2835_fb_get_pitch(&s->config);
+ if (fb_use_offsets(&s->config)) {
+ xoff = s->config.xoffset;
+ yoff = s->config.yoffset;
+ }
+
dest_width = s->config.xres;
switch (surface_bits_per_pixel(surface)) {
@@ -165,8 +183,9 @@ static void fb_update_display(void *opaque)
}
if (s->invalidate) {
+ hwaddr base = s->config.base + xoff + yoff * src_width;
framebuffer_update_memory_section(&s->fbsection, s->dma_mr,
- s->config.base,
+ base,
s->config.yres, src_width);
}
@@ -176,7 +195,8 @@ static void fb_update_display(void *opaque)
draw_line_src16, s, &first, &last);
if (first >= 0) {
- dpy_gfx_update(s->con, 0, first, s->config.xres, last - first + 1);
+ dpy_gfx_update(s->con, 0, first, s->config.xres,
+ last - first + 1);
}
s->invalidate = false;
@@ -202,8 +222,6 @@ static void bcm2835_fb_mbox_push(BCM2835FBState *s, uint32_t value)
s->config.base = s->vcram_base | (value & 0xc0000000);
s->config.base += BCM2835_FB_OFFSET;
- /* TODO - Manage properly virtual resolution */
-
pitch = bcm2835_fb_get_pitch(&s->config);
size = bcm2835_fb_get_size(&s->config);
@@ -224,8 +242,6 @@ void bcm2835_fb_reconfigure(BCM2835FBState *s, BCM2835FBConfig *newconfig)
s->config = *newconfig;
- /* TODO - Manage properly virtual resolution */
-
s->invalidate = true;
qemu_console_resize(s->con, s->config.xres, s->config.yres);
s->lock = false;