mesa: whitespace clean-up in texstore.c
[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 "errors.h"
55 #include "glheader.h"
56 #include "bufferobj.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 "util/format_rgb9e5.h"
78 #include "util/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
92
93 /**
94 * Teximage storage routine for when a simple memcpy will do.
95 * No pixel transfer operations or special texel encodings allowed.
96 * 1D, 2D and 3D images supported.
97 */
98 void
99 _mesa_memcpy_texture(struct gl_context *ctx,
100 GLuint dimensions,
101 mesa_format dstFormat,
102 GLint dstRowStride,
103 GLubyte **dstSlices,
104 GLint srcWidth, GLint srcHeight, GLint srcDepth,
105 GLenum srcFormat, GLenum srcType,
106 const GLvoid *srcAddr,
107 const struct gl_pixelstore_attrib *srcPacking)
108 {
109 const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth,
110 srcFormat, srcType);
111 const GLint srcImageStride = _mesa_image_image_stride(srcPacking,
112 srcWidth, srcHeight, srcFormat, srcType);
113 const GLubyte *srcImage = (const GLubyte *) _mesa_image_address(dimensions,
114 srcPacking, srcAddr, srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
115 const GLuint texelBytes = _mesa_get_format_bytes(dstFormat);
116 const GLint bytesPerRow = srcWidth * texelBytes;
117
118 if (dstRowStride == srcRowStride &&
119 dstRowStride == bytesPerRow) {
120 /* memcpy image by image */
121 GLint img;
122 for (img = 0; img < srcDepth; img++) {
123 GLubyte *dstImage = dstSlices[img];
124 memcpy(dstImage, srcImage, bytesPerRow * srcHeight);
125 srcImage += srcImageStride;
126 }
127 }
128 else {
129 /* memcpy row by row */
130 GLint img, row;
131 for (img = 0; img < srcDepth; img++) {
132 const GLubyte *srcRow = srcImage;
133 GLubyte *dstRow = dstSlices[img];
134 for (row = 0; row < srcHeight; row++) {
135 memcpy(dstRow, srcRow, bytesPerRow);
136 dstRow += dstRowStride;
137 srcRow += srcRowStride;
138 }
139 srcImage += srcImageStride;
140 }
141 }
142 }
143
144
145 /**
146 * Store a 32-bit integer or float depth component texture image.
147 */
148 static GLboolean
149 _mesa_texstore_z32(TEXSTORE_PARAMS)
150 {
151 const GLuint depthScale = 0xffffffff;
152 GLenum dstType;
153 (void) dims;
154 assert(dstFormat == MESA_FORMAT_Z_UNORM32 ||
155 dstFormat == MESA_FORMAT_Z_FLOAT32);
156 assert(_mesa_get_format_bytes(dstFormat) == sizeof(GLuint));
157
158 if (dstFormat == MESA_FORMAT_Z_UNORM32)
159 dstType = GL_UNSIGNED_INT;
160 else
161 dstType = GL_FLOAT;
162
163 {
164 /* general path */
165 GLint img, row;
166 for (img = 0; img < srcDepth; img++) {
167 GLubyte *dstRow = dstSlices[img];
168 for (row = 0; row < srcHeight; row++) {
169 const GLvoid *src = _mesa_image_address(dims, srcPacking,
170 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
171 _mesa_unpack_depth_span(ctx, srcWidth,
172 dstType, dstRow,
173 depthScale, srcType, src, srcPacking);
174 dstRow += dstRowStride;
175 }
176 }
177 }
178 return GL_TRUE;
179 }
180
181
182 /**
183 * Store a 24-bit integer depth component texture image.
184 */
185 static GLboolean
186 _mesa_texstore_x8_z24(TEXSTORE_PARAMS)
187 {
188 const GLuint depthScale = 0xffffff;
189
190 (void) dims;
191 assert(dstFormat == MESA_FORMAT_Z24_UNORM_X8_UINT);
192
193 {
194 /* general path */
195 GLint img, row;
196 for (img = 0; img < srcDepth; img++) {
197 GLubyte *dstRow = dstSlices[img];
198 for (row = 0; row < srcHeight; row++) {
199 const GLvoid *src = _mesa_image_address(dims, srcPacking,
200 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
201 _mesa_unpack_depth_span(ctx, srcWidth,
202 GL_UNSIGNED_INT, (GLuint *) dstRow,
203 depthScale, srcType, src, srcPacking);
204 dstRow += dstRowStride;
205 }
206 }
207 }
208 return GL_TRUE;
209 }
210
211
212 /**
213 * Store a 24-bit integer depth component texture image.
214 */
215 static GLboolean
216 _mesa_texstore_z24_x8(TEXSTORE_PARAMS)
217 {
218 const GLuint depthScale = 0xffffff;
219
220 (void) dims;
221 assert(dstFormat == MESA_FORMAT_X8_UINT_Z24_UNORM);
222
223 {
224 /* general path */
225 GLint img, row;
226 for (img = 0; img < srcDepth; img++) {
227 GLubyte *dstRow = dstSlices[img];
228 for (row = 0; row < srcHeight; row++) {
229 const GLvoid *src = _mesa_image_address(dims, srcPacking,
230 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
231 GLuint *dst = (GLuint *) dstRow;
232 GLint i;
233 _mesa_unpack_depth_span(ctx, srcWidth,
234 GL_UNSIGNED_INT, dst,
235 depthScale, srcType, src, srcPacking);
236 for (i = 0; i < srcWidth; i++)
237 dst[i] <<= 8;
238 dstRow += dstRowStride;
239 }
240 }
241 }
242 return GL_TRUE;
243 }
244
245
246 /**
247 * Store a 16-bit integer depth component texture image.
248 */
249 static GLboolean
250 _mesa_texstore_z16(TEXSTORE_PARAMS)
251 {
252 const GLuint depthScale = 0xffff;
253 (void) dims;
254 assert(dstFormat == MESA_FORMAT_Z_UNORM16);
255 assert(_mesa_get_format_bytes(dstFormat) == sizeof(GLushort));
256
257 {
258 /* general path */
259 GLint img, row;
260 for (img = 0; img < srcDepth; img++) {
261 GLubyte *dstRow = dstSlices[img];
262 for (row = 0; row < srcHeight; row++) {
263 const GLvoid *src = _mesa_image_address(dims, srcPacking,
264 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
265 GLushort *dst16 = (GLushort *) dstRow;
266 _mesa_unpack_depth_span(ctx, srcWidth,
267 GL_UNSIGNED_SHORT, dst16, depthScale,
268 srcType, src, srcPacking);
269 dstRow += dstRowStride;
270 }
271 }
272 }
273 return GL_TRUE;
274 }
275
276
277 /**
278 * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_REV.
279 */
280 static GLboolean
281 _mesa_texstore_ycbcr(TEXSTORE_PARAMS)
282 {
283 const GLboolean littleEndian = _mesa_little_endian();
284
285 (void) ctx; (void) dims; (void) baseInternalFormat;
286
287 assert((dstFormat == MESA_FORMAT_YCBCR) ||
288 (dstFormat == MESA_FORMAT_YCBCR_REV));
289 assert(_mesa_get_format_bytes(dstFormat) == 2);
290 assert(ctx->Extensions.MESA_ycbcr_texture);
291 assert(srcFormat == GL_YCBCR_MESA);
292 assert((srcType == GL_UNSIGNED_SHORT_8_8_MESA) ||
293 (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA));
294 assert(baseInternalFormat == GL_YCBCR_MESA);
295
296 /* always just memcpy since no pixel transfer ops apply */
297 _mesa_memcpy_texture(ctx, dims,
298 dstFormat,
299 dstRowStride, dstSlices,
300 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
301 srcAddr, srcPacking);
302
303 /* Check if we need byte swapping */
304 /* XXX the logic here _might_ be wrong */
305 if (srcPacking->SwapBytes ^
306 (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA) ^
307 (dstFormat == MESA_FORMAT_YCBCR_REV) ^
308 !littleEndian) {
309 GLint img, row;
310 for (img = 0; img < srcDepth; img++) {
311 GLubyte *dstRow = dstSlices[img];
312 for (row = 0; row < srcHeight; row++) {
313 _mesa_swap2((GLushort *) dstRow, srcWidth);
314 dstRow += dstRowStride;
315 }
316 }
317 }
318 return GL_TRUE;
319 }
320
321
322 /**
323 * Store a combined depth/stencil texture image.
324 */
325 static GLboolean
326 _mesa_texstore_z24_s8(TEXSTORE_PARAMS)
327 {
328 const GLuint depthScale = 0xffffff;
329 const GLint srcRowStride
330 = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType);
331 GLint img, row;
332 GLuint *depth = malloc(srcWidth * sizeof(GLuint));
333 GLubyte *stencil = malloc(srcWidth * sizeof(GLubyte));
334
335 assert(dstFormat == MESA_FORMAT_S8_UINT_Z24_UNORM);
336 assert(srcFormat == GL_DEPTH_STENCIL_EXT ||
337 srcFormat == GL_DEPTH_COMPONENT ||
338 srcFormat == GL_STENCIL_INDEX);
339 assert(srcFormat != GL_DEPTH_STENCIL_EXT ||
340 srcType == GL_UNSIGNED_INT_24_8_EXT ||
341 srcType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
342
343 if (!depth || !stencil) {
344 free(depth);
345 free(stencil);
346 return GL_FALSE;
347 }
348
349 /* In case we only upload depth we need to preserve the stencil */
350 for (img = 0; img < srcDepth; img++) {
351 GLuint *dstRow = (GLuint *) dstSlices[img];
352 const GLubyte *src
353 = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr,
354 srcWidth, srcHeight,
355 srcFormat, srcType,
356 img, 0, 0);
357 for (row = 0; row < srcHeight; row++) {
358 GLint i;
359 GLboolean keepdepth = GL_FALSE, keepstencil = GL_FALSE;
360
361 if (srcFormat == GL_DEPTH_COMPONENT) { /* preserve stencil */
362 keepstencil = GL_TRUE;
363 }
364 else if (srcFormat == GL_STENCIL_INDEX) { /* preserve depth */
365 keepdepth = GL_TRUE;
366 }
367
368 if (keepdepth == GL_FALSE)
369 /* the 24 depth bits will be in the low position: */
370 _mesa_unpack_depth_span(ctx, srcWidth,
371 GL_UNSIGNED_INT, /* dst type */
372 keepstencil ? depth : dstRow, /* dst addr */
373 depthScale,
374 srcType, src, srcPacking);
375
376 if (keepstencil == GL_FALSE)
377 /* get the 8-bit stencil values */
378 _mesa_unpack_stencil_span(ctx, srcWidth,
379 GL_UNSIGNED_BYTE, /* dst type */
380 stencil, /* dst addr */
381 srcType, src, srcPacking,
382 ctx->_ImageTransferState);
383
384 for (i = 0; i < srcWidth; i++) {
385 if (keepstencil)
386 dstRow[i] = depth[i] << 8 | (dstRow[i] & 0x000000FF);
387 else
388 dstRow[i] = (dstRow[i] & 0xFFFFFF00) | (stencil[i] & 0xFF);
389 }
390 src += srcRowStride;
391 dstRow += dstRowStride / sizeof(GLuint);
392 }
393 }
394
395 free(depth);
396 free(stencil);
397 return GL_TRUE;
398 }
399
400
401 /**
402 * Store a combined depth/stencil texture image.
403 */
404 static GLboolean
405 _mesa_texstore_s8_z24(TEXSTORE_PARAMS)
406 {
407 const GLuint depthScale = 0xffffff;
408 const GLint srcRowStride
409 = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType);
410 GLint img, row;
411 GLuint *depth;
412 GLubyte *stencil;
413
414 assert(dstFormat == MESA_FORMAT_Z24_UNORM_S8_UINT);
415 assert(srcFormat == GL_DEPTH_STENCIL_EXT ||
416 srcFormat == GL_DEPTH_COMPONENT ||
417 srcFormat == GL_STENCIL_INDEX);
418 assert(srcFormat != GL_DEPTH_STENCIL_EXT ||
419 srcType == GL_UNSIGNED_INT_24_8_EXT ||
420 srcType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
421
422 depth = malloc(srcWidth * sizeof(GLuint));
423 stencil = malloc(srcWidth * sizeof(GLubyte));
424
425 if (!depth || !stencil) {
426 free(depth);
427 free(stencil);
428 return GL_FALSE;
429 }
430
431 for (img = 0; img < srcDepth; img++) {
432 GLuint *dstRow = (GLuint *) dstSlices[img];
433 const GLubyte *src
434 = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr,
435 srcWidth, srcHeight,
436 srcFormat, srcType,
437 img, 0, 0);
438 for (row = 0; row < srcHeight; row++) {
439 GLint i;
440 GLboolean keepdepth = GL_FALSE, keepstencil = GL_FALSE;
441
442 if (srcFormat == GL_DEPTH_COMPONENT) { /* preserve stencil */
443 keepstencil = GL_TRUE;
444 }
445 else if (srcFormat == GL_STENCIL_INDEX) { /* preserve depth */
446 keepdepth = GL_TRUE;
447 }
448
449 if (keepdepth == GL_FALSE)
450 /* the 24 depth bits will be in the low position: */
451 _mesa_unpack_depth_span(ctx, srcWidth,
452 GL_UNSIGNED_INT, /* dst type */
453 keepstencil ? depth : dstRow, /* dst addr */
454 depthScale,
455 srcType, src, srcPacking);
456
457 if (keepstencil == GL_FALSE)
458 /* get the 8-bit stencil values */
459 _mesa_unpack_stencil_span(ctx, srcWidth,
460 GL_UNSIGNED_BYTE, /* dst type */
461 stencil, /* dst addr */
462 srcType, src, srcPacking,
463 ctx->_ImageTransferState);
464
465 /* merge stencil values into depth values */
466 for (i = 0; i < srcWidth; i++) {
467 if (keepstencil)
468 dstRow[i] = depth[i] | (dstRow[i] & 0xFF000000);
469 else
470 dstRow[i] = (dstRow[i] & 0xFFFFFF) | (stencil[i] << 24);
471
472 }
473 src += srcRowStride;
474 dstRow += dstRowStride / sizeof(GLuint);
475 }
476 }
477
478 free(depth);
479 free(stencil);
480
481 return GL_TRUE;
482 }
483
484
485 /**
486 * Store simple 8-bit/value stencil texture data.
487 */
488 static GLboolean
489 _mesa_texstore_s8(TEXSTORE_PARAMS)
490 {
491 assert(dstFormat == MESA_FORMAT_S_UINT8);
492 assert(srcFormat == GL_STENCIL_INDEX);
493
494 {
495 const GLint srcRowStride
496 = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType);
497 GLint img, row;
498 GLubyte *stencil = malloc(srcWidth * sizeof(GLubyte));
499
500 if (!stencil)
501 return GL_FALSE;
502
503 for (img = 0; img < srcDepth; img++) {
504 GLubyte *dstRow = dstSlices[img];
505 const GLubyte *src
506 = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr,
507 srcWidth, srcHeight,
508 srcFormat, srcType,
509 img, 0, 0);
510 for (row = 0; row < srcHeight; row++) {
511 GLint i;
512
513 /* get the 8-bit stencil values */
514 _mesa_unpack_stencil_span(ctx, srcWidth,
515 GL_UNSIGNED_BYTE, /* dst type */
516 stencil, /* dst addr */
517 srcType, src, srcPacking,
518 ctx->_ImageTransferState);
519 /* merge stencil values into depth values */
520 for (i = 0; i < srcWidth; i++)
521 dstRow[i] = stencil[i];
522
523 src += srcRowStride;
524 dstRow += dstRowStride / sizeof(GLubyte);
525 }
526 }
527
528 free(stencil);
529 }
530
531 return GL_TRUE;
532 }
533
534
535 static GLboolean
536 _mesa_texstore_z32f_x24s8(TEXSTORE_PARAMS)
537 {
538 GLint img, row;
539 const GLint srcRowStride
540 = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType)
541 / sizeof(uint64_t);
542
543 assert(dstFormat == MESA_FORMAT_Z32_FLOAT_S8X24_UINT);
544 assert(srcFormat == GL_DEPTH_STENCIL ||
545 srcFormat == GL_DEPTH_COMPONENT ||
546 srcFormat == GL_STENCIL_INDEX);
547 assert(srcFormat != GL_DEPTH_STENCIL ||
548 srcType == GL_UNSIGNED_INT_24_8 ||
549 srcType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV);
550
551 /* In case we only upload depth we need to preserve the stencil */
552 for (img = 0; img < srcDepth; img++) {
553 uint64_t *dstRow = (uint64_t *) dstSlices[img];
554 const uint64_t *src
555 = (const uint64_t *) _mesa_image_address(dims, srcPacking, srcAddr,
556 srcWidth, srcHeight,
557 srcFormat, srcType,
558 img, 0, 0);
559 for (row = 0; row < srcHeight; row++) {
560 /* The unpack functions with:
561 * dstType = GL_FLOAT_32_UNSIGNED_INT_24_8_REV
562 * only write their own dword, so the other dword (stencil
563 * or depth) is preserved. */
564 if (srcFormat != GL_STENCIL_INDEX)
565 _mesa_unpack_depth_span(ctx, srcWidth,
566 GL_FLOAT_32_UNSIGNED_INT_24_8_REV, /* dst type */
567 dstRow, /* dst addr */
568 ~0U, srcType, src, srcPacking);
569
570 if (srcFormat != GL_DEPTH_COMPONENT)
571 _mesa_unpack_stencil_span(ctx, srcWidth,
572 GL_FLOAT_32_UNSIGNED_INT_24_8_REV, /* dst type */
573 dstRow, /* dst addr */
574 srcType, src, srcPacking,
575 ctx->_ImageTransferState);
576
577 src += srcRowStride;
578 dstRow += dstRowStride / sizeof(uint64_t);
579 }
580 }
581 return GL_TRUE;
582 }
583
584 static GLboolean
585 texstore_depth_stencil(TEXSTORE_PARAMS)
586 {
587 static StoreTexImageFunc table[MESA_FORMAT_COUNT];
588 static GLboolean initialized = GL_FALSE;
589
590 if (!initialized) {
591 memset(table, 0, sizeof table);
592
593 table[MESA_FORMAT_S8_UINT_Z24_UNORM] = _mesa_texstore_z24_s8;
594 table[MESA_FORMAT_Z24_UNORM_S8_UINT] = _mesa_texstore_s8_z24;
595 table[MESA_FORMAT_Z_UNORM16] = _mesa_texstore_z16;
596 table[MESA_FORMAT_Z24_UNORM_X8_UINT] = _mesa_texstore_x8_z24;
597 table[MESA_FORMAT_X8_UINT_Z24_UNORM] = _mesa_texstore_z24_x8;
598 table[MESA_FORMAT_Z_UNORM32] = _mesa_texstore_z32;
599 table[MESA_FORMAT_S_UINT8] = _mesa_texstore_s8;
600 table[MESA_FORMAT_Z_FLOAT32] = _mesa_texstore_z32;
601 table[MESA_FORMAT_Z32_FLOAT_S8X24_UINT] = _mesa_texstore_z32f_x24s8;
602
603 initialized = GL_TRUE;
604 }
605
606 assert(table[dstFormat]);
607 return table[dstFormat](ctx, dims, baseInternalFormat,
608 dstFormat, dstRowStride, dstSlices,
609 srcWidth, srcHeight, srcDepth,
610 srcFormat, srcType, srcAddr, srcPacking);
611 }
612
613 static GLboolean
614 texstore_compressed(TEXSTORE_PARAMS)
615 {
616 static StoreTexImageFunc table[MESA_FORMAT_COUNT];
617 static GLboolean initialized = GL_FALSE;
618
619 if (!initialized) {
620 memset(table, 0, sizeof table);
621
622 table[MESA_FORMAT_SRGB_DXT1] = _mesa_texstore_rgb_dxt1;
623 table[MESA_FORMAT_SRGBA_DXT1] = _mesa_texstore_rgba_dxt1;
624 table[MESA_FORMAT_SRGBA_DXT3] = _mesa_texstore_rgba_dxt3;
625 table[MESA_FORMAT_SRGBA_DXT5] = _mesa_texstore_rgba_dxt5;
626 table[MESA_FORMAT_RGB_FXT1] = _mesa_texstore_rgb_fxt1;
627 table[MESA_FORMAT_RGBA_FXT1] = _mesa_texstore_rgba_fxt1;
628 table[MESA_FORMAT_RGB_DXT1] = _mesa_texstore_rgb_dxt1;
629 table[MESA_FORMAT_RGBA_DXT1] = _mesa_texstore_rgba_dxt1;
630 table[MESA_FORMAT_RGBA_DXT3] = _mesa_texstore_rgba_dxt3;
631 table[MESA_FORMAT_RGBA_DXT5] = _mesa_texstore_rgba_dxt5;
632 table[MESA_FORMAT_R_RGTC1_UNORM] = _mesa_texstore_red_rgtc1;
633 table[MESA_FORMAT_R_RGTC1_SNORM] = _mesa_texstore_signed_red_rgtc1;
634 table[MESA_FORMAT_RG_RGTC2_UNORM] = _mesa_texstore_rg_rgtc2;
635 table[MESA_FORMAT_RG_RGTC2_SNORM] = _mesa_texstore_signed_rg_rgtc2;
636 table[MESA_FORMAT_L_LATC1_UNORM] = _mesa_texstore_red_rgtc1;
637 table[MESA_FORMAT_L_LATC1_SNORM] = _mesa_texstore_signed_red_rgtc1;
638 table[MESA_FORMAT_LA_LATC2_UNORM] = _mesa_texstore_rg_rgtc2;
639 table[MESA_FORMAT_LA_LATC2_SNORM] = _mesa_texstore_signed_rg_rgtc2;
640 table[MESA_FORMAT_ETC1_RGB8] = _mesa_texstore_etc1_rgb8;
641 table[MESA_FORMAT_ETC2_RGB8] = _mesa_texstore_etc2_rgb8;
642 table[MESA_FORMAT_ETC2_SRGB8] = _mesa_texstore_etc2_srgb8;
643 table[MESA_FORMAT_ETC2_RGBA8_EAC] = _mesa_texstore_etc2_rgba8_eac;
644 table[MESA_FORMAT_ETC2_SRGB8_ALPHA8_EAC] = _mesa_texstore_etc2_srgb8_alpha8_eac;
645 table[MESA_FORMAT_ETC2_R11_EAC] = _mesa_texstore_etc2_r11_eac;
646 table[MESA_FORMAT_ETC2_RG11_EAC] = _mesa_texstore_etc2_rg11_eac;
647 table[MESA_FORMAT_ETC2_SIGNED_R11_EAC] = _mesa_texstore_etc2_signed_r11_eac;
648 table[MESA_FORMAT_ETC2_SIGNED_RG11_EAC] = _mesa_texstore_etc2_signed_rg11_eac;
649 table[MESA_FORMAT_ETC2_RGB8_PUNCHTHROUGH_ALPHA1] =
650 _mesa_texstore_etc2_rgb8_punchthrough_alpha1;
651 table[MESA_FORMAT_ETC2_SRGB8_PUNCHTHROUGH_ALPHA1] =
652 _mesa_texstore_etc2_srgb8_punchthrough_alpha1;
653
654 table[MESA_FORMAT_BPTC_RGBA_UNORM] =
655 _mesa_texstore_bptc_rgba_unorm;
656 table[MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM] =
657 _mesa_texstore_bptc_rgba_unorm;
658 table[MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT] =
659 _mesa_texstore_bptc_rgb_signed_float;
660 table[MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT] =
661 _mesa_texstore_bptc_rgb_unsigned_float;
662
663 initialized = GL_TRUE;
664 }
665
666 assert(table[dstFormat]);
667 return table[dstFormat](ctx, dims, baseInternalFormat,
668 dstFormat, dstRowStride, dstSlices,
669 srcWidth, srcHeight, srcDepth,
670 srcFormat, srcType, srcAddr, srcPacking);
671 }
672
673 static GLboolean
674 texstore_rgba(TEXSTORE_PARAMS)
675 {
676 void *tempImage = NULL;
677 int img;
678 GLubyte *src, *dst;
679 uint8_t rebaseSwizzle[4];
680 bool transferOpsDone = false;
681
682 /* We have to handle MESA_FORMAT_YCBCR manually because it is a special case
683 * and _mesa_format_convert does not support it. In this case the we only
684 * allow conversions between YCBCR formats and it is mostly a memcpy.
685 */
686 if (dstFormat == MESA_FORMAT_YCBCR || dstFormat == MESA_FORMAT_YCBCR_REV) {
687 return _mesa_texstore_ycbcr(ctx, dims, baseInternalFormat,
688 dstFormat, dstRowStride, dstSlices,
689 srcWidth, srcHeight, srcDepth,
690 srcFormat, srcType, srcAddr,
691 srcPacking);
692 }
693
694 /* We have to deal with GL_COLOR_INDEX manually because
695 * _mesa_format_convert does not handle this format. So what we do here is
696 * convert it to RGBA ubyte first and then convert from that to dst as usual.
697 */
698 if (srcFormat == GL_COLOR_INDEX) {
699 /* Notice that this will already handle byte swapping if necessary */
700 tempImage =
701 _mesa_unpack_color_index_to_rgba_ubyte(ctx, dims,
702 srcAddr, srcFormat, srcType,
703 srcWidth, srcHeight, srcDepth,
704 srcPacking,
705 ctx->_ImageTransferState);
706 if (!tempImage)
707 return GL_FALSE;
708
709 /* _mesa_unpack_color_index_to_rgba_ubyte has handled transferops
710 * if needed.
711 */
712 transferOpsDone = true;
713
714 /* Now we only have to adjust our src info for a conversion from
715 * the RGBA ubyte and then we continue as usual.
716 */
717 srcAddr = tempImage;
718 srcFormat = GL_RGBA;
719 srcType = GL_UNSIGNED_BYTE;
720 } else if (srcPacking->SwapBytes) {
721 /* We have to handle byte-swapping scenarios before calling
722 * _mesa_format_convert
723 */
724 GLint swapSize = _mesa_sizeof_packed_type(srcType);
725 if (swapSize == 2 || swapSize == 4) {
726 int imageStride = _mesa_image_image_stride(srcPacking, srcWidth,
727 srcHeight, srcFormat,
728 srcType);
729 int bufferSize = imageStride * srcDepth;
730 int layer;
731 const uint8_t *src;
732 uint8_t *dst;
733
734 tempImage = malloc(bufferSize);
735 if (!tempImage)
736 return GL_FALSE;
737 src = srcAddr;
738 dst = tempImage;
739 for (layer = 0; layer < srcDepth; layer++) {
740 _mesa_swap_bytes_2d_image(srcFormat, srcType,
741 srcPacking,
742 srcWidth, srcHeight,
743 dst, src);
744 src += imageStride;
745 dst += imageStride;
746 }
747 srcAddr = tempImage;
748 }
749 }
750
751 int srcRowStride =
752 _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType);
753
754 uint32_t srcMesaFormat =
755 _mesa_format_from_format_and_type(srcFormat, srcType);
756
757 dstFormat = _mesa_get_srgb_format_linear(dstFormat);
758
759 /* If we have transferOps then we need to convert to RGBA float first,
760 then apply transferOps, then do the conversion to dst
761 */
762 void *tempRGBA = NULL;
763 if (!transferOpsDone &&
764 _mesa_texstore_needs_transfer_ops(ctx, baseInternalFormat, dstFormat)) {
765 /* Allocate RGBA float image */
766 int elementCount = srcWidth * srcHeight * srcDepth;
767 tempRGBA = malloc(4 * elementCount * sizeof(float));
768 if (!tempRGBA) {
769 free(tempImage);
770 return GL_FALSE;
771 }
772
773 /* Convert from src to RGBA float */
774 src = (GLubyte *) srcAddr;
775 dst = (GLubyte *) tempRGBA;
776 for (img = 0; img < srcDepth; img++) {
777 _mesa_format_convert(dst, RGBA32_FLOAT, 4 * srcWidth * sizeof(float),
778 src, srcMesaFormat, srcRowStride,
779 srcWidth, srcHeight, NULL);
780 src += srcHeight * srcRowStride;
781 dst += srcHeight * 4 * srcWidth * sizeof(float);
782 }
783
784 /* Apply transferOps */
785 _mesa_apply_rgba_transfer_ops(ctx, ctx->_ImageTransferState, elementCount,
786 (float(*)[4]) tempRGBA);
787
788 /* Now we have to adjust our src info for a conversion from
789 * the RGBA float image and then we continue as usual.
790 */
791 srcAddr = tempRGBA;
792 srcFormat = GL_RGBA;
793 srcType = GL_FLOAT;
794 srcRowStride = srcWidth * 4 * sizeof(float);
795 srcMesaFormat = RGBA32_FLOAT;
796 srcPacking = &ctx->DefaultPacking;
797 }
798
799 src = (GLubyte *)
800 _mesa_image_address(dims, srcPacking, srcAddr, srcWidth, srcHeight,
801 srcFormat, srcType, 0, 0, 0);
802
803 bool needRebase;
804 if (_mesa_get_format_base_format(dstFormat) != baseInternalFormat) {
805 needRebase =
806 _mesa_compute_rgba2base2rgba_component_mapping(baseInternalFormat,
807 rebaseSwizzle);
808 } else {
809 needRebase = false;
810 }
811
812 for (img = 0; img < srcDepth; img++) {
813 _mesa_format_convert(dstSlices[img], dstFormat, dstRowStride,
814 src, srcMesaFormat, srcRowStride,
815 srcWidth, srcHeight,
816 needRebase ? rebaseSwizzle : NULL);
817 src += srcHeight * srcRowStride;
818 }
819
820 free(tempImage);
821 free(tempRGBA);
822
823 return GL_TRUE;
824 }
825
826 GLboolean
827 _mesa_texstore_needs_transfer_ops(struct gl_context *ctx,
828 GLenum baseInternalFormat,
829 mesa_format dstFormat)
830 {
831 GLenum dstType;
832
833 /* There are different rules depending on the base format. */
834 switch (baseInternalFormat) {
835 case GL_DEPTH_COMPONENT:
836 case GL_DEPTH_STENCIL:
837 return ctx->Pixel.DepthScale != 1.0f ||
838 ctx->Pixel.DepthBias != 0.0f;
839
840 case GL_STENCIL_INDEX:
841 return GL_FALSE;
842
843 default:
844 /* Color formats.
845 * Pixel transfer ops (scale, bias, table lookup) do not apply
846 * to integer formats.
847 */
848 dstType = _mesa_get_format_datatype(dstFormat);
849
850 return dstType != GL_INT && dstType != GL_UNSIGNED_INT &&
851 ctx->_ImageTransferState;
852 }
853 }
854
855
856 GLboolean
857 _mesa_texstore_can_use_memcpy(struct gl_context *ctx,
858 GLenum baseInternalFormat, mesa_format dstFormat,
859 GLenum srcFormat, GLenum srcType,
860 const struct gl_pixelstore_attrib *srcPacking)
861 {
862 if (_mesa_texstore_needs_transfer_ops(ctx, baseInternalFormat, dstFormat)) {
863 return GL_FALSE;
864 }
865
866 /* The base internal format and the base Mesa format must match. */
867 if (baseInternalFormat != _mesa_get_format_base_format(dstFormat)) {
868 return GL_FALSE;
869 }
870
871 /* The Mesa format must match the input format and type. */
872 if (!_mesa_format_matches_format_and_type(dstFormat, srcFormat, srcType,
873 srcPacking->SwapBytes, NULL)) {
874 return GL_FALSE;
875 }
876
877 /* Depth texture data needs clamping in following cases:
878 * - Floating point dstFormat with signed srcType: clamp to [0.0, 1.0].
879 * - Fixed point dstFormat with signed srcType: clamp to [0, 2^n -1].
880 *
881 * All the cases except one (float dstFormat with float srcType) are ruled
882 * out by _mesa_format_matches_format_and_type() check above. Handle the
883 * remaining case here.
884 */
885 if ((baseInternalFormat == GL_DEPTH_COMPONENT ||
886 baseInternalFormat == GL_DEPTH_STENCIL) &&
887 (srcType == GL_FLOAT ||
888 srcType == GL_FLOAT_32_UNSIGNED_INT_24_8_REV)) {
889 return GL_FALSE;
890 }
891
892 return GL_TRUE;
893 }
894
895 static GLboolean
896 _mesa_texstore_memcpy(TEXSTORE_PARAMS)
897 {
898 if (!_mesa_texstore_can_use_memcpy(ctx, baseInternalFormat, dstFormat,
899 srcFormat, srcType, srcPacking)) {
900 return GL_FALSE;
901 }
902
903 _mesa_memcpy_texture(ctx, dims,
904 dstFormat,
905 dstRowStride, dstSlices,
906 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
907 srcAddr, srcPacking);
908 return GL_TRUE;
909 }
910
911
912 /**
913 * Store user data into texture memory.
914 * Called via glTex[Sub]Image1/2/3D()
915 * \return GL_TRUE for success, GL_FALSE for failure (out of memory).
916 */
917 GLboolean
918 _mesa_texstore(TEXSTORE_PARAMS)
919 {
920 if (_mesa_texstore_memcpy(ctx, dims, baseInternalFormat,
921 dstFormat,
922 dstRowStride, dstSlices,
923 srcWidth, srcHeight, srcDepth,
924 srcFormat, srcType, srcAddr, srcPacking)) {
925 return GL_TRUE;
926 }
927
928 if (_mesa_is_depth_or_stencil_format(baseInternalFormat)) {
929 return texstore_depth_stencil(ctx, dims, baseInternalFormat,
930 dstFormat, dstRowStride, dstSlices,
931 srcWidth, srcHeight, srcDepth,
932 srcFormat, srcType, srcAddr, srcPacking);
933 } else if (_mesa_is_format_compressed(dstFormat)) {
934 return texstore_compressed(ctx, dims, baseInternalFormat,
935 dstFormat, dstRowStride, dstSlices,
936 srcWidth, srcHeight, srcDepth,
937 srcFormat, srcType, srcAddr, srcPacking);
938 } else {
939 return texstore_rgba(ctx, dims, baseInternalFormat,
940 dstFormat, dstRowStride, dstSlices,
941 srcWidth, srcHeight, srcDepth,
942 srcFormat, srcType, srcAddr, srcPacking);
943 }
944 }
945
946
947 /**
948 * Normally, we'll only _write_ texel data to a texture when we map it.
949 * But if the user is providing depth or stencil values and the texture
950 * image is a combined depth/stencil format, we'll actually read from
951 * the texture buffer too (in order to insert the depth or stencil values.
952 * \param userFormat the user-provided image format
953 * \param texFormat the destination texture format
954 */
955 static GLbitfield
956 get_read_write_mode(GLenum userFormat, mesa_format texFormat)
957 {
958 if ((userFormat == GL_STENCIL_INDEX || userFormat == GL_DEPTH_COMPONENT)
959 && _mesa_get_format_base_format(texFormat) == GL_DEPTH_STENCIL)
960 return GL_MAP_READ_BIT | GL_MAP_WRITE_BIT;
961 else
962 return GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT;
963 }
964
965
966 /**
967 * Helper function for storing 1D, 2D, 3D whole and subimages into texture
968 * memory.
969 * The source of the image data may be user memory or a PBO. In the later
970 * case, we'll map the PBO, copy from it, then unmap it.
971 */
972 static void
973 store_texsubimage(struct gl_context *ctx,
974 struct gl_texture_image *texImage,
975 GLint xoffset, GLint yoffset, GLint zoffset,
976 GLint width, GLint height, GLint depth,
977 GLenum format, GLenum type, const GLvoid *pixels,
978 const struct gl_pixelstore_attrib *packing,
979 const char *caller)
980
981 {
982 const GLbitfield mapMode = get_read_write_mode(format, texImage->TexFormat);
983 const GLenum target = texImage->TexObject->Target;
984 GLboolean success = GL_FALSE;
985 GLuint dims, slice, numSlices = 1, sliceOffset = 0;
986 GLint srcImageStride = 0;
987 const GLubyte *src;
988
989 assert(xoffset + width <= texImage->Width);
990 assert(yoffset + height <= texImage->Height);
991 assert(zoffset + depth <= texImage->Depth);
992
993 switch (target) {
994 case GL_TEXTURE_1D:
995 dims = 1;
996 break;
997 case GL_TEXTURE_2D_ARRAY:
998 case GL_TEXTURE_CUBE_MAP_ARRAY:
999 case GL_TEXTURE_3D:
1000 dims = 3;
1001 break;
1002 default:
1003 dims = 2;
1004 }
1005
1006 /* get pointer to src pixels (may be in a pbo which we'll map here) */
1007 src = (const GLubyte *)
1008 _mesa_validate_pbo_teximage(ctx, dims, width, height, depth,
1009 format, type, pixels, packing, caller);
1010 if (!src)
1011 return;
1012
1013 /* compute slice info (and do some sanity checks) */
1014 switch (target) {
1015 case GL_TEXTURE_2D:
1016 case GL_TEXTURE_2D_MULTISAMPLE:
1017 case GL_TEXTURE_RECTANGLE:
1018 case GL_TEXTURE_CUBE_MAP:
1019 case GL_TEXTURE_EXTERNAL_OES:
1020 /* one image slice, nothing special needs to be done */
1021 break;
1022 case GL_TEXTURE_1D:
1023 assert(height == 1);
1024 assert(depth == 1);
1025 assert(yoffset == 0);
1026 assert(zoffset == 0);
1027 break;
1028 case GL_TEXTURE_1D_ARRAY:
1029 assert(depth == 1);
1030 assert(zoffset == 0);
1031 numSlices = height;
1032 sliceOffset = yoffset;
1033 height = 1;
1034 yoffset = 0;
1035 srcImageStride = _mesa_image_row_stride(packing, width, format, type);
1036 break;
1037 case GL_TEXTURE_2D_ARRAY:
1038 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1039 numSlices = depth;
1040 sliceOffset = zoffset;
1041 depth = 1;
1042 zoffset = 0;
1043 srcImageStride = _mesa_image_image_stride(packing, width, height,
1044 format, type);
1045 break;
1046 case GL_TEXTURE_3D:
1047 /* we'll store 3D images as a series of slices */
1048 numSlices = depth;
1049 sliceOffset = zoffset;
1050 srcImageStride = _mesa_image_image_stride(packing, width, height,
1051 format, type);
1052 break;
1053 case GL_TEXTURE_CUBE_MAP_ARRAY:
1054 numSlices = depth;
1055 sliceOffset = zoffset;
1056 srcImageStride = _mesa_image_image_stride(packing, width, height,
1057 format, type);
1058 break;
1059 default:
1060 _mesa_warning(ctx, "Unexpected target 0x%x in store_texsubimage()",
1061 target);
1062 return;
1063 }
1064
1065 assert(numSlices == 1 || srcImageStride != 0);
1066
1067 for (slice = 0; slice < numSlices; slice++) {
1068 GLubyte *dstMap;
1069 GLint dstRowStride;
1070
1071 ctx->Driver.MapTextureImage(ctx, texImage,
1072 slice + sliceOffset,
1073 xoffset, yoffset, width, height,
1074 mapMode, &dstMap, &dstRowStride);
1075 if (dstMap) {
1076 /* Note: we're only storing a 2D (or 1D) slice at a time but we need
1077 * to pass the right 'dims' value so that GL_UNPACK_SKIP_IMAGES is
1078 * used for 3D images.
1079 */
1080 success = _mesa_texstore(ctx, dims, texImage->_BaseFormat,
1081 texImage->TexFormat,
1082 dstRowStride,
1083 &dstMap,
1084 width, height, 1, /* w, h, d */
1085 format, type, src, packing);
1086
1087 ctx->Driver.UnmapTextureImage(ctx, texImage, slice + sliceOffset);
1088 }
1089
1090 src += srcImageStride;
1091
1092 if (!success)
1093 break;
1094 }
1095
1096 if (!success)
1097 _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller);
1098
1099 _mesa_unmap_teximage_pbo(ctx, packing);
1100 }
1101
1102
1103
1104 /**
1105 * Fallback code for ctx->Driver.TexImage().
1106 * Basically, allocate storage for the texture image, then copy the
1107 * user's image into it.
1108 */
1109 void
1110 _mesa_store_teximage(struct gl_context *ctx,
1111 GLuint dims,
1112 struct gl_texture_image *texImage,
1113 GLenum format, GLenum type, const GLvoid *pixels,
1114 const struct gl_pixelstore_attrib *packing)
1115 {
1116 assert(dims == 1 || dims == 2 || dims == 3);
1117
1118 if (texImage->Width == 0 || texImage->Height == 0 || texImage->Depth == 0)
1119 return;
1120
1121 /* allocate storage for texture data */
1122 if (!ctx->Driver.AllocTextureImageBuffer(ctx, texImage)) {
1123 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage%uD", dims);
1124 return;
1125 }
1126
1127 store_texsubimage(ctx, texImage,
1128 0, 0, 0, texImage->Width, texImage->Height, texImage->Depth,
1129 format, type, pixels, packing, "glTexImage");
1130 }
1131
1132
1133 /*
1134 * Fallback for Driver.TexSubImage().
1135 */
1136 void
1137 _mesa_store_texsubimage(struct gl_context *ctx, GLuint dims,
1138 struct gl_texture_image *texImage,
1139 GLint xoffset, GLint yoffset, GLint zoffset,
1140 GLint width, GLint height, GLint depth,
1141 GLenum format, GLenum type, const void *pixels,
1142 const struct gl_pixelstore_attrib *packing)
1143 {
1144 store_texsubimage(ctx, texImage,
1145 xoffset, yoffset, zoffset, width, height, depth,
1146 format, type, pixels, packing, "glTexSubImage");
1147 }
1148
1149 static void
1150 clear_image_to_zero(GLubyte *dstMap, GLint dstRowStride,
1151 GLsizei width, GLsizei height,
1152 GLsizei clearValueSize)
1153 {
1154 GLsizei y;
1155
1156 for (y = 0; y < height; y++) {
1157 memset(dstMap, 0, clearValueSize * width);
1158 dstMap += dstRowStride;
1159 }
1160 }
1161
1162 static void
1163 clear_image_to_value(GLubyte *dstMap, GLint dstRowStride,
1164 GLsizei width, GLsizei height,
1165 const GLvoid *clearValue,
1166 GLsizei clearValueSize)
1167 {
1168 GLsizei y, x;
1169
1170 for (y = 0; y < height; y++) {
1171 for (x = 0; x < width; x++) {
1172 memcpy(dstMap, clearValue, clearValueSize);
1173 dstMap += clearValueSize;
1174 }
1175 dstMap += dstRowStride - clearValueSize * width;
1176 }
1177 }
1178
1179 /*
1180 * Fallback for Driver.ClearTexSubImage().
1181 */
1182 void
1183 _mesa_store_cleartexsubimage(struct gl_context *ctx,
1184 struct gl_texture_image *texImage,
1185 GLint xoffset, GLint yoffset, GLint zoffset,
1186 GLsizei width, GLsizei height, GLsizei depth,
1187 const GLvoid *clearValue)
1188 {
1189 GLubyte *dstMap;
1190 GLint dstRowStride;
1191 GLsizeiptr clearValueSize;
1192 GLsizei z;
1193
1194 clearValueSize = _mesa_get_format_bytes(texImage->TexFormat);
1195
1196 for (z = 0; z < depth; z++) {
1197 ctx->Driver.MapTextureImage(ctx, texImage,
1198 z + zoffset, xoffset, yoffset,
1199 width, height,
1200 GL_MAP_WRITE_BIT,
1201 &dstMap, &dstRowStride);
1202 if (dstMap == NULL) {
1203 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClearTex*Image");
1204 return;
1205 }
1206
1207 if (clearValue) {
1208 clear_image_to_value(dstMap, dstRowStride,
1209 width, height,
1210 clearValue,
1211 clearValueSize);
1212 } else {
1213 clear_image_to_zero(dstMap, dstRowStride,
1214 width, height,
1215 clearValueSize);
1216 }
1217
1218 ctx->Driver.UnmapTextureImage(ctx, texImage, z + zoffset);
1219 }
1220 }
1221
1222 /**
1223 * Fallback for Driver.CompressedTexImage()
1224 */
1225 void
1226 _mesa_store_compressed_teximage(struct gl_context *ctx, GLuint dims,
1227 struct gl_texture_image *texImage,
1228 GLsizei imageSize, const GLvoid *data)
1229 {
1230 /* only 2D and 3D compressed images are supported at this time */
1231 if (dims == 1) {
1232 _mesa_problem(ctx, "Unexpected glCompressedTexImage1D call");
1233 return;
1234 }
1235
1236 /* This is pretty simple, because unlike the general texstore path we don't
1237 * have to worry about the usual image unpacking or image transfer
1238 * operations.
1239 */
1240 assert(texImage);
1241 assert(texImage->Width > 0);
1242 assert(texImage->Height > 0);
1243 assert(texImage->Depth > 0);
1244
1245 /* allocate storage for texture data */
1246 if (!ctx->Driver.AllocTextureImageBuffer(ctx, texImage)) {
1247 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage%uD", dims);
1248 return;
1249 }
1250
1251 ctx->Driver.CompressedTexSubImage(ctx, dims, texImage,
1252 0, 0, 0,
1253 texImage->Width, texImage->Height, texImage->Depth,
1254 texImage->TexFormat,
1255 imageSize, data);
1256 }
1257
1258
1259 /**
1260 * Compute compressed_pixelstore parameters for copying compressed
1261 * texture data.
1262 * \param dims number of texture image dimensions: 1, 2 or 3
1263 * \param texFormat the compressed texture format
1264 * \param width, height, depth size of image to copy
1265 * \param packing pixelstore parameters describing user-space image packing
1266 * \param store returns the compressed_pixelstore parameters
1267 */
1268 void
1269 _mesa_compute_compressed_pixelstore(GLuint dims, mesa_format texFormat,
1270 GLsizei width, GLsizei height,
1271 GLsizei depth,
1272 const struct gl_pixelstore_attrib *packing,
1273 struct compressed_pixelstore *store)
1274 {
1275 GLuint bw, bh, bd;
1276
1277 _mesa_get_format_block_size_3d(texFormat, &bw, &bh, &bd);
1278
1279 store->SkipBytes = 0;
1280 store->TotalBytesPerRow = store->CopyBytesPerRow =
1281 _mesa_format_row_stride(texFormat, width);
1282 store->TotalRowsPerSlice = store->CopyRowsPerSlice =
1283 (height + bh - 1) / bh;
1284 store->CopySlices = (depth + bd - 1) / bd;
1285
1286 if (packing->CompressedBlockWidth &&
1287 packing->CompressedBlockSize) {
1288
1289 bw = packing->CompressedBlockWidth;
1290
1291 if (packing->RowLength) {
1292 store->TotalBytesPerRow = packing->CompressedBlockSize *
1293 ((packing->RowLength + bw - 1) / bw);
1294 }
1295
1296 store->SkipBytes +=
1297 packing->SkipPixels * packing->CompressedBlockSize / bw;
1298 }
1299
1300 if (dims > 1 && packing->CompressedBlockHeight &&
1301 packing->CompressedBlockSize) {
1302
1303 bh = packing->CompressedBlockHeight;
1304
1305 store->SkipBytes += packing->SkipRows * store->TotalBytesPerRow / bh;
1306 store->CopyRowsPerSlice = (height + bh - 1) / bh; /* rows in blocks */
1307
1308 if (packing->ImageHeight) {
1309 store->TotalRowsPerSlice = (packing->ImageHeight + bh - 1) / bh;
1310 }
1311 }
1312
1313 if (dims > 2 && packing->CompressedBlockDepth &&
1314 packing->CompressedBlockSize) {
1315
1316 int bd = packing->CompressedBlockDepth;
1317
1318 store->SkipBytes += packing->SkipImages * store->TotalBytesPerRow *
1319 store->TotalRowsPerSlice / bd;
1320 }
1321 }
1322
1323
1324 /**
1325 * Fallback for Driver.CompressedTexSubImage()
1326 */
1327 void
1328 _mesa_store_compressed_texsubimage(struct gl_context *ctx, GLuint dims,
1329 struct gl_texture_image *texImage,
1330 GLint xoffset, GLint yoffset, GLint zoffset,
1331 GLsizei width, GLsizei height, GLsizei depth,
1332 GLenum format,
1333 GLsizei imageSize, const GLvoid *data)
1334 {
1335 struct compressed_pixelstore store;
1336 GLint dstRowStride;
1337 GLint i, slice;
1338 GLubyte *dstMap;
1339 const GLubyte *src;
1340
1341 if (dims == 1) {
1342 _mesa_problem(ctx, "Unexpected 1D compressed texsubimage call");
1343 return;
1344 }
1345
1346 _mesa_compute_compressed_pixelstore(dims, texImage->TexFormat,
1347 width, height, depth,
1348 &ctx->Unpack, &store);
1349
1350 /* get pointer to src pixels (may be in a pbo which we'll map here) */
1351 data = _mesa_validate_pbo_compressed_teximage(ctx, dims, imageSize, data,
1352 &ctx->Unpack,
1353 "glCompressedTexSubImage");
1354 if (!data)
1355 return;
1356
1357 src = (const GLubyte *) data + store.SkipBytes;
1358
1359 for (slice = 0; slice < store.CopySlices; slice++) {
1360 /* Map dest texture buffer */
1361 ctx->Driver.MapTextureImage(ctx, texImage, slice + zoffset,
1362 xoffset, yoffset, width, height,
1363 GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT,
1364 &dstMap, &dstRowStride);
1365
1366 if (dstMap) {
1367
1368 /* copy rows of blocks */
1369 if (dstRowStride == store.TotalBytesPerRow &&
1370 dstRowStride == store.CopyBytesPerRow) {
1371 memcpy(dstMap, src, store.CopyBytesPerRow * store.CopyRowsPerSlice);
1372 src += store.CopyBytesPerRow * store.CopyRowsPerSlice;
1373 }
1374 else {
1375 for (i = 0; i < store.CopyRowsPerSlice; i++) {
1376 memcpy(dstMap, src, store.CopyBytesPerRow);
1377 dstMap += dstRowStride;
1378 src += store.TotalBytesPerRow;
1379 }
1380 }
1381
1382 ctx->Driver.UnmapTextureImage(ctx, texImage, slice + zoffset);
1383
1384 /* advance to next slice */
1385 src += store.TotalBytesPerRow * (store.TotalRowsPerSlice
1386 - store.CopyRowsPerSlice);
1387 }
1388 else {
1389 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage%uD",
1390 dims);
1391 }
1392 }
1393
1394 _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack);
1395 }