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