1 /* $Id: texutil.c,v 1.7 2000/09/13 22:07:20 brianp Exp $ */
4 * Mesa 3-D graphics library
7 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
41 * Texture utilities which may be useful to device drivers.
42 * See the texutil.h for the list of supported internal formats.
43 * It's expected that new formats will be added for new hardware.
48 * If the system is little endian and can do 4-byte word stores on
49 * non 4-byte-aligned addresses then we can use this optimization.
52 #define DO_32BIT_STORES000
58 * Convert texture image data into one a specific internal format.
60 * dstFormat - the destination internal format
61 * dstWidth, dstHeight - the destination image size
62 * dstImage - pointer to destination image buffer
63 * dstRowStride - bytes to jump between image rows
64 * srcWidth, srcHeight - size of texture image
65 * srcFormat, srcType - format and datatype of source image
66 * srcImage - pointer to user's texture image
67 * packing - describes how user's texture image is packed.
68 * Return: pointer to resulting image data or NULL if error or out of memory
69 * or NULL if we can't process the given image format/type/internalFormat
72 * Supported type conversions:
73 * srcFormat srcType dstFormat
74 * GL_INTENSITY GL_UNSIGNED_BYTE MESA_I8
75 * GL_LUMINANCE GL_UNSIGNED_BYTE MESA_L8
76 * GL_ALPHA GL_UNSIGNED_BYTE MESA_A8
77 * GL_COLOR_INDEX GL_UNSIGNED_BYTE MESA_C8
78 * GL_LUMINANCE_ALPHA GL_UNSIGNED_BYTE MESA_A8_L8
79 * GL_RGB GL_UNSIGNED_BYTE MESA_R5_G6_B5
80 * GL_RGB GL_UNSIGNED_SHORT_5_6_5 MESA_R5_G6_B5
81 * GL_RGBA GL_UNSIGNED_BYTE MESA_A4_R4_G4_B4
82 * GL_BGRA GL_UNSIGNED_SHORT_4_4_4_4_REV MESA_A4_R4_G4_B4
83 * GL_BGRA GL_UNSIGHED_SHORT_1_5_5_5_REV MESA_A1_R5_G5_B5
84 * GL_RGBA GL_UNSIGNED_BYTE MESA_A1_R5_G5_B5
85 * GL_BGRA GL_UNSIGNED_INT_8_8_8_8_REV MESA_A8_R8_G8_B8
86 * GL_RGBA GL_UNSIGNED_BYTE MESA_A8_R8_G8_B8
87 * GL_RGB GL_UNSIGNED_BYTE MESA_A8_R8_G8_B8
88 * more to be added for new drivers...
91 * Some hardware only supports texture images of specific aspect ratios.
92 * This code will do power-of-two image up-scaling if that's needed.
97 _mesa_convert_teximage(MesaIntTexFormat dstFormat
,
98 GLint dstWidth
, GLint dstHeight
, GLvoid
*dstImage
,
100 GLint srcWidth
, GLint srcHeight
,
101 GLenum srcFormat
, GLenum srcType
,
102 const GLvoid
*srcImage
,
103 const struct gl_pixelstore_attrib
*packing
)
105 const GLint wScale
= dstWidth
/ srcWidth
; /* must be power of two */
106 const GLint hScale
= dstHeight
/ srcHeight
; /* must be power of two */
107 ASSERT(dstWidth
>= srcWidth
);
108 ASSERT(dstHeight
>= srcHeight
);
118 if (srcType
!= GL_UNSIGNED_BYTE
||
119 ((srcFormat
!= GL_INTENSITY
) &&
120 (srcFormat
!= GL_LUMINANCE
) &&
121 (srcFormat
!= GL_ALPHA
) &&
122 (srcFormat
!= GL_COLOR_INDEX
))) {
123 /* bad internal format / srcFormat combination */
127 /* store as 8-bit texels */
128 if (wScale
== 1 && hScale
== 1) {
129 /* no scaling needed - fast case */
130 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
131 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
132 const GLint srcStride
= _mesa_image_row_stride(packing
,
133 srcWidth
, srcFormat
, srcType
);
134 GLubyte
*dst
= (GLubyte
*) dstImage
;
136 for (row
= 0; row
< dstHeight
; row
++) {
137 MEMCPY(dst
, src
, dstWidth
* sizeof(GLubyte
));
143 /* must rescale image */
144 GLubyte
*dst
= (GLubyte
*) dstImage
;
146 for (row
= 0; row
< dstHeight
; row
++) {
147 GLint srcRow
= row
/ hScale
;
148 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
149 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
151 for (col
= 0; col
< dstWidth
; col
++) {
152 dst
[col
] = src
[col
/ wScale
];
161 if (srcType
!= GL_UNSIGNED_BYTE
|| srcFormat
!= GL_LUMINANCE_ALPHA
) {
165 /* store as 16-bit texels */
166 if (wScale
== 1 && hScale
== 1) {
167 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
168 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
169 const GLint srcStride
= _mesa_image_row_stride(packing
,
170 srcWidth
, srcFormat
, srcType
);
171 GLushort
*dst
= (GLushort
*) dstImage
;
173 for (row
= 0; row
< dstHeight
; row
++) {
174 for (col
= 0; col
< dstWidth
; col
++) {
175 GLubyte luminance
= src
[col
* 2 + 0];
176 GLubyte alpha
= src
[col
* 2 + 1];
177 dst
[col
] = ((GLushort
) alpha
<< 8) | luminance
;
179 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
185 GLushort
*dst
= (GLushort
*) dstImage
;
187 for (row
= 0; row
< dstHeight
; row
++) {
188 GLint srcRow
= row
/ hScale
;
189 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
190 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
191 const GLint srcStride
= _mesa_image_row_stride(packing
,
192 srcWidth
, srcFormat
, srcType
);
193 for (col
= 0; col
< dstWidth
; col
++) {
194 GLint srcCol
= col
/ wScale
;
195 GLubyte luminance
= src
[srcCol
* 2 + 0];
196 GLubyte alpha
= src
[srcCol
* 2 + 1];
197 dst
[col
] = ((GLushort
) alpha
<< 8) | luminance
;
199 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
207 if (srcFormat
== GL_RGB
&& srcType
== GL_UNSIGNED_SHORT_5_6_5
) {
208 /* special, optimized case */
209 if (wScale
== 1 && hScale
== 1) {
210 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
211 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
212 const GLint srcStride
= _mesa_image_row_stride(packing
,
213 srcWidth
, srcFormat
, srcType
);
214 GLushort
*dst
= (GLushort
*) dstImage
;
216 for (row
= 0; row
< dstHeight
; row
++) {
217 MEMCPY(dst
, src
, dstWidth
* sizeof(GLushort
));
219 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
223 /* must rescale image */
224 GLushort
*dst
= (GLushort
*) dstImage
;
226 for (row
= 0; row
< dstHeight
; row
++) {
227 GLint srcRow
= row
/ hScale
;
228 const GLushort
*src
= _mesa_image_address(packing
, srcImage
,
229 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
231 for (col
= 0; col
< dstWidth
; col
++) {
232 dst
[col
] = src
[col
/ wScale
];
234 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
238 else if (srcFormat
== GL_RGB
&& srcType
== GL_UNSIGNED_BYTE
) {
240 if (wScale
== 1 && hScale
== 1) {
241 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
242 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
243 const GLint srcStride
= _mesa_image_row_stride(packing
,
244 srcWidth
, srcFormat
, srcType
);
245 #ifdef DO_32BIT_STORES
246 GLuint
*dst
= (GLuint
*) dstImage
;
248 for (row
= 0; row
< dstHeight
; row
++) {
250 GLint halfDstWidth
= dstWidth
>> 1;
251 for (col
= col3
= 0; col
< halfDstWidth
; col
++, col3
+= 6) {
252 GLubyte r0
= src
[col3
+ 0];
253 GLubyte g0
= src
[col3
+ 1];
254 GLubyte b0
= src
[col3
+ 2];
255 GLubyte r1
= src
[col3
+ 3];
256 GLubyte g1
= src
[col3
+ 4];
257 GLubyte b1
= src
[col3
+ 5];
258 GLuint d0
= ((r0
& 0xf8) << 8)
260 | ((b0
& 0xf8) >> 3);
261 GLuint d1
= ((r1
& 0xf8) << 8)
263 | ((b1
& 0xf8) >> 3);
264 dst
[col
] = (d1
<< 16) | d0
;
267 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
269 #else /* 16-bit stores */
270 GLushort
*dst
= (GLushort
*) dstImage
;
272 for (row
= 0; row
< dstHeight
; row
++) {
274 for (col
= col3
= 0; col
< dstWidth
; col
++, col3
+= 3) {
275 GLubyte r
= src
[col3
+ 0];
276 GLubyte g
= src
[col3
+ 1];
277 GLubyte b
= src
[col3
+ 2];
278 dst
[col
] = ((r
& 0xf8) << 8)
283 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
288 /* must rescale image */
289 GLushort
*dst
= (GLushort
*) dstImage
;
291 for (row
= 0; row
< dstHeight
; row
++) {
292 GLint srcRow
= row
/ hScale
;
293 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
294 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
296 for (col
= 0; col
< dstWidth
; col
++) {
297 GLint col3
= (col
/ wScale
) * 3;
298 GLubyte r
= src
[col3
+ 0];
299 GLubyte g
= src
[col3
+ 1];
300 GLubyte b
= src
[col3
+ 2];
301 dst
[col
] = ((r
& 0xf8) << 8)
305 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
309 else if (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
) {
310 /* general case (used by Quake3) */
311 if (wScale
== 1 && hScale
== 1) {
312 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
313 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
314 const GLint srcStride
= _mesa_image_row_stride(packing
,
315 srcWidth
, srcFormat
, srcType
);
316 #ifdef DO_32BIT_STORES
317 GLuint
*dst
= dstImage
;
319 for (row
= 0; row
< dstHeight
; row
++) {
321 GLint halfDstWidth
= dstWidth
>> 1;
322 for (col
= col4
= 0; col
< halfDstWidth
; col
++, col4
+= 8) {
323 GLubyte r0
= src
[col4
+ 0];
324 GLubyte g0
= src
[col4
+ 1];
325 GLubyte b0
= src
[col4
+ 2];
326 GLubyte r1
= src
[col4
+ 4];
327 GLubyte g1
= src
[col4
+ 5];
328 GLubyte b1
= src
[col4
+ 6];
329 GLuint d0
= ((r0
& 0xf8) << 8)
331 | ((b0
& 0xf8) >> 3);
332 GLuint d1
= ((r1
& 0xf8) << 8)
334 | ((b1
& 0xf8) >> 3);
335 dst
[col
] = (d1
<< 16) | d0
;
338 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
340 #else /* 16-bit stores */
341 GLushort
*dst
= (GLushort
*) dstImage
;
343 for (row
= 0; row
< dstHeight
; row
++) {
345 for (col
= col4
= 0; col
< dstWidth
; col
++, col4
+= 4) {
346 GLubyte r
= src
[col4
+ 0];
347 GLubyte g
= src
[col4
+ 1];
348 GLubyte b
= src
[col4
+ 2];
349 dst
[col
] = ((r
& 0xf8) << 8)
354 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
359 /* must rescale image */
360 GLushort
*dst
= (GLushort
*) dstImage
;
362 for (row
= 0; row
< dstHeight
; row
++) {
363 GLint srcRow
= row
/ hScale
;
364 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
365 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
367 for (col
= 0; col
< dstWidth
; col
++) {
368 GLint col4
= (col
/ wScale
) * 4;
369 GLubyte r
= src
[col4
+ 0];
370 GLubyte g
= src
[col4
+ 1];
371 GLubyte b
= src
[col4
+ 2];
372 dst
[col
] = ((r
& 0xf8) << 8)
376 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
381 /* can't handle this srcFormat/srcType combination */
386 case MESA_A4_R4_G4_B4
:
387 /* store as 16-bit texels (GR_TEXFMT_ARGB_4444) */
388 if (srcFormat
== GL_BGRA
&& srcType
== GL_UNSIGNED_SHORT_4_4_4_4_REV
){
389 /* special, optimized case */
390 if (wScale
== 1 && hScale
== 1) {
391 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
392 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
393 const GLint srcStride
= _mesa_image_row_stride(packing
,
394 srcWidth
, srcFormat
, srcType
);
395 GLushort
*dst
= (GLushort
*) dstImage
;
397 for (row
= 0; row
< dstHeight
; row
++) {
398 MEMCPY(dst
, src
, dstWidth
* sizeof(GLushort
));
400 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
404 /* must rescale image */
405 GLushort
*dst
= (GLushort
*) dstImage
;
407 for (row
= 0; row
< dstHeight
; row
++) {
408 GLint srcRow
= row
/ hScale
;
409 const GLushort
*src
= _mesa_image_address(packing
, srcImage
,
410 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
412 for (col
= 0; col
< dstWidth
; col
++) {
413 dst
[col
] = src
[col
/ wScale
];
415 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
419 else if (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
) {
421 if (wScale
== 1 && hScale
== 1) {
422 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
423 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
424 const GLint srcStride
= _mesa_image_row_stride(packing
,
425 srcWidth
, srcFormat
, srcType
);
426 #ifdef DO_32BIT_STORES
427 GLuint
*dst
= dstImage
;
429 for (row
= 0; row
< dstHeight
; row
++) {
431 GLint halfDstWidth
= dstWidth
>> 1;
432 for (col
= col4
= 0; col
< halfDstWidth
; col
++, col4
+= 8) {
433 GLubyte r0
= src
[col4
+ 0];
434 GLubyte g0
= src
[col4
+ 1];
435 GLubyte b0
= src
[col4
+ 2];
436 GLubyte a0
= src
[col4
+ 3];
437 GLubyte r1
= src
[col4
+ 4];
438 GLubyte g1
= src
[col4
+ 5];
439 GLubyte b1
= src
[col4
+ 6];
440 GLubyte a1
= src
[col4
+ 7];
441 GLuint d0
= ((a0
& 0xf0) << 8)
444 | ((b0
& 0xf0) >> 4);
445 GLuint d1
= ((a1
& 0xf0) << 8)
448 | ((b1
& 0xf0) >> 4);
449 dst
[col
] = (d1
<< 16) | d0
;
452 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
454 #else /* 16-bit stores */
455 GLushort
*dst
= (GLushort
*) dstImage
;
457 for (row
= 0; row
< dstHeight
; row
++) {
459 for (col
= col4
= 0; col
< dstWidth
; col
++, col4
+= 4) {
460 GLubyte r
= src
[col4
+ 0];
461 GLubyte g
= src
[col4
+ 1];
462 GLubyte b
= src
[col4
+ 2];
463 GLubyte a
= src
[col4
+ 3];
464 dst
[col
] = ((a
& 0xf0) << 8)
470 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
475 /* must rescale image */
476 GLushort
*dst
= (GLushort
*) dstImage
;
478 for (row
= 0; row
< dstHeight
; row
++) {
479 GLint srcRow
= row
/ hScale
;
480 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
481 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
483 for (col
= 0; col
< dstWidth
; col
++) {
484 GLint col4
= (col
/ wScale
) * 4;
485 GLubyte r
= src
[col4
+ 0];
486 GLubyte g
= src
[col4
+ 1];
487 GLubyte b
= src
[col4
+ 2];
488 GLubyte a
= src
[col4
+ 3];
489 dst
[col
] = ((a
& 0xf0) << 8)
494 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
499 /* can't handle this format/srcType combination */
504 case MESA_A1_R5_G5_B5
:
505 /* store as 16-bit texels (GR_TEXFMT_ARGB_1555) */
506 if (srcFormat
== GL_BGRA
&& srcType
== GL_UNSIGNED_SHORT_1_5_5_5_REV
){
507 /* special, optimized case */
508 if (wScale
== 1 && hScale
== 1) {
509 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
510 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
511 const GLint srcStride
= _mesa_image_row_stride(packing
,
512 srcWidth
, srcFormat
, srcType
);
513 GLushort
*dst
= (GLushort
*) dstImage
;
515 for (row
= 0; row
< dstHeight
; row
++) {
516 MEMCPY(dst
, src
, dstWidth
* sizeof(GLushort
));
518 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
522 /* must rescale image */
523 GLushort
*dst
= (GLushort
*) dstImage
;
525 for (row
= 0; row
< dstHeight
; row
++) {
526 GLint srcRow
= row
/ hScale
;
527 const GLushort
*src
= _mesa_image_address(packing
, srcImage
,
528 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
530 for (col
= 0; col
< dstWidth
; col
++) {
531 dst
[col
] = src
[col
/ wScale
];
533 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
537 else if (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
) {
539 if (wScale
== 1 && hScale
== 1) {
540 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
541 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
542 const GLint srcStride
= _mesa_image_row_stride(packing
,
543 srcWidth
, srcFormat
, srcType
);
544 GLushort
*dst
= (GLushort
*) dstImage
;
546 for (row
= 0; row
< dstHeight
; row
++) {
548 for (col
= col4
= 0; col
< dstWidth
; col
++, col4
+= 4) {
549 GLubyte r
= src
[col4
+ 0];
550 GLubyte g
= src
[col4
+ 1];
551 GLubyte b
= src
[col4
+ 2];
552 GLubyte a
= src
[col4
+ 3];
553 dst
[col
] = ((a
& 0x80) << 8)
559 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
563 /* must rescale image */
564 GLushort
*dst
= (GLushort
*) dstImage
;
566 for (row
= 0; row
< dstHeight
; row
++) {
567 GLint srcRow
= row
/ hScale
;
568 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
569 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
571 for (col
= 0; col
< dstWidth
; col
++) {
572 GLint col4
= (col
/ wScale
) * 4;
573 GLubyte r
= src
[col4
+ 0];
574 GLubyte g
= src
[col4
+ 1];
575 GLubyte b
= src
[col4
+ 2];
576 GLubyte a
= src
[col4
+ 3];
577 dst
[col
] = ((a
& 0x80) << 8)
582 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
587 /* can't handle this source format/type combination */
592 case MESA_A8_R8_G8_B8
:
593 case MESA_FF_R8_G8_B8
:
595 if (srcFormat
== GL_BGRA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
){
596 /* special, optimized case */
597 if (wScale
== 1 && hScale
== 1) {
598 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
599 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
600 const GLint srcStride
= _mesa_image_row_stride(packing
,
601 srcWidth
, srcFormat
, srcType
);
602 GLuint
*dst
= dstImage
;
604 for (row
= 0; row
< dstHeight
; row
++) {
605 MEMCPY(dst
, src
, dstWidth
* sizeof(GLuint
));
607 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
611 /* must rescale image */
612 GLuint
*dst
= dstImage
;
614 for (row
= 0; row
< dstHeight
; row
++) {
615 GLint srcRow
= row
/ hScale
;
616 const GLuint
*src
= _mesa_image_address(packing
, srcImage
,
617 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
619 for (col
= 0; col
< dstWidth
; col
++) {
620 dst
[col
] = src
[col
/ wScale
];
622 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
626 else if (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
) {
628 if (wScale
== 1 && hScale
== 1) {
629 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
630 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
631 const GLint srcStride
= _mesa_image_row_stride(packing
,
632 srcWidth
, srcFormat
, srcType
);
633 GLuint
*dst
= dstImage
;
635 for (row
= 0; row
< dstHeight
; row
++) {
637 for (col
= col4
= 0; col
< dstWidth
; col
++, col4
+= 4) {
638 GLubyte r
= src
[col4
+ 0];
639 GLubyte g
= src
[col4
+ 1];
640 GLubyte b
= src
[col4
+ 2];
641 GLubyte a
= src
[col4
+ 3];
642 dst
[col
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
645 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
649 /* must rescale image */
650 GLuint
*dst
= dstImage
;
652 for (row
= 0; row
< dstHeight
; row
++) {
653 GLint srcRow
= row
/ hScale
;
654 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
655 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
657 for (col
= 0; col
< dstWidth
; col
++) {
658 GLint col4
= (col
/ wScale
) * 4;
659 GLubyte r
= src
[col4
+ 0];
660 GLubyte g
= src
[col4
+ 1];
661 GLubyte b
= src
[col4
+ 2];
662 GLubyte a
= src
[col4
+ 3];
663 dst
[col
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
665 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
669 else if (srcFormat
== GL_RGB
&& srcType
== GL_UNSIGNED_BYTE
) {
671 if (wScale
== 1 && hScale
== 1) {
672 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
673 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
674 const GLint srcStride
= _mesa_image_row_stride(packing
,
675 srcWidth
, srcFormat
, srcType
);
676 GLuint
*dst
= dstImage
;
678 for (row
= 0; row
< dstHeight
; row
++) {
680 for (col
= col3
= 0; col
< dstWidth
; col
++, col3
+= 3) {
681 GLubyte r
= src
[col3
+ 0];
682 GLubyte g
= src
[col3
+ 1];
683 GLubyte b
= src
[col3
+ 2];
685 dst
[col
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
688 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
692 /* must rescale image */
693 GLuint
*dst
= dstImage
;
695 for (row
= 0; row
< dstHeight
; row
++) {
696 GLint srcRow
= row
/ hScale
;
697 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
698 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
700 for (col
= 0; col
< dstWidth
; col
++) {
701 GLint col3
= (col
/ wScale
) * 3;
702 GLubyte r
= src
[col3
+ 0];
703 GLubyte g
= src
[col3
+ 1];
704 GLubyte b
= src
[col3
+ 2];
706 dst
[col
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
708 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
713 /* can't handle this source format/type combination */
716 if (dstFormat
== MESA_FF_R8_G8_B8
) {
717 /* set alpha bytes to 0xff */
719 GLubyte
*dst
= (GLubyte
*) dstImage
;
720 for (i
= 0; i
< dstWidth
* dstHeight
; i
++) {
721 dst
[i
* 4 + 3] = 0xff;
727 /* unexpected internal format! */
736 * Replace a subregion of a texture image with new data.
738 * dstFormat - destination image format
739 * dstXoffset, dstYoffset - destination for new subregion
740 * dstWidth, dstHeight - total size of dest image
741 * dstImage - pointer to dest image
742 * dstRowStride - bytes to jump between image rows
743 * width, height - size of region to copy/replace
744 * srcWidth, srcHeight - size of the corresponding gl_texture_image
745 * srcFormat, srcType - source image format and datatype
746 * srcImage - source image
747 * packing - source image packing information.
748 * Return: GL_TRUE or GL_FALSE for success, failure
751 * Like _mesa_convert_teximage(), we can do power-of-two image scaling
752 * to accomodate hardware with texture image aspect ratio constraints.
753 * dstWidth / srcWidth is used to compute the horizontal scaling factor and
754 * dstHeight / srcHeight is used to compute the vertical scaling factor.
757 _mesa_convert_texsubimage(MesaIntTexFormat dstFormat
,
758 GLint dstXoffset
, GLint dstYoffset
,
759 GLint dstWidth
, GLint dstHeight
, GLvoid
*dstImage
,
761 GLint width
, GLint height
,
762 GLint srcWidth
, GLint srcHeight
,
763 GLenum srcFormat
, GLenum srcType
,
764 const GLvoid
*srcImage
,
765 const struct gl_pixelstore_attrib
*packing
)
767 const GLint wScale
= dstWidth
/ srcWidth
; /* must be power of two */
768 const GLint hScale
= dstHeight
/ srcHeight
; /* must be power of two */
769 ASSERT(dstWidth
>= srcWidth
);
770 ASSERT(dstHeight
>= srcHeight
);
777 dstXoffset
*= wScale
;
778 dstYoffset
*= hScale
;
780 /* XXX hscale != 1 and wscale != 1 not tested!!!! */
787 if (srcType
!= GL_UNSIGNED_BYTE
||
788 ((srcFormat
!= GL_INTENSITY
) &&
789 (srcFormat
!= GL_LUMINANCE
) &&
790 (srcFormat
!= GL_ALPHA
) &&
791 (srcFormat
!= GL_COLOR_INDEX
))) {
792 /* bad internal format / srcFormat combination */
796 /* store as 8-bit texels */
797 if (wScale
== 1 && hScale
== 1) {
798 /* no scaling needed - fast case */
799 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
800 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
801 const GLint srcStride
= _mesa_image_row_stride(packing
,
802 width
, srcFormat
, srcType
);
803 GLubyte
*dst
= (GLubyte
*) dstImage
804 + dstYoffset
* dstRowStride
+ dstXoffset
;
806 for (row
= 0; row
< height
; row
++) {
807 MEMCPY(dst
, src
, width
* sizeof(GLubyte
));
813 /* must rescale image */
814 GLubyte
*dst
= (GLubyte
*) dstImage
815 + dstYoffset
* dstRowStride
+ dstXoffset
;
817 for (row
= 0; row
< height
; row
++) {
818 GLint srcRow
= row
/ hScale
;
819 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
820 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
822 for (col
= 0; col
< width
; col
++) {
823 dst
[col
] = src
[col
/ wScale
];
832 if (srcType
!= GL_UNSIGNED_BYTE
|| srcFormat
!= GL_LUMINANCE_ALPHA
) {
836 /* store as 16-bit texels */
837 if (wScale
== 1 && hScale
== 1) {
838 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
839 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
840 const GLint srcStride
= _mesa_image_row_stride(packing
,
841 width
, srcFormat
, srcType
);
842 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
843 + dstYoffset
* dstRowStride
) + dstXoffset
;
845 for (row
= 0; row
< height
; row
++) {
846 for (col
= 0; col
< width
; col
++) {
847 GLubyte luminance
= src
[col
* 2 + 0];
848 GLubyte alpha
= src
[col
* 2 + 1];
849 dst
[col
] = ((GLushort
) alpha
<< 8) | luminance
;
851 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
857 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
858 + dstYoffset
* dstRowStride
) + dstXoffset
;
860 for (row
= 0; row
< height
; row
++) {
861 GLint srcRow
= row
/ hScale
;
862 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
863 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
864 const GLint srcStride
= _mesa_image_row_stride(packing
,
865 width
, srcFormat
, srcType
);
866 for (col
= 0; col
< width
; col
++) {
867 GLint srcCol
= col
/ wScale
;
868 GLubyte luminance
= src
[srcCol
* 2 + 0];
869 GLubyte alpha
= src
[srcCol
* 2 + 1];
870 dst
[col
] = ((GLushort
) alpha
<< 8) | luminance
;
872 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
880 if (srcFormat
== GL_RGB
&& srcType
== GL_UNSIGNED_SHORT_5_6_5
) {
881 /* special, optimized case */
882 if (wScale
== 1 && hScale
== 1) {
883 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
884 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
885 const GLint srcStride
= _mesa_image_row_stride(packing
,
886 width
, srcFormat
, srcType
);
887 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
888 + dstYoffset
* dstRowStride
) + dstXoffset
;
890 for (row
= 0; row
< height
; row
++) {
891 MEMCPY(dst
, src
, width
* sizeof(GLushort
));
893 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
897 /* must rescale image */
898 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
899 + dstYoffset
* dstRowStride
) + dstXoffset
;
901 for (row
= 0; row
< height
; row
++) {
902 GLint srcRow
= row
/ hScale
;
903 const GLushort
*src
= _mesa_image_address(packing
, srcImage
,
904 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
906 for (col
= 0; col
< width
; col
++) {
907 dst
[col
] = src
[col
/ wScale
];
909 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
913 else if (srcFormat
== GL_RGB
&& srcType
== GL_UNSIGNED_BYTE
) {
915 if (wScale
== 1 && hScale
== 1) {
916 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
917 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
918 const GLint srcStride
= _mesa_image_row_stride(packing
,
919 width
, srcFormat
, srcType
);
920 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
921 + dstYoffset
* dstRowStride
) + dstXoffset
;
923 for (row
= 0; row
< height
; row
++) {
925 for (col
= col3
= 0; col
< width
; col
++, col3
+= 3) {
926 GLubyte r
= src
[col3
+ 0];
927 GLubyte g
= src
[col3
+ 1];
928 GLubyte b
= src
[col3
+ 2];
929 dst
[col
] = ((r
& 0xf8) << 8)
934 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
938 /* must rescale image */
939 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
940 + dstYoffset
* dstRowStride
) + dstXoffset
;
942 for (row
= 0; row
< height
; row
++) {
943 GLint srcRow
= row
/ hScale
;
944 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
945 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
947 for (col
= 0; col
< width
; col
++) {
948 GLint col3
= (col
/ wScale
) * 3;
949 GLubyte r
= src
[col3
+ 0];
950 GLubyte g
= src
[col3
+ 1];
951 GLubyte b
= src
[col3
+ 2];
952 dst
[col
] = ((r
& 0xf8) << 8)
956 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
960 else if (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
) {
961 /* general case (used by Quake3) */
962 if (wScale
== 1 && hScale
== 1) {
963 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
964 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
965 const GLint srcStride
= _mesa_image_row_stride(packing
,
966 width
, srcFormat
, srcType
);
967 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
968 + dstYoffset
* dstRowStride
) + dstXoffset
;
970 for (row
= 0; row
< height
; row
++) {
972 for (col
= col4
= 0; col
< width
; col
++, col4
+= 4) {
973 GLubyte r
= src
[col4
+ 0];
974 GLubyte g
= src
[col4
+ 1];
975 GLubyte b
= src
[col4
+ 2];
976 dst
[col
] = ((r
& 0xf8) << 8)
981 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
985 /* must rescale image */
986 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
987 + dstYoffset
* dstRowStride
) + dstXoffset
;
989 for (row
= 0; row
< height
; row
++) {
990 GLint srcRow
= row
/ hScale
;
991 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
992 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
994 for (col
= 0; col
< width
; col
++) {
995 GLint col4
= (col
/ wScale
) * 4;
996 GLubyte r
= src
[col4
+ 0];
997 GLubyte g
= src
[col4
+ 1];
998 GLubyte b
= src
[col4
+ 2];
999 dst
[col
] = ((r
& 0xf8) << 8)
1001 | ((b
& 0xf8) >> 3);
1003 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
1008 /* can't handle this srcFormat/srcType combination */
1013 case MESA_A4_R4_G4_B4
:
1014 /* store as 16-bit texels (GR_TEXFMT_ARGB_4444) */
1015 if (srcFormat
== GL_BGRA
&& srcType
== GL_UNSIGNED_SHORT_4_4_4_4_REV
){
1016 /* special, optimized case */
1017 if (wScale
== 1 && hScale
== 1) {
1018 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
1019 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
1020 const GLint srcStride
= _mesa_image_row_stride(packing
,
1021 width
, srcFormat
, srcType
);
1022 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
1023 + dstYoffset
* dstRowStride
) + dstXoffset
;
1025 for (row
= 0; row
< height
; row
++) {
1026 MEMCPY(dst
, src
, width
* sizeof(GLushort
));
1028 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
1032 /* must rescale image */
1033 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
1034 + dstYoffset
* dstRowStride
) + dstXoffset
;
1036 for (row
= 0; row
< height
; row
++) {
1037 GLint srcRow
= row
/ hScale
;
1038 const GLushort
*src
= _mesa_image_address(packing
, srcImage
,
1039 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
1041 for (col
= 0; col
< width
; col
++) {
1042 dst
[col
] = src
[col
/ wScale
];
1044 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
1048 else if (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
) {
1050 if (wScale
== 1 && hScale
== 1) {
1051 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
1052 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
1053 const GLint srcStride
= _mesa_image_row_stride(packing
,
1054 width
, srcFormat
, srcType
);
1055 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
1056 + dstYoffset
* dstRowStride
) + dstXoffset
;
1058 for (row
= 0; row
< height
; row
++) {
1060 for (col
= col4
= 0; col
< width
; col
++, col4
+= 4) {
1061 GLubyte r
= src
[col4
+ 0];
1062 GLubyte g
= src
[col4
+ 1];
1063 GLubyte b
= src
[col4
+ 2];
1064 GLubyte a
= src
[col4
+ 3];
1065 dst
[col
] = ((a
& 0xf0) << 8)
1068 | ((b
& 0xf0) >> 4);
1071 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
1075 /* must rescale image */
1076 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
1077 + dstYoffset
* dstRowStride
) + dstXoffset
;
1079 for (row
= 0; row
< height
; row
++) {
1080 GLint srcRow
= row
/ hScale
;
1081 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
1082 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
1084 for (col
= 0; col
< width
; col
++) {
1085 GLint col4
= (col
/ wScale
) * 4;
1086 GLubyte r
= src
[col4
+ 0];
1087 GLubyte g
= src
[col4
+ 1];
1088 GLubyte b
= src
[col4
+ 2];
1089 GLubyte a
= src
[col4
+ 3];
1090 dst
[col
] = ((a
& 0xf0) << 8)
1093 | ((b
& 0xf0) >> 4);
1095 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
1100 /* can't handle this format/srcType combination */
1105 case MESA_A1_R5_G5_B5
:
1106 /* store as 16-bit texels (GR_TEXFMT_ARGB_1555) */
1107 if (srcFormat
== GL_BGRA
&& srcType
== GL_UNSIGNED_SHORT_1_5_5_5_REV
){
1108 /* special, optimized case */
1109 if (wScale
== 1 && hScale
== 1) {
1110 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
1111 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
1112 const GLint srcStride
= _mesa_image_row_stride(packing
,
1113 width
, srcFormat
, srcType
);
1114 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
1115 + dstYoffset
* dstRowStride
) + dstXoffset
;
1117 for (row
= 0; row
< height
; row
++) {
1118 MEMCPY(dst
, src
, width
* sizeof(GLushort
));
1120 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
1124 /* must rescale image */
1125 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
1126 + dstYoffset
* dstRowStride
) + dstXoffset
;
1128 for (row
= 0; row
< height
; row
++) {
1129 GLint srcRow
= row
/ hScale
;
1130 const GLushort
*src
= _mesa_image_address(packing
, srcImage
,
1131 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
1133 for (col
= 0; col
< width
; col
++) {
1134 dst
[col
] = src
[col
/ wScale
];
1136 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
1140 else if (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
) {
1142 if (wScale
== 1 && hScale
== 1) {
1143 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
1144 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
1145 const GLint srcStride
= _mesa_image_row_stride(packing
,
1146 width
, srcFormat
, srcType
);
1147 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
1148 + dstYoffset
* dstRowStride
) + dstXoffset
;
1150 for (row
= 0; row
< height
; row
++) {
1152 for (col
= col4
= 0; col
< width
; col
++, col4
+= 4) {
1153 GLubyte r
= src
[col4
+ 0];
1154 GLubyte g
= src
[col4
+ 1];
1155 GLubyte b
= src
[col4
+ 2];
1156 GLubyte a
= src
[col4
+ 3];
1157 dst
[col
] = ((a
& 0x80) << 8)
1160 | ((b
& 0xf8) >> 3);
1163 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
1167 /* must rescale image */
1168 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
1169 + dstYoffset
* dstRowStride
) + dstXoffset
;
1171 for (row
= 0; row
< height
; row
++) {
1172 GLint srcRow
= row
/ hScale
;
1173 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
1174 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
1176 for (col
= 0; col
< width
; col
++) {
1177 GLint col4
= (col
/ wScale
) * 4;
1178 GLubyte r
= src
[col4
+ 0];
1179 GLubyte g
= src
[col4
+ 1];
1180 GLubyte b
= src
[col4
+ 2];
1181 GLubyte a
= src
[col4
+ 3];
1182 dst
[col
] = ((a
& 0x80) << 8)
1185 | ((b
& 0xf8) >> 3);
1187 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
1192 /* can't handle this source format/type combination */
1197 case MESA_A8_R8_G8_B8
:
1198 case MESA_FF_R8_G8_B8
:
1200 if (srcFormat
== GL_BGRA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
){
1201 /* special, optimized case */
1202 if (wScale
== 1 && hScale
== 1) {
1203 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
1204 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
1205 const GLint srcStride
= _mesa_image_row_stride(packing
,
1206 width
, srcFormat
, srcType
);
1207 GLuint
*dst
= (GLuint
*) ((GLubyte
*) dstImage
1208 + dstYoffset
* dstRowStride
) + dstXoffset
;
1210 for (row
= 0; row
< height
; row
++) {
1211 MEMCPY(dst
, src
, width
* sizeof(GLuint
));
1213 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
1217 /* must rescale image */
1218 GLuint
*dst
= (GLuint
*) ((GLubyte
*) dstImage
1219 + dstYoffset
* dstRowStride
) + dstXoffset
;
1221 for (row
= 0; row
< height
; row
++) {
1222 GLint srcRow
= row
/ hScale
;
1223 const GLuint
*src
= _mesa_image_address(packing
, srcImage
,
1224 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
1226 for (col
= 0; col
< width
; col
++) {
1227 dst
[col
] = src
[col
/ wScale
];
1229 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
1233 else if (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
) {
1235 if (wScale
== 1 && hScale
== 1) {
1236 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
1237 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
1238 const GLint srcStride
= _mesa_image_row_stride(packing
,
1239 width
, srcFormat
, srcType
);
1240 GLuint
*dst
= (GLuint
*) ((GLubyte
*) dstImage
1241 + dstYoffset
* dstRowStride
) + dstXoffset
;
1243 for (row
= 0; row
< height
; row
++) {
1245 for (col
= col4
= 0; col
< width
; col
++, col4
+= 4) {
1246 GLubyte r
= src
[col4
+ 0];
1247 GLubyte g
= src
[col4
+ 1];
1248 GLubyte b
= src
[col4
+ 2];
1249 GLubyte a
= src
[col4
+ 3];
1250 dst
[col
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
1253 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
1257 /* must rescale image */
1258 GLuint
*dst
= (GLuint
*) ((GLubyte
*) dstImage
1259 + dstYoffset
* dstRowStride
) + dstXoffset
;
1261 for (row
= 0; row
< height
; row
++) {
1262 GLint srcRow
= row
/ hScale
;
1263 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
1264 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
1266 for (col
= 0; col
< width
; col
++) {
1267 GLint col4
= (col
/ wScale
) * 4;
1268 GLubyte r
= src
[col4
+ 0];
1269 GLubyte g
= src
[col4
+ 1];
1270 GLubyte b
= src
[col4
+ 2];
1271 GLubyte a
= src
[col4
+ 3];
1272 dst
[col
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
1274 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
1279 /* can't handle this source format/type combination */
1282 if (dstFormat
== MESA_FF_R8_G8_B8
) {
1283 /* set alpha bytes to 0xff */
1285 GLubyte
*dst
= (GLubyte
*) dstImage
1286 + dstYoffset
* dstRowStride
+ dstXoffset
;
1287 for (row
= 0; row
< height
; row
++) {
1288 for (col
= 0; col
< width
; col
++) {
1289 dst
[col
* 4 + 3] = 0xff;
1291 dst
= dst
+ dstRowStride
;
1298 /* unexpected internal format! */
1308 * Used to convert 16-bit texels into GLubyte color components.
1310 static GLubyte R5G6B5toRed
[0xffff];
1311 static GLubyte R5G6B5toGreen
[0xffff];
1312 static GLubyte R5G6B5toBlue
[0xffff];
1314 static GLubyte A4R4G4B4toRed
[0xffff];
1315 static GLubyte A4R4G4B4toGreen
[0xffff];
1316 static GLubyte A4R4G4B4toBlue
[0xffff];
1317 static GLubyte A4R4G4B4toAlpha
[0xffff];
1319 static GLubyte A1R5G5B5toRed
[0xffff];
1320 static GLubyte A1R5G5B5toGreen
[0xffff];
1321 static GLubyte A1R5G5B5toBlue
[0xffff];
1322 static GLubyte A1R5G5B5toAlpha
[0xffff];
1325 generate_lookup_tables(void)
1328 for (i
= 0; i
<= 0xffff; i
++) {
1329 GLint r
= (i
>> 8) & 0xf8;
1330 GLint g
= (i
>> 3) & 0xfc;
1331 GLint b
= (i
<< 3) & 0xf8;
1336 R5G6B5toGreen
[i
] = g
;
1337 R5G6B5toBlue
[i
] = b
;
1340 for (i
= 0; i
<= 0xffff; i
++) {
1341 GLint r
= (i
>> 8) & 0xf;
1342 GLint g
= (i
>> 4) & 0xf;
1343 GLint b
= (i
) & 0xf;
1344 GLint a
= (i
>> 12) & 0xf;
1349 A4R4G4B4toRed
[i
] = r
;
1350 A4R4G4B4toGreen
[i
] = g
;
1351 A4R4G4B4toBlue
[i
] = b
;
1352 A4R4G4B4toAlpha
[i
] = a
;
1355 for (i
= 0; i
<= 0xffff; i
++) {
1356 GLint r
= (i
>> 10) & 0xf8;
1357 GLint g
= (i
>> 5) & 0xf8;
1358 GLint b
= (i
) & 0xf8;
1359 GLint a
= (i
>> 15) & 0x1;
1364 A1R5G5B5toRed
[i
] = r
;
1365 A1R5G5B5toGreen
[i
] = g
;
1366 A1R5G5B5toBlue
[i
] = b
;
1367 A1R5G5B5toAlpha
[i
] = a
;
1374 * Convert a texture image from an internal format to one of Mesa's
1375 * core internal formats. This is likely to be used by glGetTexImage
1376 * and for fetching texture images when falling back to software rendering.
1379 * srcFormat - source image format
1380 * srcWidth, srcHeight - source image size
1381 * srcImage - source image pointer
1382 * srcRowStride - bytes to jump between image rows
1383 * dstWidth, dstHeight - size of dest image
1384 * dstFormat - format of dest image (must be one of Mesa's IntFormat values)
1385 * dstImage - pointer to dest image
1387 * This function will do power of two image down-scaling to accomodate
1388 * drivers with limited texture image aspect ratios.
1389 * The implicit dest data type is GL_UNSIGNED_BYTE.
1392 _mesa_unconvert_teximage(MesaIntTexFormat srcFormat
,
1393 GLint srcWidth
, GLint srcHeight
,
1394 const GLvoid
*srcImage
, GLint srcRowStride
,
1395 GLint dstWidth
, GLint dstHeight
,
1396 GLenum dstFormat
, GLubyte
*dstImage
)
1398 static GLboolean firstCall
= GL_TRUE
;
1399 const GLint wScale
= srcWidth
/ dstWidth
; /* must be power of two */
1400 const GLint hScale
= srcHeight
/ dstHeight
; /* must be power of two */
1401 ASSERT(srcWidth
>= dstWidth
);
1402 ASSERT(srcHeight
>= dstHeight
);
1407 generate_lookup_tables();
1408 firstCall
= GL_FALSE
;
1411 switch (srcFormat
) {
1417 if (srcFormat
== MESA_I8
) {
1418 ASSERT(dstFormat
== GL_INTENSITY
);
1420 else if (srcFormat
== MESA_L8
) {
1421 ASSERT(dstFormat
== GL_LUMINANCE
);
1423 else if (srcFormat
== MESA_A8
) {
1424 ASSERT(dstFormat
== GL_ALPHA
);
1426 else if (srcFormat
== MESA_C8
) {
1427 ASSERT(dstFormat
== GL_COLOR_INDEX
);
1430 if (wScale
== 1 && hScale
== 1) {
1432 MEMCPY(dstImage
, srcImage
, dstWidth
* dstHeight
* sizeof(GLubyte
));
1436 const GLubyte
*src8
= (const GLubyte
*) srcImage
;
1438 for (row
= 0; row
< dstHeight
; row
++) {
1439 GLint srcRow
= row
* hScale
;
1440 for (col
= 0; col
< dstWidth
; col
++) {
1441 GLint srcCol
= col
* wScale
;
1442 *dstImage
++ = src8
[srcRow
* srcWidth
+ srcCol
];
1448 ASSERT(dstFormat
== GL_LUMINANCE_ALPHA
);
1449 if (wScale
== 1 && hScale
== 1) {
1450 GLint i
, n
= dstWidth
* dstHeight
;
1451 const GLushort
*texel
= (const GLushort
*) srcImage
;
1452 for (i
= 0; i
< n
; i
++) {
1453 const GLushort tex
= *texel
++;
1454 *dstImage
++ = (tex
& 0xff); /* luminance */
1455 *dstImage
++ = (tex
>> 8); /* alpha */
1460 const GLushort
*src16
= (const GLushort
*) srcImage
;
1462 for (row
= 0; row
< dstHeight
; row
++) {
1463 GLint srcRow
= row
* hScale
;
1464 for (col
= 0; col
< dstWidth
; col
++) {
1465 GLint srcCol
= col
* wScale
;
1466 const GLushort tex
= src16
[srcRow
* srcWidth
+ srcCol
];
1467 *dstImage
++ = (tex
& 0xff); /* luminance */
1468 *dstImage
++ = (tex
>> 8); /* alpha */
1474 ASSERT(dstFormat
== GL_RGB
);
1475 if (wScale
== 1 && hScale
== 1) {
1476 GLint i
, n
= dstWidth
* dstHeight
;
1477 const GLushort
*texel
= (const GLushort
*) srcImage
;
1478 for (i
= 0; i
< n
; i
++) {
1479 const GLushort tex
= *texel
++;
1480 *dstImage
++ = R5G6B5toRed
[tex
];
1481 *dstImage
++ = R5G6B5toGreen
[tex
];
1482 *dstImage
++ = R5G6B5toBlue
[tex
];
1487 const GLushort
*src16
= (const GLushort
*) srcImage
;
1489 for (row
= 0; row
< dstHeight
; row
++) {
1490 GLint srcRow
= row
* hScale
;
1491 for (col
= 0; col
< dstWidth
; col
++) {
1492 GLint srcCol
= col
* wScale
;
1493 const GLushort tex
= src16
[srcRow
* srcWidth
+ srcCol
];
1494 *dstImage
++ = R5G6B5toRed
[tex
];
1495 *dstImage
++ = R5G6B5toGreen
[tex
];
1496 *dstImage
++ = R5G6B5toBlue
[tex
];
1501 case MESA_A4_R4_G4_B4
:
1502 ASSERT(dstFormat
== GL_RGBA
);
1503 if (wScale
== 1 && hScale
== 1) {
1504 GLint i
, n
= dstWidth
* dstHeight
;
1505 const GLushort
*texel
= (const GLushort
*) srcImage
;
1506 for (i
= 0; i
< n
; i
++) {
1507 const GLushort tex
= *texel
++;
1508 *dstImage
++ = A4R4G4B4toRed
[tex
];
1509 *dstImage
++ = A4R4G4B4toGreen
[tex
];
1510 *dstImage
++ = A4R4G4B4toBlue
[tex
];
1511 *dstImage
++ = A4R4G4B4toAlpha
[tex
];
1516 const GLushort
*src16
= (const GLushort
*) srcImage
;
1518 for (row
= 0; row
< dstHeight
; row
++) {
1519 GLint srcRow
= row
* hScale
;
1520 for (col
= 0; col
< dstWidth
; col
++) {
1521 GLint srcCol
= col
* wScale
;
1522 const GLushort tex
= src16
[srcRow
* srcWidth
+ srcCol
];
1523 *dstImage
++ = A4R4G4B4toRed
[tex
];
1524 *dstImage
++ = A4R4G4B4toGreen
[tex
];
1525 *dstImage
++ = A4R4G4B4toBlue
[tex
];
1526 *dstImage
++ = A4R4G4B4toAlpha
[tex
];
1531 case MESA_A1_R5_G5_B5
:
1532 ASSERT(dstFormat
== GL_RGBA
);
1533 if (wScale
== 1 && hScale
== 1) {
1534 GLint i
, n
= dstWidth
* dstHeight
;
1535 const GLushort
*texel
= (const GLushort
*) srcImage
;
1536 for (i
= 0; i
< n
; i
++) {
1537 const GLushort tex
= *texel
++;
1538 *dstImage
++ = A1R5G5B5toRed
[tex
];
1539 *dstImage
++ = A1R5G5B5toGreen
[tex
];
1540 *dstImage
++ = A1R5G5B5toBlue
[tex
];
1541 *dstImage
++ = A1R5G5B5toAlpha
[tex
];
1546 const GLushort
*src16
= (const GLushort
*) srcImage
;
1548 for (row
= 0; row
< dstHeight
; row
++) {
1549 GLint srcRow
= row
* hScale
;
1550 for (col
= 0; col
< dstWidth
; col
++) {
1551 GLint srcCol
= col
* wScale
;
1552 const GLushort tex
= src16
[srcRow
* srcWidth
+ srcCol
];
1553 *dstImage
++ = A1R5G5B5toRed
[tex
];
1554 *dstImage
++ = A1R5G5B5toGreen
[tex
];
1555 *dstImage
++ = A1R5G5B5toBlue
[tex
];
1556 *dstImage
++ = A1R5G5B5toAlpha
[tex
];
1561 case MESA_A8_R8_G8_B8
:
1562 case MESA_FF_R8_G8_B8
:
1563 ASSERT(dstFormat
== GL_RGBA
);
1564 if (wScale
== 1 && hScale
== 1) {
1565 GLint i
, n
= dstWidth
* dstHeight
;
1566 const GLuint
*texel
= (const GLuint
*) srcImage
;
1567 for (i
= 0; i
< n
; i
++) {
1568 const GLuint tex
= *texel
++;
1569 *dstImage
++ = (tex
>> 16) & 0xff; /* R */
1570 *dstImage
++ = (tex
>> 8) & 0xff; /* G */
1571 *dstImage
++ = (tex
) & 0xff; /* B */
1572 *dstImage
++ = (tex
>> 24) & 0xff; /* A */
1577 const GLuint
*src
= (const GLuint
*) srcImage
;
1579 for (row
= 0; row
< dstHeight
; row
++) {
1580 GLint srcRow
= row
* hScale
;
1581 for (col
= 0; col
< dstWidth
; col
++) {
1582 GLint srcCol
= col
* wScale
;
1583 const GLuint tex
= src
[srcRow
* srcWidth
+ srcCol
];
1584 *dstImage
++ = (tex
>> 16) & 0xff; /* R */
1585 *dstImage
++ = (tex
>> 8) & 0xff; /* G */
1586 *dstImage
++ = (tex
) & 0xff; /* B */
1587 *dstImage
++ = (tex
>> 24) & 0xff; /* A */
1593 gl_problem(NULL
, "bad srcFormat in _mesa_uncovert_teximage()");
1600 * Given an internal Mesa driver texture format, fill in the component
1601 * bit sizes in the given texture image struct.
1604 _mesa_set_teximage_component_sizes(MesaIntTexFormat mesaFormat
,
1605 struct gl_texture_image
*texImage
)
1607 static const GLint bitSizes
[][8] = {
1608 /* format R G B A I L C */
1609 { MESA_I8
, 0, 0, 0, 0, 8, 0, 0 },
1610 { MESA_L8
, 0, 0, 0, 0, 0, 8, 0 },
1611 { MESA_A8
, 0, 0, 0, 8, 0, 0, 0 },
1612 { MESA_C8
, 0, 0, 0, 0, 0, 0, 8 },
1613 { MESA_A8_L8
, 0, 0, 0, 8, 0, 8, 0 },
1614 { MESA_R5_G6_B5
, 5, 6, 5, 0, 0, 0, 0 },
1615 { MESA_A4_R4_G4_B4
, 4, 4, 4, 4, 0, 0, 0 },
1616 { MESA_A1_R5_G5_B5
, 5, 5, 5, 1, 0, 0, 0 },
1617 { MESA_A8_R8_G8_B8
, 8, 8, 8, 8, 0, 0, 0 },
1618 { MESA_FF_R8_G8_B8
, 8, 8, 8, 8, 0, 0, 0 },
1619 { -1, 0, 0, 0, 0, 0, 0, 0 }
1622 for (i
= 0; i
< bitSizes
[i
][0] >= 0; i
++) {
1623 if (bitSizes
[i
][0] == mesaFormat
) {
1624 texImage
->RedBits
= bitSizes
[i
][1];
1625 texImage
->GreenBits
= bitSizes
[i
][2];
1626 texImage
->BlueBits
= bitSizes
[i
][3];
1627 texImage
->AlphaBits
= bitSizes
[i
][4];
1628 texImage
->IntensityBits
= bitSizes
[i
][5];
1629 texImage
->LuminanceBits
= bitSizes
[i
][6];
1630 texImage
->IndexBits
= bitSizes
[i
][7];
1634 gl_problem(NULL
, "bad format in _mesa_set_teximage_component_sizes");