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