Add damage tracking to GLX_EXT_tfp implementation.
- Only update when pixmap content actually change; - Only update the regions that acutally changed. This is a worthwhile optimization, but it doesn't completely remove the bottleneck, as mesa still uploads then entire texture whenever it changes.
This commit is contained in:
parent
adfe8e7437
commit
54d9acd511
|
@ -1263,6 +1263,7 @@ int DoCreateGLXPixmap(__GLXclientState *cl, VisualID visual,
|
||||||
pGlxPixmap->pGlxScreen = pGlxScreen;
|
pGlxPixmap->pGlxScreen = pGlxScreen;
|
||||||
pGlxPixmap->pScreen = pScreen;
|
pGlxPixmap->pScreen = pScreen;
|
||||||
pGlxPixmap->idExists = True;
|
pGlxPixmap->idExists = True;
|
||||||
|
pGlxPixmap->pDamage = NULL;
|
||||||
pGlxPixmap->refcnt = 0;
|
pGlxPixmap->refcnt = 0;
|
||||||
|
|
||||||
pGlxPixmap->modes = modes;
|
pGlxPixmap->modes = modes;
|
||||||
|
|
|
@ -41,6 +41,8 @@
|
||||||
**
|
**
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <damage.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|
||||||
DrawablePtr pDraw;
|
DrawablePtr pDraw;
|
||||||
|
@ -49,7 +51,7 @@ typedef struct {
|
||||||
ScreenPtr pScreen;
|
ScreenPtr pScreen;
|
||||||
Bool idExists;
|
Bool idExists;
|
||||||
int refcnt;
|
int refcnt;
|
||||||
|
DamagePtr pDamage;
|
||||||
} __GLXpixmap;
|
} __GLXpixmap;
|
||||||
|
|
||||||
struct __GLXdrawable {
|
struct __GLXdrawable {
|
||||||
|
|
138
GL/glx/glxdri.c
138
GL/glx/glxdri.c
|
@ -296,24 +296,18 @@ glxCountBits(int word)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
glxFillAlphaChannel (PixmapPtr pixmap)
|
glxFillAlphaChannel (PixmapPtr pixmap, int x, int y, int width, int height)
|
||||||
{
|
{
|
||||||
int i, j;
|
int i;
|
||||||
CARD32 *pixels = (CARD32 *)pixmap->devPrivate.ptr;
|
CARD32 *p, *end, *pixels = (CARD32 *)pixmap->devPrivate.ptr;
|
||||||
CARD32 rowstride = pixmap->devKind / 4;
|
CARD32 rowstride = pixmap->devKind / 4;
|
||||||
CARD32 x, y;
|
|
||||||
|
|
||||||
x = pixmap->drawable.x;
|
|
||||||
y = pixmap->drawable.y;
|
|
||||||
|
|
||||||
for (i = y; i < pixmap->drawable.height + y; ++i)
|
for (i = y; i < y + height; i++)
|
||||||
{
|
{
|
||||||
for (j = x; j < pixmap->drawable.width + x; ++j)
|
p = &pixels[i * rowstride + x];
|
||||||
{
|
end = p + width;
|
||||||
int index = i * rowstride + j;
|
while (p < end)
|
||||||
|
*p++ |= 0xFF000000;
|
||||||
pixels[index] |= 0xFF000000;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,7 +320,6 @@ glxFillAlphaChannel (PixmapPtr pixmap)
|
||||||
* - No fbconfig handling for TEXTURE_TARGET
|
* - No fbconfig handling for TEXTURE_TARGET
|
||||||
* - No fbconfig exposure of Y inversion state
|
* - No fbconfig exposure of Y inversion state
|
||||||
* - No GenerateMipmapEXT support (due to no FBO support)
|
* - No GenerateMipmapEXT support (due to no FBO support)
|
||||||
* - No damage tracking between binds
|
|
||||||
* - No support for anything but 16bpp and 32bpp-sparse pixmaps
|
* - No support for anything but 16bpp and 32bpp-sparse pixmaps
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -335,38 +328,103 @@ __glXDRIbindTexImage(__GLXcontext *baseContext,
|
||||||
int buffer,
|
int buffer,
|
||||||
__GLXpixmap *glxPixmap)
|
__GLXpixmap *glxPixmap)
|
||||||
{
|
{
|
||||||
|
RegionPtr pRegion;
|
||||||
PixmapPtr pixmap;
|
PixmapPtr pixmap;
|
||||||
int bpp;
|
int bpp;
|
||||||
Bool npot;
|
GLenum target, format, type;
|
||||||
|
|
||||||
pixmap = (PixmapPtr) glxPixmap->pDraw;
|
pixmap = (PixmapPtr) glxPixmap->pDraw;
|
||||||
bpp = pixmap->drawable.depth >= 24 ? 4 : 2; /* XXX 24bpp packed, 8, etc */
|
if (!glxPixmap->pDamage) {
|
||||||
|
glxPixmap->pDamage = DamageCreate(NULL, NULL, DamageReportNone,
|
||||||
|
TRUE, glxPixmap->pScreen, NULL);
|
||||||
|
if (!glxPixmap->pDamage)
|
||||||
|
return BadAlloc;
|
||||||
|
|
||||||
|
DamageRegister ((DrawablePtr) pixmap, glxPixmap->pDamage);
|
||||||
|
pRegion = NULL;
|
||||||
|
} else {
|
||||||
|
pRegion = DamageRegion(glxPixmap->pDamage);
|
||||||
|
if (REGION_NIL(pRegion))
|
||||||
|
return Success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* XXX 24bpp packed, 8, etc */
|
||||||
|
if (pixmap->drawable.depth >= 24) {
|
||||||
|
bpp = 4;
|
||||||
|
format = GL_BGRA;
|
||||||
|
type = GL_UNSIGNED_BYTE;
|
||||||
|
} else {
|
||||||
|
bpp = 2;
|
||||||
|
format = GL_RGB;
|
||||||
|
type = GL_UNSIGNED_SHORT_5_6_5;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(glxCountBits(pixmap->drawable.width) == 1 &&
|
||||||
|
glxCountBits(pixmap->drawable.height) == 1)
|
||||||
|
/* || strstr(CALL_GetString(GL_EXTENSIONS,
|
||||||
|
"GL_ARB_texture_non_power_of_two")) */)
|
||||||
|
target = GL_TEXTURE_RECTANGLE_ARB;
|
||||||
|
else
|
||||||
|
target = GL_TEXTURE_2D;
|
||||||
|
|
||||||
CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_ROW_LENGTH,
|
CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_ROW_LENGTH,
|
||||||
pixmap->devKind / bpp) );
|
pixmap->devKind / bpp) );
|
||||||
CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_ROWS,
|
if (pRegion == NULL)
|
||||||
pixmap->drawable.y) );
|
{
|
||||||
CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_PIXELS,
|
if (pixmap->drawable.depth == 24)
|
||||||
pixmap->drawable.x) );
|
glxFillAlphaChannel(pixmap,
|
||||||
|
pixmap->drawable.x,
|
||||||
|
pixmap->drawable.y,
|
||||||
|
pixmap->drawable.width,
|
||||||
|
pixmap->drawable.height);
|
||||||
|
|
||||||
if (pixmap->drawable.depth == 24)
|
CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_PIXELS,
|
||||||
glxFillAlphaChannel(pixmap);
|
pixmap->drawable.x) );
|
||||||
|
CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_ROWS,
|
||||||
|
pixmap->drawable.y) );
|
||||||
|
|
||||||
npot = !(glxCountBits(pixmap->drawable.width) == 1 &&
|
CALL_TexImage2D( GET_DISPATCH(),
|
||||||
glxCountBits(pixmap->drawable.height) == 1) /* ||
|
(target,
|
||||||
strstr(CALL_GetString(GL_EXTENSIONS,
|
0,
|
||||||
"GL_ARB_texture_non_power_of_two")) */ ;
|
bpp == 4 ? 4 : 3,
|
||||||
|
pixmap->drawable.width,
|
||||||
CALL_TexImage2D( GET_DISPATCH(),
|
pixmap->drawable.height,
|
||||||
( npot ? GL_TEXTURE_RECTANGLE_ARB : GL_TEXTURE_2D,
|
0,
|
||||||
0,
|
format,
|
||||||
bpp == 4 ? 4 : 3,
|
type,
|
||||||
pixmap->drawable.width,
|
pixmap->devPrivate.ptr) );
|
||||||
pixmap->drawable.height,
|
} else {
|
||||||
0,
|
int i, numRects;
|
||||||
bpp == 4 ? GL_BGRA : GL_RGB,
|
BoxPtr p;
|
||||||
bpp == 4 ? GL_UNSIGNED_BYTE : GL_UNSIGNED_SHORT_5_6_5,
|
|
||||||
pixmap->devPrivate.ptr ) );
|
numRects = REGION_NUM_RECTS (pRegion);
|
||||||
|
p = REGION_RECTS (pRegion);
|
||||||
|
for (i = 0; i < numRects; i++)
|
||||||
|
{
|
||||||
|
if (pixmap->drawable.depth == 24)
|
||||||
|
glxFillAlphaChannel(pixmap,
|
||||||
|
pixmap->drawable.x + p[i].x1,
|
||||||
|
pixmap->drawable.y + p[i].y1,
|
||||||
|
p[i].x2 - p[i].x1,
|
||||||
|
p[i].y2 - p[i].y1);
|
||||||
|
|
||||||
|
CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_PIXELS,
|
||||||
|
pixmap->drawable.x + p[i].x1) );
|
||||||
|
CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_ROWS,
|
||||||
|
pixmap->drawable.y + p[i].y1) );
|
||||||
|
|
||||||
|
CALL_TexSubImage2D( GET_DISPATCH(),
|
||||||
|
(target,
|
||||||
|
0,
|
||||||
|
p[i].x1, p[i].y1,
|
||||||
|
p[i].x2 - p[i].x1, p[i].y2 - p[i].y1,
|
||||||
|
format,
|
||||||
|
type,
|
||||||
|
pixmap->devPrivate.ptr) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DamageEmpty(glxPixmap->pDamage);
|
||||||
|
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,6 +141,10 @@ static int PixmapGone(__GLXpixmap *pGlxPixmap, XID id)
|
||||||
|
|
||||||
pGlxPixmap->idExists = False;
|
pGlxPixmap->idExists = False;
|
||||||
if (!pGlxPixmap->refcnt) {
|
if (!pGlxPixmap->refcnt) {
|
||||||
|
if (pGlxPixmap->pDamage) {
|
||||||
|
DamageUnregister (pGlxPixmap->pDraw, pGlxPixmap->pDamage);
|
||||||
|
DamageDestroy(pGlxPixmap->pDamage);
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
** The DestroyPixmap routine should decrement the refcount and free
|
** The DestroyPixmap routine should decrement the refcount and free
|
||||||
** only if it's zero.
|
** only if it's zero.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user