• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 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.
23  */
24 
25 /**
26  * Functions for mapping/unmapping texture images.
27  */
28 
29 
30 #include "main/context.h"
31 #include "main/fbobject.h"
32 #include "main/teximage.h"
33 #include "main/texobj.h"
34 #include "util/u_memory.h"
35 #include "util/u_math.h"
36 #include "swrast/swrast.h"
37 #include "swrast/s_context.h"
38 
39 
40 /**
41  * Allocate a new swrast_texture_image (a subclass of gl_texture_image).
42  * Called via ctx->Driver.NewTextureImage().
43  */
44 struct gl_texture_image *
_swrast_new_texture_image(struct gl_context * ctx)45 _swrast_new_texture_image( struct gl_context *ctx )
46 {
47    (void) ctx;
48    return (struct gl_texture_image *) CALLOC_STRUCT(swrast_texture_image);
49 }
50 
51 
52 /**
53  * Free a swrast_texture_image (a subclass of gl_texture_image).
54  * Called via ctx->Driver.DeleteTextureImage().
55  */
56 void
_swrast_delete_texture_image(struct gl_context * ctx,struct gl_texture_image * texImage)57 _swrast_delete_texture_image(struct gl_context *ctx,
58                              struct gl_texture_image *texImage)
59 {
60    /* Nothing special for the subclass yet */
61    _mesa_delete_texture_image(ctx, texImage);
62 }
63 
64 static unsigned int
texture_slices(const struct gl_texture_image * texImage)65 texture_slices(const struct gl_texture_image *texImage)
66 {
67    if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY)
68       return texImage->Height;
69    else
70       return texImage->Depth;
71 }
72 
73 unsigned int
_swrast_teximage_slice_height(struct gl_texture_image * texImage)74 _swrast_teximage_slice_height(struct gl_texture_image *texImage)
75 {
76    /* For 1D array textures, the slices are all 1 pixel high, and Height is
77     * the number of slices.
78     */
79    if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY)
80       return 1;
81    else
82       return texImage->Height;
83 }
84 
85 /**
86  * Called via ctx->Driver.AllocTextureImageBuffer()
87  */
88 GLboolean
_swrast_alloc_texture_image_buffer(struct gl_context * ctx,struct gl_texture_image * texImage)89 _swrast_alloc_texture_image_buffer(struct gl_context *ctx,
90                                    struct gl_texture_image *texImage)
91 {
92    struct swrast_texture_image *swImg = swrast_texture_image(texImage);
93    GLuint bytesPerSlice;
94    GLuint slices = texture_slices(texImage);
95    GLuint i;
96 
97    if (!_swrast_init_texture_image(texImage))
98       return GL_FALSE;
99 
100    bytesPerSlice = _mesa_format_image_size(texImage->TexFormat, texImage->Width,
101                                            _swrast_teximage_slice_height(texImage), 1);
102 
103    assert(!swImg->Buffer);
104    swImg->Buffer = align_malloc(bytesPerSlice * slices, 512);
105    if (!swImg->Buffer)
106       return GL_FALSE;
107 
108    /* RowStride and ImageSlices[] describe how to address texels in 'Data' */
109    swImg->RowStride = _mesa_format_row_stride(texImage->TexFormat,
110                                               texImage->Width);
111 
112    for (i = 0; i < slices; i++) {
113       swImg->ImageSlices[i] = swImg->Buffer + bytesPerSlice * i;
114    }
115 
116    return GL_TRUE;
117 }
118 
119 
120 /**
121  * Code that overrides ctx->Driver.AllocTextureImageBuffer may use this to
122  * initialize the fields of swrast_texture_image without allocating the image
123  * buffer or initializing RowStride or the contents of ImageSlices.
124  *
125  * Returns GL_TRUE on success, GL_FALSE on memory allocation failure.
126  */
127 GLboolean
_swrast_init_texture_image(struct gl_texture_image * texImage)128 _swrast_init_texture_image(struct gl_texture_image *texImage)
129 {
130    struct swrast_texture_image *swImg = swrast_texture_image(texImage);
131 
132    if ((texImage->Width == 1 || util_is_power_of_two_or_zero(texImage->Width2)) &&
133        (texImage->Height == 1 || util_is_power_of_two_or_zero(texImage->Height2)) &&
134        (texImage->Depth == 1 || util_is_power_of_two_or_zero(texImage->Depth2)))
135       swImg->_IsPowerOfTwo = GL_TRUE;
136    else
137       swImg->_IsPowerOfTwo = GL_FALSE;
138 
139    /* Compute Width/Height/DepthScale for mipmap lod computation */
140    if (texImage->TexObject->Target == GL_TEXTURE_RECTANGLE_NV) {
141       /* scale = 1.0 since texture coords directly map to texels */
142       swImg->WidthScale = 1.0;
143       swImg->HeightScale = 1.0;
144       swImg->DepthScale = 1.0;
145    }
146    else {
147       swImg->WidthScale = (GLfloat) texImage->Width;
148       swImg->HeightScale = (GLfloat) texImage->Height;
149       swImg->DepthScale = (GLfloat) texImage->Depth;
150    }
151 
152    assert(!swImg->ImageSlices);
153    swImg->ImageSlices = calloc(texture_slices(texImage), sizeof(void *));
154    if (!swImg->ImageSlices)
155       return GL_FALSE;
156 
157    return GL_TRUE;
158 }
159 
160 
161 /**
162  * Called via ctx->Driver.FreeTextureImageBuffer()
163  */
164 void
_swrast_free_texture_image_buffer(struct gl_context * ctx,struct gl_texture_image * texImage)165 _swrast_free_texture_image_buffer(struct gl_context *ctx,
166                                   struct gl_texture_image *texImage)
167 {
168    struct swrast_texture_image *swImage = swrast_texture_image(texImage);
169 
170    align_free(swImage->Buffer);
171    swImage->Buffer = NULL;
172 
173    free(swImage->ImageSlices);
174    swImage->ImageSlices = NULL;
175 }
176 
177 
178 /**
179  * Error checking for debugging only.
180  */
181 static void
check_map_teximage(const struct gl_texture_image * texImage,GLuint slice,GLuint x,GLuint y,GLuint w,GLuint h)182 check_map_teximage(const struct gl_texture_image *texImage,
183                    GLuint slice, GLuint x, GLuint y, GLuint w, GLuint h)
184 {
185 
186    if (texImage->TexObject->Target == GL_TEXTURE_1D)
187       assert(y == 0 && h == 1);
188 
189    assert(x < texImage->Width || texImage->Width == 0);
190    assert(y < texImage->Height || texImage->Height == 0);
191    assert(x + w <= texImage->Width);
192    assert(y + h <= texImage->Height);
193    assert(slice < texture_slices(texImage));
194 }
195 
196 /**
197  * Map a 2D slice of a texture image into user space.
198  * (x,y,w,h) defines a region of interest (ROI).  Reading/writing texels
199  * outside of the ROI is undefined.
200  *
201  * \param texImage  the texture image
202  * \param slice  the 3D image slice or array texture slice
203  * \param x, y, w, h  region of interest
204  * \param mode  bitmask of GL_MAP_READ_BIT, GL_MAP_WRITE_BIT
205  * \param mapOut  returns start of mapping of region of interest
206  * \param rowStrideOut  returns row stride (in bytes)
207  */
208 void
_swrast_map_teximage(struct gl_context * ctx,struct gl_texture_image * texImage,GLuint slice,GLuint x,GLuint y,GLuint w,GLuint h,GLbitfield mode,GLubyte ** mapOut,GLint * rowStrideOut)209 _swrast_map_teximage(struct gl_context *ctx,
210                      struct gl_texture_image *texImage,
211                      GLuint slice,
212                      GLuint x, GLuint y, GLuint w, GLuint h,
213                      GLbitfield mode,
214                      GLubyte **mapOut,
215                      GLint *rowStrideOut)
216 {
217    struct swrast_texture_image *swImage = swrast_texture_image(texImage);
218    GLubyte *map;
219    GLint stride, texelSize;
220    GLuint bw, bh;
221 
222    check_map_teximage(texImage, slice, x, y, w, h);
223 
224    if (!swImage->Buffer) {
225       /* Either glTexImage was called with a NULL <pixels> argument or
226        * we ran out of memory when allocating texture memory,
227        */
228       *mapOut = NULL;
229       *rowStrideOut = 0;
230       return;
231    }
232 
233    texelSize = _mesa_get_format_bytes(texImage->TexFormat);
234    stride = _mesa_format_row_stride(texImage->TexFormat, texImage->Width);
235    _mesa_get_format_block_size(texImage->TexFormat, &bw, &bh);
236 
237    assert(x % bw == 0);
238    assert(y % bh == 0);
239 
240    /* This function can only be used with a swrast-allocated buffer, in which
241     * case ImageSlices is populated with pointers into Buffer.
242     */
243    assert(swImage->Buffer);
244    assert(swImage->Buffer == swImage->ImageSlices[0]);
245 
246    map = swImage->ImageSlices[slice];
247 
248    /* apply x/y offset to map address */
249    map += stride * (y / bh) + texelSize * (x / bw);
250 
251    *mapOut = map;
252    *rowStrideOut = stride;
253 }
254 
255 void
_swrast_unmap_teximage(struct gl_context * ctx,struct gl_texture_image * texImage,GLuint slice)256 _swrast_unmap_teximage(struct gl_context *ctx,
257                        struct gl_texture_image *texImage,
258                        GLuint slice)
259 {
260    /* nop */
261 }
262 
263 
264 void
_swrast_map_texture(struct gl_context * ctx,struct gl_texture_object * texObj)265 _swrast_map_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
266 {
267    const GLuint faces = _mesa_num_tex_faces(texObj->Target);
268    GLuint face, level;
269 
270    for (face = 0; face < faces; face++) {
271       for (level = texObj->Attrib.BaseLevel; level < MAX_TEXTURE_LEVELS; level++) {
272          struct gl_texture_image *texImage = texObj->Image[face][level];
273          struct swrast_texture_image *swImage = swrast_texture_image(texImage);
274          unsigned int i, slices;
275 
276          if (!texImage)
277             continue;
278 
279          /* In the case of a swrast-allocated texture buffer, the ImageSlices
280           * and RowStride are always available.
281           */
282          if (swImage->Buffer) {
283             assert(swImage->ImageSlices[0] == swImage->Buffer);
284             continue;
285          }
286 
287          if (!swImage->ImageSlices) {
288             swImage->ImageSlices =
289                calloc(texture_slices(texImage), sizeof(void *));
290             if (!swImage->ImageSlices)
291                continue;
292          }
293 
294          slices = texture_slices(texImage);
295 
296          for (i = 0; i < slices; i++) {
297             GLubyte *map;
298             GLint rowStride;
299 
300             if (swImage->ImageSlices[i])
301                continue;
302 
303             ctx->Driver.MapTextureImage(ctx, texImage, i,
304                                         0, 0,
305                                         texImage->Width, texImage->Height,
306                                         GL_MAP_READ_BIT | GL_MAP_WRITE_BIT,
307                                         &map, &rowStride);
308 
309             swImage->ImageSlices[i] = map;
310             /* A swrast-using driver has to return the same rowstride for
311              * every slice of the same texture, since we don't track them
312              * separately.
313              */
314             if (i == 0)
315                swImage->RowStride = rowStride;
316             else
317                assert(swImage->RowStride == rowStride);
318          }
319       }
320    }
321 }
322 
323 
324 void
_swrast_unmap_texture(struct gl_context * ctx,struct gl_texture_object * texObj)325 _swrast_unmap_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
326 {
327    const GLuint faces = _mesa_num_tex_faces(texObj->Target);
328    GLuint face, level;
329 
330    for (face = 0; face < faces; face++) {
331       for (level = texObj->Attrib.BaseLevel; level < MAX_TEXTURE_LEVELS; level++) {
332          struct gl_texture_image *texImage = texObj->Image[face][level];
333          struct swrast_texture_image *swImage = swrast_texture_image(texImage);
334          unsigned int i, slices;
335 
336          if (!texImage)
337             continue;
338 
339          if (swImage->Buffer)
340             return;
341 
342          if (!swImage->ImageSlices)
343             continue;
344 
345          slices = texture_slices(texImage);
346 
347          for (i = 0; i < slices; i++) {
348             if (swImage->ImageSlices[i]) {
349                ctx->Driver.UnmapTextureImage(ctx, texImage, i);
350                swImage->ImageSlices[i] = NULL;
351             }
352          }
353       }
354    }
355 }
356 
357 
358 /**
359  * Map all textures for reading prior to software rendering.
360  */
361 void
_swrast_map_textures(struct gl_context * ctx)362 _swrast_map_textures(struct gl_context *ctx)
363 {
364    int unit;
365 
366    for (unit = 0; unit <= ctx->Texture._MaxEnabledTexImageUnit; unit++) {
367       struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
368 
369       if (texObj)
370          _swrast_map_texture(ctx, texObj);
371    }
372 }
373 
374 
375 /**
376  * Unmap all textures for reading prior to software rendering.
377  */
378 void
_swrast_unmap_textures(struct gl_context * ctx)379 _swrast_unmap_textures(struct gl_context *ctx)
380 {
381    int unit;
382    for (unit = 0; unit <= ctx->Texture._MaxEnabledTexImageUnit; unit++) {
383       struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
384 
385       if (texObj)
386          _swrast_unmap_texture(ctx, texObj);
387    }
388 }
389