9c7080ab82ecb0753408d94605a23c5022ff1460
[mesa.git] / src / mesa / main / texstore.c
1 /*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
5 * Copyright (c) 2008-2009 VMware, Inc.
6 *
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:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
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.
24 */
25
26 /*
27 * Authors:
28 * Brian Paul
29 */
30
31 /**
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
35 * texture image data.
36 *
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
39 * code:
40 * ctx->Driver.TexImage = _mesa_store_teximage;
41 * ctx->Driver.TexSubImage = _mesa_store_texsubimage;
42 * etc...
43 *
44 * Texture image processing is actually kind of complicated. We have to do:
45 * Format/type conversions
46 * pixel unpacking
47 * pixel transfer (scale, bais, lookup, etc)
48 *
49 * These functions can handle most everything, including processing full
50 * images and sub-images.
51 */
52
53
54 #include "glheader.h"
55 #include "bufferobj.h"
56 #include "colormac.h"
57 #include "format_pack.h"
58 #include "format_utils.h"
59 #include "image.h"
60 #include "macros.h"
61 #include "mipmap.h"
62 #include "mtypes.h"
63 #include "pack.h"
64 #include "pbo.h"
65 #include "imports.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"
72 #include "teximage.h"
73 #include "texstore.h"
74 #include "enums.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"
79
80
81 enum {
82 ZERO = 4,
83 ONE = 5
84 };
85
86
87 /**
88 * Texture image storage function.
89 */
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 };
94
95
96 /**
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.
100 */
101 static void
102 memcpy_texture(struct gl_context *ctx,
103 GLuint dimensions,
104 mesa_format dstFormat,
105 GLint dstRowStride,
106 GLubyte **dstSlices,
107 GLint srcWidth, GLint srcHeight, GLint srcDepth,
108 GLenum srcFormat, GLenum srcType,
109 const GLvoid *srcAddr,
110 const struct gl_pixelstore_attrib *srcPacking)
111 {
112 const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth,
113 srcFormat, srcType);
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;
120
121 if (dstRowStride == srcRowStride &&
122 dstRowStride == bytesPerRow) {
123 /* memcpy image by image */
124 GLint img;
125 for (img = 0; img < srcDepth; img++) {
126 GLubyte *dstImage = dstSlices[img];
127 memcpy(dstImage, srcImage, bytesPerRow * srcHeight);
128 srcImage += srcImageStride;
129 }
130 }
131 else {
132 /* memcpy row by row */
133 GLint img, 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;
141 }
142 srcImage += srcImageStride;
143 }
144 }
145 }
146
147
148 /**
149 * Store a 32-bit integer or float depth component texture image.
150 */
151 static GLboolean
152 _mesa_texstore_z32(TEXSTORE_PARAMS)
153 {
154 const GLuint depthScale = 0xffffffff;
155 GLenum dstType;
156 (void) dims;
157 ASSERT(dstFormat == MESA_FORMAT_Z_UNORM32 ||
158 dstFormat == MESA_FORMAT_Z_FLOAT32);
159 ASSERT(_mesa_get_format_bytes(dstFormat) == sizeof(GLuint));
160
161 if (dstFormat == MESA_FORMAT_Z_UNORM32)
162 dstType = GL_UNSIGNED_INT;
163 else
164 dstType = GL_FLOAT;
165
166 {
167 /* general path */
168 GLint img, row;
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,
175 dstType, dstRow,
176 depthScale, srcType, src, srcPacking);
177 dstRow += dstRowStride;
178 }
179 }
180 }
181 return GL_TRUE;
182 }
183
184
185 /**
186 * Store a 24-bit integer depth component texture image.
187 */
188 static GLboolean
189 _mesa_texstore_x8_z24(TEXSTORE_PARAMS)
190 {
191 const GLuint depthScale = 0xffffff;
192
193 (void) dims;
194 ASSERT(dstFormat == MESA_FORMAT_Z24_UNORM_X8_UINT);
195
196 {
197 /* general path */
198 GLint img, row;
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;
208 }
209 }
210 }
211 return GL_TRUE;
212 }
213
214
215 /**
216 * Store a 24-bit integer depth component texture image.
217 */
218 static GLboolean
219 _mesa_texstore_z24_x8(TEXSTORE_PARAMS)
220 {
221 const GLuint depthScale = 0xffffff;
222
223 (void) dims;
224 ASSERT(dstFormat == MESA_FORMAT_X8_UINT_Z24_UNORM);
225
226 {
227 /* general path */
228 GLint img, row;
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;
235 GLint i;
236 _mesa_unpack_depth_span(ctx, srcWidth,
237 GL_UNSIGNED_INT, dst,
238 depthScale, srcType, src, srcPacking);
239 for (i = 0; i < srcWidth; i++)
240 dst[i] <<= 8;
241 dstRow += dstRowStride;
242 }
243 }
244 }
245 return GL_TRUE;
246 }
247
248
249 /**
250 * Store a 16-bit integer depth component texture image.
251 */
252 static GLboolean
253 _mesa_texstore_z16(TEXSTORE_PARAMS)
254 {
255 const GLuint depthScale = 0xffff;
256 (void) dims;
257 ASSERT(dstFormat == MESA_FORMAT_Z_UNORM16);
258 ASSERT(_mesa_get_format_bytes(dstFormat) == sizeof(GLushort));
259
260 {
261 /* general path */
262 GLint img, row;
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;
273 }
274 }
275 }
276 return GL_TRUE;
277 }
278
279
280 /**
281 * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_REV.
282 */
283 static GLboolean
284 _mesa_texstore_ycbcr(TEXSTORE_PARAMS)
285 {
286 const GLboolean littleEndian = _mesa_little_endian();
287
288 (void) ctx; (void) dims; (void) baseInternalFormat;
289
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);
298
299 /* always just memcpy since no pixel transfer ops apply */
300 memcpy_texture(ctx, dims,
301 dstFormat,
302 dstRowStride, dstSlices,
303 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
304 srcAddr, srcPacking);
305
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) ^
311 !littleEndian) {
312 GLint img, row;
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;
318 }
319 }
320 }
321 return GL_TRUE;
322 }
323
324
325 /**
326 * Store a combined depth/stencil texture image.
327 */
328 static GLboolean
329 _mesa_texstore_z24_s8(TEXSTORE_PARAMS)
330 {
331 const GLuint depthScale = 0xffffff;
332 const GLint srcRowStride
333 = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType);
334 GLint img, row;
335 GLuint *depth = malloc(srcWidth * sizeof(GLuint));
336 GLubyte *stencil = malloc(srcWidth * sizeof(GLubyte));
337
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);
345
346 if (!depth || !stencil) {
347 free(depth);
348 free(stencil);
349 return GL_FALSE;
350 }
351
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];
355 const GLubyte *src
356 = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr,
357 srcWidth, srcHeight,
358 srcFormat, srcType,
359 img, 0, 0);
360 for (row = 0; row < srcHeight; row++) {
361 GLint i;
362 GLboolean keepdepth = GL_FALSE, keepstencil = GL_FALSE;
363
364 if (srcFormat == GL_DEPTH_COMPONENT) { /* preserve stencil */
365 keepstencil = GL_TRUE;
366 }
367 else if (srcFormat == GL_STENCIL_INDEX) { /* preserve depth */
368 keepdepth = GL_TRUE;
369 }
370
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 */
376 depthScale,
377 srcType, src, srcPacking);
378
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);
386
387 for (i = 0; i < srcWidth; i++) {
388 if (keepstencil)
389 dstRow[i] = depth[i] << 8 | (dstRow[i] & 0x000000FF);
390 else
391 dstRow[i] = (dstRow[i] & 0xFFFFFF00) | (stencil[i] & 0xFF);
392 }
393 src += srcRowStride;
394 dstRow += dstRowStride / sizeof(GLuint);
395 }
396 }
397
398 free(depth);
399 free(stencil);
400 return GL_TRUE;
401 }
402
403
404 /**
405 * Store a combined depth/stencil texture image.
406 */
407 static GLboolean
408 _mesa_texstore_s8_z24(TEXSTORE_PARAMS)
409 {
410 const GLuint depthScale = 0xffffff;
411 const GLint srcRowStride
412 = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType);
413 GLint img, row;
414 GLuint *depth;
415 GLubyte *stencil;
416
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);
424
425 depth = malloc(srcWidth * sizeof(GLuint));
426 stencil = malloc(srcWidth * sizeof(GLubyte));
427
428 if (!depth || !stencil) {
429 free(depth);
430 free(stencil);
431 return GL_FALSE;
432 }
433
434 for (img = 0; img < srcDepth; img++) {
435 GLuint *dstRow = (GLuint *) dstSlices[img];
436 const GLubyte *src
437 = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr,
438 srcWidth, srcHeight,
439 srcFormat, srcType,
440 img, 0, 0);
441 for (row = 0; row < srcHeight; row++) {
442 GLint i;
443 GLboolean keepdepth = GL_FALSE, keepstencil = GL_FALSE;
444
445 if (srcFormat == GL_DEPTH_COMPONENT) { /* preserve stencil */
446 keepstencil = GL_TRUE;
447 }
448 else if (srcFormat == GL_STENCIL_INDEX) { /* preserve depth */
449 keepdepth = GL_TRUE;
450 }
451
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 */
457 depthScale,
458 srcType, src, srcPacking);
459
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);
467
468 /* merge stencil values into depth values */
469 for (i = 0; i < srcWidth; i++) {
470 if (keepstencil)
471 dstRow[i] = depth[i] | (dstRow[i] & 0xFF000000);
472 else
473 dstRow[i] = (dstRow[i] & 0xFFFFFF) | (stencil[i] << 24);
474
475 }
476 src += srcRowStride;
477 dstRow += dstRowStride / sizeof(GLuint);
478 }
479 }
480
481 free(depth);
482 free(stencil);
483
484 return GL_TRUE;
485 }
486
487
488 /**
489 * Store simple 8-bit/value stencil texture data.
490 */
491 static GLboolean
492 _mesa_texstore_s8(TEXSTORE_PARAMS)
493 {
494 ASSERT(dstFormat == MESA_FORMAT_S_UINT8);
495 ASSERT(srcFormat == GL_STENCIL_INDEX);
496
497 {
498 const GLint srcRowStride
499 = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType);
500 GLint img, row;
501 GLubyte *stencil = malloc(srcWidth * sizeof(GLubyte));
502
503 if (!stencil)
504 return GL_FALSE;
505
506 for (img = 0; img < srcDepth; img++) {
507 GLubyte *dstRow = dstSlices[img];
508 const GLubyte *src
509 = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr,
510 srcWidth, srcHeight,
511 srcFormat, srcType,
512 img, 0, 0);
513 for (row = 0; row < srcHeight; row++) {
514 GLint i;
515
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];
525
526 src += srcRowStride;
527 dstRow += dstRowStride / sizeof(GLubyte);
528 }
529 }
530
531 free(stencil);
532 }
533
534 return GL_TRUE;
535 }
536
537
538 static GLboolean
539 _mesa_texstore_z32f_x24s8(TEXSTORE_PARAMS)
540 {
541 GLint img, row;
542 const GLint srcRowStride
543 = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType)
544 / sizeof(uint64_t);
545
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);
553
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];
557 const uint64_t *src
558 = (const uint64_t *) _mesa_image_address(dims, srcPacking, srcAddr,
559 srcWidth, srcHeight,
560 srcFormat, srcType,
561 img, 0, 0);
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);
572
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);
579
580 src += srcRowStride;
581 dstRow += dstRowStride / sizeof(uint64_t);
582 }
583 }
584 return GL_TRUE;
585 }
586
587 static GLboolean
588 texstore_depth_stencil(TEXSTORE_PARAMS)
589 {
590 static StoreTexImageFunc table[MESA_FORMAT_COUNT];
591 static GLboolean initialized = GL_FALSE;
592
593 if (!initialized) {
594 memset(table, 0, sizeof table);
595
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;
605
606 initialized = GL_TRUE;
607 }
608
609 ASSERT(table[dstFormat]);
610 return table[dstFormat](ctx, dims, baseInternalFormat,
611 dstFormat, dstRowStride, dstSlices,
612 srcWidth, srcHeight, srcDepth,
613 srcFormat, srcType, srcAddr, srcPacking);
614 }
615
616 static GLboolean
617 texstore_compressed(TEXSTORE_PARAMS)
618 {
619 static StoreTexImageFunc table[MESA_FORMAT_COUNT];
620 static GLboolean initialized = GL_FALSE;
621
622 if (!initialized) {
623 memset(table, 0, sizeof table);
624
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;
656
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;
665
666 initialized = GL_TRUE;
667 }
668
669 ASSERT(table[dstFormat]);
670 return table[dstFormat](ctx, dims, baseInternalFormat,
671 dstFormat, dstRowStride, dstSlices,
672 srcWidth, srcHeight, srcDepth,
673 srcFormat, srcType, srcAddr, srcPacking);
674 }
675
676 static GLboolean
677 texstore_rgba(TEXSTORE_PARAMS)
678 {
679 void *tempImage = NULL, *tempRGBA = NULL;
680 int srcRowStride, img;
681 GLubyte *src, *dst;
682 uint32_t srcMesaFormat;
683 uint8_t rebaseSwizzle[4];
684 bool needRebase;
685 bool transferOpsDone = false;
686
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.
690 */
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,
696 srcPacking);
697 }
698
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.
702 */
703 if (srcFormat == GL_COLOR_INDEX) {
704 /* Notice that this will already handle byte swapping if necessary */
705 tempImage =
706 _mesa_unpack_color_index_to_rgba_ubyte(ctx, dims,
707 srcAddr, srcFormat, srcType,
708 srcWidth, srcHeight, srcDepth,
709 srcPacking,
710 ctx->_ImageTransferState);
711 if (!tempImage)
712 return GL_FALSE;
713
714 /* _mesa_unpack_color_index_to_rgba_ubyte has handled transferops
715 * if needed.
716 */
717 transferOpsDone = true;
718
719 /* Now we only have to adjust our src info for a conversion from
720 * the RGBA ubyte and then we continue as usual.
721 */
722 srcAddr = tempImage;
723 srcFormat = GL_RGBA;
724 srcType = GL_UNSIGNED_BYTE;
725 } else if (srcPacking->SwapBytes) {
726 /* We have to handle byte-swapping scenarios before calling
727 * _mesa_format_convert
728 */
729 GLint swapSize = _mesa_sizeof_packed_type(srcType);
730 if (swapSize == 2 || swapSize == 4) {
731 int components = _mesa_components_in_format(srcFormat);
732 int elementCount = srcWidth * srcHeight * components;
733 tempImage = malloc(elementCount * swapSize);
734 if (!tempImage)
735 return GL_FALSE;
736 if (swapSize == 2)
737 _mesa_swap2_copy(tempImage, (GLushort *) srcAddr, elementCount);
738 else
739 _mesa_swap4_copy(tempImage, (GLuint *) srcAddr, elementCount);
740 srcAddr = tempImage;
741 }
742 }
743
744 srcRowStride =
745 _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType);
746
747 srcMesaFormat = _mesa_format_from_format_and_type(srcFormat, srcType);
748 dstFormat = _mesa_get_srgb_format_linear(dstFormat);
749
750 /* If we have transferOps then we need to convert to RGBA float first,
751 then apply transferOps, then do the conversion to dst
752 */
753 if (!transferOpsDone &&
754 _mesa_texstore_needs_transfer_ops(ctx, baseInternalFormat, dstFormat)) {
755 /* Allocate RGBA float image */
756 int elementCount = srcWidth * srcHeight * srcDepth;
757 tempRGBA = malloc(4 * elementCount * sizeof(float));
758 if (!tempRGBA) {
759 free(tempImage);
760 free(tempRGBA);
761 return GL_FALSE;
762 }
763
764 /* Convert from src to RGBA float */
765 src = (GLubyte *) srcAddr;
766 dst = (GLubyte *) tempRGBA;
767 for (img = 0; img < srcDepth; img++) {
768 _mesa_format_convert(dst, RGBA32_FLOAT, 4 * srcWidth * sizeof(float),
769 src, srcMesaFormat, srcRowStride,
770 srcWidth, srcHeight, NULL);
771 src += srcHeight * srcRowStride;
772 dst += srcHeight * 4 * srcWidth * sizeof(float);
773 }
774
775 /* Apply transferOps */
776 _mesa_apply_rgba_transfer_ops(ctx, ctx->_ImageTransferState, elementCount,
777 (float(*)[4]) tempRGBA);
778
779 /* Now we have to adjust our src info for a conversion from
780 * the RGBA float image and then we continue as usual.
781 */
782 srcAddr = tempRGBA;
783 srcFormat = GL_RGBA;
784 srcType = GL_FLOAT;
785 srcRowStride = srcWidth * 4 * sizeof(float);
786 srcMesaFormat = RGBA32_FLOAT;
787 }
788
789 src = (GLubyte *)
790 _mesa_image_address(dims, srcPacking, srcAddr, srcWidth, srcHeight,
791 srcFormat, srcType, 0, 0, 0);
792
793 if (_mesa_get_format_base_format(dstFormat) != baseInternalFormat) {
794 needRebase =
795 _mesa_compute_rgba2base2rgba_component_mapping(baseInternalFormat,
796 rebaseSwizzle);
797 } else {
798 needRebase = false;
799 }
800
801 for (img = 0; img < srcDepth; img++) {
802 _mesa_format_convert(dstSlices[img], dstFormat, dstRowStride,
803 src, srcMesaFormat, srcRowStride,
804 srcWidth, srcHeight,
805 needRebase ? rebaseSwizzle : NULL);
806 src += srcHeight * srcRowStride;
807 }
808
809 free(tempImage);
810 free(tempRGBA);
811
812 return GL_TRUE;
813 }
814
815 GLboolean
816 _mesa_texstore_needs_transfer_ops(struct gl_context *ctx,
817 GLenum baseInternalFormat,
818 mesa_format dstFormat)
819 {
820 GLenum dstType;
821
822 /* There are different rules depending on the base format. */
823 switch (baseInternalFormat) {
824 case GL_DEPTH_COMPONENT:
825 case GL_DEPTH_STENCIL:
826 return ctx->Pixel.DepthScale != 1.0f ||
827 ctx->Pixel.DepthBias != 0.0f;
828
829 case GL_STENCIL_INDEX:
830 return GL_FALSE;
831
832 default:
833 /* Color formats.
834 * Pixel transfer ops (scale, bias, table lookup) do not apply
835 * to integer formats.
836 */
837 dstType = _mesa_get_format_datatype(dstFormat);
838
839 return dstType != GL_INT && dstType != GL_UNSIGNED_INT &&
840 ctx->_ImageTransferState;
841 }
842 }
843
844
845 GLboolean
846 _mesa_texstore_can_use_memcpy(struct gl_context *ctx,
847 GLenum baseInternalFormat, mesa_format dstFormat,
848 GLenum srcFormat, GLenum srcType,
849 const struct gl_pixelstore_attrib *srcPacking)
850 {
851 if (_mesa_texstore_needs_transfer_ops(ctx, baseInternalFormat, dstFormat)) {
852 return GL_FALSE;
853 }
854
855 /* The base internal format and the base Mesa format must match. */
856 if (baseInternalFormat != _mesa_get_format_base_format(dstFormat)) {
857 return GL_FALSE;
858 }
859
860 /* The Mesa format must match the input format and type. */
861 if (!_mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType,
862 srcPacking->SwapBytes)) {
863 return GL_FALSE;
864 }
865
866 /* Depth texture data needs clamping in following cases:
867 * - Floating point dstFormat with signed srcType: clamp to [0.0, 1.0].
868 * - Fixed point dstFormat with signed srcType: clamp to [0, 2^n -1].
869 *
870 * All the cases except one (float dstFormat with float srcType) are ruled
871 * out by _mesa_format_matches_format_and_type() check above. Handle the
872 * remaining case here.
873 */
874 if ((baseInternalFormat == GL_DEPTH_COMPONENT ||
875 baseInternalFormat == GL_DEPTH_STENCIL) &&
876 (srcType == GL_FLOAT ||
877 srcType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV)) {
878 return GL_FALSE;
879 }
880
881 return GL_TRUE;
882 }
883
884 static GLboolean
885 _mesa_texstore_memcpy(TEXSTORE_PARAMS)
886 {
887 if (!_mesa_texstore_can_use_memcpy(ctx, baseInternalFormat, dstFormat,
888 srcFormat, srcType, srcPacking)) {
889 return GL_FALSE;
890 }
891
892 memcpy_texture(ctx, dims,
893 dstFormat,
894 dstRowStride, dstSlices,
895 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
896 srcAddr, srcPacking);
897 return GL_TRUE;
898 }
899 /**
900 * Store user data into texture memory.
901 * Called via glTex[Sub]Image1/2/3D()
902 * \return GL_TRUE for success, GL_FALSE for failure (out of memory).
903 */
904 GLboolean
905 _mesa_texstore(TEXSTORE_PARAMS)
906 {
907 if (_mesa_texstore_memcpy(ctx, dims, baseInternalFormat,
908 dstFormat,
909 dstRowStride, dstSlices,
910 srcWidth, srcHeight, srcDepth,
911 srcFormat, srcType, srcAddr, srcPacking)) {
912 return GL_TRUE;
913 }
914
915 if (_mesa_is_depth_or_stencil_format(baseInternalFormat)) {
916 return texstore_depth_stencil(ctx, dims, baseInternalFormat,
917 dstFormat, dstRowStride, dstSlices,
918 srcWidth, srcHeight, srcDepth,
919 srcFormat, srcType, srcAddr, srcPacking);
920 } else if (_mesa_is_format_compressed(dstFormat)) {
921 return texstore_compressed(ctx, dims, baseInternalFormat,
922 dstFormat, dstRowStride, dstSlices,
923 srcWidth, srcHeight, srcDepth,
924 srcFormat, srcType, srcAddr, srcPacking);
925 } else {
926 return texstore_rgba(ctx, dims, baseInternalFormat,
927 dstFormat, dstRowStride, dstSlices,
928 srcWidth, srcHeight, srcDepth,
929 srcFormat, srcType, srcAddr, srcPacking);
930 }
931 }
932
933
934 /**
935 * Normally, we'll only _write_ texel data to a texture when we map it.
936 * But if the user is providing depth or stencil values and the texture
937 * image is a combined depth/stencil format, we'll actually read from
938 * the texture buffer too (in order to insert the depth or stencil values.
939 * \param userFormat the user-provided image format
940 * \param texFormat the destination texture format
941 */
942 static GLbitfield
943 get_read_write_mode(GLenum userFormat, mesa_format texFormat)
944 {
945 if ((userFormat == GL_STENCIL_INDEX || userFormat == GL_DEPTH_COMPONENT)
946 && _mesa_get_format_base_format(texFormat) == GL_DEPTH_STENCIL)
947 return GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
948 else
949 return GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT;
950 }
951
952
953 /**
954 * Helper function for storing 1D, 2D, 3D whole and subimages into texture
955 * memory.
956 * The source of the image data may be user memory or a PBO. In the later
957 * case, we'll map the PBO, copy from it, then unmap it.
958 */
959 static void
960 store_texsubimage(struct gl_context *ctx,
961 struct gl_texture_image *texImage,
962 GLint xoffset, GLint yoffset, GLint zoffset,
963 GLint width, GLint height, GLint depth,
964 GLenum format, GLenum type, const GLvoid *pixels,
965 const struct gl_pixelstore_attrib *packing,
966 const char *caller)
967
968 {
969 const GLbitfield mapMode = get_read_write_mode(format, texImage->TexFormat);
970 const GLenum target = texImage->TexObject->Target;
971 GLboolean success = GL_FALSE;
972 GLuint dims, slice, numSlices = 1, sliceOffset = 0;
973 GLint srcImageStride = 0;
974 const GLubyte *src;
975
976 assert(xoffset + width <= texImage->Width);
977 assert(yoffset + height <= texImage->Height);
978 assert(zoffset + depth <= texImage->Depth);
979
980 switch (target) {
981 case GL_TEXTURE_1D:
982 dims = 1;
983 break;
984 case GL_TEXTURE_2D_ARRAY:
985 case GL_TEXTURE_CUBE_MAP_ARRAY:
986 case GL_TEXTURE_3D:
987 dims = 3;
988 break;
989 default:
990 dims = 2;
991 }
992
993 /* get pointer to src pixels (may be in a pbo which we'll map here) */
994 src = (const GLubyte *)
995 _mesa_validate_pbo_teximage(ctx, dims, width, height, depth,
996 format, type, pixels, packing, caller);
997 if (!src)
998 return;
999
1000 /* compute slice info (and do some sanity checks) */
1001 switch (target) {
1002 case GL_TEXTURE_2D:
1003 case GL_TEXTURE_RECTANGLE:
1004 case GL_TEXTURE_CUBE_MAP:
1005 case GL_TEXTURE_EXTERNAL_OES:
1006 /* one image slice, nothing special needs to be done */
1007 break;
1008 case GL_TEXTURE_1D:
1009 assert(height == 1);
1010 assert(depth == 1);
1011 assert(yoffset == 0);
1012 assert(zoffset == 0);
1013 break;
1014 case GL_TEXTURE_1D_ARRAY:
1015 assert(depth == 1);
1016 assert(zoffset == 0);
1017 numSlices = height;
1018 sliceOffset = yoffset;
1019 height = 1;
1020 yoffset = 0;
1021 srcImageStride = _mesa_image_row_stride(packing, width, format, type);
1022 break;
1023 case GL_TEXTURE_2D_ARRAY:
1024 numSlices = depth;
1025 sliceOffset = zoffset;
1026 depth = 1;
1027 zoffset = 0;
1028 srcImageStride = _mesa_image_image_stride(packing, width, height,
1029 format, type);
1030 break;
1031 case GL_TEXTURE_3D:
1032 /* we'll store 3D images as a series of slices */
1033 numSlices = depth;
1034 sliceOffset = zoffset;
1035 srcImageStride = _mesa_image_image_stride(packing, width, height,
1036 format, type);
1037 break;
1038 case GL_TEXTURE_CUBE_MAP_ARRAY:
1039 numSlices = depth;
1040 sliceOffset = zoffset;
1041 srcImageStride = _mesa_image_image_stride(packing, width, height,
1042 format, type);
1043 break;
1044 default:
1045 _mesa_warning(ctx, "Unexpected target 0x%x in store_texsubimage()", target);
1046 return;
1047 }
1048
1049 assert(numSlices == 1 || srcImageStride != 0);
1050
1051 for (slice = 0; slice < numSlices; slice++) {
1052 GLubyte *dstMap;
1053 GLint dstRowStride;
1054
1055 ctx->Driver.MapTextureImage(ctx, texImage,
1056 slice + sliceOffset,
1057 xoffset, yoffset, width, height,
1058 mapMode, &dstMap, &dstRowStride);
1059 if (dstMap) {
1060 /* Note: we're only storing a 2D (or 1D) slice at a time but we need
1061 * to pass the right 'dims' value so that GL_UNPACK_SKIP_IMAGES is
1062 * used for 3D images.
1063 */
1064 success = _mesa_texstore(ctx, dims, texImage->_BaseFormat,
1065 texImage->TexFormat,
1066 dstRowStride,
1067 &dstMap,
1068 width, height, 1, /* w, h, d */
1069 format, type, src, packing);
1070
1071 ctx->Driver.UnmapTextureImage(ctx, texImage, slice + sliceOffset);
1072 }
1073
1074 src += srcImageStride;
1075
1076 if (!success)
1077 break;
1078 }
1079
1080 if (!success)
1081 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller);
1082
1083 _mesa_unmap_teximage_pbo(ctx, packing);
1084 }
1085
1086
1087
1088 /**
1089 * Fallback code for ctx->Driver.TexImage().
1090 * Basically, allocate storage for the texture image, then copy the
1091 * user's image into it.
1092 */
1093 void
1094 _mesa_store_teximage(struct gl_context *ctx,
1095 GLuint dims,
1096 struct gl_texture_image *texImage,
1097 GLenum format, GLenum type, const GLvoid *pixels,
1098 const struct gl_pixelstore_attrib *packing)
1099 {
1100 assert(dims == 1 || dims == 2 || dims == 3);
1101
1102 if (texImage->Width == 0 || texImage->Height == 0 || texImage->Depth == 0)
1103 return;
1104
1105 /* allocate storage for texture data */
1106 if (!ctx->Driver.AllocTextureImageBuffer(ctx, texImage)) {
1107 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage%uD", dims);
1108 return;
1109 }
1110
1111 store_texsubimage(ctx, texImage,
1112 0, 0, 0, texImage->Width, texImage->Height, texImage->Depth,
1113 format, type, pixels, packing, "glTexImage");
1114 }
1115
1116
1117 /*
1118 * Fallback for Driver.TexSubImage().
1119 */
1120 void
1121 _mesa_store_texsubimage(struct gl_context *ctx, GLuint dims,
1122 struct gl_texture_image *texImage,
1123 GLint xoffset, GLint yoffset, GLint zoffset,
1124 GLint width, GLint height, GLint depth,
1125 GLenum format, GLenum type, const void *pixels,
1126 const struct gl_pixelstore_attrib *packing)
1127 {
1128 store_texsubimage(ctx, texImage,
1129 xoffset, yoffset, zoffset, width, height, depth,
1130 format, type, pixels, packing, "glTexSubImage");
1131 }
1132
1133 static void
1134 clear_image_to_zero(GLubyte *dstMap, GLint dstRowStride,
1135 GLsizei width, GLsizei height,
1136 GLsizei clearValueSize)
1137 {
1138 GLsizei y;
1139
1140 for (y = 0; y < height; y++) {
1141 memset(dstMap, 0, clearValueSize * width);
1142 dstMap += dstRowStride;
1143 }
1144 }
1145
1146 static void
1147 clear_image_to_value(GLubyte *dstMap, GLint dstRowStride,
1148 GLsizei width, GLsizei height,
1149 const GLvoid *clearValue,
1150 GLsizei clearValueSize)
1151 {
1152 GLsizei y, x;
1153
1154 for (y = 0; y < height; y++) {
1155 for (x = 0; x < width; x++) {
1156 memcpy(dstMap, clearValue, clearValueSize);
1157 dstMap += clearValueSize;
1158 }
1159 dstMap += dstRowStride - clearValueSize * width;
1160 }
1161 }
1162
1163 /*
1164 * Fallback for Driver.ClearTexSubImage().
1165 */
1166 void
1167 _mesa_store_cleartexsubimage(struct gl_context *ctx,
1168 struct gl_texture_image *texImage,
1169 GLint xoffset, GLint yoffset, GLint zoffset,
1170 GLsizei width, GLsizei height, GLsizei depth,
1171 const GLvoid *clearValue)
1172 {
1173 GLubyte *dstMap;
1174 GLint dstRowStride;
1175 GLsizeiptr clearValueSize;
1176 GLsizei z;
1177
1178 clearValueSize = _mesa_get_format_bytes(texImage->TexFormat);
1179
1180 for (z = 0; z < depth; z++) {
1181 ctx->Driver.MapTextureImage(ctx, texImage,
1182 z + zoffset, xoffset, yoffset,
1183 width, height,
1184 GL_MAP_WRITE_BIT,
1185 &dstMap, &dstRowStride);
1186 if (dstMap == NULL) {
1187 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClearTex*Image");
1188 return;
1189 }
1190
1191 if (clearValue) {
1192 clear_image_to_value(dstMap, dstRowStride,
1193 width, height,
1194 clearValue,
1195 clearValueSize);
1196 } else {
1197 clear_image_to_zero(dstMap, dstRowStride,
1198 width, height,
1199 clearValueSize);
1200 }
1201
1202 ctx->Driver.UnmapTextureImage(ctx, texImage, z + zoffset);
1203 }
1204 }
1205
1206 /**
1207 * Fallback for Driver.CompressedTexImage()
1208 */
1209 void
1210 _mesa_store_compressed_teximage(struct gl_context *ctx, GLuint dims,
1211 struct gl_texture_image *texImage,
1212 GLsizei imageSize, const GLvoid *data)
1213 {
1214 /* only 2D and 3D compressed images are supported at this time */
1215 if (dims == 1) {
1216 _mesa_problem(ctx, "Unexpected glCompressedTexImage1D call");
1217 return;
1218 }
1219
1220 /* This is pretty simple, because unlike the general texstore path we don't
1221 * have to worry about the usual image unpacking or image transfer
1222 * operations.
1223 */
1224 ASSERT(texImage);
1225 ASSERT(texImage->Width > 0);
1226 ASSERT(texImage->Height > 0);
1227 ASSERT(texImage->Depth > 0);
1228
1229 /* allocate storage for texture data */
1230 if (!ctx->Driver.AllocTextureImageBuffer(ctx, texImage)) {
1231 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage%uD", dims);
1232 return;
1233 }
1234
1235 _mesa_store_compressed_texsubimage(ctx, dims, texImage,
1236 0, 0, 0,
1237 texImage->Width, texImage->Height, texImage->Depth,
1238 texImage->TexFormat,
1239 imageSize, data);
1240 }
1241
1242
1243 /**
1244 * Compute compressed_pixelstore parameters for copying compressed
1245 * texture data.
1246 * \param dims number of texture image dimensions: 1, 2 or 3
1247 * \param texFormat the compressed texture format
1248 * \param width, height, depth size of image to copy
1249 * \param packing pixelstore parameters describing user-space image packing
1250 * \param store returns the compressed_pixelstore parameters
1251 */
1252 void
1253 _mesa_compute_compressed_pixelstore(GLuint dims, mesa_format texFormat,
1254 GLsizei width, GLsizei height,
1255 GLsizei depth,
1256 const struct gl_pixelstore_attrib *packing,
1257 struct compressed_pixelstore *store)
1258 {
1259 GLuint bw, bh;
1260
1261 _mesa_get_format_block_size(texFormat, &bw, &bh);
1262
1263 store->SkipBytes = 0;
1264 store->TotalBytesPerRow = store->CopyBytesPerRow =
1265 _mesa_format_row_stride(texFormat, width);
1266 store->TotalRowsPerSlice = store->CopyRowsPerSlice =
1267 (height + bh - 1) / bh;
1268 store->CopySlices = depth;
1269
1270 if (packing->CompressedBlockWidth &&
1271 packing->CompressedBlockSize) {
1272
1273 bw = packing->CompressedBlockWidth;
1274
1275 if (packing->RowLength) {
1276 store->TotalBytesPerRow = packing->CompressedBlockSize *
1277 ((packing->RowLength + bw - 1) / bw);
1278 }
1279
1280 store->SkipBytes += packing->SkipPixels * packing->CompressedBlockSize / bw;
1281 }
1282
1283 if (dims > 1 && packing->CompressedBlockHeight &&
1284 packing->CompressedBlockSize) {
1285
1286 bh = packing->CompressedBlockHeight;
1287
1288 store->SkipBytes += packing->SkipRows * store->TotalBytesPerRow / bh;
1289 store->CopyRowsPerSlice = (height + bh - 1) / bh; /* rows in blocks */
1290
1291 if (packing->ImageHeight) {
1292 store->TotalRowsPerSlice = (packing->ImageHeight + bh - 1) / bh;
1293 }
1294 }
1295
1296 if (dims > 2 && packing->CompressedBlockDepth &&
1297 packing->CompressedBlockSize) {
1298
1299 int bd = packing->CompressedBlockDepth;
1300
1301 store->SkipBytes += packing->SkipImages * store->TotalBytesPerRow *
1302 store->TotalRowsPerSlice / bd;
1303 }
1304 }
1305
1306
1307 /**
1308 * Fallback for Driver.CompressedTexSubImage()
1309 */
1310 void
1311 _mesa_store_compressed_texsubimage(struct gl_context *ctx, GLuint dims,
1312 struct gl_texture_image *texImage,
1313 GLint xoffset, GLint yoffset, GLint zoffset,
1314 GLsizei width, GLsizei height, GLsizei depth,
1315 GLenum format,
1316 GLsizei imageSize, const GLvoid *data)
1317 {
1318 struct compressed_pixelstore store;
1319 GLint dstRowStride;
1320 GLint i, slice;
1321 GLubyte *dstMap;
1322 const GLubyte *src;
1323
1324 if (dims == 1) {
1325 _mesa_problem(ctx, "Unexpected 1D compressed texsubimage call");
1326 return;
1327 }
1328
1329 _mesa_compute_compressed_pixelstore(dims, texImage->TexFormat,
1330 width, height, depth,
1331 &ctx->Unpack, &store);
1332
1333 /* get pointer to src pixels (may be in a pbo which we'll map here) */
1334 data = _mesa_validate_pbo_compressed_teximage(ctx, dims, imageSize, data,
1335 &ctx->Unpack,
1336 "glCompressedTexSubImage");
1337 if (!data)
1338 return;
1339
1340 src = (const GLubyte *) data + store.SkipBytes;
1341
1342 for (slice = 0; slice < store.CopySlices; slice++) {
1343 /* Map dest texture buffer */
1344 ctx->Driver.MapTextureImage(ctx, texImage, slice + zoffset,
1345 xoffset, yoffset, width, height,
1346 GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT,
1347 &dstMap, &dstRowStride);
1348
1349 if (dstMap) {
1350
1351 /* copy rows of blocks */
1352 for (i = 0; i < store.CopyRowsPerSlice; i++) {
1353 memcpy(dstMap, src, store.CopyBytesPerRow);
1354 dstMap += dstRowStride;
1355 src += store.TotalBytesPerRow;
1356 }
1357
1358 ctx->Driver.UnmapTextureImage(ctx, texImage, slice + zoffset);
1359
1360 /* advance to next slice */
1361 src += store.TotalBytesPerRow * (store.TotalRowsPerSlice - store.CopyRowsPerSlice);
1362 }
1363 else {
1364 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage%uD",
1365 dims);
1366 }
1367 }
1368
1369 _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack);
1370 }