2 * Mesa 3-D graphics library
4 * Copyright (C) 2011 VMware, Inc.
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:
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
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 OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
26 * Functions for mapping/unmapping texture images.
30 #include "main/context.h"
31 #include "main/fbobject.h"
32 #include "main/teximage.h"
33 #include "main/texobj.h"
34 #include "swrast/swrast.h"
35 #include "swrast/s_context.h"
39 * Allocate a new swrast_texture_image (a subclass of gl_texture_image).
40 * Called via ctx->Driver.NewTextureImage().
42 struct gl_texture_image *
43 _swrast_new_texture_image( struct gl_context *ctx )
46 return (struct gl_texture_image *) CALLOC_STRUCT(swrast_texture_image);
51 * Free a swrast_texture_image (a subclass of gl_texture_image).
52 * Called via ctx->Driver.DeleteTextureImage().
55 _swrast_delete_texture_image(struct gl_context *ctx,
56 struct gl_texture_image *texImage)
58 /* Nothing special for the subclass yet */
59 _mesa_delete_texture_image(ctx, texImage);
63 texture_slices(struct gl_texture_image *texImage)
65 if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY)
66 return texImage->Height;
68 return texImage->Depth;
72 _swrast_teximage_slice_height(struct gl_texture_image *texImage)
74 /* For 1D array textures, the slices are all 1 pixel high, and Height is
75 * the number of slices.
77 if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY)
80 return texImage->Height;
84 * Called via ctx->Driver.AllocTextureImageBuffer()
87 _swrast_alloc_texture_image_buffer(struct gl_context *ctx,
88 struct gl_texture_image *texImage)
90 struct swrast_texture_image *swImg = swrast_texture_image(texImage);
91 GLuint bytes = _mesa_format_image_size(texImage->TexFormat, texImage->Width,
92 texImage->Height, texImage->Depth);
95 if (!_swrast_init_texture_image(texImage))
98 assert(!swImg->Buffer);
99 swImg->Buffer = _mesa_align_malloc(bytes, 512);
103 /* RowStride and ImageOffsets[] describe how to address texels in 'Data' */
104 swImg->RowStride = texImage->Width;
106 for (i = 0; i < texture_slices(texImage); i++) {
107 swImg->ImageOffsets[i] = i * texImage->Width * texImage->Height;
115 * Code that overrides ctx->Driver.AllocTextureImageBuffer may use this to
116 * initialize the fields of swrast_texture_image without allocating the image
117 * buffer or initializing RowStride or the contents of ImageOffsets.
119 * Returns GL_TRUE on success, GL_FALSE on memory allocation failure.
122 _swrast_init_texture_image(struct gl_texture_image *texImage)
124 struct swrast_texture_image *swImg = swrast_texture_image(texImage);
126 if ((texImage->Width == 1 || _mesa_is_pow_two(texImage->Width2)) &&
127 (texImage->Height == 1 || _mesa_is_pow_two(texImage->Height2)) &&
128 (texImage->Depth == 1 || _mesa_is_pow_two(texImage->Depth2)))
129 swImg->_IsPowerOfTwo = GL_TRUE;
131 swImg->_IsPowerOfTwo = GL_FALSE;
133 /* Compute Width/Height/DepthScale for mipmap lod computation */
134 if (texImage->TexObject->Target == GL_TEXTURE_RECTANGLE_NV) {
135 /* scale = 1.0 since texture coords directly map to texels */
136 swImg->WidthScale = 1.0;
137 swImg->HeightScale = 1.0;
138 swImg->DepthScale = 1.0;
141 swImg->WidthScale = (GLfloat) texImage->Width;
142 swImg->HeightScale = (GLfloat) texImage->Height;
143 swImg->DepthScale = (GLfloat) texImage->Depth;
146 assert(!swImg->ImageOffsets);
147 swImg->ImageOffsets = malloc(texture_slices(texImage) * sizeof(GLuint));
148 if (!swImg->ImageOffsets)
156 * Called via ctx->Driver.FreeTextureImageBuffer()
159 _swrast_free_texture_image_buffer(struct gl_context *ctx,
160 struct gl_texture_image *texImage)
162 struct swrast_texture_image *swImage = swrast_texture_image(texImage);
163 if (swImage->Buffer) {
164 _mesa_align_free(swImage->Buffer);
165 swImage->Buffer = NULL;
168 free(swImage->ImageOffsets);
169 swImage->ImageOffsets = NULL;
174 * Error checking for debugging only.
177 _mesa_check_map_teximage(struct gl_texture_image *texImage,
178 GLuint slice, GLuint x, GLuint y, GLuint w, GLuint h)
181 if (texImage->TexObject->Target == GL_TEXTURE_1D)
182 assert(y == 0 && h == 1);
184 assert(x < texImage->Width || texImage->Width == 0);
185 assert(y < texImage->Height || texImage->Height == 0);
186 assert(x + w <= texImage->Width);
187 assert(y + h <= texImage->Height);
191 * Map a 2D slice of a texture image into user space.
192 * (x,y,w,h) defines a region of interest (ROI). Reading/writing texels
193 * outside of the ROI is undefined.
195 * \param texImage the texture image
196 * \param slice the 3D image slice or array texture slice
197 * \param x, y, w, h region of interest
198 * \param mode bitmask of GL_MAP_READ_BIT, GL_MAP_WRITE_BIT
199 * \param mapOut returns start of mapping of region of interest
200 * \param rowStrideOut returns row stride (in bytes)
203 _swrast_map_teximage(struct gl_context *ctx,
204 struct gl_texture_image *texImage,
206 GLuint x, GLuint y, GLuint w, GLuint h,
211 struct swrast_texture_image *swImage = swrast_texture_image(texImage);
213 GLint stride, texelSize;
216 _mesa_check_map_teximage(texImage, slice, x, y, w, h);
218 texelSize = _mesa_get_format_bytes(texImage->TexFormat);
219 stride = _mesa_format_row_stride(texImage->TexFormat, texImage->Width);
220 _mesa_get_format_block_size(texImage->TexFormat, &bw, &bh);
225 if (!swImage->Buffer) {
226 /* probably ran out of memory when allocating tex mem */
231 map = swImage->Buffer;
233 assert(slice < texture_slices(texImage));
235 GLuint sliceSize = _mesa_format_image_size(texImage->TexFormat,
237 _swrast_teximage_slice_height(texImage),
239 map += slice * sliceSize;
242 /* apply x/y offset to map address */
243 map += stride * (y / bh) + texelSize * (x / bw);
246 *rowStrideOut = stride;
250 _swrast_unmap_teximage(struct gl_context *ctx,
251 struct gl_texture_image *texImage,
259 _swrast_map_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
261 const GLuint faces = _mesa_num_tex_faces(texObj->Target);
264 for (face = 0; face < faces; face++) {
265 for (level = texObj->BaseLevel; level < MAX_TEXTURE_LEVELS; level++) {
266 struct gl_texture_image *texImage = texObj->Image[face][level];
268 struct swrast_texture_image *swImage =
269 swrast_texture_image(texImage);
271 /* XXX we'll eventually call _swrast_map_teximage() here */
272 swImage->Map = swImage->Buffer;
280 _swrast_unmap_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
282 const GLuint faces = _mesa_num_tex_faces(texObj->Target);
285 for (face = 0; face < faces; face++) {
286 for (level = texObj->BaseLevel; level < MAX_TEXTURE_LEVELS; level++) {
287 struct gl_texture_image *texImage = texObj->Image[face][level];
289 struct swrast_texture_image *swImage
290 = swrast_texture_image(texImage);
292 /* XXX we'll eventually call _swrast_unmap_teximage() here */
301 * Map all textures for reading prior to software rendering.
304 _swrast_map_textures(struct gl_context *ctx)
306 GLbitfield enabledUnits = ctx->Texture._EnabledUnits;
308 /* loop over enabled texture units */
309 while (enabledUnits) {
310 GLuint unit = ffs(enabledUnits) - 1;
311 struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
313 _swrast_map_texture(ctx, texObj);
315 enabledUnits &= ~(1 << unit);
321 * Unmap all textures for reading prior to software rendering.
324 _swrast_unmap_textures(struct gl_context *ctx)
326 GLbitfield enabledUnits = ctx->Texture._EnabledUnits;
328 /* loop over enabled texture units */
329 while (enabledUnits) {
330 GLuint unit = ffs(enabledUnits) - 1;
331 struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
333 _swrast_unmap_texture(ctx, texObj);
335 enabledUnits &= ~(1 << unit);