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,