📄 texmem.c
字号:
{ unsigned heap; unsigned log2_size; /* Determine the largest texture size such that a texture of that size * can be bound to each texture unit at the same time. Some hardware * may require that all textures be in the same texture heap for * multitexturing. */ for ( log2_size = max_size ; log2_size > 0 ; log2_size-- ) { unsigned total = 0; for ( heap = 0 ; heap < nr_heaps ; heap++ ) { total += max_textures[ heap ].c[ log2_size ]; if ( 0 ) { fprintf( stderr, "[%s:%d] max_textures[%u].c[%02u] = %u, " "total = %u\n", __FILE__, __LINE__, heap, log2_size, max_textures[ heap ].c[ log2_size ], total ); } if ( (max_textures[ heap ].c[ log2_size ] >= texture_units) || (!all_textures_one_heap && (total >= texture_units)) ) { /* The number of mipmap levels is the log-base-2 of the * maximum texture size plus 1. If the maximum texture size * is 1x1, the log-base-2 is 0 and 1 mipmap level (the base * level) is available. */ return log2_size + 1; } } } /* This should NEVER happen. It should always be possible to have at * *least* a 1x1 texture in memory! */ assert( log2_size != 0 ); return 0;}#define SET_MAX(f,v) \ 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] - 1); } } while( 0 )/** * Given the amount of texture memory, the number of texture units, and the * maximum size of a texel, calculate the maximum texture size the driver can * advertise. * * \param heaps Texture heaps for this card * \param nr_heap Number of texture heaps * \param limits OpenGL contants. MaxTextureUnits must be set. * \param max_bytes_per_texel Maximum size of a single texel, in bytes * \param max_2D_size \f$\log_2\f$ of the maximum 2D texture size (i.e., * 1024x1024 textures, this would be 10) * \param max_3D_size \f$\log_2\f$ of the maximum 3D texture size (i.e., * 1024x1024x1024 textures, this would be 10) * \param max_cube_size \f$\log_2\f$ of the maximum cube texture size (i.e., * 1024x1024 textures, this would be 10) * \param max_rect_size \f$\log_2\f$ of the maximum texture rectangle size * (i.e., 1024x1024 textures, this would be 10). This is a power-of-2 * even though texture rectangles need not be a power-of-2. * \param mipmaps_at_once Total number of mipmaps that can be used * at one time. For most hardware this will be \f$\c max_size + 1\f$. * 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. */voiddriCalculateMaxTextureLevels( driTexHeap * const * heaps, unsigned nr_heaps, struct gl_constants * limits, 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 allow_larger_textures ){ struct maps_per_heap max_textures[8]; unsigned i; const unsigned dimensions[4] = { 2, 3, 2, 2 }; const unsigned faces[4] = { 1, 1, 6, 1 }; unsigned max_sizes[4]; unsigned mipmaps[4]; max_sizes[0] = max_2D_size; max_sizes[1] = max_3D_size; max_sizes[2] = max_cube_size; max_sizes[3] = max_rect_size; mipmaps[0] = mipmaps_at_once; mipmaps[1] = mipmaps_at_once; mipmaps[2] = mipmaps_at_once; mipmaps[3] = 1; /* Calculate the maximum number of texture levels in two passes. The * first pass determines how many textures of each power-of-two size * (including all mipmap levels for that size) can fit in each texture * heap. The second pass finds the largest texture size that allows * a texture of that size to be bound to every texture unit. */ for ( i = 0 ; i < 4 ; i++ ) { 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, 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 ); SET_MAX( Max3DTextureLevels, 1 ); SET_MAX( MaxCubeTextureLevels, 2 ); SET_MAX_RECT( MaxTextureRectSize, 3 );}/** * Perform initial binding of default textures objects on a per unit, per * texture target basis. * * \param ctx Current OpenGL context * \param swapped List of swapped-out textures * \param targets Bit-mask of value texture targets */void driInitTextureObjects( GLcontext *ctx, driTextureObject * swapped, GLuint targets ){ struct gl_texture_object *texObj; GLuint tmp = ctx->Texture.CurrentUnit; unsigned i; for ( i = 0 ; i < ctx->Const.MaxTextureUnits ; i++ ) { ctx->Texture.CurrentUnit = i; if ( (targets & DRI_TEXMGR_DO_TEXTURE_1D) != 0 ) { texObj = ctx->Texture.Unit[i].Current1D; 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; 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; 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; 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; ctx->Driver.BindTexture( ctx, GL_TEXTURE_RECTANGLE_NV, texObj ); move_to_tail( swapped, (driTextureObject *) texObj->DriverData ); } } ctx->Texture.CurrentUnit = tmp;}/** * Verify that the specified texture is in the specificed heap. * * \param tex Texture to be tested. * \param heap Texture memory heap to be tested. * \return True if the texture is in the heap, false otherwise. */static GLbooleancheck_in_heap( const driTextureObject * tex, const driTexHeap * heap ){#if 1 return tex->heap == heap;#else driTextureObject * curr; foreach( curr, & heap->texture_objects ) { if ( curr == tex ) { break; } } return curr == tex;#endif}/****************************************************************************//** * Validate the consistency of a set of texture heaps. * Original version by Keith Whitwell in r200/r200_sanity.c. */GLbooleandriValidateTextureHeaps( driTexHeap * const * texture_heaps, unsigned nr_heaps, const driTextureObject * swapped ){ driTextureObject *t; unsigned i; for ( i = 0 ; i < nr_heaps ; i++ ) { int last_end = 0; unsigned textures_in_heap = 0; unsigned blocks_in_mempool = 0; const driTexHeap * heap = texture_heaps[i]; const struct mem_block *p = heap->memory_heap; /* Check each texture object has a MemBlock, and is linked into * the correct heap. * * Check the texobj base address corresponds to the MemBlock * range. Check the texobj size (recalculate?) fits within * the MemBlock. * * Count the number of texobj's using this heap. */ foreach ( t, &heap->texture_objects ) { if ( !check_in_heap( t, heap ) ) { fprintf( stderr, "%s memory block for texture object @ %p not " "found in heap #%d\n", __FUNCTION__, (void *)t, i ); return GL_FALSE; } if ( t->totalSize > t->memBlock->size ) { fprintf( stderr, "%s: Memory block for texture object @ %p is " "only %u bytes, but %u are required\n", __FUNCTION__, (void *)t, t->totalSize, t->memBlock->size ); return GL_FALSE; } textures_in_heap++; } /* Validate the contents of the heap: * - Ordering * - Overlaps * - Bounds */ while ( p != NULL ) { if (p->reserved) { fprintf( stderr, "%s: Block (%08x,%x), is reserved?!\n", __FUNCTION__, p->ofs, p->size ); return GL_FALSE; } if (p->ofs != last_end) { fprintf( stderr, "%s: blocks_in_mempool = %d, last_end = %d, p->ofs = %d\n", __FUNCTION__, blocks_in_mempool, last_end, p->ofs ); return GL_FALSE; } if (!p->reserved && !p->free) { blocks_in_mempool++; } last_end = p->ofs + p->size; p = p->next; } if (textures_in_heap != blocks_in_mempool) { fprintf( stderr, "%s: Different number of textures objects (%u) and " "inuse memory blocks (%u)\n", __FUNCTION__, textures_in_heap, blocks_in_mempool ); return GL_FALSE; }#if 0 fprintf( stderr, "%s: textures_in_heap = %u\n", __FUNCTION__, textures_in_heap );#endif } /* Check swapped texobj's have zero memblocks */ i = 0; foreach ( t, swapped ) { if ( t->memBlock != NULL ) { fprintf( stderr, "%s: Swapped texobj %p has non-NULL memblock %p\n", __FUNCTION__, (void *)t, (void *)t->memBlock ); return GL_FALSE; } i++; }#if 0 fprintf( stderr, "%s: swapped texture count = %u\n", __FUNCTION__, i );#endif return GL_TRUE;}/****************************************************************************//** * Compute which mipmap levels that really need to be sent to the hardware. * This depends on the base image size, GL_TEXTURE_MIN_LOD, * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL. */voiddriCalculateTextureFirstLastLevel( driTextureObject * t ){ struct gl_texture_object * const tObj = t->tObj; const struct gl_texture_image * const baseImage = tObj->Image[0][tObj->BaseLevel]; /* These must be signed values. MinLod and MaxLod can be negative numbers, * and having firstLevel and lastLevel as signed prevents the need for * extra sign checks. */ int firstLevel; int lastLevel; /* Yes, this looks overly complicated, but it's all needed. */ switch (tObj->Target) { case GL_TEXTURE_1D: case GL_TEXTURE_2D: case GL_TEXTURE_3D: case GL_TEXTURE_CUBE_MAP: if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) { /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL. */ firstLevel = lastLevel = tObj->BaseLevel; } 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); lastLevel = MIN2(lastLevel, t->tObj->MaxLevel); lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */ } break; case GL_TEXTURE_RECTANGLE_NV: case GL_TEXTURE_4D_SGIS: firstLevel = lastLevel = 0; break; default: return; } /* save these values */ t->firstLevel = firstLevel; t->lastLevel = lastLevel;}/** * \name DRI texture formats. Pointers initialized to either the big- or * little-endian Mesa formats. *//*@{*/const struct gl_texture_format *_dri_texformat_rgba8888 = NULL;const struct gl_texture_format *_dri_texformat_argb8888 = NULL;const struct gl_texture_format *_dri_texformat_rgb565 = NULL;const struct gl_texture_format *_dri_texformat_argb4444 = NULL;const struct gl_texture_format *_dri_texformat_argb1555 = NULL;const struct gl_texture_format *_dri_texformat_al88 = NULL;const struct gl_texture_format *_dri_texformat_a8 = &_mesa_texformat_a8;const struct gl_texture_format *_dri_texformat_ci8 = &_mesa_texformat_ci8;const struct gl_texture_format *_dri_texformat_i8 = &_mesa_texformat_i8;const struct gl_texture_format *_dri_texformat_l8 = &_mesa_texformat_l8;/*@}*//** * Initialize little endian target, host byte order independent texture formats */voiddriInitTextureFormats(void){ const GLuint ui = 1; const GLubyte littleEndian = *((const GLubyte *) &ui); if (littleEndian) { _dri_texformat_rgba8888 = &_mesa_texformat_rgba8888; _dri_texformat_argb8888 = &_mesa_texformat_argb8888; _dri_texformat_rgb565 = &_mesa_texformat_rgb565; _dri_texformat_argb4444 = &_mesa_texformat_argb4444; _dri_texformat_argb1555 = &_mesa_texformat_argb1555; _dri_texformat_al88 = &_mesa_texformat_al88; } else { _dri_texformat_rgba8888 = &_mesa_texformat_rgba8888_rev; _dri_texformat_argb8888 = &_mesa_texformat_argb8888_rev; _dri_texformat_rgb565 = &_mesa_texformat_rgb565_rev; _dri_texformat_argb4444 = &_mesa_texformat_argb4444_rev; _dri_texformat_argb1555 = &_mesa_texformat_argb1555_rev; _dri_texformat_al88 = &_mesa_texformat_al88_rev; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -