• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_rgb_fxt1;
625       table[MESA_FORMAT_RGBA_FXT1] = _mesa_texstore_rgba_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