Use per-screen Pixmaps for glyphs

Instead of system-memory data which prevents accelerated
compositing of glyphs, (at least without forcing an upload
of the glyph data before compositing).
This commit is contained in:
Carl Worth 2007-08-01 15:48:30 -07:00
parent 19b3b1fd8f
commit a2af34d5a8
6 changed files with 127 additions and 139 deletions

View File

@ -50,6 +50,7 @@
#include "fboverlay.h" #include "fboverlay.h"
#ifdef RENDER #ifdef RENDER
#include "fbpict.h" #include "fbpict.h"
#include "glyphstr.h"
#endif #endif
#include "damage.h" #include "damage.h"

View File

@ -996,8 +996,6 @@ exaGlyphs (CARD8 op,
{ {
GCPtr pGC = NULL; GCPtr pGC = NULL;
int maxwidth = 0, maxheight = 0, i; int maxwidth = 0, maxheight = 0, i;
ExaMigrationRec pixmaps[1];
PixmapPtr pScratchPixmap = NULL;
x += list->xOff; x += list->xOff;
y += list->yOff; y += list->yOff;
@ -1021,37 +1019,9 @@ exaGlyphs (CARD8 op,
continue; continue;
} }
/* Create the (real) temporary pixmap to store the current glyph in */
pPixmap = (*pScreen->CreatePixmap) (pScreen, maxwidth, maxheight,
list->format->depth);
if (!pPixmap)
return;
/* Create a temporary picture to wrap the temporary pixmap, so it can be
* used as a source for Composite.
*/
component_alpha = NeedsComponent(list->format->format);
pPicture = CreatePicture (0, &pPixmap->drawable, list->format,
CPComponentAlpha, &component_alpha,
serverClient, &error);
if (!pPicture) {
(*pScreen->DestroyPixmap) (pPixmap);
return;
}
ValidatePicture(pPicture);
/* Give the temporary pixmap an initial kick towards the screen, so
* it'll stick there.
*/
pixmaps[0].as_dst = TRUE;
pixmaps[0].as_src = TRUE;
pixmaps[0].pPix = pPixmap;
exaDoMigration (pixmaps, 1, pExaScr->info->PrepareComposite != NULL);
while (n--) while (n--)
{ {
GlyphPtr glyph = *glyphs++; GlyphPtr glyph = *glyphs++;
pointer glyphdata = (pointer) (glyph + 1);
DrawablePtr pCmpDrw = (maskFormat ? pMask : pDst)->pDrawable; DrawablePtr pCmpDrw = (maskFormat ? pMask : pDst)->pDrawable;
x1 = x - glyph->info.x; x1 = x - glyph->info.x;
@ -1061,60 +1031,19 @@ exaGlyphs (CARD8 op,
(x1 + glyph->info.width) <= 0 || (y1 + glyph->info.height) <= 0) (x1 + glyph->info.width) <= 0 || (y1 + glyph->info.height) <= 0)
goto nextglyph; goto nextglyph;
(*pScreen->ModifyPixmapHeader) (pScratchPixmap, /* The glyph already has a pixmap waiting for us to use. */
glyph->info.width, pPixmap = GlyphPixmap (glyph)[pScreen->myNum];
glyph->info.height,
0, 0, -1, glyphdata);
/* Copy the glyph data into the proper pixmap instead of a fake. /* Create a temporary picture to wrap the pixmap, so it can be
* First we try to use UploadToScreen, if we can, then we fall back * used as a source for Composite.
* to a plain exaCopyArea in case of failure.
*/ */
if (pExaScr->info->UploadToScreen && component_alpha = NeedsComponent(list->format->format);
exaPixmapIsOffscreen(pPixmap) && pPicture = CreatePicture (0, &pPixmap->drawable, list->format,
(*pExaScr->info->UploadToScreen) (pPixmap, 0, 0, CPComponentAlpha, &component_alpha,
glyph->info.width, serverClient, &error);
glyph->info.height, if (!pPicture)
glyphdata, return;
PixmapBytePad(glyph->info.width, ValidatePicture(pPicture);
list->format->depth)))
{
exaMarkSync (pScreen);
} else {
/* Set up the scratch pixmap/GC for doing a CopyArea. */
if (pScratchPixmap == NULL) {
/* Get a scratch pixmap to wrap the original glyph data */
pScratchPixmap = GetScratchPixmapHeader (pScreen,
glyph->info.width,
glyph->info.height,
list->format->depth,
list->format->depth,
-1, glyphdata);
if (!pScratchPixmap) {
FreePicture(pPicture, 0);
(*pScreen->DestroyPixmap) (pPixmap);
return;
}
/* Get a scratch GC with which to copy the glyph data from
* scratch to temporary
*/
pGC = GetScratchGC (list->format->depth, pScreen);
ValidateGC (&pPixmap->drawable, pGC);
} else {
(*pScreen->ModifyPixmapHeader) (pScratchPixmap,
glyph->info.width,
glyph->info.height,
0, 0, -1, glyphdata);
pScratchPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
}
exaCopyArea (&pScratchPixmap->drawable, &pPixmap->drawable, pGC,
0, 0, glyph->info.width, glyph->info.height, 0, 0);
}
exaPixmapDirty (pPixmap, 0, 0,
glyph->info.width, glyph->info.height);
if (maskFormat) if (maskFormat)
{ {
@ -1134,6 +1063,8 @@ exaGlyphs (CARD8 op,
exaPixmapDirty(pDstPixmap, x1, y1, x1 + glyph->info.width, exaPixmapDirty(pDstPixmap, x1, y1, x1 + glyph->info.width,
y1 + glyph->info.height); y1 + glyph->info.height);
} }
FreePicture ((pointer) pPicture, 0);
nextglyph: nextglyph:
x += glyph->info.xOff; x += glyph->info.xOff;
y += glyph->info.yOff; y += glyph->info.yOff;
@ -1141,10 +1072,6 @@ nextglyph:
list++; list++;
if (pGC != NULL) if (pGC != NULL)
FreeScratchGC (pGC); FreeScratchGC (pGC);
FreePicture ((pointer) pPicture, 0);
(*pScreen->DestroyPixmap) (pPixmap);
if (pScratchPixmap != NULL)
FreeScratchPixmapHeader (pScratchPixmap);
} }
if (maskFormat) if (maskFormat)
{ {

View File

@ -571,9 +571,13 @@ FreeGlyph (GlyphPtr glyph, int format)
for (i = 0; i < screenInfo.numScreens; i++) for (i = 0; i < screenInfo.numScreens; i++)
{ {
ps = GetPictureScreenIfSet (screenInfo.screens[i]); ScreenPtr pScreen = screenInfo.screens[i];
(pScreen->DestroyPixmap) (GlyphPixmap (glyph)[i]);
ps = GetPictureScreenIfSet (pScreen);
if (ps) if (ps)
(*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph); (*ps->UnrealizeGlyph) (pScreen, glyph);
} }
if (glyph->devPrivates) if (glyph->devPrivates)
@ -665,7 +669,7 @@ AllocateGlyph (xGlyphInfo *gi, int fdepth)
GlyphPtr glyph; GlyphPtr glyph;
int i; int i;
size = gi->height * PixmapBytePad (gi->width, glyphDepths[fdepth]); size = screenInfo.numScreens * sizeof (PixmapPtr);
glyph = (GlyphPtr) xalloc (size + sizeof (GlyphRec)); glyph = (GlyphPtr) xalloc (size + sizeof (GlyphRec));
if (!glyph) if (!glyph)
return 0; return 0;
@ -685,27 +689,38 @@ AllocateGlyph (xGlyphInfo *gi, int fdepth)
for (i = 0; i < screenInfo.numScreens; i++) for (i = 0; i < screenInfo.numScreens; i++)
{ {
ps = GetPictureScreenIfSet (screenInfo.screens[i]); ScreenPtr pScreen = screenInfo.screens[i];
if (ps)
{
if (!(*ps->RealizeGlyph) (screenInfo.screens[i], glyph))
{
while (i--)
{
ps = GetPictureScreenIfSet (screenInfo.screens[i]);
if (ps)
(*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph);
}
if (glyph->devPrivates) GlyphPixmap (glyph)[i] = (pScreen->CreatePixmap) (pScreen,
xfree (glyph->devPrivates); gi->width, gi->height,
xfree (glyph); glyphDepths[fdepth]);
return 0; if (! GlyphPixmap (glyph)[i])
} goto bail;
ps = GetPictureScreenIfSet (pScreen);
if (! ps)
continue;
if (!(*ps->RealizeGlyph) (pScreen, glyph)) {
(pScreen->DestroyPixmap) (GlyphPixmap (glyph)[i]);
goto bail;
} }
} }
return glyph; return glyph;
bail:
while (i--)
{
ps = GetPictureScreenIfSet (screenInfo.screens[i]);
if (ps)
(*ps->UnrealizeGlyph) (screenInfo.screens[i], glyph);
}
if (glyph->devPrivates)
xfree (glyph->devPrivates);
xfree (glyph);
return 0;
} }
Bool Bool

View File

@ -44,9 +44,11 @@ typedef struct _Glyph {
unsigned char sha1[20]; unsigned char sha1[20];
CARD32 size; /* info + bitmap */ CARD32 size; /* info + bitmap */
xGlyphInfo info; xGlyphInfo info;
/* bits follow */ /* per-screen pixmaps follow */
} GlyphRec, *GlyphPtr; } GlyphRec, *GlyphPtr;
#define GlyphPixmap(glyph) ((PixmapPtr *) ((glyph) + 1))
typedef struct _GlyphRef { typedef struct _GlyphRef {
CARD32 signature; CARD32 signature;
GlyphPtr glyph; GlyphPtr glyph;

View File

@ -112,7 +112,7 @@ miGlyphs (CARD8 op,
GlyphListPtr list, GlyphListPtr list,
GlyphPtr *glyphs) GlyphPtr *glyphs)
{ {
PixmapPtr pPixmap = 0; PixmapPtr pPixmap;
PicturePtr pPicture; PicturePtr pPicture;
PixmapPtr pMaskPixmap = 0; PixmapPtr pMaskPixmap = 0;
PicturePtr pMask; PicturePtr pMask;
@ -166,7 +166,6 @@ miGlyphs (CARD8 op,
x = 0; x = 0;
y = 0; y = 0;
} }
pPicture = 0;
while (nlist--) while (nlist--)
{ {
x += list->xOff; x += list->xOff;
@ -175,28 +174,14 @@ miGlyphs (CARD8 op,
while (n--) while (n--)
{ {
glyph = *glyphs++; glyph = *glyphs++;
pPixmap = GlyphPixmap (glyph)[pScreen->myNum];
component_alpha = NeedsComponent(list->format->format);
pPicture = CreatePicture (0, &pPixmap->drawable, list->format,
CPComponentAlpha, &component_alpha,
serverClient, &error);
if (!pPicture) if (!pPicture)
{ return;
pPixmap = GetScratchPixmapHeader (pScreen, glyph->info.width, glyph->info.height,
list->format->depth,
list->format->depth,
0, (pointer) (glyph + 1));
if (!pPixmap)
return;
component_alpha = NeedsComponent(list->format->format);
pPicture = CreatePicture (0, &pPixmap->drawable, list->format,
CPComponentAlpha, &component_alpha,
serverClient, &error);
if (!pPicture)
{
FreeScratchPixmapHeader (pPixmap);
return;
}
}
(*pScreen->ModifyPixmapHeader) (pPixmap,
glyph->info.width, glyph->info.height,
0, 0, -1, (pointer) (glyph + 1));
pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
if (maskFormat) if (maskFormat)
{ {
CompositePicture (PictOpAdd, CompositePicture (PictOpAdd,
@ -224,17 +209,12 @@ miGlyphs (CARD8 op,
glyph->info.width, glyph->info.width,
glyph->info.height); glyph->info.height);
} }
FreePicture ((pointer) pPicture, 0);
x += glyph->info.xOff; x += glyph->info.xOff;
y += glyph->info.yOff; y += glyph->info.yOff;
} }
list++; list++;
if (pPicture)
{
FreeScratchPixmapHeader (pPixmap);
FreePicture ((pointer) pPicture, 0);
pPicture = 0;
pPixmap = 0;
}
} }
if (maskFormat) if (maskFormat)
{ {

View File

@ -1099,7 +1099,9 @@ ProcRenderAddGlyphs (ClientPtr client)
CARD8 *bits; CARD8 *bits;
int size; int size;
int err = BadAlloc; int err = BadAlloc;
int i; int i, screen;
PicturePtr pSrc = NULL, pDst = NULL;
PixmapPtr pSrcPix = NULL, pDstPix = NULL;
REQUEST_AT_LEAST_SIZE(xRenderAddGlyphsReq); REQUEST_AT_LEAST_SIZE(xRenderAddGlyphsReq);
glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client, glyphSet = (GlyphSetPtr) SecurityLookupIDByType (client,
@ -1164,7 +1166,62 @@ ProcRenderAddGlyphs (ClientPtr client)
goto bail; goto bail;
} }
memcpy ((CARD8 *) (glyph_new->glyph + 1), bits, size); for (screen = 0; screen < screenInfo.numScreens; screen++)
{
int width = gi[i].width;
int height = gi[i].height;
int depth = glyphSet->format->depth;
ScreenPtr pScreen;
int error;
pScreen = screenInfo.screens[screen];
pSrcPix = GetScratchPixmapHeader (pScreen,
width, height,
depth, depth,
-1, bits);
if (! pSrcPix)
{
err = BadAlloc;
goto bail;
}
pSrc = CreatePicture (0, &pSrcPix->drawable,
glyphSet->format, 0, NULL,
serverClient, &error);
if (! pSrc)
{
err = BadAlloc;
goto bail;
}
pDstPix = GlyphPixmap (glyph_new->glyph)[screen];
pDst = CreatePicture (0, &pDstPix->drawable,
glyphSet->format, 0, NULL,
serverClient, &error);
if (! pDst)
{
err = BadAlloc;
goto bail;
}
CompositePicture (PictOpSrc,
pSrc,
None,
pDst,
0, 0,
0, 0,
0, 0,
width, height);
FreePicture ((pointer) pSrc, 0);
pSrc = NULL;
FreePicture ((pointer) pDst, 0);
pDst = NULL;
FreeScratchPixmapHeader (pSrcPix);
pSrcPix = NULL;
}
memcpy (glyph_new->glyph->sha1, glyph_new->sha1, 20); memcpy (glyph_new->glyph->sha1, glyph_new->sha1, 20);
} }
@ -1192,6 +1249,12 @@ ProcRenderAddGlyphs (ClientPtr client)
Xfree (glyphsBase); Xfree (glyphsBase);
return client->noClientException; return client->noClientException;
bail: bail:
if (pSrc)
FreePicture ((pointer) pSrc, 0);
if (pDst)
FreePicture ((pointer) pDst, 0);
if (pSrcPix)
FreeScratchPixmapHeader (pSrcPix);
for (i = 0; i < nglyphs; i++) for (i = 0; i < nglyphs; i++)
if (glyphs[i].glyph && ! glyphs[i].found) if (glyphs[i].glyph && ! glyphs[i].found)
xfree (glyphs[i].glyph); xfree (glyphs[i].glyph);