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