intel_tex_validate.c revision b4b7326717d3253656f9702fc04f06f8d210a6aa
1#include "mtypes.h" 2#include "macros.h" 3 4#include "intel_context.h" 5#include "intel_batchbuffer.h" 6#include "intel_mipmap_tree.h" 7#include "intel_tex.h" 8 9#define FILE_DEBUG_FLAG DEBUG_TEXTURE 10 11/** 12 * Compute which mipmap levels that really need to be sent to the hardware. 13 * This depends on the base image size, GL_TEXTURE_MIN_LOD, 14 * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL. 15 */ 16static void 17intel_calculate_first_last_level(struct intel_texture_object *intelObj) 18{ 19 struct gl_texture_object *tObj = &intelObj->base; 20 const struct gl_texture_image *const baseImage = 21 tObj->Image[0][tObj->BaseLevel]; 22 23 /* These must be signed values. MinLod and MaxLod can be negative numbers, 24 * and having firstLevel and lastLevel as signed prevents the need for 25 * extra sign checks. 26 */ 27 int firstLevel; 28 int lastLevel; 29 30 /* Yes, this looks overly complicated, but it's all needed. 31 */ 32 switch (tObj->Target) { 33 case GL_TEXTURE_1D: 34 case GL_TEXTURE_2D: 35 case GL_TEXTURE_3D: 36 case GL_TEXTURE_CUBE_MAP: 37 if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) { 38 /* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL. 39 */ 40 firstLevel = lastLevel = tObj->BaseLevel; 41 } 42 else { 43#ifdef I915 44 firstLevel = tObj->BaseLevel + (GLint) (tObj->MinLod + 0.5); 45 firstLevel = MAX2(firstLevel, tObj->BaseLevel); 46 firstLevel = MIN2(firstLevel, tObj->BaseLevel + baseImage->MaxLog2); 47 lastLevel = tObj->BaseLevel + (GLint) (tObj->MaxLod + 0.5); 48 lastLevel = MAX2(lastLevel, tObj->BaseLevel); 49 lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2); 50 lastLevel = MIN2(lastLevel, tObj->MaxLevel); 51 lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */ 52#else 53 /* Currently not taking min/max lod into account here, those 54 * values are programmed as sampler state elsewhere and we 55 * upload the same mipmap levels regardless. Not sure if 56 * this makes sense as it means it isn't possible for the app 57 * to use min/max lod to reduce texture memory pressure: 58 */ 59 firstLevel = tObj->BaseLevel; 60 lastLevel = MIN2(tObj->BaseLevel + baseImage->MaxLog2, 61 tObj->MaxLevel); 62 lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */ 63#endif 64 } 65 break; 66 case GL_TEXTURE_RECTANGLE_NV: 67 case GL_TEXTURE_4D_SGIS: 68 firstLevel = lastLevel = 0; 69 break; 70 default: 71 return; 72 } 73 74 /* save these values */ 75 intelObj->firstLevel = firstLevel; 76 intelObj->lastLevel = lastLevel; 77} 78 79/** 80 * Copies the image's contents at its level into the object's miptree, 81 * and updates the image to point at the object's miptree. 82 */ 83static void 84copy_image_data_to_tree(struct intel_context *intel, 85 struct intel_texture_object *intelObj, 86 struct intel_texture_image *intelImage) 87{ 88 if (intelImage->mt) { 89 /* Copy potentially with the blitter: 90 */ 91 intel_miptree_image_copy(intel, 92 intelObj->mt, 93 intelImage->face, 94 intelImage->level, intelImage->mt); 95 96 intel_miptree_release(intel, &intelImage->mt); 97 } 98 else { 99 assert(intelImage->base.Data != NULL); 100 101 /* More straightforward upload. 102 */ 103 intel_miptree_image_data(intel, 104 intelObj->mt, 105 intelImage->face, 106 intelImage->level, 107 intelImage->base.Data, 108 intelImage->base.RowStride, 109 intelImage->base.RowStride * 110 intelImage->base.Height); 111 _mesa_align_free(intelImage->base.Data); 112 intelImage->base.Data = NULL; 113 } 114 115 intel_miptree_reference(&intelImage->mt, intelObj->mt); 116} 117 118 119/* 120 */ 121GLuint 122intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit) 123{ 124 struct gl_texture_object *tObj = intel->ctx.Texture.Unit[unit]._Current; 125 struct intel_texture_object *intelObj = intel_texture_object(tObj); 126 int comp_byte = 0; 127 int cpp; 128 129 GLuint face, i; 130 GLuint nr_faces = 0; 131 struct intel_texture_image *firstImage; 132 133 GLboolean need_flush = GL_FALSE; 134 135 /* We know/require this is true by now: 136 */ 137 assert(intelObj->base._Complete); 138 139 /* What levels must the tree include at a minimum? 140 */ 141 intel_calculate_first_last_level(intelObj); 142 firstImage = 143 intel_texture_image(intelObj->base.Image[0][intelObj->firstLevel]); 144 145 /* Fallback case: 146 */ 147 if (firstImage->base.Border || 148 ((firstImage->base._BaseFormat == GL_DEPTH_COMPONENT) && 149 ((tObj->WrapS == GL_CLAMP_TO_BORDER) || 150 (tObj->WrapT == GL_CLAMP_TO_BORDER)))) { 151 if (intelObj->mt) { 152 intel_miptree_release(intel, &intelObj->mt); 153 } 154 return GL_FALSE; 155 } 156 157 158 /* If both firstImage and intelObj have a tree which can contain 159 * all active images, favour firstImage. Note that because of the 160 * completeness requirement, we know that the image dimensions 161 * will match. 162 */ 163 if (firstImage->mt && 164 firstImage->mt != intelObj->mt && 165 firstImage->mt->first_level <= intelObj->firstLevel && 166 firstImage->mt->last_level >= intelObj->lastLevel) { 167 168 if (intelObj->mt) 169 intel_miptree_release(intel, &intelObj->mt); 170 171 intel_miptree_reference(&intelObj->mt, firstImage->mt); 172 } 173 174 if (firstImage->base.IsCompressed) { 175 comp_byte = intel_compressed_num_bytes(firstImage->base.TexFormat->MesaFormat); 176 cpp = comp_byte; 177 } 178 else cpp = firstImage->base.TexFormat->TexelBytes; 179 180 /* Check tree can hold all active levels. Check tree matches 181 * target, imageFormat, etc. 182 * 183 * XXX: For some layouts (eg i945?), the test might have to be 184 * first_level == firstLevel, as the tree isn't valid except at the 185 * original start level. Hope to get around this by 186 * programming minLod, maxLod, baseLevel into the hardware and 187 * leaving the tree alone. 188 */ 189 if (intelObj->mt && 190 (intelObj->mt->target != intelObj->base.Target || 191 intelObj->mt->internal_format != firstImage->base.InternalFormat || 192 intelObj->mt->first_level != intelObj->firstLevel || 193 intelObj->mt->last_level != intelObj->lastLevel || 194 intelObj->mt->width0 != firstImage->base.Width || 195 intelObj->mt->height0 != firstImage->base.Height || 196 intelObj->mt->depth0 != firstImage->base.Depth || 197 intelObj->mt->cpp != cpp || 198 intelObj->mt->compressed != firstImage->base.IsCompressed)) { 199 intel_miptree_release(intel, &intelObj->mt); 200 } 201 202 203 /* May need to create a new tree: 204 */ 205 if (!intelObj->mt) { 206 intelObj->mt = intel_miptree_create(intel, 207 intelObj->base.Target, 208 firstImage->base.InternalFormat, 209 intelObj->firstLevel, 210 intelObj->lastLevel, 211 firstImage->base.Width, 212 firstImage->base.Height, 213 firstImage->base.Depth, 214 cpp, 215 comp_byte); 216 } 217 218 /* Pull in any images not in the object's tree: 219 */ 220 nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; 221 for (face = 0; face < nr_faces; face++) { 222 for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) { 223 struct intel_texture_image *intelImage = 224 intel_texture_image(intelObj->base.Image[face][i]); 225 226 /* Need to import images in main memory or held in other trees. 227 */ 228 if (intelObj->mt != intelImage->mt) { 229 copy_image_data_to_tree(intel, intelObj, intelImage); 230 need_flush = GL_TRUE; 231 } 232 } 233 } 234 235#ifdef I915 236 /* XXX: what is this flush about? 237 * On 965, it causes a batch flush in the middle of the state relocation 238 * emits, which means that the eventual rendering doesn't have all of the 239 * required relocations in place. 240 */ 241 if (need_flush) 242 intel_batchbuffer_flush(intel->batch); 243#endif 244 245 return GL_TRUE; 246} 247 248 249 250void 251intel_tex_map_images(struct intel_context *intel, 252 struct intel_texture_object *intelObj) 253{ 254 GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; 255 GLuint face, i; 256 257 DBG("%s\n", __FUNCTION__); 258 259 for (face = 0; face < nr_faces; face++) { 260 for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) { 261 struct intel_texture_image *intelImage = 262 intel_texture_image(intelObj->base.Image[face][i]); 263 264 if (intelImage->mt) { 265 intelImage->base.Data = 266 intel_miptree_image_map(intel, 267 intelImage->mt, 268 intelImage->face, 269 intelImage->level, 270 &intelImage->base.RowStride, 271 intelImage->base.ImageOffsets); 272 /* convert stride to texels, not bytes */ 273 intelImage->base.RowStride /= intelImage->mt->cpp; 274/* intelImage->base.ImageStride /= intelImage->mt->cpp; */ 275 } 276 } 277 } 278} 279 280 281 282void 283intel_tex_unmap_images(struct intel_context *intel, 284 struct intel_texture_object *intelObj) 285{ 286 GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; 287 GLuint face, i; 288 289 for (face = 0; face < nr_faces; face++) { 290 for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) { 291 struct intel_texture_image *intelImage = 292 intel_texture_image(intelObj->base.Image[face][i]); 293 294 if (intelImage->mt) { 295 intel_miptree_image_unmap(intel, intelImage->mt); 296 intelImage->base.Data = NULL; 297 } 298 } 299 } 300} 301