Overhaul of texture image handling.
[mesa.git] / src / mesa / main / texutil.c
1 /* $Id: texutil.c,v 1.11 2000/12/26 05:09:29 keithw Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.4
6 *
7 * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
8 *
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:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
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.
25 */
26
27
28 #ifdef PC_HEADER
29 #include "all.h"
30 #else
31 #include "glheader.h"
32 #include "context.h"
33 #include "image.h"
34 #include "mem.h"
35 #include "texutil.h"
36 #include "mtypes.h"
37 #endif
38
39
40 /*
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.
44 */
45
46
47 /*
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.
50 */
51 #if defined(__i386__)
52 #define DO_32BIT_STORES000
53 #endif
54
55
56
57 /*
58 * Convert texture image data into one a specific internal format.
59 * Input:
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
70 * combination.
71 *
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...
89 *
90 * Notes:
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.
93 *
94 *
95 */
96 GLboolean
97 _mesa_convert_teximage(MesaIntTexFormat dstFormat,
98 GLint dstWidth, GLint dstHeight, GLvoid *dstImage,
99 GLint dstRowStride,
100 GLint srcWidth, GLint srcHeight,
101 GLenum srcFormat, GLenum srcType,
102 const GLvoid *srcImage,
103 const struct gl_pixelstore_attrib *packing)
104 {
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);
109 ASSERT(dstImage);
110 ASSERT(srcImage);
111 ASSERT(packing);
112
113 switch (dstFormat) {
114 case MESA_I8:
115 case MESA_L8:
116 case MESA_A8:
117 case MESA_C8:
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 */
124 return GL_FALSE;
125 }
126 else {
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;
136 GLint row;
137 for (row = 0; row < dstHeight; row++) {
138 GLuint i;
139 for (i = 0 ; i < dstWidth ; i++)
140 fprintf(stderr, "%02x ", src[i]);
141 fprintf(stderr, "\n");
142 MEMCPY(dst, src, dstWidth * sizeof(GLubyte));
143 dst += dstRowStride;
144 src += srcStride;
145 }
146 }
147 else {
148 /* must rescale image */
149 GLubyte *dst = (GLubyte *) dstImage;
150 GLint row;
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);
156 GLint col;
157 for (col = 0; col < dstWidth; col++) {
158 dst[col] = src[col / wScale];
159 }
160 dst += dstRowStride;
161 }
162 }
163 }
164 break;
165
166 case MESA_A8_L8:
167 if (srcType != GL_UNSIGNED_BYTE || srcFormat != GL_LUMINANCE_ALPHA) {
168 return GL_FALSE;
169 }
170 else {
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;
179 GLint row, col;
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;
185 }
186 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
187 src += srcStride;
188 }
189 }
190 else {
191 /* must rescale */
192 GLushort *dst = (GLushort *) dstImage;
193 GLint row, col;
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;
206 }
207 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
208 src += srcStride;
209 }
210 }
211 }
212 break;
213
214 case MESA_R5_G6_B5:
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;
224 GLint row;
225 for (row = 0; row < dstHeight; row++) {
226 MEMCPY(dst, src, dstWidth * sizeof(GLushort));
227 src += srcStride;
228 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
229 }
230 }
231 else {
232 /* must rescale image */
233 GLushort *dst = (GLushort *) dstImage;
234 GLint row;
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);
240 GLint col;
241 for (col = 0; col < dstWidth; col++) {
242 dst[col] = src[col / wScale];
243 }
244 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
245 }
246 }
247 }
248 else if (srcFormat == GL_RGB && srcType == GL_UNSIGNED_BYTE) {
249 /* general case */
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;
258 GLint row;
259 for (row = 0; row < dstHeight; row++) {
260 GLint col, col3;
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)
270 | ((g0 & 0xfc) << 3)
271 | ((b0 & 0xf8) >> 3);
272 GLuint d1 = ((r1 & 0xf8) << 8)
273 | ((g1 & 0xfc) << 3)
274 | ((b1 & 0xf8) >> 3);
275 dst[col] = (d1 << 16) | d0;
276 }
277 src += srcStride;
278 dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
279 }
280 #else /* 16-bit stores */
281 GLushort *dst = (GLushort *) dstImage;
282 GLint row;
283 for (row = 0; row < dstHeight; row++) {
284 GLint col, col3;
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)
290 | ((g & 0xfc) << 3)
291 | ((b & 0xf8) >> 3);
292 }
293 src += srcStride;
294 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
295 }
296 #endif
297 }
298 else {
299 /* must rescale image */
300 GLushort *dst = (GLushort *) dstImage;
301 GLint row;
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);
307 GLint col;
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)
314 | ((g & 0xfc) << 3)
315 | ((b & 0xf8) >> 3);
316 }
317 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
318 }
319 }
320 }
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;
331 GLint row;
332 for (row = 0; row < dstHeight; row++) {
333 GLint col, col4;
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)
343 | ((g0 & 0xfc) << 3)
344 | ((b0 & 0xf8) >> 3);
345 GLuint d1 = ((r1 & 0xf8) << 8)
346 | ((g1 & 0xfc) << 3)
347 | ((b1 & 0xf8) >> 3);
348 dst[col] = (d1 << 16) | d0;
349 }
350 src += srcStride;
351 dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
352 }
353 #else /* 16-bit stores */
354 GLushort *dst = (GLushort *) dstImage;
355 GLint row;
356 for (row = 0; row < dstHeight; row++) {
357 GLint col, col4;
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)
363 | ((g & 0xfc) << 3)
364 | ((b & 0xf8) >> 3);
365 }
366 src += srcStride;
367 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
368 }
369 #endif
370 }
371 else {
372 /* must rescale image */
373 GLushort *dst = (GLushort *) dstImage;
374 GLint row;
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);
380 GLint col;
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)
387 | ((g & 0xfc) << 3)
388 | ((b & 0xf8) >> 3);
389 }
390 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
391 }
392 }
393 }
394 else {
395 /* can't handle this srcFormat/srcType combination */
396 return GL_FALSE;
397 }
398 break;
399
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;
411 GLint row;
412 for (row = 0; row < dstHeight; row++) {
413 MEMCPY(dst, src, dstWidth * sizeof(GLushort));
414 src += srcStride;
415 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
416 }
417 }
418 else {
419 /* must rescale image */
420 GLushort *dst = (GLushort *) dstImage;
421 GLint row;
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);
427 GLint col;
428 for (col = 0; col < dstWidth; col++) {
429 dst[col] = src[col / wScale];
430 }
431 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
432 }
433 }
434 }
435 else if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) {
436 /* general case */
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;
445 GLint row;
446 for (row = 0; row < dstHeight; row++) {
447 GLint col, col4;
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)
459 | ((r0 & 0xf0) << 4)
460 | ((g0 & 0xf0) )
461 | ((b0 & 0xf0) >> 4);
462 GLuint d1 = ((a1 & 0xf0) << 8)
463 | ((r1 & 0xf0) << 4)
464 | ((g1 & 0xf0) )
465 | ((b1 & 0xf0) >> 4);
466 dst[col] = (d1 << 16) | d0;
467 }
468 src += srcStride;
469 dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
470 }
471 #else /* 16-bit stores */
472 GLushort *dst = (GLushort *) dstImage;
473 GLint row;
474 for (row = 0; row < dstHeight; row++) {
475 GLint col, col4;
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)
482 | ((r & 0xf0) << 4)
483 | ((g & 0xf0) )
484 | ((b & 0xf0) >> 4);
485 }
486 src += srcStride;
487 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
488 }
489 #endif
490 }
491 else {
492 /* must rescale image */
493 GLushort *dst = (GLushort *) dstImage;
494 GLint row;
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);
500 GLint col;
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)
508 | ((r & 0xf0) << 4)
509 | ((g & 0xf0) )
510 | ((b & 0xf0) >> 4);
511 }
512 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
513 }
514 }
515 }
516 else {
517 /* can't handle this format/srcType combination */
518 return GL_FALSE;
519 }
520 break;
521
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;
533 GLint row;
534 for (row = 0; row < dstHeight; row++) {
535 MEMCPY(dst, src, dstWidth * sizeof(GLushort));
536 src += srcStride;
537 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
538 }
539 }
540 else {
541 /* must rescale image */
542 GLushort *dst = (GLushort *) dstImage;
543 GLint row;
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);
549 GLint col;
550 for (col = 0; col < dstWidth; col++) {
551 dst[col] = src[col / wScale];
552 }
553 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
554 }
555 }
556 }
557 else if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) {
558 /* general case */
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;
566 GLint row;
567 for (row = 0; row < dstHeight; row++) {
568 GLint col, col4;
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)
575 | ((r & 0xf8) << 7)
576 | ((g & 0xf8) << 2)
577 | ((b & 0xf8) >> 3);
578 }
579 src += srcStride;
580 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
581 }
582 }
583 else {
584 /* must rescale image */
585 GLushort *dst = (GLushort *) dstImage;
586 GLint row;
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);
592 GLint col;
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)
600 | ((r & 0xf8) << 7)
601 | ((g & 0xf8) << 2)
602 | ((b & 0xf8) >> 3);
603 }
604 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
605 }
606 }
607 }
608 else {
609 /* can't handle this source format/type combination */
610 return GL_FALSE;
611 }
612 break;
613
614 case MESA_A8_R8_G8_B8:
615 case MESA_FF_R8_G8_B8:
616 /* 32-bit texels */
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;
626 GLint row;
627 for (row = 0; row < dstHeight; row++) {
628 MEMCPY(dst, src, dstWidth * sizeof(GLuint));
629 src += srcStride;
630 dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
631 }
632 }
633 else {
634 /* must rescale image */
635 GLuint *dst = (GLuint *) dstImage;
636 GLint row;
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);
642 GLint col;
643 for (col = 0; col < dstWidth; col++) {
644 dst[col] = src[col / wScale];
645 }
646 dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
647 }
648 }
649 }
650 else if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) {
651 /* general case */
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;
659 GLint row;
660 for (row = 0; row < dstHeight; row++) {
661 GLint col, col4;
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;
668 }
669 src += srcStride;
670 dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
671 }
672 }
673 else {
674 /* must rescale image */
675 GLuint *dst = (GLuint *) dstImage;
676 GLint row;
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);
682 GLint col;
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;
690 }
691 dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
692 }
693 }
694 }
695 else if (srcFormat == GL_RGB && srcType == GL_UNSIGNED_BYTE) {
696 /* general case */
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;
704 GLint row;
705 for (row = 0; row < dstHeight; row++) {
706 GLint col, col3;
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];
711 GLubyte a = 255;
712 dst[col] = (a << 24) | (r << 16) | (g << 8) | b;
713 }
714 src += srcStride;
715 dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
716 }
717 }
718 else {
719 /* must rescale image */
720 GLuint *dst = (GLuint *) dstImage;
721 GLint row;
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);
727 GLint col;
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];
733 GLubyte a = 255;
734 dst[col] = (a << 24) | (r << 16) | (g << 8) | b;
735 }
736 dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
737 }
738 }
739 }
740 else {
741 /* can't handle this source format/type combination */
742 return GL_FALSE;
743 }
744 if (dstFormat == MESA_FF_R8_G8_B8) {
745 /* set alpha bytes to 0xff */
746 GLint i;
747 GLubyte *dst = (GLubyte *) dstImage;
748 for (i = 0; i < dstWidth * dstHeight; i++) {
749 dst[i * 4 + 3] = 0xff;
750 }
751 }
752 break;
753
754 default:
755 /* unexpected internal format! */
756 return GL_FALSE;
757 }
758 return GL_TRUE;
759 }
760
761
762
763 /*
764 * Replace a subregion of a texture image with new data.
765 * Input:
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
777 *
778 * Notes:
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.
783 */
784 GLboolean
785 _mesa_convert_texsubimage(MesaIntTexFormat dstFormat,
786 GLint dstXoffset, GLint dstYoffset,
787 GLint dstWidth, GLint dstHeight, GLvoid *dstImage,
788 GLint dstRowStride,
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)
794 {
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);
799 ASSERT(dstImage);
800 ASSERT(srcImage);
801 ASSERT(packing);
802
803 width *= wScale;
804 height *= hScale;
805 dstXoffset *= wScale;
806 dstYoffset *= hScale;
807
808 /* XXX hscale != 1 and wscale != 1 not tested!!!! */
809
810 switch (dstFormat) {
811 case MESA_I8:
812 case MESA_L8:
813 case MESA_A8:
814 case MESA_C8:
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 */
821 return GL_FALSE;
822 }
823 else {
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;
834 GLint row;
835 for (row = 0; row < height; row++) {
836 MEMCPY(dst, src, width * sizeof(GLubyte));
837 dst += dstRowStride;
838 src += srcStride;
839 }
840 }
841 else {
842 /* must rescale image */
843 GLubyte *dst = (GLubyte *) dstImage
844 + dstYoffset * dstRowStride + dstXoffset;
845 GLint row;
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);
851 GLint col;
852 for (col = 0; col < width; col++) {
853 dst[col] = src[col / wScale];
854 }
855 dst += dstRowStride;
856 }
857 }
858 }
859 break;
860
861 case MESA_A8_L8:
862 if (srcType != GL_UNSIGNED_BYTE || srcFormat != GL_LUMINANCE_ALPHA) {
863 return GL_FALSE;
864 }
865 else {
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;
875 GLint row, col;
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;
881 }
882 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
883 src += srcStride;
884 }
885 }
886 else {
887 /* must rescale */
888 GLushort *dst = (GLushort *) ((GLubyte *) dstImage
889 + dstYoffset * dstRowStride) + dstXoffset;
890 GLint row, col;
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;
903 }
904 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
905 src += srcStride;
906 }
907 }
908 }
909 break;
910
911 case MESA_R5_G6_B5:
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;
922 GLint row;
923 for (row = 0; row < height; row++) {
924 MEMCPY(dst, src, width * sizeof(GLushort));
925 src += srcStride;
926 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
927 }
928 }
929 else {
930 /* must rescale image */
931 GLushort *dst = (GLushort *) ((GLubyte *) dstImage
932 + dstYoffset * dstRowStride) + dstXoffset;
933 GLint row;
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);
939 GLint col;
940 for (col = 0; col < width; col++) {
941 dst[col] = src[col / wScale];
942 }
943 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
944 }
945 }
946 }
947 else if (srcFormat == GL_RGB && srcType == GL_UNSIGNED_BYTE) {
948 /* general case */
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;
957 GLint row;
958 for (row = 0; row < height; row++) {
959 GLint col, col3;
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)
965 | ((g & 0xfc) << 3)
966 | ((b & 0xf8) >> 3);
967 }
968 src += srcStride;
969 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
970 }
971 }
972 else {
973 /* must rescale image */
974 GLushort *dst = (GLushort *) ((GLubyte *) dstImage
975 + dstYoffset * dstRowStride) + dstXoffset;
976 GLint row;
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);
982 GLint col;
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)
989 | ((g & 0xfc) << 3)
990 | ((b & 0xf8) >> 3);
991 }
992 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
993 }
994 }
995 }
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;
1006 GLint row;
1007 for (row = 0; row < height; row++) {
1008 GLint col, col4;
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)
1014 | ((g & 0xfc) << 3)
1015 | ((b & 0xf8) >> 3);
1016 }
1017 src += srcStride;
1018 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
1019 }
1020 }
1021 else {
1022 /* must rescale image */
1023 GLushort *dst = (GLushort *) ((GLubyte *) dstImage
1024 + dstYoffset * dstRowStride) + dstXoffset;
1025 GLint row;
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);
1031 GLint col;
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)
1038 | ((g & 0xfc) << 3)
1039 | ((b & 0xf8) >> 3);
1040 }
1041 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
1042 }
1043 }
1044 }
1045 else {
1046 /* can't handle this srcFormat/srcType combination */
1047 return GL_FALSE;
1048 }
1049 break;
1050
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;
1063 GLint row;
1064 for (row = 0; row < height; row++) {
1065 MEMCPY(dst, src, width * sizeof(GLushort));
1066 src += srcStride;
1067 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
1068 }
1069 }
1070 else {
1071 /* must rescale image */
1072 GLushort *dst = (GLushort *) ((GLubyte *) dstImage
1073 + dstYoffset * dstRowStride) + dstXoffset;
1074 GLint row;
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);
1080 GLint col;
1081 for (col = 0; col < width; col++) {
1082 dst[col] = src[col / wScale];
1083 }
1084 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
1085 }
1086 }
1087 }
1088 else if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) {
1089 /* general case */
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;
1098 GLint row;
1099 for (row = 0; row < height; row++) {
1100 GLint col, col4;
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)
1107 | ((r & 0xf0) << 4)
1108 | ((g & 0xf0) )
1109 | ((b & 0xf0) >> 4);
1110 }
1111 src += srcStride;
1112 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
1113 }
1114 }
1115 else {
1116 /* must rescale image */
1117 GLushort *dst = (GLushort *) ((GLubyte *) dstImage
1118 + dstYoffset * dstRowStride) + dstXoffset;
1119 GLint row;
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);
1125 GLint col;
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)
1133 | ((r & 0xf0) << 4)
1134 | ((g & 0xf0) )
1135 | ((b & 0xf0) >> 4);
1136 }
1137 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
1138 }
1139 }
1140 }
1141 else {
1142 /* can't handle this format/srcType combination */
1143 return GL_FALSE;
1144 }
1145 break;
1146
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;
1159 GLint row;
1160 for (row = 0; row < height; row++) {
1161 MEMCPY(dst, src, width * sizeof(GLushort));
1162 src += srcStride;
1163 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
1164 }
1165 }
1166 else {
1167 /* must rescale image */
1168 GLushort *dst = (GLushort *) ((GLubyte *) dstImage
1169 + dstYoffset * dstRowStride) + dstXoffset;
1170 GLint row;
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);
1176 GLint col;
1177 for (col = 0; col < width; col++) {
1178 dst[col] = src[col / wScale];
1179 }
1180 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
1181 }
1182 }
1183 }
1184 else if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) {
1185 /* general case */
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;
1194 GLint row;
1195 for (row = 0; row < height; row++) {
1196 GLint col, col4;
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)
1203 | ((r & 0xf8) << 7)
1204 | ((g & 0xf8) << 2)
1205 | ((b & 0xf8) >> 3);
1206 }
1207 src += srcStride;
1208 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
1209 }
1210 }
1211 else {
1212 /* must rescale image */
1213 GLushort *dst = (GLushort *) ((GLubyte *) dstImage
1214 + dstYoffset * dstRowStride) + dstXoffset;
1215 GLint row;
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);
1221 GLint col;
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)
1229 | ((r & 0xf8) << 7)
1230 | ((g & 0xf8) << 2)
1231 | ((b & 0xf8) >> 3);
1232 }
1233 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
1234 }
1235 }
1236 }
1237 else {
1238 /* can't handle this source format/type combination */
1239 return GL_FALSE;
1240 }
1241 break;
1242
1243 case MESA_A8_R8_G8_B8:
1244 case MESA_FF_R8_G8_B8:
1245 /* 32-bit texels */
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;
1256 GLint row;
1257 for (row = 0; row < height; row++) {
1258 MEMCPY(dst, src, width * sizeof(GLuint));
1259 src += srcStride;
1260 dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
1261 }
1262 }
1263 else {
1264 /* must rescale image */
1265 GLuint *dst = (GLuint *) ((GLubyte *) dstImage
1266 + dstYoffset * dstRowStride) + dstXoffset;
1267 GLint row;
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);
1273 GLint col;
1274 for (col = 0; col < width; col++) {
1275 dst[col] = src[col / wScale];
1276 }
1277 dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
1278 }
1279 }
1280 if (dstFormat == MESA_FF_R8_G8_B8) {
1281 /* set alpha bytes to 0xff */
1282 GLint row, col;
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;
1289 }
1290 dst = dst + dstRowStride;
1291 }
1292 }
1293 }
1294 else if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) {
1295 /* general case */
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;
1305 GLint row;
1306 for (row = 0; row < height; row++) {
1307 GLint col, col4;
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;
1314 }
1315 src += srcStride;
1316 dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
1317 }
1318 }
1319 else {
1320 /* must rescale image */
1321 GLuint *dst = (GLuint *) ((GLubyte *) dstImage
1322 + dstYoffset * dstRowStride) + dstXoffset;
1323 GLint row;
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);
1329 GLint col;
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;
1337 }
1338 dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
1339 }
1340 }
1341 }
1342 else {
1343 /* can't handle this source format/type combination */
1344 return GL_FALSE;
1345 }
1346 break;
1347
1348
1349 default:
1350 /* unexpected internal format! */
1351 return GL_FALSE;
1352 }
1353 return GL_TRUE;
1354 }
1355
1356
1357
1358
1359 /*
1360 * Used to convert 16-bit texels into GLubyte color components.
1361 */
1362 static GLubyte R5G6B5toRed[0xffff];
1363 static GLubyte R5G6B5toGreen[0xffff];
1364 static GLubyte R5G6B5toBlue[0xffff];
1365
1366 static GLubyte A4R4G4B4toRed[0xffff];
1367 static GLubyte A4R4G4B4toGreen[0xffff];
1368 static GLubyte A4R4G4B4toBlue[0xffff];
1369 static GLubyte A4R4G4B4toAlpha[0xffff];
1370
1371 static GLubyte A1R5G5B5toRed[0xffff];
1372 static GLubyte A1R5G5B5toGreen[0xffff];
1373 static GLubyte A1R5G5B5toBlue[0xffff];
1374 static GLubyte A1R5G5B5toAlpha[0xffff];
1375
1376 static void
1377 generate_lookup_tables(void)
1378 {
1379 GLint i;
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;
1384 r = r * 255 / 0xf8;
1385 g = g * 255 / 0xfc;
1386 b = b * 255 / 0xf8;
1387 R5G6B5toRed[i] = r;
1388 R5G6B5toGreen[i] = g;
1389 R5G6B5toBlue[i] = b;
1390 }
1391
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;
1397 r = r * 255 / 0xf;
1398 g = g * 255 / 0xf;
1399 b = b * 255 / 0xf;
1400 a = a * 255 / 0xf;
1401 A4R4G4B4toRed[i] = r;
1402 A4R4G4B4toGreen[i] = g;
1403 A4R4G4B4toBlue[i] = b;
1404 A4R4G4B4toAlpha[i] = a;
1405 }
1406
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;
1412 r = r * 255 / 0xf8;
1413 g = g * 255 / 0xf8;
1414 b = b * 255 / 0xf8;
1415 a = a * 255;
1416 A1R5G5B5toRed[i] = r;
1417 A1R5G5B5toGreen[i] = g;
1418 A1R5G5B5toBlue[i] = b;
1419 A1R5G5B5toAlpha[i] = a;
1420 }
1421 }
1422
1423
1424
1425 /*
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.
1429 *
1430 * Input:
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
1438 * Notes:
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.
1442 */
1443 void
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)
1449 {
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);
1455 ASSERT(dstImage);
1456 ASSERT(srcImage);
1457
1458 if (firstCall) {
1459 generate_lookup_tables();
1460 firstCall = GL_FALSE;
1461 }
1462
1463 switch (srcFormat) {
1464 case MESA_I8:
1465 case MESA_L8:
1466 case MESA_A8:
1467 case MESA_C8:
1468 #ifdef DEBUG
1469 if (srcFormat == MESA_I8) {
1470 ASSERT(dstFormat == GL_INTENSITY);
1471 }
1472 else if (srcFormat == MESA_L8) {
1473 ASSERT(dstFormat == GL_LUMINANCE);
1474 }
1475 else if (srcFormat == MESA_A8) {
1476 ASSERT(dstFormat == GL_ALPHA);
1477 }
1478 else if (srcFormat == MESA_C8) {
1479 ASSERT(dstFormat == GL_COLOR_INDEX);
1480 }
1481 #endif
1482 if (wScale == 1 && hScale == 1) {
1483 /* easy! */
1484 MEMCPY(dstImage, srcImage, dstWidth * dstHeight * sizeof(GLubyte));
1485 }
1486 else {
1487 /* rescale */
1488 const GLubyte *src8 = (const GLubyte *) srcImage;
1489 GLint row, col;
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];
1495 }
1496 }
1497 }
1498 break;
1499 case MESA_A8_L8:
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 */
1508 }
1509 }
1510 else {
1511 /* rescale */
1512 const GLushort *src16 = (const GLushort *) srcImage;
1513 GLint row, col;
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 */
1521 }
1522 }
1523 }
1524 break;
1525 case MESA_R5_G6_B5:
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];
1535 }
1536 }
1537 else {
1538 /* rescale */
1539 const GLushort *src16 = (const GLushort *) srcImage;
1540 GLint row, col;
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];
1549 }
1550 }
1551 }
1552 break;
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];
1564 }
1565 }
1566 else {
1567 /* rescale */
1568 const GLushort *src16 = (const GLushort *) srcImage;
1569 GLint row, col;
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];
1579 }
1580 }
1581 }
1582 break;
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];
1594 }
1595 }
1596 else {
1597 /* rescale */
1598 const GLushort *src16 = (const GLushort *) srcImage;
1599 GLint row, col;
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];
1609 }
1610 }
1611 }
1612 break;
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 */
1625 }
1626 }
1627 else {
1628 /* rescale */
1629 const GLuint *src = (const GLuint *) srcImage;
1630 GLint row, col;
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 */
1640 }
1641 }
1642 }
1643 break;
1644 default:
1645 gl_problem(NULL, "bad srcFormat in _mesa_uncovert_teximage()");
1646 }
1647 }
1648
1649
1650
1651 /*
1652 * Given an internal Mesa driver texture format, fill in the component
1653 * bit sizes in the given texture image struct.
1654 */
1655 void
1656 _mesa_set_teximage_component_sizes(MesaIntTexFormat mesaFormat,
1657 struct gl_texture_image *texImage)
1658 {
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 }
1672 };
1673 GLint i;
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];
1683 return;
1684 }
1685 }
1686 gl_problem(NULL, "bad format in _mesa_set_teximage_component_sizes");
1687 }