xref: /aosp_15_r20/external/mesa3d/src/mesa/main/image.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) 2009  VMware, Inc.  All Rights Reserved.
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 /**
28*61046927SAndroid Build Coastguard Worker  * \file image.c
29*61046927SAndroid Build Coastguard Worker  * Image handling.
30*61046927SAndroid Build Coastguard Worker  */
31*61046927SAndroid Build Coastguard Worker 
32*61046927SAndroid Build Coastguard Worker 
33*61046927SAndroid Build Coastguard Worker #include "util/glheader.h"
34*61046927SAndroid Build Coastguard Worker #include "colormac.h"
35*61046927SAndroid Build Coastguard Worker #include "glformats.h"
36*61046927SAndroid Build Coastguard Worker #include "image.h"
37*61046927SAndroid Build Coastguard Worker 
38*61046927SAndroid Build Coastguard Worker #include "macros.h"
39*61046927SAndroid Build Coastguard Worker #include "mtypes.h"
40*61046927SAndroid Build Coastguard Worker 
41*61046927SAndroid Build Coastguard Worker 
42*61046927SAndroid Build Coastguard Worker 
43*61046927SAndroid Build Coastguard Worker /**
44*61046927SAndroid Build Coastguard Worker  * Flip the order of the 2 bytes in each word in the given array (src) and
45*61046927SAndroid Build Coastguard Worker  * store the result in another array (dst). For in-place byte-swapping this
46*61046927SAndroid Build Coastguard Worker  * function can be called with the same array for src and dst.
47*61046927SAndroid Build Coastguard Worker  *
48*61046927SAndroid Build Coastguard Worker  * \param dst the array where byte-swapped data will be stored.
49*61046927SAndroid Build Coastguard Worker  * \param src the array with the source data we want to byte-swap.
50*61046927SAndroid Build Coastguard Worker  * \param n number of words.
51*61046927SAndroid Build Coastguard Worker  */
52*61046927SAndroid Build Coastguard Worker static void
swap2_copy(GLushort * dst,GLushort * src,GLuint n)53*61046927SAndroid Build Coastguard Worker swap2_copy( GLushort *dst, GLushort *src, GLuint n )
54*61046927SAndroid Build Coastguard Worker {
55*61046927SAndroid Build Coastguard Worker    GLuint i;
56*61046927SAndroid Build Coastguard Worker    for (i = 0; i < n; i++) {
57*61046927SAndroid Build Coastguard Worker       dst[i] = (src[i] >> 8) | ((src[i] << 8) & 0xff00);
58*61046927SAndroid Build Coastguard Worker    }
59*61046927SAndroid Build Coastguard Worker }
60*61046927SAndroid Build Coastguard Worker 
61*61046927SAndroid Build Coastguard Worker void
_mesa_swap2(GLushort * p,GLuint n)62*61046927SAndroid Build Coastguard Worker _mesa_swap2(GLushort *p, GLuint n)
63*61046927SAndroid Build Coastguard Worker {
64*61046927SAndroid Build Coastguard Worker    swap2_copy(p, p, n);
65*61046927SAndroid Build Coastguard Worker }
66*61046927SAndroid Build Coastguard Worker 
67*61046927SAndroid Build Coastguard Worker /*
68*61046927SAndroid Build Coastguard Worker  * Flip the order of the 4 bytes in each word in the given array (src) and
69*61046927SAndroid Build Coastguard Worker  * store the result in another array (dst). For in-place byte-swapping this
70*61046927SAndroid Build Coastguard Worker  * function can be called with the same array for src and dst.
71*61046927SAndroid Build Coastguard Worker  *
72*61046927SAndroid Build Coastguard Worker  * \param dst the array where byte-swapped data will be stored.
73*61046927SAndroid Build Coastguard Worker  * \param src the array with the source data we want to byte-swap.
74*61046927SAndroid Build Coastguard Worker  * \param n number of words.
75*61046927SAndroid Build Coastguard Worker  */
76*61046927SAndroid Build Coastguard Worker static void
swap4_copy(GLuint * dst,GLuint * src,GLuint n)77*61046927SAndroid Build Coastguard Worker swap4_copy( GLuint *dst, GLuint *src, GLuint n )
78*61046927SAndroid Build Coastguard Worker {
79*61046927SAndroid Build Coastguard Worker    GLuint i, a, b;
80*61046927SAndroid Build Coastguard Worker    for (i = 0; i < n; i++) {
81*61046927SAndroid Build Coastguard Worker       b = src[i];
82*61046927SAndroid Build Coastguard Worker       a =  (b >> 24)
83*61046927SAndroid Build Coastguard Worker 	| ((b >> 8) & 0xff00)
84*61046927SAndroid Build Coastguard Worker 	| ((b << 8) & 0xff0000)
85*61046927SAndroid Build Coastguard Worker 	| ((b << 24) & 0xff000000);
86*61046927SAndroid Build Coastguard Worker       dst[i] = a;
87*61046927SAndroid Build Coastguard Worker    }
88*61046927SAndroid Build Coastguard Worker }
89*61046927SAndroid Build Coastguard Worker 
90*61046927SAndroid Build Coastguard Worker void
_mesa_swap4(GLuint * p,GLuint n)91*61046927SAndroid Build Coastguard Worker _mesa_swap4(GLuint *p, GLuint n)
92*61046927SAndroid Build Coastguard Worker {
93*61046927SAndroid Build Coastguard Worker    swap4_copy(p, p, n);
94*61046927SAndroid Build Coastguard Worker }
95*61046927SAndroid Build Coastguard Worker 
96*61046927SAndroid Build Coastguard Worker /**
97*61046927SAndroid Build Coastguard Worker  * Return the byte offset of a specific pixel in an image (1D, 2D or 3D).
98*61046927SAndroid Build Coastguard Worker  *
99*61046927SAndroid Build Coastguard Worker  * Pixel unpacking/packing parameters are observed according to \p packing.
100*61046927SAndroid Build Coastguard Worker  *
101*61046927SAndroid Build Coastguard Worker  * \param dimensions either 1, 2 or 3 to indicate dimensionality of image
102*61046927SAndroid Build Coastguard Worker  * \param packing  the pixelstore attributes
103*61046927SAndroid Build Coastguard Worker  * \param width  the image width
104*61046927SAndroid Build Coastguard Worker  * \param height  the image height
105*61046927SAndroid Build Coastguard Worker  * \param format  the pixel format (must be validated beforehand)
106*61046927SAndroid Build Coastguard Worker  * \param type  the pixel data type (must be validated beforehand)
107*61046927SAndroid Build Coastguard Worker  * \param img  which image in the volume (0 for 1D or 2D images)
108*61046927SAndroid Build Coastguard Worker  * \param row  row of pixel in the image (0 for 1D images)
109*61046927SAndroid Build Coastguard Worker  * \param column column of pixel in the image
110*61046927SAndroid Build Coastguard Worker  *
111*61046927SAndroid Build Coastguard Worker  * \return offset of pixel.
112*61046927SAndroid Build Coastguard Worker  *
113*61046927SAndroid Build Coastguard Worker  * \sa gl_pixelstore_attrib.
114*61046927SAndroid Build Coastguard Worker  */
115*61046927SAndroid Build Coastguard Worker GLintptr
_mesa_image_offset(GLuint dimensions,const struct gl_pixelstore_attrib * packing,GLsizei width,GLsizei height,GLenum format,GLenum type,GLint img,GLint row,GLint column)116*61046927SAndroid Build Coastguard Worker _mesa_image_offset( GLuint dimensions,
117*61046927SAndroid Build Coastguard Worker                     const struct gl_pixelstore_attrib *packing,
118*61046927SAndroid Build Coastguard Worker                     GLsizei width, GLsizei height,
119*61046927SAndroid Build Coastguard Worker                     GLenum format, GLenum type,
120*61046927SAndroid Build Coastguard Worker                     GLint img, GLint row, GLint column )
121*61046927SAndroid Build Coastguard Worker {
122*61046927SAndroid Build Coastguard Worker    GLint alignment;        /* 1, 2 or 4 */
123*61046927SAndroid Build Coastguard Worker    GLint pixels_per_row;
124*61046927SAndroid Build Coastguard Worker    GLint rows_per_image;
125*61046927SAndroid Build Coastguard Worker    GLint skiprows;
126*61046927SAndroid Build Coastguard Worker    GLint skippixels;
127*61046927SAndroid Build Coastguard Worker    GLint skipimages;       /* for 3-D volume images */
128*61046927SAndroid Build Coastguard Worker    GLintptr offset;
129*61046927SAndroid Build Coastguard Worker 
130*61046927SAndroid Build Coastguard Worker    assert(dimensions >= 1 && dimensions <= 3);
131*61046927SAndroid Build Coastguard Worker 
132*61046927SAndroid Build Coastguard Worker    alignment = packing->Alignment;
133*61046927SAndroid Build Coastguard Worker    if (packing->RowLength > 0) {
134*61046927SAndroid Build Coastguard Worker       pixels_per_row = packing->RowLength;
135*61046927SAndroid Build Coastguard Worker    }
136*61046927SAndroid Build Coastguard Worker    else {
137*61046927SAndroid Build Coastguard Worker       pixels_per_row = width;
138*61046927SAndroid Build Coastguard Worker    }
139*61046927SAndroid Build Coastguard Worker    if (packing->ImageHeight > 0) {
140*61046927SAndroid Build Coastguard Worker       rows_per_image = packing->ImageHeight;
141*61046927SAndroid Build Coastguard Worker    }
142*61046927SAndroid Build Coastguard Worker    else {
143*61046927SAndroid Build Coastguard Worker       rows_per_image = height;
144*61046927SAndroid Build Coastguard Worker    }
145*61046927SAndroid Build Coastguard Worker 
146*61046927SAndroid Build Coastguard Worker    skippixels = packing->SkipPixels;
147*61046927SAndroid Build Coastguard Worker    /* Note: SKIP_ROWS _is_ used for 1D images */
148*61046927SAndroid Build Coastguard Worker    skiprows = packing->SkipRows;
149*61046927SAndroid Build Coastguard Worker    /* Note: SKIP_IMAGES is only used for 3D images */
150*61046927SAndroid Build Coastguard Worker    skipimages = (dimensions == 3) ? packing->SkipImages : 0;
151*61046927SAndroid Build Coastguard Worker 
152*61046927SAndroid Build Coastguard Worker    if (type == GL_BITMAP) {
153*61046927SAndroid Build Coastguard Worker       /* BITMAP data */
154*61046927SAndroid Build Coastguard Worker       GLintptr bytes_per_row;
155*61046927SAndroid Build Coastguard Worker       GLintptr bytes_per_image;
156*61046927SAndroid Build Coastguard Worker       /* components per pixel for color or stencil index: */
157*61046927SAndroid Build Coastguard Worker       const GLint comp_per_pixel = 1;
158*61046927SAndroid Build Coastguard Worker 
159*61046927SAndroid Build Coastguard Worker       /* The pixel type and format should have been error checked earlier */
160*61046927SAndroid Build Coastguard Worker       assert(format == GL_COLOR_INDEX || format == GL_STENCIL_INDEX);
161*61046927SAndroid Build Coastguard Worker 
162*61046927SAndroid Build Coastguard Worker       bytes_per_row = alignment
163*61046927SAndroid Build Coastguard Worker                     * DIV_ROUND_UP( comp_per_pixel*pixels_per_row, 8*alignment );
164*61046927SAndroid Build Coastguard Worker 
165*61046927SAndroid Build Coastguard Worker       bytes_per_image = bytes_per_row * rows_per_image;
166*61046927SAndroid Build Coastguard Worker 
167*61046927SAndroid Build Coastguard Worker       offset = (skipimages + img) * bytes_per_image
168*61046927SAndroid Build Coastguard Worker                  + (skiprows + row) * bytes_per_row
169*61046927SAndroid Build Coastguard Worker                  + (skippixels + column) / 8;
170*61046927SAndroid Build Coastguard Worker    }
171*61046927SAndroid Build Coastguard Worker    else {
172*61046927SAndroid Build Coastguard Worker       /* Non-BITMAP data */
173*61046927SAndroid Build Coastguard Worker       GLintptr bytes_per_pixel, bytes_per_row, remainder, bytes_per_image;
174*61046927SAndroid Build Coastguard Worker       GLintptr topOfImage;
175*61046927SAndroid Build Coastguard Worker 
176*61046927SAndroid Build Coastguard Worker       bytes_per_pixel = _mesa_bytes_per_pixel( format, type );
177*61046927SAndroid Build Coastguard Worker 
178*61046927SAndroid Build Coastguard Worker       /* The pixel type and format should have been error checked earlier */
179*61046927SAndroid Build Coastguard Worker       assert(bytes_per_pixel > 0);
180*61046927SAndroid Build Coastguard Worker 
181*61046927SAndroid Build Coastguard Worker       bytes_per_row = pixels_per_row * bytes_per_pixel;
182*61046927SAndroid Build Coastguard Worker       remainder = bytes_per_row % alignment;
183*61046927SAndroid Build Coastguard Worker       if (remainder > 0)
184*61046927SAndroid Build Coastguard Worker          bytes_per_row += (alignment - remainder);
185*61046927SAndroid Build Coastguard Worker 
186*61046927SAndroid Build Coastguard Worker       assert(bytes_per_row % alignment == 0);
187*61046927SAndroid Build Coastguard Worker 
188*61046927SAndroid Build Coastguard Worker       bytes_per_image = bytes_per_row * rows_per_image;
189*61046927SAndroid Build Coastguard Worker 
190*61046927SAndroid Build Coastguard Worker       if (packing->Invert) {
191*61046927SAndroid Build Coastguard Worker          /* set pixel_addr to the last row */
192*61046927SAndroid Build Coastguard Worker          topOfImage = bytes_per_row * (height - 1);
193*61046927SAndroid Build Coastguard Worker          bytes_per_row = -bytes_per_row;
194*61046927SAndroid Build Coastguard Worker       }
195*61046927SAndroid Build Coastguard Worker       else {
196*61046927SAndroid Build Coastguard Worker          topOfImage = 0;
197*61046927SAndroid Build Coastguard Worker       }
198*61046927SAndroid Build Coastguard Worker 
199*61046927SAndroid Build Coastguard Worker       /* compute final pixel address */
200*61046927SAndroid Build Coastguard Worker       offset = (skipimages + img) * bytes_per_image
201*61046927SAndroid Build Coastguard Worker                  + topOfImage
202*61046927SAndroid Build Coastguard Worker                  + (skiprows + row) * bytes_per_row
203*61046927SAndroid Build Coastguard Worker                  + (skippixels + column) * bytes_per_pixel;
204*61046927SAndroid Build Coastguard Worker    }
205*61046927SAndroid Build Coastguard Worker 
206*61046927SAndroid Build Coastguard Worker    return offset;
207*61046927SAndroid Build Coastguard Worker }
208*61046927SAndroid Build Coastguard Worker 
209*61046927SAndroid Build Coastguard Worker 
210*61046927SAndroid Build Coastguard Worker /**
211*61046927SAndroid Build Coastguard Worker  * Return the address of a specific pixel in an image (1D, 2D or 3D).
212*61046927SAndroid Build Coastguard Worker  *
213*61046927SAndroid Build Coastguard Worker  * Pixel unpacking/packing parameters are observed according to \p packing.
214*61046927SAndroid Build Coastguard Worker  *
215*61046927SAndroid Build Coastguard Worker  * \param dimensions either 1, 2 or 3 to indicate dimensionality of image
216*61046927SAndroid Build Coastguard Worker  * \param packing  the pixelstore attributes
217*61046927SAndroid Build Coastguard Worker  * \param image  starting address of image data
218*61046927SAndroid Build Coastguard Worker  * \param width  the image width
219*61046927SAndroid Build Coastguard Worker  * \param height  the image height
220*61046927SAndroid Build Coastguard Worker  * \param format  the pixel format (must be validated beforehand)
221*61046927SAndroid Build Coastguard Worker  * \param type  the pixel data type (must be validated beforehand)
222*61046927SAndroid Build Coastguard Worker  * \param img  which image in the volume (0 for 1D or 2D images)
223*61046927SAndroid Build Coastguard Worker  * \param row  row of pixel in the image (0 for 1D images)
224*61046927SAndroid Build Coastguard Worker  * \param column column of pixel in the image
225*61046927SAndroid Build Coastguard Worker  *
226*61046927SAndroid Build Coastguard Worker  * \return address of pixel.
227*61046927SAndroid Build Coastguard Worker  *
228*61046927SAndroid Build Coastguard Worker  * \sa gl_pixelstore_attrib.
229*61046927SAndroid Build Coastguard Worker  */
230*61046927SAndroid Build Coastguard Worker GLvoid *
_mesa_image_address(GLuint dimensions,const struct gl_pixelstore_attrib * packing,const GLvoid * image,GLsizei width,GLsizei height,GLenum format,GLenum type,GLint img,GLint row,GLint column)231*61046927SAndroid Build Coastguard Worker _mesa_image_address( GLuint dimensions,
232*61046927SAndroid Build Coastguard Worker                      const struct gl_pixelstore_attrib *packing,
233*61046927SAndroid Build Coastguard Worker                      const GLvoid *image,
234*61046927SAndroid Build Coastguard Worker                      GLsizei width, GLsizei height,
235*61046927SAndroid Build Coastguard Worker                      GLenum format, GLenum type,
236*61046927SAndroid Build Coastguard Worker                      GLint img, GLint row, GLint column )
237*61046927SAndroid Build Coastguard Worker {
238*61046927SAndroid Build Coastguard Worker    const GLubyte *addr = (const GLubyte *) image;
239*61046927SAndroid Build Coastguard Worker 
240*61046927SAndroid Build Coastguard Worker    addr += _mesa_image_offset(dimensions, packing, width, height,
241*61046927SAndroid Build Coastguard Worker                               format, type, img, row, column);
242*61046927SAndroid Build Coastguard Worker 
243*61046927SAndroid Build Coastguard Worker    return (GLvoid *) addr;
244*61046927SAndroid Build Coastguard Worker }
245*61046927SAndroid Build Coastguard Worker 
246*61046927SAndroid Build Coastguard Worker 
247*61046927SAndroid Build Coastguard Worker GLvoid *
_mesa_image_address1d(const struct gl_pixelstore_attrib * packing,const GLvoid * image,GLsizei width,GLenum format,GLenum type,GLint column)248*61046927SAndroid Build Coastguard Worker _mesa_image_address1d( const struct gl_pixelstore_attrib *packing,
249*61046927SAndroid Build Coastguard Worker                        const GLvoid *image,
250*61046927SAndroid Build Coastguard Worker                        GLsizei width,
251*61046927SAndroid Build Coastguard Worker                        GLenum format, GLenum type,
252*61046927SAndroid Build Coastguard Worker                        GLint column )
253*61046927SAndroid Build Coastguard Worker {
254*61046927SAndroid Build Coastguard Worker    return _mesa_image_address(1, packing, image, width, 1,
255*61046927SAndroid Build Coastguard Worker                               format, type, 0, 0, column);
256*61046927SAndroid Build Coastguard Worker }
257*61046927SAndroid Build Coastguard Worker 
258*61046927SAndroid Build Coastguard Worker 
259*61046927SAndroid Build Coastguard Worker GLvoid *
_mesa_image_address2d(const struct gl_pixelstore_attrib * packing,const GLvoid * image,GLsizei width,GLsizei height,GLenum format,GLenum type,GLint row,GLint column)260*61046927SAndroid Build Coastguard Worker _mesa_image_address2d( const struct gl_pixelstore_attrib *packing,
261*61046927SAndroid Build Coastguard Worker                        const GLvoid *image,
262*61046927SAndroid Build Coastguard Worker                        GLsizei width, GLsizei height,
263*61046927SAndroid Build Coastguard Worker                        GLenum format, GLenum type,
264*61046927SAndroid Build Coastguard Worker                        GLint row, GLint column )
265*61046927SAndroid Build Coastguard Worker {
266*61046927SAndroid Build Coastguard Worker    return _mesa_image_address(2, packing, image, width, height,
267*61046927SAndroid Build Coastguard Worker                               format, type, 0, row, column);
268*61046927SAndroid Build Coastguard Worker }
269*61046927SAndroid Build Coastguard Worker 
270*61046927SAndroid Build Coastguard Worker 
271*61046927SAndroid Build Coastguard Worker GLvoid *
_mesa_image_address3d(const struct gl_pixelstore_attrib * packing,const GLvoid * image,GLsizei width,GLsizei height,GLenum format,GLenum type,GLint img,GLint row,GLint column)272*61046927SAndroid Build Coastguard Worker _mesa_image_address3d( const struct gl_pixelstore_attrib *packing,
273*61046927SAndroid Build Coastguard Worker                        const GLvoid *image,
274*61046927SAndroid Build Coastguard Worker                        GLsizei width, GLsizei height,
275*61046927SAndroid Build Coastguard Worker                        GLenum format, GLenum type,
276*61046927SAndroid Build Coastguard Worker                        GLint img, GLint row, GLint column )
277*61046927SAndroid Build Coastguard Worker {
278*61046927SAndroid Build Coastguard Worker    return _mesa_image_address(3, packing, image, width, height,
279*61046927SAndroid Build Coastguard Worker                               format, type, img, row, column);
280*61046927SAndroid Build Coastguard Worker }
281*61046927SAndroid Build Coastguard Worker 
282*61046927SAndroid Build Coastguard Worker 
283*61046927SAndroid Build Coastguard Worker 
284*61046927SAndroid Build Coastguard Worker /**
285*61046927SAndroid Build Coastguard Worker  * Compute the stride (in bytes) between image rows.
286*61046927SAndroid Build Coastguard Worker  *
287*61046927SAndroid Build Coastguard Worker  * \param packing the pixelstore attributes
288*61046927SAndroid Build Coastguard Worker  * \param width image width.
289*61046927SAndroid Build Coastguard Worker  * \param format pixel format.
290*61046927SAndroid Build Coastguard Worker  * \param type pixel data type.
291*61046927SAndroid Build Coastguard Worker  *
292*61046927SAndroid Build Coastguard Worker  * \return the stride in bytes for the given parameters, or -1 if error
293*61046927SAndroid Build Coastguard Worker  */
294*61046927SAndroid Build Coastguard Worker GLint
_mesa_image_row_stride(const struct gl_pixelstore_attrib * packing,GLint width,GLenum format,GLenum type)295*61046927SAndroid Build Coastguard Worker _mesa_image_row_stride( const struct gl_pixelstore_attrib *packing,
296*61046927SAndroid Build Coastguard Worker                         GLint width, GLenum format, GLenum type )
297*61046927SAndroid Build Coastguard Worker {
298*61046927SAndroid Build Coastguard Worker    GLint bytesPerRow, remainder;
299*61046927SAndroid Build Coastguard Worker 
300*61046927SAndroid Build Coastguard Worker    assert(packing);
301*61046927SAndroid Build Coastguard Worker 
302*61046927SAndroid Build Coastguard Worker    if (type == GL_BITMAP) {
303*61046927SAndroid Build Coastguard Worker       if (packing->RowLength == 0) {
304*61046927SAndroid Build Coastguard Worker          bytesPerRow = (width + 7) / 8;
305*61046927SAndroid Build Coastguard Worker       }
306*61046927SAndroid Build Coastguard Worker       else {
307*61046927SAndroid Build Coastguard Worker          bytesPerRow = (packing->RowLength + 7) / 8;
308*61046927SAndroid Build Coastguard Worker       }
309*61046927SAndroid Build Coastguard Worker    }
310*61046927SAndroid Build Coastguard Worker    else {
311*61046927SAndroid Build Coastguard Worker       /* Non-BITMAP data */
312*61046927SAndroid Build Coastguard Worker       const GLint bytesPerPixel = _mesa_bytes_per_pixel(format, type);
313*61046927SAndroid Build Coastguard Worker       if (bytesPerPixel <= 0)
314*61046927SAndroid Build Coastguard Worker          return -1;  /* error */
315*61046927SAndroid Build Coastguard Worker       if (packing->RowLength == 0) {
316*61046927SAndroid Build Coastguard Worker          bytesPerRow = bytesPerPixel * width;
317*61046927SAndroid Build Coastguard Worker       }
318*61046927SAndroid Build Coastguard Worker       else {
319*61046927SAndroid Build Coastguard Worker          bytesPerRow = bytesPerPixel * packing->RowLength;
320*61046927SAndroid Build Coastguard Worker       }
321*61046927SAndroid Build Coastguard Worker    }
322*61046927SAndroid Build Coastguard Worker 
323*61046927SAndroid Build Coastguard Worker    remainder = bytesPerRow % packing->Alignment;
324*61046927SAndroid Build Coastguard Worker    if (remainder > 0) {
325*61046927SAndroid Build Coastguard Worker       bytesPerRow += (packing->Alignment - remainder);
326*61046927SAndroid Build Coastguard Worker    }
327*61046927SAndroid Build Coastguard Worker 
328*61046927SAndroid Build Coastguard Worker    if (packing->Invert) {
329*61046927SAndroid Build Coastguard Worker       /* negate the bytes per row (negative row stride) */
330*61046927SAndroid Build Coastguard Worker       bytesPerRow = -bytesPerRow;
331*61046927SAndroid Build Coastguard Worker    }
332*61046927SAndroid Build Coastguard Worker 
333*61046927SAndroid Build Coastguard Worker    return bytesPerRow;
334*61046927SAndroid Build Coastguard Worker }
335*61046927SAndroid Build Coastguard Worker 
336*61046927SAndroid Build Coastguard Worker 
337*61046927SAndroid Build Coastguard Worker /*
338*61046927SAndroid Build Coastguard Worker  * Compute the stride between images in a 3D texture (in bytes) for the given
339*61046927SAndroid Build Coastguard Worker  * pixel packing parameters and image width, format and type.
340*61046927SAndroid Build Coastguard Worker  */
341*61046927SAndroid Build Coastguard Worker intptr_t
_mesa_image_image_stride(const struct gl_pixelstore_attrib * packing,GLint width,GLint height,GLenum format,GLenum type)342*61046927SAndroid Build Coastguard Worker _mesa_image_image_stride( const struct gl_pixelstore_attrib *packing,
343*61046927SAndroid Build Coastguard Worker                           GLint width, GLint height,
344*61046927SAndroid Build Coastguard Worker                           GLenum format, GLenum type )
345*61046927SAndroid Build Coastguard Worker {
346*61046927SAndroid Build Coastguard Worker    GLint bytesPerRow, remainder;
347*61046927SAndroid Build Coastguard Worker    intptr_t bytesPerImage;
348*61046927SAndroid Build Coastguard Worker 
349*61046927SAndroid Build Coastguard Worker    assert(packing);
350*61046927SAndroid Build Coastguard Worker 
351*61046927SAndroid Build Coastguard Worker    if (type == GL_BITMAP) {
352*61046927SAndroid Build Coastguard Worker       if (packing->RowLength == 0) {
353*61046927SAndroid Build Coastguard Worker          bytesPerRow = (width + 7) / 8;
354*61046927SAndroid Build Coastguard Worker       }
355*61046927SAndroid Build Coastguard Worker       else {
356*61046927SAndroid Build Coastguard Worker          bytesPerRow = (packing->RowLength + 7) / 8;
357*61046927SAndroid Build Coastguard Worker       }
358*61046927SAndroid Build Coastguard Worker    }
359*61046927SAndroid Build Coastguard Worker    else {
360*61046927SAndroid Build Coastguard Worker       const GLint bytesPerPixel = _mesa_bytes_per_pixel(format, type);
361*61046927SAndroid Build Coastguard Worker 
362*61046927SAndroid Build Coastguard Worker       if (bytesPerPixel <= 0)
363*61046927SAndroid Build Coastguard Worker          return -1;  /* error */
364*61046927SAndroid Build Coastguard Worker       if (packing->RowLength == 0) {
365*61046927SAndroid Build Coastguard Worker          bytesPerRow = bytesPerPixel * width;
366*61046927SAndroid Build Coastguard Worker       }
367*61046927SAndroid Build Coastguard Worker       else {
368*61046927SAndroid Build Coastguard Worker          bytesPerRow = bytesPerPixel * packing->RowLength;
369*61046927SAndroid Build Coastguard Worker       }
370*61046927SAndroid Build Coastguard Worker    }
371*61046927SAndroid Build Coastguard Worker 
372*61046927SAndroid Build Coastguard Worker    remainder = bytesPerRow % packing->Alignment;
373*61046927SAndroid Build Coastguard Worker    if (remainder > 0)
374*61046927SAndroid Build Coastguard Worker       bytesPerRow += (packing->Alignment - remainder);
375*61046927SAndroid Build Coastguard Worker 
376*61046927SAndroid Build Coastguard Worker    if (packing->ImageHeight == 0)
377*61046927SAndroid Build Coastguard Worker       bytesPerImage = (intptr_t)bytesPerRow * height;
378*61046927SAndroid Build Coastguard Worker    else
379*61046927SAndroid Build Coastguard Worker       bytesPerImage = (intptr_t)bytesPerRow * packing->ImageHeight;
380*61046927SAndroid Build Coastguard Worker 
381*61046927SAndroid Build Coastguard Worker    return bytesPerImage;
382*61046927SAndroid Build Coastguard Worker }
383*61046927SAndroid Build Coastguard Worker 
384*61046927SAndroid Build Coastguard Worker 
385*61046927SAndroid Build Coastguard Worker 
386*61046927SAndroid Build Coastguard Worker /**
387*61046927SAndroid Build Coastguard Worker  * "Expand" a bitmap from 1-bit per pixel to 8-bits per pixel.
388*61046927SAndroid Build Coastguard Worker  * This is typically used to convert a bitmap into a GLubyte/pixel texture.
389*61046927SAndroid Build Coastguard Worker  * "On" bits will set texels to \p onValue.
390*61046927SAndroid Build Coastguard Worker  * "Off" bits will not modify texels.
391*61046927SAndroid Build Coastguard Worker  * \param width  src bitmap width in pixels
392*61046927SAndroid Build Coastguard Worker  * \param height  src bitmap height in pixels
393*61046927SAndroid Build Coastguard Worker  * \param unpack  bitmap unpacking state
394*61046927SAndroid Build Coastguard Worker  * \param bitmap  the src bitmap data
395*61046927SAndroid Build Coastguard Worker  * \param destBuffer  start of dest buffer
396*61046927SAndroid Build Coastguard Worker  * \param destStride  row stride in dest buffer
397*61046927SAndroid Build Coastguard Worker  * \param onValue  if bit is 1, set destBuffer pixel to this value
398*61046927SAndroid Build Coastguard Worker  */
399*61046927SAndroid Build Coastguard Worker void
_mesa_expand_bitmap(GLsizei width,GLsizei height,const struct gl_pixelstore_attrib * unpack,const GLubyte * bitmap,GLubyte * destBuffer,GLint destStride,GLubyte onValue)400*61046927SAndroid Build Coastguard Worker _mesa_expand_bitmap(GLsizei width, GLsizei height,
401*61046927SAndroid Build Coastguard Worker                     const struct gl_pixelstore_attrib *unpack,
402*61046927SAndroid Build Coastguard Worker                     const GLubyte *bitmap,
403*61046927SAndroid Build Coastguard Worker                     GLubyte *destBuffer, GLint destStride,
404*61046927SAndroid Build Coastguard Worker                     GLubyte onValue)
405*61046927SAndroid Build Coastguard Worker {
406*61046927SAndroid Build Coastguard Worker    const GLubyte *srcRow = (const GLubyte *)
407*61046927SAndroid Build Coastguard Worker       _mesa_image_address2d(unpack, bitmap, width, height,
408*61046927SAndroid Build Coastguard Worker                             GL_COLOR_INDEX, GL_BITMAP, 0, 0);
409*61046927SAndroid Build Coastguard Worker    const GLint srcStride = _mesa_image_row_stride(unpack, width,
410*61046927SAndroid Build Coastguard Worker                                                   GL_COLOR_INDEX, GL_BITMAP);
411*61046927SAndroid Build Coastguard Worker    GLint row, col;
412*61046927SAndroid Build Coastguard Worker    GLubyte *dstRow = destBuffer;
413*61046927SAndroid Build Coastguard Worker 
414*61046927SAndroid Build Coastguard Worker    for (row = 0; row < height; row++) {
415*61046927SAndroid Build Coastguard Worker       const GLubyte *src = srcRow;
416*61046927SAndroid Build Coastguard Worker 
417*61046927SAndroid Build Coastguard Worker       if (unpack->LsbFirst) {
418*61046927SAndroid Build Coastguard Worker          /* Lsb first */
419*61046927SAndroid Build Coastguard Worker          GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
420*61046927SAndroid Build Coastguard Worker          for (col = 0; col < width; col++) {
421*61046927SAndroid Build Coastguard Worker 
422*61046927SAndroid Build Coastguard Worker             if (*src & mask) {
423*61046927SAndroid Build Coastguard Worker                dstRow[col] = onValue;
424*61046927SAndroid Build Coastguard Worker             }
425*61046927SAndroid Build Coastguard Worker 
426*61046927SAndroid Build Coastguard Worker             if (mask == 128U) {
427*61046927SAndroid Build Coastguard Worker                src++;
428*61046927SAndroid Build Coastguard Worker                mask = 1U;
429*61046927SAndroid Build Coastguard Worker             }
430*61046927SAndroid Build Coastguard Worker             else {
431*61046927SAndroid Build Coastguard Worker                mask = mask << 1;
432*61046927SAndroid Build Coastguard Worker             }
433*61046927SAndroid Build Coastguard Worker          }
434*61046927SAndroid Build Coastguard Worker 
435*61046927SAndroid Build Coastguard Worker          /* get ready for next row */
436*61046927SAndroid Build Coastguard Worker          if (mask != 1)
437*61046927SAndroid Build Coastguard Worker             src++;
438*61046927SAndroid Build Coastguard Worker       }
439*61046927SAndroid Build Coastguard Worker       else {
440*61046927SAndroid Build Coastguard Worker          /* Msb first */
441*61046927SAndroid Build Coastguard Worker          GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
442*61046927SAndroid Build Coastguard Worker          for (col = 0; col < width; col++) {
443*61046927SAndroid Build Coastguard Worker 
444*61046927SAndroid Build Coastguard Worker             if (*src & mask) {
445*61046927SAndroid Build Coastguard Worker                dstRow[col] = onValue;
446*61046927SAndroid Build Coastguard Worker             }
447*61046927SAndroid Build Coastguard Worker 
448*61046927SAndroid Build Coastguard Worker             if (mask == 1U) {
449*61046927SAndroid Build Coastguard Worker                src++;
450*61046927SAndroid Build Coastguard Worker                mask = 128U;
451*61046927SAndroid Build Coastguard Worker             }
452*61046927SAndroid Build Coastguard Worker             else {
453*61046927SAndroid Build Coastguard Worker                mask = mask >> 1;
454*61046927SAndroid Build Coastguard Worker             }
455*61046927SAndroid Build Coastguard Worker          }
456*61046927SAndroid Build Coastguard Worker 
457*61046927SAndroid Build Coastguard Worker          /* get ready for next row */
458*61046927SAndroid Build Coastguard Worker          if (mask != 128)
459*61046927SAndroid Build Coastguard Worker             src++;
460*61046927SAndroid Build Coastguard Worker       }
461*61046927SAndroid Build Coastguard Worker 
462*61046927SAndroid Build Coastguard Worker       srcRow += srcStride;
463*61046927SAndroid Build Coastguard Worker       dstRow += destStride;
464*61046927SAndroid Build Coastguard Worker    } /* row */
465*61046927SAndroid Build Coastguard Worker }
466*61046927SAndroid Build Coastguard Worker 
467*61046927SAndroid Build Coastguard Worker 
468*61046927SAndroid Build Coastguard Worker 
469*61046927SAndroid Build Coastguard Worker 
470*61046927SAndroid Build Coastguard Worker /**
471*61046927SAndroid Build Coastguard Worker  * Perform basic clipping for glDrawPixels.  The image's position and size
472*61046927SAndroid Build Coastguard Worker  * and the unpack SkipPixels and SkipRows are adjusted so that the image
473*61046927SAndroid Build Coastguard Worker  * region is entirely within the window and scissor bounds.
474*61046927SAndroid Build Coastguard Worker  * NOTE: this will only work when glPixelZoom is (1, 1) or (1, -1).
475*61046927SAndroid Build Coastguard Worker  * If Pixel.ZoomY is -1, *destY will be changed to be the first row which
476*61046927SAndroid Build Coastguard Worker  * we'll actually write.  Beforehand, *destY-1 is the first drawing row.
477*61046927SAndroid Build Coastguard Worker  *
478*61046927SAndroid Build Coastguard Worker  * \return  GL_TRUE if image is ready for drawing or
479*61046927SAndroid Build Coastguard Worker  *          GL_FALSE if image was completely clipped away (draw nothing)
480*61046927SAndroid Build Coastguard Worker  */
481*61046927SAndroid Build Coastguard Worker GLboolean
_mesa_clip_drawpixels(const struct gl_context * ctx,GLint * destX,GLint * destY,GLsizei * width,GLsizei * height,struct gl_pixelstore_attrib * unpack)482*61046927SAndroid Build Coastguard Worker _mesa_clip_drawpixels(const struct gl_context *ctx,
483*61046927SAndroid Build Coastguard Worker                       GLint *destX, GLint *destY,
484*61046927SAndroid Build Coastguard Worker                       GLsizei *width, GLsizei *height,
485*61046927SAndroid Build Coastguard Worker                       struct gl_pixelstore_attrib *unpack)
486*61046927SAndroid Build Coastguard Worker {
487*61046927SAndroid Build Coastguard Worker    const struct gl_framebuffer *buffer = ctx->DrawBuffer;
488*61046927SAndroid Build Coastguard Worker 
489*61046927SAndroid Build Coastguard Worker    if (unpack->RowLength == 0) {
490*61046927SAndroid Build Coastguard Worker       unpack->RowLength = *width;
491*61046927SAndroid Build Coastguard Worker    }
492*61046927SAndroid Build Coastguard Worker 
493*61046927SAndroid Build Coastguard Worker    assert(ctx->Pixel.ZoomX == 1.0F);
494*61046927SAndroid Build Coastguard Worker    assert(ctx->Pixel.ZoomY == 1.0F || ctx->Pixel.ZoomY == -1.0F);
495*61046927SAndroid Build Coastguard Worker 
496*61046927SAndroid Build Coastguard Worker    /* left clipping */
497*61046927SAndroid Build Coastguard Worker    if (*destX < buffer->_Xmin) {
498*61046927SAndroid Build Coastguard Worker       unpack->SkipPixels += (buffer->_Xmin - *destX);
499*61046927SAndroid Build Coastguard Worker       *width -= (buffer->_Xmin - *destX);
500*61046927SAndroid Build Coastguard Worker       *destX = buffer->_Xmin;
501*61046927SAndroid Build Coastguard Worker    }
502*61046927SAndroid Build Coastguard Worker    /* right clipping */
503*61046927SAndroid Build Coastguard Worker    if (*destX + *width > buffer->_Xmax)
504*61046927SAndroid Build Coastguard Worker       *width -= (*destX + *width - buffer->_Xmax);
505*61046927SAndroid Build Coastguard Worker 
506*61046927SAndroid Build Coastguard Worker    if (*width <= 0)
507*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
508*61046927SAndroid Build Coastguard Worker 
509*61046927SAndroid Build Coastguard Worker    if (ctx->Pixel.ZoomY == 1.0F) {
510*61046927SAndroid Build Coastguard Worker       /* bottom clipping */
511*61046927SAndroid Build Coastguard Worker       if (*destY < buffer->_Ymin) {
512*61046927SAndroid Build Coastguard Worker          unpack->SkipRows += (buffer->_Ymin - *destY);
513*61046927SAndroid Build Coastguard Worker          *height -= (buffer->_Ymin - *destY);
514*61046927SAndroid Build Coastguard Worker          *destY = buffer->_Ymin;
515*61046927SAndroid Build Coastguard Worker       }
516*61046927SAndroid Build Coastguard Worker       /* top clipping */
517*61046927SAndroid Build Coastguard Worker       if (*destY + *height > buffer->_Ymax)
518*61046927SAndroid Build Coastguard Worker          *height -= (*destY + *height - buffer->_Ymax);
519*61046927SAndroid Build Coastguard Worker    }
520*61046927SAndroid Build Coastguard Worker    else { /* upside down */
521*61046927SAndroid Build Coastguard Worker       /* top clipping */
522*61046927SAndroid Build Coastguard Worker       if (*destY > buffer->_Ymax) {
523*61046927SAndroid Build Coastguard Worker          unpack->SkipRows += (*destY - buffer->_Ymax);
524*61046927SAndroid Build Coastguard Worker          *height -= (*destY - buffer->_Ymax);
525*61046927SAndroid Build Coastguard Worker          *destY = buffer->_Ymax;
526*61046927SAndroid Build Coastguard Worker       }
527*61046927SAndroid Build Coastguard Worker       /* bottom clipping */
528*61046927SAndroid Build Coastguard Worker       if (*destY - *height < buffer->_Ymin)
529*61046927SAndroid Build Coastguard Worker          *height -= (buffer->_Ymin - (*destY - *height));
530*61046927SAndroid Build Coastguard Worker       /* adjust destY so it's the first row to write to */
531*61046927SAndroid Build Coastguard Worker       (*destY)--;
532*61046927SAndroid Build Coastguard Worker    }
533*61046927SAndroid Build Coastguard Worker 
534*61046927SAndroid Build Coastguard Worker    if (*height <= 0)
535*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
536*61046927SAndroid Build Coastguard Worker 
537*61046927SAndroid Build Coastguard Worker    return GL_TRUE;
538*61046927SAndroid Build Coastguard Worker }
539*61046927SAndroid Build Coastguard Worker 
540*61046927SAndroid Build Coastguard Worker 
541*61046927SAndroid Build Coastguard Worker /**
542*61046927SAndroid Build Coastguard Worker  * Perform clipping for glReadPixels.  The image's window position
543*61046927SAndroid Build Coastguard Worker  * and size, and the pack skipPixels, skipRows and rowLength are adjusted
544*61046927SAndroid Build Coastguard Worker  * so that the image region is entirely within the window bounds.
545*61046927SAndroid Build Coastguard Worker  * Note: this is different from _mesa_clip_drawpixels() in that the
546*61046927SAndroid Build Coastguard Worker  * scissor box is ignored, and we use the bounds of the current readbuffer
547*61046927SAndroid Build Coastguard Worker  * surface or the attached image.
548*61046927SAndroid Build Coastguard Worker  *
549*61046927SAndroid Build Coastguard Worker  * \return  GL_TRUE if region to read is in bounds
550*61046927SAndroid Build Coastguard Worker  *          GL_FALSE if region is completely out of bounds (nothing to read)
551*61046927SAndroid Build Coastguard Worker  */
552*61046927SAndroid Build Coastguard Worker GLboolean
_mesa_clip_readpixels(const struct gl_context * ctx,GLint * srcX,GLint * srcY,GLsizei * width,GLsizei * height,struct gl_pixelstore_attrib * pack)553*61046927SAndroid Build Coastguard Worker _mesa_clip_readpixels(const struct gl_context *ctx,
554*61046927SAndroid Build Coastguard Worker                       GLint *srcX, GLint *srcY,
555*61046927SAndroid Build Coastguard Worker                       GLsizei *width, GLsizei *height,
556*61046927SAndroid Build Coastguard Worker                       struct gl_pixelstore_attrib *pack)
557*61046927SAndroid Build Coastguard Worker {
558*61046927SAndroid Build Coastguard Worker    const struct gl_framebuffer *buffer = ctx->ReadBuffer;
559*61046927SAndroid Build Coastguard Worker    struct gl_renderbuffer *rb = buffer->_ColorReadBuffer;
560*61046927SAndroid Build Coastguard Worker    GLsizei clip_width;
561*61046927SAndroid Build Coastguard Worker    GLsizei clip_height;
562*61046927SAndroid Build Coastguard Worker 
563*61046927SAndroid Build Coastguard Worker    if (rb) {
564*61046927SAndroid Build Coastguard Worker       clip_width = rb->Width;
565*61046927SAndroid Build Coastguard Worker       clip_height = rb->Height;
566*61046927SAndroid Build Coastguard Worker    } else {
567*61046927SAndroid Build Coastguard Worker       clip_width = buffer->Width;
568*61046927SAndroid Build Coastguard Worker       clip_height = buffer->Height;
569*61046927SAndroid Build Coastguard Worker    }
570*61046927SAndroid Build Coastguard Worker 
571*61046927SAndroid Build Coastguard Worker 
572*61046927SAndroid Build Coastguard Worker    if (pack->RowLength == 0) {
573*61046927SAndroid Build Coastguard Worker       pack->RowLength = *width;
574*61046927SAndroid Build Coastguard Worker    }
575*61046927SAndroid Build Coastguard Worker 
576*61046927SAndroid Build Coastguard Worker    /* left clipping */
577*61046927SAndroid Build Coastguard Worker    if (*srcX < 0) {
578*61046927SAndroid Build Coastguard Worker       pack->SkipPixels += (0 - *srcX);
579*61046927SAndroid Build Coastguard Worker       *width -= (0 - *srcX);
580*61046927SAndroid Build Coastguard Worker       *srcX = 0;
581*61046927SAndroid Build Coastguard Worker    }
582*61046927SAndroid Build Coastguard Worker    /* right clipping */
583*61046927SAndroid Build Coastguard Worker    if (*srcX + *width > clip_width)
584*61046927SAndroid Build Coastguard Worker       *width -= (*srcX + *width - clip_width);
585*61046927SAndroid Build Coastguard Worker 
586*61046927SAndroid Build Coastguard Worker    if (*width <= 0)
587*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
588*61046927SAndroid Build Coastguard Worker 
589*61046927SAndroid Build Coastguard Worker    /* bottom clipping */
590*61046927SAndroid Build Coastguard Worker    if (*srcY < 0) {
591*61046927SAndroid Build Coastguard Worker       pack->SkipRows += (0 - *srcY);
592*61046927SAndroid Build Coastguard Worker       *height -= (0 - *srcY);
593*61046927SAndroid Build Coastguard Worker       *srcY = 0;
594*61046927SAndroid Build Coastguard Worker    }
595*61046927SAndroid Build Coastguard Worker    /* top clipping */
596*61046927SAndroid Build Coastguard Worker    if (*srcY + *height > clip_height)
597*61046927SAndroid Build Coastguard Worker       *height -= (*srcY + *height - clip_height);
598*61046927SAndroid Build Coastguard Worker 
599*61046927SAndroid Build Coastguard Worker    if (*height <= 0)
600*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
601*61046927SAndroid Build Coastguard Worker 
602*61046927SAndroid Build Coastguard Worker    return GL_TRUE;
603*61046927SAndroid Build Coastguard Worker }
604*61046927SAndroid Build Coastguard Worker 
605*61046927SAndroid Build Coastguard Worker 
606*61046927SAndroid Build Coastguard Worker /**
607*61046927SAndroid Build Coastguard Worker  * Do clipping for a glCopyTexSubImage call.
608*61046927SAndroid Build Coastguard Worker  * The framebuffer source region might extend outside the framebuffer
609*61046927SAndroid Build Coastguard Worker  * bounds.  Clip the source region against the framebuffer bounds and
610*61046927SAndroid Build Coastguard Worker  * adjust the texture/dest position and size accordingly.
611*61046927SAndroid Build Coastguard Worker  *
612*61046927SAndroid Build Coastguard Worker  * \return GL_FALSE if region is totally clipped, GL_TRUE otherwise.
613*61046927SAndroid Build Coastguard Worker  */
614*61046927SAndroid Build Coastguard Worker GLboolean
_mesa_clip_copytexsubimage(const struct gl_context * ctx,GLint * destX,GLint * destY,GLint * srcX,GLint * srcY,GLsizei * width,GLsizei * height)615*61046927SAndroid Build Coastguard Worker _mesa_clip_copytexsubimage(const struct gl_context *ctx,
616*61046927SAndroid Build Coastguard Worker                            GLint *destX, GLint *destY,
617*61046927SAndroid Build Coastguard Worker                            GLint *srcX, GLint *srcY,
618*61046927SAndroid Build Coastguard Worker                            GLsizei *width, GLsizei *height)
619*61046927SAndroid Build Coastguard Worker {
620*61046927SAndroid Build Coastguard Worker    const struct gl_framebuffer *fb = ctx->ReadBuffer;
621*61046927SAndroid Build Coastguard Worker    const GLint srcX0 = *srcX, srcY0 = *srcY;
622*61046927SAndroid Build Coastguard Worker 
623*61046927SAndroid Build Coastguard Worker    if (_mesa_clip_to_region(0, 0, fb->Width, fb->Height,
624*61046927SAndroid Build Coastguard Worker                             srcX, srcY, width, height)) {
625*61046927SAndroid Build Coastguard Worker       *destX = *destX + *srcX - srcX0;
626*61046927SAndroid Build Coastguard Worker       *destY = *destY + *srcY - srcY0;
627*61046927SAndroid Build Coastguard Worker 
628*61046927SAndroid Build Coastguard Worker       return GL_TRUE;
629*61046927SAndroid Build Coastguard Worker    }
630*61046927SAndroid Build Coastguard Worker    else {
631*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
632*61046927SAndroid Build Coastguard Worker    }
633*61046927SAndroid Build Coastguard Worker }
634*61046927SAndroid Build Coastguard Worker 
635*61046927SAndroid Build Coastguard Worker 
636*61046927SAndroid Build Coastguard Worker 
637*61046927SAndroid Build Coastguard Worker /**
638*61046927SAndroid Build Coastguard Worker  * Clip the rectangle defined by (x, y, width, height) against the bounds
639*61046927SAndroid Build Coastguard Worker  * specified by [xmin, xmax) and [ymin, ymax).
640*61046927SAndroid Build Coastguard Worker  * \return GL_FALSE if rect is totally clipped, GL_TRUE otherwise.
641*61046927SAndroid Build Coastguard Worker  */
642*61046927SAndroid Build Coastguard Worker GLboolean
_mesa_clip_to_region(GLint xmin,GLint ymin,GLint xmax,GLint ymax,GLint * x,GLint * y,GLsizei * width,GLsizei * height)643*61046927SAndroid Build Coastguard Worker _mesa_clip_to_region(GLint xmin, GLint ymin,
644*61046927SAndroid Build Coastguard Worker                      GLint xmax, GLint ymax,
645*61046927SAndroid Build Coastguard Worker                      GLint *x, GLint *y,
646*61046927SAndroid Build Coastguard Worker                      GLsizei *width, GLsizei *height )
647*61046927SAndroid Build Coastguard Worker {
648*61046927SAndroid Build Coastguard Worker    /* left clipping */
649*61046927SAndroid Build Coastguard Worker    if (*x < xmin) {
650*61046927SAndroid Build Coastguard Worker       *width -= (xmin - *x);
651*61046927SAndroid Build Coastguard Worker       *x = xmin;
652*61046927SAndroid Build Coastguard Worker    }
653*61046927SAndroid Build Coastguard Worker 
654*61046927SAndroid Build Coastguard Worker    /* right clipping */
655*61046927SAndroid Build Coastguard Worker    if (*x + *width > xmax)
656*61046927SAndroid Build Coastguard Worker       *width -= (*x + *width - xmax);
657*61046927SAndroid Build Coastguard Worker 
658*61046927SAndroid Build Coastguard Worker    if (*width <= 0)
659*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
660*61046927SAndroid Build Coastguard Worker 
661*61046927SAndroid Build Coastguard Worker    /* bottom (or top) clipping */
662*61046927SAndroid Build Coastguard Worker    if (*y < ymin) {
663*61046927SAndroid Build Coastguard Worker       *height -= (ymin - *y);
664*61046927SAndroid Build Coastguard Worker       *y = ymin;
665*61046927SAndroid Build Coastguard Worker    }
666*61046927SAndroid Build Coastguard Worker 
667*61046927SAndroid Build Coastguard Worker    /* top (or bottom) clipping */
668*61046927SAndroid Build Coastguard Worker    if (*y + *height > ymax)
669*61046927SAndroid Build Coastguard Worker       *height -= (*y + *height - ymax);
670*61046927SAndroid Build Coastguard Worker 
671*61046927SAndroid Build Coastguard Worker    if (*height <= 0)
672*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
673*61046927SAndroid Build Coastguard Worker 
674*61046927SAndroid Build Coastguard Worker    return GL_TRUE;
675*61046927SAndroid Build Coastguard Worker }
676*61046927SAndroid Build Coastguard Worker 
677*61046927SAndroid Build Coastguard Worker 
678*61046927SAndroid Build Coastguard Worker /**
679*61046927SAndroid Build Coastguard Worker  * Clip dst coords against Xmax (or Ymax).
680*61046927SAndroid Build Coastguard Worker  */
681*61046927SAndroid Build Coastguard Worker static inline void
clip_right_or_top(GLint * srcX0,GLint * srcX1,GLint * dstX0,GLint * dstX1,GLint maxValue)682*61046927SAndroid Build Coastguard Worker clip_right_or_top(GLint *srcX0, GLint *srcX1,
683*61046927SAndroid Build Coastguard Worker                   GLint *dstX0, GLint *dstX1,
684*61046927SAndroid Build Coastguard Worker                   GLint maxValue)
685*61046927SAndroid Build Coastguard Worker {
686*61046927SAndroid Build Coastguard Worker    GLfloat t, bias;
687*61046927SAndroid Build Coastguard Worker 
688*61046927SAndroid Build Coastguard Worker    if (*dstX1 > maxValue) {
689*61046927SAndroid Build Coastguard Worker       /* X1 outside right edge */
690*61046927SAndroid Build Coastguard Worker       assert(*dstX0 < maxValue); /* X0 should be inside right edge */
691*61046927SAndroid Build Coastguard Worker       t = (GLfloat) (maxValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0);
692*61046927SAndroid Build Coastguard Worker       /* chop off [t, 1] part */
693*61046927SAndroid Build Coastguard Worker       assert(t >= 0.0 && t <= 1.0);
694*61046927SAndroid Build Coastguard Worker       *dstX1 = maxValue;
695*61046927SAndroid Build Coastguard Worker       bias = (*srcX0 < *srcX1) ? 0.5F : -0.5F;
696*61046927SAndroid Build Coastguard Worker       *srcX1 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias);
697*61046927SAndroid Build Coastguard Worker    }
698*61046927SAndroid Build Coastguard Worker    else if (*dstX0 > maxValue) {
699*61046927SAndroid Build Coastguard Worker       /* X0 outside right edge */
700*61046927SAndroid Build Coastguard Worker       assert(*dstX1 < maxValue); /* X1 should be inside right edge */
701*61046927SAndroid Build Coastguard Worker       t = (GLfloat) (maxValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1);
702*61046927SAndroid Build Coastguard Worker       /* chop off [t, 1] part */
703*61046927SAndroid Build Coastguard Worker       assert(t >= 0.0 && t <= 1.0);
704*61046927SAndroid Build Coastguard Worker       *dstX0 = maxValue;
705*61046927SAndroid Build Coastguard Worker       bias = (*srcX0 < *srcX1) ? -0.5F : 0.5F;
706*61046927SAndroid Build Coastguard Worker       *srcX0 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias);
707*61046927SAndroid Build Coastguard Worker    }
708*61046927SAndroid Build Coastguard Worker }
709*61046927SAndroid Build Coastguard Worker 
710*61046927SAndroid Build Coastguard Worker 
711*61046927SAndroid Build Coastguard Worker /**
712*61046927SAndroid Build Coastguard Worker  * Clip dst coords against Xmin (or Ymin).
713*61046927SAndroid Build Coastguard Worker  */
714*61046927SAndroid Build Coastguard Worker static inline void
clip_left_or_bottom(GLint * srcX0,GLint * srcX1,GLint * dstX0,GLint * dstX1,GLint minValue)715*61046927SAndroid Build Coastguard Worker clip_left_or_bottom(GLint *srcX0, GLint *srcX1,
716*61046927SAndroid Build Coastguard Worker                     GLint *dstX0, GLint *dstX1,
717*61046927SAndroid Build Coastguard Worker                     GLint minValue)
718*61046927SAndroid Build Coastguard Worker {
719*61046927SAndroid Build Coastguard Worker    GLfloat t, bias;
720*61046927SAndroid Build Coastguard Worker 
721*61046927SAndroid Build Coastguard Worker    if (*dstX0 < minValue) {
722*61046927SAndroid Build Coastguard Worker       /* X0 outside left edge */
723*61046927SAndroid Build Coastguard Worker       assert(*dstX1 > minValue); /* X1 should be inside left edge */
724*61046927SAndroid Build Coastguard Worker       t = (GLfloat) (minValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0);
725*61046927SAndroid Build Coastguard Worker       /* chop off [0, t] part */
726*61046927SAndroid Build Coastguard Worker       assert(t >= 0.0 && t <= 1.0);
727*61046927SAndroid Build Coastguard Worker       *dstX0 = minValue;
728*61046927SAndroid Build Coastguard Worker       bias = (*srcX0 < *srcX1) ? 0.5F : -0.5F;
729*61046927SAndroid Build Coastguard Worker       *srcX0 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias);
730*61046927SAndroid Build Coastguard Worker    }
731*61046927SAndroid Build Coastguard Worker    else if (*dstX1 < minValue) {
732*61046927SAndroid Build Coastguard Worker       /* X1 outside left edge */
733*61046927SAndroid Build Coastguard Worker       assert(*dstX0 > minValue); /* X0 should be inside left edge */
734*61046927SAndroid Build Coastguard Worker       t = (GLfloat) (minValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1);
735*61046927SAndroid Build Coastguard Worker       /* chop off [0, t] part */
736*61046927SAndroid Build Coastguard Worker       assert(t >= 0.0 && t <= 1.0);
737*61046927SAndroid Build Coastguard Worker       *dstX1 = minValue;
738*61046927SAndroid Build Coastguard Worker       bias = (*srcX0 < *srcX1) ? -0.5F : 0.5F;
739*61046927SAndroid Build Coastguard Worker       *srcX1 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias);
740*61046927SAndroid Build Coastguard Worker    }
741*61046927SAndroid Build Coastguard Worker }
742*61046927SAndroid Build Coastguard Worker 
743*61046927SAndroid Build Coastguard Worker 
744*61046927SAndroid Build Coastguard Worker /**
745*61046927SAndroid Build Coastguard Worker  * Do clipping of blit src/dest rectangles.
746*61046927SAndroid Build Coastguard Worker  * The dest rect is clipped against both the buffer bounds and scissor bounds.
747*61046927SAndroid Build Coastguard Worker  * The src rect is just clipped against the buffer bounds.
748*61046927SAndroid Build Coastguard Worker  *
749*61046927SAndroid Build Coastguard Worker  * When either the src or dest rect is clipped, the other is also clipped
750*61046927SAndroid Build Coastguard Worker  * proportionately!
751*61046927SAndroid Build Coastguard Worker  *
752*61046927SAndroid Build Coastguard Worker  * Note that X0 need not be less than X1 (same for Y) for either the source
753*61046927SAndroid Build Coastguard Worker  * and dest rects.  That makes the clipping a little trickier.
754*61046927SAndroid Build Coastguard Worker  *
755*61046927SAndroid Build Coastguard Worker  * \return GL_TRUE if anything is left to draw, GL_FALSE if totally clipped
756*61046927SAndroid Build Coastguard Worker  */
757*61046927SAndroid Build Coastguard Worker GLboolean
_mesa_clip_blit(struct gl_context * ctx,const struct gl_framebuffer * readFb,const struct gl_framebuffer * drawFb,GLint * srcX0,GLint * srcY0,GLint * srcX1,GLint * srcY1,GLint * dstX0,GLint * dstY0,GLint * dstX1,GLint * dstY1)758*61046927SAndroid Build Coastguard Worker _mesa_clip_blit(struct gl_context *ctx,
759*61046927SAndroid Build Coastguard Worker                 const struct gl_framebuffer *readFb,
760*61046927SAndroid Build Coastguard Worker                 const struct gl_framebuffer *drawFb,
761*61046927SAndroid Build Coastguard Worker                 GLint *srcX0, GLint *srcY0, GLint *srcX1, GLint *srcY1,
762*61046927SAndroid Build Coastguard Worker                 GLint *dstX0, GLint *dstY0, GLint *dstX1, GLint *dstY1)
763*61046927SAndroid Build Coastguard Worker {
764*61046927SAndroid Build Coastguard Worker    const GLint srcXmin = 0;
765*61046927SAndroid Build Coastguard Worker    const GLint srcXmax = readFb->Width;
766*61046927SAndroid Build Coastguard Worker    const GLint srcYmin = 0;
767*61046927SAndroid Build Coastguard Worker    const GLint srcYmax = readFb->Height;
768*61046927SAndroid Build Coastguard Worker 
769*61046927SAndroid Build Coastguard Worker    /* these include scissor bounds */
770*61046927SAndroid Build Coastguard Worker    const GLint dstXmin = drawFb->_Xmin;
771*61046927SAndroid Build Coastguard Worker    const GLint dstXmax = drawFb->_Xmax;
772*61046927SAndroid Build Coastguard Worker    const GLint dstYmin = drawFb->_Ymin;
773*61046927SAndroid Build Coastguard Worker    const GLint dstYmax = drawFb->_Ymax;
774*61046927SAndroid Build Coastguard Worker 
775*61046927SAndroid Build Coastguard Worker    /*
776*61046927SAndroid Build Coastguard Worker    printf("PreClipX:  src: %d .. %d  dst: %d .. %d\n",
777*61046927SAndroid Build Coastguard Worker           *srcX0, *srcX1, *dstX0, *dstX1);
778*61046927SAndroid Build Coastguard Worker    printf("PreClipY:  src: %d .. %d  dst: %d .. %d\n",
779*61046927SAndroid Build Coastguard Worker           *srcY0, *srcY1, *dstY0, *dstY1);
780*61046927SAndroid Build Coastguard Worker    */
781*61046927SAndroid Build Coastguard Worker 
782*61046927SAndroid Build Coastguard Worker    /* trivial rejection tests */
783*61046927SAndroid Build Coastguard Worker    if (*dstX0 == *dstX1)
784*61046927SAndroid Build Coastguard Worker       return GL_FALSE; /* no width */
785*61046927SAndroid Build Coastguard Worker    if (*dstX0 <= dstXmin && *dstX1 <= dstXmin)
786*61046927SAndroid Build Coastguard Worker       return GL_FALSE; /* totally out (left) of bounds */
787*61046927SAndroid Build Coastguard Worker    if (*dstX0 >= dstXmax && *dstX1 >= dstXmax)
788*61046927SAndroid Build Coastguard Worker       return GL_FALSE; /* totally out (right) of bounds */
789*61046927SAndroid Build Coastguard Worker 
790*61046927SAndroid Build Coastguard Worker    if (*dstY0 == *dstY1)
791*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
792*61046927SAndroid Build Coastguard Worker    if (*dstY0 <= dstYmin && *dstY1 <= dstYmin)
793*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
794*61046927SAndroid Build Coastguard Worker    if (*dstY0 >= dstYmax && *dstY1 >= dstYmax)
795*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
796*61046927SAndroid Build Coastguard Worker 
797*61046927SAndroid Build Coastguard Worker    if (*srcX0 == *srcX1)
798*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
799*61046927SAndroid Build Coastguard Worker    if (*srcX0 <= srcXmin && *srcX1 <= srcXmin)
800*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
801*61046927SAndroid Build Coastguard Worker    if (*srcX0 >= srcXmax && *srcX1 >= srcXmax)
802*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
803*61046927SAndroid Build Coastguard Worker 
804*61046927SAndroid Build Coastguard Worker    if (*srcY0 == *srcY1)
805*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
806*61046927SAndroid Build Coastguard Worker    if (*srcY0 <= srcYmin && *srcY1 <= srcYmin)
807*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
808*61046927SAndroid Build Coastguard Worker    if (*srcY0 >= srcYmax && *srcY1 >= srcYmax)
809*61046927SAndroid Build Coastguard Worker       return GL_FALSE;
810*61046927SAndroid Build Coastguard Worker 
811*61046927SAndroid Build Coastguard Worker    /*
812*61046927SAndroid Build Coastguard Worker     * dest clip
813*61046927SAndroid Build Coastguard Worker     */
814*61046927SAndroid Build Coastguard Worker    clip_right_or_top(srcX0, srcX1, dstX0, dstX1, dstXmax);
815*61046927SAndroid Build Coastguard Worker    clip_right_or_top(srcY0, srcY1, dstY0, dstY1, dstYmax);
816*61046927SAndroid Build Coastguard Worker    clip_left_or_bottom(srcX0, srcX1, dstX0, dstX1, dstXmin);
817*61046927SAndroid Build Coastguard Worker    clip_left_or_bottom(srcY0, srcY1, dstY0, dstY1, dstYmin);
818*61046927SAndroid Build Coastguard Worker 
819*61046927SAndroid Build Coastguard Worker    /*
820*61046927SAndroid Build Coastguard Worker     * src clip (just swap src/dst values from above)
821*61046927SAndroid Build Coastguard Worker     */
822*61046927SAndroid Build Coastguard Worker    clip_right_or_top(dstX0, dstX1, srcX0, srcX1, srcXmax);
823*61046927SAndroid Build Coastguard Worker    clip_right_or_top(dstY0, dstY1, srcY0, srcY1, srcYmax);
824*61046927SAndroid Build Coastguard Worker    clip_left_or_bottom(dstX0, dstX1, srcX0, srcX1, srcXmin);
825*61046927SAndroid Build Coastguard Worker    clip_left_or_bottom(dstY0, dstY1, srcY0, srcY1, srcYmin);
826*61046927SAndroid Build Coastguard Worker 
827*61046927SAndroid Build Coastguard Worker    /*
828*61046927SAndroid Build Coastguard Worker    printf("PostClipX: src: %d .. %d  dst: %d .. %d\n",
829*61046927SAndroid Build Coastguard Worker           *srcX0, *srcX1, *dstX0, *dstX1);
830*61046927SAndroid Build Coastguard Worker    printf("PostClipY: src: %d .. %d  dst: %d .. %d\n",
831*61046927SAndroid Build Coastguard Worker           *srcY0, *srcY1, *dstY0, *dstY1);
832*61046927SAndroid Build Coastguard Worker    */
833*61046927SAndroid Build Coastguard Worker 
834*61046927SAndroid Build Coastguard Worker    assert(*dstX0 >= dstXmin);
835*61046927SAndroid Build Coastguard Worker    assert(*dstX0 <= dstXmax);
836*61046927SAndroid Build Coastguard Worker    assert(*dstX1 >= dstXmin);
837*61046927SAndroid Build Coastguard Worker    assert(*dstX1 <= dstXmax);
838*61046927SAndroid Build Coastguard Worker 
839*61046927SAndroid Build Coastguard Worker    assert(*dstY0 >= dstYmin);
840*61046927SAndroid Build Coastguard Worker    assert(*dstY0 <= dstYmax);
841*61046927SAndroid Build Coastguard Worker    assert(*dstY1 >= dstYmin);
842*61046927SAndroid Build Coastguard Worker    assert(*dstY1 <= dstYmax);
843*61046927SAndroid Build Coastguard Worker 
844*61046927SAndroid Build Coastguard Worker    assert(*srcX0 >= srcXmin);
845*61046927SAndroid Build Coastguard Worker    assert(*srcX0 <= srcXmax);
846*61046927SAndroid Build Coastguard Worker    assert(*srcX1 >= srcXmin);
847*61046927SAndroid Build Coastguard Worker    assert(*srcX1 <= srcXmax);
848*61046927SAndroid Build Coastguard Worker 
849*61046927SAndroid Build Coastguard Worker    assert(*srcY0 >= srcYmin);
850*61046927SAndroid Build Coastguard Worker    assert(*srcY0 <= srcYmax);
851*61046927SAndroid Build Coastguard Worker    assert(*srcY1 >= srcYmin);
852*61046927SAndroid Build Coastguard Worker    assert(*srcY1 <= srcYmax);
853*61046927SAndroid Build Coastguard Worker 
854*61046927SAndroid Build Coastguard Worker    return GL_TRUE;
855*61046927SAndroid Build Coastguard Worker }
856*61046927SAndroid Build Coastguard Worker 
857*61046927SAndroid Build Coastguard Worker /**
858*61046927SAndroid Build Coastguard Worker  * Swap the bytes in a 2D image.
859*61046927SAndroid Build Coastguard Worker  *
860*61046927SAndroid Build Coastguard Worker  * using the packing information this swaps the bytes
861*61046927SAndroid Build Coastguard Worker  * according to the format and type of data being input.
862*61046927SAndroid Build Coastguard Worker  * It takes into a/c various packing parameters like
863*61046927SAndroid Build Coastguard Worker  * Alignment and RowLength.
864*61046927SAndroid Build Coastguard Worker  */
865*61046927SAndroid Build Coastguard Worker void
_mesa_swap_bytes_2d_image(GLenum format,GLenum type,const struct gl_pixelstore_attrib * packing,GLsizei width,GLsizei height,GLvoid * dst,const GLvoid * src)866*61046927SAndroid Build Coastguard Worker _mesa_swap_bytes_2d_image(GLenum format, GLenum type,
867*61046927SAndroid Build Coastguard Worker                           const struct gl_pixelstore_attrib *packing,
868*61046927SAndroid Build Coastguard Worker                           GLsizei width, GLsizei height,
869*61046927SAndroid Build Coastguard Worker                           GLvoid *dst, const GLvoid *src)
870*61046927SAndroid Build Coastguard Worker {
871*61046927SAndroid Build Coastguard Worker    GLint swapSize = _mesa_sizeof_packed_type(type);
872*61046927SAndroid Build Coastguard Worker 
873*61046927SAndroid Build Coastguard Worker    assert(packing->SwapBytes);
874*61046927SAndroid Build Coastguard Worker 
875*61046927SAndroid Build Coastguard Worker    if (swapSize == 2 || swapSize == 4) {
876*61046927SAndroid Build Coastguard Worker       int swapsPerPixel = _mesa_bytes_per_pixel(format, type) / swapSize;
877*61046927SAndroid Build Coastguard Worker       int stride = _mesa_image_row_stride(packing, width, format, type);
878*61046927SAndroid Build Coastguard Worker       int row;
879*61046927SAndroid Build Coastguard Worker       uint8_t *dstrow;
880*61046927SAndroid Build Coastguard Worker       const uint8_t *srcrow;
881*61046927SAndroid Build Coastguard Worker       assert(swapsPerPixel > 0);
882*61046927SAndroid Build Coastguard Worker       assert(_mesa_bytes_per_pixel(format, type) % swapSize == 0);
883*61046927SAndroid Build Coastguard Worker       dstrow = dst;
884*61046927SAndroid Build Coastguard Worker       srcrow = src;
885*61046927SAndroid Build Coastguard Worker       for (row = 0; row < height; row++) {
886*61046927SAndroid Build Coastguard Worker          if (swapSize == 2)
887*61046927SAndroid Build Coastguard Worker             swap2_copy((GLushort *)dstrow, (GLushort *)srcrow, width * swapsPerPixel);
888*61046927SAndroid Build Coastguard Worker          else if (swapSize == 4)
889*61046927SAndroid Build Coastguard Worker             swap4_copy((GLuint *)dstrow, (GLuint *)srcrow, width * swapsPerPixel);
890*61046927SAndroid Build Coastguard Worker          dstrow += stride;
891*61046927SAndroid Build Coastguard Worker          srcrow += stride;
892*61046927SAndroid Build Coastguard Worker       }
893*61046927SAndroid Build Coastguard Worker    }
894*61046927SAndroid Build Coastguard Worker }
895