diff options
author | James Steven Supancic III <arrummzen@arrummzen.net> | 2006-12-16 12:02:38 -0500 |
---|---|---|
committer | Kevin E Martin <kem@freedesktop.org> | 2006-12-16 12:02:38 -0500 |
commit | a5fcf1e5e7452c9be82f63b6c2be2a25c4109523 (patch) | |
tree | bfac1ca8563a7d455aa7dae8ec2156e56eebaf25 | |
parent | c92f7bef54fa737766d65fe32c200f405f39228c (diff) |
Fix RENDER issues (bug #7555) and implement RENDER add/remove screen
support (bug #8485).
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | hw/dmx/dmxextension.c | 133 | ||||
-rw-r--r-- | hw/dmx/dmxinit.c | 2 | ||||
-rw-r--r-- | hw/dmx/dmxpict.c | 85 | ||||
-rw-r--r-- | hw/dmx/dmxpict.h | 2 |
5 files changed, 188 insertions, 36 deletions
diff --git a/configure.ac b/configure.ac index 002be624c..491bdd511 100644 --- a/configure.ac +++ b/configure.ac @@ -1007,7 +1007,7 @@ dnl --------------------------------------------------------------------------- dnl DMX DDX AC_MSG_CHECKING([whether to build Xdmx DDX]) -PKG_CHECK_MODULES([DMXMODULES], [xmuu xext x11 xrender xfont xi dmxproto xau $XDMCP_MODULES], [have_dmx=yes], [have_dmx=no]) +PKG_CHECK_MODULES([DMXMODULES], [xmuu xext x11 xrender xfixes xfont xi dmxproto xau $XDMCP_MODULES], [have_dmx=yes], [have_dmx=no]) if test "x$DMX" = xauto; then DMX="$have_dmx" fi diff --git a/hw/dmx/dmxextension.c b/hw/dmx/dmxextension.c index efcaca457..c12973bd5 100644 --- a/hw/dmx/dmxextension.c +++ b/hw/dmx/dmxextension.c @@ -1056,6 +1056,116 @@ static Bool dmxCompareScreens(DMXScreenInfo *new, DMXScreenInfo *old) return TRUE; } +#ifdef RENDER +/** Restore Render's picture */ +static void dmxBERestoreRenderPict(pointer value, XID id, pointer n) +{ + PicturePtr pPicture = value; /* The picture */ + DrawablePtr pDraw = pPicture->pDrawable; /* The picture's drawable */ + int scrnNum = (int)n; + + if (pDraw->pScreen->myNum != scrnNum) { + /* Picture not on the screen we are restoring*/ + return; + } + + if (pDraw->type == DRAWABLE_PIXMAP) { + PixmapPtr pPixmap = (PixmapPtr)pDraw; + + /* Create and restore the pixmap drawable */ + dmxBECreatePixmap(pPixmap); + dmxBERestorePixmap(pPixmap); + } + + dmxBECreatePicture(pPicture); +} + +/** Restore Render's glyphs */ +static void dmxBERestoreRenderGlyph(pointer value, XID id, pointer n) +{ + GlyphSetPtr glyphSet = value; + int scrnNum = (int)n; + dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet); + DMXScreenInfo *dmxScreen = &dmxScreens[scrnNum]; + GlyphRefPtr table; + char *images; + Glyph *gids; + XGlyphInfo *glyphs; + char *pos; + int beret; + int len_images = 0; + int i; + int ctr; + + if (glyphPriv->glyphSets[scrnNum]) { + /* Only restore glyphs on the screen we are attaching */ + return; + } + + /* First we must create the glyph set on the backend. */ + if ((beret = dmxBECreateGlyphSet(scrnNum, glyphSet)) != Success) { + dmxLog(dmxWarning, + "\tdmxBERestoreRenderGlyph failed to create glyphset!\n"); + return; + } + + /* Now for the complex part, restore the glyph data */ + table = glyphSet->hash.table; + + /* We need to know how much memory to allocate for this part */ + for (i = 0; i < glyphSet->hash.hashSet->size; i++) { + GlyphRefPtr gr = &table[i]; + GlyphPtr gl = gr->glyph; + + if (!gl || gl == DeletedGlyph) continue; + len_images += gl->size - sizeof(gl->info); + } + + /* Now allocate the memory we need */ + images = ALLOCATE_LOCAL(len_images*sizeof(char)); + gids = ALLOCATE_LOCAL(glyphSet->hash.tableEntries*sizeof(Glyph)); + glyphs = ALLOCATE_LOCAL(glyphSet->hash.tableEntries*sizeof(XGlyphInfo)); + + memset(images, 0, len_images * sizeof(char)); + pos = images; + ctr = 0; + + /* Fill the allocated memory with the proper data */ + for (i = 0; i < glyphSet->hash.hashSet->size; i++) { + GlyphRefPtr gr = &table[i]; + GlyphPtr gl = gr->glyph; + + if (!gl || gl == DeletedGlyph) continue; + + /* First lets put the data into gids */ + gids[ctr] = gr->signature; + + /* Next do the glyphs data structures */ + glyphs[ctr].width = gl->info.width; + glyphs[ctr].height = gl->info.height; + glyphs[ctr].x = gl->info.x; + glyphs[ctr].y = gl->info.y; + glyphs[ctr].xOff = gl->info.xOff; + glyphs[ctr].yOff = gl->info.yOff; + + /* Copy the images from the DIX's data into the buffer */ + memcpy(pos, gl+1, gl->size - sizeof(gl->info)); + pos += gl->size - sizeof(gl->info); + ctr++; + } + + /* Now restore the glyph data */ + XRenderAddGlyphs(dmxScreen->beDisplay, glyphPriv->glyphSets[scrnNum], + gids,glyphs, glyphSet->hash.tableEntries, images, + len_images); + + /* Clean up */ + DEALLOCATE_LOCAL(len_images); + DEALLOCATE_LOCAL(gids); + DEALLOCATE_LOCAL(glyphs); +} +#endif + /** Reattach previously detached back-end screen. */ int dmxAttachScreen(int idx, DMXScreenAttributesPtr attr) { @@ -1174,6 +1284,20 @@ int dmxAttachScreen(int idx, DMXScreenAttributesPtr attr) /* Create window hierarchy (top down) */ dmxBECreateWindowTree(idx); +#ifdef RENDER + /* Restore the picture state for RENDER */ + for (i = currentMaxClients; --i >= 0; ) + if (clients[i]) + FindClientResourcesByType(clients[i],PictureType, + dmxBERestoreRenderPict,(pointer)idx); + + /* Restore the glyph state for RENDER */ + for (i = currentMaxClients; --i >= 0; ) + if (clients[i]) + FindClientResourcesByType(clients[i],GlyphSetType, + dmxBERestoreRenderGlyph,(pointer)idx); +#endif + /* Refresh screen by generating exposure events for all windows */ dmxForceExposures(idx); @@ -1362,8 +1486,15 @@ static void dmxBEDestroyResources(pointer value, XID id, RESTYPE type, #ifdef RENDER } else if ((type & TypeMask) == (PictureType & TypeMask)) { PicturePtr pPict = value; - if (pPict->pDrawable->pScreen->myNum == scrnNum) + if (pPict->pDrawable->pScreen->myNum == scrnNum) { + /* Free the pixmaps on the backend if needed */ + if (pPict->pDrawable->type == DRAWABLE_PIXMAP) { + PixmapPtr pPixmap = (PixmapPtr)(pPict->pDrawable); + dmxBESavePixmap(pPixmap); + dmxBEFreePixmap(pPixmap); + } dmxBEFreePicture((PicturePtr)value); + } } else if ((type & TypeMask) == (GlyphSetType & TypeMask)) { dmxBEFreeGlyphSet(pScreen, (GlyphSetPtr)value); #endif diff --git a/hw/dmx/dmxinit.c b/hw/dmx/dmxinit.c index 9c5356ed5..1d3689c40 100644 --- a/hw/dmx/dmxinit.c +++ b/hw/dmx/dmxinit.c @@ -624,7 +624,7 @@ void InitOutput(ScreenInfo *pScreenInfo, int argc, char *argv[]) } /* Make sure that the command-line arguments are sane. */ - if (dmxAddRemoveScreens && (!noRenderExtension || dmxGLXProxy)) { + if (dmxAddRemoveScreens && dmxGLXProxy) { /* Currently it is not possible to support GLX and Render * extensions with dynamic screen addition/removal due to the * state that each extension keeps, which cannot be restored. */ diff --git a/hw/dmx/dmxpict.c b/hw/dmx/dmxpict.c index 339692538..0f1782e51 100644 --- a/hw/dmx/dmxpict.c +++ b/hw/dmx/dmxpict.c @@ -223,6 +223,36 @@ Bool dmxBEFreeGlyphSet(ScreenPtr pScreen, GlyphSetPtr glyphSet) return FALSE; } +/** Create \a glyphSet on the backend screen number \a idx. */ +int dmxBECreateGlyphSet(int idx, GlyphSetPtr glyphSet) +{ + XRenderPictFormat *pFormat; + DMXScreenInfo *dmxScreen = &dmxScreens[idx]; + dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet); + PictFormatPtr pFmt = glyphSet->format; + int (*oldErrorHandler)(Display *, XErrorEvent *); + + pFormat = dmxFindFormat(dmxScreen, pFmt); + if (!pFormat) { + return BadMatch; + } + + dmxGlyphLastError = 0; + oldErrorHandler = XSetErrorHandler(dmxGlyphErrorHandler); + + /* Catch when this fails */ + glyphPriv->glyphSets[idx] + = XRenderCreateGlyphSet(dmxScreen->beDisplay, pFormat); + + XSetErrorHandler(oldErrorHandler); + + if (dmxGlyphLastError) { + return dmxGlyphLastError; + } + + return Success; +} + /** Create a Glyph Set on each screen. Save the glyphset ID from each * screen in the Glyph Set's private structure. Fail if the format * requested is not available or if the Glyph Set cannot be created on @@ -235,12 +265,9 @@ static int dmxProcRenderCreateGlyphSet(ClientPtr client) ret = dmxSaveRenderVector[stuff->renderReqType](client); if (ret == Success) { - int (*oldErrorHandler)(Display *, XErrorEvent *); GlyphSetPtr glyphSet; dmxGlyphPrivPtr glyphPriv; int i; - PictFormatPtr pFmt; - XRenderPictFormat *pFormat; /* Look up glyphSet that was just created ???? */ /* Store glyphsets from backends in glyphSet->devPrivate ????? */ @@ -254,21 +281,16 @@ static int dmxProcRenderCreateGlyphSet(ClientPtr client) MAXSCREENSALLOC_RETURN(glyphPriv->glyphSets, BadAlloc); DMX_SET_GLYPH_PRIV(glyphSet, glyphPriv); - pFmt = SecurityLookupIDByType(client, stuff->format, PictFormatType, - DixReadAccess); - - oldErrorHandler = XSetErrorHandler(dmxGlyphErrorHandler); - for (i = 0; i < dmxNumScreens; i++) { DMXScreenInfo *dmxScreen = &dmxScreens[i]; + int beret; if (!dmxScreen->beDisplay) { glyphPriv->glyphSets[i] = 0; continue; } - pFormat = dmxFindFormat(dmxScreen, pFmt); - if (!pFormat) { + if ((beret = dmxBECreateGlyphSet(i, glyphSet)) != Success) { int j; /* Free the glyph sets we've allocated thus far */ @@ -278,30 +300,9 @@ static int dmxProcRenderCreateGlyphSet(ClientPtr client) /* Free the resource created by render */ FreeResource(stuff->gsid, RT_NONE); - ret = BadMatch; - break; - } - - /* Catch when this fails */ - glyphPriv->glyphSets[i] - = XRenderCreateGlyphSet(dmxScreen->beDisplay, pFormat); - - if (dmxGlyphLastError) { - int j; - - /* Free the glyph sets we've allocated thus far */ - for (j = 0; j < i; j++) - dmxBEFreeGlyphSet(screenInfo.screens[j], glyphSet); - - /* Free the resource created by render */ - FreeResource(stuff->gsid, RT_NONE); - - ret = dmxGlyphLastError; - break; + return beret; } } - - XSetErrorHandler(oldErrorHandler); } return ret; @@ -753,6 +754,20 @@ void dmxCreatePictureList(WindowPtr pWindow) } } +/** Create \a pPicture on the backend. */ +int dmxBECreatePicture(PicturePtr pPicture) +{ + dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture); + + /* Create picutre on BE */ + pPictPriv->pict = dmxDoCreatePicture(pPicture); + + /* Flush changes to the backend server */ + dmxValidatePicture(pPicture, (1 << (CPLastBit+1)) - 1); + + return Success; +} + /** Create a picture. This function handles the CreatePicture * unwrapping/wrapping and calls dmxDoCreatePicture to actually create * the picture on the appropriate screen. */ @@ -853,7 +868,11 @@ int dmxChangePictureClip(PicturePtr pPicture, int clipType, /* The clip has already been changed into a region by the mi * routine called above. */ - if (pPicture->clientClip) { + if (clipType == CT_NONE) { + /* Disable clipping, show all */ + XFixesSetPictureClipRegion(dmxScreen->beDisplay, + pPictPriv->pict, 0, 0, None); + } else if (pPicture->clientClip) { RegionPtr pClip = pPicture->clientClip; BoxPtr pBox = REGION_RECTS(pClip); int nBox = REGION_NUM_RECTS(pClip); diff --git a/hw/dmx/dmxpict.h b/hw/dmx/dmxpict.h index 2ca04ed87..fe2a65959 100644 --- a/hw/dmx/dmxpict.h +++ b/hw/dmx/dmxpict.h @@ -112,7 +112,9 @@ extern void dmxTriFan(CARD8 op, INT16 xSrc, INT16 ySrc, int npoint, xPointFixed *points); +extern int dmxBECreateGlyphSet(int idx, GlyphSetPtr glyphSet); extern Bool dmxBEFreeGlyphSet(ScreenPtr pScreen, GlyphSetPtr glyphSet); +extern int dmxBECreatePicture(PicturePtr pPicture); extern Bool dmxBEFreePicture(PicturePtr pPicture); extern int dmxPictPrivateIndex; /**< Index for picture private data */ |