From: Felix Kuehling Date: Sat, 29 Jan 2005 23:26:23 +0000 (+0000) Subject: * Fixed uploading of textures of certain sizes. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=5ff53cb448aa8dcf752ceaa9eb47a7c8a9c3ab0c;p=mesa.git * Fixed uploading of textures of certain sizes. * When glTexSubImageND is used, track the set of changed tiles in a bit vector and upload only dirty tiles later. This should improve the performance of dynamic light maps and gl movie player plugins. * Renamed debug item "lru" to "tex". Indicate which levels are uploaded completely or partially. --- diff --git a/src/mesa/drivers/dri/savage/savage_xmesa.c b/src/mesa/drivers/dri/savage/savage_xmesa.c index 2c31aefce11..171cbde90ef 100644 --- a/src/mesa/drivers/dri/savage/savage_xmesa.c +++ b/src/mesa/drivers/dri/savage/savage_xmesa.c @@ -100,7 +100,7 @@ static const struct dri_debug_control debug_control[] = { { "fall", DEBUG_FALLBACKS }, { "api", DEBUG_VERBOSE_API }, - { "lru", DEBUG_VERBOSE_LRU }, + { "tex", DEBUG_VERBOSE_TEX }, { "verb", DEBUG_VERBOSE_MSG }, { "dma", DEBUG_DMA }, { "state", DEBUG_STATE }, diff --git a/src/mesa/drivers/dri/savage/savagecontext.h b/src/mesa/drivers/dri/savage/savagecontext.h index 21385ed7ec4..b2d47a46939 100644 --- a/src/mesa/drivers/dri/savage/savagecontext.h +++ b/src/mesa/drivers/dri/savage/savagecontext.h @@ -313,7 +313,7 @@ extern int SAVAGE_DEBUG; #define DEBUG_FALLBACKS 0x001 #define DEBUG_VERBOSE_API 0x002 -#define DEBUG_VERBOSE_LRU 0x004 +#define DEBUG_VERBOSE_TEX 0x004 #define DEBUG_VERBOSE_MSG 0x008 #define DEBUG_DMA 0x010 #define DEBUG_STATE 0x020 diff --git a/src/mesa/drivers/dri/savage/savagetex.c b/src/mesa/drivers/dri/savage/savagetex.c index e6954a048ab..fd8bd0d1258 100644 --- a/src/mesa/drivers/dri/savage/savagetex.c +++ b/src/mesa/drivers/dri/savage/savagetex.c @@ -203,6 +203,9 @@ static void savageUploadTexLevel( savageTexObjPtr t, int level ) (int) image->Border); if (width >= 8 && height >= tileInfo->subHeight) { + GLuint *dirtyPtr = t->image[level].dirtyTiles; + GLuint dirtyMask = 1; + if (width >= tileInfo->width && height >= tileInfo->height) { GLuint wInTiles = width / tileInfo->width; GLuint hInTiles = height / tileInfo->height; @@ -212,14 +215,41 @@ static void savageUploadTexLevel( savageTexObjPtr t, int level ) for (y = 0; y < hInTiles; ++y) { src = srcTRow; for (x = 0; x < wInTiles; ++x) { - savageUploadTile (tileInfo, - tileInfo->wInSub, tileInfo->hInSub, bpp, - src, width * bpp, dest); + if (*dirtyPtr & dirtyMask) { + savageUploadTile (tileInfo, + tileInfo->wInSub, tileInfo->hInSub, + bpp, src, width * bpp, dest); + } src += tileInfo->width * bpp; dest += 2048; /* tile size is always 2k */ + if (dirtyMask == 1<<31) { + dirtyMask = 1; + dirtyPtr++; + } else + dirtyMask <<= 1; } srcTRow += width * tileInfo->height * bpp; } + } else if (width >= tileInfo->width) { + GLuint wInTiles = width / tileInfo->width; + GLubyte *src = image->Data; + GLubyte *dest = (GLubyte *)(t->bufAddr + t->image[level].offset); + GLuint x; + for (x = 0; x < wInTiles; ++x) { + if (*dirtyPtr & dirtyMask) { + savageUploadTile (tileInfo, + tileInfo->wInSub, + height / tileInfo->subHeight, + bpp, src, width * bpp, dest); + } + src += tileInfo->width * bpp; + dest += 2048; /* tile size is always 2k */ + if (dirtyMask == 1<<31) { + dirtyMask = 1; + dirtyPtr++; + } else + dirtyMask <<= 1; + } } else { savageUploadTile (tileInfo, width / tileInfo->subWidth, height / tileInfo->subHeight, bpp, @@ -270,6 +300,67 @@ static GLuint savageTexImageSize (GLuint width, GLuint height, GLuint bpp) { return 64 * bpp; } +/** \brief Compute the number of (partial) tiles of a texture image + */ +static GLuint savageTexImageTiles (GLuint width, GLuint height, + const savageTileInfo *tileInfo) +{ + return (width + tileInfo->width - 1) / tileInfo->width * + (height + tileInfo->height - 1) / tileInfo->height; +} + +/** \brief Mark dirty tiles + * + * Some care must be taken because tileInfo may not be set or not + * up-to-date. So we check if tileInfo is initialized and if the number + * of tiles in the bit vector matches the number of tiles computed from + * the current tileInfo. + */ +static void savageMarkDirtyTiles (savageTexObjPtr t, GLuint level, + GLuint totalWidth, GLuint totalHeight, + GLint xoffset, GLint yoffset, + GLsizei width, GLsizei height) +{ + GLuint wInTiles, hInTiles; + GLuint x0, y0, x1, y1; + GLuint x, y; + if (!t->tileInfo) + return; + wInTiles = (totalWidth + t->tileInfo->width - 1) / t->tileInfo->width; + hInTiles = (totalHeight + t->tileInfo->height - 1) / t->tileInfo->height; + if (wInTiles * hInTiles != t->image[level].nTiles) + return; + + x0 = xoffset / t->tileInfo->width; + y0 = yoffset / t->tileInfo->height; + x1 = (xoffset + width - 1) / t->tileInfo->width; + y1 = (yoffset + height - 1) / t->tileInfo->height; + + for (y = y0; y <= y1; ++y) { + GLuint *ptr = t->image[level].dirtyTiles + (y * wInTiles + x0) / 32; + GLuint mask = 1 << (y * wInTiles + x0) % 32; + for (x = x0; x <= x1; ++x) { + *ptr |= mask; + if (mask == (1<<31)) { + ptr++; + mask = 1; + } else { + mask <<= 1; + } + } + } +} + +/** \brief Mark all tiles as dirty + */ +static void savageMarkAllTiles (savageTexObjPtr t, GLuint level) +{ + GLuint words = (t->image[level].nTiles + 31) / 32; + if (words) + memset(t->image[level].dirtyTiles, ~0, words*sizeof(GLuint)); +} + + static void savageSetTexWrapping(savageTexObjPtr tex, GLenum s, GLenum t) { tex->setup.sWrapMode = s; @@ -301,10 +392,19 @@ savageAllocTexObj( struct gl_texture_object *texObj ) t = (savageTexObjPtr) calloc(1,sizeof(*t)); texObj->DriverData = t; if ( t != NULL ) { + GLuint i; /* Initialize non-image-dependent parts of the state: */ t->base.tObj = texObj; + t->base.dirty_images[0] = 0; + t->dirtySubImages = 0; + t->tileInfo = NULL; + + /* Initialize dirty tiles bit vectors + */ + for (i = 0; i < SAVAGE_TEX_MAXLEVELS; ++i) + t->image[i].nTiles = 0; /* FIXME Something here to set initial values for other parts of * FIXME t->setup? @@ -521,12 +621,27 @@ static void savageSetTexImages( savageContextPtr imesa, firstLevel = t->base.firstLevel; lastLevel = t->base.lastLevel; - /* Figure out the size now (and count the levels). Upload won't be done - * until later. + /* Figure out the size now (and count the levels). Upload won't be + * done until later. If the number of tiles changes, it means that + * this function is called for the first time on this tex object or + * the image or the destination color format changed. So all tiles + * are marked as dirty. */ offset = 0; size = 1; for ( i = firstLevel ; i <= lastLevel && tObj->Image[0][i] ; i++ ) { + GLuint nTiles; + nTiles = savageTexImageTiles (image->Width2, image->Height2, t->tileInfo); + if (t->image[i].nTiles != nTiles) { + GLuint words = (nTiles + 31) / 32; + if (t->image[i].nTiles != 0) { + free(t->image[i].dirtyTiles); + } + t->image[i].dirtyTiles = malloc(words*sizeof(GLuint)); + memset(t->image[i].dirtyTiles, ~0, words*sizeof(GLuint)); + } + t->image[i].nTiles = nTiles; + t->image[i].offset = offset; image = tObj->Image[0][i]; @@ -545,18 +660,24 @@ static void savageSetTexImages( savageContextPtr imesa, t->base.totalSize = (t->base.totalSize + 2047UL) & ~2047UL; } -void savageDestroyTexObj(savageContextPtr imesa, driTextureObject *t) +void savageDestroyTexObj(savageContextPtr imesa, savageTexObjPtr t) { + GLuint i; + + /* Free dirty tiles bit vectors */ + for (i = 0; i < SAVAGE_TEX_MAXLEVELS; ++i) { + if (t->image[i].nTiles) + free (t->image[i].dirtyTiles); + } + /* See if it was the driver's current object. */ - if ( imesa != NULL ) { - GLuint i; for ( i = 0 ; i < imesa->glCtx->Const.MaxTextureUnits ; i++ ) { - if ( t == imesa->CurrentTexObj[ i ] ) { - assert( t->bound & (1 << i) ); + if ( &t->base == imesa->CurrentTexObj[ i ] ) { + assert( t->base.bound & (1 << i) ); imesa->CurrentTexObj[ i ] = NULL; } } @@ -600,21 +721,36 @@ static void savageUploadTexImages( savageContextPtr imesa, savageTexObjPtr t ) driUpdateTextureLRU( &t->base ); UNLOCK_HARDWARE(imesa); - if (t->base.dirty_images[0]) { + if (t->base.dirty_images[0] || t->dirtySubImages) { + if (SAVAGE_DEBUG & DEBUG_VERBOSE_TEX) + fprintf(stderr, "Texture upload: |"); + savageFlushVertices (imesa); LOCK_HARDWARE(imesa); savageFlushCmdBufLocked (imesa, GL_FALSE); WAIT_IDLE_EMPTY_LOCKED(imesa); - if (SAVAGE_DEBUG & DEBUG_VERBOSE_LRU) - fprintf(stderr, "*"); for (i = 0 ; i < numLevels ; i++) { const GLint j = t->base.firstLevel + i; /* the texObj's level */ - if (t->base.dirty_images[0] & (1<base.dirty_images[0] & (1 << j)) { + savageMarkAllTiles(t, j); + if (SAVAGE_DEBUG & DEBUG_VERBOSE_TEX) + fprintf (stderr, "*"); + } else if ((SAVAGE_DEBUG & DEBUG_VERBOSE_TEX) && + t->dirtySubImages & (1 << j)) + fprintf (stderr, "."); + else + fprintf (stderr, " "); + if ((t->base.dirty_images[0] | t->dirtySubImages) & (1 << j)) savageUploadTexLevel( t, j ); } + UNLOCK_HARDWARE(imesa); t->base.dirty_images[0] = 0; + t->dirtySubImages = 0; + + if (SAVAGE_DEBUG & DEBUG_VERBOSE_TEX) + fprintf(stderr, "|\n"); } } @@ -657,7 +793,7 @@ static void savageUpdateTex0State_s4( GLcontext *ctx ) imesa->CurrentTexObj[0] = &t->base; t->base.bound |= 1; - if (t->base.dirty_images[0]) { + if (t->base.dirty_images[0] || t->dirtySubImages) { savageSetTexImages(imesa, tObj); savageUploadTexImages(imesa, t); } @@ -924,7 +1060,7 @@ static void savageUpdateTex1State_s4( GLcontext *ctx ) t->base.bound |= 2; - if (t->base.dirty_images[0]) { + if (t->base.dirty_images[0] || t->dirtySubImages) { savageSetTexImages(imesa, tObj); savageUploadTexImages(imesa, t); } @@ -1112,7 +1248,7 @@ static void savageUpdateTexState_s3d( GLcontext *ctx ) imesa->CurrentTexObj[0] = &t->base; t->base.bound |= 1; - if (t->base.dirty_images[0]) { + if (t->base.dirty_images[0] || t->dirtySubImages) { savageSetTexImages(imesa, tObj); savageUploadTexImages(imesa, t); } @@ -1292,7 +1428,7 @@ static void savageTexImage1D( GLcontext *ctx, GLenum target, GLint level, { savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData; if (t) { - driSwapOutTextureObject( &t->base ); + /* Do nothing. Marking the image as dirty below is sufficient. */ } else { t = savageAllocTexObj(texObj); if (!t) { @@ -1321,18 +1457,20 @@ static void savageTexSubImage1D( GLcontext *ctx, savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData; assert( t ); /* this _should_ be true */ if (t) { - driSwapOutTextureObject( &t->base ); + savageMarkDirtyTiles(t, level, texImage->Width2, 1, + xoffset, 0, width, 1); } else { t = savageAllocTexObj(texObj); if (!t) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D"); return; } + t->base.dirty_images[0] |= (1 << level); } _mesa_store_texsubimage1d(ctx, target, level, xoffset, width, format, type, pixels, packing, texObj, texImage); - t->base.dirty_images[0] |= (1 << level); + t->dirtySubImages |= (1 << level); SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE; } @@ -1346,7 +1484,7 @@ static void savageTexImage2D( GLcontext *ctx, GLenum target, GLint level, { savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData; if (t) { - driSwapOutTextureObject( &t->base ); + /* Do nothing. Marking the image as dirty below is sufficient. */ } else { t = savageAllocTexObj(texObj); if (!t) { @@ -1375,18 +1513,20 @@ static void savageTexSubImage2D( GLcontext *ctx, savageTexObjPtr t = (savageTexObjPtr) texObj->DriverData; assert( t ); /* this _should_ be true */ if (t) { - driSwapOutTextureObject( &t->base ); + savageMarkDirtyTiles(t, level, texImage->Width2, texImage->Height2, + xoffset, yoffset, width, height); } else { t = savageAllocTexObj(texObj); if (!t) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D"); return; } + t->base.dirty_images[0] |= (1 << level); } _mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width, height, format, type, pixels, packing, texObj, texImage); - t->base.dirty_images[0] |= (1 << level); + t->dirtySubImages |= (1 << level); SAVAGE_CONTEXT(ctx)->new_state |= SAVAGE_NEW_TEXTURE; } diff --git a/src/mesa/drivers/dri/savage/savagetex.h b/src/mesa/drivers/dri/savage/savagetex.h index a6732a3dce7..f0890373909 100644 --- a/src/mesa/drivers/dri/savage/savagetex.h +++ b/src/mesa/drivers/dri/savage/savagetex.h @@ -43,6 +43,7 @@ typedef struct savage_tileinfo_t { typedef struct { GLuint offset; + GLuint nTiles; GLuint *dirtyTiles; /* bit vector of dirty tiles (still unused) */ } savageTexImage; @@ -53,6 +54,7 @@ typedef struct { GLuint age; savageTexImage image[SAVAGE_TEX_MAXLEVELS]; + GLuint dirtySubImages; struct { GLuint sWrapMode, tWrapMode; @@ -76,6 +78,6 @@ typedef struct { void savageUpdateTextureState( GLcontext *ctx ); void savageDDInitTextureFuncs( struct dd_function_table *functions ); -void savageDestroyTexObj( savageContextPtr imesa, driTextureObject *t ); +void savageDestroyTexObj( savageContextPtr imesa, savageTexObjPtr t ); #endif