intel_tex.c revision 3eb12dfaeed03f77e31943eea164acb03e86bbc9
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 assert(image->Border == 0); 65 66 /* Because the driver uses AllocTextureImageBuffer() internally, it may end 67 * up mismatched with FreeTextureImageBuffer(), but that is safe to call 68 * multiple times. 69 */ 70 ctx->Driver.FreeTextureImageBuffer(ctx, image); 71 72 /* Allocate the swrast_texture_image::ImageOffsets array now */ 73 switch (texobj->Target) { 74 case GL_TEXTURE_3D: 75 case GL_TEXTURE_2D_ARRAY: 76 slices = image->Depth; 77 break; 78 case GL_TEXTURE_1D_ARRAY: 79 slices = image->Height; 80 break; 81 default: 82 slices = 1; 83 } 84 assert(!intel_image->base.ImageOffsets); 85 intel_image->base.ImageOffsets = malloc(slices * sizeof(GLuint)); 86 87 if (intel_texobj->mt && 88 intel_miptree_match_image(intel_texobj->mt, image)) { 89 intel_miptree_reference(&intel_image->mt, intel_texobj->mt); 90 DBG("%s: alloc obj %p level %d %dx%dx%d using object's miptree %p\n", 91 __FUNCTION__, texobj, image->Level, 92 width, height, depth, intel_texobj->mt); 93 } else { 94 intel_image->mt = intel_miptree_create_for_teximage(intel, intel_texobj, 95 intel_image, 96 false); 97 98 /* Even if the object currently has a mipmap tree associated 99 * with it, this one is a more likely candidate to represent the 100 * whole object since our level didn't fit what was there 101 * before, and any lower levels would fit into our miptree. 102 */ 103 intel_miptree_reference(&intel_texobj->mt, intel_image->mt); 104 105 DBG("%s: alloc obj %p level %d %dx%dx%d using new miptree %p\n", 106 __FUNCTION__, texobj, image->Level, 107 width, height, depth, intel_image->mt); 108 } 109 110 return true; 111} 112 113static void 114intel_free_texture_image_buffer(struct gl_context * ctx, 115 struct gl_texture_image *texImage) 116{ 117 struct intel_texture_image *intelImage = intel_texture_image(texImage); 118 119 DBG("%s\n", __FUNCTION__); 120 121 intel_miptree_release(&intelImage->mt); 122 123 if (intelImage->base.Buffer) { 124 _mesa_align_free(intelImage->base.Buffer); 125 intelImage->base.Buffer = NULL; 126 } 127 128 if (intelImage->base.ImageOffsets) { 129 free(intelImage->base.ImageOffsets); 130 intelImage->base.ImageOffsets = NULL; 131 } 132} 133 134/** 135 * Map texture memory/buffer into user space. 136 * Note: the region of interest parameters are ignored here. 137 * \param mode bitmask of GL_MAP_READ_BIT, GL_MAP_WRITE_BIT 138 * \param mapOut returns start of mapping of region of interest 139 * \param rowStrideOut returns row stride in bytes 140 */ 141static void 142intel_map_texture_image(struct gl_context *ctx, 143 struct gl_texture_image *tex_image, 144 GLuint slice, 145 GLuint x, GLuint y, GLuint w, GLuint h, 146 GLbitfield mode, 147 GLubyte **map, 148 GLint *stride) 149{ 150 struct intel_context *intel = intel_context(ctx); 151 struct intel_texture_image *intel_image = intel_texture_image(tex_image); 152 struct intel_mipmap_tree *mt = intel_image->mt; 153 unsigned int bw, bh; 154 void *base; 155 unsigned int image_x, image_y; 156 157 /* Our texture data is always stored in a miptree. */ 158 assert(mt); 159 160 /* Check that our caller wasn't confused about how to map a 1D texture. */ 161 assert(tex_image->TexObject->Target != GL_TEXTURE_1D_ARRAY || 162 h == 1); 163 164 if (mt->stencil_mt) { 165 /* The miptree has depthstencil format, but uses separate stencil. The 166 * embedded stencil miptree contains the real stencil data, so gather 167 * that into the depthstencil miptree. 168 * 169 * FIXME: Avoid the gather if the texture is mapped as write-only. 170 */ 171 intel_miptree_s8z24_gather(intel, mt, tex_image->Level, slice); 172 } 173 174 /* For compressed formats, the stride is the number of bytes per 175 * row of blocks. intel_miptree_get_image_offset() already does 176 * the divide. 177 */ 178 _mesa_get_format_block_size(tex_image->TexFormat, &bw, &bh); 179 assert(y % bh == 0); 180 y /= bh; 181 182 base = intel_region_map(intel, mt->region, mode); 183 intel_miptree_get_image_offset(mt, tex_image->Level, tex_image->Face, 184 slice, &image_x, &image_y); 185 x += image_x; 186 y += image_y; 187 188 *stride = mt->region->pitch * mt->cpp; 189 *map = base + y * *stride + x * mt->cpp; 190 191 DBG("%s: %d,%d %dx%d from mt %p %d,%d = %p/%d\n", __FUNCTION__, 192 x - image_x, y - image_y, w, h, 193 mt, x, y, *map, *stride); 194} 195 196static void 197intel_unmap_texture_image(struct gl_context *ctx, 198 struct gl_texture_image *tex_image, GLuint slice) 199{ 200 struct intel_context *intel = intel_context(ctx); 201 struct intel_texture_image *intel_image = intel_texture_image(tex_image); 202 struct intel_mipmap_tree *mt = intel_image->mt; 203 204 intel_region_unmap(intel, intel_image->mt->region); 205 206 if (mt->stencil_mt) { 207 /* The miptree has depthstencil format, but uses separate stencil. The 208 * embedded stencil miptree must contain the real stencil data after 209 * unmapping, so copy it from the depthstencil miptree into the stencil 210 * miptree. 211 * 212 * FIXME: Avoid the scatter if the texture was mapped as read-only. 213 */ 214 intel_miptree_s8z24_scatter(intel, mt, tex_image->Level, slice); 215 } 216} 217 218void 219intelInitTextureFuncs(struct dd_function_table *functions) 220{ 221 functions->NewTextureObject = intelNewTextureObject; 222 functions->NewTextureImage = intelNewTextureImage; 223 functions->DeleteTextureImage = intelDeleteTextureImage; 224 functions->DeleteTexture = intelDeleteTextureObject; 225 functions->AllocTextureImageBuffer = intel_alloc_texture_image_buffer; 226 functions->FreeTextureImageBuffer = intel_free_texture_image_buffer; 227 functions->MapTextureImage = intel_map_texture_image; 228 functions->UnmapTextureImage = intel_unmap_texture_image; 229} 230