Fix RENDER issues (bug #7555) and implement RENDER add/remove screen

support (bug #8485).
This commit is contained in:
James Steven Supancic III 2006-12-16 12:02:38 -05:00 committed by Kevin E Martin
parent c92f7bef54
commit a5fcf1e5e7
5 changed files with 188 additions and 36 deletions

View File

@ -1007,7 +1007,7 @@ dnl ---------------------------------------------------------------------------
dnl DMX DDX dnl DMX DDX
AC_MSG_CHECKING([whether to build Xdmx 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 if test "x$DMX" = xauto; then
DMX="$have_dmx" DMX="$have_dmx"
fi fi

View File

@ -1056,6 +1056,116 @@ static Bool dmxCompareScreens(DMXScreenInfo *new, DMXScreenInfo *old)
return TRUE; 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. */ /** Reattach previously detached back-end screen. */
int dmxAttachScreen(int idx, DMXScreenAttributesPtr attr) int dmxAttachScreen(int idx, DMXScreenAttributesPtr attr)
{ {
@ -1174,6 +1284,20 @@ int dmxAttachScreen(int idx, DMXScreenAttributesPtr attr)
/* Create window hierarchy (top down) */ /* Create window hierarchy (top down) */
dmxBECreateWindowTree(idx); 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 */ /* Refresh screen by generating exposure events for all windows */
dmxForceExposures(idx); dmxForceExposures(idx);
@ -1362,8 +1486,15 @@ static void dmxBEDestroyResources(pointer value, XID id, RESTYPE type,
#ifdef RENDER #ifdef RENDER
} else if ((type & TypeMask) == (PictureType & TypeMask)) { } else if ((type & TypeMask) == (PictureType & TypeMask)) {
PicturePtr pPict = value; 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); dmxBEFreePicture((PicturePtr)value);
}
} else if ((type & TypeMask) == (GlyphSetType & TypeMask)) { } else if ((type & TypeMask) == (GlyphSetType & TypeMask)) {
dmxBEFreeGlyphSet(pScreen, (GlyphSetPtr)value); dmxBEFreeGlyphSet(pScreen, (GlyphSetPtr)value);
#endif #endif

View File

@ -624,7 +624,7 @@ void InitOutput(ScreenInfo *pScreenInfo, int argc, char *argv[])
} }
/* Make sure that the command-line arguments are sane. */ /* 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 /* Currently it is not possible to support GLX and Render
* extensions with dynamic screen addition/removal due to the * extensions with dynamic screen addition/removal due to the
* state that each extension keeps, which cannot be restored. */ * state that each extension keeps, which cannot be restored. */

View File

@ -223,6 +223,36 @@ Bool dmxBEFreeGlyphSet(ScreenPtr pScreen, GlyphSetPtr glyphSet)
return FALSE; 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 /** 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 * 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 * 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); ret = dmxSaveRenderVector[stuff->renderReqType](client);
if (ret == Success) { if (ret == Success) {
int (*oldErrorHandler)(Display *, XErrorEvent *);
GlyphSetPtr glyphSet; GlyphSetPtr glyphSet;
dmxGlyphPrivPtr glyphPriv; dmxGlyphPrivPtr glyphPriv;
int i; int i;
PictFormatPtr pFmt;
XRenderPictFormat *pFormat;
/* Look up glyphSet that was just created ???? */ /* Look up glyphSet that was just created ???? */
/* Store glyphsets from backends in glyphSet->devPrivate ????? */ /* Store glyphsets from backends in glyphSet->devPrivate ????? */
@ -254,21 +281,16 @@ static int dmxProcRenderCreateGlyphSet(ClientPtr client)
MAXSCREENSALLOC_RETURN(glyphPriv->glyphSets, BadAlloc); MAXSCREENSALLOC_RETURN(glyphPriv->glyphSets, BadAlloc);
DMX_SET_GLYPH_PRIV(glyphSet, glyphPriv); DMX_SET_GLYPH_PRIV(glyphSet, glyphPriv);
pFmt = SecurityLookupIDByType(client, stuff->format, PictFormatType,
DixReadAccess);
oldErrorHandler = XSetErrorHandler(dmxGlyphErrorHandler);
for (i = 0; i < dmxNumScreens; i++) { for (i = 0; i < dmxNumScreens; i++) {
DMXScreenInfo *dmxScreen = &dmxScreens[i]; DMXScreenInfo *dmxScreen = &dmxScreens[i];
int beret;
if (!dmxScreen->beDisplay) { if (!dmxScreen->beDisplay) {
glyphPriv->glyphSets[i] = 0; glyphPriv->glyphSets[i] = 0;
continue; continue;
} }
pFormat = dmxFindFormat(dmxScreen, pFmt); if ((beret = dmxBECreateGlyphSet(i, glyphSet)) != Success) {
if (!pFormat) {
int j; int j;
/* Free the glyph sets we've allocated thus far */ /* Free the glyph sets we've allocated thus far */
@ -278,30 +300,9 @@ static int dmxProcRenderCreateGlyphSet(ClientPtr client)
/* Free the resource created by render */ /* Free the resource created by render */
FreeResource(stuff->gsid, RT_NONE); FreeResource(stuff->gsid, RT_NONE);
ret = BadMatch; return beret;
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;
} }
} }
XSetErrorHandler(oldErrorHandler);
} }
return ret; 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 /** Create a picture. This function handles the CreatePicture
* unwrapping/wrapping and calls dmxDoCreatePicture to actually create * unwrapping/wrapping and calls dmxDoCreatePicture to actually create
* the picture on the appropriate screen. */ * 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 /* The clip has already been changed into a region by the mi
* routine called above. * 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; RegionPtr pClip = pPicture->clientClip;
BoxPtr pBox = REGION_RECTS(pClip); BoxPtr pBox = REGION_RECTS(pClip);
int nBox = REGION_NUM_RECTS(pClip); int nBox = REGION_NUM_RECTS(pClip);

View File

@ -112,7 +112,9 @@ extern void dmxTriFan(CARD8 op,
INT16 xSrc, INT16 ySrc, INT16 xSrc, INT16 ySrc,
int npoint, xPointFixed *points); int npoint, xPointFixed *points);
extern int dmxBECreateGlyphSet(int idx, GlyphSetPtr glyphSet);
extern Bool dmxBEFreeGlyphSet(ScreenPtr pScreen, GlyphSetPtr glyphSet); extern Bool dmxBEFreeGlyphSet(ScreenPtr pScreen, GlyphSetPtr glyphSet);
extern int dmxBECreatePicture(PicturePtr pPicture);
extern Bool dmxBEFreePicture(PicturePtr pPicture); extern Bool dmxBEFreePicture(PicturePtr pPicture);
extern int dmxPictPrivateIndex; /**< Index for picture private data */ extern int dmxPictPrivateIndex; /**< Index for picture private data */