intel_tex_validate.c revision c0b4257aa9ba783674ccf7162799385734dff211
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 lastLevel = tObj->BaseLevel + (GLint) (tObj->MaxLod + 0.5); 47 lastLevel = MAX2(lastLevel, tObj->BaseLevel); 48 lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2); 49 lastLevel = MIN2(lastLevel, tObj->MaxLevel); 50 lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */ 51#else 52 /* Currently not taking min/max lod into account here, those 53 * values are programmed as sampler state elsewhere and we 54 * upload the same mipmap levels regardless. Not sure if 55 * this makes sense as it means it isn't possible for the app 56 * to use min/max lod to reduce texture memory pressure: 57 */ 58 firstLevel = tObj->BaseLevel; 59 lastLevel = MIN2(tObj->BaseLevel + baseImage->MaxLog2, 60 tObj->MaxLevel); 61 lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */ 62#endif 63 } 64 break; 65 case GL_TEXTURE_RECTANGLE_NV: 66 case GL_TEXTURE_4D_SGIS: 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 78static void 79copy_image_data_to_tree(struct intel_context *intel, 80 struct intel_texture_object *intelObj, 81 struct intel_texture_image *intelImage) 82{ 83 if (intelImage->mt) { 84 /* Copy potentially with the blitter: 85 */ 86 intel_miptree_image_copy(intel, 87 intelObj->mt, 88 intelImage->face, 89 intelImage->level, intelImage->mt); 90 91 intel_miptree_release(intel, &intelImage->mt); 92 } 93 else { 94 assert(intelImage->base.Data != NULL); 95 96 /* More straightforward upload. 97 */ 98 intel_miptree_image_data(intel, 99 intelObj->mt, 100 intelImage->face, 101 intelImage->level, 102 intelImage->base.Data, 103 intelImage->base.RowStride, 104 intelImage->base.RowStride * 105 intelImage->base.Height); 106 _mesa_align_free(intelImage->base.Data); 107 intelImage->base.Data = NULL; 108 } 109 110 intel_miptree_reference(&intelImage->mt, intelObj->mt); 111} 112 113 114/* 115 */ 116GLuint 117intel_finalize_mipmap_tree(struct intel_context *intel, GLuint unit) 118{ 119 struct gl_texture_object *tObj = intel->ctx.Texture.Unit[unit]._Current; 120 struct intel_texture_object *intelObj = intel_texture_object(tObj); 121 int comp_byte = 0; 122 int cpp; 123 124 GLuint face, i; 125 GLuint nr_faces = 0; 126 struct intel_texture_image *firstImage; 127 128 GLboolean need_flush = GL_FALSE; 129 130 /* We know/require this is true by now: 131 */ 132 assert(intelObj->base._Complete); 133 134 /* What levels must the tree include at a minimum? 135 */ 136 intel_calculate_first_last_level(intelObj); 137 firstImage = 138 intel_texture_image(intelObj->base.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 (firstImage->base.IsCompressed) { 167 comp_byte = intel_compressed_num_bytes(firstImage->base.TexFormat->MesaFormat); 168 cpp = comp_byte; 169 } 170 else cpp = firstImage->base.TexFormat->TexelBytes; 171 172 /* Check tree can hold all active levels. Check tree matches 173 * target, imageFormat, etc. 174 * 175 * XXX: For some layouts (eg i945?), the test might have to be 176 * first_level == firstLevel, as the tree isn't valid except at the 177 * original start level. Hope to get around this by 178 * programming minLod, maxLod, baseLevel into the hardware and 179 * leaving the tree alone. 180 */ 181 if (intelObj->mt && 182 (intelObj->mt->target != intelObj->base.Target || 183 intelObj->mt->internal_format != firstImage->base.InternalFormat || 184 intelObj->mt->first_level != intelObj->firstLevel || 185 intelObj->mt->last_level != intelObj->lastLevel || 186 intelObj->mt->width0 != firstImage->base.Width || 187 intelObj->mt->height0 != firstImage->base.Height || 188 intelObj->mt->depth0 != firstImage->base.Depth || 189 intelObj->mt->cpp != cpp || 190 intelObj->mt->compressed != firstImage->base.IsCompressed)) { 191 intel_miptree_release(intel, &intelObj->mt); 192 } 193 194 195 /* May need to create a new tree: 196 */ 197 if (!intelObj->mt) { 198 intelObj->mt = intel_miptree_create(intel, 199 intelObj->base.Target, 200 firstImage->base.InternalFormat, 201 intelObj->firstLevel, 202 intelObj->lastLevel, 203 firstImage->base.Width, 204 firstImage->base.Height, 205 firstImage->base.Depth, 206 cpp, 207 comp_byte); 208 } 209 210 /* Pull in any images not in the object's tree: 211 */ 212 nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; 213 for (face = 0; face < nr_faces; face++) { 214 for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) { 215 struct intel_texture_image *intelImage = 216 intel_texture_image(intelObj->base.Image[face][i]); 217 218 /* Need to import images in main memory or held in other trees. 219 */ 220 if (intelObj->mt != intelImage->mt) { 221 copy_image_data_to_tree(intel, intelObj, intelImage); 222 need_flush = GL_TRUE; 223 } 224 } 225 } 226 227#ifdef I915 228 /* XXX: what is this flush about? 229 * On 965, it causes a batch flush in the middle of the state relocation 230 * emits, which means that the eventual rendering doesn't have all of the 231 * required relocations in place. 232 */ 233 if (need_flush) 234 intel_batchbuffer_flush(intel->batch); 235#endif 236 237 return GL_TRUE; 238} 239 240 241 242void 243intel_tex_map_images(struct intel_context *intel, 244 struct intel_texture_object *intelObj) 245{ 246 GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; 247 GLuint face, i; 248 249 DBG("%s\n", __FUNCTION__); 250 251 for (face = 0; face < nr_faces; face++) { 252 for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) { 253 struct intel_texture_image *intelImage = 254 intel_texture_image(intelObj->base.Image[face][i]); 255 256 if (intelImage->mt) { 257 intelImage->base.Data = 258 intel_miptree_image_map(intel, 259 intelImage->mt, 260 intelImage->face, 261 intelImage->level, 262 &intelImage->base.RowStride, 263 intelImage->base.ImageOffsets); 264 /* convert stride to texels, not bytes */ 265 intelImage->base.RowStride /= intelImage->mt->cpp; 266/* intelImage->base.ImageStride /= intelImage->mt->cpp; */ 267 } 268 } 269 } 270} 271 272 273 274void 275intel_tex_unmap_images(struct intel_context *intel, 276 struct intel_texture_object *intelObj) 277{ 278 GLuint nr_faces = (intelObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; 279 GLuint face, i; 280 281 for (face = 0; face < nr_faces; face++) { 282 for (i = intelObj->firstLevel; i <= intelObj->lastLevel; i++) { 283 struct intel_texture_image *intelImage = 284 intel_texture_image(intelObj->base.Image[face][i]); 285 286 if (intelImage->mt) { 287 intel_miptree_image_unmap(intel, intelImage->mt); 288 intelImage->base.Data = NULL; 289 } 290 } 291 } 292} 293