OSDN Git Service

swrast: Move ImageOffsets allocation to shared code.
[android-x86/external-mesa.git] / src / mesa / swrast / s_texture.c
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 *
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
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
63 texture_slices(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
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
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 bytes = _mesa_format_image_size(texImage->TexFormat, texImage->Width,
92                                           texImage->Height, texImage->Depth);
93    GLuint i;
94
95    if (!_swrast_init_texture_image(texImage))
96       return GL_FALSE;
97
98    assert(!swImg->Buffer);
99    swImg->Buffer = _mesa_align_malloc(bytes, 512);
100    if (!swImg->Buffer)
101       return GL_FALSE;
102
103    /* RowStride and ImageOffsets[] describe how to address texels in 'Data' */
104    swImg->RowStride = texImage->Width;
105
106    for (i = 0; i < texture_slices(texImage); i++) {
107       swImg->ImageOffsets[i] = i * texImage->Width * texImage->Height;
108    }
109
110    return GL_TRUE;
111 }
112
113
114 /**
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.
118  *
119  * Returns GL_TRUE on success, GL_FALSE on memory allocation failure.
120  */
121 GLboolean
122 _swrast_init_texture_image(struct gl_texture_image *texImage)
123 {
124    struct swrast_texture_image *swImg = swrast_texture_image(texImage);
125
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;
130    else
131       swImg->_IsPowerOfTwo = GL_FALSE;
132
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;
139    }
140    else {
141       swImg->WidthScale = (GLfloat) texImage->Width;
142       swImg->HeightScale = (GLfloat) texImage->Height;
143       swImg->DepthScale = (GLfloat) texImage->Depth;
144    }
145
146    assert(!swImg->ImageOffsets);
147    swImg->ImageOffsets = malloc(texture_slices(texImage) * sizeof(GLuint));
148    if (!swImg->ImageOffsets)
149       return GL_FALSE;
150
151    return GL_TRUE;
152 }
153
154
155 /**
156  * Called via ctx->Driver.FreeTextureImageBuffer()
157  */
158 void
159 _swrast_free_texture_image_buffer(struct gl_context *ctx,
160                                   struct gl_texture_image *texImage)
161 {
162    struct swrast_texture_image *swImage = swrast_texture_image(texImage);
163    if (swImage->Buffer) {
164       _mesa_align_free(swImage->Buffer);
165       swImage->Buffer = NULL;
166    }
167
168    free(swImage->ImageOffsets);
169    swImage->ImageOffsets = NULL;
170 }
171
172
173 /**
174  * Error checking for debugging only.
175  */
176 static void
177 _mesa_check_map_teximage(struct gl_texture_image *texImage,
178                          GLuint slice, GLuint x, GLuint y, GLuint w, GLuint h)
179 {
180
181    if (texImage->TexObject->Target == GL_TEXTURE_1D)
182       assert(y == 0 && h == 1);
183
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);
188 }
189
190 /**
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.
194  *
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)
201  */
202 void
203 _swrast_map_teximage(struct gl_context *ctx,
204                      struct gl_texture_image *texImage,
205                      GLuint slice,
206                      GLuint x, GLuint y, GLuint w, GLuint h,
207                      GLbitfield mode,
208                      GLubyte **mapOut,
209                      GLint *rowStrideOut)
210 {
211    struct swrast_texture_image *swImage = swrast_texture_image(texImage);
212    GLubyte *map;
213    GLint stride, texelSize;
214    GLuint bw, bh;
215
216    _mesa_check_map_teximage(texImage, slice, x, y, w, h);
217
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);
221
222    assert(x % bw == 0);
223    assert(y % bh == 0);
224
225    if (!swImage->Buffer) {
226       /* probably ran out of memory when allocating tex mem */
227       *mapOut = NULL;
228       return;
229    }
230       
231    map = swImage->Buffer;
232
233    assert(slice < texture_slices(texImage));
234    if (slice != 0) {
235       GLuint sliceSize = _mesa_format_image_size(texImage->TexFormat,
236                                                  texImage->Width,
237                                                  _swrast_teximage_slice_height(texImage),
238                                                  1);
239       map += slice * sliceSize;
240    }
241
242    /* apply x/y offset to map address */
243    map += stride * (y / bh) + texelSize * (x / bw);
244
245    *mapOut = map;
246    *rowStrideOut = stride;
247 }
248
249 void
250 _swrast_unmap_teximage(struct gl_context *ctx,
251                        struct gl_texture_image *texImage,
252                        GLuint slice)
253 {
254    /* nop */
255 }
256
257
258 void
259 _swrast_map_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
260 {
261    const GLuint faces = _mesa_num_tex_faces(texObj->Target);
262    GLuint face, level;
263
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];
267          if (texImage) {
268             struct swrast_texture_image *swImage =
269                swrast_texture_image(texImage);
270
271             /* XXX we'll eventually call _swrast_map_teximage() here */
272             swImage->Map = swImage->Buffer;
273          }
274       }
275    }
276 }
277
278
279 void
280 _swrast_unmap_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
281 {
282    const GLuint faces = _mesa_num_tex_faces(texObj->Target);
283    GLuint face, level;
284
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];
288          if (texImage) {
289             struct swrast_texture_image *swImage
290                = swrast_texture_image(texImage);
291
292             /* XXX we'll eventually call _swrast_unmap_teximage() here */
293             swImage->Map = NULL;
294          }
295       }
296    }
297 }
298
299
300 /**
301  * Map all textures for reading prior to software rendering.
302  */
303 void
304 _swrast_map_textures(struct gl_context *ctx)
305 {
306    GLbitfield enabledUnits = ctx->Texture._EnabledUnits;
307
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;
312       
313       _swrast_map_texture(ctx, texObj);
314
315       enabledUnits &= ~(1 << unit);
316    }
317 }
318
319
320 /**
321  * Unmap all textures for reading prior to software rendering.
322  */
323 void
324 _swrast_unmap_textures(struct gl_context *ctx)
325 {
326    GLbitfield enabledUnits = ctx->Texture._EnabledUnits;
327
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;
332       
333       _swrast_unmap_texture(ctx, texObj);
334
335       enabledUnits &= ~(1 << unit);
336    }
337 }