3 * Mesa 3-D graphics library
6 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
40 * Texture utilities which may be useful to device drivers.
41 * See the texutil.h for the list of supported internal formats.
42 * It's expected that new formats will be added for new hardware.
47 * If the system is little endian and can do 4-byte word stores on
48 * non 4-byte-aligned addresses then we can use this optimization.
51 #define DO_32BIT_STORES000
57 * Convert texture image data into one a specific internal format.
59 * dstFormat - the destination internal format
60 * dstWidth, dstHeight - the destination image size
61 * dstImage - pointer to destination image buffer
62 * dstRowStride - bytes to jump between image rows
63 * srcWidth, srcHeight - size of texture image
64 * srcFormat, srcType - format and datatype of source image
65 * srcImage - pointer to user's texture image
66 * packing - describes how user's texture image is packed.
67 * Return: pointer to resulting image data or NULL if error or out of memory
68 * or NULL if we can't process the given image format/type/internalFormat
71 * Supported type conversions:
72 * srcFormat srcType dstFormat
73 * GL_INTENSITY GL_UNSIGNED_BYTE MESA_I8
74 * GL_LUMINANCE GL_UNSIGNED_BYTE MESA_L8
75 * GL_ALPHA GL_UNSIGNED_BYTE MESA_A8
76 * GL_COLOR_INDEX GL_UNSIGNED_BYTE MESA_C8
77 * GL_LUMINANCE_ALPHA GL_UNSIGNED_BYTE MESA_A8_L8
78 * GL_RGB GL_UNSIGNED_BYTE MESA_R5_G6_B5
79 * GL_RGB GL_UNSIGNED_SHORT_5_6_5 MESA_R5_G6_B5
80 * GL_RGBA GL_UNSIGNED_BYTE MESA_A4_R4_G4_B4
81 * GL_BGRA GL_UNSIGNED_SHORT_4_4_4_4_REV MESA_A4_R4_G4_B4
82 * GL_BGRA GL_UNSIGHED_SHORT_1_5_5_5_REV MESA_A1_R5_G5_B5
83 * GL_BGRA GL_UNSIGNED_INT_8_8_8_8_REV MESA_A8_R8_G8_B8
84 * more to be added for new drivers...
87 * Some hardware only supports texture images of specific aspect ratios.
88 * This code will do power-of-two image up-scaling if that's needed.
93 _mesa_convert_teximage(MesaIntTexFormat dstFormat
,
94 GLint dstWidth
, GLint dstHeight
, GLvoid
*dstImage
,
96 GLint srcWidth
, GLint srcHeight
,
97 GLenum srcFormat
, GLenum srcType
,
98 const GLvoid
*srcImage
,
99 const struct gl_pixelstore_attrib
*packing
)
101 const GLint wScale
= dstWidth
/ srcWidth
; /* must be power of two */
102 const GLint hScale
= dstHeight
/ srcHeight
; /* must be power of two */
103 ASSERT(dstWidth
>= srcWidth
);
104 ASSERT(dstHeight
>= srcHeight
);
114 if (srcType
!= GL_UNSIGNED_BYTE
||
115 ((srcFormat
!= GL_INTENSITY
) &&
116 (srcFormat
!= GL_LUMINANCE
) &&
117 (srcFormat
!= GL_ALPHA
) &&
118 (srcFormat
!= GL_COLOR_INDEX
))) {
119 /* bad internal format / srcFormat combination */
123 /* store as 8-bit texels */
124 if (wScale
== 1 && hScale
== 1) {
125 /* no scaling needed - fast case */
126 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
127 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
128 const GLint srcStride
= _mesa_image_row_stride(packing
,
129 srcWidth
, srcFormat
, srcType
);
130 GLubyte
*dst
= (GLubyte
*) dstImage
;
132 for (row
= 0; row
< dstHeight
; row
++) {
133 MEMCPY(dst
, src
, dstWidth
* sizeof(GLubyte
));
139 /* must rescale image */
140 GLubyte
*dst
= (GLubyte
*) dstImage
;
142 for (row
= 0; row
< dstHeight
; row
++) {
143 GLint srcRow
= row
/ hScale
;
144 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
145 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
147 for (col
= 0; col
< dstWidth
; col
++) {
148 dst
[col
] = src
[col
/ wScale
];
157 if (srcType
!= GL_UNSIGNED_BYTE
|| srcFormat
!= GL_LUMINANCE_ALPHA
) {
161 /* store as 16-bit texels */
162 if (wScale
== 1 && hScale
== 1) {
163 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
164 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
165 const GLint srcStride
= _mesa_image_row_stride(packing
,
166 srcWidth
, srcFormat
, srcType
);
167 GLushort
*dst
= (GLushort
*) dstImage
;
169 for (row
= 0; row
< dstHeight
; row
++) {
170 for (col
= 0; col
< dstWidth
; col
++) {
171 GLubyte luminance
= src
[col
* 2 + 0];
172 GLubyte alpha
= src
[col
* 2 + 1];
173 dst
[col
] = ((GLushort
) alpha
<< 8) | luminance
;
175 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
181 GLushort
*dst
= (GLushort
*) dstImage
;
183 for (row
= 0; row
< dstHeight
; row
++) {
184 GLint srcRow
= row
/ hScale
;
185 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
186 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
187 const GLint srcStride
= _mesa_image_row_stride(packing
,
188 srcWidth
, srcFormat
, srcType
);
189 for (col
= 0; col
< dstWidth
; col
++) {
190 GLint srcCol
= col
/ wScale
;
191 GLubyte luminance
= src
[srcCol
* 2 + 0];
192 GLubyte alpha
= src
[srcCol
* 2 + 1];
193 dst
[col
] = ((GLushort
) alpha
<< 8) | luminance
;
195 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
203 if (srcFormat
== GL_RGB
&& srcType
== GL_UNSIGNED_SHORT_5_6_5
) {
204 /* special, optimized case */
205 if (wScale
== 1 && hScale
== 1) {
206 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
207 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
208 const GLint srcStride
= _mesa_image_row_stride(packing
,
209 srcWidth
, srcFormat
, srcType
);
210 GLushort
*dst
= (GLushort
*) dstImage
;
212 for (row
= 0; row
< dstHeight
; row
++) {
213 MEMCPY(dst
, src
, dstWidth
* sizeof(GLushort
));
215 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
219 /* must rescale image */
220 GLushort
*dst
= (GLushort
*) dstImage
;
222 for (row
= 0; row
< dstHeight
; row
++) {
223 GLint srcRow
= row
/ hScale
;
224 const GLushort
*src
= _mesa_image_address(packing
, srcImage
,
225 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
227 for (col
= 0; col
< dstWidth
; col
++) {
228 dst
[col
] = src
[col
/ wScale
];
230 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
234 else if (srcFormat
== GL_RGB
&& srcType
== GL_UNSIGNED_BYTE
) {
236 if (wScale
== 1 && hScale
== 1) {
237 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
238 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
239 const GLint srcStride
= _mesa_image_row_stride(packing
,
240 srcWidth
, srcFormat
, srcType
);
241 #ifdef DO_32BIT_STORES
242 GLuint
*dst
= (GLuint
*) dstImage
;
244 for (row
= 0; row
< dstHeight
; row
++) {
246 GLint halfDstWidth
= dstWidth
>> 1;
247 for (col
= col3
= 0; col
< halfDstWidth
; col
++, col3
+= 6) {
248 GLubyte r0
= src
[col3
+ 0];
249 GLubyte g0
= src
[col3
+ 1];
250 GLubyte b0
= src
[col3
+ 2];
251 GLubyte r1
= src
[col3
+ 3];
252 GLubyte g1
= src
[col3
+ 4];
253 GLubyte b1
= src
[col3
+ 5];
254 GLuint d0
= ((r0
& 0xf8) << 8)
256 | ((b0
& 0xf8) >> 3);
257 GLuint d1
= ((r1
& 0xf8) << 8)
259 | ((b1
& 0xf8) >> 3);
260 dst
[col
] = (d1
<< 16) | d0
;
263 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
265 #else /* 16-bit stores */
266 GLushort
*dst
= (GLushort
*) dstImage
;
268 for (row
= 0; row
< dstHeight
; row
++) {
270 for (col
= col3
= 0; col
< dstWidth
; col
++, col3
+= 3) {
271 GLubyte r
= src
[col3
+ 0];
272 GLubyte g
= src
[col3
+ 1];
273 GLubyte b
= src
[col3
+ 2];
274 dst
[col
] = ((r
& 0xf8) << 8)
279 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
284 /* must rescale image */
285 GLushort
*dst
= (GLushort
*) dstImage
;
287 for (row
= 0; row
< dstHeight
; row
++) {
288 GLint srcRow
= row
/ hScale
;
289 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
290 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
292 for (col
= 0; col
< dstWidth
; col
++) {
293 GLint col3
= (col
/ wScale
) * 3;
294 GLubyte r
= src
[col3
+ 0];
295 GLubyte g
= src
[col3
+ 1];
296 GLubyte b
= src
[col3
+ 2];
297 dst
[col
] = ((r
& 0xf8) << 8)
301 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
305 else if (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
) {
306 /* general case (used by Quake3) */
307 if (wScale
== 1 && hScale
== 1) {
308 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
309 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
310 const GLint srcStride
= _mesa_image_row_stride(packing
,
311 srcWidth
, srcFormat
, srcType
);
312 #ifdef DO_32BIT_STORES
313 GLuint
*dst
= dstImage
;
315 for (row
= 0; row
< dstHeight
; row
++) {
317 GLint halfDstWidth
= dstWidth
>> 1;
318 for (col
= col4
= 0; col
< halfDstWidth
; col
++, col4
+= 8) {
319 GLubyte r0
= src
[col4
+ 0];
320 GLubyte g0
= src
[col4
+ 1];
321 GLubyte b0
= src
[col4
+ 2];
322 GLubyte r1
= src
[col4
+ 4];
323 GLubyte g1
= src
[col4
+ 5];
324 GLubyte b1
= src
[col4
+ 6];
325 GLuint d0
= ((r0
& 0xf8) << 8)
327 | ((b0
& 0xf8) >> 3);
328 GLuint d1
= ((r1
& 0xf8) << 8)
330 | ((b1
& 0xf8) >> 3);
331 dst
[col
] = (d1
<< 16) | d0
;
334 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
336 #else /* 16-bit stores */
337 GLushort
*dst
= (GLushort
*) dstImage
;
339 for (row
= 0; row
< dstHeight
; row
++) {
341 for (col
= col4
= 0; col
< dstWidth
; col
++, col4
+= 4) {
342 GLubyte r
= src
[col4
+ 0];
343 GLubyte g
= src
[col4
+ 1];
344 GLubyte b
= src
[col4
+ 2];
345 dst
[col
] = ((r
& 0xf8) << 8)
350 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
355 /* must rescale image */
356 GLushort
*dst
= (GLushort
*) dstImage
;
358 for (row
= 0; row
< dstHeight
; row
++) {
359 GLint srcRow
= row
/ hScale
;
360 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
361 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
363 for (col
= 0; col
< dstWidth
; col
++) {
364 GLint col4
= (col
/ wScale
) * 4;
365 GLubyte r
= src
[col4
+ 0];
366 GLubyte g
= src
[col4
+ 1];
367 GLubyte b
= src
[col4
+ 2];
368 dst
[col
] = ((r
& 0xf8) << 8)
372 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
377 /* can't handle this srcFormat/srcType combination */
382 case MESA_A4_R4_G4_B4
:
383 /* store as 16-bit texels (GR_TEXFMT_ARGB_4444) */
384 if (srcFormat
== GL_BGRA
&& srcType
== GL_UNSIGNED_SHORT_4_4_4_4_REV
){
385 /* special, optimized case */
386 if (wScale
== 1 && hScale
== 1) {
387 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
388 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
389 const GLint srcStride
= _mesa_image_row_stride(packing
,
390 srcWidth
, srcFormat
, srcType
);
391 GLushort
*dst
= (GLushort
*) dstImage
;
393 for (row
= 0; row
< dstHeight
; row
++) {
394 MEMCPY(dst
, src
, dstWidth
* sizeof(GLushort
));
396 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
400 /* must rescale image */
401 GLushort
*dst
= (GLushort
*) dstImage
;
403 for (row
= 0; row
< dstHeight
; row
++) {
404 GLint srcRow
= row
/ hScale
;
405 const GLushort
*src
= _mesa_image_address(packing
, srcImage
,
406 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
408 for (col
= 0; col
< dstWidth
; col
++) {
409 dst
[col
] = src
[col
/ wScale
];
411 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
415 else if (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
) {
417 if (wScale
== 1 && hScale
== 1) {
418 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
419 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
420 const GLint srcStride
= _mesa_image_row_stride(packing
,
421 srcWidth
, srcFormat
, srcType
);
422 #ifdef DO_32BIT_STORES
423 GLuint
*dst
= dstImage
;
425 for (row
= 0; row
< dstHeight
; row
++) {
427 GLint halfDstWidth
= dstWidth
>> 1;
428 for (col
= col4
= 0; col
< halfDstWidth
; col
++, col4
+= 8) {
429 GLubyte r0
= src
[col4
+ 0];
430 GLubyte g0
= src
[col4
+ 1];
431 GLubyte b0
= src
[col4
+ 2];
432 GLubyte a0
= src
[col4
+ 3];
433 GLubyte r1
= src
[col4
+ 4];
434 GLubyte g1
= src
[col4
+ 5];
435 GLubyte b1
= src
[col4
+ 6];
436 GLubyte a1
= src
[col4
+ 7];
437 GLuint d0
= ((a0
& 0xf0) << 8)
440 | ((b0
& 0xf0) >> 4);
441 GLuint d1
= ((a1
& 0xf0) << 8)
444 | ((b1
& 0xf0) >> 4);
445 dst
[col
] = (d1
<< 16) | d0
;
448 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
450 #else /* 16-bit stores */
451 GLushort
*dst
= (GLushort
*) dstImage
;
453 for (row
= 0; row
< dstHeight
; row
++) {
455 for (col
= col4
= 0; col
< dstWidth
; col
++, col4
+= 4) {
456 GLubyte r
= src
[col4
+ 0];
457 GLubyte g
= src
[col4
+ 1];
458 GLubyte b
= src
[col4
+ 2];
459 GLubyte a
= src
[col4
+ 3];
460 dst
[col
] = ((a
& 0xf0) << 8)
466 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
471 /* must rescale image */
472 GLushort
*dst
= (GLushort
*) dstImage
;
474 for (row
= 0; row
< dstHeight
; row
++) {
475 GLint srcRow
= row
/ hScale
;
476 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
477 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
479 for (col
= 0; col
< dstWidth
; col
++) {
480 GLint col4
= (col
/ wScale
) * 4;
481 GLubyte r
= src
[col4
+ 0];
482 GLubyte g
= src
[col4
+ 1];
483 GLubyte b
= src
[col4
+ 2];
484 GLubyte a
= src
[col4
+ 3];
485 dst
[col
] = ((a
& 0xf0) << 8)
490 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
495 /* can't handle this format/srcType combination */
500 case MESA_A1_R5_G5_B5
:
501 /* store as 16-bit texels (GR_TEXFMT_ARGB_1555) */
502 if (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_SHORT_1_5_5_5_REV
){
503 /* special, optimized case */
504 if (wScale
== 1 && hScale
== 1) {
505 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
506 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
507 const GLint srcStride
= _mesa_image_row_stride(packing
,
508 srcWidth
, srcFormat
, srcType
);
509 GLushort
*dst
= (GLushort
*) dstImage
;
511 for (row
= 0; row
< dstHeight
; row
++) {
512 MEMCPY(dst
, src
, dstWidth
* sizeof(GLushort
));
514 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
518 /* must rescale image */
519 GLushort
*dst
= (GLushort
*) dstImage
;
521 for (row
= 0; row
< dstHeight
; row
++) {
522 GLint srcRow
= row
/ hScale
;
523 const GLushort
*src
= _mesa_image_address(packing
, srcImage
,
524 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
526 for (col
= 0; col
< dstWidth
; col
++) {
527 dst
[col
] = src
[col
/ wScale
];
529 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
533 else if (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
) {
535 if (wScale
== 1 && hScale
== 1) {
536 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
537 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
538 const GLint srcStride
= _mesa_image_row_stride(packing
,
539 srcWidth
, srcFormat
, srcType
);
540 GLushort
*dst
= (GLushort
*) dstImage
;
542 for (row
= 0; row
< dstHeight
; row
++) {
544 for (col
= col4
= 0; col
< dstWidth
; col
++, col4
+= 4) {
545 GLubyte r
= src
[col4
+ 0];
546 GLubyte g
= src
[col4
+ 1];
547 GLubyte b
= src
[col4
+ 2];
548 GLubyte a
= src
[col4
+ 3];
549 dst
[col
] = ((a
& 0x80) << 8)
555 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
559 /* must rescale image */
560 GLushort
*dst
= (GLushort
*) dstImage
;
562 for (row
= 0; row
< dstHeight
; row
++) {
563 GLint srcRow
= row
/ hScale
;
564 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
565 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
567 for (col
= 0; col
< dstWidth
; col
++) {
568 GLint col4
= (col
/ wScale
) * 4;
569 GLubyte r
= src
[col4
+ 0];
570 GLubyte g
= src
[col4
+ 1];
571 GLubyte b
= src
[col4
+ 2];
572 GLubyte a
= src
[col4
+ 3];
573 dst
[col
] = ((a
& 0x80) << 8)
578 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
583 /* can't handle this source format/type combination */
588 case MESA_A8_R8_G8_B8
:
590 if (srcFormat
== GL_BGRA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
){
591 /* special, optimized case */
592 if (wScale
== 1 && hScale
== 1) {
593 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
594 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
595 const GLint srcStride
= _mesa_image_row_stride(packing
,
596 srcWidth
, srcFormat
, srcType
);
597 GLuint
*dst
= dstImage
;
599 for (row
= 0; row
< dstHeight
; row
++) {
600 MEMCPY(dst
, src
, dstWidth
* sizeof(GLuint
));
602 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
606 /* must rescale image */
607 GLuint
*dst
= dstImage
;
609 for (row
= 0; row
< dstHeight
; row
++) {
610 GLint srcRow
= row
/ hScale
;
611 const GLuint
*src
= _mesa_image_address(packing
, srcImage
,
612 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
614 for (col
= 0; col
< dstWidth
; col
++) {
615 dst
[col
] = src
[col
/ wScale
];
617 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
621 else if (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
) {
623 if (wScale
== 1 && hScale
== 1) {
624 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
625 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
626 const GLint srcStride
= _mesa_image_row_stride(packing
,
627 srcWidth
, srcFormat
, srcType
);
628 GLuint
*dst
= dstImage
;
630 for (row
= 0; row
< dstHeight
; row
++) {
632 for (col
= col4
= 0; col
< dstWidth
; col
++, col4
+= 4) {
633 GLubyte r
= src
[col4
+ 0];
634 GLubyte g
= src
[col4
+ 1];
635 GLubyte b
= src
[col4
+ 2];
636 GLubyte a
= src
[col4
+ 3];
637 dst
[col
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
640 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
644 /* must rescale image */
645 GLuint
*dst
= dstImage
;
647 for (row
= 0; row
< dstHeight
; row
++) {
648 GLint srcRow
= row
/ hScale
;
649 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
650 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
652 for (col
= 0; col
< dstWidth
; col
++) {
653 GLint col4
= (col
/ wScale
) * 4;
654 GLubyte r
= src
[col4
+ 0];
655 GLubyte g
= src
[col4
+ 1];
656 GLubyte b
= src
[col4
+ 2];
657 GLubyte a
= src
[col4
+ 3];
658 dst
[col
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
660 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
665 /* can't handle this source format/type combination */
672 /* unexpected internal format! */
681 * Replace a subregion of a texture image with new data.
683 * dstFormat - destination image format
684 * dstXoffset, dstYoffset - destination for new subregion
685 * dstWidth, dstHeight - total size of dest image
686 * dstImage - pointer to dest image
687 * dstRowStride - bytes to jump between image rows
688 * width, height - size of region to copy/replace
689 * srcWidth, srcHeight - size of the corresponding gl_texture_image
690 * srcFormat, srcType - source image format and datatype
691 * srcImage - source image
692 * packing - source image packing information.
693 * Return: GL_TRUE or GL_FALSE for success, failure
696 * Like _mesa_convert_teximage(), we can do power-of-two image scaling
697 * to accomodate hardware with texture image aspect ratio constraints.
698 * dstWidth / srcWidth is used to compute the horizontal scaling factor and
699 * dstHeight / srcHeight is used to compute the vertical scaling factor.
702 _mesa_convert_texsubimage(MesaIntTexFormat dstFormat
,
703 GLint dstXoffset
, GLint dstYoffset
,
704 GLint dstWidth
, GLint dstHeight
, GLvoid
*dstImage
,
706 GLint width
, GLint height
,
707 GLint srcWidth
, GLint srcHeight
,
708 GLenum srcFormat
, GLenum srcType
,
709 const GLvoid
*srcImage
,
710 const struct gl_pixelstore_attrib
*packing
)
712 const GLint wScale
= dstWidth
/ srcWidth
; /* must be power of two */
713 const GLint hScale
= dstHeight
/ srcHeight
; /* must be power of two */
714 ASSERT(dstWidth
>= srcWidth
);
715 ASSERT(dstHeight
>= srcHeight
);
722 dstXoffset
*= wScale
;
723 dstYoffset
*= hScale
;
725 /* XXX hscale != 1 and wscale != 1 not tested!!!! */
732 if (srcType
!= GL_UNSIGNED_BYTE
||
733 ((srcFormat
!= GL_INTENSITY
) &&
734 (srcFormat
!= GL_LUMINANCE
) &&
735 (srcFormat
!= GL_ALPHA
) &&
736 (srcFormat
!= GL_COLOR_INDEX
))) {
737 /* bad internal format / srcFormat combination */
741 /* store as 8-bit texels */
742 if (wScale
== 1 && hScale
== 1) {
743 /* no scaling needed - fast case */
744 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
745 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
746 const GLint srcStride
= _mesa_image_row_stride(packing
,
747 width
, srcFormat
, srcType
);
748 GLubyte
*dst
= (GLubyte
*) dstImage
749 + dstYoffset
* dstRowStride
+ dstXoffset
;
751 for (row
= 0; row
< height
; row
++) {
752 MEMCPY(dst
, src
, width
* sizeof(GLubyte
));
758 /* must rescale image */
759 GLubyte
*dst
= (GLubyte
*) dstImage
760 + dstYoffset
* dstRowStride
+ dstXoffset
;
762 for (row
= 0; row
< height
; row
++) {
763 GLint srcRow
= row
/ hScale
;
764 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
765 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
767 for (col
= 0; col
< width
; col
++) {
768 dst
[col
] = src
[col
/ wScale
];
777 if (srcType
!= GL_UNSIGNED_BYTE
|| srcFormat
!= GL_LUMINANCE_ALPHA
) {
781 /* store as 16-bit texels */
782 if (wScale
== 1 && hScale
== 1) {
783 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
784 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
785 const GLint srcStride
= _mesa_image_row_stride(packing
,
786 width
, srcFormat
, srcType
);
787 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
788 + dstYoffset
* dstRowStride
) + dstXoffset
;
790 for (row
= 0; row
< height
; row
++) {
791 for (col
= 0; col
< width
; col
++) {
792 GLubyte luminance
= src
[col
* 2 + 0];
793 GLubyte alpha
= src
[col
* 2 + 1];
794 dst
[col
] = ((GLushort
) alpha
<< 8) | luminance
;
796 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
802 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
803 + dstYoffset
* dstRowStride
) + dstXoffset
;
805 for (row
= 0; row
< height
; row
++) {
806 GLint srcRow
= row
/ hScale
;
807 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
808 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
809 const GLint srcStride
= _mesa_image_row_stride(packing
,
810 width
, srcFormat
, srcType
);
811 for (col
= 0; col
< width
; col
++) {
812 GLint srcCol
= col
/ wScale
;
813 GLubyte luminance
= src
[srcCol
* 2 + 0];
814 GLubyte alpha
= src
[srcCol
* 2 + 1];
815 dst
[col
] = ((GLushort
) alpha
<< 8) | luminance
;
817 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
825 if (srcFormat
== GL_RGB
&& srcType
== GL_UNSIGNED_SHORT_5_6_5
) {
826 /* special, optimized case */
827 if (wScale
== 1 && hScale
== 1) {
828 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
829 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
830 const GLint srcStride
= _mesa_image_row_stride(packing
,
831 width
, srcFormat
, srcType
);
832 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
833 + dstYoffset
* dstRowStride
) + dstXoffset
;
835 for (row
= 0; row
< height
; row
++) {
836 MEMCPY(dst
, src
, width
* sizeof(GLushort
));
838 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
842 /* must rescale image */
843 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
844 + dstYoffset
* dstRowStride
) + dstXoffset
;
846 for (row
= 0; row
< height
; row
++) {
847 GLint srcRow
= row
/ hScale
;
848 const GLushort
*src
= _mesa_image_address(packing
, srcImage
,
849 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
851 for (col
= 0; col
< width
; col
++) {
852 dst
[col
] = src
[col
/ wScale
];
854 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
858 else if (srcFormat
== GL_RGB
&& srcType
== GL_UNSIGNED_BYTE
) {
860 if (wScale
== 1 && hScale
== 1) {
861 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
862 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
863 const GLint srcStride
= _mesa_image_row_stride(packing
,
864 width
, srcFormat
, srcType
);
865 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
866 + dstYoffset
* dstRowStride
) + dstXoffset
;
868 for (row
= 0; row
< height
; row
++) {
870 for (col
= col3
= 0; col
< width
; col
++, col3
+= 3) {
871 GLubyte r
= src
[col3
+ 0];
872 GLubyte g
= src
[col3
+ 1];
873 GLubyte b
= src
[col3
+ 2];
874 dst
[col
] = ((r
& 0xf8) << 8)
879 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
883 /* must rescale image */
884 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
885 + dstYoffset
* dstRowStride
) + dstXoffset
;
887 for (row
= 0; row
< height
; row
++) {
888 GLint srcRow
= row
/ hScale
;
889 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
890 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
892 for (col
= 0; col
< width
; col
++) {
893 GLint col3
= (col
/ wScale
) * 3;
894 GLubyte r
= src
[col3
+ 0];
895 GLubyte g
= src
[col3
+ 1];
896 GLubyte b
= src
[col3
+ 2];
897 dst
[col
] = ((r
& 0xf8) << 8)
901 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
905 else if (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
) {
906 /* general case (used by Quake3) */
907 if (wScale
== 1 && hScale
== 1) {
908 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
909 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
910 const GLint srcStride
= _mesa_image_row_stride(packing
,
911 width
, srcFormat
, srcType
);
912 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
913 + dstYoffset
* dstRowStride
) + dstXoffset
;
915 for (row
= 0; row
< height
; row
++) {
917 for (col
= col4
= 0; col
< width
; col
++, col4
+= 4) {
918 GLubyte r
= src
[col4
+ 0];
919 GLubyte g
= src
[col4
+ 1];
920 GLubyte b
= src
[col4
+ 2];
921 dst
[col
] = ((r
& 0xf8) << 8)
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 GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
937 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
939 for (col
= 0; col
< width
; col
++) {
940 GLint col4
= (col
/ wScale
) * 4;
941 GLubyte r
= src
[col4
+ 0];
942 GLubyte g
= src
[col4
+ 1];
943 GLubyte b
= src
[col4
+ 2];
944 dst
[col
] = ((r
& 0xf8) << 8)
948 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
953 /* can't handle this srcFormat/srcType combination */
958 case MESA_A4_R4_G4_B4
:
959 /* store as 16-bit texels (GR_TEXFMT_ARGB_4444) */
960 if (srcFormat
== GL_BGRA
&& srcType
== GL_UNSIGNED_SHORT_4_4_4_4_REV
){
961 /* special, optimized case */
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
++) {
971 MEMCPY(dst
, src
, width
* sizeof(GLushort
));
973 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
977 /* must rescale image */
978 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
979 + dstYoffset
* dstRowStride
) + dstXoffset
;
981 for (row
= 0; row
< height
; row
++) {
982 GLint srcRow
= row
/ hScale
;
983 const GLushort
*src
= _mesa_image_address(packing
, srcImage
,
984 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
986 for (col
= 0; col
< width
; col
++) {
987 dst
[col
] = src
[col
/ wScale
];
989 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
993 else if (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
) {
995 if (wScale
== 1 && hScale
== 1) {
996 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
997 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
998 const GLint srcStride
= _mesa_image_row_stride(packing
,
999 width
, srcFormat
, srcType
);
1000 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
1001 + dstYoffset
* dstRowStride
) + dstXoffset
;
1003 for (row
= 0; row
< height
; row
++) {
1005 for (col
= col4
= 0; col
< width
; col
++, col4
+= 4) {
1006 GLubyte r
= src
[col4
+ 0];
1007 GLubyte g
= src
[col4
+ 1];
1008 GLubyte b
= src
[col4
+ 2];
1009 GLubyte a
= src
[col4
+ 3];
1010 dst
[col
] = ((a
& 0xf0) << 8)
1013 | ((b
& 0xf0) >> 4);
1016 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
1020 /* must rescale image */
1021 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
1022 + dstYoffset
* dstRowStride
) + dstXoffset
;
1024 for (row
= 0; row
< height
; row
++) {
1025 GLint srcRow
= row
/ hScale
;
1026 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
1027 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
1029 for (col
= 0; col
< width
; col
++) {
1030 GLint col4
= (col
/ wScale
) * 4;
1031 GLubyte r
= src
[col4
+ 0];
1032 GLubyte g
= src
[col4
+ 1];
1033 GLubyte b
= src
[col4
+ 2];
1034 GLubyte a
= src
[col4
+ 3];
1035 dst
[col
] = ((a
& 0xf0) << 8)
1038 | ((b
& 0xf0) >> 4);
1040 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
1045 /* can't handle this format/srcType combination */
1050 case MESA_A1_R5_G5_B5
:
1051 /* store as 16-bit texels (GR_TEXFMT_ARGB_1555) */
1052 if (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_SHORT_1_5_5_5_REV
){
1053 /* special, optimized case */
1054 if (wScale
== 1 && hScale
== 1) {
1055 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
1056 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
1057 const GLint srcStride
= _mesa_image_row_stride(packing
,
1058 width
, srcFormat
, srcType
);
1059 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
1060 + dstYoffset
* dstRowStride
) + dstXoffset
;
1062 for (row
= 0; row
< height
; row
++) {
1063 MEMCPY(dst
, src
, width
* sizeof(GLushort
));
1065 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
1069 /* must rescale image */
1070 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
1071 + dstYoffset
* dstRowStride
) + dstXoffset
;
1073 for (row
= 0; row
< height
; row
++) {
1074 GLint srcRow
= row
/ hScale
;
1075 const GLushort
*src
= _mesa_image_address(packing
, srcImage
,
1076 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
1078 for (col
= 0; col
< width
; col
++) {
1079 dst
[col
] = src
[col
/ wScale
];
1081 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
1085 else if (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
) {
1087 if (wScale
== 1 && hScale
== 1) {
1088 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
1089 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
1090 const GLint srcStride
= _mesa_image_row_stride(packing
,
1091 width
, srcFormat
, srcType
);
1092 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
1093 + dstYoffset
* dstRowStride
) + dstXoffset
;
1095 for (row
= 0; row
< height
; row
++) {
1097 for (col
= col4
= 0; col
< width
; col
++, col4
+= 4) {
1098 GLubyte r
= src
[col4
+ 0];
1099 GLubyte g
= src
[col4
+ 1];
1100 GLubyte b
= src
[col4
+ 2];
1101 GLubyte a
= src
[col4
+ 3];
1102 dst
[col
] = ((a
& 0x80) << 8)
1105 | ((b
& 0xf8) >> 3);
1108 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
1112 /* must rescale image */
1113 GLushort
*dst
= (GLushort
*) ((GLubyte
*) dstImage
1114 + dstYoffset
* dstRowStride
) + dstXoffset
;
1116 for (row
= 0; row
< height
; row
++) {
1117 GLint srcRow
= row
/ hScale
;
1118 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
1119 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
1121 for (col
= 0; col
< width
; col
++) {
1122 GLint col4
= (col
/ wScale
) * 4;
1123 GLubyte r
= src
[col4
+ 0];
1124 GLubyte g
= src
[col4
+ 1];
1125 GLubyte b
= src
[col4
+ 2];
1126 GLubyte a
= src
[col4
+ 3];
1127 dst
[col
] = ((a
& 0x80) << 8)
1130 | ((b
& 0xf8) >> 3);
1132 dst
= (GLushort
*) ((GLubyte
*) dst
+ dstRowStride
);
1137 /* can't handle this source format/type combination */
1142 case MESA_A8_R8_G8_B8
:
1144 if (srcFormat
== GL_BGRA
&& srcType
== GL_UNSIGNED_INT_8_8_8_8_REV
){
1145 /* special, optimized case */
1146 if (wScale
== 1 && hScale
== 1) {
1147 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
1148 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
1149 const GLint srcStride
= _mesa_image_row_stride(packing
,
1150 width
, srcFormat
, srcType
);
1151 GLuint
*dst
= (GLuint
*) ((GLubyte
*) dstImage
1152 + dstYoffset
* dstRowStride
) + dstXoffset
;
1154 for (row
= 0; row
< height
; row
++) {
1155 MEMCPY(dst
, src
, width
* sizeof(GLuint
));
1157 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
1161 /* must rescale image */
1162 GLuint
*dst
= (GLuint
*) ((GLubyte
*) dstImage
1163 + dstYoffset
* dstRowStride
) + dstXoffset
;
1165 for (row
= 0; row
< height
; row
++) {
1166 GLint srcRow
= row
/ hScale
;
1167 const GLuint
*src
= _mesa_image_address(packing
, srcImage
,
1168 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
1170 for (col
= 0; col
< width
; col
++) {
1171 dst
[col
] = src
[col
/ wScale
];
1173 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
1177 else if (srcFormat
== GL_RGBA
&& srcType
== GL_UNSIGNED_BYTE
) {
1179 if (wScale
== 1 && hScale
== 1) {
1180 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
1181 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, 0, 0);
1182 const GLint srcStride
= _mesa_image_row_stride(packing
,
1183 width
, srcFormat
, srcType
);
1184 GLuint
*dst
= (GLuint
*) ((GLubyte
*) dstImage
1185 + dstYoffset
* dstRowStride
) + dstXoffset
;
1187 for (row
= 0; row
< height
; row
++) {
1189 for (col
= col4
= 0; col
< width
; col
++, col4
+= 4) {
1190 GLubyte r
= src
[col4
+ 0];
1191 GLubyte g
= src
[col4
+ 1];
1192 GLubyte b
= src
[col4
+ 2];
1193 GLubyte a
= src
[col4
+ 3];
1194 dst
[col
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
1197 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
1201 /* must rescale image */
1202 GLuint
*dst
= (GLuint
*) ((GLubyte
*) dstImage
1203 + dstYoffset
* dstRowStride
) + dstXoffset
;
1205 for (row
= 0; row
< height
; row
++) {
1206 GLint srcRow
= row
/ hScale
;
1207 const GLubyte
*src
= _mesa_image_address(packing
, srcImage
,
1208 srcWidth
, srcHeight
, srcFormat
, srcType
, 0, srcRow
, 0);
1210 for (col
= 0; col
< width
; col
++) {
1211 GLint col4
= (col
/ wScale
) * 4;
1212 GLubyte r
= src
[col4
+ 0];
1213 GLubyte g
= src
[col4
+ 1];
1214 GLubyte b
= src
[col4
+ 2];
1215 GLubyte a
= src
[col4
+ 3];
1216 dst
[col
] = (a
<< 24) | (r
<< 16) | (g
<< 8) | b
;
1218 dst
= (GLuint
*) ((GLubyte
*) dst
+ dstRowStride
);
1223 /* can't handle this source format/type combination */
1230 /* unexpected internal format! */
1240 * Used to convert 16-bit texels into GLubyte color components.
1242 static GLubyte R5G6B5toRed
[0xffff];
1243 static GLubyte R5G6B5toGreen
[0xffff];
1244 static GLubyte R5G6B5toBlue
[0xffff];
1246 static GLubyte A4R4G4B4toRed
[0xffff];
1247 static GLubyte A4R4G4B4toGreen
[0xffff];
1248 static GLubyte A4R4G4B4toBlue
[0xffff];
1249 static GLubyte A4R4G4B4toAlpha
[0xffff];
1251 static GLubyte A1R5G5B5toRed
[0xffff];
1252 static GLubyte A1R5G5B5toGreen
[0xffff];
1253 static GLubyte A1R5G5B5toBlue
[0xffff];
1254 static GLubyte A1R5G5B5toAlpha
[0xffff];
1257 generate_lookup_tables(void)
1260 for (i
= 0; i
<= 0xffff; i
++) {
1261 GLint r
= (i
>> 8) & 0xf8;
1262 GLint g
= (i
>> 3) & 0xfc;
1263 GLint b
= (i
<< 3) & 0xf8;
1268 R5G6B5toGreen
[i
] = g
;
1269 R5G6B5toBlue
[i
] = b
;
1272 for (i
= 0; i
<= 0xffff; i
++) {
1273 GLint r
= (i
>> 8) & 0xf;
1274 GLint g
= (i
>> 4) & 0xf;
1275 GLint b
= (i
) & 0xf;
1276 GLint a
= (i
>> 12) & 0xf;
1281 A4R4G4B4toRed
[i
] = r
;
1282 A4R4G4B4toGreen
[i
] = g
;
1283 A4R4G4B4toBlue
[i
] = b
;
1284 A4R4G4B4toAlpha
[i
] = a
;
1287 for (i
= 0; i
<= 0xffff; i
++) {
1288 GLint r
= (i
>> 10) & 0xf8;
1289 GLint g
= (i
>> 5) & 0xf8;
1290 GLint b
= (i
) & 0xf8;
1291 GLint a
= (i
>> 15) & 0x1;
1296 A1R5G5B5toRed
[i
] = r
;
1297 A1R5G5B5toGreen
[i
] = g
;
1298 A1R5G5B5toBlue
[i
] = b
;
1299 A1R5G5B5toAlpha
[i
] = a
;
1306 * Convert a texture image from an internal format to one of Mesa's
1307 * core internal formats. This is likely to be used by glGetTexImage
1308 * and for fetching texture images when falling back to software rendering.
1311 * srcFormat - source image format
1312 * srcWidth, srcHeight - source image size
1313 * srcImage - source image pointer
1314 * srcRowStride - bytes to jump between image rows
1315 * dstWidth, dstHeight - size of dest image
1316 * dstFormat - format of dest image (must be one of Mesa's IntFormat values)
1317 * dstImage - pointer to dest image
1319 * This function will do power of two image down-scaling to accomodate
1320 * drivers with limited texture image aspect ratios.
1321 * The implicit dest data type is GL_UNSIGNED_BYTE.
1324 _mesa_unconvert_teximage(MesaIntTexFormat srcFormat
,
1325 GLint srcWidth
, GLint srcHeight
,
1326 const GLvoid
*srcImage
, GLint srcRowStride
,
1327 GLint dstWidth
, GLint dstHeight
,
1328 GLenum dstFormat
, GLubyte
*dstImage
)
1330 static GLboolean firstCall
= GL_TRUE
;
1331 const GLint wScale
= srcWidth
/ dstWidth
; /* must be power of two */
1332 const GLint hScale
= srcHeight
/ dstHeight
; /* must be power of two */
1333 ASSERT(srcWidth
>= dstWidth
);
1334 ASSERT(srcHeight
>= dstHeight
);
1339 generate_lookup_tables();
1340 firstCall
= GL_FALSE
;
1343 switch (srcFormat
) {
1349 if (srcFormat
== MESA_I8
) {
1350 ASSERT(dstFormat
== GL_INTENSITY
);
1352 else if (srcFormat
== MESA_L8
) {
1353 ASSERT(dstFormat
== GL_LUMINANCE
);
1355 else if (srcFormat
== MESA_A8
) {
1356 ASSERT(dstFormat
== GL_ALPHA
);
1358 else if (srcFormat
== MESA_C8
) {
1359 ASSERT(dstFormat
== GL_COLOR_INDEX
);
1362 if (wScale
== 1 && hScale
== 1) {
1364 MEMCPY(dstImage
, srcImage
, dstWidth
* dstHeight
* sizeof(GLubyte
));
1368 const GLubyte
*src8
= (const GLubyte
*) srcImage
;
1370 for (row
= 0; row
< dstHeight
; row
++) {
1371 GLint srcRow
= row
* hScale
;
1372 for (col
= 0; col
< dstWidth
; col
++) {
1373 GLint srcCol
= col
* wScale
;
1374 *dstImage
++ = src8
[srcRow
* srcWidth
+ srcCol
];
1380 ASSERT(dstFormat
== GL_LUMINANCE_ALPHA
);
1381 if (wScale
== 1 && hScale
== 1) {
1382 GLint i
, n
= dstWidth
* dstHeight
;
1383 const GLushort
*texel
= (const GLushort
*) srcImage
;
1384 for (i
= 0; i
< n
; i
++) {
1385 const GLushort tex
= *texel
++;
1386 *dstImage
++ = (tex
& 0xff); /* luminance */
1387 *dstImage
++ = (tex
>> 8); /* alpha */
1392 const GLushort
*src16
= (const GLushort
*) srcImage
;
1394 for (row
= 0; row
< dstHeight
; row
++) {
1395 GLint srcRow
= row
* hScale
;
1396 for (col
= 0; col
< dstWidth
; col
++) {
1397 GLint srcCol
= col
* wScale
;
1398 const GLushort tex
= src16
[srcRow
* srcWidth
+ srcCol
];
1399 *dstImage
++ = (tex
& 0xff); /* luminance */
1400 *dstImage
++ = (tex
>> 8); /* alpha */
1406 ASSERT(dstFormat
== GL_RGB
);
1407 if (wScale
== 1 && hScale
== 1) {
1408 GLint i
, n
= dstWidth
* dstHeight
;
1409 const GLushort
*texel
= (const GLushort
*) srcImage
;
1410 for (i
= 0; i
< n
; i
++) {
1411 const GLushort tex
= *texel
++;
1412 *dstImage
++ = R5G6B5toRed
[tex
];
1413 *dstImage
++ = R5G6B5toGreen
[tex
];
1414 *dstImage
++ = R5G6B5toBlue
[tex
];
1419 const GLushort
*src16
= (const GLushort
*) srcImage
;
1421 for (row
= 0; row
< dstHeight
; row
++) {
1422 GLint srcRow
= row
* hScale
;
1423 for (col
= 0; col
< dstWidth
; col
++) {
1424 GLint srcCol
= col
* wScale
;
1425 const GLushort tex
= src16
[srcRow
* srcWidth
+ srcCol
];
1426 *dstImage
++ = R5G6B5toRed
[tex
];
1427 *dstImage
++ = R5G6B5toGreen
[tex
];
1428 *dstImage
++ = R5G6B5toBlue
[tex
];
1433 case MESA_A4_R4_G4_B4
:
1434 ASSERT(dstFormat
== GL_RGBA
);
1435 if (wScale
== 1 && hScale
== 1) {
1436 GLint i
, n
= dstWidth
* dstHeight
;
1437 const GLushort
*texel
= (const GLushort
*) srcImage
;
1438 for (i
= 0; i
< n
; i
++) {
1439 const GLushort tex
= *texel
++;
1440 *dstImage
++ = A4R4G4B4toRed
[tex
];
1441 *dstImage
++ = A4R4G4B4toGreen
[tex
];
1442 *dstImage
++ = A4R4G4B4toBlue
[tex
];
1443 *dstImage
++ = A4R4G4B4toAlpha
[tex
];
1448 const GLushort
*src16
= (const GLushort
*) srcImage
;
1450 for (row
= 0; row
< dstHeight
; row
++) {
1451 GLint srcRow
= row
* hScale
;
1452 for (col
= 0; col
< dstWidth
; col
++) {
1453 GLint srcCol
= col
* wScale
;
1454 const GLushort tex
= src16
[srcRow
* srcWidth
+ srcCol
];
1455 *dstImage
++ = A4R4G4B4toRed
[tex
];
1456 *dstImage
++ = A4R4G4B4toGreen
[tex
];
1457 *dstImage
++ = A4R4G4B4toBlue
[tex
];
1458 *dstImage
++ = A4R4G4B4toAlpha
[tex
];
1463 case MESA_A1_R5_G5_B5
:
1464 ASSERT(dstFormat
== GL_RGBA
);
1465 if (wScale
== 1 && hScale
== 1) {
1466 GLint i
, n
= dstWidth
* dstHeight
;
1467 const GLushort
*texel
= (const GLushort
*) srcImage
;
1468 for (i
= 0; i
< n
; i
++) {
1469 const GLushort tex
= *texel
++;
1470 *dstImage
++ = A1R5G5B5toRed
[tex
];
1471 *dstImage
++ = A1R5G5B5toGreen
[tex
];
1472 *dstImage
++ = A1R5G5B5toBlue
[tex
];
1473 *dstImage
++ = A1R5G5B5toAlpha
[tex
];
1478 const GLushort
*src16
= (const GLushort
*) srcImage
;
1480 for (row
= 0; row
< dstHeight
; row
++) {
1481 GLint srcRow
= row
* hScale
;
1482 for (col
= 0; col
< dstWidth
; col
++) {
1483 GLint srcCol
= col
* wScale
;
1484 const GLushort tex
= src16
[srcRow
* srcWidth
+ srcCol
];
1485 *dstImage
++ = A1R5G5B5toRed
[tex
];
1486 *dstImage
++ = A1R5G5B5toGreen
[tex
];
1487 *dstImage
++ = A1R5G5B5toBlue
[tex
];
1488 *dstImage
++ = A1R5G5B5toAlpha
[tex
];
1493 case MESA_A8_R8_G8_B8
:
1494 ASSERT(dstFormat
== GL_RGBA
);
1495 if (wScale
== 1 && hScale
== 1) {
1496 GLint i
, n
= dstWidth
* dstHeight
;
1497 const GLuint
*texel
= (const GLuint
*) srcImage
;
1498 for (i
= 0; i
< n
; i
++) {
1499 const GLuint tex
= *texel
++;
1500 *dstImage
++ = (tex
>> 16) & 0xff; /* R */
1501 *dstImage
++ = (tex
>> 8) & 0xff; /* G */
1502 *dstImage
++ = (tex
) & 0xff; /* B */
1503 *dstImage
++ = (tex
>> 24) & 0xff; /* A */
1508 const GLuint
*src
= (const GLuint
*) srcImage
;
1510 for (row
= 0; row
< dstHeight
; row
++) {
1511 GLint srcRow
= row
* hScale
;
1512 for (col
= 0; col
< dstWidth
; col
++) {
1513 GLint srcCol
= col
* wScale
;
1514 const GLuint tex
= src
[srcRow
* srcWidth
+ srcCol
];
1515 *dstImage
++ = (tex
>> 16) & 0xff; /* R */
1516 *dstImage
++ = (tex
>> 8) & 0xff; /* G */
1517 *dstImage
++ = (tex
) & 0xff; /* B */
1518 *dstImage
++ = (tex
>> 24) & 0xff; /* A */
1524 gl_problem(NULL
, "bad srcFormat in _mesa_uncovert_teximage()");
1531 * Given an internal Mesa driver texture format, fill in the component
1532 * bit sizes in the given texture image struct.
1535 _mesa_set_teximage_component_sizes(MesaIntTexFormat mesaFormat
,
1536 struct gl_texture_image
*texImage
)
1538 static const GLint bitSizes
[][8] = {
1539 /* format R G B A I L C */
1540 { MESA_I8
, 0, 0, 0, 0, 8, 0, 0 },
1541 { MESA_L8
, 0, 0, 0, 0, 0, 8, 0 },
1542 { MESA_A8
, 0, 0, 0, 8, 0, 0, 0 },
1543 { MESA_C8
, 0, 0, 0, 0, 0, 0, 8 },
1544 { MESA_A8_L8
, 0, 0, 0, 8, 0, 8, 0 },
1545 { MESA_R5_G6_B5
, 5, 6, 5, 0, 0, 0, 0 },
1546 { MESA_A4_R4_G4_B4
, 4, 4, 4, 4, 0, 0, 0 },
1547 { MESA_A1_R5_G5_B5
, 5, 5, 5, 1, 0, 0, 0 },
1548 { MESA_A8_R8_G8_B8
, 8, 8, 8, 8, 0, 0, 0 },
1549 { -1, 0, 0, 0, 0, 0, 0, 0 }
1552 for (i
= 0; i
< bitSizes
[i
][0] >= 0; i
++) {
1553 if (bitSizes
[i
][0] == mesaFormat
) {
1554 texImage
->RedBits
= bitSizes
[i
][1];
1555 texImage
->GreenBits
= bitSizes
[i
][2];
1556 texImage
->BlueBits
= bitSizes
[i
][3];
1557 texImage
->AlphaBits
= bitSizes
[i
][4];
1558 texImage
->IntensityBits
= bitSizes
[i
][5];
1559 texImage
->LuminanceBits
= bitSizes
[i
][6];
1560 texImage
->IndexBits
= bitSizes
[i
][7];
1564 gl_problem(NULL
, "bad format in _mesa_set_teximage_component_sizes");