From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LpTtY-0003K2-RL for qemu-devel@nongnu.org; Thu, 02 Apr 2009 16:52:16 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LpTtU-0003CU-Li for qemu-devel@nongnu.org; Thu, 02 Apr 2009 16:52:16 -0400 Received: from [199.232.76.173] (port=35252 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LpTtU-0003CQ-93 for qemu-devel@nongnu.org; Thu, 02 Apr 2009 16:52:12 -0400 Received: from mail-fx0-f169.google.com ([209.85.220.169]:39517) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1LpTtT-0001LV-RO for qemu-devel@nongnu.org; Thu, 02 Apr 2009 16:52:12 -0400 Received: by fxm17 with SMTP id 17so642025fxm.34 for ; Thu, 02 Apr 2009 13:52:09 -0700 (PDT) MIME-Version: 1.0 In-Reply-To: References: Date: Thu, 2 Apr 2009 21:52:09 +0100 Message-ID: Subject: Re: [Qemu-devel] [6965] Implement and use shared memory framebuffer device rendering reoutine. From: andrzej zaborowski Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org 2009/4/1 Paul Brook : > Revision: 6965 > =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0http://svn.sv.gnu.org/viewvc/?view=3Dre= v&root=3Dqemu&revision=3D6965 > Author: =C2=A0 pbrook > Date: =C2=A0 =C2=A0 2009-04-01 12:27:59 +0000 (Wed, 01 Apr 2009) > Log Message: > ----------- > Implement and use shared memory framebuffer device rendering reoutine. > Use DMA mapping API. > > Signed-off-by: Paul Brook > > Modified Paths: > -------------- > =C2=A0 =C2=A0trunk/Makefile.target > =C2=A0 =C2=A0trunk/hw/omap.h > =C2=A0 =C2=A0trunk/hw/omap_lcd_template.h > =C2=A0 =C2=A0trunk/hw/omap_lcdc.c > =C2=A0 =C2=A0trunk/hw/pl110.c > =C2=A0 =C2=A0trunk/hw/pl110_template.h > =C2=A0 =C2=A0trunk/hw/pxa2xx_lcd.c > =C2=A0 =C2=A0trunk/hw/pxa2xx_template.h > > Added Paths: > ----------- > =C2=A0 =C2=A0trunk/hw/framebuffer.c > =C2=A0 =C2=A0trunk/hw/framebuffer.h > > Modified: trunk/Makefile.target > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > --- trunk/Makefile.target =C2=A0 =C2=A0 =C2=A0 2009-04-01 11:43:02 UTC (r= ev 6964) > +++ trunk/Makefile.target =C2=A0 =C2=A0 =C2=A0 2009-04-01 12:27:59 UTC (r= ev 6965) > @@ -672,6 +672,7 @@ > =C2=A0OBJS+=3D tsc2005.o bt-hci-csr.o > =C2=A0OBJS+=3D mst_fpga.o mainstone.o > =C2=A0OBJS+=3D musicpal.o pflash_cfi02.o > +OBJS+=3D framebuffer.o > =C2=A0CPPFLAGS +=3D -DHAS_AUDIO > =C2=A0endif > =C2=A0ifeq ($(TARGET_BASE_ARCH), sh4) > > Added: trunk/hw/framebuffer.c > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > --- trunk/hw/framebuffer.c =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0(rev 0) > +++ trunk/hw/framebuffer.c =C2=A0 =C2=A0 =C2=A02009-04-01 12:27:59 UTC (r= ev 6965) > @@ -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: > + =C2=A0 - Do something similar for framebuffers with local ram > + =C2=A0 - Handle rotation here instead of hacking dest_pitch > + =C2=A0 - Use common pixel conversion routines instead of per-device dra= wfn > + =C2=A0 - 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. =C2=A0*/ > + > +void framebuffer_update_display( > + =C2=A0 =C2=A0DisplayState *ds, > + =C2=A0 =C2=A0target_phys_addr_t base, > + =C2=A0 =C2=A0int cols, /* Width in pixels. =C2=A0*/ > + =C2=A0 =C2=A0int rows, /* Leight in pixels. =C2=A0*/ > + =C2=A0 =C2=A0int src_width, /* Length of source line, in bytes. =C2=A0*= / > + =C2=A0 =C2=A0int dest_row_pitch, /* Bytes between adjacent horizontal o= utput pixels. =C2=A0*/ > + =C2=A0 =C2=A0int dest_col_pitch, /* Bytes between adjacent vertical out= put pixels. =C2=A0*/ > + =C2=A0 =C2=A0int invalidate, /* nonzero to redraw the whole image. =C2= =A0*/ > + =C2=A0 =C2=A0drawfn fn, > + =C2=A0 =C2=A0void *opaque, > + =C2=A0 =C2=A0int *first_row, /* Input and output. =C2=A0*/ > + =C2=A0 =C2=A0int *last_row /* Output only */) > +{ > + =C2=A0 =C2=A0target_phys_addr_t src_len; > + =C2=A0 =C2=A0uint8_t *dest; > + =C2=A0 =C2=A0uint8_t *src; > + =C2=A0 =C2=A0uint8_t *src_base; > + =C2=A0 =C2=A0int first, last =3D 0; > + =C2=A0 =C2=A0int dirty; > + =C2=A0 =C2=A0int i; > + =C2=A0 =C2=A0ram_addr_t addr; > + =C2=A0 =C2=A0ram_addr_t pd; > + =C2=A0 =C2=A0ram_addr_t pd2; > + > + =C2=A0 =C2=A0i =3D *first_row; > + =C2=A0 =C2=A0*first_row =3D -1; > + =C2=A0 =C2=A0src_len =3D src_width * rows; > + > + =C2=A0 =C2=A0if (kvm_enabled()) { > + =C2=A0 =C2=A0 =C2=A0 =C2=A0kvm_physical_sync_dirty_bitmap(base, src_len= ); > + =C2=A0 =C2=A0} > + =C2=A0 =C2=A0pd =3D cpu_get_physical_page_desc(base); > + =C2=A0 =C2=A0pd2 =3D cpu_get_physical_page_desc(base + src_len - 1); > + =C2=A0 =C2=A0/* We should reall check that this is a continuous ram reg= ion. > + =C2=A0 =C2=A0 =C2=A0 Instead we just check that the first and last page= s are > + =C2=A0 =C2=A0 =C2=A0 both ram, and the right distance apart. =C2=A0*/ > + =C2=A0 =C2=A0if ((pd & ~TARGET_PAGE_MASK) > IO_MEM_ROM > + =C2=A0 =C2=A0 =C2=A0 =C2=A0|| (pd2 & ~TARGET_PAGE_MASK) > IO_MEM_ROM) { > + =C2=A0 =C2=A0 =C2=A0 =C2=A0return; > + =C2=A0 =C2=A0} > + =C2=A0 =C2=A0pd =3D (pd & TARGET_PAGE_MASK) + (base & ~TARGET_PAGE_MASK= ); > + =C2=A0 =C2=A0if (((pd + src_len - 1) & TARGET_PAGE_MASK) !=3D (pd2 & TA= RGET_PAGE_MASK)) { > + =C2=A0 =C2=A0 =C2=A0 =C2=A0return; > + =C2=A0 =C2=A0} > + > + =C2=A0 =C2=A0src_base =3D cpu_physical_memory_map(base, &src_len, 0); > + =C2=A0 =C2=A0/* If we can't map the framebuffer then bail. =C2=A0We cou= ld try harder, > + =C2=A0 =C2=A0 =C2=A0 but it's not really worth it as dirty flag trackin= g will probably > + =C2=A0 =C2=A0 =C2=A0 already have failed above. =C2=A0*/ > + =C2=A0 =C2=A0if (!src_base) > + =C2=A0 =C2=A0 =C2=A0 =C2=A0return; > + =C2=A0 =C2=A0if (src_len !=3D src_width * rows) { > + =C2=A0 =C2=A0 =C2=A0 =C2=A0cpu_physical_memory_unmap(src_base, src_len,= 0, 0); > + =C2=A0 =C2=A0 =C2=A0 =C2=A0return; > + =C2=A0 =C2=A0} > + =C2=A0 =C2=A0src =3D src_base; > + =C2=A0 =C2=A0dest =3D ds_get_data(ds); > + =C2=A0 =C2=A0if (dest_col_pitch < 0) > + =C2=A0 =C2=A0 =C2=A0 =C2=A0dest -=3D dest_col_pitch * (cols - 1); > + =C2=A0 =C2=A0first =3D -1; > + =C2=A0 =C2=A0addr =3D pd; If we must use the map/unmap api for framebuffers (even though we know this memory is continuous in qemu) then we could map omly the region we determined is dirty. Cheers