intel_tex_validate.c revision e2ee0c55d360f6b0bb8cd140b6dd6c0f46998ab1
1#include "main/mtypes.h" 2#include "main/macros.h" 3 4#include "intel_context.h" 5#include "intel_mipmap_tree.h" 6#include "intel_tex.h" 7 8#define FILE_DEBUG_FLAG DEBUG_TEXTURE 9 10/** 11 * Compute which mipmap levels that really need to be sent to the hardware. 12 * This depends on the base image size, GL_TEXTURE_MIN_LOD, 13 * GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL. 14 */ 15static void 16intel_calculate_first_last_level(struct intel_context *intel, 17 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 if (intel->gen == 2) { 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 /* Min/max LOD are taken into account in sampler state. We don't 54 * want to re-layout textures just because clamping has been applied 55 * since it means a bunch of blitting around and probably no memory 56 * savings (since we have to keep the other levels around anyway). 57 */ 58 firstLevel = tObj->BaseLevel; 59 lastLevel = MIN2(tObj->BaseLevel + baseImage->MaxLog2, 60 tObj->MaxLevel); 61 /* need at least one level */ 62 lastLevel = MAX2(firstLevel, lastLevel); 63 } 64 } 65 break; 66 case GL_TEXTURE_RECTANGLE_NV: 67 firstLevel = lastLevel = 0; 68 break; 69 default: 70 return; 71 } 72 73 /* save these values */ 74 intelObj->firstLevel = firstLevel; 75 intelObj->lastLevel = lastLevel; 76} 77 78/** 79 * Copies the image's contents at its level into the object's miptree, 80 * and updates the image to point at the object's miptree. 81 */ 82static void 83copy_image_data_to_tree(struct intel_context *intel, 84 struct intel_texture_object *intelObj, 85 struct intel_texture_image *intelImage) 86{ 87 if (intelImage->mt) { 88 /* Copy potentially with the blitter: 89 */ 90 intel_miptree_image_copy(intel, 91 intelObj->mt, 92 intelImage->face, 93 intelImage->level, intelImage->mt); 94 95 intel_miptree_release(intel, &intelImage->mt); 96 } 97 else { 98 assert(intelImage->base.Data != NULL); 99 100 /* More straightforward upload. 101 */ 102 intel_miptree_image_data(intel, 103 intelObj->mt, 104 intelImage->face, 105 intelImage->level, 106 intelImage->base.Data, 107 intelImage->base.RowStride, 108 intelImage->base.RowStride * 109 intelImage->base.Height); 110 _mesa_align_free(intelImage->base.Data); 111 intelImage->base.Data = NULL; 112 } 113 114 intel_miptree_reference(&intelImage->mt, intelObj->mt); 115} 116 117 118/* 119 */ 120GLuint 121intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit) 122{ 123 struct gl_texture_object *tObj = intel->ctx.Texture.Unit[unit]._Current; 124 struct intel_texture_object *intelObj = intel_texture_object(tObj); 125 int comp_byte = 0; 126 int cpp; 127 GLuint face, i; 128 GLuint nr_faces = 0; 129 struct intel_texture_image *firstImage; 130 131 /* We know/require this is true by now: 132 */ 133 assert(intelObj->base._Complete); 134 135 /* What levels must the tree include at a minimum? 136 */ 137 intel_calculate_first_last_level(intel, intelObj); 138 firstImage = intel_texture_image(tObj->Image[0][intelObj->firstLevel]); 139 140 /* Fallback case: 141 */ 142 if (firstImage->base.Border) { 143 if (intelObj->mt) { 144 intel_miptree_release(intel, &intelObj->mt); 145 } 146 return GL_FALSE; 147 } 148 149 150 /* If both firstImage and intelObj have a tree which can contain 151 * all active images, favour firstImage. Note that because of the 152 * completeness requirement, we know that the image dimensions 153 * will match. 154 */ 155 if (firstImage->mt && 156 firstImage->mt != intelObj->mt && 157 firstImage->mt->first_level <= intelObj->firstLevel && 158 firstImage->mt->last_level >= intelObj->lastLevel) { 159 160 if (intelObj->mt) 161 intel_miptree_release(intel, &intelObj->mt); 162 163 intel_miptree_reference(&intelObj->mt, firstImage->mt); 164 } 165 166 if (_mesa_is_format_compressed(firstImage->base.TexFormat)) { 167 comp_byte = intel_compressed_num_bytes(firstImage->base.TexFormat); 168 cpp = comp_byte; 169 } 170 else 171 cpp = _mesa_get_format_bytes(firstImage->base.TexFormat); 172 173 /* Check tree can hold all active levels. Check tree matches 174 * target, imageFormat, etc. 175 * 176 * XXX: For some layouts (eg i945?), the test might have to be 177 * first_level == firstLevel, as the tree isn't valid except at the 178 * original start level. Hope to get around this by 179 * programming minLod, maxLod, baseLevel into the hardware and 180 * leaving the tree alone. 181 */ 182 if (intelObj->mt && 183 (intelObj->mt->target != intelObj->base.Target || 184 intelObj->mt->internal_format != firstImage->base.InternalFormat || 185 intelObj->mt->first_level != intelObj->firstLevel || 186 intelObj->mt->last_level != intelObj->lastLevel || 187 intelObj->mt->width0 != firstImage->base.Width || 188 intelObj->mt->height0 != firstImage->base.Height || 189 intelObj->mt->depth0 != firstImage->base.Depth || 190 intelObj->mt->cpp != cpp || 191 intelObj->mt->compressed != _mesa_is_format_compressed(firstImage->base.TexFormat))) { 192 intel_miptree_release(intel, &intelObj->mt); 193 } 194 195 196 /* May need to create a new tree: 197 */ 198 if (!intelObj->mt) { 199 intelObj->mt = intel_miptree_create(intel, 200 intelObj->base.Target, 201 firstImage->base._BaseFormat, 202 firstImage->base.InternalFormat, 203 intelObj->firstLevel, 204 intelObj->lastLevel, 205 firstImage->base.Width, 206 firstImage->base.Height, 207 firstImage->base.Depth, 208 cpp, 209 comp_byte, 210 GL_TRUE); 211 } 212 213 /* Pull in any images not in the object's tree: 214 */ 215 nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; 216 for (face = 0; face < nr_faces; face++) { 217 for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) { 218 struct intel_texture_image *intelImage = 219 intel_texture_image(intelObj->base.Image[face][i]); 220 221 /* Need to import images in main memory or held in other trees. 222 * If it's a render target, then its data isn't needed to be in 223 * the object tree (otherwise we'd be FBO incomplete), and we need 224 * to keep track of the image's MT as needing to be pulled in still, 225 * or we'll lose the rendering that's done to it. 226 */ 227 if (intelObj->mt != intelImage->mt && 228 !intelImage->used_as_render_target) { 229 copy_image_data_to_tree(intel, intelObj, intelImage); 230 } 231 } 232 } 233 234 return GL_TRUE; 235} 236 237void 238intel_tex_map_level_images(struct intel_context *intel, 239 struct intel_texture_object *intelObj, 240 int level) 241{ 242 GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; 243 GLuint face; 244 245 for (face = 0; face < nr_faces; face++) { 246 struct intel_texture_image *intelImage = 247 intel_texture_image(intelObj->base.Image[face][level]); 248 249 if (intelImage && intelImage->mt) { 250 intelImage->base.Data = 251 intel_miptree_image_map(intel, 252 intelImage->mt, 253 intelImage->face, 254 intelImage->level, 255 &intelImage->base.RowStride, 256 intelImage->base.ImageOffsets); 257 /* convert stride to texels, not bytes */ 258 intelImage->base.RowStride /= intelImage->mt->cpp; 259 /* intelImage->base.ImageStride /= intelImage->mt->cpp; */ 260 } 261 } 262} 263 264void 265intel_tex_unmap_level_images(struct intel_context *intel, 266 struct intel_texture_object *intelObj, 267 int level) 268{ 269 GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; 270 GLuint face; 271 272 for (face = 0; face < nr_faces; face++) { 273 struct intel_texture_image *intelImage = 274 intel_texture_image(intelObj->base.Image[face][level]); 275 276 if (intelImage && intelImage->mt) { 277 intel_miptree_image_unmap(intel, intelImage->mt); 278 intelImage->base.Data = NULL; 279 } 280 } 281} 282 283void 284intel_tex_map_images(struct intel_context *intel, 285 struct intel_texture_object *intelObj) 286{ 287 int i; 288 289 DBG("%s\n", __FUNCTION__); 290 291 for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) 292 intel_tex_map_level_images(intel, intelObj, i); 293} 294 295void 296intel_tex_unmap_images(struct intel_context *intel, 297 struct intel_texture_object *intelObj) 298{ 299 int i; 300 301 for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) 302 intel_tex_unmap_level_images(intel, intelObj, i); 303} 304