1 /* $Id: texutil.c,v 1.11 2000/12/26 05:09:29 keithw 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
= (const GLubyte
*)
131 _mesa_image_address(packing
, srcImage
, srcWidth
, srcHeight
,
132 srcFormat
, srcType
, 0, 0, 0);
133 const GLint srcStride
= _mesa_image_row_stride(packing
,
134 srcWidth
, srcFormat
, srcType
);
135 GLubyte
*dst
= (GLubyte
*) dstImage
;
137 for (row
= 0; row
< dstHeight
; row
++) {
139 for (i
= 0 ; i
< dstWidth
; i
++)
140 fprintf(stderr
, "%02x ", src
[i
]);
141 fprintf(stderr
, "\n");
142 MEMCPY(dst
, src
, dstWidth
* sizeof(GLubyte
));
148 /* must rescale image */
149 GLubyte
*dst
= (GLubyte
*) dstImage
;
151 for (row
= 0; row
< dstHeight
; row
++) {
152 GLint srcRow
= row
/ hScale
;
153 const GLubyte
*src
= (const GLubyte
*)
154 _mesa_image_address(packing
, srcImage
, srcWidth
,
155 srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
157 for (col
= 0; col
< dstWidth
; col
++) {
158 dst
[col
] = src
[col
/ wScale
];
167 if (srcType
!= GL_UNSIGNED_BYTE
|| srcFormat
!= GL_LUMINANCE_ALPHA
) {
171 /* store as 16-bit texels */
172 if (wScale
== 1 && hScale
== 1) {
173 const GLubyte
*src
= (const GLubyte
*)
174 _mesa_image_address(packing
, srcImage
, srcWidth
, srcHeight
,
175 srcFormat
, srcType
, 0, 0, 0);
176 const GLint srcStride
= _mesa_image_row_stride(packing
,
177 srcWidth
, srcFormat
, srcType
);
178 GLushort
*dst
= (GLushort
*) dstImage
;
180 for (row
= 0; row
< dstHeight
; row
++) {
181 for (col
= 0; col
< dstWidth
; col
++) {
182 GLubyte luminance
= src
[col
* 2 + 0];
183 GLubyte alpha
= src
[col
* 2 + 1];
184 dst
[col
] = ((GLushort
) alpha
<< 8) | luminance
;
186 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
192 GLushort
*dst
= (GLushort
*) dstImage
;
194 for (row
= 0; row
< dstHeight
; row
++) {
195 GLint srcRow
= row
/ hScale
;
196 const GLubyte
*src
= (const GLubyte
*)
197 _mesa_image_address(packing
, srcImage
, srcWidth
,
198 srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
199 const GLint srcStride
= _mesa_image_row_stride(packing
,
200 srcWidth
, srcFormat
, srcType
);
201 for (col
= 0; col
< dstWidth
; col
++) {
202 GLint srcCol
= col
/ wScale
;
203 GLubyte luminance
= src
[srcCol
* 2 + 0];
204 GLubyte alpha
= src
[srcCol
* 2 + 1];
205 dst
[col
] = ((GLushort
) alpha
<< 8) | luminance
;
207 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
215 if (srcFormat
== GL_RGB
&& srcType
== GL_UNSIGNED_SHORT_5_6_5
) {
216 /* special, optimized case */
217 if (wScale
== 1 && hScale
== 1) {
218 const GLubyte
*src
= (const GLubyte
*)
219 _mesa_image_address(packing
, srcImage
, srcWidth
, srcHeight
,
220 srcFormat
, srcType
, 0, 0, 0);
221 const GLint srcStride
= _mesa_image_row_stride(packing
,
222 srcWidth
, srcFormat
, srcType
);
223 GLushort
*dst
= (GLushort
*) dstImage
;
225 for (row
= 0; row
< dstHeight
; row
++) {
226 MEMCPY(dst
, src
, dstWidth
* sizeof(GLushort
));
228 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
232 /* must rescale image */
233 GLushort
*dst
= (GLushort
*) dstImage
;
235 for (row
= 0; row
< dstHeight
; row
++) {
236 GLint srcRow
= row
/ hScale
;
237 const GLushort
*src
= (const GLushort
*)
238 _mesa_image_address(packing
, srcImage
, srcWidth
,
239 srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
241 for (col
= 0; col
< dstWidth
; col
++) {
242 dst
[col
] = src
[col
/ wScale
];
244 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
248 else if (srcFormat
== GL_RGB
&& srcType
== GL_UNSIGNED_BYTE
) {
250 if (wScale
== 1 && hScale
== 1) {
251 const GLubyte
*src
= (const GLubyte
*)
252 _mesa_image_address(packing
, srcImage
, srcWidth
, srcHeight
,
253 srcFormat
, srcType
, 0, 0, 0);
254 const GLint srcStride
= _mesa_image_row_stride(packing
,
255 srcWidth
, srcFormat
, srcType
);
256 #ifdef DO_32BIT_STORES
257 GLuint
*dst
= (GLuint
*) dstImage
;
259 for (row
= 0; row
< dstHeight
; row
++) {
261 GLint halfDstWidth
= dstWidth
>> 1;
262 for (col
= col3
= 0; col
< halfDstWidth
; col
++, col3
+= 6) {
263 GLubyte r0
= src
[col3
+ 0];
264 GLubyte g0
= src
[col3
+ 1];
265 GLubyte b0
= src
[col3
+ 2];
266 GLubyte r1
= src
[col3
+ 3];
267 GLubyte g1
= src
[col3
+ 4];
268 GLubyte b1
= src
[col3
+ 5];
269 GLuint d0
= ((r0
& 0xf8) << 8)
271 | ((b0
& 0xf8) >> 3);
272 GLuint d1
= ((r1
& 0xf8) << 8)
274 | ((b1
& 0xf8) >> 3);
275 dst
[col
] = (d1
<< 16) | d0
;
278 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
280 #else /* 16-bit stores */
281 GLushort
*dst
= (GLushort
*) dstImage
;
283 for (row
= 0; row
< dstHeight
; row
++) {
285 for (col
= col3
= 0; col
< dstWidth
; col
++, col3
+= 3) {
286 GLubyte r
= src
[col3
+ 0];
287 GLubyte g
= src
[col3
+ 1];
288 GLubyte b
= src
[col3
+ 2];
289 dst
[col
] = ((r
& 0xf8) << 8)
294 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
299 /* must rescale image */
300 GLushort
*dst
= (GLushort
*) dstImage
;
302 for (row
= 0; row
< dstHeight
; row
++) {
303 GLint srcRow
= row
/ hScale
;
304 const GLubyte
*src
= (const GLubyte
*)
305 _mesa_image_address(packing
, srcImage
, srcWidth
,
306 srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
308 for (col
= 0; col
< dstWidth
; col
++) {
309 GLint col3
= (col
/ wScale
) * 3;
310 GLubyte r
= src
[col3
+ 0];
311 GLubyte g
= src
[col3
+ 1];
312 GLubyte b
= src
[col3
+ 2];
313 dst
[col
] = ((r
& 0xf8) << 8)
317 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
321 else if (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
) {
322 /* general case (used by Quake3) */
323 if (wScale
== 1 && hScale
== 1) {
324 const GLubyte
*src
= (const GLubyte
*)
325 _mesa_image_address(packing
, srcImage
, srcWidth
, srcHeight
,
326 srcFormat
, srcType
, 0, 0, 0);
327 const GLint srcStride
= _mesa_image_row_stride(packing
,
328 srcWidth
, srcFormat
, srcType
);
329 #ifdef DO_32BIT_STORES
330 GLuint
*dst
= dstImage
;
332 for (row
= 0; row
< dstHeight
; row
++) {
334 GLint halfDstWidth
= dstWidth
>> 1;
335 for (col
= col4
= 0; col
< halfDstWidth
; col
++, col4
+= 8) {
336 GLubyte r0
= src
[col4
+ 0];
337 GLubyte g0
= src
[col4
+ 1];
338 GLubyte b0
= src
[col4
+ 2];
339 GLubyte r1
= src
[col4
+ 4];
340 GLubyte g1
= src
[col4
+ 5];
341 GLubyte b1
= src
[col4
+ 6];
342 GLuint d0
= ((r0
& 0xf8) << 8)
344 | ((b0
& 0xf8) >> 3);
345 GLuint d1
= ((r1
& 0xf8) << 8)
347 | ((b1
& 0xf8) >> 3);
348 dst
[col
] = (d1
<< 16) | d0
;
351 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
353 #else /* 16-bit stores */
354 GLushort
*dst
= (GLushort
*) dstImage
;
356 for (row
= 0; row
< dstHeight
; row
++) {
358 for (col
= col4
= 0; col
< dstWidth
; col
++, col4
+= 4) {
359 GLubyte r
= src
[col4
+ 0];
360 GLubyte g
= src
[col4
+ 1];
361 GLubyte b
= src
[col4
+ 2];
362 dst
[col
] = ((r
& 0xf8) << 8)
367 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
372 /* must rescale image */
373 GLushort
*dst
= (GLushort
*) dstImage
;
375 for (row
= 0; row
< dstHeight
; row
++) {
376 GLint srcRow
= row
/ hScale
;
377 const GLubyte
*src
= (const GLubyte
*)
378 _mesa_image_address(packing
, srcImage
, srcWidth
,
379 srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
381 for (col
= 0; col
< dstWidth
; col
++) {
382 GLint col4
= (col
/ wScale
) * 4;
383 GLubyte r
= src
[col4
+ 0];
384 GLubyte g
= src
[col4
+ 1];
385 GLubyte b
= src
[col4
+ 2];
386 dst
[col
] = ((r
& 0xf8) << 8)
390 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
395 /* can't handle this srcFormat/srcType combination */
400 case MESA_A4_R4_G4_B4
:
401 /* store as 16-bit texels (GR_TEXFMT_ARGB_4444) */
402 if (srcFormat
== GL_BGRA
&& srcType
== GL_UNSIGNED_SHORT_4_4_4_4_REV
){
403 /* special, optimized case */
404 if (wScale
== 1 && hScale
== 1) {
405 const GLubyte
*src
= (const GLubyte
*)
406 _mesa_image_address(packing
, srcImage
, srcWidth
, srcHeight
,
407 srcFormat
, srcType
, 0, 0, 0);
408 const GLint srcStride
= _mesa_image_row_stride(packing
,
409 srcWidth
, srcFormat
, srcType
);
410 GLushort
*dst
= (GLushort
*) dstImage
;
412 for (row
= 0; row
< dstHeight
; row
++) {
413 MEMCPY(dst
, src
, dstWidth
* sizeof(GLushort
));
415 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
419 /* must rescale image */
420 GLushort
*dst
= (GLushort
*) dstImage
;
422 for (row
= 0; row
< dstHeight
; row
++) {
423 GLint srcRow
= row
/ hScale
;
424 const GLushort
*src
= (const GLushort
*)
425 _mesa_image_address(packing
, srcImage
, srcWidth
,
426 srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
428 for (col
= 0; col
< dstWidth
; col
++) {
429 dst
[col
] = src
[col
/ wScale
];
431 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
435 else if (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
) {
437 if (wScale
== 1 && hScale
== 1) {
438 const GLubyte
*src
= (const GLubyte
*)
439 _mesa_image_address(packing
, srcImage
, srcWidth
, srcHeight
,
440 srcFormat
, srcType
, 0, 0, 0);
441 const GLint srcStride
= _mesa_image_row_stride(packing
,
442 srcWidth
, srcFormat
, srcType
);
443 #ifdef DO_32BIT_STORES
444 GLuint
*dst
= dstImage
;
446 for (row
= 0; row
< dstHeight
; row
++) {
448 GLint halfDstWidth
= dstWidth
>> 1;
449 for (col
= col4
= 0; col
< halfDstWidth
; col
++, col4
+= 8) {
450 GLubyte r0
= src
[col4
+ 0];
451 GLubyte g0
= src
[col4
+ 1];
452 GLubyte b0
= src
[col4
+ 2];
453 GLubyte a0
= src
[col4
+ 3];
454 GLubyte r1
= src
[col4
+ 4];
455 GLubyte g1
= src
[col4
+ 5];
456 GLubyte b1
= src
[col4
+ 6];
457 GLubyte a1
= src
[col4
+ 7];
458 GLuint d0
= ((a0
& 0xf0) << 8)
461 | ((b0
& 0xf0) >> 4);
462 GLuint d1
= ((a1
& 0xf0) << 8)
465 | ((b1
& 0xf0) >> 4);
466 dst
[col
] = (d1
<< 16) | d0
;
469 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
471 #else /* 16-bit stores */
472 GLushort
*dst
= (GLushort
*) dstImage
;
474 for (row
= 0; row
< dstHeight
; row
++) {
476 for (col
= col4
= 0; col
< dstWidth
; col
++, col4
+= 4) {
477 GLubyte r
= src
[col4
+ 0];
478 GLubyte g
= src
[col4
+ 1];
479 GLubyte b
= src
[col4
+ 2];
480 GLubyte a
= src
[col4
+ 3];
481 dst
[col
] = ((a
& 0xf0) << 8)
487 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
492 /* must rescale image */
493 GLushort
*dst
= (GLushort
*) dstImage
;
495 for (row
= 0; row
< dstHeight
; row
++) {
496 GLint srcRow
= row
/ hScale
;
497 const GLubyte
*src
= (const GLubyte
*)
498 _mesa_image_address(packing
, srcImage
, srcWidth
,
499 srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
501 for (col
= 0; col
< dstWidth
; col
++) {
502 GLint col4
= (col
/ wScale
) * 4;
503 GLubyte r
= src
[col4
+ 0];
504 GLubyte g
= src
[col4
+ 1];
505 GLubyte b
= src
[col4
+ 2];
506 GLubyte a
= src
[col4
+ 3];
507 dst
[col
] = ((a
& 0xf0) << 8)
512 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
517 /* can't handle this format/srcType combination */
522 case MESA_A1_R5_G5_B5
:
523 /* store as 16-bit texels (GR_TEXFMT_ARGB_1555) */
524 if (srcFormat
== GL_BGRA
&& srcType
== GL_UNSIGNED_SHORT_1_5_5_5_REV
){
525 /* special, optimized case */
526 if (wScale
== 1 && hScale
== 1) {
527 const GLubyte
*src
= (const GLubyte
*)
528 _mesa_image_address(packing
, srcImage
, srcWidth
, srcHeight
,
529 srcFormat
, srcType
, 0, 0, 0);
530 const GLint srcStride
= _mesa_image_row_stride(packing
,
531 srcWidth
, srcFormat
, srcType
);
532 GLushort
*dst
= (GLushort
*) dstImage
;
534 for (row
= 0; row
< dstHeight
; row
++) {
535 MEMCPY(dst
, src
, dstWidth
* sizeof(GLushort
));
537 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
541 /* must rescale image */
542 GLushort
*dst
= (GLushort
*) dstImage
;
544 for (row
= 0; row
< dstHeight
; row
++) {
545 GLint srcRow
= row
/ hScale
;
546 const GLushort
*src
= (const GLushort
*)
547 _mesa_image_address(packing
, srcImage
, srcWidth
,
548 srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
550 for (col
= 0; col
< dstWidth
; col
++) {
551 dst
[col
] = src
[col
/ wScale
];
553 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
557 else if (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
) {
559 if (wScale
== 1 && hScale
== 1) {
560 const GLubyte
*src
= (const GLubyte
*)
561 _mesa_image_address(packing
, srcImage
, srcWidth
, srcHeight
,
562 srcFormat
, srcType
, 0, 0, 0);
563 const GLint srcStride
= _mesa_image_row_stride(packing
,
564 srcWidth
, srcFormat
, srcType
);
565 GLushort
*dst
= (GLushort
*) dstImage
;
567 for (row
= 0; row
< dstHeight
; row
++) {
569 for (col
= col4
= 0; col
< dstWidth
; col
++, col4
+= 4) {
570 GLubyte r
= src
[col4
+ 0];
571 GLubyte g
= src
[col4
+ 1];
572 GLubyte b
= src
[col4
+ 2];
573 GLubyte a
= src
[col4
+ 3];
574 dst
[col
] = ((a
& 0x80) << 8)
580 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
584 /* must rescale image */
585 GLushort
*dst
= (GLushort
*) dstImage
;
587 for (row
= 0; row
< dstHeight
; row
++) {
588 GLint srcRow
= row
/ hScale
;
589 const GLubyte
*src
= (const GLubyte
*)
590 _mesa_image_address(packing
, srcImage
, srcWidth
,
591 srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
593 for (col
= 0; col
< dstWidth
; col
++) {
594 GLint col4
= (col
/ wScale
) * 4;
595 GLubyte r
= src
[col4
+ 0];
596 GLubyte g
= src
[col4
+ 1];
597 GLubyte b
= src
[col4
+ 2];
598 GLubyte a
= src
[col4
+ 3];
599 dst
[col
] = ((a
& 0x80) << 8)
604 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
609 /* can't handle this source format/type combination */
614 case MESA_A8_R8_G8_B8
:
615 case MESA_FF_R8_G8_B8
:
617 if (srcFormat
== GL_BGRA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
){
618 /* special, optimized case */
619 if (wScale
== 1 && hScale
== 1) {
620 const GLubyte
*src
= (const GLubyte
*)
621 _mesa_image_address(packing
, srcImage
, srcWidth
, srcHeight
,
622 srcFormat
, srcType
, 0, 0, 0);
623 const GLint srcStride
= _mesa_image_row_stride(packing
,
624 srcWidth
, srcFormat
, srcType
);
625 GLuint
*dst
= (GLuint
*) dstImage
;
627 for (row
= 0; row
< dstHeight
; row
++) {
628 MEMCPY(dst
, src
, dstWidth
* sizeof(GLuint
));
630 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
634 /* must rescale image */
635 GLuint
*dst
= (GLuint
*) dstImage
;
637 for (row
= 0; row
< dstHeight
; row
++) {
638 GLint srcRow
= row
/ hScale
;
639 const GLuint
*src
= (const GLuint
*)
640 _mesa_image_address(packing
, srcImage
, srcWidth
,
641 srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
643 for (col
= 0; col
< dstWidth
; col
++) {
644 dst
[col
] = src
[col
/ wScale
];
646 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
650 else if (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
) {
652 if (wScale
== 1 && hScale
== 1) {
653 const GLubyte
*src
= (const GLubyte
*)
654 _mesa_image_address(packing
, srcImage
, srcWidth
, srcHeight
,
655 srcFormat
, srcType
, 0, 0, 0);
656 const GLint srcStride
= _mesa_image_row_stride(packing
,
657 srcWidth
, srcFormat
, srcType
);
658 GLuint
*dst
= (GLuint
*) dstImage
;
660 for (row
= 0; row
< dstHeight
; row
++) {
662 for (col
= col4
= 0; col
< dstWidth
; col
++, col4
+= 4) {
663 GLubyte r
= src
[col4
+ 0];
664 GLubyte g
= src
[col4
+ 1];
665 GLubyte b
= src
[col4
+ 2];
666 GLubyte a
= src
[col4
+ 3];
667 dst
[col
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
670 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
674 /* must rescale image */
675 GLuint
*dst
= (GLuint
*) dstImage
;
677 for (row
= 0; row
< dstHeight
; row
++) {
678 GLint srcRow
= row
/ hScale
;
679 const GLubyte
*src
= (const GLubyte
*)
680 _mesa_image_address(packing
, srcImage
, srcWidth
,
681 srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
683 for (col
= 0; col
< dstWidth
; col
++) {
684 GLint col4
= (col
/ wScale
) * 4;
685 GLubyte r
= src
[col4
+ 0];
686 GLubyte g
= src
[col4
+ 1];
687 GLubyte b
= src
[col4
+ 2];
688 GLubyte a
= src
[col4
+ 3];
689 dst
[col
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
691 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
695 else if (srcFormat
== GL_RGB
&& srcType
== GL_UNSIGNED_BYTE
) {
697 if (wScale
== 1 && hScale
== 1) {
698 const GLubyte
*src
= (const GLubyte
*)
699 _mesa_image_address(packing
, srcImage
, srcWidth
, srcHeight
,
700 srcFormat
, srcType
, 0, 0, 0);
701 const GLint srcStride
= _mesa_image_row_stride(packing
,
702 srcWidth
, srcFormat
, srcType
);
703 GLuint
*dst
= (GLuint
*) dstImage
;
705 for (row
= 0; row
< dstHeight
; row
++) {
707 for (col
= col3
= 0; col
< dstWidth
; col
++, col3
+= 3) {
708 GLubyte r
= src
[col3
+ 0];
709 GLubyte g
= src
[col3
+ 1];
710 GLubyte b
= src
[col3
+ 2];
712 dst
[col
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
715 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
719 /* must rescale image */
720 GLuint
*dst
= (GLuint
*) dstImage
;
722 for (row
= 0; row
< dstHeight
; row
++) {
723 GLint srcRow
= row
/ hScale
;
724 const GLubyte
*src
= (const GLubyte
*)
725 _mesa_image_address(packing
, srcImage
, srcWidth
,
726 srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
728 for (col
= 0; col
< dstWidth
; col
++) {
729 GLint col3
= (col
/ wScale
) * 3;
730 GLubyte r
= src
[col3
+ 0];
731 GLubyte g
= src
[col3
+ 1];
732 GLubyte b
= src
[col3
+ 2];
734 dst
[col
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
736 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
741 /* can't handle this source format/type combination */
744 if (dstFormat
== MESA_FF_R8_G8_B8
) {
745 /* set alpha bytes to 0xff */
747 GLubyte
*dst
= (GLubyte
*) dstImage
;
748 for (i
= 0; i
< dstWidth
* dstHeight
; i
++) {
749 dst
[i
* 4 + 3] = 0xff;
755 /* unexpected internal format! */
764 * Replace a subregion of a texture image with new data.
766 * dstFormat - destination image format
767 * dstXoffset, dstYoffset - destination for new subregion (in texels)
768 * dstWidth, dstHeight - total size of dest image (in texels)
769 * dstImage - pointer to dest image
770 * dstRowStride - bytes to jump between image rows (in bytes)
771 * width, height - size of region to copy/replace (in texels)
772 * srcWidth, srcHeight - size of the corresponding gl_texture_image
773 * srcFormat, srcType - source image format and datatype
774 * srcImage - source image
775 * packing - source image packing information.
776 * Return: GL_TRUE or GL_FALSE for success, failure
779 * Like _mesa_convert_teximage(), we can do power-of-two image scaling
780 * to accomodate hardware with texture image aspect ratio constraints.
781 * dstWidth / srcWidth is used to compute the horizontal scaling factor and
782 * dstHeight / srcHeight is used to compute the vertical scaling factor.
785 _mesa_convert_texsubimage(MesaIntTexFormat dstFormat
,
786 GLint dstXoffset
, GLint dstYoffset
,
787 GLint dstWidth
, GLint dstHeight
, GLvoid
*dstImage
,
789 GLint width
, GLint height
,
790 GLint srcWidth
, GLint srcHeight
,
791 GLenum srcFormat
, GLenum srcType
,
792 const GLvoid
*srcImage
,
793 const struct gl_pixelstore_attrib
*packing
)
795 const GLint wScale
= dstWidth
/ srcWidth
; /* must be power of two */
796 const GLint hScale
= dstHeight
/ srcHeight
; /* must be power of two */
797 ASSERT(dstWidth
>= srcWidth
);
798 ASSERT(dstHeight
>= srcHeight
);
805 dstXoffset
*= wScale
;
806 dstYoffset
*= hScale
;
808 /* XXX hscale != 1 and wscale != 1 not tested!!!! */
815 if (srcType
!= GL_UNSIGNED_BYTE
||
816 ((srcFormat
!= GL_INTENSITY
) &&
817 (srcFormat
!= GL_LUMINANCE
) &&
818 (srcFormat
!= GL_ALPHA
) &&
819 (srcFormat
!= GL_COLOR_INDEX
))) {
820 /* bad internal format / srcFormat combination */
824 /* store as 8-bit texels */
825 if (wScale
== 1 && hScale
== 1) {
826 /* no scaling needed - fast case */
827 const GLubyte
*src
= (const GLubyte
*)
828 _mesa_image_address(packing
, srcImage
, srcWidth
, srcHeight
,
829 srcFormat
, srcType
, 0, 0, 0);
830 const GLint srcStride
= _mesa_image_row_stride(packing
,
831 width
, srcFormat
, srcType
);
832 GLubyte
*dst
= (GLubyte
*) dstImage
833 + dstYoffset
* dstRowStride
+ dstXoffset
;
835 for (row
= 0; row
< height
; row
++) {
836 MEMCPY(dst
, src
, width
* sizeof(GLubyte
));
842 /* must rescale image */
843 GLubyte
*dst
= (GLubyte
*) dstImage
844 + dstYoffset
* dstRowStride
+ dstXoffset
;
846 for (row
= 0; row
< height
; row
++) {
847 GLint srcRow
= row
/ hScale
;
848 const GLubyte
*src
= (const GLubyte
*)
849 _mesa_image_address(packing
, srcImage
, srcWidth
,
850 srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
852 for (col
= 0; col
< width
; col
++) {
853 dst
[col
] = src
[col
/ wScale
];
862 if (srcType
!= GL_UNSIGNED_BYTE
|| srcFormat
!= GL_LUMINANCE_ALPHA
) {
866 /* store as 16-bit texels */
867 if (wScale
== 1 && hScale
== 1) {
868 const GLubyte
*src
= (const GLubyte
*)
869 _mesa_image_address(packing
, srcImage
, srcWidth
, srcHeight
,
870 srcFormat
, srcType
, 0, 0, 0);
871 const GLint srcStride
= _mesa_image_row_stride(packing
,
872 width
, srcFormat
, srcType
);
873 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
874 + dstYoffset
* dstRowStride
) + dstXoffset
;
876 for (row
= 0; row
< height
; row
++) {
877 for (col
= 0; col
< width
; col
++) {
878 GLubyte luminance
= src
[col
* 2 + 0];
879 GLubyte alpha
= src
[col
* 2 + 1];
880 dst
[col
] = ((GLushort
) alpha
<< 8) | luminance
;
882 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
888 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
889 + dstYoffset
* dstRowStride
) + dstXoffset
;
891 for (row
= 0; row
< height
; row
++) {
892 GLint srcRow
= row
/ hScale
;
893 const GLubyte
*src
= (const GLubyte
*)
894 _mesa_image_address(packing
, srcImage
, srcWidth
,
895 srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
896 const GLint srcStride
= _mesa_image_row_stride(packing
,
897 width
, srcFormat
, srcType
);
898 for (col
= 0; col
< width
; col
++) {
899 GLint srcCol
= col
/ wScale
;
900 GLubyte luminance
= src
[srcCol
* 2 + 0];
901 GLubyte alpha
= src
[srcCol
* 2 + 1];
902 dst
[col
] = ((GLushort
) alpha
<< 8) | luminance
;
904 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
912 if (srcFormat
== GL_RGB
&& srcType
== GL_UNSIGNED_SHORT_5_6_5
) {
913 /* special, optimized case */
914 if (wScale
== 1 && hScale
== 1) {
915 const GLubyte
*src
= (const GLubyte
*)
916 _mesa_image_address(packing
, srcImage
, srcWidth
, srcHeight
,
917 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
++) {
924 MEMCPY(dst
, src
, width
* sizeof(GLushort
));
926 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
930 /* must rescale image */
931 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
932 + dstYoffset
* dstRowStride
) + dstXoffset
;
934 for (row
= 0; row
< height
; row
++) {
935 GLint srcRow
= row
/ hScale
;
936 const GLushort
*src
= (const GLushort
*)
937 _mesa_image_address(packing
, srcImage
, srcWidth
,
938 srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
940 for (col
= 0; col
< width
; col
++) {
941 dst
[col
] = src
[col
/ wScale
];
943 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
947 else if (srcFormat
== GL_RGB
&& srcType
== GL_UNSIGNED_BYTE
) {
949 if (wScale
== 1 && hScale
== 1) {
950 const GLubyte
*src
= (const GLubyte
*)
951 _mesa_image_address(packing
, srcImage
, srcWidth
, srcHeight
,
952 srcFormat
, srcType
, 0, 0, 0);
953 const GLint srcStride
= _mesa_image_row_stride(packing
,
954 width
, srcFormat
, srcType
);
955 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
956 + dstYoffset
* dstRowStride
) + dstXoffset
;
958 for (row
= 0; row
< height
; row
++) {
960 for (col
= col3
= 0; col
< width
; col
++, col3
+= 3) {
961 GLubyte r
= src
[col3
+ 0];
962 GLubyte g
= src
[col3
+ 1];
963 GLubyte b
= src
[col3
+ 2];
964 dst
[col
] = ((r
& 0xf8) << 8)
969 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
973 /* must rescale image */
974 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
975 + dstYoffset
* dstRowStride
) + dstXoffset
;
977 for (row
= 0; row
< height
; row
++) {
978 GLint srcRow
= row
/ hScale
;
979 const GLubyte
*src
= (const GLubyte
*)
980 _mesa_image_address(packing
, srcImage
, srcWidth
,
981 srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
983 for (col
= 0; col
< width
; col
++) {
984 GLint col3
= (col
/ wScale
) * 3;
985 GLubyte r
= src
[col3
+ 0];
986 GLubyte g
= src
[col3
+ 1];
987 GLubyte b
= src
[col3
+ 2];
988 dst
[col
] = ((r
& 0xf8) << 8)
992 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
996 else if (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
) {
997 /* general case (used by Quake3) */
998 if (wScale
== 1 && hScale
== 1) {
999 const GLubyte
*src
= (const GLubyte
*)
1000 _mesa_image_address(packing
, srcImage
, srcWidth
, srcHeight
,
1001 srcFormat
, srcType
, 0, 0, 0);
1002 const GLint srcStride
= _mesa_image_row_stride(packing
,
1003 width
, srcFormat
, srcType
);
1004 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
1005 + dstYoffset
* dstRowStride
) + dstXoffset
;
1007 for (row
= 0; row
< height
; row
++) {
1009 for (col
= col4
= 0; col
< width
; col
++, col4
+= 4) {
1010 GLubyte r
= src
[col4
+ 0];
1011 GLubyte g
= src
[col4
+ 1];
1012 GLubyte b
= src
[col4
+ 2];
1013 dst
[col
] = ((r
& 0xf8) << 8)
1015 | ((b
& 0xf8) >> 3);
1018 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
1022 /* must rescale image */
1023 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
1024 + dstYoffset
* dstRowStride
) + dstXoffset
;
1026 for (row
= 0; row
< height
; row
++) {
1027 GLint srcRow
= row
/ hScale
;
1028 const GLubyte
*src
= (const GLubyte
*)
1029 _mesa_image_address(packing
, srcImage
, srcWidth
,
1030 srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
1032 for (col
= 0; col
< width
; col
++) {
1033 GLint col4
= (col
/ wScale
) * 4;
1034 GLubyte r
= src
[col4
+ 0];
1035 GLubyte g
= src
[col4
+ 1];
1036 GLubyte b
= src
[col4
+ 2];
1037 dst
[col
] = ((r
& 0xf8) << 8)
1039 | ((b
& 0xf8) >> 3);
1041 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
1046 /* can't handle this srcFormat/srcType combination */
1051 case MESA_A4_R4_G4_B4
:
1052 /* store as 16-bit texels (GR_TEXFMT_ARGB_4444) */
1053 if (srcFormat
== GL_BGRA
&& srcType
== GL_UNSIGNED_SHORT_4_4_4_4_REV
){
1054 /* special, optimized case */
1055 if (wScale
== 1 && hScale
== 1) {
1056 const GLubyte
*src
= (const GLubyte
*)
1057 _mesa_image_address(packing
, srcImage
, srcWidth
, srcHeight
,
1058 srcFormat
, srcType
, 0, 0, 0);
1059 const GLint srcStride
= _mesa_image_row_stride(packing
,
1060 width
, srcFormat
, srcType
);
1061 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
1062 + dstYoffset
* dstRowStride
) + dstXoffset
;
1064 for (row
= 0; row
< height
; row
++) {
1065 MEMCPY(dst
, src
, width
* sizeof(GLushort
));
1067 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
1071 /* must rescale image */
1072 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
1073 + dstYoffset
* dstRowStride
) + dstXoffset
;
1075 for (row
= 0; row
< height
; row
++) {
1076 GLint srcRow
= row
/ hScale
;
1077 const GLushort
*src
= (const GLushort
*)
1078 _mesa_image_address(packing
, srcImage
, srcWidth
,
1079 srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
1081 for (col
= 0; col
< width
; col
++) {
1082 dst
[col
] = src
[col
/ wScale
];
1084 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
1088 else if (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
) {
1090 if (wScale
== 1 && hScale
== 1) {
1091 const GLubyte
*src
= (const GLubyte
*)
1092 _mesa_image_address(packing
, srcImage
, srcWidth
, srcHeight
,
1093 srcFormat
, srcType
, 0, 0, 0);
1094 const GLint srcStride
= _mesa_image_row_stride(packing
,
1095 width
, srcFormat
, srcType
);
1096 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
1097 + dstYoffset
* dstRowStride
) + dstXoffset
;
1099 for (row
= 0; row
< height
; row
++) {
1101 for (col
= col4
= 0; col
< width
; col
++, col4
+= 4) {
1102 GLubyte r
= src
[col4
+ 0];
1103 GLubyte g
= src
[col4
+ 1];
1104 GLubyte b
= src
[col4
+ 2];
1105 GLubyte a
= src
[col4
+ 3];
1106 dst
[col
] = ((a
& 0xf0) << 8)
1109 | ((b
& 0xf0) >> 4);
1112 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
1116 /* must rescale image */
1117 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
1118 + dstYoffset
* dstRowStride
) + dstXoffset
;
1120 for (row
= 0; row
< height
; row
++) {
1121 GLint srcRow
= row
/ hScale
;
1122 const GLubyte
*src
= (const GLubyte
*)
1123 _mesa_image_address(packing
, srcImage
, srcWidth
,
1124 srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
1126 for (col
= 0; col
< width
; col
++) {
1127 GLint col4
= (col
/ wScale
) * 4;
1128 GLubyte r
= src
[col4
+ 0];
1129 GLubyte g
= src
[col4
+ 1];
1130 GLubyte b
= src
[col4
+ 2];
1131 GLubyte a
= src
[col4
+ 3];
1132 dst
[col
] = ((a
& 0xf0) << 8)
1135 | ((b
& 0xf0) >> 4);
1137 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
1142 /* can't handle this format/srcType combination */
1147 case MESA_A1_R5_G5_B5
:
1148 /* store as 16-bit texels (GR_TEXFMT_ARGB_1555) */
1149 if (srcFormat
== GL_BGRA
&& srcType
== GL_UNSIGNED_SHORT_1_5_5_5_REV
){
1150 /* special, optimized case */
1151 if (wScale
== 1 && hScale
== 1) {
1152 const GLubyte
*src
= (const GLubyte
*)
1153 _mesa_image_address(packing
, srcImage
, srcWidth
, srcHeight
,
1154 srcFormat
, srcType
, 0, 0, 0);
1155 const GLint srcStride
= _mesa_image_row_stride(packing
,
1156 width
, srcFormat
, srcType
);
1157 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
1158 + dstYoffset
* dstRowStride
) + dstXoffset
;
1160 for (row
= 0; row
< height
; row
++) {
1161 MEMCPY(dst
, src
, width
* sizeof(GLushort
));
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 GLushort
*src
= (const GLushort
*)
1174 _mesa_image_address(packing
, srcImage
, srcWidth
,
1175 srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
1177 for (col
= 0; col
< width
; col
++) {
1178 dst
[col
] = src
[col
/ wScale
];
1180 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
1184 else if (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
) {
1186 if (wScale
== 1 && hScale
== 1) {
1187 const GLubyte
*src
= (const GLubyte
*)
1188 _mesa_image_address(packing
, srcImage
, srcWidth
, srcHeight
,
1189 srcFormat
, srcType
, 0, 0, 0);
1190 const GLint srcStride
= _mesa_image_row_stride(packing
,
1191 width
, srcFormat
, srcType
);
1192 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
1193 + dstYoffset
* dstRowStride
) + dstXoffset
;
1195 for (row
= 0; row
< height
; row
++) {
1197 for (col
= col4
= 0; col
< width
; col
++, col4
+= 4) {
1198 GLubyte r
= src
[col4
+ 0];
1199 GLubyte g
= src
[col4
+ 1];
1200 GLubyte b
= src
[col4
+ 2];
1201 GLubyte a
= src
[col4
+ 3];
1202 dst
[col
] = ((a
& 0x80) << 8)
1205 | ((b
& 0xf8) >> 3);
1208 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
1212 /* must rescale image */
1213 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
1214 + dstYoffset
* dstRowStride
) + dstXoffset
;
1216 for (row
= 0; row
< height
; row
++) {
1217 GLint srcRow
= row
/ hScale
;
1218 const GLubyte
*src
= (const GLubyte
*)
1219 _mesa_image_address(packing
, srcImage
, srcWidth
,
1220 srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
1222 for (col
= 0; col
< width
; col
++) {
1223 GLint col4
= (col
/ wScale
) * 4;
1224 GLubyte r
= src
[col4
+ 0];
1225 GLubyte g
= src
[col4
+ 1];
1226 GLubyte b
= src
[col4
+ 2];
1227 GLubyte a
= src
[col4
+ 3];
1228 dst
[col
] = ((a
& 0x80) << 8)
1231 | ((b
& 0xf8) >> 3);
1233 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
1238 /* can't handle this source format/type combination */
1243 case MESA_A8_R8_G8_B8
:
1244 case MESA_FF_R8_G8_B8
:
1246 if (srcFormat
== GL_BGRA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
) {
1247 /* special, optimized case */
1248 if (wScale
== 1 && hScale
== 1) {
1249 const GLubyte
*src
= (const GLubyte
*)
1250 _mesa_image_address(packing
, srcImage
, srcWidth
, srcHeight
,
1251 srcFormat
, srcType
, 0, 0, 0);
1252 const GLint srcStride
= _mesa_image_row_stride(packing
,
1253 width
, srcFormat
, srcType
);
1254 GLuint
*dst
= (GLuint
*) ((GLubyte
*) dstImage
1255 + dstYoffset
* dstRowStride
) + dstXoffset
;
1257 for (row
= 0; row
< height
; row
++) {
1258 MEMCPY(dst
, src
, width
* sizeof(GLuint
));
1260 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
1264 /* must rescale image */
1265 GLuint
*dst
= (GLuint
*) ((GLubyte
*) dstImage
1266 + dstYoffset
* dstRowStride
) + dstXoffset
;
1268 for (row
= 0; row
< height
; row
++) {
1269 GLint srcRow
= row
/ hScale
;
1270 const GLuint
*src
= (const GLuint
*)
1271 _mesa_image_address(packing
, srcImage
, srcWidth
,
1272 srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
1274 for (col
= 0; col
< width
; col
++) {
1275 dst
[col
] = src
[col
/ wScale
];
1277 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
1280 if (dstFormat
== MESA_FF_R8_G8_B8
) {
1281 /* set alpha bytes to 0xff */
1283 GLubyte
*dst
= (GLubyte
*) dstImage
1284 + dstYoffset
* dstRowStride
+ dstXoffset
* 4;
1285 assert(wScale
== 1 && hScale
== 1); /* XXX not done */
1286 for (row
= 0; row
< height
; row
++) {
1287 for (col
= 0; col
< width
; col
++) {
1288 dst
[col
* 4 + 3] = 0xff;
1290 dst
= dst
+ dstRowStride
;
1294 else if (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
) {
1296 const GLubyte aMask
= (dstFormat
==MESA_FF_R8_G8_B8
) ? 0xff : 0x00;
1297 if (wScale
== 1 && hScale
== 1) {
1298 const GLubyte
*src
= (const GLubyte
*)
1299 _mesa_image_address(packing
, srcImage
, srcWidth
, srcHeight
,
1300 srcFormat
, srcType
, 0, 0, 0);
1301 const GLint srcStride
= _mesa_image_row_stride(packing
,
1302 width
, srcFormat
, srcType
);
1303 GLuint
*dst
= (GLuint
*) ((GLubyte
*) dstImage
1304 + dstYoffset
* dstRowStride
) + dstXoffset
;
1306 for (row
= 0; row
< height
; row
++) {
1308 for (col
= col4
= 0; col
< width
; col
++, col4
+= 4) {
1309 GLubyte r
= src
[col4
+ 0];
1310 GLubyte g
= src
[col4
+ 1];
1311 GLubyte b
= src
[col4
+ 2];
1312 GLubyte a
= src
[col4
+ 3] | aMask
;
1313 dst
[col
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
1316 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
1320 /* must rescale image */
1321 GLuint
*dst
= (GLuint
*) ((GLubyte
*) dstImage
1322 + dstYoffset
* dstRowStride
) + dstXoffset
;
1324 for (row
= 0; row
< height
; row
++) {
1325 GLint srcRow
= row
/ hScale
;
1326 const GLubyte
*src
= (const GLubyte
*)
1327 _mesa_image_address(packing
, srcImage
, srcWidth
,
1328 srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
1330 for (col
= 0; col
< width
; col
++) {
1331 GLint col4
= (col
/ wScale
) * 4;
1332 GLubyte r
= src
[col4
+ 0];
1333 GLubyte g
= src
[col4
+ 1];
1334 GLubyte b
= src
[col4
+ 2];
1335 GLubyte a
= src
[col4
+ 3] | aMask
;
1336 dst
[col
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
1338 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
1343 /* can't handle this source format/type combination */
1350 /* unexpected internal format! */
1360 * Used to convert 16-bit texels into GLubyte color components.
1362 static GLubyte R5G6B5toRed
[0xffff];
1363 static GLubyte R5G6B5toGreen
[0xffff];
1364 static GLubyte R5G6B5toBlue
[0xffff];
1366 static GLubyte A4R4G4B4toRed
[0xffff];
1367 static GLubyte A4R4G4B4toGreen
[0xffff];
1368 static GLubyte A4R4G4B4toBlue
[0xffff];
1369 static GLubyte A4R4G4B4toAlpha
[0xffff];
1371 static GLubyte A1R5G5B5toRed
[0xffff];
1372 static GLubyte A1R5G5B5toGreen
[0xffff];
1373 static GLubyte A1R5G5B5toBlue
[0xffff];
1374 static GLubyte A1R5G5B5toAlpha
[0xffff];
1377 generate_lookup_tables(void)
1380 for (i
= 0; i
<= 0xffff; i
++) {
1381 GLint r
= (i
>> 8) & 0xf8;
1382 GLint g
= (i
>> 3) & 0xfc;
1383 GLint b
= (i
<< 3) & 0xf8;
1388 R5G6B5toGreen
[i
] = g
;
1389 R5G6B5toBlue
[i
] = b
;
1392 for (i
= 0; i
<= 0xffff; i
++) {
1393 GLint r
= (i
>> 8) & 0xf;
1394 GLint g
= (i
>> 4) & 0xf;
1395 GLint b
= (i
) & 0xf;
1396 GLint a
= (i
>> 12) & 0xf;
1401 A4R4G4B4toRed
[i
] = r
;
1402 A4R4G4B4toGreen
[i
] = g
;
1403 A4R4G4B4toBlue
[i
] = b
;
1404 A4R4G4B4toAlpha
[i
] = a
;
1407 for (i
= 0; i
<= 0xffff; i
++) {
1408 GLint r
= (i
>> 10) & 0xf8;
1409 GLint g
= (i
>> 5) & 0xf8;
1410 GLint b
= (i
) & 0xf8;
1411 GLint a
= (i
>> 15) & 0x1;
1416 A1R5G5B5toRed
[i
] = r
;
1417 A1R5G5B5toGreen
[i
] = g
;
1418 A1R5G5B5toBlue
[i
] = b
;
1419 A1R5G5B5toAlpha
[i
] = a
;
1426 * Convert a texture image from an internal format to one of Mesa's
1427 * core internal formats. This is likely to be used by glGetTexImage
1428 * and for fetching texture images when falling back to software rendering.
1431 * srcFormat - source image format
1432 * srcWidth, srcHeight - source image size
1433 * srcImage - source image pointer
1434 * srcRowStride - bytes to jump between image rows
1435 * dstWidth, dstHeight - size of dest image
1436 * dstFormat - format of dest image (must be one of Mesa's IntFormat values)
1437 * dstImage - pointer to dest image
1439 * This function will do power of two image down-scaling to accomodate
1440 * drivers with limited texture image aspect ratios.
1441 * The implicit dest data type is GL_UNSIGNED_BYTE.
1444 _mesa_unconvert_teximage(MesaIntTexFormat srcFormat
,
1445 GLint srcWidth
, GLint srcHeight
,
1446 const GLvoid
*srcImage
, GLint srcRowStride
,
1447 GLint dstWidth
, GLint dstHeight
,
1448 GLenum dstFormat
, GLubyte
*dstImage
)
1450 static GLboolean firstCall
= GL_TRUE
;
1451 const GLint wScale
= srcWidth
/ dstWidth
; /* must be power of two */
1452 const GLint hScale
= srcHeight
/ dstHeight
; /* must be power of two */
1453 ASSERT(srcWidth
>= dstWidth
);
1454 ASSERT(srcHeight
>= dstHeight
);
1459 generate_lookup_tables();
1460 firstCall
= GL_FALSE
;
1463 switch (srcFormat
) {
1469 if (srcFormat
== MESA_I8
) {
1470 ASSERT(dstFormat
== GL_INTENSITY
);
1472 else if (srcFormat
== MESA_L8
) {
1473 ASSERT(dstFormat
== GL_LUMINANCE
);
1475 else if (srcFormat
== MESA_A8
) {
1476 ASSERT(dstFormat
== GL_ALPHA
);
1478 else if (srcFormat
== MESA_C8
) {
1479 ASSERT(dstFormat
== GL_COLOR_INDEX
);
1482 if (wScale
== 1 && hScale
== 1) {
1484 MEMCPY(dstImage
, srcImage
, dstWidth
* dstHeight
* sizeof(GLubyte
));
1488 const GLubyte
*src8
= (const GLubyte
*) srcImage
;
1490 for (row
= 0; row
< dstHeight
; row
++) {
1491 GLint srcRow
= row
* hScale
;
1492 for (col
= 0; col
< dstWidth
; col
++) {
1493 GLint srcCol
= col
* wScale
;
1494 *dstImage
++ = src8
[srcRow
* srcWidth
+ srcCol
];
1500 ASSERT(dstFormat
== GL_LUMINANCE_ALPHA
);
1501 if (wScale
== 1 && hScale
== 1) {
1502 GLint i
, n
= dstWidth
* dstHeight
;
1503 const GLushort
*texel
= (const GLushort
*) srcImage
;
1504 for (i
= 0; i
< n
; i
++) {
1505 const GLushort tex
= *texel
++;
1506 *dstImage
++ = (tex
& 0xff); /* luminance */
1507 *dstImage
++ = (tex
>> 8); /* alpha */
1512 const GLushort
*src16
= (const GLushort
*) srcImage
;
1514 for (row
= 0; row
< dstHeight
; row
++) {
1515 GLint srcRow
= row
* hScale
;
1516 for (col
= 0; col
< dstWidth
; col
++) {
1517 GLint srcCol
= col
* wScale
;
1518 const GLushort tex
= src16
[srcRow
* srcWidth
+ srcCol
];
1519 *dstImage
++ = (tex
& 0xff); /* luminance */
1520 *dstImage
++ = (tex
>> 8); /* alpha */
1526 ASSERT(dstFormat
== GL_RGB
);
1527 if (wScale
== 1 && hScale
== 1) {
1528 GLint i
, n
= dstWidth
* dstHeight
;
1529 const GLushort
*texel
= (const GLushort
*) srcImage
;
1530 for (i
= 0; i
< n
; i
++) {
1531 const GLushort tex
= *texel
++;
1532 *dstImage
++ = R5G6B5toRed
[tex
];
1533 *dstImage
++ = R5G6B5toGreen
[tex
];
1534 *dstImage
++ = R5G6B5toBlue
[tex
];
1539 const GLushort
*src16
= (const GLushort
*) srcImage
;
1541 for (row
= 0; row
< dstHeight
; row
++) {
1542 GLint srcRow
= row
* hScale
;
1543 for (col
= 0; col
< dstWidth
; col
++) {
1544 GLint srcCol
= col
* wScale
;
1545 const GLushort tex
= src16
[srcRow
* srcWidth
+ srcCol
];
1546 *dstImage
++ = R5G6B5toRed
[tex
];
1547 *dstImage
++ = R5G6B5toGreen
[tex
];
1548 *dstImage
++ = R5G6B5toBlue
[tex
];
1553 case MESA_A4_R4_G4_B4
:
1554 ASSERT(dstFormat
== GL_RGBA
);
1555 if (wScale
== 1 && hScale
== 1) {
1556 GLint i
, n
= dstWidth
* dstHeight
;
1557 const GLushort
*texel
= (const GLushort
*) srcImage
;
1558 for (i
= 0; i
< n
; i
++) {
1559 const GLushort tex
= *texel
++;
1560 *dstImage
++ = A4R4G4B4toRed
[tex
];
1561 *dstImage
++ = A4R4G4B4toGreen
[tex
];
1562 *dstImage
++ = A4R4G4B4toBlue
[tex
];
1563 *dstImage
++ = A4R4G4B4toAlpha
[tex
];
1568 const GLushort
*src16
= (const GLushort
*) srcImage
;
1570 for (row
= 0; row
< dstHeight
; row
++) {
1571 GLint srcRow
= row
* hScale
;
1572 for (col
= 0; col
< dstWidth
; col
++) {
1573 GLint srcCol
= col
* wScale
;
1574 const GLushort tex
= src16
[srcRow
* srcWidth
+ srcCol
];
1575 *dstImage
++ = A4R4G4B4toRed
[tex
];
1576 *dstImage
++ = A4R4G4B4toGreen
[tex
];
1577 *dstImage
++ = A4R4G4B4toBlue
[tex
];
1578 *dstImage
++ = A4R4G4B4toAlpha
[tex
];
1583 case MESA_A1_R5_G5_B5
:
1584 ASSERT(dstFormat
== GL_RGBA
);
1585 if (wScale
== 1 && hScale
== 1) {
1586 GLint i
, n
= dstWidth
* dstHeight
;
1587 const GLushort
*texel
= (const GLushort
*) srcImage
;
1588 for (i
= 0; i
< n
; i
++) {
1589 const GLushort tex
= *texel
++;
1590 *dstImage
++ = A1R5G5B5toRed
[tex
];
1591 *dstImage
++ = A1R5G5B5toGreen
[tex
];
1592 *dstImage
++ = A1R5G5B5toBlue
[tex
];
1593 *dstImage
++ = A1R5G5B5toAlpha
[tex
];
1598 const GLushort
*src16
= (const GLushort
*) srcImage
;
1600 for (row
= 0; row
< dstHeight
; row
++) {
1601 GLint srcRow
= row
* hScale
;
1602 for (col
= 0; col
< dstWidth
; col
++) {
1603 GLint srcCol
= col
* wScale
;
1604 const GLushort tex
= src16
[srcRow
* srcWidth
+ srcCol
];
1605 *dstImage
++ = A1R5G5B5toRed
[tex
];
1606 *dstImage
++ = A1R5G5B5toGreen
[tex
];
1607 *dstImage
++ = A1R5G5B5toBlue
[tex
];
1608 *dstImage
++ = A1R5G5B5toAlpha
[tex
];
1613 case MESA_A8_R8_G8_B8
:
1614 case MESA_FF_R8_G8_B8
:
1615 ASSERT(dstFormat
== GL_RGBA
);
1616 if (wScale
== 1 && hScale
== 1) {
1617 GLint i
, n
= dstWidth
* dstHeight
;
1618 const GLuint
*texel
= (const GLuint
*) srcImage
;
1619 for (i
= 0; i
< n
; i
++) {
1620 const GLuint tex
= *texel
++;
1621 *dstImage
++ = (tex
>> 16) & 0xff; /* R */
1622 *dstImage
++ = (tex
>> 8) & 0xff; /* G */
1623 *dstImage
++ = (tex
) & 0xff; /* B */
1624 *dstImage
++ = (tex
>> 24) & 0xff; /* A */
1629 const GLuint
*src
= (const GLuint
*) srcImage
;
1631 for (row
= 0; row
< dstHeight
; row
++) {
1632 GLint srcRow
= row
* hScale
;
1633 for (col
= 0; col
< dstWidth
; col
++) {
1634 GLint srcCol
= col
* wScale
;
1635 const GLuint tex
= src
[srcRow
* srcWidth
+ srcCol
];
1636 *dstImage
++ = (tex
>> 16) & 0xff; /* R */
1637 *dstImage
++ = (tex
>> 8) & 0xff; /* G */
1638 *dstImage
++ = (tex
) & 0xff; /* B */
1639 *dstImage
++ = (tex
>> 24) & 0xff; /* A */
1645 gl_problem(NULL
, "bad srcFormat in _mesa_uncovert_teximage()");
1652 * Given an internal Mesa driver texture format, fill in the component
1653 * bit sizes in the given texture image struct.
1656 _mesa_set_teximage_component_sizes(MesaIntTexFormat mesaFormat
,
1657 struct gl_texture_image
*texImage
)
1659 static const GLint bitSizes
[][8] = {
1660 /* format R G B A I L C */
1661 { MESA_I8
, 0, 0, 0, 0, 8, 0, 0 },
1662 { MESA_L8
, 0, 0, 0, 0, 0, 8, 0 },
1663 { MESA_A8
, 0, 0, 0, 8, 0, 0, 0 },
1664 { MESA_C8
, 0, 0, 0, 0, 0, 0, 8 },
1665 { MESA_A8_L8
, 0, 0, 0, 8, 0, 8, 0 },
1666 { MESA_R5_G6_B5
, 5, 6, 5, 0, 0, 0, 0 },
1667 { MESA_A4_R4_G4_B4
, 4, 4, 4, 4, 0, 0, 0 },
1668 { MESA_A1_R5_G5_B5
, 5, 5, 5, 1, 0, 0, 0 },
1669 { MESA_A8_R8_G8_B8
, 8, 8, 8, 8, 0, 0, 0 },
1670 { MESA_FF_R8_G8_B8
, 8, 8, 8, 8, 0, 0, 0 },
1671 { -1, 0, 0, 0, 0, 0, 0, 0 }
1674 for (i
= 0; i
< bitSizes
[i
][0] >= 0; i
++) {
1675 if (bitSizes
[i
][0] == mesaFormat
) {
1676 texImage
->RedBits
= bitSizes
[i
][1];
1677 texImage
->GreenBits
= bitSizes
[i
][2];
1678 texImage
->BlueBits
= bitSizes
[i
][3];
1679 texImage
->AlphaBits
= bitSizes
[i
][4];
1680 texImage
->IntensityBits
= bitSizes
[i
][5];
1681 texImage
->LuminanceBits
= bitSizes
[i
][6];
1682 texImage
->IndexBits
= bitSizes
[i
][7];
1686 gl_problem(NULL
, "bad format in _mesa_set_teximage_component_sizes");