1afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach/*
2afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach * Mesa 3-D graphics library
35e3bc0c2a2bcdf59949410f94c9b705fc1281ce8Jouk Jansen *
418d2822905ac3187318bd662f80c2836bdfa7c1fBrian Paul * Copyright (C) 1999-2008  Brian Paul   All Rights Reserved.
5995456f9305593005f8466520314ee087f3d422aBrian Paul * Copyright (C) 2009  VMware, Inc.  All Rights Reserved.
65e3bc0c2a2bcdf59949410f94c9b705fc1281ce8Jouk Jansen *
7afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach * Permission is hereby granted, free of charge, to any person obtaining a
8afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach * copy of this software and associated documentation files (the "Software"),
9afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach * to deal in the Software without restriction, including without limitation
10afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach * and/or sell copies of the Software, and to permit persons to whom the
12afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach * Software is furnished to do so, subject to the following conditions:
135e3bc0c2a2bcdf59949410f94c9b705fc1281ce8Jouk Jansen *
14afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach * The above copyright notice and this permission notice shall be included
15afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach * in all copies or substantial portions of the Software.
165e3bc0c2a2bcdf59949410f94c9b705fc1281ce8Jouk Jansen *
17afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
203d8d5b298a268b119d840bc9bae0ee9e0c9244a9Kenneth Graunke * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
213d8d5b298a268b119d840bc9bae0ee9e0c9244a9Kenneth Graunke * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
223d8d5b298a268b119d840bc9bae0ee9e0c9244a9Kenneth Graunke * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
233d8d5b298a268b119d840bc9bae0ee9e0c9244a9Kenneth Graunke * OTHER DEALINGS IN THE SOFTWARE.
24afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach */
25afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach
266dc85575000127630489b407c50a4b3ea87c9acbKeith Whitwell
27f959f6e1dc27c71fc0ccc56e09b29101b3bf3b97Brian Paul/**
28f959f6e1dc27c71fc0ccc56e09b29101b3bf3b97Brian Paul * \file image.c
29f959f6e1dc27c71fc0ccc56e09b29101b3bf3b97Brian Paul * Image handling.
30f959f6e1dc27c71fc0ccc56e09b29101b3bf3b97Brian Paul */
31f959f6e1dc27c71fc0ccc56e09b29101b3bf3b97Brian Paul
32f959f6e1dc27c71fc0ccc56e09b29101b3bf3b97Brian Paul
33fbd8f212c3866ec98c1d8c9d3db3ddb7e7c479a5Brian Paul#include "glheader.h"
34c893a015d8a50a38cd3f727d99835e7e7e2ccea9Brian Paul#include "colormac.h"
35a1287f549a3e6527b8cf3bf5b5f563ba63c6f48cBrian Paul#include "glformats.h"
36afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach#include "image.h"
373c63452e64df7e10aa073c6c3b9492b1d7dabbb8Brian Paul#include "imports.h"
38afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach#include "macros.h"
390117da40cd7edd3d165bb28569c289b37eca12b9Vinson Lee#include "mtypes.h"
40afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach
41afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach
4227558a160a9fe91745728d7626995cd88f8fe339Brian Paul
436dc85575000127630489b407c50a4b3ea87c9acbKeith Whitwell/**
44a177b30f1f2a74c14a649e9990eaab8826523c69Iago Toral Quiroga * Flip the order of the 2 bytes in each word in the given array (src) and
45a177b30f1f2a74c14a649e9990eaab8826523c69Iago Toral Quiroga * store the result in another array (dst). For in-place byte-swapping this
46a177b30f1f2a74c14a649e9990eaab8826523c69Iago Toral Quiroga * function can be called with the same array for src and dst.
476dc85575000127630489b407c50a4b3ea87c9acbKeith Whitwell *
48a177b30f1f2a74c14a649e9990eaab8826523c69Iago Toral Quiroga * \param dst the array where byte-swapped data will be stored.
49a177b30f1f2a74c14a649e9990eaab8826523c69Iago Toral Quiroga * \param src the array with the source data we want to byte-swap.
506dc85575000127630489b407c50a4b3ea87c9acbKeith Whitwell * \param n number of words.
51afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach */
520ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airliestatic void
530ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlieswap2_copy( GLushort *dst, GLushort *src, GLuint n )
54afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach{
55f0707c789a4c8f02b9b9f51012bd41691779e166Brian Paul   GLuint i;
56f0707c789a4c8f02b9b9f51012bd41691779e166Brian Paul   for (i = 0; i < n; i++) {
57a177b30f1f2a74c14a649e9990eaab8826523c69Iago Toral Quiroga      dst[i] = (src[i] >> 8) | ((src[i] << 8) & 0xff00);
58afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach   }
59afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach}
60afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach
610ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlievoid
620ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie_mesa_swap2(GLushort *p, GLuint n)
630ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie{
640ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie   swap2_copy(p, p, n);
650ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie}
66afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach
67afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach/*
68a177b30f1f2a74c14a649e9990eaab8826523c69Iago Toral Quiroga * Flip the order of the 4 bytes in each word in the given array (src) and
69a177b30f1f2a74c14a649e9990eaab8826523c69Iago Toral Quiroga * store the result in another array (dst). For in-place byte-swapping this
70a177b30f1f2a74c14a649e9990eaab8826523c69Iago Toral Quiroga * function can be called with the same array for src and dst.
71a177b30f1f2a74c14a649e9990eaab8826523c69Iago Toral Quiroga *
72a177b30f1f2a74c14a649e9990eaab8826523c69Iago Toral Quiroga * \param dst the array where byte-swapped data will be stored.
73a177b30f1f2a74c14a649e9990eaab8826523c69Iago Toral Quiroga * \param src the array with the source data we want to byte-swap.
74a177b30f1f2a74c14a649e9990eaab8826523c69Iago Toral Quiroga * \param n number of words.
75afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach */
760ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airliestatic void
770ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlieswap4_copy( GLuint *dst, GLuint *src, GLuint n )
78afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach{
79f0707c789a4c8f02b9b9f51012bd41691779e166Brian Paul   GLuint i, a, b;
80f0707c789a4c8f02b9b9f51012bd41691779e166Brian Paul   for (i = 0; i < n; i++) {
81a177b30f1f2a74c14a649e9990eaab8826523c69Iago Toral Quiroga      b = src[i];
82afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach      a =  (b >> 24)
83afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach	| ((b >> 8) & 0xff00)
84afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach	| ((b << 8) & 0xff0000)
85afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach	| ((b << 24) & 0xff000000);
86a177b30f1f2a74c14a649e9990eaab8826523c69Iago Toral Quiroga      dst[i] = a;
87afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach   }
88afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach}
89afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach
900ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlievoid
910ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie_mesa_swap4(GLuint *p, GLuint n)
920ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie{
930ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie   swap4_copy(p, p, n);
940ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie}
95afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach
966dc85575000127630489b407c50a4b3ea87c9acbKeith Whitwell/**
974a2b9b53052a74e71aac59592e95e3910b5b7da5nobled * Return the byte offset of a specific pixel in an image (1D, 2D or 3D).
986dc85575000127630489b407c50a4b3ea87c9acbKeith Whitwell *
996dc85575000127630489b407c50a4b3ea87c9acbKeith Whitwell * Pixel unpacking/packing parameters are observed according to \p packing.
1006dc85575000127630489b407c50a4b3ea87c9acbKeith Whitwell *
10160909388ab136d849d99eab49e782a53772a618fBrian Paul * \param dimensions either 1, 2 or 3 to indicate dimensionality of image
102f22421e9b9ae08512d02927c85e8a7c69867856fnobled * \param packing  the pixelstore attributes
10360909388ab136d849d99eab49e782a53772a618fBrian Paul * \param width  the image width
104f22421e9b9ae08512d02927c85e8a7c69867856fnobled * \param height  the image height
105f22421e9b9ae08512d02927c85e8a7c69867856fnobled * \param format  the pixel format (must be validated beforehand)
106f22421e9b9ae08512d02927c85e8a7c69867856fnobled * \param type  the pixel data type (must be validated beforehand)
10760909388ab136d849d99eab49e782a53772a618fBrian Paul * \param img  which image in the volume (0 for 1D or 2D images)
10860909388ab136d849d99eab49e782a53772a618fBrian Paul * \param row  row of pixel in the image (0 for 1D images)
10960909388ab136d849d99eab49e782a53772a618fBrian Paul * \param column column of pixel in the image
1104a2b9b53052a74e71aac59592e95e3910b5b7da5nobled *
1114a2b9b53052a74e71aac59592e95e3910b5b7da5nobled * \return offset of pixel.
1126dc85575000127630489b407c50a4b3ea87c9acbKeith Whitwell *
1136dc85575000127630489b407c50a4b3ea87c9acbKeith Whitwell * \sa gl_pixelstore_attrib.
114afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach */
1154a2b9b53052a74e71aac59592e95e3910b5b7da5nobledGLintptr
1164a2b9b53052a74e71aac59592e95e3910b5b7da5nobled_mesa_image_offset( GLuint dimensions,
1174a2b9b53052a74e71aac59592e95e3910b5b7da5nobled                    const struct gl_pixelstore_attrib *packing,
1184a2b9b53052a74e71aac59592e95e3910b5b7da5nobled                    GLsizei width, GLsizei height,
1194a2b9b53052a74e71aac59592e95e3910b5b7da5nobled                    GLenum format, GLenum type,
1204a2b9b53052a74e71aac59592e95e3910b5b7da5nobled                    GLint img, GLint row, GLint column )
121afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach{
122afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach   GLint alignment;        /* 1, 2 or 4 */
123afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach   GLint pixels_per_row;
124afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach   GLint rows_per_image;
125afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach   GLint skiprows;
126afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach   GLint skippixels;
127afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach   GLint skipimages;       /* for 3-D volume images */
1284a2b9b53052a74e71aac59592e95e3910b5b7da5nobled   GLintptr offset;
129afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach
130bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner   assert(dimensions >= 1 && dimensions <= 3);
13160909388ab136d849d99eab49e782a53772a618fBrian Paul
132afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach   alignment = packing->Alignment;
133afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach   if (packing->RowLength > 0) {
134afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach      pixels_per_row = packing->RowLength;
135afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach   }
136afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach   else {
137afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach      pixels_per_row = width;
138afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach   }
139afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach   if (packing->ImageHeight > 0) {
140afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach      rows_per_image = packing->ImageHeight;
141afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach   }
142afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach   else {
143afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach      rows_per_image = height;
144afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach   }
14560909388ab136d849d99eab49e782a53772a618fBrian Paul
146afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach   skippixels = packing->SkipPixels;
14760909388ab136d849d99eab49e782a53772a618fBrian Paul   /* Note: SKIP_ROWS _is_ used for 1D images */
14860909388ab136d849d99eab49e782a53772a618fBrian Paul   skiprows = packing->SkipRows;
14960909388ab136d849d99eab49e782a53772a618fBrian Paul   /* Note: SKIP_IMAGES is only used for 3D images */
15060909388ab136d849d99eab49e782a53772a618fBrian Paul   skipimages = (dimensions == 3) ? packing->SkipImages : 0;
151afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach
152450e917c9d71f696bca2ba11960a521e64385ec2Brian Paul   if (type == GL_BITMAP) {
153afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach      /* BITMAP data */
1546510e0734563ff8d30e45b8781153367db15cc5bNicolai Hähnle      GLintptr bytes_per_row;
1556510e0734563ff8d30e45b8781153367db15cc5bNicolai Hähnle      GLintptr bytes_per_image;
156f22421e9b9ae08512d02927c85e8a7c69867856fnobled      /* components per pixel for color or stencil index: */
157f22421e9b9ae08512d02927c85e8a7c69867856fnobled      const GLint comp_per_pixel = 1;
158afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach
159f22421e9b9ae08512d02927c85e8a7c69867856fnobled      /* The pixel type and format should have been error checked earlier */
160f22421e9b9ae08512d02927c85e8a7c69867856fnobled      assert(format == GL_COLOR_INDEX || format == GL_STENCIL_INDEX);
161afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach
162afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach      bytes_per_row = alignment
163818585b9f9ccd55b992e35f4d74120f0e879559fFrancisco Jerez                    * DIV_ROUND_UP( comp_per_pixel*pixels_per_row, 8*alignment );
164afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach
165afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach      bytes_per_image = bytes_per_row * rows_per_image;
166afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach
1674a2b9b53052a74e71aac59592e95e3910b5b7da5nobled      offset = (skipimages + img) * bytes_per_image
168afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach                 + (skiprows + row) * bytes_per_row
169afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach                 + (skippixels + column) / 8;
170afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach   }
171afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach   else {
172afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach      /* Non-BITMAP data */
1736510e0734563ff8d30e45b8781153367db15cc5bNicolai Hähnle      GLintptr bytes_per_pixel, bytes_per_row, remainder, bytes_per_image;
1746510e0734563ff8d30e45b8781153367db15cc5bNicolai Hähnle      GLintptr topOfImage;
175afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach
176b7d076fc96ac27117421653a043d00a95f789d24Brian Paul      bytes_per_pixel = _mesa_bytes_per_pixel( format, type );
177afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach
178afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach      /* The pixel type and format should have been error checked earlier */
179afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach      assert(bytes_per_pixel > 0);
180afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach
181afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach      bytes_per_row = pixels_per_row * bytes_per_pixel;
182afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach      remainder = bytes_per_row % alignment;
183afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach      if (remainder > 0)
184afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach         bytes_per_row += (alignment - remainder);
185afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach
186bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner      assert(bytes_per_row % alignment == 0);
187afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach
188afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach      bytes_per_image = bytes_per_row * rows_per_image;
189afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach
190551b65f13754e6760e5c272ff86f8873c9c13e5cBrian Paul      if (packing->Invert) {
191551b65f13754e6760e5c272ff86f8873c9c13e5cBrian Paul         /* set pixel_addr to the last row */
192551b65f13754e6760e5c272ff86f8873c9c13e5cBrian Paul         topOfImage = bytes_per_row * (height - 1);
193551b65f13754e6760e5c272ff86f8873c9c13e5cBrian Paul         bytes_per_row = -bytes_per_row;
194551b65f13754e6760e5c272ff86f8873c9c13e5cBrian Paul      }
195551b65f13754e6760e5c272ff86f8873c9c13e5cBrian Paul      else {
196551b65f13754e6760e5c272ff86f8873c9c13e5cBrian Paul         topOfImage = 0;
197551b65f13754e6760e5c272ff86f8873c9c13e5cBrian Paul      }
198551b65f13754e6760e5c272ff86f8873c9c13e5cBrian Paul
199afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach      /* compute final pixel address */
2004a2b9b53052a74e71aac59592e95e3910b5b7da5nobled      offset = (skipimages + img) * bytes_per_image
201551b65f13754e6760e5c272ff86f8873c9c13e5cBrian Paul                 + topOfImage
202afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach                 + (skiprows + row) * bytes_per_row
203afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach                 + (skippixels + column) * bytes_per_pixel;
204afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach   }
205afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach
2064a2b9b53052a74e71aac59592e95e3910b5b7da5nobled   return offset;
2074a2b9b53052a74e71aac59592e95e3910b5b7da5nobled}
2084a2b9b53052a74e71aac59592e95e3910b5b7da5nobled
2094a2b9b53052a74e71aac59592e95e3910b5b7da5nobled
2104a2b9b53052a74e71aac59592e95e3910b5b7da5nobled/**
2114a2b9b53052a74e71aac59592e95e3910b5b7da5nobled * Return the address of a specific pixel in an image (1D, 2D or 3D).
2124a2b9b53052a74e71aac59592e95e3910b5b7da5nobled *
2134a2b9b53052a74e71aac59592e95e3910b5b7da5nobled * Pixel unpacking/packing parameters are observed according to \p packing.
2144a2b9b53052a74e71aac59592e95e3910b5b7da5nobled *
2154a2b9b53052a74e71aac59592e95e3910b5b7da5nobled * \param dimensions either 1, 2 or 3 to indicate dimensionality of image
2164a2b9b53052a74e71aac59592e95e3910b5b7da5nobled * \param packing  the pixelstore attributes
2174a2b9b53052a74e71aac59592e95e3910b5b7da5nobled * \param image  starting address of image data
2184a2b9b53052a74e71aac59592e95e3910b5b7da5nobled * \param width  the image width
2194a2b9b53052a74e71aac59592e95e3910b5b7da5nobled * \param height  the image height
2204a2b9b53052a74e71aac59592e95e3910b5b7da5nobled * \param format  the pixel format (must be validated beforehand)
2214a2b9b53052a74e71aac59592e95e3910b5b7da5nobled * \param type  the pixel data type (must be validated beforehand)
2224a2b9b53052a74e71aac59592e95e3910b5b7da5nobled * \param img  which image in the volume (0 for 1D or 2D images)
2234a2b9b53052a74e71aac59592e95e3910b5b7da5nobled * \param row  row of pixel in the image (0 for 1D images)
2244a2b9b53052a74e71aac59592e95e3910b5b7da5nobled * \param column column of pixel in the image
2254a2b9b53052a74e71aac59592e95e3910b5b7da5nobled *
2264a2b9b53052a74e71aac59592e95e3910b5b7da5nobled * \return address of pixel.
2274a2b9b53052a74e71aac59592e95e3910b5b7da5nobled *
2284a2b9b53052a74e71aac59592e95e3910b5b7da5nobled * \sa gl_pixelstore_attrib.
2294a2b9b53052a74e71aac59592e95e3910b5b7da5nobled */
2304a2b9b53052a74e71aac59592e95e3910b5b7da5nobledGLvoid *
2314a2b9b53052a74e71aac59592e95e3910b5b7da5nobled_mesa_image_address( GLuint dimensions,
2324a2b9b53052a74e71aac59592e95e3910b5b7da5nobled                     const struct gl_pixelstore_attrib *packing,
2334a2b9b53052a74e71aac59592e95e3910b5b7da5nobled                     const GLvoid *image,
2344a2b9b53052a74e71aac59592e95e3910b5b7da5nobled                     GLsizei width, GLsizei height,
2354a2b9b53052a74e71aac59592e95e3910b5b7da5nobled                     GLenum format, GLenum type,
2364a2b9b53052a74e71aac59592e95e3910b5b7da5nobled                     GLint img, GLint row, GLint column )
2374a2b9b53052a74e71aac59592e95e3910b5b7da5nobled{
2384a2b9b53052a74e71aac59592e95e3910b5b7da5nobled   const GLubyte *addr = (const GLubyte *) image;
2394a2b9b53052a74e71aac59592e95e3910b5b7da5nobled
2404a2b9b53052a74e71aac59592e95e3910b5b7da5nobled   addr += _mesa_image_offset(dimensions, packing, width, height,
2414a2b9b53052a74e71aac59592e95e3910b5b7da5nobled                              format, type, img, row, column);
2424a2b9b53052a74e71aac59592e95e3910b5b7da5nobled
2434a2b9b53052a74e71aac59592e95e3910b5b7da5nobled   return (GLvoid *) addr;
244afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach}
245afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach
246afb833d4e89c312460a4ab9ed6a7a8ca4ebbfe1cJochen Gerlach
24760909388ab136d849d99eab49e782a53772a618fBrian PaulGLvoid *
24860909388ab136d849d99eab49e782a53772a618fBrian Paul_mesa_image_address1d( const struct gl_pixelstore_attrib *packing,
24960909388ab136d849d99eab49e782a53772a618fBrian Paul                       const GLvoid *image,
25060909388ab136d849d99eab49e782a53772a618fBrian Paul                       GLsizei width,
25160909388ab136d849d99eab49e782a53772a618fBrian Paul                       GLenum format, GLenum type,
25260909388ab136d849d99eab49e782a53772a618fBrian Paul                       GLint column )
25360909388ab136d849d99eab49e782a53772a618fBrian Paul{
25460909388ab136d849d99eab49e782a53772a618fBrian Paul   return _mesa_image_address(1, packing, image, width, 1,
25560909388ab136d849d99eab49e782a53772a618fBrian Paul                              format, type, 0, 0, column);
25660909388ab136d849d99eab49e782a53772a618fBrian Paul}
25760909388ab136d849d99eab49e782a53772a618fBrian Paul
25860909388ab136d849d99eab49e782a53772a618fBrian Paul
25960909388ab136d849d99eab49e782a53772a618fBrian PaulGLvoid *
26060909388ab136d849d99eab49e782a53772a618fBrian Paul_mesa_image_address2d( const struct gl_pixelstore_attrib *packing,
26160909388ab136d849d99eab49e782a53772a618fBrian Paul                       const GLvoid *image,
26260909388ab136d849d99eab49e782a53772a618fBrian Paul                       GLsizei width, GLsizei height,
26360909388ab136d849d99eab49e782a53772a618fBrian Paul                       GLenum format, GLenum type,
26460909388ab136d849d99eab49e782a53772a618fBrian Paul                       GLint row, GLint column )
26560909388ab136d849d99eab49e782a53772a618fBrian Paul{
26660909388ab136d849d99eab49e782a53772a618fBrian Paul   return _mesa_image_address(2, packing, image, width, height,
26760909388ab136d849d99eab49e782a53772a618fBrian Paul                              format, type, 0, row, column);
26860909388ab136d849d99eab49e782a53772a618fBrian Paul}
26960909388ab136d849d99eab49e782a53772a618fBrian Paul
27060909388ab136d849d99eab49e782a53772a618fBrian Paul
27160909388ab136d849d99eab49e782a53772a618fBrian PaulGLvoid *
27260909388ab136d849d99eab49e782a53772a618fBrian Paul_mesa_image_address3d( const struct gl_pixelstore_attrib *packing,
27360909388ab136d849d99eab49e782a53772a618fBrian Paul                       const GLvoid *image,
27460909388ab136d849d99eab49e782a53772a618fBrian Paul                       GLsizei width, GLsizei height,
27560909388ab136d849d99eab49e782a53772a618fBrian Paul                       GLenum format, GLenum type,
27660909388ab136d849d99eab49e782a53772a618fBrian Paul                       GLint img, GLint row, GLint column )
27760909388ab136d849d99eab49e782a53772a618fBrian Paul{
27860909388ab136d849d99eab49e782a53772a618fBrian Paul   return _mesa_image_address(3, packing, image, width, height,
27960909388ab136d849d99eab49e782a53772a618fBrian Paul                              format, type, img, row, column);
28060909388ab136d849d99eab49e782a53772a618fBrian Paul}
28160909388ab136d849d99eab49e782a53772a618fBrian Paul
28260909388ab136d849d99eab49e782a53772a618fBrian Paul
28360909388ab136d849d99eab49e782a53772a618fBrian Paul
2846dc85575000127630489b407c50a4b3ea87c9acbKeith Whitwell/**
28517fb7821d7cdc0ed211eaef013ee7798619a61d3Brian Paul * Compute the stride (in bytes) between image rows.
2866dc85575000127630489b407c50a4b3ea87c9acbKeith Whitwell *
2876dc85575000127630489b407c50a4b3ea87c9acbKeith Whitwell * \param packing the pixelstore attributes
2886dc85575000127630489b407c50a4b3ea87c9acbKeith Whitwell * \param width image width.
2896dc85575000127630489b407c50a4b3ea87c9acbKeith Whitwell * \param format pixel format.
2906dc85575000127630489b407c50a4b3ea87c9acbKeith Whitwell * \param type pixel data type.
2916dc85575000127630489b407c50a4b3ea87c9acbKeith Whitwell *
29217fb7821d7cdc0ed211eaef013ee7798619a61d3Brian Paul * \return the stride in bytes for the given parameters, or -1 if error
293ae40595b6943d41dfad0e9b500d5db70b2ad8c6eBrian Paul */
294ae40595b6943d41dfad0e9b500d5db70b2ad8c6eBrian PaulGLint
295ae40595b6943d41dfad0e9b500d5db70b2ad8c6eBrian Paul_mesa_image_row_stride( const struct gl_pixelstore_attrib *packing,
296ae40595b6943d41dfad0e9b500d5db70b2ad8c6eBrian Paul                        GLint width, GLenum format, GLenum type )
297ae40595b6943d41dfad0e9b500d5db70b2ad8c6eBrian Paul{
29817fb7821d7cdc0ed211eaef013ee7798619a61d3Brian Paul   GLint bytesPerRow, remainder;
29917fb7821d7cdc0ed211eaef013ee7798619a61d3Brian Paul
300bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner   assert(packing);
30117fb7821d7cdc0ed211eaef013ee7798619a61d3Brian Paul
302ae40595b6943d41dfad0e9b500d5db70b2ad8c6eBrian Paul   if (type == GL_BITMAP) {
303ae40595b6943d41dfad0e9b500d5db70b2ad8c6eBrian Paul      if (packing->RowLength == 0) {
30417fb7821d7cdc0ed211eaef013ee7798619a61d3Brian Paul         bytesPerRow = (width + 7) / 8;
305ae40595b6943d41dfad0e9b500d5db70b2ad8c6eBrian Paul      }
306ae40595b6943d41dfad0e9b500d5db70b2ad8c6eBrian Paul      else {
30717fb7821d7cdc0ed211eaef013ee7798619a61d3Brian Paul         bytesPerRow = (packing->RowLength + 7) / 8;
308551b65f13754e6760e5c272ff86f8873c9c13e5cBrian Paul      }
309ae40595b6943d41dfad0e9b500d5db70b2ad8c6eBrian Paul   }
310ae40595b6943d41dfad0e9b500d5db70b2ad8c6eBrian Paul   else {
311ae40595b6943d41dfad0e9b500d5db70b2ad8c6eBrian Paul      /* Non-BITMAP data */
312b7d076fc96ac27117421653a043d00a95f789d24Brian Paul      const GLint bytesPerPixel = _mesa_bytes_per_pixel(format, type);
313ae40595b6943d41dfad0e9b500d5db70b2ad8c6eBrian Paul      if (bytesPerPixel <= 0)
314ae40595b6943d41dfad0e9b500d5db70b2ad8c6eBrian Paul         return -1;  /* error */
315ae40595b6943d41dfad0e9b500d5db70b2ad8c6eBrian Paul      if (packing->RowLength == 0) {
316fbbac25ad304e09a4cde52bd09b4940ac4785623Brian Paul         bytesPerRow = bytesPerPixel * width;
317ae40595b6943d41dfad0e9b500d5db70b2ad8c6eBrian Paul      }
318ae40595b6943d41dfad0e9b500d5db70b2ad8c6eBrian Paul      else {
319fbbac25ad304e09a4cde52bd09b4940ac4785623Brian Paul         bytesPerRow = bytesPerPixel * packing->RowLength;
320ae40595b6943d41dfad0e9b500d5db70b2ad8c6eBrian Paul      }
321ae40595b6943d41dfad0e9b500d5db70b2ad8c6eBrian Paul   }
32217fb7821d7cdc0ed211eaef013ee7798619a61d3Brian Paul
32317fb7821d7cdc0ed211eaef013ee7798619a61d3Brian Paul   remainder = bytesPerRow % packing->Alignment;
32417fb7821d7cdc0ed211eaef013ee7798619a61d3Brian Paul   if (remainder > 0) {
32517fb7821d7cdc0ed211eaef013ee7798619a61d3Brian Paul      bytesPerRow += (packing->Alignment - remainder);
32617fb7821d7cdc0ed211eaef013ee7798619a61d3Brian Paul   }
32717fb7821d7cdc0ed211eaef013ee7798619a61d3Brian Paul
32817fb7821d7cdc0ed211eaef013ee7798619a61d3Brian Paul   if (packing->Invert) {
32917fb7821d7cdc0ed211eaef013ee7798619a61d3Brian Paul      /* negate the bytes per row (negative row stride) */
33017fb7821d7cdc0ed211eaef013ee7798619a61d3Brian Paul      bytesPerRow = -bytesPerRow;
33117fb7821d7cdc0ed211eaef013ee7798619a61d3Brian Paul   }
33217fb7821d7cdc0ed211eaef013ee7798619a61d3Brian Paul
33317fb7821d7cdc0ed211eaef013ee7798619a61d3Brian Paul   return bytesPerRow;
334ae40595b6943d41dfad0e9b500d5db70b2ad8c6eBrian Paul}
335ae40595b6943d41dfad0e9b500d5db70b2ad8c6eBrian Paul
336ae40595b6943d41dfad0e9b500d5db70b2ad8c6eBrian Paul
337ae40595b6943d41dfad0e9b500d5db70b2ad8c6eBrian Paul/*
338d488af5b34e390a9b81dac96053bd45f34ffffffBrian Paul * Compute the stride between images in a 3D texture (in bytes) for the given
339d488af5b34e390a9b81dac96053bd45f34ffffffBrian Paul * pixel packing parameters and image width, format and type.
340d488af5b34e390a9b81dac96053bd45f34ffffffBrian Paul */
341d488af5b34e390a9b81dac96053bd45f34ffffffBrian PaulGLint
342d488af5b34e390a9b81dac96053bd45f34ffffffBrian Paul_mesa_image_image_stride( const struct gl_pixelstore_attrib *packing,
343d488af5b34e390a9b81dac96053bd45f34ffffffBrian Paul                          GLint width, GLint height,
344d488af5b34e390a9b81dac96053bd45f34ffffffBrian Paul                          GLenum format, GLenum type )
345d488af5b34e390a9b81dac96053bd45f34ffffffBrian Paul{
346995456f9305593005f8466520314ee087f3d422aBrian Paul   GLint bytesPerRow, bytesPerImage, remainder;
347995456f9305593005f8466520314ee087f3d422aBrian Paul
348bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner   assert(packing);
349d488af5b34e390a9b81dac96053bd45f34ffffffBrian Paul
350995456f9305593005f8466520314ee087f3d422aBrian Paul   if (type == GL_BITMAP) {
351995456f9305593005f8466520314ee087f3d422aBrian Paul      if (packing->RowLength == 0) {
352995456f9305593005f8466520314ee087f3d422aBrian Paul         bytesPerRow = (width + 7) / 8;
353995456f9305593005f8466520314ee087f3d422aBrian Paul      }
354995456f9305593005f8466520314ee087f3d422aBrian Paul      else {
355995456f9305593005f8466520314ee087f3d422aBrian Paul         bytesPerRow = (packing->RowLength + 7) / 8;
356995456f9305593005f8466520314ee087f3d422aBrian Paul      }
357995456f9305593005f8466520314ee087f3d422aBrian Paul   }
358995456f9305593005f8466520314ee087f3d422aBrian Paul   else {
359d488af5b34e390a9b81dac96053bd45f34ffffffBrian Paul      const GLint bytesPerPixel = _mesa_bytes_per_pixel(format, type);
360d488af5b34e390a9b81dac96053bd45f34ffffffBrian Paul
361d488af5b34e390a9b81dac96053bd45f34ffffffBrian Paul      if (bytesPerPixel <= 0)
362d488af5b34e390a9b81dac96053bd45f34ffffffBrian Paul         return -1;  /* error */
363d488af5b34e390a9b81dac96053bd45f34ffffffBrian Paul      if (packing->RowLength == 0) {
364d488af5b34e390a9b81dac96053bd45f34ffffffBrian Paul         bytesPerRow = bytesPerPixel * width;
365d488af5b34e390a9b81dac96053bd45f34ffffffBrian Paul      }
366d488af5b34e390a9b81dac96053bd45f34ffffffBrian Paul      else {
367d488af5b34e390a9b81dac96053bd45f34ffffffBrian Paul         bytesPerRow = bytesPerPixel * packing->RowLength;
368d488af5b34e390a9b81dac96053bd45f34ffffffBrian Paul      }
369995456f9305593005f8466520314ee087f3d422aBrian Paul   }
370d488af5b34e390a9b81dac96053bd45f34ffffffBrian Paul
371995456f9305593005f8466520314ee087f3d422aBrian Paul   remainder = bytesPerRow % packing->Alignment;
372995456f9305593005f8466520314ee087f3d422aBrian Paul   if (remainder > 0)
373995456f9305593005f8466520314ee087f3d422aBrian Paul      bytesPerRow += (packing->Alignment - remainder);
374d488af5b34e390a9b81dac96053bd45f34ffffffBrian Paul
375995456f9305593005f8466520314ee087f3d422aBrian Paul   if (packing->ImageHeight == 0)
376995456f9305593005f8466520314ee087f3d422aBrian Paul      bytesPerImage = bytesPerRow * height;
377995456f9305593005f8466520314ee087f3d422aBrian Paul   else
378995456f9305593005f8466520314ee087f3d422aBrian Paul      bytesPerImage = bytesPerRow * packing->ImageHeight;
379995456f9305593005f8466520314ee087f3d422aBrian Paul
380995456f9305593005f8466520314ee087f3d422aBrian Paul   return bytesPerImage;
381d488af5b34e390a9b81dac96053bd45f34ffffffBrian Paul}
382d488af5b34e390a9b81dac96053bd45f34ffffffBrian Paul
383d488af5b34e390a9b81dac96053bd45f34ffffffBrian Paul
384116970154dc3bb148178e1a9fe38554fbbd133c8Brian Paul
385278e76832fc26678592368b7b89bfddc137e0e93Brian Paul/**
386278e76832fc26678592368b7b89bfddc137e0e93Brian Paul * "Expand" a bitmap from 1-bit per pixel to 8-bits per pixel.
387278e76832fc26678592368b7b89bfddc137e0e93Brian Paul * This is typically used to convert a bitmap into a GLubyte/pixel texture.
388278e76832fc26678592368b7b89bfddc137e0e93Brian Paul * "On" bits will set texels to \p onValue.
389278e76832fc26678592368b7b89bfddc137e0e93Brian Paul * "Off" bits will not modify texels.
390278e76832fc26678592368b7b89bfddc137e0e93Brian Paul * \param width  src bitmap width in pixels
391278e76832fc26678592368b7b89bfddc137e0e93Brian Paul * \param height  src bitmap height in pixels
392278e76832fc26678592368b7b89bfddc137e0e93Brian Paul * \param unpack  bitmap unpacking state
393278e76832fc26678592368b7b89bfddc137e0e93Brian Paul * \param bitmap  the src bitmap data
394278e76832fc26678592368b7b89bfddc137e0e93Brian Paul * \param destBuffer  start of dest buffer
395278e76832fc26678592368b7b89bfddc137e0e93Brian Paul * \param destStride  row stride in dest buffer
396278e76832fc26678592368b7b89bfddc137e0e93Brian Paul * \param onValue  if bit is 1, set destBuffer pixel to this value
397278e76832fc26678592368b7b89bfddc137e0e93Brian Paul */
398278e76832fc26678592368b7b89bfddc137e0e93Brian Paulvoid
399278e76832fc26678592368b7b89bfddc137e0e93Brian Paul_mesa_expand_bitmap(GLsizei width, GLsizei height,
400278e76832fc26678592368b7b89bfddc137e0e93Brian Paul                    const struct gl_pixelstore_attrib *unpack,
401278e76832fc26678592368b7b89bfddc137e0e93Brian Paul                    const GLubyte *bitmap,
402278e76832fc26678592368b7b89bfddc137e0e93Brian Paul                    GLubyte *destBuffer, GLint destStride,
403278e76832fc26678592368b7b89bfddc137e0e93Brian Paul                    GLubyte onValue)
404278e76832fc26678592368b7b89bfddc137e0e93Brian Paul{
405278e76832fc26678592368b7b89bfddc137e0e93Brian Paul   const GLubyte *srcRow = (const GLubyte *)
406278e76832fc26678592368b7b89bfddc137e0e93Brian Paul      _mesa_image_address2d(unpack, bitmap, width, height,
407278e76832fc26678592368b7b89bfddc137e0e93Brian Paul                            GL_COLOR_INDEX, GL_BITMAP, 0, 0);
408278e76832fc26678592368b7b89bfddc137e0e93Brian Paul   const GLint srcStride = _mesa_image_row_stride(unpack, width,
409278e76832fc26678592368b7b89bfddc137e0e93Brian Paul                                                  GL_COLOR_INDEX, GL_BITMAP);
410278e76832fc26678592368b7b89bfddc137e0e93Brian Paul   GLint row, col;
4110eb7b5c2a3f17d64e85247c1f4907ce20bc57a73Brian Paul   GLubyte *dstRow = destBuffer;
412278e76832fc26678592368b7b89bfddc137e0e93Brian Paul
413278e76832fc26678592368b7b89bfddc137e0e93Brian Paul   for (row = 0; row < height; row++) {
414278e76832fc26678592368b7b89bfddc137e0e93Brian Paul      const GLubyte *src = srcRow;
415278e76832fc26678592368b7b89bfddc137e0e93Brian Paul
416278e76832fc26678592368b7b89bfddc137e0e93Brian Paul      if (unpack->LsbFirst) {
417278e76832fc26678592368b7b89bfddc137e0e93Brian Paul         /* Lsb first */
418278e76832fc26678592368b7b89bfddc137e0e93Brian Paul         GLubyte mask = 1U << (unpack->SkipPixels & 0x7);
419278e76832fc26678592368b7b89bfddc137e0e93Brian Paul         for (col = 0; col < width; col++) {
420278e76832fc26678592368b7b89bfddc137e0e93Brian Paul
421278e76832fc26678592368b7b89bfddc137e0e93Brian Paul            if (*src & mask) {
4220eb7b5c2a3f17d64e85247c1f4907ce20bc57a73Brian Paul               dstRow[col] = onValue;
423278e76832fc26678592368b7b89bfddc137e0e93Brian Paul            }
424278e76832fc26678592368b7b89bfddc137e0e93Brian Paul
425278e76832fc26678592368b7b89bfddc137e0e93Brian Paul            if (mask == 128U) {
426278e76832fc26678592368b7b89bfddc137e0e93Brian Paul               src++;
427278e76832fc26678592368b7b89bfddc137e0e93Brian Paul               mask = 1U;
428278e76832fc26678592368b7b89bfddc137e0e93Brian Paul            }
429278e76832fc26678592368b7b89bfddc137e0e93Brian Paul            else {
430278e76832fc26678592368b7b89bfddc137e0e93Brian Paul               mask = mask << 1;
431278e76832fc26678592368b7b89bfddc137e0e93Brian Paul            }
432278e76832fc26678592368b7b89bfddc137e0e93Brian Paul         }
433278e76832fc26678592368b7b89bfddc137e0e93Brian Paul
434278e76832fc26678592368b7b89bfddc137e0e93Brian Paul         /* get ready for next row */
435278e76832fc26678592368b7b89bfddc137e0e93Brian Paul         if (mask != 1)
436278e76832fc26678592368b7b89bfddc137e0e93Brian Paul            src++;
437278e76832fc26678592368b7b89bfddc137e0e93Brian Paul      }
438278e76832fc26678592368b7b89bfddc137e0e93Brian Paul      else {
439278e76832fc26678592368b7b89bfddc137e0e93Brian Paul         /* Msb first */
440278e76832fc26678592368b7b89bfddc137e0e93Brian Paul         GLubyte mask = 128U >> (unpack->SkipPixels & 0x7);
441278e76832fc26678592368b7b89bfddc137e0e93Brian Paul         for (col = 0; col < width; col++) {
442278e76832fc26678592368b7b89bfddc137e0e93Brian Paul
443278e76832fc26678592368b7b89bfddc137e0e93Brian Paul            if (*src & mask) {
4440eb7b5c2a3f17d64e85247c1f4907ce20bc57a73Brian Paul               dstRow[col] = onValue;
445278e76832fc26678592368b7b89bfddc137e0e93Brian Paul            }
446278e76832fc26678592368b7b89bfddc137e0e93Brian Paul
447278e76832fc26678592368b7b89bfddc137e0e93Brian Paul            if (mask == 1U) {
448278e76832fc26678592368b7b89bfddc137e0e93Brian Paul               src++;
449278e76832fc26678592368b7b89bfddc137e0e93Brian Paul               mask = 128U;
450278e76832fc26678592368b7b89bfddc137e0e93Brian Paul            }
451278e76832fc26678592368b7b89bfddc137e0e93Brian Paul            else {
452278e76832fc26678592368b7b89bfddc137e0e93Brian Paul               mask = mask >> 1;
453278e76832fc26678592368b7b89bfddc137e0e93Brian Paul            }
454278e76832fc26678592368b7b89bfddc137e0e93Brian Paul         }
455278e76832fc26678592368b7b89bfddc137e0e93Brian Paul
456278e76832fc26678592368b7b89bfddc137e0e93Brian Paul         /* get ready for next row */
457278e76832fc26678592368b7b89bfddc137e0e93Brian Paul         if (mask != 128)
458278e76832fc26678592368b7b89bfddc137e0e93Brian Paul            src++;
459278e76832fc26678592368b7b89bfddc137e0e93Brian Paul      }
460278e76832fc26678592368b7b89bfddc137e0e93Brian Paul
461278e76832fc26678592368b7b89bfddc137e0e93Brian Paul      srcRow += srcStride;
4620eb7b5c2a3f17d64e85247c1f4907ce20bc57a73Brian Paul      dstRow += destStride;
463278e76832fc26678592368b7b89bfddc137e0e93Brian Paul   } /* row */
464278e76832fc26678592368b7b89bfddc137e0e93Brian Paul}
465278e76832fc26678592368b7b89bfddc137e0e93Brian Paul
466278e76832fc26678592368b7b89bfddc137e0e93Brian Paul
4674084e3c215d4db6370422fc718217bade7445618Brian Paul
46832a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul
46932a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul/**
47032a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul * Convert an array of RGBA colors from one datatype to another.
4714bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul * NOTE: src may equal dst.  In that case, we use a temporary buffer.
47232a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul */
47332a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paulvoid
47432a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul_mesa_convert_colors(GLenum srcType, const GLvoid *src,
47532a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul                     GLenum dstType, GLvoid *dst,
47632a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul                     GLuint count, const GLubyte mask[])
47732a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul{
4781614de4045c36ab6ec060e3bd0d1f3394d05b91eBrian Paul   GLuint *tempBuffer;
4794bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul   const GLboolean useTemp = (src == dst);
4804bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul
4811614de4045c36ab6ec060e3bd0d1f3394d05b91eBrian Paul   tempBuffer = malloc(count * MAX_PIXEL_BYTES);
4821614de4045c36ab6ec060e3bd0d1f3394d05b91eBrian Paul   if (!tempBuffer)
4831614de4045c36ab6ec060e3bd0d1f3394d05b91eBrian Paul      return;
4841614de4045c36ab6ec060e3bd0d1f3394d05b91eBrian Paul
485bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner   assert(srcType != dstType);
48632a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul
48732a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul   switch (srcType) {
48832a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul   case GL_UNSIGNED_BYTE:
48932a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul      if (dstType == GL_UNSIGNED_SHORT) {
4904bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul         const GLubyte (*src1)[4] = (const GLubyte (*)[4]) src;
4914bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul         GLushort (*dst2)[4] = (GLushort (*)[4]) (useTemp ? tempBuffer : dst);
49232a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul         GLuint i;
49332a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul         for (i = 0; i < count; i++) {
49432a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul            if (!mask || mask[i]) {
4954bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul               dst2[i][RCOMP] = UBYTE_TO_USHORT(src1[i][RCOMP]);
4964bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul               dst2[i][GCOMP] = UBYTE_TO_USHORT(src1[i][GCOMP]);
4974bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul               dst2[i][BCOMP] = UBYTE_TO_USHORT(src1[i][BCOMP]);
4984bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul               dst2[i][ACOMP] = UBYTE_TO_USHORT(src1[i][ACOMP]);
49932a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul            }
50032a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul         }
5014bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul         if (useTemp)
502c7ac486261ad30ef654f6d0b1608da4e8483cd40Kenneth Graunke            memcpy(dst, tempBuffer, count * 4 * sizeof(GLushort));
50332a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul      }
50432a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul      else {
5054bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul         const GLubyte (*src1)[4] = (const GLubyte (*)[4]) src;
5064bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul         GLfloat (*dst4)[4] = (GLfloat (*)[4]) (useTemp ? tempBuffer : dst);
50732a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul         GLuint i;
508bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner         assert(dstType == GL_FLOAT);
50932a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul         for (i = 0; i < count; i++) {
51032a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul            if (!mask || mask[i]) {
5114bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul               dst4[i][RCOMP] = UBYTE_TO_FLOAT(src1[i][RCOMP]);
5124bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul               dst4[i][GCOMP] = UBYTE_TO_FLOAT(src1[i][GCOMP]);
5134bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul               dst4[i][BCOMP] = UBYTE_TO_FLOAT(src1[i][BCOMP]);
5144bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul               dst4[i][ACOMP] = UBYTE_TO_FLOAT(src1[i][ACOMP]);
51532a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul            }
51632a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul         }
5174bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul         if (useTemp)
518c7ac486261ad30ef654f6d0b1608da4e8483cd40Kenneth Graunke            memcpy(dst, tempBuffer, count * 4 * sizeof(GLfloat));
51932a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul      }
52032a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul      break;
52132a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul   case GL_UNSIGNED_SHORT:
52232a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul      if (dstType == GL_UNSIGNED_BYTE) {
5234bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul         const GLushort (*src2)[4] = (const GLushort (*)[4]) src;
5244bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul         GLubyte (*dst1)[4] = (GLubyte (*)[4]) (useTemp ? tempBuffer : dst);
52532a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul         GLuint i;
52632a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul         for (i = 0; i < count; i++) {
52732a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul            if (!mask || mask[i]) {
5284bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul               dst1[i][RCOMP] = USHORT_TO_UBYTE(src2[i][RCOMP]);
5294bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul               dst1[i][GCOMP] = USHORT_TO_UBYTE(src2[i][GCOMP]);
5304bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul               dst1[i][BCOMP] = USHORT_TO_UBYTE(src2[i][BCOMP]);
5314bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul               dst1[i][ACOMP] = USHORT_TO_UBYTE(src2[i][ACOMP]);
53232a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul            }
53332a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul         }
5344bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul         if (useTemp)
535c7ac486261ad30ef654f6d0b1608da4e8483cd40Kenneth Graunke            memcpy(dst, tempBuffer, count * 4 * sizeof(GLubyte));
53632a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul      }
53732a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul      else {
5384bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul         const GLushort (*src2)[4] = (const GLushort (*)[4]) src;
5394bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul         GLfloat (*dst4)[4] = (GLfloat (*)[4]) (useTemp ? tempBuffer : dst);
54032a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul         GLuint i;
541bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner         assert(dstType == GL_FLOAT);
54232a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul         for (i = 0; i < count; i++) {
54332a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul            if (!mask || mask[i]) {
5444bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul               dst4[i][RCOMP] = USHORT_TO_FLOAT(src2[i][RCOMP]);
5454bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul               dst4[i][GCOMP] = USHORT_TO_FLOAT(src2[i][GCOMP]);
5464bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul               dst4[i][BCOMP] = USHORT_TO_FLOAT(src2[i][BCOMP]);
5474bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul               dst4[i][ACOMP] = USHORT_TO_FLOAT(src2[i][ACOMP]);
54832a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul            }
54932a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul         }
5504bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul         if (useTemp)
551c7ac486261ad30ef654f6d0b1608da4e8483cd40Kenneth Graunke            memcpy(dst, tempBuffer, count * 4 * sizeof(GLfloat));
55232a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul      }
55332a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul      break;
55432a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul   case GL_FLOAT:
55532a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul      if (dstType == GL_UNSIGNED_BYTE) {
5564bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul         const GLfloat (*src4)[4] = (const GLfloat (*)[4]) src;
5574bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul         GLubyte (*dst1)[4] = (GLubyte (*)[4]) (useTemp ? tempBuffer : dst);
55832a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul         GLuint i;
55932a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul         for (i = 0; i < count; i++) {
56081a86aea4f0990a1b8795f9e00e7a6c4ba368281Dave Airlie            if (!mask || mask[i])
56181a86aea4f0990a1b8795f9e00e7a6c4ba368281Dave Airlie               _mesa_unclamped_float_rgba_to_ubyte(dst1[i], src4[i]);
56232a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul         }
5634bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul         if (useTemp)
564c7ac486261ad30ef654f6d0b1608da4e8483cd40Kenneth Graunke            memcpy(dst, tempBuffer, count * 4 * sizeof(GLubyte));
56532a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul      }
56632a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul      else {
5674bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul         const GLfloat (*src4)[4] = (const GLfloat (*)[4]) src;
5684bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul         GLushort (*dst2)[4] = (GLushort (*)[4]) (useTemp ? tempBuffer : dst);
56932a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul         GLuint i;
570bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner         assert(dstType == GL_UNSIGNED_SHORT);
57132a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul         for (i = 0; i < count; i++) {
57232a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul            if (!mask || mask[i]) {
5734bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul               UNCLAMPED_FLOAT_TO_USHORT(dst2[i][RCOMP], src4[i][RCOMP]);
5744bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul               UNCLAMPED_FLOAT_TO_USHORT(dst2[i][GCOMP], src4[i][GCOMP]);
5754bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul               UNCLAMPED_FLOAT_TO_USHORT(dst2[i][BCOMP], src4[i][BCOMP]);
5764bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul               UNCLAMPED_FLOAT_TO_USHORT(dst2[i][ACOMP], src4[i][ACOMP]);
57732a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul            }
57832a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul         }
5794bb9f4115c4b1930a140da78feff953e80f8a4f5Brian Paul         if (useTemp)
580c7ac486261ad30ef654f6d0b1608da4e8483cd40Kenneth Graunke            memcpy(dst, tempBuffer, count * 4 * sizeof(GLushort));
58132a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul      }
58232a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul      break;
58332a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul   default:
58432a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul      _mesa_problem(NULL, "Invalid datatype in _mesa_convert_colors");
58532a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul   }
5861614de4045c36ab6ec060e3bd0d1f3394d05b91eBrian Paul
5871614de4045c36ab6ec060e3bd0d1f3394d05b91eBrian Paul   free(tempBuffer);
58832a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul}
58932a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul
59032a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul
59132a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul
59232a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul
5934084e3c215d4db6370422fc718217bade7445618Brian Paul/**
59432a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul * Perform basic clipping for glDrawPixels.  The image's position and size
59532a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul * and the unpack SkipPixels and SkipRows are adjusted so that the image
59632a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul * region is entirely within the window and scissor bounds.
59732a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul * NOTE: this will only work when glPixelZoom is (1, 1) or (1, -1).
59832a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul * If Pixel.ZoomY is -1, *destY will be changed to be the first row which
59932a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul * we'll actually write.  Beforehand, *destY-1 is the first drawing row.
6004084e3c215d4db6370422fc718217bade7445618Brian Paul *
6014084e3c215d4db6370422fc718217bade7445618Brian Paul * \return  GL_TRUE if image is ready for drawing or
6024084e3c215d4db6370422fc718217bade7445618Brian Paul *          GL_FALSE if image was completely clipped away (draw nothing)
6034084e3c215d4db6370422fc718217bade7445618Brian Paul */
6044084e3c215d4db6370422fc718217bade7445618Brian PaulGLboolean
605f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_clip_drawpixels(const struct gl_context *ctx,
6064084e3c215d4db6370422fc718217bade7445618Brian Paul                      GLint *destX, GLint *destY,
6074084e3c215d4db6370422fc718217bade7445618Brian Paul                      GLsizei *width, GLsizei *height,
6081ad7b99925e044f82e635f746c1ef2df77f69ac9Brian Paul                      struct gl_pixelstore_attrib *unpack)
6094084e3c215d4db6370422fc718217bade7445618Brian Paul{
61031aca27c08d6a385c595d34fe4ee06390bf5b0e8Kristian Høgsberg   const struct gl_framebuffer *buffer = ctx->DrawBuffer;
6114084e3c215d4db6370422fc718217bade7445618Brian Paul
6121ad7b99925e044f82e635f746c1ef2df77f69ac9Brian Paul   if (unpack->RowLength == 0) {
6131ad7b99925e044f82e635f746c1ef2df77f69ac9Brian Paul      unpack->RowLength = *width;
6141ad7b99925e044f82e635f746c1ef2df77f69ac9Brian Paul   }
6151ad7b99925e044f82e635f746c1ef2df77f69ac9Brian Paul
616bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner   assert(ctx->Pixel.ZoomX == 1.0F);
617bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner   assert(ctx->Pixel.ZoomY == 1.0F || ctx->Pixel.ZoomY == -1.0F);
618e677da9e54e836609f94a3aaca27d68a0bacbb96Brian Paul
6194084e3c215d4db6370422fc718217bade7445618Brian Paul   /* left clipping */
6204084e3c215d4db6370422fc718217bade7445618Brian Paul   if (*destX < buffer->_Xmin) {
6211ad7b99925e044f82e635f746c1ef2df77f69ac9Brian Paul      unpack->SkipPixels += (buffer->_Xmin - *destX);
6224084e3c215d4db6370422fc718217bade7445618Brian Paul      *width -= (buffer->_Xmin - *destX);
6234084e3c215d4db6370422fc718217bade7445618Brian Paul      *destX = buffer->_Xmin;
6244084e3c215d4db6370422fc718217bade7445618Brian Paul   }
6254084e3c215d4db6370422fc718217bade7445618Brian Paul   /* right clipping */
6264084e3c215d4db6370422fc718217bade7445618Brian Paul   if (*destX + *width > buffer->_Xmax)
6274084e3c215d4db6370422fc718217bade7445618Brian Paul      *width -= (*destX + *width - buffer->_Xmax);
6284084e3c215d4db6370422fc718217bade7445618Brian Paul
6294084e3c215d4db6370422fc718217bade7445618Brian Paul   if (*width <= 0)
6304084e3c215d4db6370422fc718217bade7445618Brian Paul      return GL_FALSE;
6314084e3c215d4db6370422fc718217bade7445618Brian Paul
63232a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul   if (ctx->Pixel.ZoomY == 1.0F) {
63332a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul      /* bottom clipping */
63432a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul      if (*destY < buffer->_Ymin) {
63532a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul         unpack->SkipRows += (buffer->_Ymin - *destY);
63632a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul         *height -= (buffer->_Ymin - *destY);
63732a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul         *destY = buffer->_Ymin;
63832a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul      }
63932a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul      /* top clipping */
64032a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul      if (*destY + *height > buffer->_Ymax)
64132a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul         *height -= (*destY + *height - buffer->_Ymax);
64232a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul   }
64332a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul   else { /* upside down */
64432a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul      /* top clipping */
64532a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul      if (*destY > buffer->_Ymax) {
64632a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul         unpack->SkipRows += (*destY - buffer->_Ymax);
64732a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul         *height -= (*destY - buffer->_Ymax);
64832a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul         *destY = buffer->_Ymax;
64932a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul      }
65032a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul      /* bottom clipping */
65132a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul      if (*destY - *height < buffer->_Ymin)
65232a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul         *height -= (buffer->_Ymin - (*destY - *height));
65332a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul      /* adjust destY so it's the first row to write to */
65432a966dad9c5c6309adafcb58050cd0f70c32bdeBrian Paul      (*destY)--;
6554084e3c215d4db6370422fc718217bade7445618Brian Paul   }
6564084e3c215d4db6370422fc718217bade7445618Brian Paul
6574084e3c215d4db6370422fc718217bade7445618Brian Paul   if (*height <= 0)
6587aeaca33c331f70d507fc83583b13b8d9fc3e847Ben Skeggs      return GL_FALSE;
6594084e3c215d4db6370422fc718217bade7445618Brian Paul
6604084e3c215d4db6370422fc718217bade7445618Brian Paul   return GL_TRUE;
6614084e3c215d4db6370422fc718217bade7445618Brian Paul}
6624084e3c215d4db6370422fc718217bade7445618Brian Paul
6634084e3c215d4db6370422fc718217bade7445618Brian Paul
6644084e3c215d4db6370422fc718217bade7445618Brian Paul/**
6654084e3c215d4db6370422fc718217bade7445618Brian Paul * Perform clipping for glReadPixels.  The image's window position
6661ad7b99925e044f82e635f746c1ef2df77f69ac9Brian Paul * and size, and the pack skipPixels, skipRows and rowLength are adjusted
6671ad7b99925e044f82e635f746c1ef2df77f69ac9Brian Paul * so that the image region is entirely within the window bounds.
6684084e3c215d4db6370422fc718217bade7445618Brian Paul * Note: this is different from _mesa_clip_drawpixels() in that the
6691ad7b99925e044f82e635f746c1ef2df77f69ac9Brian Paul * scissor box is ignored, and we use the bounds of the current readbuffer
67055d56d34e0535baa2c7e1e1d8f1be11593a07fa8Nanley Chery * surface or the attached image.
6714084e3c215d4db6370422fc718217bade7445618Brian Paul *
672d44fbd3c9d976763ec1f4a8f0314f294be8c14f4Brian Paul * \return  GL_TRUE if region to read is in bounds
673d44fbd3c9d976763ec1f4a8f0314f294be8c14f4Brian Paul *          GL_FALSE if region is completely out of bounds (nothing to read)
6744084e3c215d4db6370422fc718217bade7445618Brian Paul */
6754084e3c215d4db6370422fc718217bade7445618Brian PaulGLboolean
676f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_clip_readpixels(const struct gl_context *ctx,
6774084e3c215d4db6370422fc718217bade7445618Brian Paul                      GLint *srcX, GLint *srcY,
6784084e3c215d4db6370422fc718217bade7445618Brian Paul                      GLsizei *width, GLsizei *height,
6791ad7b99925e044f82e635f746c1ef2df77f69ac9Brian Paul                      struct gl_pixelstore_attrib *pack)
6804084e3c215d4db6370422fc718217bade7445618Brian Paul{
68131aca27c08d6a385c595d34fe4ee06390bf5b0e8Kristian Høgsberg   const struct gl_framebuffer *buffer = ctx->ReadBuffer;
68255d56d34e0535baa2c7e1e1d8f1be11593a07fa8Nanley Chery   struct gl_renderbuffer *rb = buffer->_ColorReadBuffer;
68355d56d34e0535baa2c7e1e1d8f1be11593a07fa8Nanley Chery   GLsizei clip_width;
68455d56d34e0535baa2c7e1e1d8f1be11593a07fa8Nanley Chery   GLsizei clip_height;
68555d56d34e0535baa2c7e1e1d8f1be11593a07fa8Nanley Chery
68655d56d34e0535baa2c7e1e1d8f1be11593a07fa8Nanley Chery   if (rb) {
68755d56d34e0535baa2c7e1e1d8f1be11593a07fa8Nanley Chery      clip_width = rb->Width;
68855d56d34e0535baa2c7e1e1d8f1be11593a07fa8Nanley Chery      clip_height = rb->Height;
68955d56d34e0535baa2c7e1e1d8f1be11593a07fa8Nanley Chery   } else {
69055d56d34e0535baa2c7e1e1d8f1be11593a07fa8Nanley Chery      clip_width = buffer->Width;
69155d56d34e0535baa2c7e1e1d8f1be11593a07fa8Nanley Chery      clip_height = buffer->Height;
69255d56d34e0535baa2c7e1e1d8f1be11593a07fa8Nanley Chery   }
69355d56d34e0535baa2c7e1e1d8f1be11593a07fa8Nanley Chery
6944084e3c215d4db6370422fc718217bade7445618Brian Paul
6951ad7b99925e044f82e635f746c1ef2df77f69ac9Brian Paul   if (pack->RowLength == 0) {
6961ad7b99925e044f82e635f746c1ef2df77f69ac9Brian Paul      pack->RowLength = *width;
6971ad7b99925e044f82e635f746c1ef2df77f69ac9Brian Paul   }
6981ad7b99925e044f82e635f746c1ef2df77f69ac9Brian Paul
6994084e3c215d4db6370422fc718217bade7445618Brian Paul   /* left clipping */
7004084e3c215d4db6370422fc718217bade7445618Brian Paul   if (*srcX < 0) {
7011ad7b99925e044f82e635f746c1ef2df77f69ac9Brian Paul      pack->SkipPixels += (0 - *srcX);
7024084e3c215d4db6370422fc718217bade7445618Brian Paul      *width -= (0 - *srcX);
7034084e3c215d4db6370422fc718217bade7445618Brian Paul      *srcX = 0;
7044084e3c215d4db6370422fc718217bade7445618Brian Paul   }
7054084e3c215d4db6370422fc718217bade7445618Brian Paul   /* right clipping */
70655d56d34e0535baa2c7e1e1d8f1be11593a07fa8Nanley Chery   if (*srcX + *width > clip_width)
70755d56d34e0535baa2c7e1e1d8f1be11593a07fa8Nanley Chery      *width -= (*srcX + *width - clip_width);
7084084e3c215d4db6370422fc718217bade7445618Brian Paul
7094084e3c215d4db6370422fc718217bade7445618Brian Paul   if (*width <= 0)
7104084e3c215d4db6370422fc718217bade7445618Brian Paul      return GL_FALSE;
7114084e3c215d4db6370422fc718217bade7445618Brian Paul
7124084e3c215d4db6370422fc718217bade7445618Brian Paul   /* bottom clipping */
7134084e3c215d4db6370422fc718217bade7445618Brian Paul   if (*srcY < 0) {
7141ad7b99925e044f82e635f746c1ef2df77f69ac9Brian Paul      pack->SkipRows += (0 - *srcY);
7154084e3c215d4db6370422fc718217bade7445618Brian Paul      *height -= (0 - *srcY);
7164084e3c215d4db6370422fc718217bade7445618Brian Paul      *srcY = 0;
7174084e3c215d4db6370422fc718217bade7445618Brian Paul   }
7184084e3c215d4db6370422fc718217bade7445618Brian Paul   /* top clipping */
71955d56d34e0535baa2c7e1e1d8f1be11593a07fa8Nanley Chery   if (*srcY + *height > clip_height)
72055d56d34e0535baa2c7e1e1d8f1be11593a07fa8Nanley Chery      *height -= (*srcY + *height - clip_height);
7214084e3c215d4db6370422fc718217bade7445618Brian Paul
7224084e3c215d4db6370422fc718217bade7445618Brian Paul   if (*height <= 0)
7237aeaca33c331f70d507fc83583b13b8d9fc3e847Ben Skeggs      return GL_FALSE;
7244084e3c215d4db6370422fc718217bade7445618Brian Paul
7254084e3c215d4db6370422fc718217bade7445618Brian Paul   return GL_TRUE;
7264084e3c215d4db6370422fc718217bade7445618Brian Paul}
7274084e3c215d4db6370422fc718217bade7445618Brian Paul
728ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul
729ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul/**
73003bafd1f9fa000abdb794b2ae344a68840c83201Brian Paul * Do clipping for a glCopyTexSubImage call.
73103bafd1f9fa000abdb794b2ae344a68840c83201Brian Paul * The framebuffer source region might extend outside the framebuffer
73203bafd1f9fa000abdb794b2ae344a68840c83201Brian Paul * bounds.  Clip the source region against the framebuffer bounds and
73303bafd1f9fa000abdb794b2ae344a68840c83201Brian Paul * adjust the texture/dest position and size accordingly.
73403bafd1f9fa000abdb794b2ae344a68840c83201Brian Paul *
73503bafd1f9fa000abdb794b2ae344a68840c83201Brian Paul * \return GL_FALSE if region is totally clipped, GL_TRUE otherwise.
73603bafd1f9fa000abdb794b2ae344a68840c83201Brian Paul */
73703bafd1f9fa000abdb794b2ae344a68840c83201Brian PaulGLboolean
738f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_clip_copytexsubimage(const struct gl_context *ctx,
73903bafd1f9fa000abdb794b2ae344a68840c83201Brian Paul                           GLint *destX, GLint *destY,
74003bafd1f9fa000abdb794b2ae344a68840c83201Brian Paul                           GLint *srcX, GLint *srcY,
74103bafd1f9fa000abdb794b2ae344a68840c83201Brian Paul                           GLsizei *width, GLsizei *height)
74203bafd1f9fa000abdb794b2ae344a68840c83201Brian Paul{
74303bafd1f9fa000abdb794b2ae344a68840c83201Brian Paul   const struct gl_framebuffer *fb = ctx->ReadBuffer;
74403bafd1f9fa000abdb794b2ae344a68840c83201Brian Paul   const GLint srcX0 = *srcX, srcY0 = *srcY;
74503bafd1f9fa000abdb794b2ae344a68840c83201Brian Paul
746d01c44aacaeabe1dd187163f9e204f40401698bcEric Anholt   if (_mesa_clip_to_region(0, 0, fb->Width, fb->Height,
74703bafd1f9fa000abdb794b2ae344a68840c83201Brian Paul                            srcX, srcY, width, height)) {
74803bafd1f9fa000abdb794b2ae344a68840c83201Brian Paul      *destX = *destX + *srcX - srcX0;
74903bafd1f9fa000abdb794b2ae344a68840c83201Brian Paul      *destY = *destY + *srcY - srcY0;
75003bafd1f9fa000abdb794b2ae344a68840c83201Brian Paul
75103bafd1f9fa000abdb794b2ae344a68840c83201Brian Paul      return GL_TRUE;
75203bafd1f9fa000abdb794b2ae344a68840c83201Brian Paul   }
75303bafd1f9fa000abdb794b2ae344a68840c83201Brian Paul   else {
75403bafd1f9fa000abdb794b2ae344a68840c83201Brian Paul      return GL_FALSE;
75503bafd1f9fa000abdb794b2ae344a68840c83201Brian Paul   }
75603bafd1f9fa000abdb794b2ae344a68840c83201Brian Paul}
75703bafd1f9fa000abdb794b2ae344a68840c83201Brian Paul
75803bafd1f9fa000abdb794b2ae344a68840c83201Brian Paul
75903bafd1f9fa000abdb794b2ae344a68840c83201Brian Paul
76003bafd1f9fa000abdb794b2ae344a68840c83201Brian Paul/**
761ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul * Clip the rectangle defined by (x, y, width, height) against the bounds
762ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul * specified by [xmin, xmax) and [ymin, ymax).
763ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul * \return GL_FALSE if rect is totally clipped, GL_TRUE otherwise.
764ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul */
765ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian PaulGLboolean
766ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul_mesa_clip_to_region(GLint xmin, GLint ymin,
767ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul                     GLint xmax, GLint ymax,
768ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul                     GLint *x, GLint *y,
769ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul                     GLsizei *width, GLsizei *height )
770ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul{
771ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul   /* left clipping */
772ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul   if (*x < xmin) {
773ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul      *width -= (xmin - *x);
774ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul      *x = xmin;
775ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul   }
776ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul
777ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul   /* right clipping */
778ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul   if (*x + *width > xmax)
779aa09e0a1d532d0de2e094957d0509a7f60ebeafaEric Anholt      *width -= (*x + *width - xmax);
780ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul
781ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul   if (*width <= 0)
782ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul      return GL_FALSE;
783ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul
784ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul   /* bottom (or top) clipping */
785ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul   if (*y < ymin) {
786ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul      *height -= (ymin - *y);
787ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul      *y = ymin;
788ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul   }
789ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul
790ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul   /* top (or bottom) clipping */
791ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul   if (*y + *height > ymax)
792aa09e0a1d532d0de2e094957d0509a7f60ebeafaEric Anholt      *height -= (*y + *height - ymax);
793ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul
794ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul   if (*height <= 0)
795ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul      return GL_FALSE;
796ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul
797ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul   return GL_TRUE;
798ea4fe661d7f3a95d9db17e1475076f1badf8e1a6Brian Paul}
799727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul
800727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul
801727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul/**
802727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul * Clip dst coords against Xmax (or Ymax).
803727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul */
8049520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline void
805727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paulclip_right_or_top(GLint *srcX0, GLint *srcX1,
806727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul                  GLint *dstX0, GLint *dstX1,
807727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul                  GLint maxValue)
808727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul{
809727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   GLfloat t, bias;
810727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul
811727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   if (*dstX1 > maxValue) {
812727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul      /* X1 outside right edge */
813bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner      assert(*dstX0 < maxValue); /* X0 should be inside right edge */
814727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul      t = (GLfloat) (maxValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0);
815727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul      /* chop off [t, 1] part */
816bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner      assert(t >= 0.0 && t <= 1.0);
817727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul      *dstX1 = maxValue;
818b30898f4ab533085d97a33638ad0a1cf9ddb1d67Karl Schultz      bias = (*srcX0 < *srcX1) ? 0.5F : -0.5F;
819727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul      *srcX1 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias);
820727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   }
821727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   else if (*dstX0 > maxValue) {
822727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul      /* X0 outside right edge */
823bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner      assert(*dstX1 < maxValue); /* X1 should be inside right edge */
824727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul      t = (GLfloat) (maxValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1);
825727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul      /* chop off [t, 1] part */
826bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner      assert(t >= 0.0 && t <= 1.0);
827727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul      *dstX0 = maxValue;
828b30898f4ab533085d97a33638ad0a1cf9ddb1d67Karl Schultz      bias = (*srcX0 < *srcX1) ? -0.5F : 0.5F;
829727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul      *srcX0 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias);
830727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   }
831727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul}
832727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul
833727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul
834727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul/**
835727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul * Clip dst coords against Xmin (or Ymin).
836727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul */
8379520f483b8f1e45fa474674b415554988de5d8d3Brian Paulstatic inline void
838727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paulclip_left_or_bottom(GLint *srcX0, GLint *srcX1,
839727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul                    GLint *dstX0, GLint *dstX1,
840727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul                    GLint minValue)
841727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul{
842727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   GLfloat t, bias;
843727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul
844727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   if (*dstX0 < minValue) {
845727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul      /* X0 outside left edge */
846bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner      assert(*dstX1 > minValue); /* X1 should be inside left edge */
847727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul      t = (GLfloat) (minValue - *dstX0) / (GLfloat) (*dstX1 - *dstX0);
848727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul      /* chop off [0, t] part */
849bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner      assert(t >= 0.0 && t <= 1.0);
850727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul      *dstX0 = minValue;
851d1b929a13713e740c06e3abc8666fe56b513a41aMarek Olšák      bias = (*srcX0 < *srcX1) ? 0.5F : -0.5F;
852727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul      *srcX0 = *srcX0 + (GLint) (t * (*srcX1 - *srcX0) + bias);
853727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   }
854727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   else if (*dstX1 < minValue) {
855727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul      /* X1 outside left edge */
856bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner      assert(*dstX0 > minValue); /* X0 should be inside left edge */
857727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul      t = (GLfloat) (minValue - *dstX1) / (GLfloat) (*dstX0 - *dstX1);
858727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul      /* chop off [0, t] part */
859bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner      assert(t >= 0.0 && t <= 1.0);
860727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul      *dstX1 = minValue;
861d1b929a13713e740c06e3abc8666fe56b513a41aMarek Olšák      bias = (*srcX0 < *srcX1) ? -0.5F : 0.5F;
862727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul      *srcX1 = *srcX1 + (GLint) (t * (*srcX0 - *srcX1) + bias);
863727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   }
864727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul}
865727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul
866727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul
867727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul/**
868727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul * Do clipping of blit src/dest rectangles.
869727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul * The dest rect is clipped against both the buffer bounds and scissor bounds.
870727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul * The src rect is just clipped against the buffer bounds.
871727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul *
872727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul * When either the src or dest rect is clipped, the other is also clipped
873727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul * proportionately!
874727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul *
875727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul * Note that X0 need not be less than X1 (same for Y) for either the source
876727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul * and dest rects.  That makes the clipping a little trickier.
877727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul *
878727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul * \return GL_TRUE if anything is left to draw, GL_FALSE if totally clipped
879727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul */
880727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian PaulGLboolean
881f9995b30756140724f41daf963fa06167912be7fKristian Høgsberg_mesa_clip_blit(struct gl_context *ctx,
882e187c2f5432466c7b49dba266026fb9b01f5f667Laura Ekstrand                const struct gl_framebuffer *readFb,
883e187c2f5432466c7b49dba266026fb9b01f5f667Laura Ekstrand                const struct gl_framebuffer *drawFb,
884727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul                GLint *srcX0, GLint *srcY0, GLint *srcX1, GLint *srcY1,
885727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul                GLint *dstX0, GLint *dstY0, GLint *dstX1, GLint *dstY1)
886727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul{
887727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   const GLint srcXmin = 0;
888e187c2f5432466c7b49dba266026fb9b01f5f667Laura Ekstrand   const GLint srcXmax = readFb->Width;
889727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   const GLint srcYmin = 0;
890e187c2f5432466c7b49dba266026fb9b01f5f667Laura Ekstrand   const GLint srcYmax = readFb->Height;
891727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul
892727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   /* these include scissor bounds */
893e187c2f5432466c7b49dba266026fb9b01f5f667Laura Ekstrand   const GLint dstXmin = drawFb->_Xmin;
894e187c2f5432466c7b49dba266026fb9b01f5f667Laura Ekstrand   const GLint dstXmax = drawFb->_Xmax;
895e187c2f5432466c7b49dba266026fb9b01f5f667Laura Ekstrand   const GLint dstYmin = drawFb->_Ymin;
896e187c2f5432466c7b49dba266026fb9b01f5f667Laura Ekstrand   const GLint dstYmax = drawFb->_Ymax;
897727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul
898727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   /*
899727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   printf("PreClipX:  src: %d .. %d  dst: %d .. %d\n",
900727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul          *srcX0, *srcX1, *dstX0, *dstX1);
901727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   printf("PreClipY:  src: %d .. %d  dst: %d .. %d\n",
902727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul          *srcY0, *srcY1, *dstY0, *dstY1);
903727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   */
904727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul
905727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   /* trivial rejection tests */
906727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   if (*dstX0 == *dstX1)
907727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul      return GL_FALSE; /* no width */
908727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   if (*dstX0 <= dstXmin && *dstX1 <= dstXmin)
909727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul      return GL_FALSE; /* totally out (left) of bounds */
910727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   if (*dstX0 >= dstXmax && *dstX1 >= dstXmax)
911727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul      return GL_FALSE; /* totally out (right) of bounds */
912727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul
913727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   if (*dstY0 == *dstY1)
914727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul      return GL_FALSE;
915727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   if (*dstY0 <= dstYmin && *dstY1 <= dstYmin)
916727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul      return GL_FALSE;
917727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   if (*dstY0 >= dstYmax && *dstY1 >= dstYmax)
918727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul      return GL_FALSE;
919727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul
920727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   if (*srcX0 == *srcX1)
921727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul      return GL_FALSE;
922727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   if (*srcX0 <= srcXmin && *srcX1 <= srcXmin)
923727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul      return GL_FALSE;
924727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   if (*srcX0 >= srcXmax && *srcX1 >= srcXmax)
925727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul      return GL_FALSE;
926727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul
927727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   if (*srcY0 == *srcY1)
928727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul      return GL_FALSE;
929727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   if (*srcY0 <= srcYmin && *srcY1 <= srcYmin)
930727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul      return GL_FALSE;
931727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   if (*srcY0 >= srcYmax && *srcY1 >= srcYmax)
932727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul      return GL_FALSE;
933727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul
934727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   /*
935727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul    * dest clip
936727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul    */
937727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   clip_right_or_top(srcX0, srcX1, dstX0, dstX1, dstXmax);
938727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   clip_right_or_top(srcY0, srcY1, dstY0, dstY1, dstYmax);
939727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   clip_left_or_bottom(srcX0, srcX1, dstX0, dstX1, dstXmin);
940727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   clip_left_or_bottom(srcY0, srcY1, dstY0, dstY1, dstYmin);
941727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul
942727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   /*
943727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul    * src clip (just swap src/dst values from above)
944727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul    */
945727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   clip_right_or_top(dstX0, dstX1, srcX0, srcX1, srcXmax);
946727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   clip_right_or_top(dstY0, dstY1, srcY0, srcY1, srcYmax);
947727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   clip_left_or_bottom(dstX0, dstX1, srcX0, srcX1, srcXmin);
948727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   clip_left_or_bottom(dstY0, dstY1, srcY0, srcY1, srcYmin);
949727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul
950727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   /*
951727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   printf("PostClipX: src: %d .. %d  dst: %d .. %d\n",
952727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul          *srcX0, *srcX1, *dstX0, *dstX1);
953727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   printf("PostClipY: src: %d .. %d  dst: %d .. %d\n",
954727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul          *srcY0, *srcY1, *dstY0, *dstY1);
955727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   */
956727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul
957bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner   assert(*dstX0 >= dstXmin);
958bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner   assert(*dstX0 <= dstXmax);
959bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner   assert(*dstX1 >= dstXmin);
960bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner   assert(*dstX1 <= dstXmax);
961bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner
962bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner   assert(*dstY0 >= dstYmin);
963bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner   assert(*dstY0 <= dstYmax);
964bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner   assert(*dstY1 >= dstYmin);
965bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner   assert(*dstY1 <= dstYmax);
966bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner
967bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner   assert(*srcX0 >= srcXmin);
968bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner   assert(*srcX0 <= srcXmax);
969bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner   assert(*srcX1 >= srcXmin);
970bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner   assert(*srcX1 <= srcXmax);
971bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner
972bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner   assert(*srcY0 >= srcYmin);
973bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner   assert(*srcY0 <= srcYmax);
974bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner   assert(*srcY1 >= srcYmin);
975bfcdb843830bba0190e00e35e3c5c18c4bdb5de1Matt Turner   assert(*srcY1 <= srcYmax);
976727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul
977727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul   return GL_TRUE;
978727b2d747e13fed78bf62cfbf4a31427eed0ef29Brian Paul}
9790ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie
9800ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie/**
9810ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie * Swap the bytes in a 2D image.
9820ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie *
9830ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie * using the packing information this swaps the bytes
9840ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie * according to the format and type of data being input.
9850ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie * It takes into a/c various packing parameters like
9860ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie * Alignment and RowLength.
9870ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie */
9880ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlievoid
9890ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie_mesa_swap_bytes_2d_image(GLenum format, GLenum type,
9900ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie                          const struct gl_pixelstore_attrib *packing,
9910ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie                          GLsizei width, GLsizei height,
9920ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie                          GLvoid *dst, const GLvoid *src)
9930ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie{
9940ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie   GLint swapSize = _mesa_sizeof_packed_type(type);
9950ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie
9960ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie   assert(packing->SwapBytes);
9970ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie
9980ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie   if (swapSize == 2 || swapSize == 4) {
9990ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie      int swapsPerPixel = _mesa_bytes_per_pixel(format, type) / swapSize;
10000ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie      int stride = _mesa_image_row_stride(packing, width, format, type);
10010ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie      int row;
10020ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie      uint8_t *dstrow;
10030ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie      const uint8_t *srcrow;
10040ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie      assert(swapsPerPixel > 0);
10050ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie      assert(_mesa_bytes_per_pixel(format, type) % swapSize == 0);
10060ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie      dstrow = dst;
10070ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie      srcrow = src;
10080ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie      for (row = 0; row < height; row++) {
10090ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie         if (swapSize == 2)
10100ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie            swap2_copy((GLushort *)dstrow, (GLushort *)srcrow, width * swapsPerPixel);
10110ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie         else if (swapSize == 4)
10120ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie            swap4_copy((GLuint *)dstrow, (GLuint *)srcrow, width * swapsPerPixel);
10130ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie         dstrow += stride;
10140ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie         srcrow += stride;
10150ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie      }
10160ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie   }
10170ad3a475ef81dad3baf607d749b91dfa1700ca23Dave Airlie}
1018