2 * Mesa 3-D graphics library
4 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
5 * Copyright (c) 2008-2009 VMware, Inc.
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
32 * The GL texture image functions in teximage.c basically just do
33 * error checking and data structure allocation. They in turn call
34 * device driver functions which actually copy/convert/store the user's
37 * However, most device drivers will be able to use the fallback functions
38 * in this file. That is, most drivers will have the following bit of
40 * ctx->Driver.TexImage = _mesa_store_teximage;
41 * ctx->Driver.TexSubImage = _mesa_store_texsubimage;
44 * Texture image processing is actually kind of complicated. We have to do:
45 * Format/type conversions
47 * pixel transfer (scale, bais, lookup, etc)
49 * These functions can handle most everything, including processing full
50 * images and sub-images.
55 #include "bufferobj.h"
57 #include "format_pack.h"
58 #include "format_utils.h"
66 #include "texcompress.h"
67 #include "texcompress_fxt1.h"
68 #include "texcompress_rgtc.h"
69 #include "texcompress_s3tc.h"
70 #include "texcompress_etc.h"
71 #include "texcompress_bptc.h"
75 #include "glformats.h"
76 #include "pixeltransfer.h"
77 #include "../../gallium/auxiliary/util/u_format_rgb9e5.h"
78 #include "../../gallium/auxiliary/util/u_format_r11g11b10f.h"
88 * Texture image storage function.
90 typedef GLboolean (*StoreTexImageFunc
)(TEXSTORE_PARAMS
);
91 static const GLubyte map_identity
[6] = { 0, 1, 2, 3, ZERO
, ONE
};
92 static const GLubyte map_3210
[6] = { 3, 2, 1, 0, ZERO
, ONE
};
93 static const GLubyte map_1032
[6] = { 1, 0, 3, 2, ZERO
, ONE
};
97 * Teximage storage routine for when a simple memcpy will do.
98 * No pixel transfer operations or special texel encodings allowed.
99 * 1D, 2D and 3D images supported.
102 memcpy_texture(struct gl_context
*ctx
,
104 mesa_format dstFormat
,
107 GLint srcWidth
, GLint srcHeight
, GLint srcDepth
,
108 GLenum srcFormat
, GLenum srcType
,
109 const GLvoid
*srcAddr
,
110 const struct gl_pixelstore_attrib
*srcPacking
)
112 const GLint srcRowStride
= _mesa_image_row_stride(srcPacking
, srcWidth
,
114 const GLint srcImageStride
= _mesa_image_image_stride(srcPacking
,
115 srcWidth
, srcHeight
, srcFormat
, srcType
);
116 const GLubyte
*srcImage
= (const GLubyte
*) _mesa_image_address(dimensions
,
117 srcPacking
, srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
118 const GLuint texelBytes
= _mesa_get_format_bytes(dstFormat
);
119 const GLint bytesPerRow
= srcWidth
* texelBytes
;
121 if (dstRowStride
== srcRowStride
&&
122 dstRowStride
== bytesPerRow
) {
123 /* memcpy image by image */
125 for (img
= 0; img
< srcDepth
; img
++) {
126 GLubyte
*dstImage
= dstSlices
[img
];
127 memcpy(dstImage
, srcImage
, bytesPerRow
* srcHeight
);
128 srcImage
+= srcImageStride
;
132 /* memcpy row by row */
134 for (img
= 0; img
< srcDepth
; img
++) {
135 const GLubyte
*srcRow
= srcImage
;
136 GLubyte
*dstRow
= dstSlices
[img
];
137 for (row
= 0; row
< srcHeight
; row
++) {
138 memcpy(dstRow
, srcRow
, bytesPerRow
);
139 dstRow
+= dstRowStride
;
140 srcRow
+= srcRowStride
;
142 srcImage
+= srcImageStride
;
149 * Store a 32-bit integer or float depth component texture image.
152 _mesa_texstore_z32(TEXSTORE_PARAMS
)
154 const GLuint depthScale
= 0xffffffff;
157 assert(dstFormat
== MESA_FORMAT_Z_UNORM32
||
158 dstFormat
== MESA_FORMAT_Z_FLOAT32
);
159 assert(_mesa_get_format_bytes(dstFormat
) == sizeof(GLuint
));
161 if (dstFormat
== MESA_FORMAT_Z_UNORM32
)
162 dstType
= GL_UNSIGNED_INT
;
169 for (img
= 0; img
< srcDepth
; img
++) {
170 GLubyte
*dstRow
= dstSlices
[img
];
171 for (row
= 0; row
< srcHeight
; row
++) {
172 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
173 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
174 _mesa_unpack_depth_span(ctx
, srcWidth
,
176 depthScale
, srcType
, src
, srcPacking
);
177 dstRow
+= dstRowStride
;
186 * Store a 24-bit integer depth component texture image.
189 _mesa_texstore_x8_z24(TEXSTORE_PARAMS
)
191 const GLuint depthScale
= 0xffffff;
194 assert(dstFormat
== MESA_FORMAT_Z24_UNORM_X8_UINT
);
199 for (img
= 0; img
< srcDepth
; img
++) {
200 GLubyte
*dstRow
= dstSlices
[img
];
201 for (row
= 0; row
< srcHeight
; row
++) {
202 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
203 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
204 _mesa_unpack_depth_span(ctx
, srcWidth
,
205 GL_UNSIGNED_INT
, (GLuint
*) dstRow
,
206 depthScale
, srcType
, src
, srcPacking
);
207 dstRow
+= dstRowStride
;
216 * Store a 24-bit integer depth component texture image.
219 _mesa_texstore_z24_x8(TEXSTORE_PARAMS
)
221 const GLuint depthScale
= 0xffffff;
224 assert(dstFormat
== MESA_FORMAT_X8_UINT_Z24_UNORM
);
229 for (img
= 0; img
< srcDepth
; img
++) {
230 GLubyte
*dstRow
= dstSlices
[img
];
231 for (row
= 0; row
< srcHeight
; row
++) {
232 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
233 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
234 GLuint
*dst
= (GLuint
*) dstRow
;
236 _mesa_unpack_depth_span(ctx
, srcWidth
,
237 GL_UNSIGNED_INT
, dst
,
238 depthScale
, srcType
, src
, srcPacking
);
239 for (i
= 0; i
< srcWidth
; i
++)
241 dstRow
+= dstRowStride
;
250 * Store a 16-bit integer depth component texture image.
253 _mesa_texstore_z16(TEXSTORE_PARAMS
)
255 const GLuint depthScale
= 0xffff;
257 assert(dstFormat
== MESA_FORMAT_Z_UNORM16
);
258 assert(_mesa_get_format_bytes(dstFormat
) == sizeof(GLushort
));
263 for (img
= 0; img
< srcDepth
; img
++) {
264 GLubyte
*dstRow
= dstSlices
[img
];
265 for (row
= 0; row
< srcHeight
; row
++) {
266 const GLvoid
*src
= _mesa_image_address(dims
, srcPacking
,
267 srcAddr
, srcWidth
, srcHeight
, srcFormat
, srcType
, img
, row
, 0);
268 GLushort
*dst16
= (GLushort
*) dstRow
;
269 _mesa_unpack_depth_span(ctx
, srcWidth
,
270 GL_UNSIGNED_SHORT
, dst16
, depthScale
,
271 srcType
, src
, srcPacking
);
272 dstRow
+= dstRowStride
;
281 * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_REV.
284 _mesa_texstore_ycbcr(TEXSTORE_PARAMS
)
286 const GLboolean littleEndian
= _mesa_little_endian();
288 (void) ctx
; (void) dims
; (void) baseInternalFormat
;
290 assert((dstFormat
== MESA_FORMAT_YCBCR
) ||
291 (dstFormat
== MESA_FORMAT_YCBCR_REV
));
292 assert(_mesa_get_format_bytes(dstFormat
) == 2);
293 assert(ctx
->Extensions
.MESA_ycbcr_texture
);
294 assert(srcFormat
== GL_YCBCR_MESA
);
295 assert((srcType
== GL_UNSIGNED_SHORT_8_8_MESA
) ||
296 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
));
297 assert(baseInternalFormat
== GL_YCBCR_MESA
);
299 /* always just memcpy since no pixel transfer ops apply */
300 memcpy_texture(ctx
, dims
,
302 dstRowStride
, dstSlices
,
303 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
304 srcAddr
, srcPacking
);
306 /* Check if we need byte swapping */
307 /* XXX the logic here _might_ be wrong */
308 if (srcPacking
->SwapBytes
^
309 (srcType
== GL_UNSIGNED_SHORT_8_8_REV_MESA
) ^
310 (dstFormat
== MESA_FORMAT_YCBCR_REV
) ^
313 for (img
= 0; img
< srcDepth
; img
++) {
314 GLubyte
*dstRow
= dstSlices
[img
];
315 for (row
= 0; row
< srcHeight
; row
++) {
316 _mesa_swap2((GLushort
*) dstRow
, srcWidth
);
317 dstRow
+= dstRowStride
;
326 * Store a combined depth/stencil texture image.
329 _mesa_texstore_z24_s8(TEXSTORE_PARAMS
)
331 const GLuint depthScale
= 0xffffff;
332 const GLint srcRowStride
333 = _mesa_image_row_stride(srcPacking
, srcWidth
, srcFormat
, srcType
);
335 GLuint
*depth
= malloc(srcWidth
* sizeof(GLuint
));
336 GLubyte
*stencil
= malloc(srcWidth
* sizeof(GLubyte
));
338 assert(dstFormat
== MESA_FORMAT_S8_UINT_Z24_UNORM
);
339 assert(srcFormat
== GL_DEPTH_STENCIL_EXT
||
340 srcFormat
== GL_DEPTH_COMPONENT
||
341 srcFormat
== GL_STENCIL_INDEX
);
342 assert(srcFormat
!= GL_DEPTH_STENCIL_EXT
||
343 srcType
== GL_UNSIGNED_INT_24_8_EXT
||
344 srcType
== GL_FLOAT_32_UNSIGNED_INT_24_8_REV
);
346 if (!depth
|| !stencil
) {
352 /* In case we only upload depth we need to preserve the stencil */
353 for (img
= 0; img
< srcDepth
; img
++) {
354 GLuint
*dstRow
= (GLuint
*) dstSlices
[img
];
356 = (const GLubyte
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
360 for (row
= 0; row
< srcHeight
; row
++) {
362 GLboolean keepdepth
= GL_FALSE
, keepstencil
= GL_FALSE
;
364 if (srcFormat
== GL_DEPTH_COMPONENT
) { /* preserve stencil */
365 keepstencil
= GL_TRUE
;
367 else if (srcFormat
== GL_STENCIL_INDEX
) { /* preserve depth */
371 if (keepdepth
== GL_FALSE
)
372 /* the 24 depth bits will be in the low position: */
373 _mesa_unpack_depth_span(ctx
, srcWidth
,
374 GL_UNSIGNED_INT
, /* dst type */
375 keepstencil
? depth
: dstRow
, /* dst addr */
377 srcType
, src
, srcPacking
);
379 if (keepstencil
== GL_FALSE
)
380 /* get the 8-bit stencil values */
381 _mesa_unpack_stencil_span(ctx
, srcWidth
,
382 GL_UNSIGNED_BYTE
, /* dst type */
383 stencil
, /* dst addr */
384 srcType
, src
, srcPacking
,
385 ctx
->_ImageTransferState
);
387 for (i
= 0; i
< srcWidth
; i
++) {
389 dstRow
[i
] = depth
[i
] << 8 | (dstRow
[i
] & 0x000000FF);
391 dstRow
[i
] = (dstRow
[i
] & 0xFFFFFF00) | (stencil
[i
] & 0xFF);
394 dstRow
+= dstRowStride
/ sizeof(GLuint
);
405 * Store a combined depth/stencil texture image.
408 _mesa_texstore_s8_z24(TEXSTORE_PARAMS
)
410 const GLuint depthScale
= 0xffffff;
411 const GLint srcRowStride
412 = _mesa_image_row_stride(srcPacking
, srcWidth
, srcFormat
, srcType
);
417 assert(dstFormat
== MESA_FORMAT_Z24_UNORM_S8_UINT
);
418 assert(srcFormat
== GL_DEPTH_STENCIL_EXT
||
419 srcFormat
== GL_DEPTH_COMPONENT
||
420 srcFormat
== GL_STENCIL_INDEX
);
421 assert(srcFormat
!= GL_DEPTH_STENCIL_EXT
||
422 srcType
== GL_UNSIGNED_INT_24_8_EXT
||
423 srcType
== GL_FLOAT_32_UNSIGNED_INT_24_8_REV
);
425 depth
= malloc(srcWidth
* sizeof(GLuint
));
426 stencil
= malloc(srcWidth
* sizeof(GLubyte
));
428 if (!depth
|| !stencil
) {
434 for (img
= 0; img
< srcDepth
; img
++) {
435 GLuint
*dstRow
= (GLuint
*) dstSlices
[img
];
437 = (const GLubyte
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
441 for (row
= 0; row
< srcHeight
; row
++) {
443 GLboolean keepdepth
= GL_FALSE
, keepstencil
= GL_FALSE
;
445 if (srcFormat
== GL_DEPTH_COMPONENT
) { /* preserve stencil */
446 keepstencil
= GL_TRUE
;
448 else if (srcFormat
== GL_STENCIL_INDEX
) { /* preserve depth */
452 if (keepdepth
== GL_FALSE
)
453 /* the 24 depth bits will be in the low position: */
454 _mesa_unpack_depth_span(ctx
, srcWidth
,
455 GL_UNSIGNED_INT
, /* dst type */
456 keepstencil
? depth
: dstRow
, /* dst addr */
458 srcType
, src
, srcPacking
);
460 if (keepstencil
== GL_FALSE
)
461 /* get the 8-bit stencil values */
462 _mesa_unpack_stencil_span(ctx
, srcWidth
,
463 GL_UNSIGNED_BYTE
, /* dst type */
464 stencil
, /* dst addr */
465 srcType
, src
, srcPacking
,
466 ctx
->_ImageTransferState
);
468 /* merge stencil values into depth values */
469 for (i
= 0; i
< srcWidth
; i
++) {
471 dstRow
[i
] = depth
[i
] | (dstRow
[i
] & 0xFF000000);
473 dstRow
[i
] = (dstRow
[i
] & 0xFFFFFF) | (stencil
[i
] << 24);
477 dstRow
+= dstRowStride
/ sizeof(GLuint
);
489 * Store simple 8-bit/value stencil texture data.
492 _mesa_texstore_s8(TEXSTORE_PARAMS
)
494 assert(dstFormat
== MESA_FORMAT_S_UINT8
);
495 assert(srcFormat
== GL_STENCIL_INDEX
);
498 const GLint srcRowStride
499 = _mesa_image_row_stride(srcPacking
, srcWidth
, srcFormat
, srcType
);
501 GLubyte
*stencil
= malloc(srcWidth
* sizeof(GLubyte
));
506 for (img
= 0; img
< srcDepth
; img
++) {
507 GLubyte
*dstRow
= dstSlices
[img
];
509 = (const GLubyte
*) _mesa_image_address(dims
, srcPacking
, srcAddr
,
513 for (row
= 0; row
< srcHeight
; row
++) {
516 /* get the 8-bit stencil values */
517 _mesa_unpack_stencil_span(ctx
, srcWidth
,
518 GL_UNSIGNED_BYTE
, /* dst type */
519 stencil
, /* dst addr */
520 srcType
, src
, srcPacking
,
521 ctx
->_ImageTransferState
);
522 /* merge stencil values into depth values */
523 for (i
= 0; i
< srcWidth
; i
++)
524 dstRow
[i
] = stencil
[i
];
527 dstRow
+= dstRowStride
/ sizeof(GLubyte
);
539 _mesa_texstore_z32f_x24s8(TEXSTORE_PARAMS
)
542 const GLint srcRowStride
543 = _mesa_image_row_stride(srcPacking
, srcWidth
, srcFormat
, srcType
)
546 assert(dstFormat
== MESA_FORMAT_Z32_FLOAT_S8X24_UINT
);
547 assert(srcFormat
== GL_DEPTH_STENCIL
||
548 srcFormat
== GL_DEPTH_COMPONENT
||
549 srcFormat
== GL_STENCIL_INDEX
);
550 assert(srcFormat
!= GL_DEPTH_STENCIL
||
551 srcType
== GL_UNSIGNED_INT_24_8
||
552 srcType
== GL_FLOAT_32_UNSIGNED_INT_24_8_REV
);
554 /* In case we only upload depth we need to preserve the stencil */
555 for (img
= 0; img
< srcDepth
; img
++) {
556 uint64_t *dstRow
= (uint64_t *) dstSlices
[img
];
558 = (const uint64_t *) _mesa_image_address(dims
, srcPacking
, srcAddr
,
562 for (row
= 0; row
< srcHeight
; row
++) {
563 /* The unpack functions with:
564 * dstType = GL_FLOAT_32_UNSIGNED_INT_24_8_REV
565 * only write their own dword, so the other dword (stencil
566 * or depth) is preserved. */
567 if (srcFormat
!= GL_STENCIL_INDEX
)
568 _mesa_unpack_depth_span(ctx
, srcWidth
,
569 GL_FLOAT_32_UNSIGNED_INT_24_8_REV
, /* dst type */
570 dstRow
, /* dst addr */
571 ~0U, srcType
, src
, srcPacking
);
573 if (srcFormat
!= GL_DEPTH_COMPONENT
)
574 _mesa_unpack_stencil_span(ctx
, srcWidth
,
575 GL_FLOAT_32_UNSIGNED_INT_24_8_REV
, /* dst type */
576 dstRow
, /* dst addr */
577 srcType
, src
, srcPacking
,
578 ctx
->_ImageTransferState
);
581 dstRow
+= dstRowStride
/ sizeof(uint64_t);
588 texstore_depth_stencil(TEXSTORE_PARAMS
)
590 static StoreTexImageFunc table
[MESA_FORMAT_COUNT
];
591 static GLboolean initialized
= GL_FALSE
;
594 memset(table
, 0, sizeof table
);
596 table
[MESA_FORMAT_S8_UINT_Z24_UNORM
] = _mesa_texstore_z24_s8
;
597 table
[MESA_FORMAT_Z24_UNORM_S8_UINT
] = _mesa_texstore_s8_z24
;
598 table
[MESA_FORMAT_Z_UNORM16
] = _mesa_texstore_z16
;
599 table
[MESA_FORMAT_Z24_UNORM_X8_UINT
] = _mesa_texstore_x8_z24
;
600 table
[MESA_FORMAT_X8_UINT_Z24_UNORM
] = _mesa_texstore_z24_x8
;
601 table
[MESA_FORMAT_Z_UNORM32
] = _mesa_texstore_z32
;
602 table
[MESA_FORMAT_S_UINT8
] = _mesa_texstore_s8
;
603 table
[MESA_FORMAT_Z_FLOAT32
] = _mesa_texstore_z32
;
604 table
[MESA_FORMAT_Z32_FLOAT_S8X24_UINT
] = _mesa_texstore_z32f_x24s8
;
606 initialized
= GL_TRUE
;
609 assert(table
[dstFormat
]);
610 return table
[dstFormat
](ctx
, dims
, baseInternalFormat
,
611 dstFormat
, dstRowStride
, dstSlices
,
612 srcWidth
, srcHeight
, srcDepth
,
613 srcFormat
, srcType
, srcAddr
, srcPacking
);
617 texstore_compressed(TEXSTORE_PARAMS
)
619 static StoreTexImageFunc table
[MESA_FORMAT_COUNT
];
620 static GLboolean initialized
= GL_FALSE
;
623 memset(table
, 0, sizeof table
);
625 table
[MESA_FORMAT_SRGB_DXT1
] = _mesa_texstore_rgb_dxt1
;
626 table
[MESA_FORMAT_SRGBA_DXT1
] = _mesa_texstore_rgba_dxt1
;
627 table
[MESA_FORMAT_SRGBA_DXT3
] = _mesa_texstore_rgba_dxt3
;
628 table
[MESA_FORMAT_SRGBA_DXT5
] = _mesa_texstore_rgba_dxt5
;
629 table
[MESA_FORMAT_RGB_FXT1
] = _mesa_texstore_rgb_fxt1
;
630 table
[MESA_FORMAT_RGBA_FXT1
] = _mesa_texstore_rgba_fxt1
;
631 table
[MESA_FORMAT_RGB_DXT1
] = _mesa_texstore_rgb_dxt1
;
632 table
[MESA_FORMAT_RGBA_DXT1
] = _mesa_texstore_rgba_dxt1
;
633 table
[MESA_FORMAT_RGBA_DXT3
] = _mesa_texstore_rgba_dxt3
;
634 table
[MESA_FORMAT_RGBA_DXT5
] = _mesa_texstore_rgba_dxt5
;
635 table
[MESA_FORMAT_R_RGTC1_UNORM
] = _mesa_texstore_red_rgtc1
;
636 table
[MESA_FORMAT_R_RGTC1_SNORM
] = _mesa_texstore_signed_red_rgtc1
;
637 table
[MESA_FORMAT_RG_RGTC2_UNORM
] = _mesa_texstore_rg_rgtc2
;
638 table
[MESA_FORMAT_RG_RGTC2_SNORM
] = _mesa_texstore_signed_rg_rgtc2
;
639 table
[MESA_FORMAT_L_LATC1_UNORM
] = _mesa_texstore_red_rgtc1
;
640 table
[MESA_FORMAT_L_LATC1_SNORM
] = _mesa_texstore_signed_red_rgtc1
;
641 table
[MESA_FORMAT_LA_LATC2_UNORM
] = _mesa_texstore_rg_rgtc2
;
642 table
[MESA_FORMAT_LA_LATC2_SNORM
] = _mesa_texstore_signed_rg_rgtc2
;
643 table
[MESA_FORMAT_ETC1_RGB8
] = _mesa_texstore_etc1_rgb8
;
644 table
[MESA_FORMAT_ETC2_RGB8
] = _mesa_texstore_etc2_rgb8
;
645 table
[MESA_FORMAT_ETC2_SRGB8
] = _mesa_texstore_etc2_srgb8
;
646 table
[MESA_FORMAT_ETC2_RGBA8_EAC
] = _mesa_texstore_etc2_rgba8_eac
;
647 table
[MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC
] = _mesa_texstore_etc2_srgb8_alpha8_eac
;
648 table
[MESA_FORMAT_ETC2_R11_EAC
] = _mesa_texstore_etc2_r11_eac
;
649 table
[MESA_FORMAT_ETC2_RG11_EAC
] = _mesa_texstore_etc2_rg11_eac
;
650 table
[MESA_FORMAT_ETC2_SIGNED_R11_EAC
] = _mesa_texstore_etc2_signed_r11_eac
;
651 table
[MESA_FORMAT_ETC2_SIGNED_RG11_EAC
] = _mesa_texstore_etc2_signed_rg11_eac
;
652 table
[MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1
] =
653 _mesa_texstore_etc2_rgb8_punchthrough_alpha1
;
654 table
[MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1
] =
655 _mesa_texstore_etc2_srgb8_punchthrough_alpha1
;
657 table
[MESA_FORMAT_BPTC_RGBA_UNORM
] =
658 _mesa_texstore_bptc_rgba_unorm
;
659 table
[MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM
] =
660 _mesa_texstore_bptc_rgba_unorm
;
661 table
[MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT
] =
662 _mesa_texstore_bptc_rgb_signed_float
;
663 table
[MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT
] =
664 _mesa_texstore_bptc_rgb_unsigned_float
;
666 initialized
= GL_TRUE
;
669 assert(table
[dstFormat
]);
670 return table
[dstFormat
](ctx
, dims
, baseInternalFormat
,
671 dstFormat
, dstRowStride
, dstSlices
,
672 srcWidth
, srcHeight
, srcDepth
,
673 srcFormat
, srcType
, srcAddr
, srcPacking
);
677 texstore_rgba(TEXSTORE_PARAMS
)
679 void *tempImage
= NULL
, *tempRGBA
= NULL
;
680 int srcRowStride
, img
;
682 uint32_t srcMesaFormat
;
683 uint8_t rebaseSwizzle
[4];
685 bool transferOpsDone
= false;
687 /* We have to handle MESA_FORMAT_YCBCR manually because it is a special case
688 * and _mesa_format_convert does not support it. In this case the we only
689 * allow conversions between YCBCR formats and it is mostly a memcpy.
691 if (dstFormat
== MESA_FORMAT_YCBCR
|| dstFormat
== MESA_FORMAT_YCBCR_REV
) {
692 return _mesa_texstore_ycbcr(ctx
, dims
, baseInternalFormat
,
693 dstFormat
, dstRowStride
, dstSlices
,
694 srcWidth
, srcHeight
, srcDepth
,
695 srcFormat
, srcType
, srcAddr
,
699 /* We have to deal with GL_COLOR_INDEX manually because
700 * _mesa_format_convert does not handle this format. So what we do here is
701 * convert it to RGBA ubyte first and then convert from that to dst as usual.
703 if (srcFormat
== GL_COLOR_INDEX
) {
704 /* Notice that this will already handle byte swapping if necessary */
706 _mesa_unpack_color_index_to_rgba_ubyte(ctx
, dims
,
707 srcAddr
, srcFormat
, srcType
,
708 srcWidth
, srcHeight
, srcDepth
,
710 ctx
->_ImageTransferState
);
714 /* _mesa_unpack_color_index_to_rgba_ubyte has handled transferops
717 transferOpsDone
= true;
719 /* Now we only have to adjust our src info for a conversion from
720 * the RGBA ubyte and then we continue as usual.
724 srcType
= GL_UNSIGNED_BYTE
;
725 } else if (srcPacking
->SwapBytes
) {
726 /* We have to handle byte-swapping scenarios before calling
727 * _mesa_format_convert
729 GLint swapSize
= _mesa_sizeof_packed_type(srcType
);
730 if (swapSize
== 2 || swapSize
== 4) {
731 int bytesPerPixel
= _mesa_bytes_per_pixel(srcFormat
, srcType
);
732 int swapsPerPixel
= bytesPerPixel
/ swapSize
;
733 int elementCount
= srcWidth
* srcHeight
* srcDepth
;
734 assert(bytesPerPixel
% swapSize
== 0);
735 tempImage
= malloc(elementCount
* bytesPerPixel
);
739 _mesa_swap2_copy(tempImage
, (GLushort
*) srcAddr
,
740 elementCount
* swapsPerPixel
);
742 _mesa_swap4_copy(tempImage
, (GLuint
*) srcAddr
,
743 elementCount
* swapsPerPixel
);
749 _mesa_image_row_stride(srcPacking
, srcWidth
, srcFormat
, srcType
);
751 srcMesaFormat
= _mesa_format_from_format_and_type(srcFormat
, srcType
);
752 dstFormat
= _mesa_get_srgb_format_linear(dstFormat
);
754 /* If we have transferOps then we need to convert to RGBA float first,
755 then apply transferOps, then do the conversion to dst
757 if (!transferOpsDone
&&
758 _mesa_texstore_needs_transfer_ops(ctx
, baseInternalFormat
, dstFormat
)) {
759 /* Allocate RGBA float image */
760 int elementCount
= srcWidth
* srcHeight
* srcDepth
;
761 tempRGBA
= malloc(4 * elementCount
* sizeof(float));
768 /* Convert from src to RGBA float */
769 src
= (GLubyte
*) srcAddr
;
770 dst
= (GLubyte
*) tempRGBA
;
771 for (img
= 0; img
< srcDepth
; img
++) {
772 _mesa_format_convert(dst
, RGBA32_FLOAT
, 4 * srcWidth
* sizeof(float),
773 src
, srcMesaFormat
, srcRowStride
,
774 srcWidth
, srcHeight
, NULL
);
775 src
+= srcHeight
* srcRowStride
;
776 dst
+= srcHeight
* 4 * srcWidth
* sizeof(float);
779 /* Apply transferOps */
780 _mesa_apply_rgba_transfer_ops(ctx
, ctx
->_ImageTransferState
, elementCount
,
781 (float(*)[4]) tempRGBA
);
783 /* Now we have to adjust our src info for a conversion from
784 * the RGBA float image and then we continue as usual.
789 srcRowStride
= srcWidth
* 4 * sizeof(float);
790 srcMesaFormat
= RGBA32_FLOAT
;
794 _mesa_image_address(dims
, srcPacking
, srcAddr
, srcWidth
, srcHeight
,
795 srcFormat
, srcType
, 0, 0, 0);
797 if (_mesa_get_format_base_format(dstFormat
) != baseInternalFormat
) {
799 _mesa_compute_rgba2base2rgba_component_mapping(baseInternalFormat
,
805 for (img
= 0; img
< srcDepth
; img
++) {
806 _mesa_format_convert(dstSlices
[img
], dstFormat
, dstRowStride
,
807 src
, srcMesaFormat
, srcRowStride
,
809 needRebase
? rebaseSwizzle
: NULL
);
810 src
+= srcHeight
* srcRowStride
;
820 _mesa_texstore_needs_transfer_ops(struct gl_context
*ctx
,
821 GLenum baseInternalFormat
,
822 mesa_format dstFormat
)
826 /* There are different rules depending on the base format. */
827 switch (baseInternalFormat
) {
828 case GL_DEPTH_COMPONENT
:
829 case GL_DEPTH_STENCIL
:
830 return ctx
->Pixel
.DepthScale
!= 1.0f
||
831 ctx
->Pixel
.DepthBias
!= 0.0f
;
833 case GL_STENCIL_INDEX
:
838 * Pixel transfer ops (scale, bias, table lookup) do not apply
839 * to integer formats.
841 dstType
= _mesa_get_format_datatype(dstFormat
);
843 return dstType
!= GL_INT
&& dstType
!= GL_UNSIGNED_INT
&&
844 ctx
->_ImageTransferState
;
850 _mesa_texstore_can_use_memcpy(struct gl_context
*ctx
,
851 GLenum baseInternalFormat
, mesa_format dstFormat
,
852 GLenum srcFormat
, GLenum srcType
,
853 const struct gl_pixelstore_attrib
*srcPacking
)
855 if (_mesa_texstore_needs_transfer_ops(ctx
, baseInternalFormat
, dstFormat
)) {
859 /* The base internal format and the base Mesa format must match. */
860 if (baseInternalFormat
!= _mesa_get_format_base_format(dstFormat
)) {
864 /* The Mesa format must match the input format and type. */
865 if (!_mesa_format_matches_format_and_type(dstFormat
, srcFormat
, srcType
,
866 srcPacking
->SwapBytes
)) {
870 /* Depth texture data needs clamping in following cases:
871 * - Floating point dstFormat with signed srcType: clamp to [0.0, 1.0].
872 * - Fixed point dstFormat with signed srcType: clamp to [0, 2^n -1].
874 * All the cases except one (float dstFormat with float srcType) are ruled
875 * out by _mesa_format_matches_format_and_type() check above. Handle the
876 * remaining case here.
878 if ((baseInternalFormat
== GL_DEPTH_COMPONENT
||
879 baseInternalFormat
== GL_DEPTH_STENCIL
) &&
880 (srcType
== GL_FLOAT
||
881 srcType
== GL_FLOAT_32_UNSIGNED_INT_24_8_REV
)) {
889 _mesa_texstore_memcpy(TEXSTORE_PARAMS
)
891 if (!_mesa_texstore_can_use_memcpy(ctx
, baseInternalFormat
, dstFormat
,
892 srcFormat
, srcType
, srcPacking
)) {
896 memcpy_texture(ctx
, dims
,
898 dstRowStride
, dstSlices
,
899 srcWidth
, srcHeight
, srcDepth
, srcFormat
, srcType
,
900 srcAddr
, srcPacking
);
904 * Store user data into texture memory.
905 * Called via glTex[Sub]Image1/2/3D()
906 * \return GL_TRUE for success, GL_FALSE for failure (out of memory).
909 _mesa_texstore(TEXSTORE_PARAMS
)
911 if (_mesa_texstore_memcpy(ctx
, dims
, baseInternalFormat
,
913 dstRowStride
, dstSlices
,
914 srcWidth
, srcHeight
, srcDepth
,
915 srcFormat
, srcType
, srcAddr
, srcPacking
)) {
919 if (_mesa_is_depth_or_stencil_format(baseInternalFormat
)) {
920 return texstore_depth_stencil(ctx
, dims
, baseInternalFormat
,
921 dstFormat
, dstRowStride
, dstSlices
,
922 srcWidth
, srcHeight
, srcDepth
,
923 srcFormat
, srcType
, srcAddr
, srcPacking
);
924 } else if (_mesa_is_format_compressed(dstFormat
)) {
925 return texstore_compressed(ctx
, dims
, baseInternalFormat
,
926 dstFormat
, dstRowStride
, dstSlices
,
927 srcWidth
, srcHeight
, srcDepth
,
928 srcFormat
, srcType
, srcAddr
, srcPacking
);
930 return texstore_rgba(ctx
, dims
, baseInternalFormat
,
931 dstFormat
, dstRowStride
, dstSlices
,
932 srcWidth
, srcHeight
, srcDepth
,
933 srcFormat
, srcType
, srcAddr
, srcPacking
);
939 * Normally, we'll only _write_ texel data to a texture when we map it.
940 * But if the user is providing depth or stencil values and the texture
941 * image is a combined depth/stencil format, we'll actually read from
942 * the texture buffer too (in order to insert the depth or stencil values.
943 * \param userFormat the user-provided image format
944 * \param texFormat the destination texture format
947 get_read_write_mode(GLenum userFormat
, mesa_format texFormat
)
949 if ((userFormat
== GL_STENCIL_INDEX
|| userFormat
== GL_DEPTH_COMPONENT
)
950 && _mesa_get_format_base_format(texFormat
) == GL_DEPTH_STENCIL
)
951 return GL_MAP_READ_BIT
| GL_MAP_WRITE_BIT
;
953 return GL_MAP_WRITE_BIT
| GL_MAP_INVALIDATE_RANGE_BIT
;
958 * Helper function for storing 1D, 2D, 3D whole and subimages into texture
960 * The source of the image data may be user memory or a PBO. In the later
961 * case, we'll map the PBO, copy from it, then unmap it.
964 store_texsubimage(struct gl_context
*ctx
,
965 struct gl_texture_image
*texImage
,
966 GLint xoffset
, GLint yoffset
, GLint zoffset
,
967 GLint width
, GLint height
, GLint depth
,
968 GLenum format
, GLenum type
, const GLvoid
*pixels
,
969 const struct gl_pixelstore_attrib
*packing
,
973 const GLbitfield mapMode
= get_read_write_mode(format
, texImage
->TexFormat
);
974 const GLenum target
= texImage
->TexObject
->Target
;
975 GLboolean success
= GL_FALSE
;
976 GLuint dims
, slice
, numSlices
= 1, sliceOffset
= 0;
977 GLint srcImageStride
= 0;
980 assert(xoffset
+ width
<= texImage
->Width
);
981 assert(yoffset
+ height
<= texImage
->Height
);
982 assert(zoffset
+ depth
<= texImage
->Depth
);
988 case GL_TEXTURE_2D_ARRAY
:
989 case GL_TEXTURE_CUBE_MAP_ARRAY
:
997 /* get pointer to src pixels (may be in a pbo which we'll map here) */
998 src
= (const GLubyte
*)
999 _mesa_validate_pbo_teximage(ctx
, dims
, width
, height
, depth
,
1000 format
, type
, pixels
, packing
, caller
);
1004 /* compute slice info (and do some sanity checks) */
1007 case GL_TEXTURE_RECTANGLE
:
1008 case GL_TEXTURE_CUBE_MAP
:
1009 case GL_TEXTURE_EXTERNAL_OES
:
1010 /* one image slice, nothing special needs to be done */
1013 assert(height
== 1);
1015 assert(yoffset
== 0);
1016 assert(zoffset
== 0);
1018 case GL_TEXTURE_1D_ARRAY
:
1020 assert(zoffset
== 0);
1022 sliceOffset
= yoffset
;
1025 srcImageStride
= _mesa_image_row_stride(packing
, width
, format
, type
);
1027 case GL_TEXTURE_2D_ARRAY
:
1029 sliceOffset
= zoffset
;
1032 srcImageStride
= _mesa_image_image_stride(packing
, width
, height
,
1036 /* we'll store 3D images as a series of slices */
1038 sliceOffset
= zoffset
;
1039 srcImageStride
= _mesa_image_image_stride(packing
, width
, height
,
1042 case GL_TEXTURE_CUBE_MAP_ARRAY
:
1044 sliceOffset
= zoffset
;
1045 srcImageStride
= _mesa_image_image_stride(packing
, width
, height
,
1049 _mesa_warning(ctx
, "Unexpected target 0x%x in store_texsubimage()", target
);
1053 assert(numSlices
== 1 || srcImageStride
!= 0);
1055 for (slice
= 0; slice
< numSlices
; slice
++) {
1059 ctx
->Driver
.MapTextureImage(ctx
, texImage
,
1060 slice
+ sliceOffset
,
1061 xoffset
, yoffset
, width
, height
,
1062 mapMode
, &dstMap
, &dstRowStride
);
1064 /* Note: we're only storing a 2D (or 1D) slice at a time but we need
1065 * to pass the right 'dims' value so that GL_UNPACK_SKIP_IMAGES is
1066 * used for 3D images.
1068 success
= _mesa_texstore(ctx
, dims
, texImage
->_BaseFormat
,
1069 texImage
->TexFormat
,
1072 width
, height
, 1, /* w, h, d */
1073 format
, type
, src
, packing
);
1075 ctx
->Driver
.UnmapTextureImage(ctx
, texImage
, slice
+ sliceOffset
);
1078 src
+= srcImageStride
;
1085 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "%s", caller
);
1087 _mesa_unmap_teximage_pbo(ctx
, packing
);
1093 * Fallback code for ctx->Driver.TexImage().
1094 * Basically, allocate storage for the texture image, then copy the
1095 * user's image into it.
1098 _mesa_store_teximage(struct gl_context
*ctx
,
1100 struct gl_texture_image
*texImage
,
1101 GLenum format
, GLenum type
, const GLvoid
*pixels
,
1102 const struct gl_pixelstore_attrib
*packing
)
1104 assert(dims
== 1 || dims
== 2 || dims
== 3);
1106 if (texImage
->Width
== 0 || texImage
->Height
== 0 || texImage
->Depth
== 0)
1109 /* allocate storage for texture data */
1110 if (!ctx
->Driver
.AllocTextureImageBuffer(ctx
, texImage
)) {
1111 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glTexImage%uD", dims
);
1115 store_texsubimage(ctx
, texImage
,
1116 0, 0, 0, texImage
->Width
, texImage
->Height
, texImage
->Depth
,
1117 format
, type
, pixels
, packing
, "glTexImage");
1122 * Fallback for Driver.TexSubImage().
1125 _mesa_store_texsubimage(struct gl_context
*ctx
, GLuint dims
,
1126 struct gl_texture_image
*texImage
,
1127 GLint xoffset
, GLint yoffset
, GLint zoffset
,
1128 GLint width
, GLint height
, GLint depth
,
1129 GLenum format
, GLenum type
, const void *pixels
,
1130 const struct gl_pixelstore_attrib
*packing
)
1132 store_texsubimage(ctx
, texImage
,
1133 xoffset
, yoffset
, zoffset
, width
, height
, depth
,
1134 format
, type
, pixels
, packing
, "glTexSubImage");
1138 clear_image_to_zero(GLubyte
*dstMap
, GLint dstRowStride
,
1139 GLsizei width
, GLsizei height
,
1140 GLsizei clearValueSize
)
1144 for (y
= 0; y
< height
; y
++) {
1145 memset(dstMap
, 0, clearValueSize
* width
);
1146 dstMap
+= dstRowStride
;
1151 clear_image_to_value(GLubyte
*dstMap
, GLint dstRowStride
,
1152 GLsizei width
, GLsizei height
,
1153 const GLvoid
*clearValue
,
1154 GLsizei clearValueSize
)
1158 for (y
= 0; y
< height
; y
++) {
1159 for (x
= 0; x
< width
; x
++) {
1160 memcpy(dstMap
, clearValue
, clearValueSize
);
1161 dstMap
+= clearValueSize
;
1163 dstMap
+= dstRowStride
- clearValueSize
* width
;
1168 * Fallback for Driver.ClearTexSubImage().
1171 _mesa_store_cleartexsubimage(struct gl_context
*ctx
,
1172 struct gl_texture_image
*texImage
,
1173 GLint xoffset
, GLint yoffset
, GLint zoffset
,
1174 GLsizei width
, GLsizei height
, GLsizei depth
,
1175 const GLvoid
*clearValue
)
1179 GLsizeiptr clearValueSize
;
1182 clearValueSize
= _mesa_get_format_bytes(texImage
->TexFormat
);
1184 for (z
= 0; z
< depth
; z
++) {
1185 ctx
->Driver
.MapTextureImage(ctx
, texImage
,
1186 z
+ zoffset
, xoffset
, yoffset
,
1189 &dstMap
, &dstRowStride
);
1190 if (dstMap
== NULL
) {
1191 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glClearTex*Image");
1196 clear_image_to_value(dstMap
, dstRowStride
,
1201 clear_image_to_zero(dstMap
, dstRowStride
,
1206 ctx
->Driver
.UnmapTextureImage(ctx
, texImage
, z
+ zoffset
);
1211 * Fallback for Driver.CompressedTexImage()
1214 _mesa_store_compressed_teximage(struct gl_context
*ctx
, GLuint dims
,
1215 struct gl_texture_image
*texImage
,
1216 GLsizei imageSize
, const GLvoid
*data
)
1218 /* only 2D and 3D compressed images are supported at this time */
1220 _mesa_problem(ctx
, "Unexpected glCompressedTexImage1D call");
1224 /* This is pretty simple, because unlike the general texstore path we don't
1225 * have to worry about the usual image unpacking or image transfer
1229 assert(texImage
->Width
> 0);
1230 assert(texImage
->Height
> 0);
1231 assert(texImage
->Depth
> 0);
1233 /* allocate storage for texture data */
1234 if (!ctx
->Driver
.AllocTextureImageBuffer(ctx
, texImage
)) {
1235 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexImage%uD", dims
);
1239 _mesa_store_compressed_texsubimage(ctx
, dims
, texImage
,
1241 texImage
->Width
, texImage
->Height
, texImage
->Depth
,
1242 texImage
->TexFormat
,
1248 * Compute compressed_pixelstore parameters for copying compressed
1250 * \param dims number of texture image dimensions: 1, 2 or 3
1251 * \param texFormat the compressed texture format
1252 * \param width, height, depth size of image to copy
1253 * \param packing pixelstore parameters describing user-space image packing
1254 * \param store returns the compressed_pixelstore parameters
1257 _mesa_compute_compressed_pixelstore(GLuint dims
, mesa_format texFormat
,
1258 GLsizei width
, GLsizei height
,
1260 const struct gl_pixelstore_attrib
*packing
,
1261 struct compressed_pixelstore
*store
)
1265 _mesa_get_format_block_size(texFormat
, &bw
, &bh
);
1267 store
->SkipBytes
= 0;
1268 store
->TotalBytesPerRow
= store
->CopyBytesPerRow
=
1269 _mesa_format_row_stride(texFormat
, width
);
1270 store
->TotalRowsPerSlice
= store
->CopyRowsPerSlice
=
1271 (height
+ bh
- 1) / bh
;
1272 store
->CopySlices
= depth
;
1274 if (packing
->CompressedBlockWidth
&&
1275 packing
->CompressedBlockSize
) {
1277 bw
= packing
->CompressedBlockWidth
;
1279 if (packing
->RowLength
) {
1280 store
->TotalBytesPerRow
= packing
->CompressedBlockSize
*
1281 ((packing
->RowLength
+ bw
- 1) / bw
);
1284 store
->SkipBytes
+= packing
->SkipPixels
* packing
->CompressedBlockSize
/ bw
;
1287 if (dims
> 1 && packing
->CompressedBlockHeight
&&
1288 packing
->CompressedBlockSize
) {
1290 bh
= packing
->CompressedBlockHeight
;
1292 store
->SkipBytes
+= packing
->SkipRows
* store
->TotalBytesPerRow
/ bh
;
1293 store
->CopyRowsPerSlice
= (height
+ bh
- 1) / bh
; /* rows in blocks */
1295 if (packing
->ImageHeight
) {
1296 store
->TotalRowsPerSlice
= (packing
->ImageHeight
+ bh
- 1) / bh
;
1300 if (dims
> 2 && packing
->CompressedBlockDepth
&&
1301 packing
->CompressedBlockSize
) {
1303 int bd
= packing
->CompressedBlockDepth
;
1305 store
->SkipBytes
+= packing
->SkipImages
* store
->TotalBytesPerRow
*
1306 store
->TotalRowsPerSlice
/ bd
;
1312 * Fallback for Driver.CompressedTexSubImage()
1315 _mesa_store_compressed_texsubimage(struct gl_context
*ctx
, GLuint dims
,
1316 struct gl_texture_image
*texImage
,
1317 GLint xoffset
, GLint yoffset
, GLint zoffset
,
1318 GLsizei width
, GLsizei height
, GLsizei depth
,
1320 GLsizei imageSize
, const GLvoid
*data
)
1322 struct compressed_pixelstore store
;
1329 _mesa_problem(ctx
, "Unexpected 1D compressed texsubimage call");
1333 _mesa_compute_compressed_pixelstore(dims
, texImage
->TexFormat
,
1334 width
, height
, depth
,
1335 &ctx
->Unpack
, &store
);
1337 /* get pointer to src pixels (may be in a pbo which we'll map here) */
1338 data
= _mesa_validate_pbo_compressed_teximage(ctx
, dims
, imageSize
, data
,
1340 "glCompressedTexSubImage");
1344 src
= (const GLubyte
*) data
+ store
.SkipBytes
;
1346 for (slice
= 0; slice
< store
.CopySlices
; slice
++) {
1347 /* Map dest texture buffer */
1348 ctx
->Driver
.MapTextureImage(ctx
, texImage
, slice
+ zoffset
,
1349 xoffset
, yoffset
, width
, height
,
1350 GL_MAP_WRITE_BIT
| GL_MAP_INVALIDATE_RANGE_BIT
,
1351 &dstMap
, &dstRowStride
);
1355 /* copy rows of blocks */
1356 for (i
= 0; i
< store
.CopyRowsPerSlice
; i
++) {
1357 memcpy(dstMap
, src
, store
.CopyBytesPerRow
);
1358 dstMap
+= dstRowStride
;
1359 src
+= store
.TotalBytesPerRow
;
1362 ctx
->Driver
.UnmapTextureImage(ctx
, texImage
, slice
+ zoffset
);
1364 /* advance to next slice */
1365 src
+= store
.TotalBytesPerRow
* (store
.TotalRowsPerSlice
- store
.CopyRowsPerSlice
);
1368 _mesa_error(ctx
, GL_OUT_OF_MEMORY
, "glCompressedTexSubImage%uD",
1373 _mesa_unmap_teximage_pbo(ctx
, &ctx
->Unpack
);