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