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