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:04:42 -05:00 committed by Kevin E Martin
parent 7d927a6f6a
commit c10663e9cc
5 changed files with 188 additions and 36 deletions

View File

@ -936,7 +936,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

View File

@ -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

View File

@ -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. */

View File

@ -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,
SecurityReadAccess);
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);

View File

@ -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 */