From 714fa308a3f86e1dc55021ff1282c1afe6954d3d Mon Sep 17 00:00:00 2001 From: pbrook Date: Wed, 1 Apr 2009 12:27:59 +0000 Subject: [PATCH] Implement and use shared memory framebuffer device rendering reoutine. Use DMA mapping API. Signed-off-by: Paul Brook git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@6965 c046a42c-6fe2-441c-8c8c-71466251a162 --- Makefile.target | 1 + hw/framebuffer.c | 119 ++++++++++++++++++++++++++++++++++++++++++++++++ hw/framebuffer.h | 22 +++++++++ hw/omap.h | 2 +- hw/omap_lcd_template.h | 23 ++++++---- hw/omap_lcdc.c | 96 +++++++++++++------------------------- hw/pl110.c | 61 +++++-------------------- hw/pl110_template.h | 16 ++++--- hw/pxa2xx_lcd.c | 117 ++++++++++++----------------------------------- hw/pxa2xx_template.h | 27 ++++++----- 10 files changed, 253 insertions(+), 231 deletions(-) create mode 100644 hw/framebuffer.c create mode 100644 hw/framebuffer.h diff --git a/Makefile.target b/Makefile.target index f862d90..046427d 100644 --- a/Makefile.target +++ b/Makefile.target @@ -672,6 +672,7 @@ OBJS+= nseries.o blizzard.o onenand.o vga.o cbus.o tusb6010.o usb-musb.o OBJS+= tsc2005.o bt-hci-csr.o OBJS+= mst_fpga.o mainstone.o OBJS+= musicpal.o pflash_cfi02.o +OBJS+= framebuffer.o CPPFLAGS += -DHAS_AUDIO endif ifeq ($(TARGET_BASE_ARCH), sh4) diff --git a/hw/framebuffer.c b/hw/framebuffer.c new file mode 100644 index 0000000..1086ba9 --- /dev/null +++ b/hw/framebuffer.c @@ -0,0 +1,119 @@ +/* + * Framebuffer device helper routines + * + * Copyright (c) 2009 CodeSourcery + * Written by Paul Brook + * + * This code is licensed under the GNU GPLv2. + */ + +/* TODO: + - Do something similar for framebuffers with local ram + - Handle rotation here instead of hacking dest_pitch + - Use common pixel conversion routines instead of per-device drawfn + - Remove all DisplayState knowledge from devices. + */ + +#include "hw.h" +#include "console.h" +#include "framebuffer.h" +#include "kvm.h" + +/* Render an image from a shared memory framebuffer. */ + +void framebuffer_update_display( + DisplayState *ds, + target_phys_addr_t base, + int cols, /* Width in pixels. */ + int rows, /* Leight in pixels. */ + int src_width, /* Length of source line, in bytes. */ + int dest_row_pitch, /* Bytes between adjacent horizontal output pixels. */ + int dest_col_pitch, /* Bytes between adjacent vertical output pixels. */ + int invalidate, /* nonzero to redraw the whole image. */ + drawfn fn, + void *opaque, + int *first_row, /* Input and output. */ + int *last_row /* Output only */) +{ + target_phys_addr_t src_len; + uint8_t *dest; + uint8_t *src; + uint8_t *src_base; + int first, last = 0; + int dirty; + int i; + ram_addr_t addr; + ram_addr_t pd; + ram_addr_t pd2; + + i = *first_row; + *first_row = -1; + src_len = src_width * rows; + + if (kvm_enabled()) { + kvm_physical_sync_dirty_bitmap(base, src_len); + } + pd = cpu_get_physical_page_desc(base); + pd2 = cpu_get_physical_page_desc(base + src_len - 1); + /* We should reall check that this is a continuous ram region. + Instead we just check that the first and last pages are + both ram, and the right distance apart. */ + if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM + || (pd2 & ~TARGET_PAGE_MASK) > IO_MEM_ROM) { + return; + } + pd = (pd & TARGET_PAGE_MASK) + (base & ~TARGET_PAGE_MASK); + if (((pd + src_len - 1) & TARGET_PAGE_MASK) != (pd2 & TARGET_PAGE_MASK)) { + return; + } + + src_base = cpu_physical_memory_map(base, &src_len, 0); + /* If we can't map the framebuffer then bail. We could try harder, + but it's not really worth it as dirty flag tracking will probably + already have failed above. */ + if (!src_base) + return; + if (src_len != src_width * rows) { + cpu_physical_memory_unmap(src_base, src_len, 0, 0); + return; + } + src = src_base; + dest = ds_get_data(ds); + if (dest_col_pitch < 0) + dest -= dest_col_pitch * (cols - 1); + first = -1; + addr = pd; + + addr += i * src_width; + src += i * src_width; + dest += i * dest_row_pitch; + + for (; i < rows; i++) { + target_phys_addr_t dirty_offset; + dirty = 0; + dirty_offset = 0; + while (addr + dirty_offset < TARGET_PAGE_ALIGN(addr + src_width)) { + dirty |= cpu_physical_memory_get_dirty(addr + dirty_offset, + VGA_DIRTY_FLAG); + dirty_offset += TARGET_PAGE_SIZE; + } + + if (dirty || invalidate) { + fn(opaque, dest, src, cols, dest_col_pitch); + if (first == -1) + first = i; + last = i; + } + addr += src_width; + src += src_width; + dest += dest_row_pitch; + } + cpu_physical_memory_unmap(src_base, src_len, 0, 0); + if (first < 0) { + return; + } + cpu_physical_memory_reset_dirty(pd, pd + src_len, VGA_DIRTY_FLAG); + *first_row = first; + *last_row = last; + return; +} diff --git a/hw/framebuffer.h b/hw/framebuffer.h new file mode 100644 index 0000000..a3a2146 --- /dev/null +++ b/hw/framebuffer.h @@ -0,0 +1,22 @@ +#ifndef QEMU_FRAMEBUFFER_H +#define QEMU_FRAMEBUFFER_H + +/* Framebuffer device helper routines. */ + +typedef void (*drawfn)(void *, uint8_t *, const uint8_t *, int, int); + +void framebuffer_update_display( + DisplayState *ds, + target_phys_addr_t base, + int cols, + int rows, + int src_width, + int dest_row_pitch, + int dest_col_pitch, + int invalidate, + drawfn fn, + void *opaque, + int *first_row, + int *last_row); + +#endif diff --git a/hw/omap.h b/hw/omap.h index 7965eb2..e940474 100644 --- a/hw/omap.h +++ b/hw/omap.h @@ -490,7 +490,7 @@ struct omap_dma_lcd_channel_s { int dual; int current_frame; - ram_addr_t phys_framebuffer[2]; + target_phys_addr_t phys_framebuffer[2]; qemu_irq irq; struct omap_mpu_state_s *mpu; } *omap_dma_get_lcdch(struct soc_dma_s *s); diff --git a/hw/omap_lcd_template.h b/hw/omap_lcd_template.h index 4e84fa1..0590e45 100644 --- a/hw/omap_lcd_template.h +++ b/hw/omap_lcd_template.h @@ -43,9 +43,10 @@ /* * 2-bit colour */ -static void glue(draw_line2_, DEPTH)( - uint8_t *d, const uint8_t *s, int width, const uint16_t *pal) +static void glue(draw_line2_, DEPTH)(void *opaque, + uint8_t *d, const uint8_t *s, int width, int deststep) { + uint16_t *pal = opaque; uint8_t v, r, g, b; do { @@ -81,9 +82,10 @@ static void glue(draw_line2_, DEPTH)( /* * 4-bit colour */ -static void glue(draw_line4_, DEPTH)( - uint8_t *d, const uint8_t *s, int width, const uint16_t *pal) +static void glue(draw_line4_, DEPTH)(void *opaque, + uint8_t *d, const uint8_t *s, int width, int deststep) { + uint16_t *pal = opaque; uint8_t v, r, g, b; do { @@ -107,9 +109,10 @@ static void glue(draw_line4_, DEPTH)( /* * 8-bit colour */ -static void glue(draw_line8_, DEPTH)( - uint8_t *d, const uint8_t *s, int width, const uint16_t *pal) +static void glue(draw_line8_, DEPTH)(void *opaque, + uint8_t *d, const uint8_t *s, int width, int deststep) { + uint16_t *pal = opaque; uint8_t v, r, g, b; do { @@ -126,8 +129,8 @@ static void glue(draw_line8_, DEPTH)( /* * 12-bit colour */ -static void glue(draw_line12_, DEPTH)( - uint8_t *d, const uint8_t *s, int width, const uint16_t *pal) +static void glue(draw_line12_, DEPTH)(void *opaque, + uint8_t *d, const uint8_t *s, int width, int deststep) { uint16_t v; uint8_t r, g, b; @@ -146,8 +149,8 @@ static void glue(draw_line12_, DEPTH)( /* * 16-bit colour */ -static void glue(draw_line16_, DEPTH)( - uint8_t *d, const uint8_t *s, int width, const uint16_t *pal) +static void glue(draw_line16_, DEPTH)(void *opaque, + uint8_t *d, const uint8_t *s, int width, int deststep) { #if DEPTH == 16 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN) memcpy(d, s, width * 2); diff --git a/hw/omap_lcdc.c b/hw/omap_lcdc.c index a02d99d..6a91b27 100644 --- a/hw/omap_lcdc.c +++ b/hw/omap_lcdc.c @@ -20,6 +20,7 @@ #include "hw.h" #include "console.h" #include "omap.h" +#include "framebuffer.h" struct omap_lcd_panel_s { qemu_irq irq; @@ -68,8 +69,7 @@ static void omap_lcd_interrupts(struct omap_lcd_panel_s *s) #include "pixel_ops.h" -typedef void draw_line_func( - uint8_t *d, const uint8_t *s, int width, const uint16_t *pal); +#define draw_line_func drawfn #define DEPTH 8 #include "omap_lcd_template.h" @@ -80,31 +80,31 @@ typedef void draw_line_func( #define DEPTH 32 #include "omap_lcd_template.h" -static draw_line_func *draw_line_table2[33] = { +static draw_line_func draw_line_table2[33] = { [0 ... 32] = 0, [8] = draw_line2_8, [15] = draw_line2_15, [16] = draw_line2_16, [32] = draw_line2_32, -}, *draw_line_table4[33] = { +}, draw_line_table4[33] = { [0 ... 32] = 0, [8] = draw_line4_8, [15] = draw_line4_15, [16] = draw_line4_16, [32] = draw_line4_32, -}, *draw_line_table8[33] = { +}, draw_line_table8[33] = { [0 ... 32] = 0, [8] = draw_line8_8, [15] = draw_line8_15, [16] = draw_line8_16, [32] = draw_line8_32, -}, *draw_line_table12[33] = { +}, draw_line_table12[33] = { [0 ... 32] = 0, [8] = draw_line12_8, [15] = draw_line12_15, [16] = draw_line12_16, [32] = draw_line12_32, -}, *draw_line_table16[33] = { +}, draw_line_table16[33] = { [0 ... 32] = 0, [8] = draw_line16_8, [15] = draw_line16_15, @@ -115,11 +115,10 @@ static draw_line_func *draw_line_table2[33] = { static void omap_update_display(void *opaque) { struct omap_lcd_panel_s *omap_lcd = (struct omap_lcd_panel_s *) opaque; - draw_line_func *draw_line; - int size, dirty[2], minline, maxline, height; - int line, width, linesize, step, bpp, frame_offset; - ram_addr_t frame_base, scanline, newline, x; - uint8_t *s, *d; + draw_line_func draw_line; + int size, height, first, last; + int width, linesize, step, bpp, frame_offset; + target_phys_addr_t frame_base; if (!omap_lcd || omap_lcd->plm == 1 || !omap_lcd->enable || !ds_get_bits_per_pixel(omap_lcd->state)) @@ -127,9 +126,9 @@ static void omap_update_display(void *opaque) frame_offset = 0; if (omap_lcd->plm != 2) { - memcpy(omap_lcd->palette, phys_ram_base + - omap_lcd->dma->phys_framebuffer[ - omap_lcd->dma->current_frame], 0x200); + cpu_physical_memory_read(omap_lcd->dma->phys_framebuffer[ + omap_lcd->dma->current_frame], + (void *)omap_lcd->palette, 0x200); switch (omap_lcd->palette[0] >> 12 & 7) { case 3 ... 7: frame_offset += 0x200; @@ -202,49 +201,28 @@ static void omap_update_display(void *opaque) if (!ds_get_bits_per_pixel(omap_lcd->state)) return; - line = 0; + first = 0; height = omap_lcd->height; if (omap_lcd->subpanel & (1 << 31)) { if (omap_lcd->subpanel & (1 << 29)) - line = (omap_lcd->subpanel >> 16) & 0x3ff; + first = (omap_lcd->subpanel >> 16) & 0x3ff; else height = (omap_lcd->subpanel >> 16) & 0x3ff; /* TODO: fill the rest of the panel with DPD */ } + step = width * bpp >> 3; - scanline = frame_base + step * line; - s = (uint8_t *) (phys_ram_base + scanline); - d = ds_get_data(omap_lcd->state); linesize = ds_get_linesize(omap_lcd->state); - - dirty[0] = dirty[1] = - cpu_physical_memory_get_dirty(scanline, VGA_DIRTY_FLAG); - minline = height; - maxline = line; - for (; line < height; line ++) { - newline = scanline + step; - for (x = scanline + TARGET_PAGE_SIZE; x < newline; - x += TARGET_PAGE_SIZE) { - dirty[1] = cpu_physical_memory_get_dirty(x, VGA_DIRTY_FLAG); - dirty[0] |= dirty[1]; - } - if (dirty[0] || omap_lcd->invalidate) { - draw_line(d, s, width, omap_lcd->palette); - if (line < minline) - minline = line; - maxline = line + 1; - } - scanline = newline; - dirty[0] = dirty[1]; - s += step; - d += linesize; - } - - if (maxline >= minline) { - dpy_update(omap_lcd->state, 0, minline, width, maxline); - cpu_physical_memory_reset_dirty(frame_base + step * minline, - frame_base + step * maxline, VGA_DIRTY_FLAG); + framebuffer_update_display(omap_lcd->state, + frame_base, width, height, + step, linesize, 0, + omap_lcd->invalidate, + draw_line, omap_lcd->palette, + &first, &last); + if (first >= 0) { + dpy_update(omap_lcd->state, 0, first, width, last - first + 1); } + omap_lcd->invalidate = 0; } static int ppm_save(const char *filename, uint8_t *data, @@ -336,25 +314,13 @@ static void omap_lcd_update(struct omap_lcd_panel_s *s) { return; } - if (s->dma->src == imif) { - /* Framebuffers are in SRAM */ - s->dma->phys_framebuffer[0] = s->imif_base + - s->dma->src_f1_top - OMAP_IMIF_BASE; - - s->dma->phys_framebuffer[1] = s->imif_base + - s->dma->src_f2_top - OMAP_IMIF_BASE; - } else { - /* Framebuffers are in RAM */ - s->dma->phys_framebuffer[0] = s->emiff_base + - s->dma->src_f1_top - OMAP_EMIFF_BASE; - - s->dma->phys_framebuffer[1] = s->emiff_base + - s->dma->src_f2_top - OMAP_EMIFF_BASE; - } + s->dma->phys_framebuffer[0] = s->dma->src_f1_top; + s->dma->phys_framebuffer[1] = s->dma->src_f2_top; if (s->plm != 2 && !s->palette_done) { - memcpy(s->palette, phys_ram_base + - s->dma->phys_framebuffer[s->dma->current_frame], 0x200); + cpu_physical_memory_read( + s->dma->phys_framebuffer[s->dma->current_frame], + (void *)s->palette, 0x200); s->palette_done = 1; omap_lcd_interrupts(s); } diff --git a/hw/pl110.c b/hw/pl110.c index 7ce74a2..f21b63b 100644 --- a/hw/pl110.c +++ b/hw/pl110.c @@ -10,6 +10,7 @@ #include "hw.h" #include "primecell.h" #include "console.h" +#include "framebuffer.h" #define PL110_CR_EN 0x001 #define PL110_CR_BGR 0x100 @@ -61,8 +62,6 @@ static const unsigned char pl110_versatile_id[] = #include "pixel_ops.h" -typedef void (*drawfn)(uint32_t *, uint8_t *, const uint8_t *, int); - #define BITS 8 #include "pl110_template.h" #define BITS 15 @@ -84,17 +83,11 @@ static void pl110_update_display(void *opaque) pl110_state *s = (pl110_state *)opaque; drawfn* fntable; drawfn fn; - uint32_t *pallette; - uint32_t addr; - uint32_t base; int dest_width; int src_width; - uint8_t *dest; - uint8_t *src; - int first, last = 0; - int dirty, new_dirty; - int i; int bpp_offset; + int first; + int last; if (!pl110_enabled(s)) return; @@ -159,47 +152,17 @@ static void pl110_update_display(void *opaque) break; } dest_width *= s->cols; - pallette = s->pallette; - base = s->upbase; - /* HACK: Arm aliases physical memory at 0x80000000. */ - if (base > 0x80000000) - base -= 0x80000000; - src = phys_ram_base + base; - dest = ds_get_data(s->ds); - first = -1; - addr = base; - - dirty = cpu_physical_memory_get_dirty(addr, VGA_DIRTY_FLAG); - new_dirty = dirty; - for (i = 0; i < s->rows; i++) { - if ((addr & ~TARGET_PAGE_MASK) + src_width >= TARGET_PAGE_SIZE) { - uint32_t tmp; - new_dirty = 0; - for (tmp = 0; tmp < src_width; tmp += TARGET_PAGE_SIZE) { - new_dirty |= cpu_physical_memory_get_dirty(addr + tmp, - VGA_DIRTY_FLAG); - } - } - - if (dirty || new_dirty || s->invalidate) { - fn(pallette, dest, src, s->cols); - if (first == -1) - first = i; - last = i; - } - dirty = new_dirty; - addr += src_width; - dest += dest_width; - src += src_width; + first = 0; + framebuffer_update_display(s->ds, + s->upbase, s->cols, s->rows, + src_width, dest_width, 0, + s->invalidate, + fn, s->pallette, + &first, &last); + if (first >= 0) { + dpy_update(s->ds, 0, first, s->cols, last - first + 1); } - if (first < 0) - return; - s->invalidate = 0; - cpu_physical_memory_reset_dirty(base + first * src_width, - base + (last + 1) * src_width, - VGA_DIRTY_FLAG); - dpy_update(s->ds, 0, first, s->cols, last - first + 1); } static void pl110_invalidate_display(void * opaque) diff --git a/hw/pl110_template.h b/hw/pl110_template.h index 33483c0..5b5f475 100644 --- a/hw/pl110_template.h +++ b/hw/pl110_template.h @@ -115,8 +115,9 @@ static drawfn glue(pl110_draw_fn_,BITS)[36] = #define FN_4(x, y) FN_2(x, y) FN_2(x+2, y) #define FN_8(y) FN_4(0, y) FN_4(4, y) -static void glue(pl110_draw_line1_,NAME)(uint32_t *pallette, uint8_t *d, const uint8_t *src, int width) +static void glue(pl110_draw_line1_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep) { + uint32_t *pallette = opaque; uint32_t data; while (width > 0) { data = *(uint32_t *)src; @@ -142,8 +143,9 @@ static void glue(pl110_draw_line1_,NAME)(uint32_t *pallette, uint8_t *d, const u } } -static void glue(pl110_draw_line2_,NAME)(uint32_t *pallette, uint8_t *d, const uint8_t *src, int width) +static void glue(pl110_draw_line2_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep) { + uint32_t *pallette = opaque; uint32_t data; while (width > 0) { data = *(uint32_t *)src; @@ -169,8 +171,9 @@ static void glue(pl110_draw_line2_,NAME)(uint32_t *pallette, uint8_t *d, const u } } -static void glue(pl110_draw_line4_,NAME)(uint32_t *pallette, uint8_t *d, const uint8_t *src, int width) +static void glue(pl110_draw_line4_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep) { + uint32_t *pallette = opaque; uint32_t data; while (width > 0) { data = *(uint32_t *)src; @@ -196,8 +199,9 @@ static void glue(pl110_draw_line4_,NAME)(uint32_t *pallette, uint8_t *d, const u } } -static void glue(pl110_draw_line8_,NAME)(uint32_t *pallette, uint8_t *d, const uint8_t *src, int width) +static void glue(pl110_draw_line8_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep) { + uint32_t *pallette = opaque; uint32_t data; while (width > 0) { data = *(uint32_t *)src; @@ -219,7 +223,7 @@ static void glue(pl110_draw_line8_,NAME)(uint32_t *pallette, uint8_t *d, const u } } -static void glue(pl110_draw_line16_,NAME)(uint32_t *pallette, uint8_t *d, const uint8_t *src, int width) +static void glue(pl110_draw_line16_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep) { uint32_t data; unsigned int r, g, b; @@ -265,7 +269,7 @@ static void glue(pl110_draw_line16_,NAME)(uint32_t *pallette, uint8_t *d, const } } -static void glue(pl110_draw_line32_,NAME)(uint32_t *pallette, uint8_t *d, const uint8_t *src, int width) +static void glue(pl110_draw_line32_,NAME)(void *opaque, uint8_t *d, const uint8_t *src, int width, int deststep) { uint32_t data; unsigned int r, g, b; diff --git a/hw/pxa2xx_lcd.c b/hw/pxa2xx_lcd.c index 5c2eff1..49eafa7 100644 --- a/hw/pxa2xx_lcd.c +++ b/hw/pxa2xx_lcd.c @@ -13,8 +13,7 @@ #include "pixel_ops.h" /* FIXME: For graphic_rotate. Should probably be done in common code. */ #include "sysemu.h" - -typedef void (*drawfn)(uint32_t *, uint8_t *, const uint8_t *, int, int); +#include "framebuffer.h" struct pxa2xx_lcdc_s { qemu_irq irq; @@ -56,7 +55,7 @@ struct pxa2xx_lcdc_s { int up; uint8_t palette[1024]; uint8_t pbuffer[1024]; - void (*redraw)(struct pxa2xx_lcdc_s *s, uint8_t *fb, + void (*redraw)(struct pxa2xx_lcdc_s *s, target_phys_addr_t addr, int *miny, int *maxy); target_phys_addr_t descriptor; @@ -669,18 +668,15 @@ static void pxa2xx_palette_parse(struct pxa2xx_lcdc_s *s, int ch, int bpp) } static void pxa2xx_lcdc_dma0_redraw_horiz(struct pxa2xx_lcdc_s *s, - uint8_t *fb, int *miny, int *maxy) + target_phys_addr_t addr, int *miny, int *maxy) { - int y, src_width, dest_width, dirty[2]; - uint8_t *src, *dest; - ram_addr_t x, addr, new_addr, start, end; + int src_width, dest_width; drawfn fn = 0; if (s->dest_width) fn = s->line_fn[s->transp][s->bpp]; if (!fn) return; - src = fb; src_width = (s->xres + 3) & ~3; /* Pad to a 4 pixels multiple */ if (s->bpp == pxa_lcdc_19pbpp || s->bpp == pxa_lcdc_18pbpp) src_width *= 3; @@ -689,54 +685,25 @@ static void pxa2xx_lcdc_dma0_redraw_horiz(struct pxa2xx_lcdc_s *s, else if (s->bpp > pxa_lcdc_8bpp) src_width *= 2; - dest = ds_get_data(s->ds); dest_width = s->xres * s->dest_width; - - addr = (ram_addr_t) (fb - phys_ram_base); - start = addr + s->yres * src_width; - end = addr; - dirty[0] = dirty[1] = cpu_physical_memory_get_dirty(addr, VGA_DIRTY_FLAG); - for (y = 0; y < s->yres; y ++) { - new_addr = addr + src_width; - for (x = addr + TARGET_PAGE_SIZE; x < new_addr; - x += TARGET_PAGE_SIZE) { - dirty[1] = cpu_physical_memory_get_dirty(x, VGA_DIRTY_FLAG); - dirty[0] |= dirty[1]; - } - if (dirty[0] || s->invalidated) { - fn((uint32_t *) s->dma_ch[0].palette, - dest, src, s->xres, s->dest_width); - if (addr < start) - start = addr; - end = new_addr; - if (y < *miny) - *miny = y; - if (y >= *maxy) - *maxy = y + 1; - } - addr = new_addr; - dirty[0] = dirty[1]; - src += src_width; - dest += dest_width; - } - - if (end > start) - cpu_physical_memory_reset_dirty(start, end, VGA_DIRTY_FLAG); + *miny = 0; + framebuffer_update_display(s->ds, + addr, s->xres, s->yres, + src_width, dest_width, s->dest_width, + s->invalidated, + fn, s->dma_ch[0].palette, miny, maxy); } static void pxa2xx_lcdc_dma0_redraw_vert(struct pxa2xx_lcdc_s *s, - uint8_t *fb, int *miny, int *maxy) + target_phys_addr_t addr, int *miny, int *maxy) { - int y, src_width, dest_width, dirty[2]; - uint8_t *src, *dest; - ram_addr_t x, addr, new_addr, start, end; + int src_width, dest_width; drawfn fn = 0; if (s->dest_width) fn = s->line_fn[s->transp][s->bpp]; if (!fn) return; - src = fb; src_width = (s->xres + 3) & ~3; /* Pad to a 4 pixels multiple */ if (s->bpp == pxa_lcdc_19pbpp || s->bpp == pxa_lcdc_18pbpp) src_width *= 3; @@ -746,38 +713,13 @@ static void pxa2xx_lcdc_dma0_redraw_vert(struct pxa2xx_lcdc_s *s, src_width *= 2; dest_width = s->yres * s->dest_width; - dest = ds_get_data(s->ds) + dest_width * (s->xres - 1); - - addr = (ram_addr_t) (fb - phys_ram_base); - start = addr + s->yres * src_width; - end = addr; - x = addr + TARGET_PAGE_SIZE; - dirty[0] = dirty[1] = cpu_physical_memory_get_dirty(start, VGA_DIRTY_FLAG); - for (y = 0; y < s->yres; y ++) { - new_addr = addr + src_width; - for (; x < new_addr; x += TARGET_PAGE_SIZE) { - dirty[1] = cpu_physical_memory_get_dirty(x, VGA_DIRTY_FLAG); - dirty[0] |= dirty[1]; - } - if (dirty[0] || s->invalidated) { - fn((uint32_t *) s->dma_ch[0].palette, - dest, src, s->xres, -dest_width); - if (addr < start) - start = addr; - end = new_addr; - if (y < *miny) - *miny = y; - if (y >= *maxy) - *maxy = y + 1; - } - addr = new_addr; - dirty[0] = dirty[1]; - src += src_width; - dest += s->dest_width; - } - - if (end > start) - cpu_physical_memory_reset_dirty(start, end, VGA_DIRTY_FLAG); + *miny = 0; + framebuffer_update_display(s->ds, + addr, s->xres, s->yres, + src_width, s->dest_width, -dest_width, + s->invalidated, + fn, s->dma_ch[0].palette, + miny, maxy); } static void pxa2xx_lcdc_resize(struct pxa2xx_lcdc_s *s) @@ -803,7 +745,6 @@ static void pxa2xx_lcdc_resize(struct pxa2xx_lcdc_s *s) static void pxa2xx_update_display(void *opaque) { struct pxa2xx_lcdc_s *s = (struct pxa2xx_lcdc_s *) opaque; - uint8_t *fb; target_phys_addr_t fbptr; int miny, maxy; int ch; @@ -829,13 +770,11 @@ static void pxa2xx_update_display(void *opaque) pxa2xx_dma_ber_set(s, ch); continue; } - fbptr -= PXA2XX_SDRAM_BASE; - fb = phys_ram_base + fbptr; if (s->dma_ch[ch].command & LDCMD_PAL) { - memcpy(s->dma_ch[ch].pbuffer, fb, - MAX(LDCMD_LENGTH(s->dma_ch[ch].command), - sizeof(s->dma_ch[ch].pbuffer))); + cpu_physical_memory_read(fbptr, s->dma_ch[ch].pbuffer, + MAX(LDCMD_LENGTH(s->dma_ch[ch].command), + sizeof(s->dma_ch[ch].pbuffer))); pxa2xx_palette_parse(s, ch, s->bpp); } else { /* Do we need to reparse palette */ @@ -845,7 +784,7 @@ static void pxa2xx_update_display(void *opaque) /* ACK frame start */ pxa2xx_dma_sof_set(s, ch); - s->dma_ch[ch].redraw(s, fb, &miny, &maxy); + s->dma_ch[ch].redraw(s, fbptr, &miny, &maxy); s->invalidated = 0; /* ACK frame completed */ @@ -859,10 +798,12 @@ static void pxa2xx_update_display(void *opaque) s->status[0] |= LCSR0_LDD; } - if (s->orientation) - dpy_update(s->ds, miny, 0, maxy, s->xres); - else - dpy_update(s->ds, 0, miny, s->xres, maxy); + if (miny >= 0) { + if (s->orientation) + dpy_update(s->ds, miny, 0, maxy, s->xres); + else + dpy_update(s->ds, 0, miny, s->xres, maxy); + } pxa2xx_lcdc_int_update(s); qemu_irq_raise(s->vsync_cb); diff --git a/hw/pxa2xx_template.h b/hw/pxa2xx_template.h index 903df7b..35312ec 100644 --- a/hw/pxa2xx_template.h +++ b/hw/pxa2xx_template.h @@ -30,9 +30,10 @@ #define FN_2(x) FN(x + 1) FN(x) #define FN_4(x) FN_2(x + 2) FN_2(x) -static void glue(pxa2xx_draw_line2_, BITS)(uint32_t *palette, +static void glue(pxa2xx_draw_line2_, BITS)(void *opaque, uint8_t *dest, const uint8_t *src, int width, int deststep) { + uint32_t *palette = opaque; uint32_t data; while (width > 0) { data = *(uint32_t *) src; @@ -54,9 +55,10 @@ static void glue(pxa2xx_draw_line2_, BITS)(uint32_t *palette, } } -static void glue(pxa2xx_draw_line4_, BITS)(uint32_t *palette, +static void glue(pxa2xx_draw_line4_, BITS)(void *opaque, uint8_t *dest, const uint8_t *src, int width, int deststep) { + uint32_t *palette = opaque; uint32_t data; while (width > 0) { data = *(uint32_t *) src; @@ -78,9 +80,10 @@ static void glue(pxa2xx_draw_line4_, BITS)(uint32_t *palette, } } -static void glue(pxa2xx_draw_line8_, BITS)(uint32_t *palette, +static void glue(pxa2xx_draw_line8_, BITS)(void *opaque, uint8_t *dest, const uint8_t *src, int width, int deststep) { + uint32_t *palette = opaque; uint32_t data; while (width > 0) { data = *(uint32_t *) src; @@ -102,7 +105,7 @@ static void glue(pxa2xx_draw_line8_, BITS)(uint32_t *palette, } } -static void glue(pxa2xx_draw_line16_, BITS)(uint32_t *palette, +static void glue(pxa2xx_draw_line16_, BITS)(void *opaque, uint8_t *dest, const uint8_t *src, int width, int deststep) { uint32_t data; @@ -130,7 +133,7 @@ static void glue(pxa2xx_draw_line16_, BITS)(uint32_t *palette, } } -static void glue(pxa2xx_draw_line16t_, BITS)(uint32_t *palette, +static void glue(pxa2xx_draw_line16t_, BITS)(void *opaque, uint8_t *dest, const uint8_t *src, int width, int deststep) { uint32_t data; @@ -166,7 +169,7 @@ static void glue(pxa2xx_draw_line16t_, BITS)(uint32_t *palette, } } -static void glue(pxa2xx_draw_line18_, BITS)(uint32_t *palette, +static void glue(pxa2xx_draw_line18_, BITS)(void *opaque, uint8_t *dest, const uint8_t *src, int width, int deststep) { uint32_t data; @@ -188,7 +191,7 @@ static void glue(pxa2xx_draw_line18_, BITS)(uint32_t *palette, } /* The wicked packed format */ -static void glue(pxa2xx_draw_line18p_, BITS)(uint32_t *palette, +static void glue(pxa2xx_draw_line18p_, BITS)(void *opaque, uint8_t *dest, const uint8_t *src, int width, int deststep) { uint32_t data[3]; @@ -236,7 +239,7 @@ static void glue(pxa2xx_draw_line18p_, BITS)(uint32_t *palette, } } -static void glue(pxa2xx_draw_line19_, BITS)(uint32_t *palette, +static void glue(pxa2xx_draw_line19_, BITS)(void *opaque, uint8_t *dest, const uint8_t *src, int width, int deststep) { uint32_t data; @@ -262,7 +265,7 @@ static void glue(pxa2xx_draw_line19_, BITS)(uint32_t *palette, } /* The wicked packed format */ -static void glue(pxa2xx_draw_line19p_, BITS)(uint32_t *palette, +static void glue(pxa2xx_draw_line19p_, BITS)(void *opaque, uint8_t *dest, const uint8_t *src, int width, int deststep) { uint32_t data[3]; @@ -326,7 +329,7 @@ static void glue(pxa2xx_draw_line19p_, BITS)(uint32_t *palette, } } -static void glue(pxa2xx_draw_line24_, BITS)(uint32_t *palette, +static void glue(pxa2xx_draw_line24_, BITS)(void *opaque, uint8_t *dest, const uint8_t *src, int width, int deststep) { uint32_t data; @@ -347,7 +350,7 @@ static void glue(pxa2xx_draw_line24_, BITS)(uint32_t *palette, } } -static void glue(pxa2xx_draw_line24t_, BITS)(uint32_t *palette, +static void glue(pxa2xx_draw_line24t_, BITS)(void *opaque, uint8_t *dest, const uint8_t *src, int width, int deststep) { uint32_t data; @@ -372,7 +375,7 @@ static void glue(pxa2xx_draw_line24t_, BITS)(uint32_t *palette, } } -static void glue(pxa2xx_draw_line25_, BITS)(uint32_t *palette, +static void glue(pxa2xx_draw_line25_, BITS)(void *opaque, uint8_t *dest, const uint8_t *src, int width, int deststep) { uint32_t data; -- 1.7.9.5