intel_tex.c revision 66681b4c8cb1ef16f42c1591298cb30c83bca09b
1#include "swrast/swrast.h" 2#include "main/renderbuffer.h" 3#include "main/texobj.h" 4#include "main/teximage.h" 5#include "main/mipmap.h" 6#include "drivers/common/meta.h" 7#include "intel_context.h" 8#include "intel_mipmap_tree.h" 9#include "intel_tex.h" 10 11#define FILE_DEBUG_FLAG DEBUG_TEXTURE 12 13static struct gl_texture_image * 14intelNewTextureImage(struct gl_context * ctx) 15{ 16 DBG("%s\n", __FUNCTION__); 17 (void) ctx; 18 return (struct gl_texture_image *) CALLOC_STRUCT(intel_texture_image); 19} 20 21static void 22intelDeleteTextureImage(struct gl_context * ctx, struct gl_texture_image *img) 23{ 24 /* nothing special (yet) for intel_texture_image */ 25 _mesa_delete_texture_image(ctx, img); 26} 27 28 29static struct gl_texture_object * 30intelNewTextureObject(struct gl_context * ctx, GLuint name, GLenum target) 31{ 32 struct intel_texture_object *obj = CALLOC_STRUCT(intel_texture_object); 33 34 (void) ctx; 35 36 DBG("%s\n", __FUNCTION__); 37 _mesa_initialize_texture_object(&obj->base, name, target); 38 39 return &obj->base; 40} 41 42static void 43intelDeleteTextureObject(struct gl_context *ctx, 44 struct gl_texture_object *texObj) 45{ 46 struct intel_texture_object *intelObj = intel_texture_object(texObj); 47 48 intel_miptree_release(&intelObj->mt); 49 _mesa_delete_texture_object(ctx, texObj); 50} 51 52static GLboolean 53intel_alloc_texture_image_buffer(struct gl_context *ctx, 54 struct gl_texture_image *image, 55 gl_format format, GLsizei width, 56 GLsizei height, GLsizei depth) 57{ 58 struct intel_context *intel = intel_context(ctx); 59 struct intel_texture_image *intel_image = intel_texture_image(image); 60 struct gl_texture_object *texobj = image->TexObject; 61 struct intel_texture_object *intel_texobj = intel_texture_object(texobj); 62 GLuint slices; 63 64 /* Because the driver uses AllocTextureImageBuffer() internally, it may end 65 * up mismatched with FreeTextureImageBuffer(), but that is safe to call 66 * multiple times. 67 */ 68 ctx->Driver.FreeTextureImageBuffer(ctx, image); 69 70 if (intel->must_use_separate_stencil 71 && image->TexFormat == MESA_FORMAT_S8_Z24) { 72 intel_tex_image_s8z24_create_renderbuffers(intel, intel_image); 73 } 74 75 /* Allocate the swrast_texture_image::ImageOffsets array now */ 76 switch (texobj->Target) { 77 case GL_TEXTURE_3D: 78 case GL_TEXTURE_2D_ARRAY: 79 slices = image->Depth; 80 break; 81 case GL_TEXTURE_1D_ARRAY: 82 slices = image->Height; 83 break; 84 default: 85 slices = 1; 86 } 87 assert(!intel_image->base.ImageOffsets); 88 intel_image->base.ImageOffsets = malloc(slices * sizeof(GLuint)); 89 90 if (intel_texobj->mt && 91 intel_miptree_match_image(intel_texobj->mt, image)) { 92 intel_miptree_reference(&intel_image->mt, intel_texobj->mt); 93 DBG("%s: alloc obj %p level %d %dx%dx%d using object's miptree %p\n", 94 __FUNCTION__, texobj, image->Level, 95 width, height, depth, intel_texobj->mt); 96 return true; 97 } else if (image->Border == 0) { 98 intel_image->mt = intel_miptree_create_for_teximage(intel, intel_texobj, 99 intel_image, 100 false); 101 102 /* Even if the object currently has a mipmap tree associated 103 * with it, this one is a more likely candidate to represent the 104 * whole object since our level didn't fit what was there 105 * before, and any lower levels would fit into our miptree. 106 */ 107 intel_miptree_reference(&intel_texobj->mt, intel_image->mt); 108 109 if (intel->must_use_separate_stencil 110 && image->TexFormat == MESA_FORMAT_S8_Z24) { 111 intel_tex_image_s8z24_create_renderbuffers(intel, intel_image); 112 } 113 114 DBG("%s: alloc obj %p level %d %dx%dx%d using new miptree %p\n", 115 __FUNCTION__, texobj, image->Level, 116 width, height, depth, intel_image->mt); 117 return true; 118 } 119 120 DBG("%s: alloc obj %p level %d %dx%dx%d using swrast\n", 121 __FUNCTION__, texobj, image->Level, width, height, depth); 122 123 return _swrast_alloc_texture_image_buffer(ctx, image, format, 124 width, height, depth); 125} 126 127static void 128intel_free_texture_image_buffer(struct gl_context * ctx, 129 struct gl_texture_image *texImage) 130{ 131 struct intel_texture_image *intelImage = intel_texture_image(texImage); 132 133 DBG("%s\n", __FUNCTION__); 134 135 intel_miptree_release(&intelImage->mt); 136 137 if (intelImage->base.Data) { 138 _mesa_align_free(intelImage->base.Data); 139 intelImage->base.Data = NULL; 140 } 141 142 if (intelImage->base.ImageOffsets) { 143 free(intelImage->base.ImageOffsets); 144 intelImage->base.ImageOffsets = NULL; 145 } 146 147 _mesa_reference_renderbuffer(&intelImage->depth_rb, NULL); 148 _mesa_reference_renderbuffer(&intelImage->stencil_rb, NULL); 149} 150 151/** 152 * Map texture memory/buffer into user space. 153 * Note: the region of interest parameters are ignored here. 154 * \param mode bitmask of GL_MAP_READ_BIT, GL_MAP_WRITE_BIT 155 * \param mapOut returns start of mapping of region of interest 156 * \param rowStrideOut returns row stride in bytes 157 */ 158static void 159intel_map_texture_image(struct gl_context *ctx, 160 struct gl_texture_image *tex_image, 161 GLuint slice, 162 GLuint x, GLuint y, GLuint w, GLuint h, 163 GLbitfield mode, 164 GLubyte **map, 165 GLint *stride) 166{ 167 struct intel_context *intel = intel_context(ctx); 168 struct intel_texture_image *intel_image = intel_texture_image(tex_image); 169 struct intel_mipmap_tree *mt = intel_image->mt; 170 unsigned int bw, bh; 171 172 /* Check that our caller wasn't confused about how to map a 1D texture. */ 173 assert(tex_image->TexObject->Target != GL_TEXTURE_1D_ARRAY || 174 h == 1); 175 176 if (intel_image->stencil_rb) { 177 /* 178 * The texture has packed depth/stencil format, but uses separate 179 * stencil. The texture's embedded stencil buffer contains the real 180 * stencil data, so copy that into the miptree. 181 */ 182 intel_tex_image_s8z24_gather(intel, intel_image); 183 } 184 185 /* For compressed formats, the stride is the number of bytes per 186 * row of blocks. intel_miptree_get_image_offset() already does 187 * the divide. 188 */ 189 _mesa_get_format_block_size(tex_image->TexFormat, &bw, &bh); 190 assert(y % bh == 0); 191 y /= bh; 192 193 if (likely(mt)) { 194 void *base = intel_region_map(intel, mt->region, mode); 195 unsigned int image_x, image_y; 196 197 intel_miptree_get_image_offset(mt, tex_image->Level, tex_image->Face, 198 slice, &image_x, &image_y); 199 x += image_x; 200 y += image_y; 201 202 *stride = mt->region->pitch * mt->cpp; 203 *map = base + y * *stride + x * mt->cpp; 204 205 DBG("%s: %d,%d %dx%d from mt %p %d,%d = %p/%d\n", __FUNCTION__, 206 x - image_x, y - image_y, w, h, 207 mt, x, y, *map, *stride); 208 } else { 209 /* texture data is in malloc'd memory */ 210 GLuint width = tex_image->Width; 211 GLuint height = ALIGN(tex_image->Height, bh) / bh; 212 GLuint texelSize = _mesa_get_format_bytes(tex_image->TexFormat); 213 214 assert(map); 215 216 *stride = _mesa_format_row_stride(tex_image->TexFormat, width); 217 *map = intel_image->base.Data + (slice * height + y) * *stride + x * texelSize; 218 219 DBG("%s: %d,%d %dx%d from data %p = %p/%d\n", __FUNCTION__, 220 x, y, w, h, 221 intel_image->base.Data, *map, *stride); 222 } 223} 224 225static void 226intel_unmap_texture_image(struct gl_context *ctx, 227 struct gl_texture_image *tex_image, GLuint slice) 228{ 229 struct intel_context *intel = intel_context(ctx); 230 struct intel_texture_image *intel_image = intel_texture_image(tex_image); 231 232 if (intel_image->mt) 233 intel_region_unmap(intel, intel_image->mt->region); 234 235 if (intel_image->stencil_rb) { 236 /* 237 * The texture has packed depth/stencil format, but uses separate 238 * stencil. The texture's embedded stencil buffer contains the real 239 * stencil data, so copy that into the miptree. 240 */ 241 intel_tex_image_s8z24_scatter(intel, intel_image); 242 } 243} 244 245/** 246 * Called via ctx->Driver.GenerateMipmap() 247 * This is basically a wrapper for _mesa_meta_GenerateMipmap() which checks 248 * if we'll be using software mipmap generation. In that case, we need to 249 * map/unmap the base level texture image. 250 */ 251static void 252intelGenerateMipmap(struct gl_context *ctx, GLenum target, 253 struct gl_texture_object *texObj) 254{ 255 if (_mesa_meta_check_generate_mipmap_fallback(ctx, target, texObj)) { 256 fallback_debug("%s - fallback to swrast\n", __FUNCTION__); 257 258 _mesa_generate_mipmap(ctx, target, texObj); 259 } 260 else { 261 _mesa_meta_GenerateMipmap(ctx, target, texObj); 262 } 263} 264 265 266void 267intelInitTextureFuncs(struct dd_function_table *functions) 268{ 269 functions->GenerateMipmap = intelGenerateMipmap; 270 271 functions->NewTextureObject = intelNewTextureObject; 272 functions->NewTextureImage = intelNewTextureImage; 273 functions->DeleteTextureImage = intelDeleteTextureImage; 274 functions->DeleteTexture = intelDeleteTextureObject; 275 functions->AllocTextureImageBuffer = intel_alloc_texture_image_buffer; 276 functions->FreeTextureImageBuffer = intel_free_texture_image_buffer; 277 functions->MapTextureImage = intel_map_texture_image; 278 functions->UnmapTextureImage = intel_unmap_texture_image; 279} 280