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
);
392 adjust
= convert
->dstImageWidth
- convert
->width
;
395 _mesa_debug( NULL
, __FUNCTION__
":\n" );
396 _mesa_debug( NULL
, " x=%d y=%d w=%d h=%d s=%d\n",
397 convert
->xoffset
, convert
->yoffset
, convert
->width
,
398 convert
->height
, convert
->dstImageWidth
);
399 _mesa_debug( NULL
, " adjust=%d\n", adjust
);
402 for ( row
= 0 ; row
< convert
->height
; row
++ ) {
403 #ifdef CONVERT_DIRECT
404 MEMCPY( dst
, src
, DST_ROW_BYTES
);
406 dst
+= convert
->dstImageWidth
;
408 const GLubyte
*srcRow
= src
;
409 for ( col
= 0 ; col
< convert
->width
; col
++ ) {
410 CONVERT_TEXEL( *dst
++, src
);
411 src
+= SRC_TEXEL_BYTES
;
413 src
= srcRow
+ srcRowStride
;
421 /** \sa convert_func */
423 TAG(texsubimage3d_stride_unpack
)( const struct convert_info
*convert
)
425 const GLubyte
*src
= (const GLubyte
*)
426 _mesa_image_address( convert
->unpacking
, convert
->srcImage
,
427 convert
->width
, convert
->height
,
428 convert
->format
, convert
->type
, 0, 0, 0 );
429 const GLint srcImgStride
= (const GLubyte
*)
430 _mesa_image_address( convert
->unpacking
, convert
->srcImage
,
431 convert
->width
, convert
->height
,
432 convert
->format
, convert
->type
, 1, 0, 0 ) - src
;
433 const GLint srcRowStride
=
434 _mesa_image_row_stride( convert
->unpacking
, convert
->width
,
435 convert
->format
, convert
->type
);
436 DST_TYPE
*dst
= (DST_TYPE
*)((GLubyte
*)convert
->dstImage
+
437 ((convert
->zoffset
* convert
->dstImageHeight
+
438 convert
->yoffset
) * convert
->dstImageWidth
+
439 convert
->xoffset
) * DST_TEXEL_BYTES
);
441 GLint row
, col
= 0, img
;
444 adjust
= convert
->dstImageWidth
- convert
->width
;
447 _mesa_debug( NULL
, __FUNCTION__
":\n" );
448 _mesa_debug( NULL
, " x=%d y=%d w=%d h=%d s=%d\n",
449 convert
->xoffset
, convert
->yoffset
, convert
->width
,
450 convert
->height
, convert
->dstImageWidth
);
451 _mesa_debug( NULL
, " adjust=%d\n", adjust
);
454 for ( img
= 0 ; img
< convert
->depth
; img
++ ) {
455 const GLubyte
*srcImage
= src
;
456 for ( row
= 0 ; row
< convert
->height
; row
++ ) {
457 #ifdef CONVERT_DIRECT
458 MEMCPY( dst
, src
, DST_ROW_BYTES
);
460 dst
+= convert
->dstImageWidth
;
462 const GLubyte
*srcRow
= src
;
463 for ( col
= 0 ; col
< convert
->width
; col
++ ) {
464 CONVERT_TEXEL( *dst
++, src
);
465 src
+= SRC_TEXEL_BYTES
;
467 src
= srcRow
+ srcRowStride
;
471 src
= srcImage
+ srcImgStride
;
480 /***********************************************************************/
481 /** \name Conversion function tables
486 * 2D texture conversion functions table.
490 static convert_func
TAG(texsubimage2d_tab
)[] = {
492 TAG(texsubimage2d_stride
),
493 TAG(texsubimage2d_unpack
),
494 TAG(texsubimage2d_stride_unpack
),
498 * 3D texture conversion functions table.
502 static convert_func
TAG(texsubimage3d_tab
)[] = {
504 TAG(texsubimage3d_stride
),
505 TAG(texsubimage3d_unpack
),
506 TAG(texsubimage3d_stride_unpack
),
512 #ifndef PRESERVE_DST_TYPE
514 #undef DST_TEXELS_PER_DWORD
517 #undef SRC_TEXEL_BYTES
518 #undef DST_TEXEL_BYTES
520 #undef DST_ROW_STRIDE
523 #undef CONVERT_TEXEL_DWORD
524 #undef CONVERT_DIRECT
528 #undef PRESERVE_DST_TYPE