337a52f32a049dec412475b7821e6cef3fca3e25
[profile/ivi/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 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 "swrast/swrast.h"
33 #include "swrast/s_context.h"
34
35
36 /**
37  * Allocate a new swrast_texture_image (a subclass of gl_texture_image).
38  * Called via ctx->Driver.NewTextureImage().
39  */
40 struct gl_texture_image *
41 _swrast_new_texture_image( struct gl_context *ctx )
42 {
43    (void) ctx;
44    return (struct gl_texture_image *) CALLOC_STRUCT(swrast_texture_image);
45 }
46
47
48 /**
49  * Free a swrast_texture_image (a subclass of gl_texture_image).
50  * Called via ctx->Driver.DeleteTextureImage().
51  */
52 void
53 _swrast_delete_texture_image(struct gl_context *ctx,
54                              struct gl_texture_image *texImage)
55 {
56    /* Nothing special for the subclass yet */
57    _mesa_delete_texture_image(ctx, texImage);
58 }
59
60
61 /**
62  * Called via ctx->Driver.AllocTextureImageBuffer()
63  */
64 GLboolean
65 _swrast_alloc_texture_image_buffer(struct gl_context *ctx,
66                                    struct gl_texture_image *texImage,
67                                    gl_format format, GLsizei width,
68                                    GLsizei height, GLsizei depth)
69 {
70    struct swrast_texture_image *swImg = swrast_texture_image(texImage);
71    GLuint bytes = _mesa_format_image_size(format, width, height, depth);
72    GLuint i;
73
74    /* This _should_ be true (revisit if these ever fail) */
75    assert(texImage->Width == width);
76    assert(texImage->Height == height);
77    assert(texImage->Depth == depth);
78
79    assert(!swImg->Buffer);
80    swImg->Buffer = _mesa_align_malloc(bytes, 512);
81    if (!swImg->Buffer)
82       return GL_FALSE;
83
84    /* RowStride and ImageOffsets[] describe how to address texels in 'Data' */
85    swImg->RowStride = width;
86
87    /* Allocate the ImageOffsets array and initialize to typical values.
88     * We allocate the array for 1D/2D textures too in order to avoid special-
89     * case code in the texstore routines.
90     */
91    swImg->ImageOffsets = (GLuint *) malloc(depth * sizeof(GLuint));
92    if (!swImg->ImageOffsets)
93       return GL_FALSE;
94
95    for (i = 0; i < depth; i++) {
96       swImg->ImageOffsets[i] = i * width * height;
97    }
98
99    if ((width == 1 || _mesa_is_pow_two(texImage->Width2)) &&
100        (height == 1 || _mesa_is_pow_two(texImage->Height2)) &&
101        (depth == 1 || _mesa_is_pow_two(texImage->Depth2)))
102       swImg->_IsPowerOfTwo = GL_TRUE;
103    else
104       swImg->_IsPowerOfTwo = GL_FALSE;
105
106    /* Compute Width/Height/DepthScale for mipmap lod computation */
107    if (texImage->TexObject->Target == GL_TEXTURE_RECTANGLE_NV) {
108       /* scale = 1.0 since texture coords directly map to texels */
109       swImg->WidthScale = 1.0;
110       swImg->HeightScale = 1.0;
111       swImg->DepthScale = 1.0;
112    }
113    else {
114       swImg->WidthScale = (GLfloat) texImage->Width;
115       swImg->HeightScale = (GLfloat) texImage->Height;
116       swImg->DepthScale = (GLfloat) texImage->Depth;
117    }
118
119    return GL_TRUE;
120 }
121
122
123 /**
124  * Called via ctx->Driver.FreeTextureImageBuffer()
125  */
126 void
127 _swrast_free_texture_image_buffer(struct gl_context *ctx,
128                                   struct gl_texture_image *texImage)
129 {
130    struct swrast_texture_image *swImage = swrast_texture_image(texImage);
131    if (swImage->Buffer) {
132       _mesa_align_free(swImage->Buffer);
133       swImage->Buffer = NULL;
134    }
135
136    if (swImage->ImageOffsets) {
137       free(swImage->ImageOffsets);
138       swImage->ImageOffsets = NULL;
139    }
140 }
141
142
143 /**
144  * Error checking for debugging only.
145  */
146 static void
147 _mesa_check_map_teximage(struct gl_texture_image *texImage,
148                          GLuint slice, GLuint x, GLuint y, GLuint w, GLuint h)
149 {
150
151    if (texImage->TexObject->Target == GL_TEXTURE_1D)
152       assert(y == 0 && h == 1);
153
154    assert(x < texImage->Width || texImage->Width == 0);
155    assert(y < texImage->Height || texImage->Height == 0);
156    assert(x + w <= texImage->Width);
157    assert(y + h <= texImage->Height);
158 }
159
160 /**
161  * Map a 2D slice of a texture image into user space.
162  * (x,y,w,h) defines a region of interest (ROI).  Reading/writing texels
163  * outside of the ROI is undefined.
164  *
165  * \param texImage  the texture image
166  * \param slice  the 3D image slice or array texture slice
167  * \param x, y, w, h  region of interest
168  * \param mode  bitmask of GL_MAP_READ_BIT, GL_MAP_WRITE_BIT
169  * \param mapOut  returns start of mapping of region of interest
170  * \param rowStrideOut  returns row stride (in bytes)
171  */
172 void
173 _swrast_map_teximage(struct gl_context *ctx,
174                      struct gl_texture_image *texImage,
175                      GLuint slice,
176                      GLuint x, GLuint y, GLuint w, GLuint h,
177                      GLbitfield mode,
178                      GLubyte **mapOut,
179                      GLint *rowStrideOut)
180 {
181    struct swrast_texture_image *swImage = swrast_texture_image(texImage);
182    GLubyte *map;
183    GLint stride, texelSize;
184    GLuint bw, bh;
185
186    _mesa_check_map_teximage(texImage, slice, x, y, w, h);
187
188    texelSize = _mesa_get_format_bytes(texImage->TexFormat);
189    stride = _mesa_format_row_stride(texImage->TexFormat, texImage->Width);
190    _mesa_get_format_block_size(texImage->TexFormat, &bw, &bh);
191
192    assert(x % bw == 0);
193    assert(y % bh == 0);
194
195    if (!swImage->Buffer) {
196       /* probably ran out of memory when allocating tex mem */
197       *mapOut = NULL;
198       return;
199    }
200       
201    map = swImage->Buffer;
202
203    if (texImage->TexObject->Target == GL_TEXTURE_3D ||
204        texImage->TexObject->Target == GL_TEXTURE_2D_ARRAY) {
205       GLuint sliceSize = _mesa_format_image_size(texImage->TexFormat,
206                                                  texImage->Width,
207                                                  texImage->Height,
208                                                  1);
209       assert(slice < texImage->Depth);
210       map += slice * sliceSize;
211    } else if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) {
212       GLuint sliceSize = _mesa_format_image_size(texImage->TexFormat,
213                                                  texImage->Width,
214                                                  1,
215                                                  1);
216       assert(slice < texImage->Height);
217       map += slice * sliceSize;
218    }
219
220    /* apply x/y offset to map address */
221    map += stride * (y / bh) + texelSize * (x / bw);
222
223    *mapOut = map;
224    *rowStrideOut = stride;
225 }
226
227 void
228 _swrast_unmap_teximage(struct gl_context *ctx,
229                        struct gl_texture_image *texImage,
230                        GLuint slice)
231 {
232    /* nop */
233 }
234
235
236 void
237 _swrast_map_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
238 {
239    const GLuint faces = texObj->Target == GL_TEXTURE_CUBE_MAP ? 6 : 1;
240    GLuint face, level;
241
242    for (face = 0; face < faces; face++) {
243       for (level = texObj->BaseLevel; level < MAX_TEXTURE_LEVELS; level++) {
244          struct gl_texture_image *texImage = texObj->Image[face][level];
245          if (texImage) {
246             struct swrast_texture_image *swImage =
247                swrast_texture_image(texImage);
248
249             /* XXX we'll eventually call _swrast_map_teximage() here */
250             swImage->Data = swImage->Buffer;
251          }
252       }
253    }
254 }
255
256
257 void
258 _swrast_unmap_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
259 {
260    const GLuint faces = texObj->Target == GL_TEXTURE_CUBE_MAP ? 6 : 1;
261    GLuint face, level;
262
263    for (face = 0; face < faces; face++) {
264       for (level = texObj->BaseLevel; level < MAX_TEXTURE_LEVELS; level++) {
265          struct gl_texture_image *texImage = texObj->Image[face][level];
266          if (texImage) {
267             struct swrast_texture_image *swImage
268                = swrast_texture_image(texImage);
269
270             /* XXX we'll eventually call _swrast_unmap_teximage() here */
271             swImage->Data = NULL;
272          }
273       }
274    }
275 }
276
277
278 /**
279  * Map all textures for reading prior to software rendering.
280  */
281 void
282 _swrast_map_textures(struct gl_context *ctx)
283 {
284    GLbitfield enabledUnits = ctx->Texture._EnabledUnits;
285
286    /* loop over enabled texture units */
287    while (enabledUnits) {
288       GLuint unit = ffs(enabledUnits) - 1;
289       struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
290       
291       _swrast_map_texture(ctx, texObj);
292
293       enabledUnits &= ~(1 << unit);
294    }
295 }
296
297
298 /**
299  * Unmap all textures for reading prior to software rendering.
300  */
301 void
302 _swrast_unmap_textures(struct gl_context *ctx)
303 {
304    GLbitfield enabledUnits = ctx->Texture._EnabledUnits;
305
306    /* loop over enabled texture units */
307    while (enabledUnits) {
308       GLuint unit = ffs(enabledUnits) - 1;
309       struct gl_texture_object *texObj = ctx->Texture.Unit[unit]._Current;
310       
311       _swrast_unmap_texture(ctx, texObj);
312
313       enabledUnits &= ~(1 << unit);
314    }
315 }
316
317
318 /**
319  * Map or unmap any textures that we may be rendering to as renderbuffers.
320  */
321 static void
322 map_unmap_renderbuffers(struct gl_context *ctx,
323                         struct gl_framebuffer *fb,
324                         GLboolean map)
325 {
326    GLuint i;
327
328    for (i = 0; i < Elements(fb->Attachment); i++) {
329       struct gl_texture_object *texObj = fb->Attachment[i].Texture;
330       if (texObj) {
331          const GLuint level = fb->Attachment[i].TextureLevel;
332          const GLuint face = fb->Attachment[i].CubeMapFace;
333          struct gl_texture_image *texImage = texObj->Image[face][level];
334          if (texImage) {
335             struct swrast_texture_image *swImage
336                = swrast_texture_image(texImage);
337
338             if (map) {
339                /* XXX we'll eventually call _swrast_map_teximage() here */
340                swImage->Data = swImage->Buffer;
341             }
342             else {
343                /* XXX we'll eventually call _swrast_unmap_teximage() here */
344                swImage->Data = NULL;
345             }
346          }
347       }
348    }
349 }
350
351
352 void
353 _swrast_map_renderbuffers(struct gl_context *ctx)
354 {
355    map_unmap_renderbuffers(ctx, ctx->DrawBuffer, GL_TRUE);
356    if (ctx->ReadBuffer != ctx->DrawBuffer)
357       map_unmap_renderbuffers(ctx, ctx->ReadBuffer, GL_TRUE);
358 }
359
360
361 void
362 _swrast_unmap_renderbuffers(struct gl_context *ctx)
363 {
364    map_unmap_renderbuffers(ctx, ctx->DrawBuffer, GL_FALSE);
365    if (ctx->ReadBuffer != ctx->DrawBuffer)
366       map_unmap_renderbuffers(ctx, ctx->ReadBuffer, GL_FALSE);
367 }
368
369
370
371 /**
372  * Called via ctx->Driver.AllocTextureStorage()
373  * Just have to allocate memory for the texture images.
374  */
375 GLboolean
376 _swrast_AllocTextureStorage(struct gl_context *ctx,
377                             struct gl_texture_object *texObj,
378                             GLsizei levels, GLsizei width,
379                             GLsizei height, GLsizei depth)
380 {
381    const GLint numFaces = (texObj->Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
382    GLint face, level;
383
384    for (face = 0; face < numFaces; face++) {
385       for (level = 0; level < levels; level++) {
386          struct gl_texture_image *texImage = texObj->Image[face][level];
387          if (!_swrast_alloc_texture_image_buffer(ctx, texImage,
388                                                  texImage->TexFormat,
389                                                  texImage->Width,
390                                                  texImage->Height,
391                                                  texImage->Depth)) {
392             return GL_FALSE;
393          }
394       }
395    }
396
397    return GL_TRUE;
398 }
399