intel_tex.c revision 455a19b1b3d7ca0a40c65d89e45209dbd8ac7b35
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_context *intel = intel_context(ctx); 47 struct intel_texture_object *intelObj = intel_texture_object(texObj); 48 49 if (intelObj->mt) 50 intel_miptree_release(intel, &intelObj->mt); 51 52 _mesa_delete_texture_object(ctx, texObj); 53} 54 55 56static void 57intel_free_texture_image_buffer(struct gl_context * ctx, 58 struct gl_texture_image *texImage) 59{ 60 struct intel_context *intel = intel_context(ctx); 61 struct intel_texture_image *intelImage = intel_texture_image(texImage); 62 63 DBG("%s\n", __FUNCTION__); 64 65 if (intelImage->mt) { 66 intel_miptree_release(intel, &intelImage->mt); 67 } 68 69 if (texImage->Data) { 70 _mesa_free_texmemory(texImage->Data); 71 texImage->Data = NULL; 72 } 73 74 if (intelImage->depth_rb) { 75 _mesa_reference_renderbuffer(&intelImage->depth_rb, NULL); 76 } 77 78 if (intelImage->stencil_rb) { 79 _mesa_reference_renderbuffer(&intelImage->stencil_rb, NULL); 80 } 81} 82 83/** 84 * Map texture memory/buffer into user space. 85 * Note: the region of interest parameters are ignored here. 86 * \param mapOut returns start of mapping of region of interest 87 * \param rowStrideOut returns row stride in bytes 88 */ 89static void 90intel_map_texture_image(struct gl_context *ctx, 91 struct gl_texture_image *tex_image, 92 GLuint slice, 93 GLuint x, GLuint y, GLuint w, GLuint h, 94 GLbitfield mode, 95 GLubyte **map, 96 GLint *stride) 97{ 98 struct intel_context *intel = intel_context(ctx); 99 struct intel_texture_image *intel_image = intel_texture_image(tex_image); 100 struct intel_mipmap_tree *mt = intel_image->mt; 101 unsigned int bw, bh; 102 103 if (intel_image->stencil_rb) { 104 /* 105 * The texture has packed depth/stencil format, but uses separate 106 * stencil. The texture's embedded stencil buffer contains the real 107 * stencil data, so copy that into the miptree. 108 */ 109 intel_tex_image_s8z24_gather(intel, intel_image); 110 } 111 112 /* For compressed formats, the stride is the number of bytes per 113 * row of blocks. intel_miptree_get_image_offset() already does 114 * the divide. 115 */ 116 _mesa_get_format_block_size(tex_image->TexFormat, &bw, &bh); 117 assert(y % bh == 0); 118 y /= bh; 119 120 if (likely(mt)) { 121 void *base = intel_region_map(intel, mt->region); 122 unsigned int image_x, image_y; 123 124 intel_miptree_get_image_offset(mt, tex_image->Level, tex_image->Face, 125 slice, &image_x, &image_y); 126 x += image_x; 127 y += image_y; 128 129 *stride = mt->region->pitch * mt->cpp; 130 *map = base + y * *stride + x * mt->cpp; 131 } else { 132 /* texture data is in malloc'd memory */ 133 GLuint width = tex_image->Width; 134 GLuint height = ALIGN(tex_image->Height, bh) / bh; 135 GLuint texelSize = _mesa_get_format_bytes(tex_image->TexFormat); 136 137 assert(map); 138 139 *stride = _mesa_format_row_stride(tex_image->TexFormat, width); 140 *map = tex_image->Data + (slice * height + y) * *stride + x * texelSize; 141 142 return; 143 } 144} 145 146static void 147intel_unmap_texture_image(struct gl_context *ctx, 148 struct gl_texture_image *tex_image, GLuint slice) 149{ 150 struct intel_context *intel = intel_context(ctx); 151 struct intel_texture_image *intel_image = intel_texture_image(tex_image); 152 153 if (intel_image->mt) 154 intel_region_unmap(intel, intel_image->mt->region); 155 156 if (intel_image->stencil_rb) { 157 /* 158 * The texture has packed depth/stencil format, but uses separate 159 * stencil. The texture's embedded stencil buffer contains the real 160 * stencil data, so copy that into the miptree. 161 */ 162 intel_tex_image_s8z24_scatter(intel, intel_image); 163 } 164} 165 166/** 167 * Called via ctx->Driver.GenerateMipmap() 168 * This is basically a wrapper for _mesa_meta_GenerateMipmap() which checks 169 * if we'll be using software mipmap generation. In that case, we need to 170 * map/unmap the base level texture image. 171 */ 172static void 173intelGenerateMipmap(struct gl_context *ctx, GLenum target, 174 struct gl_texture_object *texObj) 175{ 176 if (_mesa_meta_check_generate_mipmap_fallback(ctx, target, texObj)) { 177 /* sw path: need to map texture images */ 178 struct intel_context *intel = intel_context(ctx); 179 struct intel_texture_object *intelObj = intel_texture_object(texObj); 180 struct gl_texture_image *first_image = texObj->Image[0][texObj->BaseLevel]; 181 182 fallback_debug("%s - fallback to swrast\n", __FUNCTION__); 183 184 intel_tex_map_level_images(intel, intelObj, texObj->BaseLevel); 185 _mesa_generate_mipmap(ctx, target, texObj); 186 intel_tex_unmap_level_images(intel, intelObj, texObj->BaseLevel); 187 188 if (!_mesa_is_format_compressed(first_image->TexFormat)) { 189 GLuint nr_faces = (texObj->Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; 190 GLuint face, i; 191 for (face = 0; face < nr_faces; face++) { 192 for (i = texObj->BaseLevel + 1; i < texObj->MaxLevel; i++) { 193 struct intel_texture_image *intelImage = 194 intel_texture_image(texObj->Image[face][i]); 195 if (!intelImage) 196 break; 197 /* Unreference the miptree to signal that the new Data is a 198 * bare pointer from mesa. 199 */ 200 intel_miptree_release(intel, &intelImage->mt); 201 } 202 } 203 } 204 } 205 else { 206 _mesa_meta_GenerateMipmap(ctx, target, texObj); 207 } 208} 209 210 211void 212intelInitTextureFuncs(struct dd_function_table *functions) 213{ 214 functions->GenerateMipmap = intelGenerateMipmap; 215 216 functions->NewTextureObject = intelNewTextureObject; 217 functions->NewTextureImage = intelNewTextureImage; 218 functions->DeleteTextureImage = intelDeleteTextureImage; 219 functions->DeleteTexture = intelDeleteTextureObject; 220 functions->FreeTextureImageBuffer = intel_free_texture_image_buffer; 221 functions->MapTextureImage = intel_map_texture_image; 222 functions->UnmapTextureImage = intel_unmap_texture_image; 223} 224