1 /* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 2011 VMware, Inc. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included 14 * in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 20 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 */ 23 24 /** 25 * Functions for mapping/unmapping texture images. 26 */ 27 28 29 #include "main/context.h" 30 #include "main/fbobject.h" 31 #include "main/teximage.h" 32 #include "main/texobj.h" 33 #include "swrast/swrast.h" 34 #include "swrast/s_context.h" 35 36 37 /** 38 * Allocate a new swrast_texture_image (a subclass of gl_texture_image). 39 * Called via ctx->Driver.NewTextureImage(). 40 */ 41 struct gl_texture_image * 42 _swrast_new_texture_image( struct gl_context *ctx ) 43 { 44 (void) ctx; 45 return (struct gl_texture_image *) CALLOC_STRUCT(swrast_texture_image); 46 } 47 48 49 /** 50 * Free a swrast_texture_image (a subclass of gl_texture_image). 51 * Called via ctx->Driver.DeleteTextureImage(). 52 */ 53 void 54 _swrast_delete_texture_image(struct gl_context *ctx, 55 struct gl_texture_image *texImage) 56 { 57 /* Nothing special for the subclass yet */ 58 _mesa_delete_texture_image(ctx, texImage); 59 } 60 61 62 /** 63 * Called via ctx->Driver.AllocTextureImageBuffer() 64 */ 65 GLboolean 66 _swrast_alloc_texture_image_buffer(struct gl_context *ctx, 67 struct gl_texture_image *texImage) 68 { 69 struct swrast_texture_image *swImg = swrast_texture_image(texImage); 70 GLuint bytes = _mesa_format_image_size(texImage->TexFormat, texImage->Width, 71 texImage->Height, texImage->Depth); 72 GLuint i; 73 74 assert(!swImg->Buffer); 75 swImg->Buffer = _mesa_align_malloc(bytes, 512); 76 if (!swImg->Buffer) 77 return GL_FALSE; 78 79 /* RowStride and ImageOffsets[] describe how to address texels in 'Data' */ 80 swImg->RowStride = texImage->Width; 81 82 /* Allocate the ImageOffsets array and initialize to typical values. 83 * We allocate the array for 1D/2D textures too in order to avoid special- 84 * case code in the texstore routines. 85 */ 86 swImg->ImageOffsets = (GLuint *) malloc(texImage->Depth * sizeof(GLuint)); 87 if (!swImg->ImageOffsets) 88 return GL_FALSE; 89 90 for (i = 0; i < texImage->Depth; i++) { 91 swImg->ImageOffsets[i] = i * texImage->Width * texImage->Height; 92 } 93 94 _swrast_init_texture_image(texImage); 95 96 return GL_TRUE; 97 } 98 99 100 /** 101 * Code that overrides ctx->Driver.AllocTextureImageBuffer may use this to 102 * initialize the fields of swrast_texture_image without allocating the image 103 * buffer or initializing ImageOffsets or RowStride. 104 * 105 * Returns GL_TRUE on success, GL_FALSE on memory allocation failure. 106 */ 107 void 108 _swrast_init_texture_image(struct gl_texture_image *texImage) 109 { 110 struct swrast_texture_image *swImg = swrast_texture_image(texImage); 111 112 if ((texImage->Width == 1 || _mesa_is_pow_two(texImage->Width2)) && 113 (texImage->Height == 1 || _mesa_is_pow_two(texImage->Height2)) && 114 (texImage->Depth == 1 || _mesa_is_pow_two(texImage->Depth2))) 115 swImg->_IsPowerOfTwo = GL_TRUE; 116 else 117 swImg->_IsPowerOfTwo = GL_FALSE; 118 119 /* Compute Width/Height/DepthScale for mipmap lod computation */ 120 if (texImage->TexObject->Target == GL_TEXTURE_RECTANGLE_NV) { 121 /* scale = 1.0 since texture coords directly map to texels */ 122 swImg->WidthScale = 1.0; 123 swImg->HeightScale = 1.0; 124 swImg->DepthScale = 1.0; 125 } 126 else { 127 swImg->WidthScale = (GLfloat) texImage->Width; 128 swImg->HeightScale = (GLfloat) texImage->Height; 129 swImg->DepthScale = (GLfloat) texImage->Depth; 130 } 131 } 132 133 134 /** 135 * Called via ctx->Driver.FreeTextureImageBuffer() 136 */ 137 void 138 _swrast_free_texture_image_buffer(struct gl_context *ctx, 139 struct gl_texture_image *texImage) 140 { 141 struct swrast_texture_image *swImage = swrast_texture_image(texImage); 142 if (swImage->Buffer) { 143 _mesa_align_free(swImage->Buffer); 144 swImage->Buffer = NULL; 145 } 146 147 if (swImage->ImageOffsets) { 148 free(swImage->ImageOffsets); 149 swImage->ImageOffsets = NULL; 150 } 151 } 152 153 154 /** 155 * Error checking for debugging only. 156 */ 157 static void 158 _mesa_check_map_teximage(struct gl_texture_image *texImage, 159 GLuint slice, GLuint x, GLuint y, GLuint w, GLuint h) 160 { 161 162 if (texImage->TexObject->Target == GL_TEXTURE_1D) 163 assert(y == 0 && h == 1); 164 165 assert(x < texImage->Width || texImage->Width == 0); 166 assert(y < texImage->Height || texImage->Height == 0); 167 assert(x + w <= texImage->Width); 168 assert(y + h <= texImage->Height); 169 } 170 171 /** 172 * Map a 2D slice of a texture image into user space. 173 * (x,y,w,h) defines a region of interest (ROI). Reading/writing texels 174 * outside of the ROI is undefined. 175 * 176 * \param texImage the texture image 177 * \param slice the 3D image slice or array texture slice 178 * \param x, y, w, h region of interest 179 * \param mode bitmask of GL_MAP_READ_BIT, GL_MAP_WRITE_BIT 180 * \param mapOut returns start of mapping of region of interest 181 * \param rowStrideOut returns row stride (in bytes) 182 */ 183 void 184 _swrast_map_teximage(struct gl_context *ctx, 185 struct gl_texture_image *texImage, 186 GLuint slice, 187 GLuint x, GLuint y, GLuint w, GLuint h, 188 GLbitfield mode, 189 GLubyte **mapOut, 190 GLint *rowStrideOut) 191 { 192 struct swrast_texture_image *swImage = swrast_texture_image(texImage); 193 GLubyte *map; 194 GLint stride, texelSize; 195 GLuint bw, bh; 196 197 _mesa_check_map_teximage(texImage, slice, x, y, w, h); 198 199 texelSize = _mesa_get_format_bytes(texImage->TexFormat); 200 stride = _mesa_format_row_stride(texImage->TexFormat, texImage->Width); 201 _mesa_get_format_block_size(texImage->TexFormat, &bw, &bh); 202 203 assert(x % bw == 0); 204 assert(y % bh == 0); 205 206 if (!swImage->Buffer) { 207 /* probably ran out of memory when allocating tex mem */ 208 *mapOut = NULL; 209 return; 210 } 211 212 map = swImage->Buffer; 213 214 if (texImage->TexObject->Target == GL_TEXTURE_3D || 215 texImage->TexObject->Target == GL_TEXTURE_2D_ARRAY) { 216 GLuint sliceSize = _mesa_format_image_size(texImage->TexFormat, 217 texImage->Width, 218 texImage->Height, 219 1); 220 assert(slice < texImage->Depth); 221 map += slice * sliceSize; 222 } else if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) { 223 GLuint sliceSize = _mesa_format_image_size(texImage->TexFormat, 224 texImage->Width, 225 1, 226 1); 227 assert(slice < texImage->Height); 228 map += slice * sliceSize; 229 } 230 231 /* apply x/y offset to map address */ 232 map += stride * (y / bh) + texelSize * (x / bw); 233 234 *mapOut = map; 235 *rowStrideOut = stride; 236 } 237 238 void 239 _swrast_unmap_teximage(struct gl_context *ctx, 240 struct gl_texture_image *texImage, 241 GLuint slice) 242 { 243 /* nop */ 244 } 245 246 247 void 248 _swrast_map_texture(struct gl_context *ctx, struct gl_texture_object *texObj) 249 { 250 const GLuint faces = _mesa_num_tex_faces(texObj->Target); 251 GLuint face, level; 252 253 for (face = 0; face < faces; face++) { 254 for (level = texObj->BaseLevel; level < MAX_TEXTURE_LEVELS; level++) { 255 struct gl_texture_image *texImage = texObj->Image[face][level]; 256 if (texImage) { 257 struct swrast_texture_image *swImage = 258 swrast_texture_image(texImage); 259 260 /* XXX we'll eventually call _swrast_map_teximage() here */ 261 swImage->Map = swImage->Buffer; 262 } 263 } 264 } 265 } 266 267 268 void 269 _swrast_unmap_texture(struct gl_context *ctx, struct gl_texture_object *texObj) 270 { 271 const GLuint faces = _mesa_num_tex_faces(texObj->Target); 272 GLuint face, level; 273 274 for (face = 0; face < faces; face++) { 275 for (level = texObj->BaseLevel; level < MAX_TEXTURE_LEVELS; level++) { 276 struct gl_texture_image *texImage = texObj->Image[face][level]; 277 if (texImage) { 278 struct swrast_texture_image *swImage 279 = swrast_texture_image(texImage); 280 281 /* XXX we'll eventually call _swrast_unmap_teximage() here */ 282 swImage->Map = NULL; 283 } 284 } 285 } 286 } 287 288 289 /** 290 * Map all textures for reading prior to software rendering. 291 */ 292 void 293 _swrast_map_textures(struct gl_context *ctx) 294 { 295 GLbitfield enabledUnits = ctx->Texture._EnabledUnits; 296 297 /* loop over enabled texture units */ 298 while (enabledUnits) { 299 GLuint unit = ffs(enabledUnits) - 1; 300 struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current; 301 302 _swrast_map_texture(ctx, texObj); 303 304 enabledUnits &= ~(1 << unit); 305 } 306 } 307 308 309 /** 310 * Unmap all textures for reading prior to software rendering. 311 */ 312 void 313 _swrast_unmap_textures(struct gl_context *ctx) 314 { 315 GLbitfield enabledUnits = ctx->Texture._EnabledUnits; 316 317 /* loop over enabled texture units */ 318 while (enabledUnits) { 319 GLuint unit = ffs(enabledUnits) - 1; 320 struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current; 321 322 _swrast_unmap_texture(ctx, texObj); 323 324 enabledUnits &= ~(1 << unit); 325 } 326 } 327 328 329 /** 330 * Called via ctx->Driver.AllocTextureStorage() 331 * Just have to allocate memory for the texture images. 332 */ 333 GLboolean 334 _swrast_AllocTextureStorage(struct gl_context *ctx, 335 struct gl_texture_object *texObj, 336 GLsizei levels, GLsizei width, 337 GLsizei height, GLsizei depth) 338 { 339 const GLint numFaces = (texObj->Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1; 340 GLint face, level; 341 342 for (face = 0; face < numFaces; face++) { 343 for (level = 0; level < levels; level++) { 344 struct gl_texture_image *texImage = texObj->Image[face][level]; 345 if (!_swrast_alloc_texture_image_buffer(ctx, texImage)) { 346 return GL_FALSE; 347 } 348 } 349 } 350 351 return GL_TRUE; 352 } 353 354