9628816795788c09c8064767b43874e2ff653e46
[mesa.git] / src / mesa / main / texutil.c
1 /* $Id: texutil.c,v 1.7 2000/09/13 22:07:20 brianp 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 "types.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 = _mesa_image_address(packing, srcImage,
131 srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
132 const GLint srcStride = _mesa_image_row_stride(packing,
133 srcWidth, srcFormat, srcType);
134 GLubyte *dst = (GLubyte *) dstImage;
135 GLint row;
136 for (row = 0; row < dstHeight; row++) {
137 MEMCPY(dst, src, dstWidth * sizeof(GLubyte));
138 dst += dstRowStride;
139 src += srcStride;
140 }
141 }
142 else {
143 /* must rescale image */
144 GLubyte *dst = (GLubyte *) dstImage;
145 GLint row;
146 for (row = 0; row < dstHeight; row++) {
147 GLint srcRow = row / hScale;
148 const GLubyte *src = _mesa_image_address(packing, srcImage,
149 srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
150 GLint col;
151 for (col = 0; col < dstWidth; col++) {
152 dst[col] = src[col / wScale];
153 }
154 dst += dstRowStride;
155 }
156 }
157 }
158 break;
159
160 case MESA_A8_L8:
161 if (srcType != GL_UNSIGNED_BYTE || srcFormat != GL_LUMINANCE_ALPHA) {
162 return GL_FALSE;
163 }
164 else {
165 /* store as 16-bit texels */
166 if (wScale == 1 && hScale == 1) {
167 const GLubyte *src = _mesa_image_address(packing, srcImage,
168 srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
169 const GLint srcStride = _mesa_image_row_stride(packing,
170 srcWidth, srcFormat, srcType);
171 GLushort *dst = (GLushort *) dstImage;
172 GLint row, col;
173 for (row = 0; row < dstHeight; row++) {
174 for (col = 0; col < dstWidth; col++) {
175 GLubyte luminance = src[col * 2 + 0];
176 GLubyte alpha = src[col * 2 + 1];
177 dst[col] = ((GLushort) alpha << 8) | luminance;
178 }
179 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
180 src += srcStride;
181 }
182 }
183 else {
184 /* must rescale */
185 GLushort *dst = (GLushort *) dstImage;
186 GLint row, col;
187 for (row = 0; row < dstHeight; row++) {
188 GLint srcRow = row / hScale;
189 const GLubyte *src = _mesa_image_address(packing, srcImage,
190 srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
191 const GLint srcStride = _mesa_image_row_stride(packing,
192 srcWidth, srcFormat, srcType);
193 for (col = 0; col < dstWidth; col++) {
194 GLint srcCol = col / wScale;
195 GLubyte luminance = src[srcCol * 2 + 0];
196 GLubyte alpha = src[srcCol * 2 + 1];
197 dst[col] = ((GLushort) alpha << 8) | luminance;
198 }
199 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
200 src += srcStride;
201 }
202 }
203 }
204 break;
205
206 case MESA_R5_G6_B5:
207 if (srcFormat == GL_RGB && srcType == GL_UNSIGNED_SHORT_5_6_5) {
208 /* special, optimized case */
209 if (wScale == 1 && hScale == 1) {
210 const GLubyte *src = _mesa_image_address(packing, srcImage,
211 srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
212 const GLint srcStride = _mesa_image_row_stride(packing,
213 srcWidth, srcFormat, srcType);
214 GLushort *dst = (GLushort *) dstImage;
215 GLint row;
216 for (row = 0; row < dstHeight; row++) {
217 MEMCPY(dst, src, dstWidth * sizeof(GLushort));
218 src += srcStride;
219 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
220 }
221 }
222 else {
223 /* must rescale image */
224 GLushort *dst = (GLushort *) dstImage;
225 GLint row;
226 for (row = 0; row < dstHeight; row++) {
227 GLint srcRow = row / hScale;
228 const GLushort *src = _mesa_image_address(packing, srcImage,
229 srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
230 GLint col;
231 for (col = 0; col < dstWidth; col++) {
232 dst[col] = src[col / wScale];
233 }
234 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
235 }
236 }
237 }
238 else if (srcFormat == GL_RGB && srcType == GL_UNSIGNED_BYTE) {
239 /* general case */
240 if (wScale == 1 && hScale == 1) {
241 const GLubyte *src = _mesa_image_address(packing, srcImage,
242 srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
243 const GLint srcStride = _mesa_image_row_stride(packing,
244 srcWidth, srcFormat, srcType);
245 #ifdef DO_32BIT_STORES
246 GLuint *dst = (GLuint *) dstImage;
247 GLint row;
248 for (row = 0; row < dstHeight; row++) {
249 GLint col, col3;
250 GLint halfDstWidth = dstWidth >> 1;
251 for (col = col3 = 0; col < halfDstWidth; col++, col3 += 6) {
252 GLubyte r0 = src[col3 + 0];
253 GLubyte g0 = src[col3 + 1];
254 GLubyte b0 = src[col3 + 2];
255 GLubyte r1 = src[col3 + 3];
256 GLubyte g1 = src[col3 + 4];
257 GLubyte b1 = src[col3 + 5];
258 GLuint d0 = ((r0 & 0xf8) << 8)
259 | ((g0 & 0xfc) << 3)
260 | ((b0 & 0xf8) >> 3);
261 GLuint d1 = ((r1 & 0xf8) << 8)
262 | ((g1 & 0xfc) << 3)
263 | ((b1 & 0xf8) >> 3);
264 dst[col] = (d1 << 16) | d0;
265 }
266 src += srcStride;
267 dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
268 }
269 #else /* 16-bit stores */
270 GLushort *dst = (GLushort *) dstImage;
271 GLint row;
272 for (row = 0; row < dstHeight; row++) {
273 GLint col, col3;
274 for (col = col3 = 0; col < dstWidth; col++, col3 += 3) {
275 GLubyte r = src[col3 + 0];
276 GLubyte g = src[col3 + 1];
277 GLubyte b = src[col3 + 2];
278 dst[col] = ((r & 0xf8) << 8)
279 | ((g & 0xfc) << 3)
280 | ((b & 0xf8) >> 3);
281 }
282 src += srcStride;
283 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
284 }
285 #endif
286 }
287 else {
288 /* must rescale image */
289 GLushort *dst = (GLushort *) dstImage;
290 GLint row;
291 for (row = 0; row < dstHeight; row++) {
292 GLint srcRow = row / hScale;
293 const GLubyte *src = _mesa_image_address(packing, srcImage,
294 srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
295 GLint col;
296 for (col = 0; col < dstWidth; col++) {
297 GLint col3 = (col / wScale) * 3;
298 GLubyte r = src[col3 + 0];
299 GLubyte g = src[col3 + 1];
300 GLubyte b = src[col3 + 2];
301 dst[col] = ((r & 0xf8) << 8)
302 | ((g & 0xfc) << 3)
303 | ((b & 0xf8) >> 3);
304 }
305 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
306 }
307 }
308 }
309 else if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) {
310 /* general case (used by Quake3) */
311 if (wScale == 1 && hScale == 1) {
312 const GLubyte *src = _mesa_image_address(packing, srcImage,
313 srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
314 const GLint srcStride = _mesa_image_row_stride(packing,
315 srcWidth, srcFormat, srcType);
316 #ifdef DO_32BIT_STORES
317 GLuint *dst = dstImage;
318 GLint row;
319 for (row = 0; row < dstHeight; row++) {
320 GLint col, col4;
321 GLint halfDstWidth = dstWidth >> 1;
322 for (col = col4 = 0; col < halfDstWidth; col++, col4 += 8) {
323 GLubyte r0 = src[col4 + 0];
324 GLubyte g0 = src[col4 + 1];
325 GLubyte b0 = src[col4 + 2];
326 GLubyte r1 = src[col4 + 4];
327 GLubyte g1 = src[col4 + 5];
328 GLubyte b1 = src[col4 + 6];
329 GLuint d0 = ((r0 & 0xf8) << 8)
330 | ((g0 & 0xfc) << 3)
331 | ((b0 & 0xf8) >> 3);
332 GLuint d1 = ((r1 & 0xf8) << 8)
333 | ((g1 & 0xfc) << 3)
334 | ((b1 & 0xf8) >> 3);
335 dst[col] = (d1 << 16) | d0;
336 }
337 src += srcStride;
338 dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
339 }
340 #else /* 16-bit stores */
341 GLushort *dst = (GLushort *) dstImage;
342 GLint row;
343 for (row = 0; row < dstHeight; row++) {
344 GLint col, col4;
345 for (col = col4 = 0; col < dstWidth; col++, col4 += 4) {
346 GLubyte r = src[col4 + 0];
347 GLubyte g = src[col4 + 1];
348 GLubyte b = src[col4 + 2];
349 dst[col] = ((r & 0xf8) << 8)
350 | ((g & 0xfc) << 3)
351 | ((b & 0xf8) >> 3);
352 }
353 src += srcStride;
354 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
355 }
356 #endif
357 }
358 else {
359 /* must rescale image */
360 GLushort *dst = (GLushort *) dstImage;
361 GLint row;
362 for (row = 0; row < dstHeight; row++) {
363 GLint srcRow = row / hScale;
364 const GLubyte *src = _mesa_image_address(packing, srcImage,
365 srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
366 GLint col;
367 for (col = 0; col < dstWidth; col++) {
368 GLint col4 = (col / wScale) * 4;
369 GLubyte r = src[col4 + 0];
370 GLubyte g = src[col4 + 1];
371 GLubyte b = src[col4 + 2];
372 dst[col] = ((r & 0xf8) << 8)
373 | ((g & 0xfc) << 3)
374 | ((b & 0xf8) >> 3);
375 }
376 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
377 }
378 }
379 }
380 else {
381 /* can't handle this srcFormat/srcType combination */
382 return GL_FALSE;
383 }
384 break;
385
386 case MESA_A4_R4_G4_B4:
387 /* store as 16-bit texels (GR_TEXFMT_ARGB_4444) */
388 if (srcFormat == GL_BGRA && srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV){
389 /* special, optimized case */
390 if (wScale == 1 && hScale == 1) {
391 const GLubyte *src = _mesa_image_address(packing, srcImage,
392 srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
393 const GLint srcStride = _mesa_image_row_stride(packing,
394 srcWidth, srcFormat, srcType);
395 GLushort *dst = (GLushort *) dstImage;
396 GLint row;
397 for (row = 0; row < dstHeight; row++) {
398 MEMCPY(dst, src, dstWidth * sizeof(GLushort));
399 src += srcStride;
400 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
401 }
402 }
403 else {
404 /* must rescale image */
405 GLushort *dst = (GLushort *) dstImage;
406 GLint row;
407 for (row = 0; row < dstHeight; row++) {
408 GLint srcRow = row / hScale;
409 const GLushort *src = _mesa_image_address(packing, srcImage,
410 srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
411 GLint col;
412 for (col = 0; col < dstWidth; col++) {
413 dst[col] = src[col / wScale];
414 }
415 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
416 }
417 }
418 }
419 else if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) {
420 /* general case */
421 if (wScale == 1 && hScale == 1) {
422 const GLubyte *src = _mesa_image_address(packing, srcImage,
423 srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
424 const GLint srcStride = _mesa_image_row_stride(packing,
425 srcWidth, srcFormat, srcType);
426 #ifdef DO_32BIT_STORES
427 GLuint *dst = dstImage;
428 GLint row;
429 for (row = 0; row < dstHeight; row++) {
430 GLint col, col4;
431 GLint halfDstWidth = dstWidth >> 1;
432 for (col = col4 = 0; col < halfDstWidth; col++, col4 += 8) {
433 GLubyte r0 = src[col4 + 0];
434 GLubyte g0 = src[col4 + 1];
435 GLubyte b0 = src[col4 + 2];
436 GLubyte a0 = src[col4 + 3];
437 GLubyte r1 = src[col4 + 4];
438 GLubyte g1 = src[col4 + 5];
439 GLubyte b1 = src[col4 + 6];
440 GLubyte a1 = src[col4 + 7];
441 GLuint d0 = ((a0 & 0xf0) << 8)
442 | ((r0 & 0xf0) << 4)
443 | ((g0 & 0xf0) )
444 | ((b0 & 0xf0) >> 4);
445 GLuint d1 = ((a1 & 0xf0) << 8)
446 | ((r1 & 0xf0) << 4)
447 | ((g1 & 0xf0) )
448 | ((b1 & 0xf0) >> 4);
449 dst[col] = (d1 << 16) | d0;
450 }
451 src += srcStride;
452 dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
453 }
454 #else /* 16-bit stores */
455 GLushort *dst = (GLushort *) dstImage;
456 GLint row;
457 for (row = 0; row < dstHeight; row++) {
458 GLint col, col4;
459 for (col = col4 = 0; col < dstWidth; col++, col4 += 4) {
460 GLubyte r = src[col4 + 0];
461 GLubyte g = src[col4 + 1];
462 GLubyte b = src[col4 + 2];
463 GLubyte a = src[col4 + 3];
464 dst[col] = ((a & 0xf0) << 8)
465 | ((r & 0xf0) << 4)
466 | ((g & 0xf0) )
467 | ((b & 0xf0) >> 4);
468 }
469 src += srcStride;
470 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
471 }
472 #endif
473 }
474 else {
475 /* must rescale image */
476 GLushort *dst = (GLushort *) dstImage;
477 GLint row;
478 for (row = 0; row < dstHeight; row++) {
479 GLint srcRow = row / hScale;
480 const GLubyte *src = _mesa_image_address(packing, srcImage,
481 srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
482 GLint col;
483 for (col = 0; col < dstWidth; col++) {
484 GLint col4 = (col / wScale) * 4;
485 GLubyte r = src[col4 + 0];
486 GLubyte g = src[col4 + 1];
487 GLubyte b = src[col4 + 2];
488 GLubyte a = src[col4 + 3];
489 dst[col] = ((a & 0xf0) << 8)
490 | ((r & 0xf0) << 4)
491 | ((g & 0xf0) )
492 | ((b & 0xf0) >> 4);
493 }
494 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
495 }
496 }
497 }
498 else {
499 /* can't handle this format/srcType combination */
500 return GL_FALSE;
501 }
502 break;
503
504 case MESA_A1_R5_G5_B5:
505 /* store as 16-bit texels (GR_TEXFMT_ARGB_1555) */
506 if (srcFormat == GL_BGRA && srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV){
507 /* special, optimized case */
508 if (wScale == 1 && hScale == 1) {
509 const GLubyte *src = _mesa_image_address(packing, srcImage,
510 srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
511 const GLint srcStride = _mesa_image_row_stride(packing,
512 srcWidth, srcFormat, srcType);
513 GLushort *dst = (GLushort *) dstImage;
514 GLint row;
515 for (row = 0; row < dstHeight; row++) {
516 MEMCPY(dst, src, dstWidth * sizeof(GLushort));
517 src += srcStride;
518 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
519 }
520 }
521 else {
522 /* must rescale image */
523 GLushort *dst = (GLushort *) dstImage;
524 GLint row;
525 for (row = 0; row < dstHeight; row++) {
526 GLint srcRow = row / hScale;
527 const GLushort *src = _mesa_image_address(packing, srcImage,
528 srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
529 GLint col;
530 for (col = 0; col < dstWidth; col++) {
531 dst[col] = src[col / wScale];
532 }
533 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
534 }
535 }
536 }
537 else if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) {
538 /* general case */
539 if (wScale == 1 && hScale == 1) {
540 const GLubyte *src = _mesa_image_address(packing, srcImage,
541 srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
542 const GLint srcStride = _mesa_image_row_stride(packing,
543 srcWidth, srcFormat, srcType);
544 GLushort *dst = (GLushort *) dstImage;
545 GLint row;
546 for (row = 0; row < dstHeight; row++) {
547 GLint col, col4;
548 for (col = col4 = 0; col < dstWidth; col++, col4 += 4) {
549 GLubyte r = src[col4 + 0];
550 GLubyte g = src[col4 + 1];
551 GLubyte b = src[col4 + 2];
552 GLubyte a = src[col4 + 3];
553 dst[col] = ((a & 0x80) << 8)
554 | ((r & 0xf8) << 7)
555 | ((g & 0xf8) << 2)
556 | ((b & 0xf8) >> 3);
557 }
558 src += srcStride;
559 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
560 }
561 }
562 else {
563 /* must rescale image */
564 GLushort *dst = (GLushort *) dstImage;
565 GLint row;
566 for (row = 0; row < dstHeight; row++) {
567 GLint srcRow = row / hScale;
568 const GLubyte *src = _mesa_image_address(packing, srcImage,
569 srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
570 GLint col;
571 for (col = 0; col < dstWidth; col++) {
572 GLint col4 = (col / wScale) * 4;
573 GLubyte r = src[col4 + 0];
574 GLubyte g = src[col4 + 1];
575 GLubyte b = src[col4 + 2];
576 GLubyte a = src[col4 + 3];
577 dst[col] = ((a & 0x80) << 8)
578 | ((r & 0xf8) << 7)
579 | ((g & 0xf8) << 2)
580 | ((b & 0xf8) >> 3);
581 }
582 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
583 }
584 }
585 }
586 else {
587 /* can't handle this source format/type combination */
588 return GL_FALSE;
589 }
590 break;
591
592 case MESA_A8_R8_G8_B8:
593 case MESA_FF_R8_G8_B8:
594 /* 32-bit texels */
595 if (srcFormat == GL_BGRA && srcType == GL_UNSIGNED_INT_8_8_8_8_REV){
596 /* special, optimized case */
597 if (wScale == 1 && hScale == 1) {
598 const GLubyte *src = _mesa_image_address(packing, srcImage,
599 srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
600 const GLint srcStride = _mesa_image_row_stride(packing,
601 srcWidth, srcFormat, srcType);
602 GLuint *dst = dstImage;
603 GLint row;
604 for (row = 0; row < dstHeight; row++) {
605 MEMCPY(dst, src, dstWidth * sizeof(GLuint));
606 src += srcStride;
607 dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
608 }
609 }
610 else {
611 /* must rescale image */
612 GLuint *dst = dstImage;
613 GLint row;
614 for (row = 0; row < dstHeight; row++) {
615 GLint srcRow = row / hScale;
616 const GLuint *src = _mesa_image_address(packing, srcImage,
617 srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
618 GLint col;
619 for (col = 0; col < dstWidth; col++) {
620 dst[col] = src[col / wScale];
621 }
622 dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
623 }
624 }
625 }
626 else if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) {
627 /* general case */
628 if (wScale == 1 && hScale == 1) {
629 const GLubyte *src = _mesa_image_address(packing, srcImage,
630 srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
631 const GLint srcStride = _mesa_image_row_stride(packing,
632 srcWidth, srcFormat, srcType);
633 GLuint *dst = dstImage;
634 GLint row;
635 for (row = 0; row < dstHeight; row++) {
636 GLint col, col4;
637 for (col = col4 = 0; col < dstWidth; col++, col4 += 4) {
638 GLubyte r = src[col4 + 0];
639 GLubyte g = src[col4 + 1];
640 GLubyte b = src[col4 + 2];
641 GLubyte a = src[col4 + 3];
642 dst[col] = (a << 24) | (r << 16) | (g << 8) | b;
643 }
644 src += srcStride;
645 dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
646 }
647 }
648 else {
649 /* must rescale image */
650 GLuint *dst = dstImage;
651 GLint row;
652 for (row = 0; row < dstHeight; row++) {
653 GLint srcRow = row / hScale;
654 const GLubyte *src = _mesa_image_address(packing, srcImage,
655 srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
656 GLint col;
657 for (col = 0; col < dstWidth; col++) {
658 GLint col4 = (col / wScale) * 4;
659 GLubyte r = src[col4 + 0];
660 GLubyte g = src[col4 + 1];
661 GLubyte b = src[col4 + 2];
662 GLubyte a = src[col4 + 3];
663 dst[col] = (a << 24) | (r << 16) | (g << 8) | b;
664 }
665 dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
666 }
667 }
668 }
669 else if (srcFormat == GL_RGB && srcType == GL_UNSIGNED_BYTE) {
670 /* general case */
671 if (wScale == 1 && hScale == 1) {
672 const GLubyte *src = _mesa_image_address(packing, srcImage,
673 srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
674 const GLint srcStride = _mesa_image_row_stride(packing,
675 srcWidth, srcFormat, srcType);
676 GLuint *dst = dstImage;
677 GLint row;
678 for (row = 0; row < dstHeight; row++) {
679 GLint col, col3;
680 for (col = col3 = 0; col < dstWidth; col++, col3 += 3) {
681 GLubyte r = src[col3 + 0];
682 GLubyte g = src[col3 + 1];
683 GLubyte b = src[col3 + 2];
684 GLubyte a = 255;
685 dst[col] = (a << 24) | (r << 16) | (g << 8) | b;
686 }
687 src += srcStride;
688 dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
689 }
690 }
691 else {
692 /* must rescale image */
693 GLuint *dst = dstImage;
694 GLint row;
695 for (row = 0; row < dstHeight; row++) {
696 GLint srcRow = row / hScale;
697 const GLubyte *src = _mesa_image_address(packing, srcImage,
698 srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
699 GLint col;
700 for (col = 0; col < dstWidth; col++) {
701 GLint col3 = (col / wScale) * 3;
702 GLubyte r = src[col3 + 0];
703 GLubyte g = src[col3 + 1];
704 GLubyte b = src[col3 + 2];
705 GLubyte a = 255;
706 dst[col] = (a << 24) | (r << 16) | (g << 8) | b;
707 }
708 dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
709 }
710 }
711 }
712 else {
713 /* can't handle this source format/type combination */
714 return GL_FALSE;
715 }
716 if (dstFormat == MESA_FF_R8_G8_B8) {
717 /* set alpha bytes to 0xff */
718 GLuint i;
719 GLubyte *dst = (GLubyte *) dstImage;
720 for (i = 0; i < dstWidth * dstHeight; i++) {
721 dst[i * 4 + 3] = 0xff;
722 }
723 }
724 break;
725
726 default:
727 /* unexpected internal format! */
728 return GL_FALSE;
729 }
730 return GL_TRUE;
731 }
732
733
734
735 /*
736 * Replace a subregion of a texture image with new data.
737 * Input:
738 * dstFormat - destination image format
739 * dstXoffset, dstYoffset - destination for new subregion
740 * dstWidth, dstHeight - total size of dest image
741 * dstImage - pointer to dest image
742 * dstRowStride - bytes to jump between image rows
743 * width, height - size of region to copy/replace
744 * srcWidth, srcHeight - size of the corresponding gl_texture_image
745 * srcFormat, srcType - source image format and datatype
746 * srcImage - source image
747 * packing - source image packing information.
748 * Return: GL_TRUE or GL_FALSE for success, failure
749 *
750 * Notes:
751 * Like _mesa_convert_teximage(), we can do power-of-two image scaling
752 * to accomodate hardware with texture image aspect ratio constraints.
753 * dstWidth / srcWidth is used to compute the horizontal scaling factor and
754 * dstHeight / srcHeight is used to compute the vertical scaling factor.
755 */
756 GLboolean
757 _mesa_convert_texsubimage(MesaIntTexFormat dstFormat,
758 GLint dstXoffset, GLint dstYoffset,
759 GLint dstWidth, GLint dstHeight, GLvoid *dstImage,
760 GLint dstRowStride,
761 GLint width, GLint height,
762 GLint srcWidth, GLint srcHeight,
763 GLenum srcFormat, GLenum srcType,
764 const GLvoid *srcImage,
765 const struct gl_pixelstore_attrib *packing)
766 {
767 const GLint wScale = dstWidth / srcWidth; /* must be power of two */
768 const GLint hScale = dstHeight / srcHeight; /* must be power of two */
769 ASSERT(dstWidth >= srcWidth);
770 ASSERT(dstHeight >= srcHeight);
771 ASSERT(dstImage);
772 ASSERT(srcImage);
773 ASSERT(packing);
774
775 width *= wScale;
776 height *= hScale;
777 dstXoffset *= wScale;
778 dstYoffset *= hScale;
779
780 /* XXX hscale != 1 and wscale != 1 not tested!!!! */
781
782 switch (dstFormat) {
783 case MESA_I8:
784 case MESA_L8:
785 case MESA_A8:
786 case MESA_C8:
787 if (srcType != GL_UNSIGNED_BYTE ||
788 ((srcFormat != GL_INTENSITY) &&
789 (srcFormat != GL_LUMINANCE) &&
790 (srcFormat != GL_ALPHA) &&
791 (srcFormat != GL_COLOR_INDEX))) {
792 /* bad internal format / srcFormat combination */
793 return GL_FALSE;
794 }
795 else {
796 /* store as 8-bit texels */
797 if (wScale == 1 && hScale == 1) {
798 /* no scaling needed - fast case */
799 const GLubyte *src = _mesa_image_address(packing, srcImage,
800 srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
801 const GLint srcStride = _mesa_image_row_stride(packing,
802 width, srcFormat, srcType);
803 GLubyte *dst = (GLubyte *) dstImage
804 + dstYoffset * dstRowStride + dstXoffset;
805 GLint row;
806 for (row = 0; row < height; row++) {
807 MEMCPY(dst, src, width * sizeof(GLubyte));
808 dst += dstRowStride;
809 src += srcStride;
810 }
811 }
812 else {
813 /* must rescale image */
814 GLubyte *dst = (GLubyte *) dstImage
815 + dstYoffset * dstRowStride + dstXoffset;
816 GLint row;
817 for (row = 0; row < height; row++) {
818 GLint srcRow = row / hScale;
819 const GLubyte *src = _mesa_image_address(packing, srcImage,
820 srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
821 GLint col;
822 for (col = 0; col < width; col++) {
823 dst[col] = src[col / wScale];
824 }
825 dst += dstRowStride;
826 }
827 }
828 }
829 break;
830
831 case MESA_A8_L8:
832 if (srcType != GL_UNSIGNED_BYTE || srcFormat != GL_LUMINANCE_ALPHA) {
833 return GL_FALSE;
834 }
835 else {
836 /* store as 16-bit texels */
837 if (wScale == 1 && hScale == 1) {
838 const GLubyte *src = _mesa_image_address(packing, srcImage,
839 srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
840 const GLint srcStride = _mesa_image_row_stride(packing,
841 width, srcFormat, srcType);
842 GLushort *dst = (GLushort *) ((GLubyte *) dstImage
843 + dstYoffset * dstRowStride) + dstXoffset;
844 GLint row, col;
845 for (row = 0; row < height; row++) {
846 for (col = 0; col < width; col++) {
847 GLubyte luminance = src[col * 2 + 0];
848 GLubyte alpha = src[col * 2 + 1];
849 dst[col] = ((GLushort) alpha << 8) | luminance;
850 }
851 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
852 src += srcStride;
853 }
854 }
855 else {
856 /* must rescale */
857 GLushort *dst = (GLushort *) ((GLubyte *) dstImage
858 + dstYoffset * dstRowStride) + dstXoffset;
859 GLint row, col;
860 for (row = 0; row < height; row++) {
861 GLint srcRow = row / hScale;
862 const GLubyte *src = _mesa_image_address(packing, srcImage,
863 srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
864 const GLint srcStride = _mesa_image_row_stride(packing,
865 width, srcFormat, srcType);
866 for (col = 0; col < width; col++) {
867 GLint srcCol = col / wScale;
868 GLubyte luminance = src[srcCol * 2 + 0];
869 GLubyte alpha = src[srcCol * 2 + 1];
870 dst[col] = ((GLushort) alpha << 8) | luminance;
871 }
872 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
873 src += srcStride;
874 }
875 }
876 }
877 break;
878
879 case MESA_R5_G6_B5:
880 if (srcFormat == GL_RGB && srcType == GL_UNSIGNED_SHORT_5_6_5) {
881 /* special, optimized case */
882 if (wScale == 1 && hScale == 1) {
883 const GLubyte *src = _mesa_image_address(packing, srcImage,
884 srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
885 const GLint srcStride = _mesa_image_row_stride(packing,
886 width, srcFormat, srcType);
887 GLushort *dst = (GLushort *) ((GLubyte *) dstImage
888 + dstYoffset * dstRowStride) + dstXoffset;
889 GLint row;
890 for (row = 0; row < height; row++) {
891 MEMCPY(dst, src, width * sizeof(GLushort));
892 src += srcStride;
893 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
894 }
895 }
896 else {
897 /* must rescale image */
898 GLushort *dst = (GLushort *) ((GLubyte *) dstImage
899 + dstYoffset * dstRowStride) + dstXoffset;
900 GLint row;
901 for (row = 0; row < height; row++) {
902 GLint srcRow = row / hScale;
903 const GLushort *src = _mesa_image_address(packing, srcImage,
904 srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
905 GLint col;
906 for (col = 0; col < width; col++) {
907 dst[col] = src[col / wScale];
908 }
909 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
910 }
911 }
912 }
913 else if (srcFormat == GL_RGB && srcType == GL_UNSIGNED_BYTE) {
914 /* general case */
915 if (wScale == 1 && hScale == 1) {
916 const GLubyte *src = _mesa_image_address(packing, srcImage,
917 srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
918 const GLint srcStride = _mesa_image_row_stride(packing,
919 width, srcFormat, srcType);
920 GLushort *dst = (GLushort *) ((GLubyte *) dstImage
921 + dstYoffset * dstRowStride) + dstXoffset;
922 GLint row;
923 for (row = 0; row < height; row++) {
924 GLint col, col3;
925 for (col = col3 = 0; col < width; col++, col3 += 3) {
926 GLubyte r = src[col3 + 0];
927 GLubyte g = src[col3 + 1];
928 GLubyte b = src[col3 + 2];
929 dst[col] = ((r & 0xf8) << 8)
930 | ((g & 0xfc) << 3)
931 | ((b & 0xf8) >> 3);
932 }
933 src += srcStride;
934 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
935 }
936 }
937 else {
938 /* must rescale image */
939 GLushort *dst = (GLushort *) ((GLubyte *) dstImage
940 + dstYoffset * dstRowStride) + dstXoffset;
941 GLint row;
942 for (row = 0; row < height; row++) {
943 GLint srcRow = row / hScale;
944 const GLubyte *src = _mesa_image_address(packing, srcImage,
945 srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
946 GLint col;
947 for (col = 0; col < width; col++) {
948 GLint col3 = (col / wScale) * 3;
949 GLubyte r = src[col3 + 0];
950 GLubyte g = src[col3 + 1];
951 GLubyte b = src[col3 + 2];
952 dst[col] = ((r & 0xf8) << 8)
953 | ((g & 0xfc) << 3)
954 | ((b & 0xf8) >> 3);
955 }
956 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
957 }
958 }
959 }
960 else if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) {
961 /* general case (used by Quake3) */
962 if (wScale == 1 && hScale == 1) {
963 const GLubyte *src = _mesa_image_address(packing, srcImage,
964 srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
965 const GLint srcStride = _mesa_image_row_stride(packing,
966 width, srcFormat, srcType);
967 GLushort *dst = (GLushort *) ((GLubyte *) dstImage
968 + dstYoffset * dstRowStride) + dstXoffset;
969 GLint row;
970 for (row = 0; row < height; row++) {
971 GLint col, col4;
972 for (col = col4 = 0; col < width; col++, col4 += 4) {
973 GLubyte r = src[col4 + 0];
974 GLubyte g = src[col4 + 1];
975 GLubyte b = src[col4 + 2];
976 dst[col] = ((r & 0xf8) << 8)
977 | ((g & 0xfc) << 3)
978 | ((b & 0xf8) >> 3);
979 }
980 src += srcStride;
981 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
982 }
983 }
984 else {
985 /* must rescale image */
986 GLushort *dst = (GLushort *) ((GLubyte *) dstImage
987 + dstYoffset * dstRowStride) + dstXoffset;
988 GLint row;
989 for (row = 0; row < height; row++) {
990 GLint srcRow = row / hScale;
991 const GLubyte *src = _mesa_image_address(packing, srcImage,
992 srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
993 GLint col;
994 for (col = 0; col < width; col++) {
995 GLint col4 = (col / wScale) * 4;
996 GLubyte r = src[col4 + 0];
997 GLubyte g = src[col4 + 1];
998 GLubyte b = src[col4 + 2];
999 dst[col] = ((r & 0xf8) << 8)
1000 | ((g & 0xfc) << 3)
1001 | ((b & 0xf8) >> 3);
1002 }
1003 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
1004 }
1005 }
1006 }
1007 else {
1008 /* can't handle this srcFormat/srcType combination */
1009 return GL_FALSE;
1010 }
1011 break;
1012
1013 case MESA_A4_R4_G4_B4:
1014 /* store as 16-bit texels (GR_TEXFMT_ARGB_4444) */
1015 if (srcFormat == GL_BGRA && srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV){
1016 /* special, optimized case */
1017 if (wScale == 1 && hScale == 1) {
1018 const GLubyte *src = _mesa_image_address(packing, srcImage,
1019 srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
1020 const GLint srcStride = _mesa_image_row_stride(packing,
1021 width, srcFormat, srcType);
1022 GLushort *dst = (GLushort *) ((GLubyte *) dstImage
1023 + dstYoffset * dstRowStride) + dstXoffset;
1024 GLint row;
1025 for (row = 0; row < height; row++) {
1026 MEMCPY(dst, src, width * sizeof(GLushort));
1027 src += srcStride;
1028 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
1029 }
1030 }
1031 else {
1032 /* must rescale image */
1033 GLushort *dst = (GLushort *) ((GLubyte *) dstImage
1034 + dstYoffset * dstRowStride) + dstXoffset;
1035 GLint row;
1036 for (row = 0; row < height; row++) {
1037 GLint srcRow = row / hScale;
1038 const GLushort *src = _mesa_image_address(packing, srcImage,
1039 srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
1040 GLint col;
1041 for (col = 0; col < width; col++) {
1042 dst[col] = src[col / wScale];
1043 }
1044 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
1045 }
1046 }
1047 }
1048 else if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) {
1049 /* general case */
1050 if (wScale == 1 && hScale == 1) {
1051 const GLubyte *src = _mesa_image_address(packing, srcImage,
1052 srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
1053 const GLint srcStride = _mesa_image_row_stride(packing,
1054 width, srcFormat, srcType);
1055 GLushort *dst = (GLushort *) ((GLubyte *) dstImage
1056 + dstYoffset * dstRowStride) + dstXoffset;
1057 GLint row;
1058 for (row = 0; row < height; row++) {
1059 GLint col, col4;
1060 for (col = col4 = 0; col < width; col++, col4 += 4) {
1061 GLubyte r = src[col4 + 0];
1062 GLubyte g = src[col4 + 1];
1063 GLubyte b = src[col4 + 2];
1064 GLubyte a = src[col4 + 3];
1065 dst[col] = ((a & 0xf0) << 8)
1066 | ((r & 0xf0) << 4)
1067 | ((g & 0xf0) )
1068 | ((b & 0xf0) >> 4);
1069 }
1070 src += srcStride;
1071 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
1072 }
1073 }
1074 else {
1075 /* must rescale image */
1076 GLushort *dst = (GLushort *) ((GLubyte *) dstImage
1077 + dstYoffset * dstRowStride) + dstXoffset;
1078 GLint row;
1079 for (row = 0; row < height; row++) {
1080 GLint srcRow = row / hScale;
1081 const GLubyte *src = _mesa_image_address(packing, srcImage,
1082 srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
1083 GLint col;
1084 for (col = 0; col < width; col++) {
1085 GLint col4 = (col / wScale) * 4;
1086 GLubyte r = src[col4 + 0];
1087 GLubyte g = src[col4 + 1];
1088 GLubyte b = src[col4 + 2];
1089 GLubyte a = src[col4 + 3];
1090 dst[col] = ((a & 0xf0) << 8)
1091 | ((r & 0xf0) << 4)
1092 | ((g & 0xf0) )
1093 | ((b & 0xf0) >> 4);
1094 }
1095 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
1096 }
1097 }
1098 }
1099 else {
1100 /* can't handle this format/srcType combination */
1101 return GL_FALSE;
1102 }
1103 break;
1104
1105 case MESA_A1_R5_G5_B5:
1106 /* store as 16-bit texels (GR_TEXFMT_ARGB_1555) */
1107 if (srcFormat == GL_BGRA && srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV){
1108 /* special, optimized case */
1109 if (wScale == 1 && hScale == 1) {
1110 const GLubyte *src = _mesa_image_address(packing, srcImage,
1111 srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
1112 const GLint srcStride = _mesa_image_row_stride(packing,
1113 width, srcFormat, srcType);
1114 GLushort *dst = (GLushort *) ((GLubyte *) dstImage
1115 + dstYoffset * dstRowStride) + dstXoffset;
1116 GLint row;
1117 for (row = 0; row < height; row++) {
1118 MEMCPY(dst, src, width * sizeof(GLushort));
1119 src += srcStride;
1120 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
1121 }
1122 }
1123 else {
1124 /* must rescale image */
1125 GLushort *dst = (GLushort *) ((GLubyte *) dstImage
1126 + dstYoffset * dstRowStride) + dstXoffset;
1127 GLint row;
1128 for (row = 0; row < height; row++) {
1129 GLint srcRow = row / hScale;
1130 const GLushort *src = _mesa_image_address(packing, srcImage,
1131 srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
1132 GLint col;
1133 for (col = 0; col < width; col++) {
1134 dst[col] = src[col / wScale];
1135 }
1136 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
1137 }
1138 }
1139 }
1140 else if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) {
1141 /* general case */
1142 if (wScale == 1 && hScale == 1) {
1143 const GLubyte *src = _mesa_image_address(packing, srcImage,
1144 srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
1145 const GLint srcStride = _mesa_image_row_stride(packing,
1146 width, srcFormat, srcType);
1147 GLushort *dst = (GLushort *) ((GLubyte *) dstImage
1148 + dstYoffset * dstRowStride) + dstXoffset;
1149 GLint row;
1150 for (row = 0; row < height; row++) {
1151 GLint col, col4;
1152 for (col = col4 = 0; col < width; col++, col4 += 4) {
1153 GLubyte r = src[col4 + 0];
1154 GLubyte g = src[col4 + 1];
1155 GLubyte b = src[col4 + 2];
1156 GLubyte a = src[col4 + 3];
1157 dst[col] = ((a & 0x80) << 8)
1158 | ((r & 0xf8) << 7)
1159 | ((g & 0xf8) << 2)
1160 | ((b & 0xf8) >> 3);
1161 }
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 GLubyte *src = _mesa_image_address(packing, srcImage,
1174 srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
1175 GLint col;
1176 for (col = 0; col < width; col++) {
1177 GLint col4 = (col / wScale) * 4;
1178 GLubyte r = src[col4 + 0];
1179 GLubyte g = src[col4 + 1];
1180 GLubyte b = src[col4 + 2];
1181 GLubyte a = src[col4 + 3];
1182 dst[col] = ((a & 0x80) << 8)
1183 | ((r & 0xf8) << 7)
1184 | ((g & 0xf8) << 2)
1185 | ((b & 0xf8) >> 3);
1186 }
1187 dst = (GLushort *) ((GLubyte *) dst + dstRowStride);
1188 }
1189 }
1190 }
1191 else {
1192 /* can't handle this source format/type combination */
1193 return GL_FALSE;
1194 }
1195 break;
1196
1197 case MESA_A8_R8_G8_B8:
1198 case MESA_FF_R8_G8_B8:
1199 /* 32-bit texels */
1200 if (srcFormat == GL_BGRA && srcType == GL_UNSIGNED_INT_8_8_8_8_REV){
1201 /* special, optimized case */
1202 if (wScale == 1 && hScale == 1) {
1203 const GLubyte *src = _mesa_image_address(packing, srcImage,
1204 srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
1205 const GLint srcStride = _mesa_image_row_stride(packing,
1206 width, srcFormat, srcType);
1207 GLuint *dst = (GLuint *) ((GLubyte *) dstImage
1208 + dstYoffset * dstRowStride) + dstXoffset;
1209 GLint row;
1210 for (row = 0; row < height; row++) {
1211 MEMCPY(dst, src, width * sizeof(GLuint));
1212 src += srcStride;
1213 dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
1214 }
1215 }
1216 else {
1217 /* must rescale image */
1218 GLuint *dst = (GLuint *) ((GLubyte *) dstImage
1219 + dstYoffset * dstRowStride) + dstXoffset;
1220 GLint row;
1221 for (row = 0; row < height; row++) {
1222 GLint srcRow = row / hScale;
1223 const GLuint *src = _mesa_image_address(packing, srcImage,
1224 srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
1225 GLint col;
1226 for (col = 0; col < width; col++) {
1227 dst[col] = src[col / wScale];
1228 }
1229 dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
1230 }
1231 }
1232 }
1233 else if (srcFormat == GL_RGBA && srcType == GL_UNSIGNED_BYTE) {
1234 /* general case */
1235 if (wScale == 1 && hScale == 1) {
1236 const GLubyte *src = _mesa_image_address(packing, srcImage,
1237 srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
1238 const GLint srcStride = _mesa_image_row_stride(packing,
1239 width, srcFormat, srcType);
1240 GLuint *dst = (GLuint *) ((GLubyte *) dstImage
1241 + dstYoffset * dstRowStride) + dstXoffset;
1242 GLint row;
1243 for (row = 0; row < height; row++) {
1244 GLint col, col4;
1245 for (col = col4 = 0; col < width; col++, col4 += 4) {
1246 GLubyte r = src[col4 + 0];
1247 GLubyte g = src[col4 + 1];
1248 GLubyte b = src[col4 + 2];
1249 GLubyte a = src[col4 + 3];
1250 dst[col] = (a << 24) | (r << 16) | (g << 8) | b;
1251 }
1252 src += srcStride;
1253 dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
1254 }
1255 }
1256 else {
1257 /* must rescale image */
1258 GLuint *dst = (GLuint *) ((GLubyte *) dstImage
1259 + dstYoffset * dstRowStride) + dstXoffset;
1260 GLint row;
1261 for (row = 0; row < height; row++) {
1262 GLint srcRow = row / hScale;
1263 const GLubyte *src = _mesa_image_address(packing, srcImage,
1264 srcWidth, srcHeight, srcFormat, srcType, 0, srcRow, 0);
1265 GLint col;
1266 for (col = 0; col < width; col++) {
1267 GLint col4 = (col / wScale) * 4;
1268 GLubyte r = src[col4 + 0];
1269 GLubyte g = src[col4 + 1];
1270 GLubyte b = src[col4 + 2];
1271 GLubyte a = src[col4 + 3];
1272 dst[col] = (a << 24) | (r << 16) | (g << 8) | b;
1273 }
1274 dst = (GLuint *) ((GLubyte *) dst + dstRowStride);
1275 }
1276 }
1277 }
1278 else {
1279 /* can't handle this source format/type combination */
1280 return GL_FALSE;
1281 }
1282 if (dstFormat == MESA_FF_R8_G8_B8) {
1283 /* set alpha bytes to 0xff */
1284 GLint row, col;
1285 GLubyte *dst = (GLubyte *) dstImage
1286 + dstYoffset * dstRowStride + dstXoffset;
1287 for (row = 0; row < height; row++) {
1288 for (col = 0; col < width; col++) {
1289 dst[col * 4 + 3] = 0xff;
1290 }
1291 dst = dst + dstRowStride;
1292 }
1293 }
1294 break;
1295
1296
1297 default:
1298 /* unexpected internal format! */
1299 return GL_FALSE;
1300 }
1301 return GL_TRUE;
1302 }
1303
1304
1305
1306
1307 /*
1308 * Used to convert 16-bit texels into GLubyte color components.
1309 */
1310 static GLubyte R5G6B5toRed[0xffff];
1311 static GLubyte R5G6B5toGreen[0xffff];
1312 static GLubyte R5G6B5toBlue[0xffff];
1313
1314 static GLubyte A4R4G4B4toRed[0xffff];
1315 static GLubyte A4R4G4B4toGreen[0xffff];
1316 static GLubyte A4R4G4B4toBlue[0xffff];
1317 static GLubyte A4R4G4B4toAlpha[0xffff];
1318
1319 static GLubyte A1R5G5B5toRed[0xffff];
1320 static GLubyte A1R5G5B5toGreen[0xffff];
1321 static GLubyte A1R5G5B5toBlue[0xffff];
1322 static GLubyte A1R5G5B5toAlpha[0xffff];
1323
1324 static void
1325 generate_lookup_tables(void)
1326 {
1327 GLint i;
1328 for (i = 0; i <= 0xffff; i++) {
1329 GLint r = (i >> 8) & 0xf8;
1330 GLint g = (i >> 3) & 0xfc;
1331 GLint b = (i << 3) & 0xf8;
1332 r = r * 255 / 0xf8;
1333 g = g * 255 / 0xfc;
1334 b = b * 255 / 0xf8;
1335 R5G6B5toRed[i] = r;
1336 R5G6B5toGreen[i] = g;
1337 R5G6B5toBlue[i] = b;
1338 }
1339
1340 for (i = 0; i <= 0xffff; i++) {
1341 GLint r = (i >> 8) & 0xf;
1342 GLint g = (i >> 4) & 0xf;
1343 GLint b = (i ) & 0xf;
1344 GLint a = (i >> 12) & 0xf;
1345 r = r * 255 / 0xf;
1346 g = g * 255 / 0xf;
1347 b = b * 255 / 0xf;
1348 a = a * 255 / 0xf;
1349 A4R4G4B4toRed[i] = r;
1350 A4R4G4B4toGreen[i] = g;
1351 A4R4G4B4toBlue[i] = b;
1352 A4R4G4B4toAlpha[i] = a;
1353 }
1354
1355 for (i = 0; i <= 0xffff; i++) {
1356 GLint r = (i >> 10) & 0xf8;
1357 GLint g = (i >> 5) & 0xf8;
1358 GLint b = (i ) & 0xf8;
1359 GLint a = (i >> 15) & 0x1;
1360 r = r * 255 / 0xf8;
1361 g = g * 255 / 0xf8;
1362 b = b * 255 / 0xf8;
1363 a = a * 255;
1364 A1R5G5B5toRed[i] = r;
1365 A1R5G5B5toGreen[i] = g;
1366 A1R5G5B5toBlue[i] = b;
1367 A1R5G5B5toAlpha[i] = a;
1368 }
1369 }
1370
1371
1372
1373 /*
1374 * Convert a texture image from an internal format to one of Mesa's
1375 * core internal formats. This is likely to be used by glGetTexImage
1376 * and for fetching texture images when falling back to software rendering.
1377 *
1378 * Input:
1379 * srcFormat - source image format
1380 * srcWidth, srcHeight - source image size
1381 * srcImage - source image pointer
1382 * srcRowStride - bytes to jump between image rows
1383 * dstWidth, dstHeight - size of dest image
1384 * dstFormat - format of dest image (must be one of Mesa's IntFormat values)
1385 * dstImage - pointer to dest image
1386 * Notes:
1387 * This function will do power of two image down-scaling to accomodate
1388 * drivers with limited texture image aspect ratios.
1389 * The implicit dest data type is GL_UNSIGNED_BYTE.
1390 */
1391 void
1392 _mesa_unconvert_teximage(MesaIntTexFormat srcFormat,
1393 GLint srcWidth, GLint srcHeight,
1394 const GLvoid *srcImage, GLint srcRowStride,
1395 GLint dstWidth, GLint dstHeight,
1396 GLenum dstFormat, GLubyte *dstImage)
1397 {
1398 static GLboolean firstCall = GL_TRUE;
1399 const GLint wScale = srcWidth / dstWidth; /* must be power of two */
1400 const GLint hScale = srcHeight / dstHeight; /* must be power of two */
1401 ASSERT(srcWidth >= dstWidth);
1402 ASSERT(srcHeight >= dstHeight);
1403 ASSERT(dstImage);
1404 ASSERT(srcImage);
1405
1406 if (firstCall) {
1407 generate_lookup_tables();
1408 firstCall = GL_FALSE;
1409 }
1410
1411 switch (srcFormat) {
1412 case MESA_I8:
1413 case MESA_L8:
1414 case MESA_A8:
1415 case MESA_C8:
1416 #ifdef DEBUG
1417 if (srcFormat == MESA_I8) {
1418 ASSERT(dstFormat == GL_INTENSITY);
1419 }
1420 else if (srcFormat == MESA_L8) {
1421 ASSERT(dstFormat == GL_LUMINANCE);
1422 }
1423 else if (srcFormat == MESA_A8) {
1424 ASSERT(dstFormat == GL_ALPHA);
1425 }
1426 else if (srcFormat == MESA_C8) {
1427 ASSERT(dstFormat == GL_COLOR_INDEX);
1428 }
1429 #endif
1430 if (wScale == 1 && hScale == 1) {
1431 /* easy! */
1432 MEMCPY(dstImage, srcImage, dstWidth * dstHeight * sizeof(GLubyte));
1433 }
1434 else {
1435 /* rescale */
1436 const GLubyte *src8 = (const GLubyte *) srcImage;
1437 GLint row, col;
1438 for (row = 0; row < dstHeight; row++) {
1439 GLint srcRow = row * hScale;
1440 for (col = 0; col < dstWidth; col++) {
1441 GLint srcCol = col * wScale;
1442 *dstImage++ = src8[srcRow * srcWidth + srcCol];
1443 }
1444 }
1445 }
1446 break;
1447 case MESA_A8_L8:
1448 ASSERT(dstFormat == GL_LUMINANCE_ALPHA);
1449 if (wScale == 1 && hScale == 1) {
1450 GLint i, n = dstWidth * dstHeight;
1451 const GLushort *texel = (const GLushort *) srcImage;
1452 for (i = 0; i < n; i++) {
1453 const GLushort tex = *texel++;
1454 *dstImage++ = (tex & 0xff); /* luminance */
1455 *dstImage++ = (tex >> 8); /* alpha */
1456 }
1457 }
1458 else {
1459 /* rescale */
1460 const GLushort *src16 = (const GLushort *) srcImage;
1461 GLint row, col;
1462 for (row = 0; row < dstHeight; row++) {
1463 GLint srcRow = row * hScale;
1464 for (col = 0; col < dstWidth; col++) {
1465 GLint srcCol = col * wScale;
1466 const GLushort tex = src16[srcRow * srcWidth + srcCol];
1467 *dstImage++ = (tex & 0xff); /* luminance */
1468 *dstImage++ = (tex >> 8); /* alpha */
1469 }
1470 }
1471 }
1472 break;
1473 case MESA_R5_G6_B5:
1474 ASSERT(dstFormat == GL_RGB);
1475 if (wScale == 1 && hScale == 1) {
1476 GLint i, n = dstWidth * dstHeight;
1477 const GLushort *texel = (const GLushort *) srcImage;
1478 for (i = 0; i < n; i++) {
1479 const GLushort tex = *texel++;
1480 *dstImage++ = R5G6B5toRed[tex];
1481 *dstImage++ = R5G6B5toGreen[tex];
1482 *dstImage++ = R5G6B5toBlue[tex];
1483 }
1484 }
1485 else {
1486 /* rescale */
1487 const GLushort *src16 = (const GLushort *) srcImage;
1488 GLint row, col;
1489 for (row = 0; row < dstHeight; row++) {
1490 GLint srcRow = row * hScale;
1491 for (col = 0; col < dstWidth; col++) {
1492 GLint srcCol = col * wScale;
1493 const GLushort tex = src16[srcRow * srcWidth + srcCol];
1494 *dstImage++ = R5G6B5toRed[tex];
1495 *dstImage++ = R5G6B5toGreen[tex];
1496 *dstImage++ = R5G6B5toBlue[tex];
1497 }
1498 }
1499 }
1500 break;
1501 case MESA_A4_R4_G4_B4:
1502 ASSERT(dstFormat == GL_RGBA);
1503 if (wScale == 1 && hScale == 1) {
1504 GLint i, n = dstWidth * dstHeight;
1505 const GLushort *texel = (const GLushort *) srcImage;
1506 for (i = 0; i < n; i++) {
1507 const GLushort tex = *texel++;
1508 *dstImage++ = A4R4G4B4toRed[tex];
1509 *dstImage++ = A4R4G4B4toGreen[tex];
1510 *dstImage++ = A4R4G4B4toBlue[tex];
1511 *dstImage++ = A4R4G4B4toAlpha[tex];
1512 }
1513 }
1514 else {
1515 /* rescale */
1516 const GLushort *src16 = (const GLushort *) srcImage;
1517 GLint row, col;
1518 for (row = 0; row < dstHeight; row++) {
1519 GLint srcRow = row * hScale;
1520 for (col = 0; col < dstWidth; col++) {
1521 GLint srcCol = col * wScale;
1522 const GLushort tex = src16[srcRow * srcWidth + srcCol];
1523 *dstImage++ = A4R4G4B4toRed[tex];
1524 *dstImage++ = A4R4G4B4toGreen[tex];
1525 *dstImage++ = A4R4G4B4toBlue[tex];
1526 *dstImage++ = A4R4G4B4toAlpha[tex];
1527 }
1528 }
1529 }
1530 break;
1531 case MESA_A1_R5_G5_B5:
1532 ASSERT(dstFormat == GL_RGBA);
1533 if (wScale == 1 && hScale == 1) {
1534 GLint i, n = dstWidth * dstHeight;
1535 const GLushort *texel = (const GLushort *) srcImage;
1536 for (i = 0; i < n; i++) {
1537 const GLushort tex = *texel++;
1538 *dstImage++ = A1R5G5B5toRed[tex];
1539 *dstImage++ = A1R5G5B5toGreen[tex];
1540 *dstImage++ = A1R5G5B5toBlue[tex];
1541 *dstImage++ = A1R5G5B5toAlpha[tex];
1542 }
1543 }
1544 else {
1545 /* rescale */
1546 const GLushort *src16 = (const GLushort *) srcImage;
1547 GLint row, col;
1548 for (row = 0; row < dstHeight; row++) {
1549 GLint srcRow = row * hScale;
1550 for (col = 0; col < dstWidth; col++) {
1551 GLint srcCol = col * wScale;
1552 const GLushort tex = src16[srcRow * srcWidth + srcCol];
1553 *dstImage++ = A1R5G5B5toRed[tex];
1554 *dstImage++ = A1R5G5B5toGreen[tex];
1555 *dstImage++ = A1R5G5B5toBlue[tex];
1556 *dstImage++ = A1R5G5B5toAlpha[tex];
1557 }
1558 }
1559 }
1560 break;
1561 case MESA_A8_R8_G8_B8:
1562 case MESA_FF_R8_G8_B8:
1563 ASSERT(dstFormat == GL_RGBA);
1564 if (wScale == 1 && hScale == 1) {
1565 GLint i, n = dstWidth * dstHeight;
1566 const GLuint *texel = (const GLuint *) srcImage;
1567 for (i = 0; i < n; i++) {
1568 const GLuint tex = *texel++;
1569 *dstImage++ = (tex >> 16) & 0xff; /* R */
1570 *dstImage++ = (tex >> 8) & 0xff; /* G */
1571 *dstImage++ = (tex ) & 0xff; /* B */
1572 *dstImage++ = (tex >> 24) & 0xff; /* A */
1573 }
1574 }
1575 else {
1576 /* rescale */
1577 const GLuint *src = (const GLuint *) srcImage;
1578 GLint row, col;
1579 for (row = 0; row < dstHeight; row++) {
1580 GLint srcRow = row * hScale;
1581 for (col = 0; col < dstWidth; col++) {
1582 GLint srcCol = col * wScale;
1583 const GLuint tex = src[srcRow * srcWidth + srcCol];
1584 *dstImage++ = (tex >> 16) & 0xff; /* R */
1585 *dstImage++ = (tex >> 8) & 0xff; /* G */
1586 *dstImage++ = (tex ) & 0xff; /* B */
1587 *dstImage++ = (tex >> 24) & 0xff; /* A */
1588 }
1589 }
1590 }
1591 break;
1592 default:
1593 gl_problem(NULL, "bad srcFormat in _mesa_uncovert_teximage()");
1594 }
1595 }
1596
1597
1598
1599 /*
1600 * Given an internal Mesa driver texture format, fill in the component
1601 * bit sizes in the given texture image struct.
1602 */
1603 void
1604 _mesa_set_teximage_component_sizes(MesaIntTexFormat mesaFormat,
1605 struct gl_texture_image *texImage)
1606 {
1607 static const GLint bitSizes [][8] = {
1608 /* format R G B A I L C */
1609 { MESA_I8, 0, 0, 0, 0, 8, 0, 0 },
1610 { MESA_L8, 0, 0, 0, 0, 0, 8, 0 },
1611 { MESA_A8, 0, 0, 0, 8, 0, 0, 0 },
1612 { MESA_C8, 0, 0, 0, 0, 0, 0, 8 },
1613 { MESA_A8_L8, 0, 0, 0, 8, 0, 8, 0 },
1614 { MESA_R5_G6_B5, 5, 6, 5, 0, 0, 0, 0 },
1615 { MESA_A4_R4_G4_B4, 4, 4, 4, 4, 0, 0, 0 },
1616 { MESA_A1_R5_G5_B5, 5, 5, 5, 1, 0, 0, 0 },
1617 { MESA_A8_R8_G8_B8, 8, 8, 8, 8, 0, 0, 0 },
1618 { MESA_FF_R8_G8_B8, 8, 8, 8, 8, 0, 0, 0 },
1619 { -1, 0, 0, 0, 0, 0, 0, 0 }
1620 };
1621 GLint i;
1622 for (i = 0; i < bitSizes[i][0] >= 0; i++) {
1623 if (bitSizes[i][0] == mesaFormat) {
1624 texImage->RedBits = bitSizes[i][1];
1625 texImage->GreenBits = bitSizes[i][2];
1626 texImage->BlueBits = bitSizes[i][3];
1627 texImage->AlphaBits = bitSizes[i][4];
1628 texImage->IntensityBits = bitSizes[i][5];
1629 texImage->LuminanceBits = bitSizes[i][6];
1630 texImage->IndexBits = bitSizes[i][7];
1631 return;
1632 }
1633 }
1634 gl_problem(NULL, "bad format in _mesa_set_teximage_component_sizes");
1635 }