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