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 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.
25 * Functions for mapping/unmapping texture images.
29 #include "main/context.h"
30 #include "main/fbobject.h"
31 #include "main/teximage.h"
32 #include "main/texobj.h"
33 #include "swrast/swrast.h"
34 #include "swrast/s_context.h"
38 * Allocate a new swrast_texture_image (a subclass of gl_texture_image).
39 * Called via ctx->Driver.NewTextureImage().
41 struct gl_texture_image
*
42 _swrast_new_texture_image( struct gl_context
*ctx
)
45 return (struct gl_texture_image
*) CALLOC_STRUCT(swrast_texture_image
);
50 * Free a swrast_texture_image (a subclass of gl_texture_image).
51 * Called via ctx->Driver.DeleteTextureImage().
54 _swrast_delete_texture_image(struct gl_context
*ctx
,
55 struct gl_texture_image
*texImage
)
57 /* Nothing special for the subclass yet */
58 _mesa_delete_texture_image(ctx
, texImage
);
63 * Called via ctx->Driver.AllocTextureImageBuffer()
66 _swrast_alloc_texture_image_buffer(struct gl_context
*ctx
,
67 struct gl_texture_image
*texImage
)
69 struct swrast_texture_image
*swImg
= swrast_texture_image(texImage
);
70 GLuint bytes
= _mesa_format_image_size(texImage
->TexFormat
, texImage
->Width
,
71 texImage
->Height
, texImage
->Depth
);
74 assert(!swImg
->Buffer
);
75 swImg
->Buffer
= _mesa_align_malloc(bytes
, 512);
79 /* RowStride and ImageOffsets[] describe how to address texels in 'Data' */
80 swImg
->RowStride
= texImage
->Width
;
82 /* Allocate the ImageOffsets array and initialize to typical values.
83 * We allocate the array for 1D/2D textures too in order to avoid special-
84 * case code in the texstore routines.
86 swImg
->ImageOffsets
= malloc(texImage
->Depth
* sizeof(GLuint
));
87 if (!swImg
->ImageOffsets
)
90 for (i
= 0; i
< texImage
->Depth
; i
++) {
91 swImg
->ImageOffsets
[i
] = i
* texImage
->Width
* texImage
->Height
;
94 _swrast_init_texture_image(texImage
);
101 * Code that overrides ctx->Driver.AllocTextureImageBuffer may use this to
102 * initialize the fields of swrast_texture_image without allocating the image
103 * buffer or initializing ImageOffsets or RowStride.
105 * Returns GL_TRUE on success, GL_FALSE on memory allocation failure.
108 _swrast_init_texture_image(struct gl_texture_image
*texImage
)
110 struct swrast_texture_image
*swImg
= swrast_texture_image(texImage
);
112 if ((texImage
->Width
== 1 || _mesa_is_pow_two(texImage
->Width2
)) &&
113 (texImage
->Height
== 1 || _mesa_is_pow_two(texImage
->Height2
)) &&
114 (texImage
->Depth
== 1 || _mesa_is_pow_two(texImage
->Depth2
)))
115 swImg
->_IsPowerOfTwo
= GL_TRUE
;
117 swImg
->_IsPowerOfTwo
= GL_FALSE
;
119 /* Compute Width/Height/DepthScale for mipmap lod computation */
120 if (texImage
->TexObject
->Target
== GL_TEXTURE_RECTANGLE_NV
) {
121 /* scale = 1.0 since texture coords directly map to texels */
122 swImg
->WidthScale
= 1.0;
123 swImg
->HeightScale
= 1.0;
124 swImg
->DepthScale
= 1.0;
127 swImg
->WidthScale
= (GLfloat
) texImage
->Width
;
128 swImg
->HeightScale
= (GLfloat
) texImage
->Height
;
129 swImg
->DepthScale
= (GLfloat
) texImage
->Depth
;
135 * Called via ctx->Driver.FreeTextureImageBuffer()
138 _swrast_free_texture_image_buffer(struct gl_context
*ctx
,
139 struct gl_texture_image
*texImage
)
141 struct swrast_texture_image
*swImage
= swrast_texture_image(texImage
);
142 if (swImage
->Buffer
) {
143 _mesa_align_free(swImage
->Buffer
);
144 swImage
->Buffer
= NULL
;
147 if (swImage
->ImageOffsets
) {
148 free(swImage
->ImageOffsets
);
149 swImage
->ImageOffsets
= NULL
;
155 * Error checking for debugging only.
158 _mesa_check_map_teximage(struct gl_texture_image
*texImage
,
159 GLuint slice
, GLuint x
, GLuint y
, GLuint w
, GLuint h
)
162 if (texImage
->TexObject
->Target
== GL_TEXTURE_1D
)
163 assert(y
== 0 && h
== 1);
165 assert(x
< texImage
->Width
|| texImage
->Width
== 0);
166 assert(y
< texImage
->Height
|| texImage
->Height
== 0);
167 assert(x
+ w
<= texImage
->Width
);
168 assert(y
+ h
<= texImage
->Height
);
172 * Map a 2D slice of a texture image into user space.
173 * (x,y,w,h) defines a region of interest (ROI). Reading/writing texels
174 * outside of the ROI is undefined.
176 * \param texImage the texture image
177 * \param slice the 3D image slice or array texture slice
178 * \param x, y, w, h region of interest
179 * \param mode bitmask of GL_MAP_READ_BIT, GL_MAP_WRITE_BIT
180 * \param mapOut returns start of mapping of region of interest
181 * \param rowStrideOut returns row stride (in bytes)
184 _swrast_map_teximage(struct gl_context
*ctx
,
185 struct gl_texture_image
*texImage
,
187 GLuint x
, GLuint y
, GLuint w
, GLuint h
,
192 struct swrast_texture_image
*swImage
= swrast_texture_image(texImage
);
194 GLint stride
, texelSize
;
197 _mesa_check_map_teximage(texImage
, slice
, x
, y
, w
, h
);
199 texelSize
= _mesa_get_format_bytes(texImage
->TexFormat
);
200 stride
= _mesa_format_row_stride(texImage
->TexFormat
, texImage
->Width
);
201 _mesa_get_format_block_size(texImage
->TexFormat
, &bw
, &bh
);
206 if (!swImage
->Buffer
) {
207 /* probably ran out of memory when allocating tex mem */
212 map
= swImage
->Buffer
;
214 if (texImage
->TexObject
->Target
== GL_TEXTURE_3D
||
215 texImage
->TexObject
->Target
== GL_TEXTURE_2D_ARRAY
) {
216 GLuint sliceSize
= _mesa_format_image_size(texImage
->TexFormat
,
220 assert(slice
< texImage
->Depth
);
221 map
+= slice
* sliceSize
;
222 } else if (texImage
->TexObject
->Target
== GL_TEXTURE_1D_ARRAY
) {
223 GLuint sliceSize
= _mesa_format_image_size(texImage
->TexFormat
,
227 assert(slice
< texImage
->Height
);
228 map
+= slice
* sliceSize
;
231 /* apply x/y offset to map address */
232 map
+= stride
* (y
/ bh
) + texelSize
* (x
/ bw
);
235 *rowStrideOut
= stride
;
239 _swrast_unmap_teximage(struct gl_context
*ctx
,
240 struct gl_texture_image
*texImage
,
248 _swrast_map_texture(struct gl_context
*ctx
, struct gl_texture_object
*texObj
)
250 const GLuint faces
= _mesa_num_tex_faces(texObj
->Target
);
253 for (face
= 0; face
< faces
; face
++) {
254 for (level
= texObj
->BaseLevel
; level
< MAX_TEXTURE_LEVELS
; level
++) {
255 struct gl_texture_image
*texImage
= texObj
->Image
[face
][level
];
257 struct swrast_texture_image
*swImage
=
258 swrast_texture_image(texImage
);
260 /* XXX we'll eventually call _swrast_map_teximage() here */
261 swImage
->Map
= swImage
->Buffer
;
269 _swrast_unmap_texture(struct gl_context
*ctx
, struct gl_texture_object
*texObj
)
271 const GLuint faces
= _mesa_num_tex_faces(texObj
->Target
);
274 for (face
= 0; face
< faces
; face
++) {
275 for (level
= texObj
->BaseLevel
; level
< MAX_TEXTURE_LEVELS
; level
++) {
276 struct gl_texture_image
*texImage
= texObj
->Image
[face
][level
];
278 struct swrast_texture_image
*swImage
279 = swrast_texture_image(texImage
);
281 /* XXX we'll eventually call _swrast_unmap_teximage() here */
290 * Map all textures for reading prior to software rendering.
293 _swrast_map_textures(struct gl_context
*ctx
)
295 GLbitfield enabledUnits
= ctx
->Texture
._EnabledUnits
;
297 /* loop over enabled texture units */
298 while (enabledUnits
) {
299 GLuint unit
= ffs(enabledUnits
) - 1;
300 struct gl_texture_object
*texObj
= ctx
->Texture
.Unit
[unit
]._Current
;
302 _swrast_map_texture(ctx
, texObj
);
304 enabledUnits
&= ~(1 << unit
);
310 * Unmap all textures for reading prior to software rendering.
313 _swrast_unmap_textures(struct gl_context
*ctx
)
315 GLbitfield enabledUnits
= ctx
->Texture
._EnabledUnits
;
317 /* loop over enabled texture units */
318 while (enabledUnits
) {
319 GLuint unit
= ffs(enabledUnits
) - 1;
320 struct gl_texture_object
*texObj
= ctx
->Texture
.Unit
[unit
]._Current
;
322 _swrast_unmap_texture(ctx
, texObj
);
324 enabledUnits
&= ~(1 << unit
);
330 * Called via ctx->Driver.AllocTextureStorage()
331 * Just have to allocate memory for the texture images.
334 _swrast_AllocTextureStorage(struct gl_context
*ctx
,
335 struct gl_texture_object
*texObj
,
336 GLsizei levels
, GLsizei width
,
337 GLsizei height
, GLsizei depth
)
339 const GLint numFaces
= (texObj
->Target
== GL_TEXTURE_CUBE_MAP
) ? 6 : 1;
342 for (face
= 0; face
< numFaces
; face
++) {
343 for (level
= 0; level
< levels
; level
++) {
344 struct gl_texture_image
*texImage
= texObj
->Image
[face
][level
];
345 if (!_swrast_alloc_texture_image_buffer(ctx
, texImage
)) {