3 * Texture conversion templates.
5 * \author Gareth Hughes
7 * For 2D and 3D texture images, we generate functions for
8 * - conversion without pixel unpacking and standard stride
9 * - conversion without pixel unpacking and non-standard stride
10 * - conversion with pixel unpacking and standard stride
11 * - conversion with pixel unpacking and non-standard stride
13 * Macros which need to be defined before including this file:
14 * - \c TAG(x) - the function name wrapper
15 * - \c DST_TYPE - the destination texel data type (GLuint, GLushort, etc)
16 * - \c DST_TEXELS_PER_DWORD - number of destination texels that'll fit in 4 bytes
17 * - \c CONVERT_TEXEL - code to convert from source to destination texel
18 * - \c CONVER_TEXEL_DWORD - if multiple texels fit in 4 bytes, this macros
19 * will convert/store multiple texels at once
20 * - \c CONVERT_DIRECT - if defined, just memcpy texels from source to destination
21 * - \c SRC_TEXEL_BYTES - bytes per source texel
22 * - \c PRESERVE_DST_TYPE - if defined, don't undefined these macros at end
28 * Mesa 3-D graphics library
31 * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
33 * Permission is hereby granted, free of charge, to any person obtaining a
34 * copy of this software and associated documentation files (the "Software"),
35 * to deal in the Software without restriction, including without limitation
36 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
37 * and/or sell copies of the Software, and to permit persons to whom the
38 * Software is furnished to do so, subject to the following conditions:
40 * The above copyright notice and this permission notice shall be included
41 * in all copies or substantial portions of the Software.
43 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
44 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
45 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
46 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
47 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
48 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
52 #define DST_TEXEL_BYTES (4 / DST_TEXELS_PER_DWORD)
53 #define DST_ROW_BYTES (convert->width * DST_TEXEL_BYTES)
54 #define DST_ROW_STRIDE (convert->dstImageWidth * DST_TEXEL_BYTES)
55 #define DST_IMG_STRIDE (convert->dstImageWidth * \
56 convert->dstImageHeight * DST_TEXEL_BYTES)
59 /***************************************************************/
60 /** \name Doesn't require pixelstore attributes or stride
62 * \code width == dstImageWidth \endcode
64 * \code height == dstImageHeight \endcode
69 /** \sa convert_func */
71 TAG(texsubimage2d
)( const struct convert_info
*convert
)
73 const GLubyte
*src
= (const GLubyte
*)convert
->srcImage
;
74 GLuint
*dst
= (GLuint
*)((GLubyte
*)convert
->dstImage
+
75 (convert
->yoffset
* convert
->dstImageWidth
+
76 convert
->xoffset
) * DST_TEXEL_BYTES
);
79 _mesa_debug( NULL
, __FUNCTION__
"\n" );
83 MEMCPY( dst
, src
, convert
->height
* DST_ROW_BYTES
);
86 const GLint texels
= convert
->width
* convert
->height
;
87 const GLint dwords
= texels
/ DST_TEXELS_PER_DWORD
;
88 const GLint leftover
= texels
- dwords
* DST_TEXELS_PER_DWORD
;
90 for ( i
= 0 ; i
< dwords
; i
++ ) {
91 CONVERT_TEXEL_DWORD( *dst
++, src
);
92 src
+= SRC_TEXEL_BYTES
* DST_TEXELS_PER_DWORD
;
94 for ( i
= 0; i
< leftover
; i
++ ) {
95 CONVERT_TEXEL( *dst
++, src
);
96 src
+= SRC_TEXEL_BYTES
;
104 /** \sa convert_func */
106 TAG(texsubimage3d
)( const struct convert_info
*convert
)
108 const GLubyte
*src
= (const GLubyte
*)convert
->srcImage
;
109 GLuint
*dst
= (GLuint
*)((GLubyte
*)convert
->dstImage
+
110 ((convert
->zoffset
* convert
->height
+
111 convert
->yoffset
) * convert
->width
+
112 convert
->xoffset
) * DST_TEXEL_BYTES
);
114 _mesa_debug( NULL
, __FUNCTION__
"\n" );
117 #ifdef CONVERT_DIRECT
118 MEMCPY( dst
, src
, convert
->depth
* convert
->height
* DST_ROW_BYTES
);
121 const GLint texels
= convert
->width
* convert
->height
* convert
->depth
;
122 const GLint dwords
= texels
/ DST_TEXELS_PER_DWORD
;
123 const GLint leftover
= texels
- dwords
* DST_TEXELS_PER_DWORD
;
125 for ( i
= 0 ; i
< dwords
; i
++ ) {
126 CONVERT_TEXEL_DWORD( *dst
++, src
);
127 src
+= SRC_TEXEL_BYTES
* DST_TEXELS_PER_DWORD
;
129 for ( i
= 0; i
< leftover
; i
++ ) {
130 CONVERT_TEXEL( *dst
++, src
);
131 src
+= SRC_TEXEL_BYTES
;
142 /***************************************************************/
143 /** \name Requires stride but no pixelstore attributes
145 * \code width != dstImageWidth \endcode
147 * \code height != dstImageHeight \endcode
152 /** \sa convert_func */
154 TAG(texsubimage2d_stride
)( const struct convert_info
*convert
)
156 const GLubyte
*src
= (const GLubyte
*)convert
->srcImage
;
157 DST_TYPE
*dst
= (DST_TYPE
*)((GLubyte
*)convert
->dstImage
+
158 (convert
->yoffset
* convert
->dstImageWidth
+
159 convert
->xoffset
) * DST_TEXEL_BYTES
);
163 adjust
= convert
->dstImageWidth
- convert
->width
;
166 _mesa_debug( NULL
, __FUNCTION__
":\n" );
167 _mesa_debug( NULL
, " x=%d y=%d w=%d h=%d s=%d\n",
168 convert
->xoffset
, convert
->yoffset
, convert
->width
,
169 convert
->height
, convert
->dstImageWidth
);
170 _mesa_debug( NULL
, " adjust=%d\n", adjust
);
173 for ( row
= 0 ; row
< convert
->height
; row
++ ) {
174 for ( col
= 0 ; col
< convert
->width
; col
++ ) {
175 CONVERT_TEXEL( *dst
++, src
);
176 src
+= SRC_TEXEL_BYTES
;
184 /** \sa convert_func */
186 TAG(texsubimage3d_stride
)( const struct convert_info
*convert
)
188 const GLubyte
*src
= (const GLubyte
*)convert
->srcImage
;
189 DST_TYPE
*dst
= (DST_TYPE
*)((GLubyte
*)convert
->dstImage
+
190 ((convert
->zoffset
* convert
->dstImageHeight
+
191 convert
->yoffset
) * convert
->dstImageWidth
+
192 convert
->xoffset
) * DST_TEXEL_BYTES
);
196 adjust
= convert
->dstImageWidth
- convert
->width
;
199 _mesa_debug( NULL
, __FUNCTION__
":\n" );
200 _mesa_debug( NULL
, " x=%d y=%d w=%d h=%d s=%d\n",
201 convert
->xoffset
, convert
->yoffset
, convert
->width
,
202 convert
->height
, convert
->dstImageWidth
);
203 _mesa_debug( NULL
, " adjust=%d\n", adjust
);
206 for ( img
= 0 ; img
< convert
->depth
; img
++ ) {
207 for ( row
= 0 ; row
< convert
->height
; row
++ ) {
208 for ( col
= 0 ; col
< convert
->width
; col
++ ) {
209 CONVERT_TEXEL( *dst
++, src
);
210 src
+= SRC_TEXEL_BYTES
;
223 /***************************************************************/
224 /** \name Requires pixelstore attributes but no stride.
226 * \code width == dstImageWidth \endcode
228 * \code height == dstImageHeight \endcode
233 /** \sa convert_func */
235 TAG(texsubimage2d_unpack
)( const struct convert_info
*convert
)
237 const GLubyte
*src
= (const GLubyte
*)
238 _mesa_image_address( convert
->unpacking
, convert
->srcImage
,
239 convert
->width
, convert
->height
,
240 convert
->format
, convert
->type
, 0, 0, 0 );
241 const GLint srcRowStride
=
242 _mesa_image_row_stride( convert
->unpacking
, convert
->width
,
243 convert
->format
, convert
->type
);
247 _mesa_debug( NULL
, __FUNCTION__
"\n" );
250 if (convert
->width
& (DST_TEXELS_PER_DWORD
- 1)) {
251 /* Can't use dword conversion (i.e. when width = 1 and texels/dword = 2
252 * or width = 2 and texels/dword = 4).
254 DST_TYPE
*dst
= (DST_TYPE
*)((GLubyte
*)convert
->dstImage
+
255 (convert
->yoffset
* convert
->width
+
256 convert
->xoffset
) * DST_TEXEL_BYTES
);
257 for ( row
= 0 ; row
< convert
->height
; row
++ ) {
258 const GLubyte
*srcRow
= src
;
259 for ( col
= 0; col
< convert
->width
; col
++ ) {
260 CONVERT_TEXEL(*dst
, src
);
261 src
+= SRC_TEXEL_BYTES
;
263 src
= srcRow
+ srcRowStride
;
267 /* the common case */
268 GLuint
*dst
= (GLuint
*)((GLubyte
*)convert
->dstImage
+
269 (convert
->yoffset
* convert
->width
+
270 convert
->xoffset
) * DST_TEXEL_BYTES
);
271 for ( row
= 0 ; row
< convert
->height
; row
++ ) {
272 #ifdef CONVERT_DIRECT
273 MEMCPY( dst
, src
, DST_ROW_STRIDE
);
275 dst
= (GLuint
*)((GLubyte
*)dst
+ DST_ROW_STRIDE
);
277 const GLubyte
*srcRow
= src
;
278 for ( col
= convert
->width
/ DST_TEXELS_PER_DWORD
; col
; col
-- ) {
279 CONVERT_TEXEL_DWORD( *dst
++, src
);
280 src
+= SRC_TEXEL_BYTES
* DST_TEXELS_PER_DWORD
;
282 src
= srcRow
+ srcRowStride
;
290 /** \sa convert_func */
292 TAG(texsubimage3d_unpack
)( const struct convert_info
*convert
)
294 const GLubyte
*src
= (const GLubyte
*)
295 _mesa_image_address( convert
->unpacking
, convert
->srcImage
,
296 convert
->width
, convert
->height
,
297 convert
->format
, convert
->type
, 0, 0, 0 );
298 const GLint srcImgStride
= (const GLubyte
*)
299 _mesa_image_address( convert
->unpacking
, convert
->srcImage
,
300 convert
->width
, convert
->height
,
301 convert
->format
, convert
->type
, 1, 0, 0 ) - src
;
302 const GLint srcRowStride
=
303 _mesa_image_row_stride( convert
->unpacking
, convert
->width
,
304 convert
->format
, convert
->type
);
308 _mesa_debug( NULL
, __FUNCTION__
"\n" );
311 if (convert
->width
& (DST_TEXELS_PER_DWORD
- 1)) {
312 /* Can't use dword conversion (i.e. when width = 1 and texels/dword = 2
313 * or width = 2 and texels/dword = 4).
315 DST_TYPE
*dst
= (DST_TYPE
*)((GLubyte
*)convert
->dstImage
+
316 ((convert
->zoffset
* convert
->height
+
317 convert
->yoffset
) * convert
->width
+
318 convert
->xoffset
) * DST_TEXEL_BYTES
);
319 for ( img
= 0 ; img
< convert
->depth
; img
++ ) {
320 const GLubyte
*srcImage
= src
;
321 for ( row
= 0 ; row
< convert
->height
; row
++ ) {
322 const GLubyte
*srcRow
= src
;
323 for ( col
= 0; col
< convert
->width
; col
++ ) {
324 CONVERT_TEXEL(*dst
, src
);
325 src
+= SRC_TEXEL_BYTES
;
327 src
= srcRow
+ srcRowStride
;
329 src
= srcImage
+ srcImgStride
;
333 /* the common case */
334 GLuint
*dst
= (GLuint
*)((GLubyte
*)convert
->dstImage
+
335 ((convert
->zoffset
* convert
->height
+
336 convert
->yoffset
) * convert
->width
+
337 convert
->xoffset
) * DST_TEXEL_BYTES
);
338 for ( img
= 0 ; img
< convert
->depth
; img
++ ) {
339 const GLubyte
*srcImage
= src
;
340 for ( row
= 0 ; row
< convert
->height
; row
++ ) {
341 #ifdef CONVERT_DIRECT
342 MEMCPY( dst
, src
, DST_ROW_STRIDE
);
344 dst
= (GLuint
*)((GLubyte
*)dst
+ DST_ROW_STRIDE
);
346 const GLubyte
*srcRow
= src
;
347 for ( col
= convert
->width
/ DST_TEXELS_PER_DWORD
; col
; col
-- ) {
348 CONVERT_TEXEL_DWORD( *dst
++, src
);
349 src
+= SRC_TEXEL_BYTES
* DST_TEXELS_PER_DWORD
;
351 src
= srcRow
+ srcRowStride
;
354 src
= srcImage
+ srcImgStride
;
364 /***************************************************************/
365 /** \name Requires pixelstore attributes and stride.
367 * \code width != dstImageWidth \endcode
369 * \code height != dstImageHeight \endcode
374 /** \sa convert_func */
376 TAG(texsubimage2d_stride_unpack
)( const struct convert_info
*convert
)
378 const GLubyte
*src
= (const GLubyte
*)
379 _mesa_image_address( convert
->unpacking
, convert
->srcImage
,
380 convert
->width
, convert
->height
,
381 convert
->format
, convert
->type
, 0, 0, 0 );
382 const GLint srcRowStride
=
383 _mesa_image_row_stride( convert
->unpacking
, convert
->width
,
384 convert
->format
, convert
->type
);
385 DST_TYPE
*dst
= (DST_TYPE
*)((GLubyte
*)convert
->dstImage
+
386 (convert
->yoffset
* convert
->dstImageWidth
+
387 convert
->xoffset
) * DST_TEXEL_BYTES
);
389 #ifndef CONVERT_DIRECT
390 GLint adjust
= convert
->dstImageWidth
- convert
->width
;
394 _mesa_debug( NULL
, __FUNCTION__
":\n" );
395 _mesa_debug( NULL
, " x=%d y=%d w=%d h=%d s=%d\n",
396 convert
->xoffset
, convert
->yoffset
, convert
->width
,
397 convert
->height
, convert
->dstImageWidth
);
400 for ( row
= 0 ; row
< convert
->height
; row
++ ) {
401 #ifdef CONVERT_DIRECT
402 MEMCPY( dst
, src
, DST_ROW_BYTES
);
404 dst
+= convert
->dstImageWidth
;
406 const GLubyte
*srcRow
= src
;
408 for ( col
= 0 ; col
< convert
->width
; col
++ ) {
409 CONVERT_TEXEL( *dst
++, src
);
410 src
+= SRC_TEXEL_BYTES
;
412 src
= srcRow
+ srcRowStride
;
420 /** \sa convert_func */
422 TAG(texsubimage3d_stride_unpack
)( const struct convert_info
*convert
)
424 const GLubyte
*src
= (const GLubyte
*)
425 _mesa_image_address( convert
->unpacking
, convert
->srcImage
,
426 convert
->width
, convert
->height
,
427 convert
->format
, convert
->type
, 0, 0, 0 );
428 const GLint srcImgStride
= (const GLubyte
*)
429 _mesa_image_address( convert
->unpacking
, convert
->srcImage
,
430 convert
->width
, convert
->height
,
431 convert
->format
, convert
->type
, 1, 0, 0 ) - src
;
432 const GLint srcRowStride
=
433 _mesa_image_row_stride( convert
->unpacking
, convert
->width
,
434 convert
->format
, convert
->type
);
435 DST_TYPE
*dst
= (DST_TYPE
*)((GLubyte
*)convert
->dstImage
+
436 ((convert
->zoffset
* convert
->dstImageHeight
+
437 convert
->yoffset
) * convert
->dstImageWidth
+
438 convert
->xoffset
) * DST_TEXEL_BYTES
);
440 #ifndef CONVERT_DIRECT
441 GLint adjust
= convert
->dstImageWidth
- convert
->width
;
445 _mesa_debug( NULL
, __FUNCTION__
":\n" );
446 _mesa_debug( NULL
, " x=%d y=%d w=%d h=%d s=%d\n",
447 convert
->xoffset
, convert
->yoffset
, convert
->width
,
448 convert
->height
, convert
->dstImageWidth
);
451 for ( img
= 0 ; img
< convert
->depth
; img
++ ) {
452 const GLubyte
*srcImage
= src
;
453 for ( row
= 0 ; row
< convert
->height
; row
++ ) {
454 #ifdef CONVERT_DIRECT
455 MEMCPY( dst
, src
, DST_ROW_BYTES
);
457 dst
+= convert
->dstImageWidth
;
459 const GLubyte
*srcRow
= src
;
461 for ( col
= 0 ; col
< convert
->width
; col
++ ) {
462 CONVERT_TEXEL( *dst
++, src
);
463 src
+= SRC_TEXEL_BYTES
;
465 src
= srcRow
+ srcRowStride
;
469 src
= srcImage
+ srcImgStride
;
478 /***********************************************************************/
479 /** \name Conversion function tables
484 * 2D texture conversion functions table.
488 static convert_func
TAG(texsubimage2d_tab
)[] = {
490 TAG(texsubimage2d_stride
),
491 TAG(texsubimage2d_unpack
),
492 TAG(texsubimage2d_stride_unpack
),
496 * 3D texture conversion functions table.
500 static convert_func
TAG(texsubimage3d_tab
)[] = {
502 TAG(texsubimage3d_stride
),
503 TAG(texsubimage3d_unpack
),
504 TAG(texsubimage3d_stride_unpack
),
510 #ifndef PRESERVE_DST_TYPE
512 #undef DST_TEXELS_PER_DWORD
515 #undef SRC_TEXEL_BYTES
516 #undef DST_TEXEL_BYTES
518 #undef DST_ROW_STRIDE
521 #undef CONVERT_TEXEL_DWORD
522 #undef CONVERT_DIRECT
526 #undef PRESERVE_DST_TYPE