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 "swrast/swrast.h"
35 #include "swrast/s_context.h"
39 * Allocate a new swrast_texture_image (a subclass of gl_texture_image).
40 * Called via ctx->Driver.NewTextureImage().
42 struct gl_texture_image
*
43 _swrast_new_texture_image( struct gl_context
*ctx
)
46 return (struct gl_texture_image
*) CALLOC_STRUCT(swrast_texture_image
);
51 * Free a swrast_texture_image (a subclass of gl_texture_image).
52 * Called via ctx->Driver.DeleteTextureImage().
55 _swrast_delete_texture_image(struct gl_context
*ctx
,
56 struct gl_texture_image
*texImage
)
58 /* Nothing special for the subclass yet */
59 _mesa_delete_texture_image(ctx
, texImage
);
63 texture_slices(struct gl_texture_image
*texImage
)
65 if (texImage
->TexObject
->Target
== GL_TEXTURE_1D_ARRAY
)
66 return texImage
->Height
;
68 return texImage
->Depth
;
72 _swrast_teximage_slice_height(struct gl_texture_image
*texImage
)
74 /* For 1D array textures, the slices are all 1 pixel high, and Height is
75 * the number of slices.
77 if (texImage
->TexObject
->Target
== GL_TEXTURE_1D_ARRAY
)
80 return texImage
->Height
;
84 * Called via ctx->Driver.AllocTextureImageBuffer()
87 _swrast_alloc_texture_image_buffer(struct gl_context
*ctx
,
88 struct gl_texture_image
*texImage
)
90 struct swrast_texture_image
*swImg
= swrast_texture_image(texImage
);
92 GLuint slices
= texture_slices(texImage
);
95 if (!_swrast_init_texture_image(texImage
))
98 bytesPerSlice
= _mesa_format_image_size(texImage
->TexFormat
, texImage
->Width
,
99 _swrast_teximage_slice_height(texImage
), 1);
101 assert(!swImg
->Buffer
);
102 swImg
->Buffer
= _mesa_align_malloc(bytesPerSlice
* slices
, 512);
106 /* RowStride and ImageSlices[] describe how to address texels in 'Data' */
107 swImg
->RowStride
= _mesa_format_row_stride(texImage
->TexFormat
,
110 for (i
= 0; i
< slices
; i
++) {
111 swImg
->ImageSlices
[i
] = swImg
->Buffer
+ bytesPerSlice
* i
;
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.
123 * Returns GL_TRUE on success, GL_FALSE on memory allocation failure.
126 _swrast_init_texture_image(struct gl_texture_image
*texImage
)
128 struct swrast_texture_image
*swImg
= swrast_texture_image(texImage
);
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
;
135 swImg
->_IsPowerOfTwo
= GL_FALSE
;
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;
145 swImg
->WidthScale
= (GLfloat
) texImage
->Width
;
146 swImg
->HeightScale
= (GLfloat
) texImage
->Height
;
147 swImg
->DepthScale
= (GLfloat
) texImage
->Depth
;
150 assert(!swImg
->ImageSlices
);
151 swImg
->ImageSlices
= calloc(texture_slices(texImage
), sizeof(void *));
152 if (!swImg
->ImageSlices
)
160 * Called via ctx->Driver.FreeTextureImageBuffer()
163 _swrast_free_texture_image_buffer(struct gl_context
*ctx
,
164 struct gl_texture_image
*texImage
)
166 struct swrast_texture_image
*swImage
= swrast_texture_image(texImage
);
167 if (swImage
->Buffer
) {
168 _mesa_align_free(swImage
->Buffer
);
169 swImage
->Buffer
= NULL
;
172 free(swImage
->ImageSlices
);
173 swImage
->ImageSlices
= NULL
;
178 * Error checking for debugging only.
181 _mesa_check_map_teximage(struct gl_texture_image
*texImage
,
182 GLuint slice
, GLuint x
, GLuint y
, GLuint w
, GLuint h
)
185 if (texImage
->TexObject
->Target
== GL_TEXTURE_1D
)
186 assert(y
== 0 && h
== 1);
188 assert(x
< texImage
->Width
|| texImage
->Width
== 0);
189 assert(y
< texImage
->Height
|| texImage
->Height
== 0);
190 assert(x
+ w
<= texImage
->Width
);
191 assert(y
+ h
<= texImage
->Height
);
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.
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)
207 _swrast_map_teximage(struct gl_context
*ctx
,
208 struct gl_texture_image
*texImage
,
210 GLuint x
, GLuint y
, GLuint w
, GLuint h
,
215 struct swrast_texture_image
*swImage
= swrast_texture_image(texImage
);
217 GLint stride
, texelSize
;
220 _mesa_check_map_teximage(texImage
, slice
, x
, y
, w
, h
);
222 texelSize
= _mesa_get_format_bytes(texImage
->TexFormat
);
223 stride
= _mesa_format_row_stride(texImage
->TexFormat
, texImage
->Width
);
224 _mesa_get_format_block_size(texImage
->TexFormat
, &bw
, &bh
);
229 if (!swImage
->Buffer
) {
230 /* probably ran out of memory when allocating tex mem */
235 /* This function can only be used with a swrast-allocated buffer, in which
236 * case ImageSlices is populated with pointers into Buffer.
238 assert(swImage
->Buffer
);
239 assert(swImage
->Buffer
== swImage
->ImageSlices
[0]);
241 assert(slice
< texture_slices(texImage
));
242 map
= swImage
->ImageSlices
[slice
];
244 /* apply x/y offset to map address */
245 map
+= stride
* (y
/ bh
) + texelSize
* (x
/ bw
);
248 *rowStrideOut
= stride
;
252 _swrast_unmap_teximage(struct gl_context
*ctx
,
253 struct gl_texture_image
*texImage
,
261 _swrast_map_texture(struct gl_context
*ctx
, struct gl_texture_object
*texObj
)
263 const GLuint faces
= _mesa_num_tex_faces(texObj
->Target
);
266 for (face
= 0; face
< faces
; face
++) {
267 for (level
= texObj
->BaseLevel
; level
< MAX_TEXTURE_LEVELS
; level
++) {
268 struct gl_texture_image
*texImage
= texObj
->Image
[face
][level
];
269 struct swrast_texture_image
*swImage
= swrast_texture_image(texImage
);
275 /* In the case of a swrast-allocated texture buffer, the ImageSlices
276 * and RowStride are always available.
278 if (swImage
->Buffer
) {
279 assert(swImage
->ImageSlices
[0] == swImage
->Buffer
);
283 for (i
= 0; i
< texture_slices(texImage
); i
++) {
287 if (swImage
->ImageSlices
[i
])
290 ctx
->Driver
.MapTextureImage(ctx
, texImage
, i
,
292 texImage
->Width
, texImage
->Height
,
293 GL_MAP_READ_BIT
| GL_MAP_WRITE_BIT
,
296 swImage
->ImageSlices
[i
] = map
;
297 /* A swrast-using driver has to return the same rowstride for
298 * every slice of the same texture, since we don't track them
302 swImage
->RowStride
= rowStride
;
304 assert(swImage
->RowStride
== rowStride
);
312 _swrast_unmap_texture(struct gl_context
*ctx
, struct gl_texture_object
*texObj
)
314 const GLuint faces
= _mesa_num_tex_faces(texObj
->Target
);
317 for (face
= 0; face
< faces
; face
++) {
318 for (level
= texObj
->BaseLevel
; level
< MAX_TEXTURE_LEVELS
; level
++) {
319 struct gl_texture_image
*texImage
= texObj
->Image
[face
][level
];
320 struct swrast_texture_image
*swImage
= swrast_texture_image(texImage
);
329 for (i
= 0; i
< texture_slices(texImage
); i
++) {
330 if (swImage
->ImageSlices
[i
]) {
331 ctx
->Driver
.UnmapTextureImage(ctx
, texImage
, i
);
332 swImage
->ImageSlices
[i
] = NULL
;
341 * Map all textures for reading prior to software rendering.
344 _swrast_map_textures(struct gl_context
*ctx
)
346 GLbitfield enabledUnits
= ctx
->Texture
._EnabledUnits
;
348 /* loop over enabled texture units */
349 while (enabledUnits
) {
350 GLuint unit
= ffs(enabledUnits
) - 1;
351 struct gl_texture_object
*texObj
= ctx
->Texture
.Unit
[unit
]._Current
;
353 _swrast_map_texture(ctx
, texObj
);
355 enabledUnits
&= ~(1 << unit
);
361 * Unmap all textures for reading prior to software rendering.
364 _swrast_unmap_textures(struct gl_context
*ctx
)
366 GLbitfield enabledUnits
= ctx
->Texture
._EnabledUnits
;
368 /* loop over enabled texture units */
369 while (enabledUnits
) {
370 GLuint unit
= ffs(enabledUnits
) - 1;
371 struct gl_texture_object
*texObj
= ctx
->Texture
.Unit
[unit
]._Current
;
373 _swrast_unmap_texture(ctx
, texObj
);
375 enabledUnits
&= ~(1 << unit
);