diff options
author | Felix Kuehling <[email protected]> | 2005-01-29 23:26:23 +0000 |
---|---|---|
committer | Felix Kuehling <[email protected]> | 2005-01-29 23:26:23 +0000 |
commit | 5ff53cb448aa8dcf752ceaa9eb47a7c8a9c3ab0c (patch) | |
tree | 24f35f6e6cb190f0b01f88ff47a2a205ba73d6b8 /src/mesa/drivers/dri/savage/savagetex.c | |
parent | 9ff3c49ef2390d79f6a0bdd03af54ae4b02ba3d2 (diff) |
* 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.
Diffstat (limited to 'src/mesa/drivers/dri/savage/savagetex.c')
-rw-r--r-- | src/mesa/drivers/dri/savage/savagetex.c | 186 |
1 files changed, 163 insertions, 23 deletions
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<<j)) + if (t->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; } |