X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fdrivers%2Fdri%2Fcommon%2Ftexmem.c;h=8eec07d5bcc611494f5e9be6dd46b95afa41d4b4;hb=b922a0ce12916a91cfc3e56714913fcf63279ff2;hp=c76d3716822c79fa60514bbc635ec85f13111467;hpb=462183fe4cb6df6d90632d9e2cee881c8d26b1cb;p=mesa.git diff --git a/src/mesa/drivers/dri/common/texmem.c b/src/mesa/drivers/dri/common/texmem.c index c76d3716822..8eec07d5bcc 100644 --- a/src/mesa/drivers/dri/common/texmem.c +++ b/src/mesa/drivers/dri/common/texmem.c @@ -28,7 +28,6 @@ * Kevin E. Martin * Gareth Hughes */ -/* $XFree86:$ */ /** \file texmem.c * Implements all of the device-independent texture memory management. @@ -43,13 +42,10 @@ * application. */ +#include "main/imports.h" +#include "main/macros.h" +#include "main/simple_list.h" #include "texmem.h" -#include "simple_list.h" -#include "imports.h" -#include "macros.h" - -#include - static unsigned dummy_swap_counter; @@ -64,11 +60,10 @@ static unsigned dummy_swap_counter; * \param n Value whose \f$\log_2\f$ is to be calculated */ -static unsigned -driLog2( unsigned n ) +static GLuint +driLog2( GLuint n ) { - unsigned log2; - + GLuint log2; for ( log2 = 1 ; n > 1 ; log2++ ) { n >>= 1; @@ -94,7 +89,7 @@ driLog2( unsigned n ) */ GLboolean -driIsTextureResident( GLcontext * ctx, +driIsTextureResident( struct gl_context * ctx, struct gl_texture_object * texObj ) { driTextureObject * t; @@ -188,7 +183,7 @@ static void printLocalLRU( driTexHeap * heap, const char *callername ) static void printGlobalLRU( driTexHeap * heap, const char *callername ) { drmTextureRegionPtr list = heap->global_regions; - int i, j; + unsigned int i, j; fprintf( stderr, "%s in %s:\nGlobal LRU, heap %d list %p:\n", __FUNCTION__, callername, heap->heapId, (void *)list ); @@ -410,11 +405,12 @@ static void driTexturesGone( driTexHeap * heap, int offset, int size, fprintf( stderr, "Couldn't alloc placeholder: heap %u sz %x ofs %x\n", heap->heapId, (int)size, (int)offset ); mmDumpMemInfo( heap->memory_heap ); + FREE(t); return; } t->heap = heap; if (in_use) - t->bound = 99; + t->reserved = 1; insert_at_head( & heap->texture_objects, t ); } } @@ -477,6 +473,8 @@ void driAgeTextures( driTexHeap * heap ) +#define INDEX_ARRAY_SIZE 6 /* I'm not aware of driver with more than 2 heaps */ + /** * Allocate memory from a texture heap to hold a texture object. This * routine will attempt to allocate memory for the texture from the heaps @@ -528,35 +526,91 @@ driAllocateTexture( driTexHeap * const * heap_array, unsigned nr_heaps, */ if ( t->memBlock == NULL ) { - for ( id = 0 ; (t->memBlock == NULL) && (id < nr_heaps) ; id++ ) { - heap = heap_array[ id ]; - if ( t->totalSize <= heap->size ) { + unsigned index[INDEX_ARRAY_SIZE]; + unsigned nrGoodHeaps = 0; - for ( cursor = heap->texture_objects.prev, temp = cursor->prev; - cursor != &heap->texture_objects ; - cursor = temp, temp = cursor->prev ) { - - /* The the LRU element. If the texture is bound to one of - * the texture units, then we cannot kick it out. - */ - if ( cursor->bound /* || cursor->reserved */ ) { - continue; - } + /* Trying to avoid dynamic memory allocation. If you have more + * heaps, increase INDEX_ARRAY_SIZE. I'm not aware of any + * drivers with more than 2 tex heaps. */ + assert( nr_heaps < INDEX_ARRAY_SIZE ); - /* If this is a placeholder, there's no need to keep it */ - if (cursor->tObj) - driSwapOutTextureObject( cursor ); - else - driDestroyTextureObject( cursor ); + /* Sort large enough heaps by duty. Insertion sort should be + * fast enough for such a short array. */ + for ( id = 0 ; id < nr_heaps ; id++ ) { + heap = heap_array[ id ]; - t->memBlock = mmAllocMem( heap->memory_heap, t->totalSize, - heap->alignmentShift, 0 ); + if ( heap != NULL && t->totalSize <= heap->size ) { + unsigned j; - if (t->memBlock) + for ( j = 0 ; j < nrGoodHeaps; j++ ) { + if ( heap->duty > heap_array[ index[ j ] ]->duty ) break; } - } /* if ( t->totalSize <= heap->size ) ... */ + + if ( j < nrGoodHeaps ) { + memmove( &index[ j+1 ], &index[ j ], + sizeof(index[ 0 ]) * (nrGoodHeaps - j) ); + } + + index[ j ] = id; + + nrGoodHeaps++; + } + } + + for ( id = 0 ; (t->memBlock == NULL) && (id < nrGoodHeaps) ; id++ ) { + heap = heap_array[ index[ id ] ]; + + for ( cursor = heap->texture_objects.prev, temp = cursor->prev; + cursor != &heap->texture_objects ; + cursor = temp, temp = cursor->prev ) { + + /* The the LRU element. If the texture is bound to one of + * the texture units, then we cannot kick it out. + */ + if ( cursor->bound || cursor->reserved ) { + continue; + } + + if ( cursor->memBlock ) + heap->duty -= cursor->memBlock->size; + + /* If this is a placeholder, there's no need to keep it */ + if (cursor->tObj) + driSwapOutTextureObject( cursor ); + else + driDestroyTextureObject( cursor ); + + t->memBlock = mmAllocMem( heap->memory_heap, t->totalSize, + heap->alignmentShift, 0 ); + + if (t->memBlock) + break; + } } + + /* Rebalance duties. If a heap kicked more data than its duty, + * then all other heaps get that amount multiplied with their + * relative weight added to their duty. The negative duty is + * reset to 0. In the end all heaps have a duty >= 0. + * + * CAUTION: we must not change the heap pointer here, because it + * is used below to update the texture object. + */ + for ( id = 0 ; id < nr_heaps ; id++ ) + if ( heap_array[ id ] != NULL && heap_array[ id ]->duty < 0) { + int duty = -heap_array[ id ]->duty; + double weight = heap_array[ id ]->weight; + unsigned j; + + for ( j = 0 ; j < nr_heaps ; j++ ) + if ( j != id && heap_array[ j ] != NULL ) { + heap_array[ j ]->duty += (double) duty * + heap_array[ j ]->weight / weight; + } + + heap_array[ id ]->duty = 0; + } } @@ -675,6 +729,9 @@ driCreateTextureHeap( unsigned heap_id, void * context, unsigned size, make_empty_list( & heap->texture_objects ); driSetTextureSwapCounterLocation( heap, NULL ); + + heap->weight = heap->size; + heap->duty = 0; } else { FREE( heap ); @@ -884,7 +941,7 @@ get_max_size( unsigned nr_heaps, do { if ( max_sizes[v] != 0 ) { limits-> f = max_sizes[v]; } } while( 0 ) #define SET_MAX_RECT(f,v) \ - do { if ( max_sizes[v] != 0 ) { limits-> f = 1 << max_sizes[v]; } } while( 0 ) + do { if ( max_sizes[v] != 0 ) { limits-> f = 1 << (max_sizes[v] - 1); } } while( 0 ) /** @@ -910,19 +967,22 @@ get_max_size( unsigned nr_heaps, * For hardware that does not support mipmapping, this will be 1. * \param all_textures_one_heap True if the hardware requires that all * textures be in a single texture heap for multitexturing. + * \param allow_larger_textures 0 conservative, 1 calculate limits + * so at least one worst-case texture can fit, 2 just use hw limits. */ void driCalculateMaxTextureLevels( driTexHeap * const * heaps, unsigned nr_heaps, struct gl_constants * limits, - unsigned max_bytes_per_texel, + unsigned max_bytes_per_texel, unsigned max_2D_size, unsigned max_3D_size, unsigned max_cube_size, unsigned max_rect_size, unsigned mipmaps_at_once, - int all_textures_one_heap ) + int all_textures_one_heap, + int allow_larger_textures ) { struct maps_per_heap max_textures[8]; unsigned i; @@ -939,8 +999,8 @@ driCalculateMaxTextureLevels( driTexHeap * const * heaps, mipmaps[0] = mipmaps_at_once; mipmaps[1] = mipmaps_at_once; - mipmaps[2] = 1; - mipmaps[3] = mipmaps_at_once; + mipmaps[2] = mipmaps_at_once; + mipmaps[3] = 1; /* Calculate the maximum number of texture levels in two passes. The @@ -951,18 +1011,22 @@ driCalculateMaxTextureLevels( driTexHeap * const * heaps, */ for ( i = 0 ; i < 4 ; i++ ) { - if ( max_sizes[ i ] != 0 ) { - fill_in_maximums( heaps, nr_heaps, max_bytes_per_texel, + if ( (allow_larger_textures != 2) && (max_sizes[ i ] != 0) ) { + fill_in_maximums( heaps, nr_heaps, max_bytes_per_texel, max_sizes[ i ], mipmaps[ i ], dimensions[ i ], faces[ i ], max_textures ); - max_sizes[ i ] = get_max_size( nr_heaps, - limits->MaxTextureUnits, + max_sizes[ i ] = get_max_size( nr_heaps, + allow_larger_textures == 1 ? + 1 : limits->MaxTextureUnits, max_sizes[ i ], all_textures_one_heap, max_textures ); } + else if (max_sizes[ i ] != 0) { + max_sizes[ i ] += 1; + } } SET_MAX( MaxTextureLevels, 0 ); @@ -983,7 +1047,7 @@ driCalculateMaxTextureLevels( driTexHeap * const * heaps, * \param targets Bit-mask of value texture targets */ -void driInitTextureObjects( GLcontext *ctx, driTextureObject * swapped, +void driInitTextureObjects( struct gl_context *ctx, driTextureObject * swapped, GLuint targets ) { struct gl_texture_object *texObj; @@ -995,31 +1059,31 @@ void driInitTextureObjects( GLcontext *ctx, driTextureObject * swapped, ctx->Texture.CurrentUnit = i; if ( (targets & DRI_TEXMGR_DO_TEXTURE_1D) != 0 ) { - texObj = ctx->Texture.Unit[i].Current1D; + texObj = ctx->Texture.Unit[i].CurrentTex[TEXTURE_1D_INDEX]; ctx->Driver.BindTexture( ctx, GL_TEXTURE_1D, texObj ); move_to_tail( swapped, (driTextureObject *) texObj->DriverData ); } if ( (targets & DRI_TEXMGR_DO_TEXTURE_2D) != 0 ) { - texObj = ctx->Texture.Unit[i].Current2D; + texObj = ctx->Texture.Unit[i].CurrentTex[TEXTURE_2D_INDEX]; ctx->Driver.BindTexture( ctx, GL_TEXTURE_2D, texObj ); move_to_tail( swapped, (driTextureObject *) texObj->DriverData ); } if ( (targets & DRI_TEXMGR_DO_TEXTURE_3D) != 0 ) { - texObj = ctx->Texture.Unit[i].Current3D; + texObj = ctx->Texture.Unit[i].CurrentTex[TEXTURE_3D_INDEX]; ctx->Driver.BindTexture( ctx, GL_TEXTURE_3D, texObj ); move_to_tail( swapped, (driTextureObject *) texObj->DriverData ); } if ( (targets & DRI_TEXMGR_DO_TEXTURE_CUBE) != 0 ) { - texObj = ctx->Texture.Unit[i].CurrentCubeMap; + texObj = ctx->Texture.Unit[i].CurrentTex[TEXTURE_CUBE_INDEX]; ctx->Driver.BindTexture( ctx, GL_TEXTURE_CUBE_MAP_ARB, texObj ); move_to_tail( swapped, (driTextureObject *) texObj->DriverData ); } if ( (targets & DRI_TEXMGR_DO_TEXTURE_RECT) != 0 ) { - texObj = ctx->Texture.Unit[i].CurrentRect; + texObj = ctx->Texture.Unit[i].CurrentTex[TEXTURE_RECT_INDEX]; ctx->Driver.BindTexture( ctx, GL_TEXTURE_RECTANGLE_NV, texObj ); move_to_tail( swapped, (driTextureObject *) texObj->DriverData ); } @@ -1077,7 +1141,7 @@ driValidateTextureHeaps( driTexHeap * const * texture_heaps, unsigned textures_in_heap = 0; unsigned blocks_in_mempool = 0; const driTexHeap * heap = texture_heaps[i]; - const memHeap_t * p = heap->memory_heap; + const struct mem_block *p = heap->memory_heap; /* Check each texture object has a MemBlock, and is linked into * the correct heap. @@ -1209,6 +1273,7 @@ driCalculateTextureFirstLastLevel( driTextureObject * t ) else { firstLevel = tObj->BaseLevel + (GLint)(tObj->MinLod + 0.5); firstLevel = MAX2(firstLevel, tObj->BaseLevel); + firstLevel = MIN2(firstLevel, tObj->BaseLevel + baseImage->MaxLog2); lastLevel = tObj->BaseLevel + (GLint)(tObj->MaxLod + 0.5); lastLevel = MAX2(lastLevel, t->tObj->BaseLevel); lastLevel = MIN2(lastLevel, t->tObj->BaseLevel + baseImage->MaxLog2); @@ -1228,3 +1293,49 @@ driCalculateTextureFirstLastLevel( driTextureObject * t ) t->firstLevel = firstLevel; t->lastLevel = lastLevel; } + + + + +/** + * \name DRI texture formats. These vars are initialized to either the + * big- or little-endian Mesa formats. + */ +/*@{*/ +gl_format _dri_texformat_rgba8888 = MESA_FORMAT_NONE; +gl_format _dri_texformat_argb8888 = MESA_FORMAT_NONE; +gl_format _dri_texformat_rgb565 = MESA_FORMAT_NONE; +gl_format _dri_texformat_argb4444 = MESA_FORMAT_NONE; +gl_format _dri_texformat_argb1555 = MESA_FORMAT_NONE; +gl_format _dri_texformat_al88 = MESA_FORMAT_NONE; +gl_format _dri_texformat_a8 = MESA_FORMAT_A8; +gl_format _dri_texformat_ci8 = MESA_FORMAT_CI8; +gl_format _dri_texformat_i8 = MESA_FORMAT_I8; +gl_format _dri_texformat_l8 = MESA_FORMAT_L8; +/*@}*/ + + +/** + * Initialize _dri_texformat_* vars according to whether we're on + * a big or little endian system. + */ +void +driInitTextureFormats(void) +{ + if (_mesa_little_endian()) { + _dri_texformat_rgba8888 = MESA_FORMAT_RGBA8888; + _dri_texformat_argb8888 = MESA_FORMAT_ARGB8888; + _dri_texformat_rgb565 = MESA_FORMAT_RGB565; + _dri_texformat_argb4444 = MESA_FORMAT_ARGB4444; + _dri_texformat_argb1555 = MESA_FORMAT_ARGB1555; + _dri_texformat_al88 = MESA_FORMAT_AL88; + } + else { + _dri_texformat_rgba8888 = MESA_FORMAT_RGBA8888_REV; + _dri_texformat_argb8888 = MESA_FORMAT_ARGB8888_REV; + _dri_texformat_rgb565 = MESA_FORMAT_RGB565_REV; + _dri_texformat_argb4444 = MESA_FORMAT_ARGB4444_REV; + _dri_texformat_argb1555 = MESA_FORMAT_ARGB1555_REV; + _dri_texformat_al88 = MESA_FORMAT_AL88_REV; + } +}