f945a6b0fa8dd2766923f345cd576a1b2fe27472
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 "swrast/swrast.h"
33 #include "swrast/s_context.h"
37 * Allocate a new swrast_texture_image (a subclass of gl_texture_image).
38 * Called via ctx->Driver.NewTextureImage().
40 struct gl_texture_image
*
41 _swrast_new_texture_image( struct gl_context
*ctx
)
44 return (struct gl_texture_image
*) CALLOC_STRUCT(swrast_texture_image
);
49 * Free a swrast_texture_image (a subclass of gl_texture_image).
50 * Called via ctx->Driver.DeleteTextureImage().
53 _swrast_delete_texture_image(struct gl_context
*ctx
,
54 struct gl_texture_image
*texImage
)
56 /* Nothing special for the subclass yet */
57 _mesa_delete_texture_image(ctx
, texImage
);
62 * Called via ctx->Driver.AllocTextureImageBuffer()
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
)
70 struct swrast_texture_image
*swImg
= swrast_texture_image(texImage
);
71 GLuint bytes
= _mesa_format_image_size(format
, width
, height
, depth
);
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
);
79 assert(!swImg
->Buffer
);
80 swImg
->Buffer
= _mesa_align_malloc(bytes
, 512);
84 /* RowStride and ImageOffsets[] describe how to address texels in 'Data' */
85 swImg
->RowStride
= width
;
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.
91 swImg
->ImageOffsets
= (GLuint
*) malloc(depth
* sizeof(GLuint
));
92 if (!swImg
->ImageOffsets
)
95 for (i
= 0; i
< depth
; i
++) {
96 swImg
->ImageOffsets
[i
] = i
* width
* height
;
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
;
104 swImg
->_IsPowerOfTwo
= GL_FALSE
;
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;
114 swImg
->WidthScale
= (GLfloat
) texImage
->Width
;
115 swImg
->HeightScale
= (GLfloat
) texImage
->Height
;
116 swImg
->DepthScale
= (GLfloat
) texImage
->Depth
;
124 * Called via ctx->Driver.FreeTextureImageBuffer()
127 _swrast_free_texture_image_buffer(struct gl_context
*ctx
,
128 struct gl_texture_image
*texImage
)
130 struct swrast_texture_image
*swImage
= swrast_texture_image(texImage
);
131 if (swImage
->Buffer
) {
132 _mesa_align_free(swImage
->Buffer
);
133 swImage
->Buffer
= NULL
;
136 if (swImage
->ImageOffsets
) {
137 free(swImage
->ImageOffsets
);
138 swImage
->ImageOffsets
= NULL
;
144 * Error checking for debugging only.
147 _mesa_check_map_teximage(struct gl_texture_image
*texImage
,
148 GLuint slice
, GLuint x
, GLuint y
, GLuint w
, GLuint h
)
151 if (texImage
->TexObject
->Target
== GL_TEXTURE_1D
)
152 assert(y
== 0 && h
== 1);
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
);
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.
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)
173 _swrast_map_teximage(struct gl_context
*ctx
,
174 struct gl_texture_image
*texImage
,
176 GLuint x
, GLuint y
, GLuint w
, GLuint h
,
181 struct swrast_texture_image
*swImage
= swrast_texture_image(texImage
);
183 GLint stride
, texelSize
;
186 _mesa_check_map_teximage(texImage
, slice
, x
, y
, w
, h
);
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
);
195 if (!swImage
->Buffer
) {
196 /* probably ran out of memory when allocating tex mem */
201 map
= swImage
->Buffer
;
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
,
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
,
216 assert(slice
< texImage
->Height
);
217 map
+= slice
* sliceSize
;
220 /* apply x/y offset to map address */
221 map
+= stride
* (y
/ bh
) + texelSize
* (x
/ bw
);
224 *rowStrideOut
= stride
;
228 _swrast_unmap_teximage(struct gl_context
*ctx
,
229 struct gl_texture_image
*texImage
,
237 _swrast_map_texture(struct gl_context
*ctx
, struct gl_texture_object
*texObj
)
239 const GLuint faces
= texObj
->Target
== GL_TEXTURE_CUBE_MAP
? 6 : 1;
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
];
246 struct swrast_texture_image
*swImage
=
247 swrast_texture_image(texImage
);
249 /* XXX we'll eventually call _swrast_map_teximage() here */
250 swImage
->Map
= swImage
->Buffer
;
258 _swrast_unmap_texture(struct gl_context
*ctx
, struct gl_texture_object
*texObj
)
260 const GLuint faces
= texObj
->Target
== GL_TEXTURE_CUBE_MAP
? 6 : 1;
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
];
267 struct swrast_texture_image
*swImage
268 = swrast_texture_image(texImage
);
270 /* XXX we'll eventually call _swrast_unmap_teximage() here */
279 * Map all textures for reading prior to software rendering.
282 _swrast_map_textures(struct gl_context
*ctx
)
284 GLbitfield enabledUnits
= ctx
->Texture
._EnabledUnits
;
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
;
291 _swrast_map_texture(ctx
, texObj
);
293 enabledUnits
&= ~(1 << unit
);
299 * Unmap all textures for reading prior to software rendering.
302 _swrast_unmap_textures(struct gl_context
*ctx
)
304 GLbitfield enabledUnits
= ctx
->Texture
._EnabledUnits
;
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
;
311 _swrast_unmap_texture(ctx
, texObj
);
313 enabledUnits
&= ~(1 << unit
);
319 map_attachment(struct gl_context
*ctx
,
320 struct gl_framebuffer
*fb
,
321 gl_buffer_index buffer
)
323 struct gl_texture_object
*texObj
= fb
->Attachment
[buffer
].Texture
;
324 struct gl_renderbuffer
*rb
= fb
->Attachment
[buffer
].Renderbuffer
;
327 const GLuint level
= fb
->Attachment
[buffer
].TextureLevel
;
328 const GLuint face
= fb
->Attachment
[buffer
].CubeMapFace
;
329 struct gl_texture_image
*texImage
= texObj
->Image
[face
][level
];
331 struct swrast_texture_image
*swImage
332 = swrast_texture_image(texImage
);
334 /* XXX we'll eventually call _swrast_map_teximage() here */
335 swImage
->Map
= swImage
->Buffer
;
337 rb
->Map
= swImage
->Buffer
;
338 rb
->RowStrideBytes
= swImage
->RowStride
*
339 _mesa_get_format_bytes(swImage
->Base
.TexFormat
);
344 /* Map ordinary renderbuffer */
345 /* XXX don't map color buffers yet */
346 if (buffer
== BUFFER_DEPTH
|| buffer
== BUFFER_STENCIL
) {
347 ctx
->Driver
.MapRenderbuffer(ctx
, rb
,
348 0, 0, rb
->Width
, rb
->Height
,
349 GL_MAP_READ_BIT
| GL_MAP_WRITE_BIT
,
350 &rb
->Map
, &rb
->RowStrideBytes
);
358 unmap_attachment(struct gl_context
*ctx
,
359 struct gl_framebuffer
*fb
,
360 gl_buffer_index buffer
)
362 struct gl_texture_object
*texObj
= fb
->Attachment
[buffer
].Texture
;
363 struct gl_renderbuffer
*rb
= fb
->Attachment
[buffer
].Renderbuffer
;
366 const GLuint level
= fb
->Attachment
[buffer
].TextureLevel
;
367 const GLuint face
= fb
->Attachment
[buffer
].CubeMapFace
;
368 struct gl_texture_image
*texImage
= texObj
->Image
[face
][level
];
371 /* XXX we'll eventually call _swrast_unmap_teximage() here */
375 /* unmap ordinary renderbuffer */
376 /* XXX don't map color buffers yet */
377 if (buffer
== BUFFER_DEPTH
|| buffer
== BUFFER_STENCIL
) {
378 ctx
->Driver
.UnmapRenderbuffer(ctx
, rb
);
383 rb
->RowStrideBytes
= 0;
388 * Map the renderbuffers we'll use for tri/line/point rendering.
391 _swrast_map_renderbuffers(struct gl_context
*ctx
)
393 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
394 struct gl_renderbuffer
*depthRb
, *stencilRb
;
397 depthRb
= fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
399 /* map depth buffer */
400 map_attachment(ctx
, fb
, BUFFER_DEPTH
);
403 stencilRb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
404 if (stencilRb
&& stencilRb
!= depthRb
) {
405 /* map stencil buffer */
406 map_attachment(ctx
, fb
, BUFFER_STENCIL
);
409 for (buf
= 0; buf
< fb
->_NumColorDrawBuffers
; buf
++) {
410 map_attachment(ctx
, fb
, fb
->_ColorDrawBufferIndexes
[buf
]);
416 * Unmap renderbuffers after rendering.
419 _swrast_unmap_renderbuffers(struct gl_context
*ctx
)
421 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
422 struct gl_renderbuffer
*depthRb
, *stencilRb
;
425 depthRb
= fb
->Attachment
[BUFFER_DEPTH
].Renderbuffer
;
427 /* map depth buffer */
428 unmap_attachment(ctx
, fb
, BUFFER_DEPTH
);
431 stencilRb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
432 if (stencilRb
&& stencilRb
!= depthRb
) {
433 /* map stencil buffer */
434 unmap_attachment(ctx
, fb
, BUFFER_STENCIL
);
437 for (buf
= 0; buf
< fb
->_NumColorDrawBuffers
; buf
++) {
438 unmap_attachment(ctx
, fb
, fb
->_ColorDrawBufferIndexes
[buf
]);
445 * Called via ctx->Driver.AllocTextureStorage()
446 * Just have to allocate memory for the texture images.
449 _swrast_AllocTextureStorage(struct gl_context
*ctx
,
450 struct gl_texture_object
*texObj
,
451 GLsizei levels
, GLsizei width
,
452 GLsizei height
, GLsizei depth
)
454 const GLint numFaces
= (texObj
->Target
== GL_TEXTURE_CUBE_MAP
) ? 6 : 1;
457 for (face
= 0; face
< numFaces
; face
++) {
458 for (level
= 0; level
< levels
; level
++) {
459 struct gl_texture_image
*texImage
= texObj
->Image
[face
][level
];
460 if (!_swrast_alloc_texture_image_buffer(ctx
, texImage
,