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