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 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.
26 * Functions for mapping/unmapping texture images.
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"
41 * Allocate a new swrast_texture_image (a subclass of gl_texture_image).
42 * Called via ctx->Driver.NewTextureImage().
44 struct gl_texture_image
*
45 _swrast_new_texture_image( struct gl_context
*ctx
)
48 return (struct gl_texture_image
*) CALLOC_STRUCT(swrast_texture_image
);
53 * Free a swrast_texture_image (a subclass of gl_texture_image).
54 * Called via ctx->Driver.DeleteTextureImage().
57 _swrast_delete_texture_image(struct gl_context
*ctx
,
58 struct gl_texture_image
*texImage
)
60 /* Nothing special for the subclass yet */
61 _mesa_delete_texture_image(ctx
, texImage
);
65 texture_slices(const struct gl_texture_image
*texImage
)
67 if (texImage
->TexObject
->Target
== GL_TEXTURE_1D_ARRAY
)
68 return texImage
->Height
;
70 return texImage
->Depth
;
74 _swrast_teximage_slice_height(struct gl_texture_image
*texImage
)
76 /* For 1D array textures, the slices are all 1 pixel high, and Height is
77 * the number of slices.
79 if (texImage
->TexObject
->Target
== GL_TEXTURE_1D_ARRAY
)
82 return texImage
->Height
;
86 * Called via ctx->Driver.AllocTextureImageBuffer()
89 _swrast_alloc_texture_image_buffer(struct gl_context
*ctx
,
90 struct gl_texture_image
*texImage
)
92 struct swrast_texture_image
*swImg
= swrast_texture_image(texImage
);
94 GLuint slices
= texture_slices(texImage
);
97 if (!_swrast_init_texture_image(texImage
))
100 bytesPerSlice
= _mesa_format_image_size(texImage
->TexFormat
, texImage
->Width
,
101 _swrast_teximage_slice_height(texImage
), 1);
103 assert(!swImg
->Buffer
);
104 swImg
->Buffer
= align_malloc(bytesPerSlice
* slices
, 512);
108 /* RowStride and ImageSlices[] describe how to address texels in 'Data' */
109 swImg
->RowStride
= _mesa_format_row_stride(texImage
->TexFormat
,
112 for (i
= 0; i
< slices
; i
++) {
113 swImg
->ImageSlices
[i
] = swImg
->Buffer
+ bytesPerSlice
* i
;
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.
125 * Returns GL_TRUE on success, GL_FALSE on memory allocation failure.
128 _swrast_init_texture_image(struct gl_texture_image
*texImage
)
130 struct swrast_texture_image
*swImg
= swrast_texture_image(texImage
);
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
;
137 swImg
->_IsPowerOfTwo
= GL_FALSE
;
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;
147 swImg
->WidthScale
= (GLfloat
) texImage
->Width
;
148 swImg
->HeightScale
= (GLfloat
) texImage
->Height
;
149 swImg
->DepthScale
= (GLfloat
) texImage
->Depth
;
152 assert(!swImg
->ImageSlices
);
153 swImg
->ImageSlices
= calloc(texture_slices(texImage
), sizeof(void *));
154 if (!swImg
->ImageSlices
)
162 * Called via ctx->Driver.FreeTextureImageBuffer()
165 _swrast_free_texture_image_buffer(struct gl_context
*ctx
,
166 struct gl_texture_image
*texImage
)
168 struct swrast_texture_image
*swImage
= swrast_texture_image(texImage
);
170 align_free(swImage
->Buffer
);
171 swImage
->Buffer
= NULL
;
173 free(swImage
->ImageSlices
);
174 swImage
->ImageSlices
= NULL
;
179 * Error checking for debugging only.
182 check_map_teximage(const struct gl_texture_image
*texImage
,
183 GLuint slice
, GLuint x
, GLuint y
, GLuint w
, GLuint h
)
186 if (texImage
->TexObject
->Target
== GL_TEXTURE_1D
)
187 assert(y
== 0 && h
== 1);
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
));
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.
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)
209 _swrast_map_teximage(struct gl_context
*ctx
,
210 struct gl_texture_image
*texImage
,
212 GLuint x
, GLuint y
, GLuint w
, GLuint h
,
217 struct swrast_texture_image
*swImage
= swrast_texture_image(texImage
);
219 GLint stride
, texelSize
;
222 check_map_teximage(texImage
, slice
, x
, y
, w
, h
);
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,
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
);
240 /* This function can only be used with a swrast-allocated buffer, in which
241 * case ImageSlices is populated with pointers into Buffer.
243 assert(swImage
->Buffer
);
244 assert(swImage
->Buffer
== swImage
->ImageSlices
[0]);
246 map
= swImage
->ImageSlices
[slice
];
248 /* apply x/y offset to map address */
249 map
+= stride
* (y
/ bh
) + texelSize
* (x
/ bw
);
252 *rowStrideOut
= stride
;
256 _swrast_unmap_teximage(struct gl_context
*ctx
,
257 struct gl_texture_image
*texImage
,
265 _swrast_map_texture(struct gl_context
*ctx
, struct gl_texture_object
*texObj
)
267 const GLuint faces
= _mesa_num_tex_faces(texObj
->Target
);
270 for (face
= 0; face
< faces
; face
++) {
271 for (level
= texObj
->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
;
279 /* In the case of a swrast-allocated texture buffer, the ImageSlices
280 * and RowStride are always available.
282 if (swImage
->Buffer
) {
283 assert(swImage
->ImageSlices
[0] == swImage
->Buffer
);
287 if (!swImage
->ImageSlices
) {
288 swImage
->ImageSlices
=
289 calloc(texture_slices(texImage
), sizeof(void *));
290 if (!swImage
->ImageSlices
)
294 slices
= texture_slices(texImage
);
296 for (i
= 0; i
< slices
; i
++) {
300 if (swImage
->ImageSlices
[i
])
303 ctx
->Driver
.MapTextureImage(ctx
, texImage
, i
,
305 texImage
->Width
, texImage
->Height
,
306 GL_MAP_READ_BIT
| GL_MAP_WRITE_BIT
,
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
315 swImage
->RowStride
= rowStride
;
317 assert(swImage
->RowStride
== rowStride
);
325 _swrast_unmap_texture(struct gl_context
*ctx
, struct gl_texture_object
*texObj
)
327 const GLuint faces
= _mesa_num_tex_faces(texObj
->Target
);
330 for (face
= 0; face
< faces
; face
++) {
331 for (level
= texObj
->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
;
342 if (!swImage
->ImageSlices
)
345 slices
= texture_slices(texImage
);
347 for (i
= 0; i
< slices
; i
++) {
348 if (swImage
->ImageSlices
[i
]) {
349 ctx
->Driver
.UnmapTextureImage(ctx
, texImage
, i
);
350 swImage
->ImageSlices
[i
] = NULL
;
359 * Map all textures for reading prior to software rendering.
362 _swrast_map_textures(struct gl_context
*ctx
)
366 for (unit
= 0; unit
<= ctx
->Texture
._MaxEnabledTexImageUnit
; unit
++) {
367 struct gl_texture_object
*texObj
= ctx
->Texture
.Unit
[unit
]._Current
;
370 _swrast_map_texture(ctx
, texObj
);
376 * Unmap all textures for reading prior to software rendering.
379 _swrast_unmap_textures(struct gl_context
*ctx
)
382 for (unit
= 0; unit
<= ctx
->Texture
._MaxEnabledTexImageUnit
; unit
++) {
383 struct gl_texture_object
*texObj
= ctx
->Texture
.Unit
[unit
]._Current
;
386 _swrast_unmap_texture(ctx
, texObj
);