diff options
Diffstat (limited to 'src/mesa/drivers/dri/i965/intel_tex_validate.c')
-rw-r--r-- | src/mesa/drivers/dri/i965/intel_tex_validate.c | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/src/mesa/drivers/dri/i965/intel_tex_validate.c b/src/mesa/drivers/dri/i965/intel_tex_validate.c new file mode 100644 index 0000000000..5023aae1b8 --- /dev/null +++ b/src/mesa/drivers/dri/i965/intel_tex_validate.c @@ -0,0 +1,245 @@ +/************************************************************************** + * + * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "mtypes.h" +#include "macros.h" + +#include "intel_context.h" +#include "intel_mipmap_tree.h" +#include "intel_tex.h" +#include "bufmgr.h" + +/** + * 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. + */ +static void intel_calculate_first_last_level( struct intel_texture_object *intelObj ) +{ + struct gl_texture_object *tObj = &intelObj->base; + 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 { + /* Currently not taking min/max lod into account here, those + * values are programmed as sampler state elsewhere and we + * upload the same mipmap levels regardless. Not sure if + * this makes sense as it means it isn't possible for the app + * to use min/max lod to reduce texture memory pressure: + */ + firstLevel = tObj->BaseLevel; + lastLevel = MIN2(tObj->BaseLevel + baseImage->MaxLog2, + 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 */ + intelObj->firstLevel = firstLevel; + intelObj->lastLevel = lastLevel; +} + +static void copy_image_data_to_tree( struct intel_context *intel, + struct intel_texture_object *intelObj, + struct gl_texture_image *texImage, + GLuint face, + GLuint level) +{ + intel_miptree_image_data(intel, + intelObj->mt, + face, + level, + texImage->Data, + texImage->RowStride, + (texImage->RowStride * + texImage->Height * + texImage->TexFormat->TexelBytes)); +} + +static void intel_texture_invalidate( struct intel_texture_object *intelObj ) +{ + GLint nr_faces, face; + intelObj->dirty = ~0; + + nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; + for (face = 0; face < nr_faces; face++) + intelObj->dirty_images[face] = ~0; +} + +static void intel_texture_invalidate_cb( struct intel_context *intel, + void *ptr ) +{ + intel_texture_invalidate( (struct intel_texture_object *) ptr ); +} + + +/* + */ +GLuint intel_finalize_mipmap_tree( struct intel_context *intel, + struct gl_texture_object *tObj ) +{ + struct intel_texture_object *intelObj = intel_texture_object(tObj); + + GLuint face, i; + GLuint nr_faces = 0; + struct gl_texture_image *firstImage; + + /* We know/require this is true by now: + */ + assert(intelObj->base.Complete); + + /* What levels must the tree include at a minimum? + */ + if (intelObj->dirty) { + intel_calculate_first_last_level( intelObj ); +/* intel_miptree_destroy(intel, intelObj->mt); */ +/* intelObj->mt = NULL; */ + } + + firstImage = intelObj->base.Image[0][intelObj->firstLevel]; + + /* Fallback case: + */ + if (firstImage->Border) { + if (intelObj->mt) { + intel_miptree_destroy(intel, intelObj->mt); + intelObj->mt = NULL; + /* Set all images dirty: + */ + intel_texture_invalidate(intelObj); + } + return GL_FALSE; + } + + + + /* Check tree can hold all active levels. Check tree matches + * target, imageFormat, etc. + */ + if (intelObj->mt && + (intelObj->mt->first_level != intelObj->firstLevel || + intelObj->mt->last_level != intelObj->lastLevel || + intelObj->mt->internal_format != firstImage->InternalFormat || + intelObj->mt->width0 != firstImage->Width || + intelObj->mt->height0 != firstImage->Height || + intelObj->mt->depth0 != firstImage->Depth)) + { + intel_miptree_destroy(intel, intelObj->mt); + intelObj->mt = NULL; + + /* Set all images dirty: + */ + intel_texture_invalidate(intelObj); + } + + + /* May need to create a new tree: + */ + if (!intelObj->mt) { + intelObj->mt = intel_miptree_create(intel, + intelObj->base.Target, + firstImage->InternalFormat, + intelObj->firstLevel, + intelObj->lastLevel, + firstImage->Width, + firstImage->Height, + firstImage->Depth, + firstImage->TexFormat->TexelBytes, + firstImage->IsCompressed); + + /* Tell the buffer manager that we will manage the backing + * store, but we still want it to do fencing for us. + */ + bmBufferSetInvalidateCB(intel, + intelObj->mt->region->buffer, + intel_texture_invalidate_cb, + intelObj, + GL_FALSE); + } + + /* Pull in any images not in the object's tree: + */ + if (intelObj->dirty) { + nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; + for (face = 0; face < nr_faces; face++) { + if (intelObj->dirty_images[face]) { + for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) { + struct gl_texture_image *texImage = intelObj->base.Image[face][i]; + + /* Need to import images in main memory or held in other trees. + */ + if (intelObj->dirty_images[face] & (1<<i) && + texImage) { + + if (INTEL_DEBUG & DEBUG_TEXTURE) + _mesa_printf("copy data from image %d (%p) into object miptree\n", + i, + texImage->Data); + + copy_image_data_to_tree(intel, + intelObj, + texImage, + face, + i); + + } + } + intelObj->dirty_images[face] = 0; + } + } + + intelObj->dirty = 0; + } + + return GL_TRUE; +} |