From d6955798489813ef77cca13cf5f5c67d49e6dece Mon Sep 17 00:00:00 2001 From: Eric Anholt Date: Fri, 10 Mar 2006 21:36:24 +0000 Subject: [PATCH] If fakexa is enabled, create a larger buffer in the Ximage, but keep the same width/height for front-buffer drawing. The fakexa code then uses this extra space for offscreen pixmaps. Note that this tones down the absurdity of fakexa's offscreen pixmap alignment requirements (odd alignment is too weird, so stick with "24", which is still strange but exists out there). It also fixes a couple of bugs in the fakexa implementation revealed by using offscreen pixmaps. --- ChangeLog | 15 +++++++++++++++ hw/kdrive/ephyr/ephyr.c | 16 ++++++++++++---- hw/kdrive/ephyr/ephyr_draw.c | 30 +++++------------------------- hw/kdrive/ephyr/hostx.c | 24 ++++++++++++++++++------ hw/kdrive/ephyr/hostx.h | 2 +- 5 files changed, 51 insertions(+), 36 deletions(-) diff --git a/ChangeLog b/ChangeLog index c238bb4d3..a549a58aa 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2006-03-10 Eric Anholt + + * hw/kdrive/ephyr/ephyr.c: (ephyrMapFramebuffer): + * hw/kdrive/ephyr/ephyr_draw.c: (ephyrPrepareComposite), + (ephyrDrawInit): + * hw/kdrive/ephyr/hostx.c: (hostx_screen_init): + * hw/kdrive/ephyr/hostx.h: + If fakexa is enabled, create a larger buffer in the Ximage, but keep + the same width/height for front-buffer drawing. The fakexa code then + uses this extra space for offscreen pixmaps. Note that this tones down + the absurdity of fakexa's offscreen pixmap alignment requirements (odd + alignment is too weird, so stick with "24", which is still strange but + exists out there). It also fixes a couple of bugs in the fakexa + implementation revealed by using offscreen pixmaps. + 2006-03-10 Eric Anholt * exa/exa.c: (exaPrepareAccess), (exaFinishAccess): diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c index d6b3a158c..a9ea0eb0c 100644 --- a/hw/kdrive/ephyr/ephyr.c +++ b/hw/kdrive/ephyr/ephyr.c @@ -199,6 +199,7 @@ ephyrMapFramebuffer (KdScreenInfo *screen) EphyrScrPriv *scrpriv = screen->driver; EphyrPriv *priv = screen->card->driver; KdMouseMatrix m; + int buffer_height; EPHYR_DBG(" screen->width: %d, screen->height: %d", screen->width, screen->height); @@ -210,11 +211,19 @@ ephyrMapFramebuffer (KdScreenInfo *screen) priv->bytes_per_line = ((screen->width * screen->fb[0].bitsPerPixel + 31) >> 5) << 2; /* point the framebuffer to the data in an XImage */ - priv->base = hostx_screen_init (screen->width, screen->height); + /* If fakexa is enabled, allocate a larger buffer so that fakexa has space to + * put offscreen pixmaps. + */ + if (ephyrFuncs.initAccel == NULL) + buffer_height = screen->height; + else + buffer_height = 3 * screen->height; + priv->base = hostx_screen_init (screen->width, screen->height, buffer_height); + screen->memory_base = (CARD8 *) (priv->base); - screen->memory_size = 0; - screen->off_screen_base = 0; + screen->memory_size = priv->bytes_per_line * buffer_height; + screen->off_screen_base = priv->bytes_per_line * screen->height; if ((scrpriv->randr & RR_Rotate_0) && !(scrpriv->randr & RR_Reflect_All)) { @@ -223,7 +232,6 @@ ephyrMapFramebuffer (KdScreenInfo *screen) screen->fb[0].byteStride = priv->bytes_per_line; screen->fb[0].pixelStride = screen->width; screen->fb[0].frameBuffer = (CARD8 *) (priv->base); - screen->off_screen_base = priv->bytes_per_line * screen->height; } else { diff --git a/hw/kdrive/ephyr/ephyr_draw.c b/hw/kdrive/ephyr/ephyr_draw.c index 03c2b2f36..6525183d6 100644 --- a/hw/kdrive/ephyr/ephyr_draw.c +++ b/hw/kdrive/ephyr/ephyr_draw.c @@ -42,8 +42,8 @@ #endif /* Use some oddball alignments, to expose issues in alignment handling in EXA. */ -#define EPHYR_OFFSET_ALIGN 11 -#define EPHYR_PITCH_ALIGN 9 +#define EPHYR_OFFSET_ALIGN 24 +#define EPHYR_PITCH_ALIGN 24 #define EPHYR_OFFSCREEN_SIZE (16 * 1024 * 1024) #define EPHYR_OFFSCREEN_BASE (1 * 1024 * 1024) @@ -194,7 +194,7 @@ ephyrPrepareComposite(int op, PicturePtr pSrcPicture, PicturePtr pMaskPicture, EphyrScrPriv *scrpriv = screen->driver; EphyrFakexaPriv *fakexa = scrpriv->fakexa; - op = op; + fakexa->op = op; fakexa->pSrcPicture = pSrcPicture; fakexa->pMaskPicture = pMaskPicture; fakexa->pDstPicture = pDstPicture; @@ -286,30 +286,10 @@ ephyrDrawInit(ScreenPtr pScreen) xfree(fakexa); return FALSE; } -#if 0 - /* Currently, EXA isn't ready for what we want to do here. We want one - * pointer to the framebuffer (which is set in exaMapFramebuffer) to be - * considered "in framebuffer", and a separate pointer to offscreen memory, - * which is also considered to be in framebuffer. The alternative would be - * to extend the XImage data area set up in hostx.c from exaMapFramebuffer, - * but that may be complicated. - */ - fakexa->exa->memoryBase = xalloc(EPHYR_OFFSCREEN_SIZE); - if (fakexa->exa->memoryBase == NULL) { - xfree(fakexa->exa); - xfree(fakexa); - return FALSE; - } - fakexa->exa->memorySize = EPHYR_OFFSCREEN_SIZE; - fakexa->exa->offScreenBase = EPHYR_OFFSCREEN_BASE; -#else - /* Tell EXA that there's a single framebuffer area, which happens to cover - * exactly what the front buffer is. - */ + fakexa->exa->memoryBase = screen->memory_base; - fakexa->exa->memorySize = screen->off_screen_base; + fakexa->exa->memorySize = screen->memory_size; fakexa->exa->offScreenBase = screen->off_screen_base; -#endif /* Since we statically link against EXA, we shouldn't have to be smart about * versioning. diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c index ca04c8bea..ae776a7eb 100644 --- a/hw/kdrive/ephyr/hostx.c +++ b/hw/kdrive/ephyr/hostx.c @@ -438,8 +438,20 @@ hostx_set_cmap_entry(unsigned char idx, HostX.cmap[idx] = (r << 16) | (g << 8) | (b); } +/** + * hostx_screen_init creates the XImage that will contain the front buffer of + * the ephyr screen, and possibly offscreen memory. + * + * @param width width of the screen + * @param height height of the screen + * @param buffer_height height of the rectangle to be allocated. + * + * hostx_screen_init() creates an XImage, using MIT-SHM if it's available. + * buffer_height can be used to create a larger offscreen buffer, which is used + * by fakexa for storing offscreen pixmap data. + */ void* -hostx_screen_init (int width, int height) +hostx_screen_init (int width, int height, int buffer_height) { int bitmap_pad; Bool shm_success = False; @@ -476,10 +488,10 @@ hostx_screen_init (int width, int height) { HostX.ximg = XShmCreateImage(HostX.dpy, HostX.visual, HostX.depth, ZPixmap, NULL, &HostX.shminfo, - width, height ); + width, buffer_height ); HostX.shminfo.shmid = shmget(IPC_PRIVATE, - HostX.ximg->bytes_per_line * height, + HostX.ximg->bytes_per_line * buffer_height, IPC_CREAT|0777); HostX.shminfo.shmaddr = HostX.ximg->data = shmat(HostX.shminfo.shmid, 0, 0); @@ -509,11 +521,11 @@ hostx_screen_init (int width, int height) HostX.depth, ZPixmap, 0, 0, width, - height, + buffer_height, bitmap_pad, 0); - HostX.ximg->data = malloc( HostX.ximg->bytes_per_line * height ); + HostX.ximg->data = malloc( HostX.ximg->bytes_per_line * buffer_height ); } @@ -548,7 +560,7 @@ hostx_screen_init (int width, int height) else { EPHYR_DBG("server bpp %i", HostX.server_depth>>3); - HostX.fb_data = malloc(width*height*(HostX.server_depth>>3)); + HostX.fb_data = malloc(width*buffer_height*(HostX.server_depth>>3)); return HostX.fb_data; } } diff --git a/hw/kdrive/ephyr/hostx.h b/hw/kdrive/ephyr/hostx.h index 9a4a8959d..d3f6da3d3 100644 --- a/hw/kdrive/ephyr/hostx.h +++ b/hw/kdrive/ephyr/hostx.h @@ -136,7 +136,7 @@ hostx_set_cmap_entry(unsigned char idx, unsigned char b); void* -hostx_screen_init (int width, int height); +hostx_screen_init (int width, int height, int buffer_height); void hostx_paint_rect(int sx, int sy,