fix for-loop in _mesa_GetDouble to avoid out of bounds memory read
[mesa.git] / src / mesa / main / texstore.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.3
4 *
5 * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25 /*
26 * Authors:
27 * Brian Paul
28 */
29
30 /*
31 * The GL texture image functions in teximage.c basically just do
32 * error checking and data structure allocation. They in turn call
33 * device driver functions which actually copy/convert/store the user's
34 * texture image data.
35 *
36 * However, most device drivers will be able to use the fallback functions
37 * in this file. That is, most drivers will have the following bit of
38 * code:
39 * ctx->Driver.TexImage1D = _mesa_store_teximage1d;
40 * ctx->Driver.TexImage2D = _mesa_store_teximage2d;
41 * ctx->Driver.TexImage3D = _mesa_store_teximage3d;
42 * etc...
43 *
44 * Texture image processing is actually kind of complicated. We have to do:
45 * Format/type conversions
46 * pixel unpacking
47 * pixel transfer (scale, bais, lookup, convolution!, etc)
48 *
49 * These functions can handle most everything, including processing full
50 * images and sub-images.
51 */
52
53
54 #include "glheader.h"
55 #include "bufferobj.h"
56 #include "colormac.h"
57 #include "context.h"
58 #include "convolve.h"
59 #include "image.h"
60 #include "macros.h"
61 #include "imports.h"
62 #include "texcompress.h"
63 #include "texformat.h"
64 #include "teximage.h"
65 #include "texstore.h"
66
67
68 static const GLint ZERO = 4, ONE = 5;
69
70 static GLboolean can_swizzle(GLenum logicalBaseFormat)
71 {
72 switch (logicalBaseFormat) {
73 case GL_RGBA:
74 case GL_RGB:
75 case GL_LUMINANCE_ALPHA:
76 case GL_INTENSITY:
77 case GL_ALPHA:
78 case GL_LUMINANCE:
79 return GL_TRUE;
80 default:
81 return GL_FALSE;
82 }
83 }
84
85
86 /**
87 * When promoting texture formats (see below) we need to compute the
88 * mapping of dest components back to source components.
89 * This function does that.
90 * \param logicalBaseFormat the logical format of the texture
91 * \param textureBaseFormat the final texture format
92 * \return map[4] the four mapping values
93 */
94 static void
95 compute_component_mapping(GLenum logicalBaseFormat, GLenum textureBaseFormat,
96 GLubyte map[6])
97 {
98 map[ZERO] = ZERO;
99 map[ONE] = ONE;
100
101 /* compute mapping from dest components back to src components */
102 switch (textureBaseFormat) {
103 case GL_RGB:
104 case GL_RGBA:
105 switch (logicalBaseFormat) {
106 case GL_LUMINANCE:
107 map[0] = map[1] = map[2] = 0;
108 if (textureBaseFormat == GL_RGBA)
109 map[3] = ONE;
110 break;
111 case GL_ALPHA:
112 ASSERT(textureBaseFormat == GL_RGBA);
113 map[0] = map[1] = map[2] = ZERO;
114 map[3] = 0;
115 break;
116 case GL_INTENSITY:
117 map[0] = map[1] = map[2] = 0;
118 if (textureBaseFormat == GL_RGBA)
119 map[3] = 0;
120 break;
121 case GL_LUMINANCE_ALPHA:
122 ASSERT(textureBaseFormat == GL_RGBA);
123 map[0] = map[1] = map[2] = 0;
124 map[3] = 1;
125 break;
126 case GL_RGB:
127 ASSERT(textureBaseFormat == GL_RGBA);
128 map[0] = 0;
129 map[1] = 1;
130 map[2] = 2;
131 map[3] = ONE;
132 break;
133 case GL_RGBA:
134 ASSERT(textureBaseFormat == GL_RGBA);
135 map[0] = 0;
136 map[1] = 1;
137 map[2] = 2;
138 map[3] = 3;
139 break;
140 default:
141 _mesa_problem(NULL, "Unexpected logicalBaseFormat");
142 map[0] = map[1] = map[2] = map[3] = 0;
143 }
144 break;
145 case GL_LUMINANCE_ALPHA:
146 switch (logicalBaseFormat) {
147 case GL_LUMINANCE:
148 map[0] = 0;
149 map[1] = ONE;
150 break;
151 case GL_ALPHA:
152 map[0] = ZERO;
153 map[1] = 0;
154 break;
155 case GL_INTENSITY:
156 map[0] = 0;
157 map[1] = 0;
158 break;
159 default:
160 _mesa_problem(NULL, "Unexpected logicalBaseFormat");
161 map[0] = map[1] = 0;
162 }
163 break;
164 default:
165 _mesa_problem(NULL, "Unexpected logicalBaseFormat");
166 map[0] = map[1] = 0;
167 break;
168 }
169 }
170
171
172 /**
173 * Make a temporary (color) texture image with GLfloat components.
174 * Apply all needed pixel unpacking and pixel transfer operations.
175 * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
176 * Suppose the user specifies GL_LUMINANCE as the internal texture format
177 * but the graphics hardware doesn't support luminance textures. So, might
178 * use an RGB hardware format instead.
179 * If logicalBaseFormat != textureBaseFormat we have some extra work to do.
180 *
181 * \param ctx the rendering context
182 * \param dims image dimensions: 1, 2 or 3
183 * \param logicalBaseFormat basic texture derived from the user's
184 * internal texture format value
185 * \param textureBaseFormat the actual basic format of the texture
186 * \param srcWidth source image width
187 * \param srcHeight source image height
188 * \param srcDepth source image depth
189 * \param srcFormat source image format
190 * \param srcType source image type
191 * \param srcAddr source image address
192 * \param srcPacking source image pixel packing
193 * \return resulting image with format = textureBaseFormat and type = GLfloat.
194 */
195 static GLfloat *
196 make_temp_float_image(GLcontext *ctx, GLuint dims,
197 GLenum logicalBaseFormat,
198 GLenum textureBaseFormat,
199 GLint srcWidth, GLint srcHeight, GLint srcDepth,
200 GLenum srcFormat, GLenum srcType,
201 const GLvoid *srcAddr,
202 const struct gl_pixelstore_attrib *srcPacking)
203 {
204 GLuint transferOps = ctx->_ImageTransferState;
205 GLfloat *tempImage;
206
207 ASSERT(dims >= 1 && dims <= 3);
208
209 ASSERT(logicalBaseFormat == GL_RGBA ||
210 logicalBaseFormat == GL_RGB ||
211 logicalBaseFormat == GL_LUMINANCE_ALPHA ||
212 logicalBaseFormat == GL_LUMINANCE ||
213 logicalBaseFormat == GL_ALPHA ||
214 logicalBaseFormat == GL_INTENSITY ||
215 logicalBaseFormat == GL_COLOR_INDEX ||
216 logicalBaseFormat == GL_DEPTH_COMPONENT);
217
218 ASSERT(textureBaseFormat == GL_RGBA ||
219 textureBaseFormat == GL_RGB ||
220 textureBaseFormat == GL_LUMINANCE_ALPHA ||
221 textureBaseFormat == GL_LUMINANCE ||
222 textureBaseFormat == GL_ALPHA ||
223 textureBaseFormat == GL_INTENSITY ||
224 textureBaseFormat == GL_COLOR_INDEX ||
225 textureBaseFormat == GL_DEPTH_COMPONENT);
226
227 /* conventional color image */
228
229 if ((dims == 1 && ctx->Pixel.Convolution1DEnabled) ||
230 (dims >= 2 && ctx->Pixel.Convolution2DEnabled) ||
231 (dims >= 2 && ctx->Pixel.Separable2DEnabled)) {
232 /* need image convolution */
233 const GLuint preConvTransferOps
234 = (transferOps & IMAGE_PRE_CONVOLUTION_BITS) | IMAGE_CLAMP_BIT;
235 const GLuint postConvTransferOps
236 = (transferOps & IMAGE_POST_CONVOLUTION_BITS) | IMAGE_CLAMP_BIT;
237 GLint img, row;
238 GLint convWidth, convHeight;
239 GLfloat *convImage;
240
241 /* pre-convolution image buffer (3D) */
242 tempImage = (GLfloat *) _mesa_malloc(srcWidth * srcHeight * srcDepth
243 * 4 * sizeof(GLfloat));
244 if (!tempImage)
245 return NULL;
246
247 /* post-convolution image buffer (2D) */
248 convImage = (GLfloat *) _mesa_malloc(srcWidth * srcHeight
249 * 4 * sizeof(GLfloat));
250 if (!convImage) {
251 _mesa_free(tempImage);
252 return NULL;
253 }
254
255 /* loop over 3D image slices */
256 for (img = 0; img < srcDepth; img++) {
257 GLfloat *dst = tempImage + img * (srcWidth * srcHeight * 4);
258
259 /* unpack and do transfer ops up to convolution */
260 for (row = 0; row < srcHeight; row++) {
261 const GLvoid *src = _mesa_image_address(dims, srcPacking,
262 srcAddr, srcWidth, srcHeight,
263 srcFormat, srcType, img, row, 0);
264 _mesa_unpack_color_span_float(ctx, srcWidth, GL_RGBA, dst,
265 srcFormat, srcType, src,
266 srcPacking,
267 preConvTransferOps);
268 dst += srcWidth * 4;
269 }
270
271 /* do convolution */
272 {
273 GLfloat *src = tempImage + img * (srcWidth * srcHeight * 4);
274 convWidth = srcWidth;
275 convHeight = srcHeight;
276 if (dims == 1) {
277 ASSERT(ctx->Pixel.Convolution1DEnabled);
278 _mesa_convolve_1d_image(ctx, &convWidth, src, convImage);
279 }
280 else {
281 if (ctx->Pixel.Convolution2DEnabled) {
282 _mesa_convolve_2d_image(ctx, &convWidth, &convHeight,
283 src, convImage);
284 }
285 else {
286 ASSERT(ctx->Pixel.Separable2DEnabled);
287 _mesa_convolve_sep_image(ctx, &convWidth, &convHeight,
288 src, convImage);
289 }
290 }
291 }
292
293 /* do post-convolution transfer and pack into tempImage */
294 {
295 const GLint logComponents
296 = _mesa_components_in_format(logicalBaseFormat);
297 const GLfloat *src = convImage;
298 GLfloat *dst = tempImage + img * (convWidth * convHeight * 4);
299 for (row = 0; row < convHeight; row++) {
300 _mesa_pack_rgba_span_float(ctx, convWidth,
301 (const GLfloat (*)[4]) src,
302 logicalBaseFormat, GL_FLOAT,
303 dst, &ctx->DefaultPacking,
304 postConvTransferOps);
305 src += convWidth * 4;
306 dst += convWidth * logComponents;
307 }
308 }
309 } /* loop over 3D image slices */
310
311 _mesa_free(convImage);
312
313 /* might need these below */
314 srcWidth = convWidth;
315 srcHeight = convHeight;
316 }
317 else {
318 /* no convolution */
319 const GLint components = _mesa_components_in_format(logicalBaseFormat);
320 const GLint srcStride = _mesa_image_row_stride(srcPacking,
321 srcWidth, srcFormat, srcType);
322 GLfloat *dst;
323 GLint img, row;
324
325 tempImage = (GLfloat *) _mesa_malloc(srcWidth * srcHeight * srcDepth
326 * components * sizeof(GLfloat));
327 if (!tempImage)
328 return NULL;
329
330 dst = tempImage;
331 for (img = 0; img < srcDepth; img++) {
332 const GLubyte *src
333 = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr,
334 srcWidth, srcHeight,
335 srcFormat, srcType,
336 img, 0, 0);
337 for (row = 0; row < srcHeight; row++) {
338 _mesa_unpack_color_span_float(ctx, srcWidth, logicalBaseFormat,
339 dst, srcFormat, srcType, src,
340 srcPacking, transferOps);
341 dst += srcWidth * components;
342 src += srcStride;
343 }
344 }
345 }
346
347 if (logicalBaseFormat != textureBaseFormat) {
348 /* more work */
349 GLint texComponents = _mesa_components_in_format(textureBaseFormat);
350 GLint logComponents = _mesa_components_in_format(logicalBaseFormat);
351 GLfloat *newImage;
352 GLint i, n;
353 GLubyte map[6];
354
355 /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
356 ASSERT(textureBaseFormat == GL_RGB || textureBaseFormat == GL_RGBA ||
357 textureBaseFormat == GL_LUMINANCE_ALPHA);
358
359 /* The actual texture format should have at least as many components
360 * as the logical texture format.
361 */
362 ASSERT(texComponents >= logComponents);
363
364 newImage = (GLfloat *) _mesa_malloc(srcWidth * srcHeight * srcDepth
365 * texComponents * sizeof(GLfloat));
366 if (!newImage) {
367 _mesa_free(tempImage);
368 return NULL;
369 }
370
371 compute_component_mapping(logicalBaseFormat, textureBaseFormat, map);
372
373 n = srcWidth * srcHeight * srcDepth;
374 for (i = 0; i < n; i++) {
375 GLint k;
376 for (k = 0; k < texComponents; k++) {
377 GLint j = map[k];
378 if (j == ZERO)
379 newImage[i * texComponents + k] = 0.0F;
380 else if (j == ONE)
381 newImage[i * texComponents + k] = 1.0F;
382 else
383 newImage[i * texComponents + k] = tempImage[i * logComponents + j];
384 }
385 }
386
387 _mesa_free(tempImage);
388 tempImage = newImage;
389 }
390
391 return tempImage;
392 }
393
394
395 /**
396 * Make a temporary (color) texture image with GLchan components.
397 * Apply all needed pixel unpacking and pixel transfer operations.
398 * Note that there are both logicalBaseFormat and textureBaseFormat parameters.
399 * Suppose the user specifies GL_LUMINANCE as the internal texture format
400 * but the graphics hardware doesn't support luminance textures. So, might
401 * use an RGB hardware format instead.
402 * If logicalBaseFormat != textureBaseFormat we have some extra work to do.
403 *
404 * \param ctx the rendering context
405 * \param dims image dimensions: 1, 2 or 3
406 * \param logicalBaseFormat basic texture derived from the user's
407 * internal texture format value
408 * \param textureBaseFormat the actual basic format of the texture
409 * \param srcWidth source image width
410 * \param srcHeight source image height
411 * \param srcDepth source image depth
412 * \param srcFormat source image format
413 * \param srcType source image type
414 * \param srcAddr source image address
415 * \param srcPacking source image pixel packing
416 * \return resulting image with format = textureBaseFormat and type = GLchan.
417 */
418 GLchan *
419 _mesa_make_temp_chan_image(GLcontext *ctx, GLuint dims,
420 GLenum logicalBaseFormat,
421 GLenum textureBaseFormat,
422 GLint srcWidth, GLint srcHeight, GLint srcDepth,
423 GLenum srcFormat, GLenum srcType,
424 const GLvoid *srcAddr,
425 const struct gl_pixelstore_attrib *srcPacking)
426 {
427 GLuint transferOps = ctx->_ImageTransferState;
428 const GLint components = _mesa_components_in_format(logicalBaseFormat);
429 GLboolean freeSrcImage = GL_FALSE;
430 GLint img, row;
431 GLchan *tempImage, *dst;
432
433 ASSERT(dims >= 1 && dims <= 3);
434
435 ASSERT(logicalBaseFormat == GL_RGBA ||
436 logicalBaseFormat == GL_RGB ||
437 logicalBaseFormat == GL_LUMINANCE_ALPHA ||
438 logicalBaseFormat == GL_LUMINANCE ||
439 logicalBaseFormat == GL_ALPHA ||
440 logicalBaseFormat == GL_INTENSITY);
441
442 ASSERT(textureBaseFormat == GL_RGBA ||
443 textureBaseFormat == GL_RGB ||
444 textureBaseFormat == GL_LUMINANCE_ALPHA ||
445 textureBaseFormat == GL_LUMINANCE ||
446 textureBaseFormat == GL_ALPHA ||
447 textureBaseFormat == GL_INTENSITY);
448
449 if ((dims == 1 && ctx->Pixel.Convolution1DEnabled) ||
450 (dims >= 2 && ctx->Pixel.Convolution2DEnabled) ||
451 (dims >= 2 && ctx->Pixel.Separable2DEnabled)) {
452 /* get convolved image */
453 GLfloat *convImage = make_temp_float_image(ctx, dims,
454 logicalBaseFormat,
455 logicalBaseFormat,
456 srcWidth, srcHeight, srcDepth,
457 srcFormat, srcType,
458 srcAddr, srcPacking);
459 if (!convImage)
460 return NULL;
461 /* the convolved image is our new source image */
462 srcAddr = convImage;
463 srcFormat = logicalBaseFormat;
464 srcType = GL_FLOAT;
465 srcPacking = &ctx->DefaultPacking;
466 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
467 transferOps = 0;
468 freeSrcImage = GL_TRUE;
469 }
470
471 /* unpack and transfer the source image */
472 tempImage = (GLchan *) _mesa_malloc(srcWidth * srcHeight * srcDepth
473 * components * sizeof(GLchan));
474 if (!tempImage)
475 return NULL;
476
477 dst = tempImage;
478 for (img = 0; img < srcDepth; img++) {
479 const GLint srcStride = _mesa_image_row_stride(srcPacking,
480 srcWidth, srcFormat,
481 srcType);
482 const GLubyte *src
483 = (const GLubyte *) _mesa_image_address(dims, srcPacking, srcAddr,
484 srcWidth, srcHeight,
485 srcFormat, srcType,
486 img, 0, 0);
487 for (row = 0; row < srcHeight; row++) {
488 _mesa_unpack_color_span_chan(ctx, srcWidth, logicalBaseFormat, dst,
489 srcFormat, srcType, src, srcPacking,
490 transferOps);
491 dst += srcWidth * components;
492 src += srcStride;
493 }
494 }
495
496 /* If we made a temporary image for convolution, free it here */
497 if (freeSrcImage) {
498 _mesa_free((void *) srcAddr);
499 }
500
501 if (logicalBaseFormat != textureBaseFormat) {
502 /* one more conversion step */
503 GLint texComponents = _mesa_components_in_format(textureBaseFormat);
504 GLint logComponents = _mesa_components_in_format(logicalBaseFormat);
505 GLchan *newImage;
506 GLint i, n;
507 GLubyte map[6];
508
509 /* we only promote up to RGB, RGBA and LUMINANCE_ALPHA formats for now */
510 ASSERT(textureBaseFormat == GL_RGB || textureBaseFormat == GL_RGBA ||
511 textureBaseFormat == GL_LUMINANCE_ALPHA);
512
513 /* The actual texture format should have at least as many components
514 * as the logical texture format.
515 */
516 ASSERT(texComponents >= logComponents);
517
518 newImage = (GLchan *) _mesa_malloc(srcWidth * srcHeight * srcDepth
519 * texComponents * sizeof(GLchan));
520 if (!newImage) {
521 _mesa_free(tempImage);
522 return NULL;
523 }
524
525 compute_component_mapping(logicalBaseFormat, textureBaseFormat, map);
526
527 n = srcWidth * srcHeight * srcDepth;
528 for (i = 0; i < n; i++) {
529 GLint k;
530 for (k = 0; k < texComponents; k++) {
531 GLint j = map[k];
532 if (j == ZERO)
533 newImage[i * texComponents + k] = 0;
534 else if (j == ONE)
535 newImage[i * texComponents + k] = CHAN_MAX;
536 else
537 newImage[i * texComponents + k] = tempImage[i * logComponents + j];
538 }
539 }
540
541 _mesa_free(tempImage);
542 tempImage = newImage;
543 }
544
545 return tempImage;
546 }
547
548
549 /**
550 * Copy GLubyte pixels from <src> to <dst> with swizzling.
551 * \param dst destination pixels
552 * \param dstComponents number of color components in destination pixels
553 * \param src source pixels
554 * \param srcComponents number of color components in source pixels
555 * \param map the swizzle mapping
556 * \param count number of pixels to copy/swizzle.
557 */
558 static void
559 swizzle_copy(GLubyte *dst, GLuint dstComponents, const GLubyte *src,
560 GLuint srcComponents, const GLubyte *map, GLuint count)
561 {
562 GLubyte tmp[8];
563 GLint i;
564
565 tmp[ZERO] = 0x0;
566 tmp[ONE] = 0xff;
567
568 switch (dstComponents) {
569 case 4:
570 for (i = 0; i < count; i++) {
571 COPY_4UBV(tmp, src);
572 src += srcComponents;
573 dst[0] = tmp[map[0]];
574 dst[1] = tmp[map[1]];
575 dst[2] = tmp[map[2]];
576 dst[3] = tmp[map[3]];
577 dst += 4;
578 }
579 break;
580 case 3:
581 for (i = 0; i < count; i++) {
582 COPY_4UBV(tmp, src);
583 src += srcComponents;
584 dst[0] = tmp[map[0]];
585 dst[1] = tmp[map[1]];
586 dst[2] = tmp[map[2]];
587 dst += 3;
588 }
589 break;
590 case 2:
591 for (i = 0; i < count; i++) {
592 COPY_4UBV(tmp, src);
593 src += srcComponents;
594 dst[0] = tmp[map[0]];
595 dst[1] = tmp[map[1]];
596 dst += 2;
597 }
598 break;
599 }
600 }
601
602
603 /**
604 * Transfer a GLubyte texture image with component swizzling.
605 */
606 static void
607 _mesa_swizzle_ubyte_image(GLcontext *ctx,
608 GLuint dimensions,
609 GLenum srcFormat,
610 const GLubyte *dstmap, GLint dstComponents,
611
612 GLvoid *dstAddr,
613 GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
614 GLint dstRowStride, GLint dstImageStride,
615
616 GLint srcWidth, GLint srcHeight, GLint srcDepth,
617 const GLvoid *srcAddr,
618 const struct gl_pixelstore_attrib *srcPacking )
619 {
620 GLint srcComponents = _mesa_components_in_format(srcFormat);
621 GLubyte srcmap[6], map[4];
622 GLint i;
623
624 const GLint srcRowStride =
625 _mesa_image_row_stride(srcPacking, srcWidth,
626 srcFormat, GL_UNSIGNED_BYTE);
627 const GLint srcImageStride
628 = _mesa_image_image_stride(srcPacking, srcWidth, srcHeight, srcFormat,
629 GL_UNSIGNED_BYTE);
630 const GLubyte *srcImage
631 = (const GLubyte *) _mesa_image_address(dimensions, srcPacking, srcAddr,
632 srcWidth, srcHeight, srcFormat,
633 GL_UNSIGNED_BYTE, 0, 0, 0);
634
635 GLubyte *dstImage = (GLubyte *) dstAddr
636 + dstZoffset * dstImageStride
637 + dstYoffset * dstRowStride
638 + dstXoffset * dstComponents;
639
640 compute_component_mapping(srcFormat, GL_RGBA, srcmap);
641
642 for (i = 0; i < 4; i++)
643 map[i] = srcmap[dstmap[i]];
644
645 if (srcRowStride == srcWidth * srcComponents &&
646 (srcImageStride == srcWidth * srcHeight * srcComponents ||
647 srcDepth == 1)) {
648 swizzle_copy(dstImage, dstComponents, srcImage, srcComponents, map,
649 srcWidth * srcHeight * srcDepth);
650 }
651 else {
652 GLint img, row;
653 for (img = 0; img < srcDepth; img++) {
654 const GLubyte *srcRow = srcImage;
655 GLubyte *dstRow = dstImage;
656 for (row = 0; row < srcHeight; row++) {
657 swizzle_copy(dstRow, dstComponents, srcRow, srcComponents, map, srcWidth);
658 dstRow += dstRowStride;
659 srcRow += srcRowStride;
660 }
661 srcImage += srcImageStride;
662 dstImage += dstImageStride;
663 }
664 }
665 }
666
667
668 /**
669 * Teximage storage routine for when a simple memcpy will do.
670 * No pixel transfer operations or special texel encodings allowed.
671 * 1D, 2D and 3D images supported.
672 */
673 static void
674 memcpy_texture(GLcontext *ctx,
675 GLuint dimensions,
676 const struct gl_texture_format *dstFormat,
677 GLvoid *dstAddr,
678 GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
679 GLint dstRowStride, GLint dstImageStride,
680 GLint srcWidth, GLint srcHeight, GLint srcDepth,
681 GLenum srcFormat, GLenum srcType,
682 const GLvoid *srcAddr,
683 const struct gl_pixelstore_attrib *srcPacking)
684 {
685 const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth,
686 srcFormat, srcType);
687 const GLint srcImageStride = _mesa_image_image_stride(srcPacking,
688 srcWidth, srcHeight, srcFormat, srcType);
689 const GLubyte *srcImage = (const GLubyte *) _mesa_image_address(dimensions,
690 srcPacking, srcAddr, srcWidth, srcHeight, srcFormat, srcType, 0, 0, 0);
691 const GLint bytesPerRow = srcWidth * dstFormat->TexelBytes;
692 const GLint bytesPerImage = srcHeight * bytesPerRow;
693 const GLint bytesPerTexture = srcDepth * bytesPerImage;
694 GLubyte *dstImage = (GLubyte *) dstAddr
695 + dstZoffset * dstImageStride
696 + dstYoffset * dstRowStride
697 + dstXoffset * dstFormat->TexelBytes;
698
699 if (dstRowStride == srcRowStride &&
700 dstRowStride == bytesPerRow &&
701 ((dstImageStride == srcImageStride &&
702 dstImageStride == bytesPerImage) ||
703 (srcDepth == 1))) {
704 /* one big memcpy */
705 ctx->Driver.TextureMemCpy(dstImage, srcImage, bytesPerTexture);
706 }
707 else {
708 GLint img, row;
709 for (img = 0; img < srcDepth; img++) {
710 const GLubyte *srcRow = srcImage;
711 GLubyte *dstRow = dstImage;
712 for (row = 0; row < srcHeight; row++) {
713 ctx->Driver.TextureMemCpy(dstRow, srcRow, bytesPerRow);
714 dstRow += dstRowStride;
715 srcRow += srcRowStride;
716 }
717 srcImage += srcImageStride;
718 dstImage += dstImageStride;
719 }
720 }
721 }
722
723
724
725 /**
726 * Store an image in any of the formats:
727 * _mesa_texformat_rgba
728 * _mesa_texformat_rgb
729 * _mesa_texformat_alpha
730 * _mesa_texformat_luminance
731 * _mesa_texformat_luminance_alpha
732 * _mesa_texformat_intensity
733 *
734 * \param dims either 1 or 2 or 3
735 * \param baseInternalFormat user-specified base internal format
736 * \param dstFormat destination Mesa texture format
737 * \param dstAddr destination image address
738 * \param dstX/Y/Zoffset destination x/y/z offset (ala TexSubImage), in texels
739 * \param dstRowStride destination image row stride, in bytes
740 * \param dstImageStride destination image layer stride, in bytes
741 * \param srcWidth/Height/Depth source image size, in pixels
742 * \param srcFormat incoming image format
743 * \param srcType incoming image data type
744 * \param srcAddr source image address
745 * \param srcPacking source image packing parameters
746 */
747 GLboolean
748 _mesa_texstore_rgba(GLcontext *ctx, GLuint dims,
749 GLenum baseInternalFormat,
750 const struct gl_texture_format *dstFormat,
751 GLvoid *dstAddr,
752 GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
753 GLint dstRowStride, GLint dstImageStride,
754 GLint srcWidth, GLint srcHeight, GLint srcDepth,
755 GLenum srcFormat, GLenum srcType,
756 const GLvoid *srcAddr,
757 const struct gl_pixelstore_attrib *srcPacking)
758 {
759 const GLint components = _mesa_components_in_format(baseInternalFormat);
760
761 ASSERT(dstFormat == &_mesa_texformat_rgba ||
762 dstFormat == &_mesa_texformat_rgb ||
763 dstFormat == &_mesa_texformat_alpha ||
764 dstFormat == &_mesa_texformat_luminance ||
765 dstFormat == &_mesa_texformat_luminance_alpha ||
766 dstFormat == &_mesa_texformat_intensity);
767 ASSERT(baseInternalFormat == GL_RGBA ||
768 baseInternalFormat == GL_RGB ||
769 baseInternalFormat == GL_ALPHA ||
770 baseInternalFormat == GL_LUMINANCE ||
771 baseInternalFormat == GL_LUMINANCE_ALPHA ||
772 baseInternalFormat == GL_INTENSITY);
773 ASSERT(dstFormat->TexelBytes == components * sizeof(GLchan));
774
775 if (!ctx->_ImageTransferState &&
776 !srcPacking->SwapBytes &&
777 baseInternalFormat == srcFormat &&
778 srcType == CHAN_TYPE) {
779 /* simple memcpy path */
780 memcpy_texture(ctx, dims,
781 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
782 dstRowStride, dstImageStride,
783 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
784 srcAddr, srcPacking);
785 }
786 else if (!ctx->_ImageTransferState &&
787 !srcPacking->SwapBytes &&
788 dstFormat == &_mesa_texformat_rgb &&
789 srcFormat == GL_RGBA &&
790 srcType == CHAN_TYPE) {
791 /* extract RGB from RGBA */
792 int img, row, col;
793 GLchan *dstImage = (GLchan *) (GLubyte *) dstAddr
794 + dstZoffset * dstImageStride
795 + dstYoffset * dstRowStride
796 + dstXoffset * dstFormat->TexelBytes;
797 for (img = 0; img < srcDepth; img++) {
798 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
799 srcWidth, srcFormat, srcType);
800 GLchan *srcRow = (GLchan *) _mesa_image_address(dims, srcPacking,
801 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
802 GLchan *dstRow = dstImage;
803 for (row = 0; row < srcHeight; row++) {
804 for (col = 0; col < srcWidth; col++) {
805 dstRow[col * 3 + RCOMP] = srcRow[col * 4 + RCOMP];
806 dstRow[col * 3 + GCOMP] = srcRow[col * 4 + GCOMP];
807 dstRow[col * 3 + BCOMP] = srcRow[col * 4 + BCOMP];
808 }
809 dstRow += dstRowStride;
810 srcRow = (GLchan *) ((GLubyte *) srcRow + srcRowStride);
811 }
812 dstImage += dstImageStride;
813 }
814 }
815 else {
816 /* general path */
817 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
818 baseInternalFormat,
819 dstFormat->BaseFormat,
820 srcWidth, srcHeight, srcDepth,
821 srcFormat, srcType, srcAddr,
822 srcPacking);
823 const GLchan *src = tempImage;
824 GLint bytesPerRow;
825 GLubyte *dstImage = (GLubyte *) dstAddr
826 + dstZoffset * dstImageStride
827 + dstYoffset * dstRowStride
828 + dstXoffset * dstFormat->TexelBytes;
829 GLint img, row;
830 if (!tempImage)
831 return GL_FALSE;
832 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
833 bytesPerRow = srcWidth * components * sizeof(GLchan);
834 for (img = 0; img < srcDepth; img++) {
835 GLubyte *dstRow = dstImage;
836 for (row = 0; row < srcHeight; row++) {
837 _mesa_memcpy(dstRow, src, bytesPerRow);
838 dstRow += dstRowStride;
839 src += srcWidth * components;
840 }
841 dstImage += dstImageStride;
842 }
843
844 _mesa_free((void *) tempImage);
845 }
846 return GL_TRUE;
847 }
848
849
850 /**
851 * Store a floating point depth component texture image.
852 */
853 GLboolean
854 _mesa_texstore_depth_component_float32(STORE_PARAMS)
855 {
856 (void) dims;
857 ASSERT(dstFormat == &_mesa_texformat_depth_component_float32);
858 ASSERT(dstFormat->TexelBytes == sizeof(GLfloat));
859
860 if (!ctx->_ImageTransferState &&
861 !srcPacking->SwapBytes &&
862 baseInternalFormat == GL_DEPTH_COMPONENT &&
863 srcFormat == GL_DEPTH_COMPONENT &&
864 srcType == GL_FLOAT) {
865 /* simple memcpy path */
866 memcpy_texture(ctx, dims,
867 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
868 dstRowStride, dstImageStride,
869 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
870 srcAddr, srcPacking);
871 }
872 else {
873 /* general path */
874 GLubyte *dstImage = (GLubyte *) dstAddr
875 + dstZoffset * dstImageStride
876 + dstYoffset * dstRowStride
877 + dstXoffset * dstFormat->TexelBytes;
878 GLint img, row;
879 for (img = 0; img < srcDepth; img++) {
880 GLubyte *dstRow = dstImage;
881 for (row = 0; row < srcHeight; row++) {
882 const GLvoid *src = _mesa_image_address(dims, srcPacking,
883 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
884 _mesa_unpack_depth_span(ctx, srcWidth, (GLfloat *) dstRow,
885 srcType, src, srcPacking);
886 dstRow += dstRowStride;
887 }
888 dstImage += dstImageStride;
889 }
890 }
891 return GL_TRUE;
892 }
893
894
895 /**
896 * Store a 16-bit integer depth component texture image.
897 */
898 GLboolean
899 _mesa_texstore_depth_component16(STORE_PARAMS)
900 {
901 (void) dims;
902 ASSERT(dstFormat == &_mesa_texformat_depth_component16);
903 ASSERT(dstFormat->TexelBytes == sizeof(GLushort));
904
905 if (!ctx->_ImageTransferState &&
906 !srcPacking->SwapBytes &&
907 baseInternalFormat == GL_DEPTH_COMPONENT &&
908 srcFormat == GL_DEPTH_COMPONENT &&
909 srcType == GL_UNSIGNED_SHORT) {
910 /* simple memcpy path */
911 memcpy_texture(ctx, dims,
912 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
913 dstRowStride, dstImageStride,
914 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
915 srcAddr, srcPacking);
916 }
917 else {
918 /* general path */
919 GLubyte *dstImage = (GLubyte *) dstAddr
920 + dstZoffset * dstImageStride
921 + dstYoffset * dstRowStride
922 + dstXoffset * dstFormat->TexelBytes;
923 GLint img, row, col;
924 for (img = 0; img < srcDepth; img++) {
925 GLubyte *dstRow = dstImage;
926 for (row = 0; row < srcHeight; row++) {
927 GLfloat depthTemp[MAX_WIDTH];
928 const GLvoid *src = _mesa_image_address(dims, srcPacking,
929 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
930 GLushort *dst16 = (GLushort *) dstRow;
931 _mesa_unpack_depth_span(ctx, srcWidth, depthTemp,
932 srcType, src, srcPacking);
933 for (col = 0; col < srcWidth; col++) {
934 dst16[col] = (GLushort) (depthTemp[col] * 65535.0F);
935 }
936 dstRow += dstRowStride;
937 }
938 dstImage += dstImageStride;
939 }
940 }
941 return GL_TRUE;
942 }
943
944
945 /**
946 * Store an rgb565 or rgb565_rev texture image.
947 */
948 GLboolean
949 _mesa_texstore_rgb565(STORE_PARAMS)
950 {
951 ASSERT(dstFormat == &_mesa_texformat_rgb565 ||
952 dstFormat == &_mesa_texformat_rgb565_rev);
953 ASSERT(dstFormat->TexelBytes == 2);
954
955 if (!ctx->_ImageTransferState &&
956 !srcPacking->SwapBytes &&
957 dstFormat == &_mesa_texformat_rgb565 &&
958 baseInternalFormat == GL_RGB &&
959 srcFormat == GL_RGB &&
960 srcType == GL_UNSIGNED_SHORT_5_6_5) {
961 /* simple memcpy path */
962 memcpy_texture(ctx, dims,
963 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
964 dstRowStride, dstImageStride,
965 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
966 srcAddr, srcPacking);
967 }
968 else if (!ctx->_ImageTransferState &&
969 !srcPacking->SwapBytes &&
970 baseInternalFormat == GL_RGB &&
971 srcFormat == GL_RGB &&
972 srcType == GL_UNSIGNED_BYTE &&
973 dims == 2) {
974 /* do optimized tex store */
975 const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth,
976 srcFormat, srcType);
977 const GLubyte *src = (const GLubyte *)
978 _mesa_image_address(dims, srcPacking, srcAddr, srcWidth, srcHeight,
979 srcFormat, srcType, 0, 0, 0);
980 GLubyte *dst = (GLubyte *) dstAddr
981 + dstZoffset * dstImageStride
982 + dstYoffset * dstRowStride
983 + dstXoffset * dstFormat->TexelBytes;
984 GLint row, col;
985 for (row = 0; row < srcHeight; row++) {
986 const GLubyte *srcUB = (const GLubyte *) src;
987 GLushort *dstUS = (GLushort *) dst;
988 /* check for byteswapped format */
989 if (dstFormat == &_mesa_texformat_rgb565) {
990 for (col = 0; col < srcWidth; col++) {
991 dstUS[col] = PACK_COLOR_565( srcUB[0], srcUB[1], srcUB[2] );
992 srcUB += 3;
993 }
994 }
995 else {
996 for (col = 0; col < srcWidth; col++) {
997 dstUS[col] = PACK_COLOR_565_REV( srcUB[0], srcUB[1], srcUB[2] );
998 srcUB += 3;
999 }
1000 }
1001 dst += dstRowStride;
1002 src += srcRowStride;
1003 }
1004 }
1005 else {
1006 /* general path */
1007 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1008 baseInternalFormat,
1009 dstFormat->BaseFormat,
1010 srcWidth, srcHeight, srcDepth,
1011 srcFormat, srcType, srcAddr,
1012 srcPacking);
1013 const GLchan *src = tempImage;
1014 GLubyte *dstImage = (GLubyte *) dstAddr
1015 + dstZoffset * dstImageStride
1016 + dstYoffset * dstRowStride
1017 + dstXoffset * dstFormat->TexelBytes;
1018 GLint img, row, col;
1019 if (!tempImage)
1020 return GL_FALSE;
1021 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1022 for (img = 0; img < srcDepth; img++) {
1023 GLubyte *dstRow = dstImage;
1024 for (row = 0; row < srcHeight; row++) {
1025 GLushort *dstUS = (GLushort *) dstRow;
1026 /* check for byteswapped format */
1027 if (dstFormat == &_mesa_texformat_rgb565) {
1028 for (col = 0; col < srcWidth; col++) {
1029 dstUS[col] = PACK_COLOR_565( CHAN_TO_UBYTE(src[RCOMP]),
1030 CHAN_TO_UBYTE(src[GCOMP]),
1031 CHAN_TO_UBYTE(src[BCOMP]) );
1032 src += 3;
1033 }
1034 }
1035 else {
1036 for (col = 0; col < srcWidth; col++) {
1037 dstUS[col] = PACK_COLOR_565_REV( CHAN_TO_UBYTE(src[RCOMP]),
1038 CHAN_TO_UBYTE(src[GCOMP]),
1039 CHAN_TO_UBYTE(src[BCOMP]) );
1040 src += 3;
1041 }
1042 }
1043 dstRow += dstRowStride;
1044 }
1045 dstImage += dstImageStride;
1046 }
1047 _mesa_free((void *) tempImage);
1048 }
1049 return GL_TRUE;
1050 }
1051
1052
1053 GLboolean
1054 _mesa_texstore_rgba8888(STORE_PARAMS)
1055 {
1056 const GLuint ui = 1;
1057 const GLubyte littleEndian = *((const GLubyte *) &ui);
1058
1059 (void)littleEndian;
1060 ASSERT(dstFormat == &_mesa_texformat_rgba8888 ||
1061 dstFormat == &_mesa_texformat_rgba8888_rev);
1062 ASSERT(dstFormat->TexelBytes == 4);
1063
1064 if (!ctx->_ImageTransferState &&
1065 !srcPacking->SwapBytes &&
1066 dstFormat == &_mesa_texformat_rgba8888 &&
1067 baseInternalFormat == GL_RGBA &&
1068 ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8) ||
1069 (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8_REV))) {
1070 /* simple memcpy path */
1071 memcpy_texture(ctx, dims,
1072 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1073 dstRowStride, dstImageStride,
1074 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1075 srcAddr, srcPacking);
1076 }
1077 #if 0
1078 else if (!ctx->_ImageTransferState &&
1079 !srcPacking->SwapBytes &&
1080 srcType == GL_UNSIGNED_BYTE &&
1081 dstFormat == &_mesa_texformat_rgba8888 &&
1082 littleEndian &&
1083 /* Three texture formats involved: srcFormat,
1084 * baseInternalFormat and destFormat (GL_RGBA). Only two
1085 * may differ. _mesa_swizzle_ubyte_image can't handle two
1086 * propagations at once correctly. */
1087 (srcFormat == baseInternalFormat ||
1088 baseInternalFormat == GL_RGBA) &&
1089 can_swizzle(srcFormat)) {
1090 GLubyte dstmap[4];
1091
1092 /* dstmap - how to swizzle from GL_RGBA to dst format:
1093 *
1094 * FIXME - add !litteEndian and _rev varients:
1095 */
1096 dstmap[3] = 0;
1097 dstmap[2] = 1;
1098 dstmap[1] = 2;
1099 dstmap[0] = 3;
1100
1101 _mesa_swizzle_ubyte_image(ctx, dims,
1102 srcFormat,
1103 dstmap, 4,
1104 dstAddr, dstXoffset, dstYoffset, dstZoffset,
1105 dstRowStride, dstImageStride,
1106 srcWidth, srcHeight, srcDepth, srcAddr,
1107 srcPacking);
1108 }
1109 #endif
1110 else {
1111 /* general path */
1112 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1113 baseInternalFormat,
1114 dstFormat->BaseFormat,
1115 srcWidth, srcHeight, srcDepth,
1116 srcFormat, srcType, srcAddr,
1117 srcPacking);
1118 const GLchan *src = tempImage;
1119 GLubyte *dstImage = (GLubyte *) dstAddr
1120 + dstZoffset * dstImageStride
1121 + dstYoffset * dstRowStride
1122 + dstXoffset * dstFormat->TexelBytes;
1123 GLint img, row, col;
1124 if (!tempImage)
1125 return GL_FALSE;
1126 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1127 for (img = 0; img < srcDepth; img++) {
1128 GLubyte *dstRow = dstImage;
1129 for (row = 0; row < srcHeight; row++) {
1130 GLuint *dstUI = (GLuint *) dstRow;
1131 if (dstFormat == &_mesa_texformat_rgba8888) {
1132 for (col = 0; col < srcWidth; col++) {
1133 dstUI[col] = PACK_COLOR_8888( CHAN_TO_UBYTE(src[RCOMP]),
1134 CHAN_TO_UBYTE(src[GCOMP]),
1135 CHAN_TO_UBYTE(src[BCOMP]),
1136 CHAN_TO_UBYTE(src[ACOMP]) );
1137 src += 4;
1138 }
1139 }
1140 else {
1141 for (col = 0; col < srcWidth; col++) {
1142 dstUI[col] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src[RCOMP]),
1143 CHAN_TO_UBYTE(src[GCOMP]),
1144 CHAN_TO_UBYTE(src[BCOMP]),
1145 CHAN_TO_UBYTE(src[ACOMP]) );
1146 src += 4;
1147 }
1148 }
1149 dstRow += dstRowStride;
1150 }
1151 dstImage += dstImageStride;
1152 }
1153 _mesa_free((void *) tempImage);
1154 }
1155 return GL_TRUE;
1156 }
1157
1158
1159 GLboolean
1160 _mesa_texstore_argb8888(STORE_PARAMS)
1161 {
1162 const GLuint ui = 1;
1163 const GLubyte littleEndian = *((const GLubyte *) &ui);
1164
1165 ASSERT(dstFormat == &_mesa_texformat_argb8888 ||
1166 dstFormat == &_mesa_texformat_argb8888_rev);
1167 ASSERT(dstFormat->TexelBytes == 4);
1168
1169 if (!ctx->_ImageTransferState &&
1170 !srcPacking->SwapBytes &&
1171 dstFormat == &_mesa_texformat_argb8888 &&
1172 baseInternalFormat == GL_RGBA &&
1173 srcFormat == GL_BGRA &&
1174 ((srcType == GL_UNSIGNED_BYTE && littleEndian) ||
1175 srcType == GL_UNSIGNED_INT_8_8_8_8_REV)) {
1176 /* simple memcpy path (little endian) */
1177 memcpy_texture(ctx, dims,
1178 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1179 dstRowStride, dstImageStride,
1180 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1181 srcAddr, srcPacking);
1182 }
1183 else if (!ctx->_ImageTransferState &&
1184 !srcPacking->SwapBytes &&
1185 dstFormat == &_mesa_texformat_argb8888_rev &&
1186 baseInternalFormat == GL_RGBA &&
1187 srcFormat == GL_BGRA &&
1188 ((srcType == GL_UNSIGNED_BYTE && !littleEndian) ||
1189 srcType == GL_UNSIGNED_INT_8_8_8_8)) {
1190 /* simple memcpy path (big endian) */
1191 memcpy_texture(ctx, dims,
1192 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1193 dstRowStride, dstImageStride,
1194 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1195 srcAddr, srcPacking);
1196 }
1197 else if (!ctx->_ImageTransferState &&
1198 !srcPacking->SwapBytes &&
1199 dstFormat == &_mesa_texformat_argb8888 &&
1200 srcFormat == GL_RGB &&
1201 srcType == GL_UNSIGNED_BYTE) {
1202
1203 int img, row, col;
1204 GLubyte *dstImage = (GLubyte *) dstAddr
1205 + dstZoffset * dstImageStride
1206 + dstYoffset * dstRowStride
1207 + dstXoffset * dstFormat->TexelBytes;
1208 for (img = 0; img < srcDepth; img++) {
1209 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
1210 srcWidth, srcFormat, srcType);
1211 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
1212 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
1213 GLubyte *dstRow = dstImage;
1214 for (row = 0; row < srcHeight; row++) {
1215 for (col = 0; col < srcWidth; col++) {
1216 dstRow[col * 4 + 0] = srcRow[col * 3 + BCOMP];
1217 dstRow[col * 4 + 1] = srcRow[col * 3 + GCOMP];
1218 dstRow[col * 4 + 2] = srcRow[col * 3 + RCOMP];
1219 dstRow[col * 4 + 3] = 0xff;
1220 }
1221 dstRow += dstRowStride;
1222 srcRow += srcRowStride;
1223 }
1224 dstImage += dstImageStride;
1225 }
1226 }
1227 else if (!ctx->_ImageTransferState &&
1228 !srcPacking->SwapBytes &&
1229 dstFormat == &_mesa_texformat_argb8888 &&
1230 srcFormat == GL_RGBA &&
1231 srcType == GL_UNSIGNED_BYTE) {
1232
1233 int img, row, col;
1234 GLubyte *dstImage = (GLubyte *) dstAddr
1235 + dstZoffset * dstImageStride
1236 + dstYoffset * dstRowStride
1237 + dstXoffset * dstFormat->TexelBytes;
1238 for (img = 0; img < srcDepth; img++) {
1239 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
1240 srcWidth, srcFormat, srcType);
1241 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
1242 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
1243 GLubyte *dstRow = dstImage;
1244 for (row = 0; row < srcHeight; row++) {
1245 for (col = 0; col < srcWidth; col++) {
1246 dstRow[col * 4 + 0] = srcRow[col * 4 + BCOMP];
1247 dstRow[col * 4 + 1] = srcRow[col * 4 + GCOMP];
1248 dstRow[col * 4 + 2] = srcRow[col * 4 + RCOMP];
1249 dstRow[col * 4 + 3] = srcRow[col * 4 + ACOMP];
1250 }
1251 dstRow += dstRowStride;
1252 srcRow += srcRowStride;
1253 }
1254 dstImage += dstImageStride;
1255 }
1256 }
1257 else if (!ctx->_ImageTransferState &&
1258 !srcPacking->SwapBytes &&
1259 dstFormat == &_mesa_texformat_argb8888 &&
1260 srcType == GL_UNSIGNED_BYTE &&
1261 littleEndian &&
1262 /* Three texture formats involved: srcFormat,
1263 * baseInternalFormat and destFormat (GL_RGBA). Only two
1264 * may differ. _mesa_swizzle_ubyte_image can't handle two
1265 * propagations at once correctly. */
1266 (srcFormat == baseInternalFormat ||
1267 baseInternalFormat == GL_RGBA) &&
1268 can_swizzle(srcFormat)) {
1269
1270 GLubyte dstmap[4];
1271
1272 /* dstmap - how to swizzle from GL_RGBA to dst format:
1273 */
1274 dstmap[3] = 3; /* alpha */
1275 dstmap[2] = 0; /* red */
1276 dstmap[1] = 1; /* green */
1277 dstmap[0] = 2; /* blue */
1278
1279 _mesa_swizzle_ubyte_image(ctx, dims,
1280 srcFormat,
1281 dstmap, 4,
1282 dstAddr, dstXoffset, dstYoffset, dstZoffset,
1283 dstRowStride, dstImageStride,
1284 srcWidth, srcHeight, srcDepth, srcAddr,
1285 srcPacking);
1286 }
1287 else {
1288 /* general path */
1289 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1290 baseInternalFormat,
1291 dstFormat->BaseFormat,
1292 srcWidth, srcHeight, srcDepth,
1293 srcFormat, srcType, srcAddr,
1294 srcPacking);
1295 const GLchan *src = tempImage;
1296 GLubyte *dstImage = (GLubyte *) dstAddr
1297 + dstZoffset * dstImageStride
1298 + dstYoffset * dstRowStride
1299 + dstXoffset * dstFormat->TexelBytes;
1300 GLint img, row, col;
1301 if (!tempImage)
1302 return GL_FALSE;
1303 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1304 for (img = 0; img < srcDepth; img++) {
1305 GLubyte *dstRow = dstImage;
1306 for (row = 0; row < srcHeight; row++) {
1307 GLuint *dstUI = (GLuint *) dstRow;
1308 if (dstFormat == &_mesa_texformat_argb8888) {
1309 for (col = 0; col < srcWidth; col++) {
1310 dstUI[col] = PACK_COLOR_8888( CHAN_TO_UBYTE(src[ACOMP]),
1311 CHAN_TO_UBYTE(src[RCOMP]),
1312 CHAN_TO_UBYTE(src[GCOMP]),
1313 CHAN_TO_UBYTE(src[BCOMP]) );
1314 src += 4;
1315 }
1316 }
1317 else {
1318 for (col = 0; col < srcWidth; col++) {
1319 dstUI[col] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src[ACOMP]),
1320 CHAN_TO_UBYTE(src[RCOMP]),
1321 CHAN_TO_UBYTE(src[GCOMP]),
1322 CHAN_TO_UBYTE(src[BCOMP]) );
1323 src += 4;
1324 }
1325 }
1326 dstRow += dstRowStride;
1327 }
1328 dstImage += dstImageStride;
1329 }
1330 _mesa_free((void *) tempImage);
1331 }
1332 return GL_TRUE;
1333 }
1334
1335
1336 GLboolean
1337 _mesa_texstore_rgb888(STORE_PARAMS)
1338 {
1339 const GLuint ui = 1;
1340 const GLubyte littleEndian = *((const GLubyte *) &ui);
1341
1342 ASSERT(dstFormat == &_mesa_texformat_rgb888);
1343 ASSERT(dstFormat->TexelBytes == 3);
1344
1345 if (!ctx->_ImageTransferState &&
1346 !srcPacking->SwapBytes &&
1347 baseInternalFormat == GL_RGB &&
1348 srcFormat == GL_BGR &&
1349 srcType == GL_UNSIGNED_BYTE &&
1350 littleEndian) {
1351 /* simple memcpy path */
1352 memcpy_texture(ctx, dims,
1353 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1354 dstRowStride, dstImageStride,
1355 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1356 srcAddr, srcPacking);
1357 }
1358 else if (!ctx->_ImageTransferState &&
1359 !srcPacking->SwapBytes &&
1360 srcFormat == GL_RGBA &&
1361 srcType == GL_UNSIGNED_BYTE) {
1362 /* extract RGB from RGBA */
1363 int img, row, col;
1364 GLubyte *dstImage = (GLubyte *) dstAddr
1365 + dstZoffset * dstImageStride
1366 + dstYoffset * dstRowStride
1367 + dstXoffset * dstFormat->TexelBytes;
1368 for (img = 0; img < srcDepth; img++) {
1369 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
1370 srcWidth, srcFormat, srcType);
1371 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
1372 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
1373 GLubyte *dstRow = dstImage;
1374 for (row = 0; row < srcHeight; row++) {
1375 for (col = 0; col < srcWidth; col++) {
1376 dstRow[col * 3 + 0] = srcRow[col * 4 + BCOMP];
1377 dstRow[col * 3 + 1] = srcRow[col * 4 + GCOMP];
1378 dstRow[col * 3 + 2] = srcRow[col * 4 + RCOMP];
1379 }
1380 dstRow += dstRowStride;
1381 srcRow += srcRowStride;
1382 }
1383 dstImage += dstImageStride;
1384 }
1385 }
1386 else {
1387 /* general path */
1388 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1389 baseInternalFormat,
1390 dstFormat->BaseFormat,
1391 srcWidth, srcHeight, srcDepth,
1392 srcFormat, srcType, srcAddr,
1393 srcPacking);
1394 const GLchan *src = (const GLchan *) tempImage;
1395 GLubyte *dstImage = (GLubyte *) dstAddr
1396 + dstZoffset * dstImageStride
1397 + dstYoffset * dstRowStride
1398 + dstXoffset * dstFormat->TexelBytes;
1399 GLint img, row, col;
1400 if (!tempImage)
1401 return GL_FALSE;
1402 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1403 for (img = 0; img < srcDepth; img++) {
1404 GLubyte *dstRow = dstImage;
1405 for (row = 0; row < srcHeight; row++) {
1406 #if 0
1407 if (littleEndian) {
1408 for (col = 0; col < srcWidth; col++) {
1409 dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[RCOMP]);
1410 dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]);
1411 dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[BCOMP]);
1412 srcUB += 3;
1413 }
1414 }
1415 else {
1416 for (col = 0; col < srcWidth; col++) {
1417 dstRow[col * 3 + 0] = srcUB[BCOMP];
1418 dstRow[col * 3 + 1] = srcUB[GCOMP];
1419 dstRow[col * 3 + 2] = srcUB[RCOMP];
1420 srcUB += 3;
1421 }
1422 }
1423 #else
1424 for (col = 0; col < srcWidth; col++) {
1425 dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[BCOMP]);
1426 dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]);
1427 dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[RCOMP]);
1428 src += 3;
1429 }
1430 #endif
1431 dstRow += dstRowStride;
1432 }
1433 dstImage += dstImageStride;
1434 }
1435 _mesa_free((void *) tempImage);
1436 }
1437 return GL_TRUE;
1438 }
1439
1440
1441 GLboolean
1442 _mesa_texstore_bgr888(STORE_PARAMS)
1443 {
1444 const GLuint ui = 1;
1445 const GLubyte littleEndian = *((const GLubyte *) &ui);
1446
1447 ASSERT(dstFormat == &_mesa_texformat_bgr888);
1448 ASSERT(dstFormat->TexelBytes == 3);
1449
1450 if (!ctx->_ImageTransferState &&
1451 !srcPacking->SwapBytes &&
1452 baseInternalFormat == GL_RGB &&
1453 srcFormat == GL_RGB &&
1454 srcType == GL_UNSIGNED_BYTE &&
1455 littleEndian) {
1456 /* simple memcpy path */
1457 memcpy_texture(ctx, dims,
1458 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1459 dstRowStride, dstImageStride,
1460 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1461 srcAddr, srcPacking);
1462 }
1463 else if (!ctx->_ImageTransferState &&
1464 !srcPacking->SwapBytes &&
1465 srcFormat == GL_RGBA &&
1466 srcType == GL_UNSIGNED_BYTE) {
1467 /* extract BGR from RGBA */
1468 int img, row, col;
1469 GLubyte *dstImage = (GLubyte *) dstAddr
1470 + dstZoffset * dstImageStride
1471 + dstYoffset * dstRowStride
1472 + dstXoffset * dstFormat->TexelBytes;
1473 for (img = 0; img < srcDepth; img++) {
1474 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
1475 srcWidth, srcFormat, srcType);
1476 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
1477 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
1478 GLubyte *dstRow = dstImage;
1479 for (row = 0; row < srcHeight; row++) {
1480 for (col = 0; col < srcWidth; col++) {
1481 dstRow[col * 3 + 0] = srcRow[col * 4 + RCOMP];
1482 dstRow[col * 3 + 1] = srcRow[col * 4 + GCOMP];
1483 dstRow[col * 3 + 2] = srcRow[col * 4 + BCOMP];
1484 }
1485 dstRow += dstRowStride;
1486 srcRow += srcRowStride;
1487 }
1488 dstImage += dstImageStride;
1489 }
1490 }
1491 else {
1492 /* general path */
1493 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1494 baseInternalFormat,
1495 dstFormat->BaseFormat,
1496 srcWidth, srcHeight, srcDepth,
1497 srcFormat, srcType, srcAddr,
1498 srcPacking);
1499 const GLchan *src = (const GLchan *) tempImage;
1500 GLubyte *dstImage = (GLubyte *) dstAddr
1501 + dstZoffset * dstImageStride
1502 + dstYoffset * dstRowStride
1503 + dstXoffset * dstFormat->TexelBytes;
1504 GLint img, row, col;
1505 if (!tempImage)
1506 return GL_FALSE;
1507 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1508 for (img = 0; img < srcDepth; img++) {
1509 GLubyte *dstRow = dstImage;
1510 for (row = 0; row < srcHeight; row++) {
1511 for (col = 0; col < srcWidth; col++) {
1512 dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[RCOMP]);
1513 dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]);
1514 dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[BCOMP]);
1515 src += 3;
1516 }
1517 dstRow += dstRowStride;
1518 }
1519 dstImage += dstImageStride;
1520 }
1521 _mesa_free((void *) tempImage);
1522 }
1523 return GL_TRUE;
1524 }
1525
1526
1527 GLboolean
1528 _mesa_texstore_argb4444(STORE_PARAMS)
1529 {
1530 ASSERT(dstFormat == &_mesa_texformat_argb4444 ||
1531 dstFormat == &_mesa_texformat_argb4444_rev);
1532 ASSERT(dstFormat->TexelBytes == 2);
1533
1534 if (!ctx->_ImageTransferState &&
1535 !srcPacking->SwapBytes &&
1536 dstFormat == &_mesa_texformat_argb4444 &&
1537 baseInternalFormat == GL_RGBA &&
1538 srcFormat == GL_BGRA &&
1539 srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV) {
1540 /* simple memcpy path */
1541 memcpy_texture(ctx, dims,
1542 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1543 dstRowStride, dstImageStride,
1544 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1545 srcAddr, srcPacking);
1546 }
1547 else {
1548 /* general path */
1549 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1550 baseInternalFormat,
1551 dstFormat->BaseFormat,
1552 srcWidth, srcHeight, srcDepth,
1553 srcFormat, srcType, srcAddr,
1554 srcPacking);
1555 const GLchan *src = tempImage;
1556 GLubyte *dstImage = (GLubyte *) dstAddr
1557 + dstZoffset * dstImageStride
1558 + dstYoffset * dstRowStride
1559 + dstXoffset * dstFormat->TexelBytes;
1560 GLint img, row, col;
1561 if (!tempImage)
1562 return GL_FALSE;
1563 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1564 for (img = 0; img < srcDepth; img++) {
1565 GLubyte *dstRow = dstImage;
1566 for (row = 0; row < srcHeight; row++) {
1567 GLushort *dstUS = (GLushort *) dstRow;
1568 if (dstFormat == &_mesa_texformat_argb4444) {
1569 for (col = 0; col < srcWidth; col++) {
1570 dstUS[col] = PACK_COLOR_4444( CHAN_TO_UBYTE(src[ACOMP]),
1571 CHAN_TO_UBYTE(src[RCOMP]),
1572 CHAN_TO_UBYTE(src[GCOMP]),
1573 CHAN_TO_UBYTE(src[BCOMP]) );
1574 src += 4;
1575 }
1576 }
1577 else {
1578 for (col = 0; col < srcWidth; col++) {
1579 dstUS[col] = PACK_COLOR_4444_REV( CHAN_TO_UBYTE(src[ACOMP]),
1580 CHAN_TO_UBYTE(src[RCOMP]),
1581 CHAN_TO_UBYTE(src[GCOMP]),
1582 CHAN_TO_UBYTE(src[BCOMP]) );
1583 src += 4;
1584 }
1585 }
1586 dstRow += dstRowStride;
1587 }
1588 dstImage += dstImageStride;
1589 }
1590 _mesa_free((void *) tempImage);
1591 }
1592 return GL_TRUE;
1593 }
1594
1595
1596
1597 GLboolean
1598 _mesa_texstore_argb1555(STORE_PARAMS)
1599 {
1600 ASSERT(dstFormat == &_mesa_texformat_argb1555 ||
1601 dstFormat == &_mesa_texformat_argb1555_rev);
1602 ASSERT(dstFormat->TexelBytes == 2);
1603
1604 if (!ctx->_ImageTransferState &&
1605 !srcPacking->SwapBytes &&
1606 dstFormat == &_mesa_texformat_argb1555 &&
1607 baseInternalFormat == GL_RGBA &&
1608 srcFormat == GL_BGRA &&
1609 srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV) {
1610 /* simple memcpy path */
1611 memcpy_texture(ctx, dims,
1612 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1613 dstRowStride, dstImageStride,
1614 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1615 srcAddr, srcPacking);
1616 }
1617 else {
1618 /* general path */
1619 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1620 baseInternalFormat,
1621 dstFormat->BaseFormat,
1622 srcWidth, srcHeight, srcDepth,
1623 srcFormat, srcType, srcAddr,
1624 srcPacking);
1625 const GLchan *src =tempImage;
1626 GLubyte *dstImage = (GLubyte *) dstAddr
1627 + dstZoffset * dstImageStride
1628 + dstYoffset * dstRowStride
1629 + dstXoffset * dstFormat->TexelBytes;
1630 GLint img, row, col;
1631 if (!tempImage)
1632 return GL_FALSE;
1633 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1634 for (img = 0; img < srcDepth; img++) {
1635 GLubyte *dstRow = dstImage;
1636 for (row = 0; row < srcHeight; row++) {
1637 GLushort *dstUS = (GLushort *) dstRow;
1638 if (dstFormat == &_mesa_texformat_argb1555) {
1639 for (col = 0; col < srcWidth; col++) {
1640 dstUS[col] = PACK_COLOR_1555( CHAN_TO_UBYTE(src[ACOMP]),
1641 CHAN_TO_UBYTE(src[RCOMP]),
1642 CHAN_TO_UBYTE(src[GCOMP]),
1643 CHAN_TO_UBYTE(src[BCOMP]) );
1644 src += 4;
1645 }
1646 }
1647 else {
1648 for (col = 0; col < srcWidth; col++) {
1649 dstUS[col] = PACK_COLOR_1555_REV( CHAN_TO_UBYTE(src[ACOMP]),
1650 CHAN_TO_UBYTE(src[RCOMP]),
1651 CHAN_TO_UBYTE(src[GCOMP]),
1652 CHAN_TO_UBYTE(src[BCOMP]) );
1653 src += 4;
1654 }
1655 }
1656 dstRow += dstRowStride;
1657 }
1658 dstImage += dstImageStride;
1659 }
1660 _mesa_free((void *) tempImage);
1661 }
1662 return GL_TRUE;
1663 }
1664
1665
1666 GLboolean
1667 _mesa_texstore_al88(STORE_PARAMS)
1668 {
1669 const GLuint ui = 1;
1670 const GLubyte littleEndian = *((const GLubyte *) &ui);
1671
1672 ASSERT(dstFormat == &_mesa_texformat_al88 ||
1673 dstFormat == &_mesa_texformat_al88_rev);
1674 ASSERT(dstFormat->TexelBytes == 2);
1675
1676 if (!ctx->_ImageTransferState &&
1677 !srcPacking->SwapBytes &&
1678 dstFormat == &_mesa_texformat_al88 &&
1679 baseInternalFormat == GL_LUMINANCE_ALPHA &&
1680 srcFormat == GL_LUMINANCE_ALPHA &&
1681 srcType == GL_UNSIGNED_BYTE &&
1682 littleEndian) {
1683 /* simple memcpy path */
1684 memcpy_texture(ctx, dims,
1685 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1686 dstRowStride, dstImageStride,
1687 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1688 srcAddr, srcPacking);
1689 }
1690 else {
1691 /* general path */
1692 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1693 baseInternalFormat,
1694 dstFormat->BaseFormat,
1695 srcWidth, srcHeight, srcDepth,
1696 srcFormat, srcType, srcAddr,
1697 srcPacking);
1698 const GLchan *src = tempImage;
1699 GLubyte *dstImage = (GLubyte *) dstAddr
1700 + dstZoffset * dstImageStride
1701 + dstYoffset * dstRowStride
1702 + dstXoffset * dstFormat->TexelBytes;
1703 GLint img, row, col;
1704 if (!tempImage)
1705 return GL_FALSE;
1706 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1707 for (img = 0; img < srcDepth; img++) {
1708 GLubyte *dstRow = dstImage;
1709 for (row = 0; row < srcHeight; row++) {
1710 GLushort *dstUS = (GLushort *) dstRow;
1711 if (dstFormat == &_mesa_texformat_al88) {
1712 for (col = 0; col < srcWidth; col++) {
1713 /* src[0] is luminance, src[1] is alpha */
1714 dstUS[col] = PACK_COLOR_88( CHAN_TO_UBYTE(src[1]),
1715 CHAN_TO_UBYTE(src[0]) );
1716 src += 2;
1717 }
1718 }
1719 else {
1720 for (col = 0; col < srcWidth; col++) {
1721 /* src[0] is luminance, src[1] is alpha */
1722 dstUS[col] = PACK_COLOR_88_REV( CHAN_TO_UBYTE(src[1]),
1723 CHAN_TO_UBYTE(src[0]) );
1724 src += 2;
1725 }
1726 }
1727 dstRow += dstRowStride;
1728 }
1729 dstImage += dstImageStride;
1730 }
1731 _mesa_free((void *) tempImage);
1732 }
1733 return GL_TRUE;
1734 }
1735
1736
1737 GLboolean
1738 _mesa_texstore_rgb332(STORE_PARAMS)
1739 {
1740 ASSERT(dstFormat == &_mesa_texformat_rgb332);
1741 ASSERT(dstFormat->TexelBytes == 1);
1742
1743 if (!ctx->_ImageTransferState &&
1744 !srcPacking->SwapBytes &&
1745 baseInternalFormat == GL_RGB &&
1746 srcFormat == GL_RGB && srcType == GL_UNSIGNED_BYTE_3_3_2) {
1747 /* simple memcpy path */
1748 memcpy_texture(ctx, dims,
1749 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1750 dstRowStride, dstImageStride,
1751 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1752 srcAddr, srcPacking);
1753 }
1754 else {
1755 /* general path */
1756 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1757 baseInternalFormat,
1758 dstFormat->BaseFormat,
1759 srcWidth, srcHeight, srcDepth,
1760 srcFormat, srcType, srcAddr,
1761 srcPacking);
1762 const GLchan *src = tempImage;
1763 GLubyte *dstImage = (GLubyte *) dstAddr
1764 + dstZoffset * dstImageStride
1765 + dstYoffset * dstRowStride
1766 + dstXoffset * dstFormat->TexelBytes;
1767 GLint img, row, col;
1768 if (!tempImage)
1769 return GL_FALSE;
1770 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1771 for (img = 0; img < srcDepth; img++) {
1772 GLubyte *dstRow = dstImage;
1773 for (row = 0; row < srcHeight; row++) {
1774 for (col = 0; col < srcWidth; col++) {
1775 dstRow[col] = PACK_COLOR_332( CHAN_TO_UBYTE(src[RCOMP]),
1776 CHAN_TO_UBYTE(src[GCOMP]),
1777 CHAN_TO_UBYTE(src[BCOMP]) );
1778 src += 3;
1779 }
1780 dstRow += dstRowStride;
1781 }
1782 dstImage += dstImageStride;
1783 }
1784 _mesa_free((void *) tempImage);
1785 }
1786 return GL_TRUE;
1787 }
1788
1789
1790 /**
1791 * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8.
1792 */
1793 GLboolean
1794 _mesa_texstore_a8(STORE_PARAMS)
1795 {
1796 ASSERT(dstFormat == &_mesa_texformat_a8 ||
1797 dstFormat == &_mesa_texformat_l8 ||
1798 dstFormat == &_mesa_texformat_i8);
1799 ASSERT(dstFormat->TexelBytes == 1);
1800
1801 if (!ctx->_ImageTransferState &&
1802 !srcPacking->SwapBytes &&
1803 baseInternalFormat == srcFormat &&
1804 srcType == GL_UNSIGNED_BYTE) {
1805 /* simple memcpy path */
1806 memcpy_texture(ctx, dims,
1807 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1808 dstRowStride, dstImageStride,
1809 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1810 srcAddr, srcPacking);
1811 }
1812 else {
1813 /* general path */
1814 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1815 baseInternalFormat,
1816 dstFormat->BaseFormat,
1817 srcWidth, srcHeight, srcDepth,
1818 srcFormat, srcType, srcAddr,
1819 srcPacking);
1820 const GLchan *src = tempImage;
1821 GLubyte *dstImage = (GLubyte *) dstAddr
1822 + dstZoffset * dstImageStride
1823 + dstYoffset * dstRowStride
1824 + dstXoffset * dstFormat->TexelBytes;
1825 GLint img, row, col;
1826 if (!tempImage)
1827 return GL_FALSE;
1828 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1829 for (img = 0; img < srcDepth; img++) {
1830 GLubyte *dstRow = dstImage;
1831 for (row = 0; row < srcHeight; row++) {
1832 for (col = 0; col < srcWidth; col++) {
1833 dstRow[col] = CHAN_TO_UBYTE(src[col]);
1834 }
1835 dstRow += dstRowStride;
1836 src += srcWidth;
1837 }
1838 dstImage += dstImageStride;
1839 }
1840 _mesa_free((void *) tempImage);
1841 }
1842 return GL_TRUE;
1843 }
1844
1845
1846
1847 GLboolean
1848 _mesa_texstore_ci8(STORE_PARAMS)
1849 {
1850 (void) dims; (void) baseInternalFormat;
1851 ASSERT(dstFormat == &_mesa_texformat_ci8);
1852 ASSERT(dstFormat->TexelBytes == 1);
1853 ASSERT(baseInternalFormat == GL_COLOR_INDEX);
1854
1855 if (!ctx->_ImageTransferState &&
1856 !srcPacking->SwapBytes &&
1857 srcFormat == GL_COLOR_INDEX &&
1858 srcType == GL_UNSIGNED_BYTE) {
1859 /* simple memcpy path */
1860 memcpy_texture(ctx, dims,
1861 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1862 dstRowStride, dstImageStride,
1863 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1864 srcAddr, srcPacking);
1865 }
1866 else {
1867 /* general path */
1868 GLubyte *dstImage = (GLubyte *) dstAddr
1869 + dstZoffset * dstImageStride
1870 + dstYoffset * dstRowStride
1871 + dstXoffset * dstFormat->TexelBytes;
1872 GLint img, row;
1873 for (img = 0; img < srcDepth; img++) {
1874 GLubyte *dstRow = dstImage;
1875 for (row = 0; row < srcHeight; row++) {
1876 const GLvoid *src = _mesa_image_address(dims, srcPacking,
1877 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
1878 _mesa_unpack_index_span(ctx, srcWidth, GL_UNSIGNED_BYTE, dstRow,
1879 srcType, src, srcPacking,
1880 ctx->_ImageTransferState);
1881 dstRow += dstRowStride;
1882 }
1883 dstImage += dstImageStride;
1884 }
1885 }
1886 return GL_TRUE;
1887 }
1888
1889
1890 /**
1891 * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_rev.
1892 */
1893 GLboolean
1894 _mesa_texstore_ycbcr(STORE_PARAMS)
1895 {
1896 const GLuint ui = 1;
1897 const GLubyte littleEndian = *((const GLubyte *) &ui);
1898 (void) ctx; (void) dims; (void) baseInternalFormat;
1899
1900 ASSERT((dstFormat == &_mesa_texformat_ycbcr) ||
1901 (dstFormat == &_mesa_texformat_ycbcr_rev));
1902 ASSERT(dstFormat->TexelBytes == 2);
1903 ASSERT(ctx->Extensions.MESA_ycbcr_texture);
1904 ASSERT(srcFormat == GL_YCBCR_MESA);
1905 ASSERT((srcType == GL_UNSIGNED_SHORT_8_8_MESA) ||
1906 (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA));
1907 ASSERT(baseInternalFormat == GL_YCBCR_MESA);
1908
1909 /* always just memcpy since no pixel transfer ops apply */
1910 memcpy_texture(ctx, dims,
1911 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1912 dstRowStride, dstImageStride,
1913 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1914 srcAddr, srcPacking);
1915
1916 /* Check if we need byte swapping */
1917 /* XXX the logic here _might_ be wrong */
1918 if (srcPacking->SwapBytes ^
1919 (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA) ^
1920 (dstFormat == &_mesa_texformat_ycbcr_rev) ^
1921 !littleEndian) {
1922 GLushort *pImage = (GLushort *) ((GLubyte *) dstAddr
1923 + dstZoffset * dstImageStride
1924 + dstYoffset * dstRowStride
1925 + dstXoffset * dstFormat->TexelBytes);
1926 GLint img, row;
1927 for (img = 0; img < srcDepth; img++) {
1928 GLushort *pRow = pImage;
1929 for (row = 0; row < srcHeight; row++) {
1930 _mesa_swap2(pRow, srcWidth);
1931 pRow += dstRowStride;
1932 }
1933 pImage += dstImageStride;
1934 }
1935 }
1936 return GL_TRUE;
1937 }
1938
1939
1940
1941
1942 /**
1943 * Store an image in any of the formats:
1944 * _mesa_texformat_rgba_float32
1945 * _mesa_texformat_rgb_float32
1946 * _mesa_texformat_alpha_float32
1947 * _mesa_texformat_luminance_float32
1948 * _mesa_texformat_luminance_alpha_float32
1949 * _mesa_texformat_intensity_float32
1950 */
1951 GLboolean
1952 _mesa_texstore_rgba_float32(STORE_PARAMS)
1953 {
1954 const GLint components = _mesa_components_in_format(baseInternalFormat);
1955
1956 ASSERT(dstFormat == &_mesa_texformat_rgba_float32 ||
1957 dstFormat == &_mesa_texformat_rgb_float32 ||
1958 dstFormat == &_mesa_texformat_alpha_float32 ||
1959 dstFormat == &_mesa_texformat_luminance_float32 ||
1960 dstFormat == &_mesa_texformat_luminance_alpha_float32 ||
1961 dstFormat == &_mesa_texformat_intensity_float32);
1962 ASSERT(baseInternalFormat == GL_RGBA ||
1963 baseInternalFormat == GL_RGB ||
1964 baseInternalFormat == GL_ALPHA ||
1965 baseInternalFormat == GL_LUMINANCE ||
1966 baseInternalFormat == GL_LUMINANCE_ALPHA ||
1967 baseInternalFormat == GL_INTENSITY);
1968 ASSERT(dstFormat->TexelBytes == components * sizeof(GLfloat));
1969
1970 if (!ctx->_ImageTransferState &&
1971 !srcPacking->SwapBytes &&
1972 baseInternalFormat == srcFormat &&
1973 srcType == GL_FLOAT) {
1974 /* simple memcpy path */
1975 memcpy_texture(ctx, dims,
1976 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1977 dstRowStride, dstImageStride,
1978 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1979 srcAddr, srcPacking);
1980 }
1981 else {
1982 /* general path */
1983 const GLfloat *tempImage = make_temp_float_image(ctx, dims,
1984 baseInternalFormat,
1985 dstFormat->BaseFormat,
1986 srcWidth, srcHeight, srcDepth,
1987 srcFormat, srcType, srcAddr,
1988 srcPacking);
1989 const GLfloat *src = tempImage;
1990 GLint bytesPerRow;
1991 GLubyte *dstImage = (GLubyte *) dstAddr
1992 + dstZoffset * dstImageStride
1993 + dstYoffset * dstRowStride
1994 + dstXoffset * dstFormat->TexelBytes;
1995 GLint img, row;
1996 if (!tempImage)
1997 return GL_FALSE;
1998 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1999 bytesPerRow = srcWidth * components * sizeof(GLfloat);
2000 for (img = 0; img < srcDepth; img++) {
2001 GLubyte *dst = dstImage;
2002 for (row = 0; row < srcHeight; row++) {
2003 _mesa_memcpy(dst, src, bytesPerRow);
2004 dst += dstRowStride;
2005 src += srcWidth * components;
2006 }
2007 dstImage += dstImageStride;
2008 }
2009
2010 _mesa_free((void *) tempImage);
2011 }
2012 return GL_TRUE;
2013 }
2014
2015
2016 /**
2017 * As above, but store 16-bit floats.
2018 */
2019 GLboolean
2020 _mesa_texstore_rgba_float16(STORE_PARAMS)
2021 {
2022 const GLint components = _mesa_components_in_format(baseInternalFormat);
2023
2024 ASSERT(dstFormat == &_mesa_texformat_rgba_float16 ||
2025 dstFormat == &_mesa_texformat_rgb_float16 ||
2026 dstFormat == &_mesa_texformat_alpha_float16 ||
2027 dstFormat == &_mesa_texformat_luminance_float16 ||
2028 dstFormat == &_mesa_texformat_luminance_alpha_float16 ||
2029 dstFormat == &_mesa_texformat_intensity_float16);
2030 ASSERT(baseInternalFormat == GL_RGBA ||
2031 baseInternalFormat == GL_RGB ||
2032 baseInternalFormat == GL_ALPHA ||
2033 baseInternalFormat == GL_LUMINANCE ||
2034 baseInternalFormat == GL_LUMINANCE_ALPHA ||
2035 baseInternalFormat == GL_INTENSITY);
2036 ASSERT(dstFormat->TexelBytes == components * sizeof(GLhalfARB));
2037
2038 if (!ctx->_ImageTransferState &&
2039 !srcPacking->SwapBytes &&
2040 baseInternalFormat == srcFormat &&
2041 srcType == GL_HALF_FLOAT_ARB) {
2042 /* simple memcpy path */
2043 memcpy_texture(ctx, dims,
2044 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2045 dstRowStride, dstImageStride,
2046 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2047 srcAddr, srcPacking);
2048 }
2049 else {
2050 /* general path */
2051 const GLfloat *tempImage = make_temp_float_image(ctx, dims,
2052 baseInternalFormat,
2053 dstFormat->BaseFormat,
2054 srcWidth, srcHeight, srcDepth,
2055 srcFormat, srcType, srcAddr,
2056 srcPacking);
2057 const GLfloat *src = tempImage;
2058 GLubyte *dstImage = (GLubyte *) dstAddr
2059 + dstZoffset * dstImageStride
2060 + dstYoffset * dstRowStride
2061 + dstXoffset * dstFormat->TexelBytes;
2062 GLint img, row;
2063 if (!tempImage)
2064 return GL_FALSE;
2065 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
2066 for (img = 0; img < srcDepth; img++) {
2067 GLubyte *dstRow = dstImage;
2068 for (row = 0; row < srcHeight; row++) {
2069 GLhalfARB *dstTexel = (GLhalfARB *) dstRow;
2070 GLint i;
2071 for (i = 0; i < srcWidth * components; i++) {
2072 dstTexel[i] = _mesa_float_to_half(src[i]);
2073 }
2074 dstRow += dstRowStride;
2075 src += srcWidth * components;
2076 }
2077 dstImage += dstImageStride;
2078 }
2079
2080 _mesa_free((void *) tempImage);
2081 }
2082 return GL_TRUE;
2083 }
2084
2085
2086
2087 /**
2088 * Check if an unpack PBO is active prior to fetching a texture image.
2089 * If so, do bounds checking and map the buffer into main memory.
2090 * Any errors detected will be recorded.
2091 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2092 */
2093 const GLvoid *
2094 _mesa_validate_pbo_teximage(GLcontext *ctx, GLuint dimensions,
2095 GLsizei width, GLsizei height, GLsizei depth,
2096 GLenum format, GLenum type, const GLvoid *pixels,
2097 const struct gl_pixelstore_attrib *unpack,
2098 const char *funcName)
2099 {
2100 GLubyte *buf;
2101
2102 if (unpack->BufferObj->Name == 0) {
2103 /* no PBO */
2104 return pixels;
2105 }
2106 if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth,
2107 format, type, pixels)) {
2108 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access");
2109 return NULL;
2110 }
2111
2112 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
2113 GL_READ_ONLY_ARB, unpack->BufferObj);
2114 if (!buf) {
2115 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped");
2116 return NULL;
2117 }
2118
2119 return ADD_POINTERS(buf, pixels);
2120 }
2121
2122
2123 /**
2124 * Check if an unpack PBO is active prior to fetching a compressed texture
2125 * image.
2126 * If so, do bounds checking and map the buffer into main memory.
2127 * Any errors detected will be recorded.
2128 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2129 */
2130 const GLvoid *
2131 _mesa_validate_pbo_compressed_teximage(GLcontext *ctx,
2132 GLsizei imageSize, const GLvoid *pixels,
2133 const struct gl_pixelstore_attrib *packing,
2134 const char *funcName)
2135 {
2136 GLubyte *buf;
2137
2138 if (packing->BufferObj->Name == 0) {
2139 /* not using a PBO - return pointer unchanged */
2140 return pixels;
2141 }
2142 if ((const GLubyte *) pixels + imageSize >
2143 (const GLubyte *)(uintptr_t) packing->BufferObj->Size) {
2144 /* out of bounds read! */
2145 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access");
2146 return NULL;
2147 }
2148
2149 buf = (GLubyte*) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
2150 GL_READ_ONLY_ARB, packing->BufferObj);
2151 if (!buf) {
2152 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped");
2153 return NULL;
2154 }
2155
2156 return ADD_POINTERS(buf, pixels);
2157 }
2158
2159
2160 /**
2161 * This function must be called after either of the validate_pbo_*_teximage()
2162 * functions. It unmaps the PBO buffer if it was mapped earlier.
2163 */
2164 void
2165 _mesa_unmap_teximage_pbo(GLcontext *ctx,
2166 const struct gl_pixelstore_attrib *unpack)
2167 {
2168 if (unpack->BufferObj->Name) {
2169 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
2170 unpack->BufferObj);
2171 }
2172 }
2173
2174
2175 /*
2176 * This is the software fallback for Driver.TexImage1D()
2177 * and Driver.CopyTexImage1D().
2178 * \sa _mesa_store_teximage2d()
2179 */
2180 void
2181 _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level,
2182 GLint internalFormat,
2183 GLint width, GLint border,
2184 GLenum format, GLenum type, const GLvoid *pixels,
2185 const struct gl_pixelstore_attrib *packing,
2186 struct gl_texture_object *texObj,
2187 struct gl_texture_image *texImage)
2188 {
2189 GLint postConvWidth = width;
2190 GLint sizeInBytes;
2191 (void) border;
2192
2193 if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
2194 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2195 }
2196
2197 /* choose the texture format */
2198 assert(ctx->Driver.ChooseTextureFormat);
2199 texImage->TexFormat = ctx->Driver.ChooseTextureFormat(ctx, internalFormat,
2200 format, type);
2201 assert(texImage->TexFormat);
2202 texImage->FetchTexelc = texImage->TexFormat->FetchTexel1D;
2203 texImage->FetchTexelf = texImage->TexFormat->FetchTexel1Df;
2204
2205 /* allocate memory */
2206 if (texImage->IsCompressed)
2207 sizeInBytes = texImage->CompressedSize;
2208 else
2209 sizeInBytes = postConvWidth * texImage->TexFormat->TexelBytes;
2210 texImage->Data = MESA_PBUFFER_ALLOC(sizeInBytes);
2211 if (!texImage->Data) {
2212 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
2213 return;
2214 }
2215
2216 pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type,
2217 pixels, packing, "glTexImage1D");
2218 if (!pixels) {
2219 /* Note: we check for a NULL image pointer here, _after_ we allocated
2220 * memory for the texture. That's what the GL spec calls for.
2221 */
2222 return;
2223 }
2224 else {
2225 const GLint dstRowStride = 0, dstImageStride = 0;
2226 GLboolean success;
2227 ASSERT(texImage->TexFormat->StoreImage);
2228 success = texImage->TexFormat->StoreImage(ctx, 1, texImage->Format,
2229 texImage->TexFormat,
2230 texImage->Data,
2231 0, 0, 0, /* dstX/Y/Zoffset */
2232 dstRowStride, dstImageStride,
2233 width, 1, 1,
2234 format, type, pixels, packing);
2235 if (!success) {
2236 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
2237 }
2238 }
2239
2240 /* GL_SGIS_generate_mipmap */
2241 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
2242 _mesa_generate_mipmap(ctx, target,
2243 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
2244 texObj);
2245 }
2246
2247 _mesa_unmap_teximage_pbo(ctx, packing);
2248 }
2249
2250
2251 /**
2252 * This is the software fallback for Driver.TexImage2D()
2253 * and Driver.CopyTexImage2D().
2254 * We store the image in heap memory. We know nothing about on-board
2255 * VRAM here. But since most DRI drivers rely on keeping a copy of all
2256 * textures in main memory, this routine will typically be used by
2257 * hardware drivers too.
2258 *
2259 * Reasons why a driver might override this function:
2260 * - Special memory allocation needs (VRAM, AGP, etc)
2261 * - Unusual row/image strides or padding
2262 * - Special housekeeping
2263 * - Using VRAM-based Pixel Buffer Objects
2264 */
2265 void
2266 _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level,
2267 GLint internalFormat,
2268 GLint width, GLint height, GLint border,
2269 GLenum format, GLenum type, const void *pixels,
2270 const struct gl_pixelstore_attrib *packing,
2271 struct gl_texture_object *texObj,
2272 struct gl_texture_image *texImage)
2273 {
2274 GLint postConvWidth = width, postConvHeight = height;
2275 GLint texelBytes, sizeInBytes;
2276 (void) border;
2277
2278 if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
2279 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
2280 &postConvHeight);
2281 }
2282
2283 /* choose the texture format */
2284 assert(ctx->Driver.ChooseTextureFormat);
2285 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
2286 internalFormat, format, type);
2287 assert(texImage->TexFormat);
2288 texImage->FetchTexelc = texImage->TexFormat->FetchTexel2D;
2289 texImage->FetchTexelf = texImage->TexFormat->FetchTexel2Df;
2290
2291 texelBytes = texImage->TexFormat->TexelBytes;
2292
2293 /* allocate memory */
2294 if (texImage->IsCompressed)
2295 sizeInBytes = texImage->CompressedSize;
2296 else
2297 sizeInBytes = postConvWidth * postConvHeight * texelBytes;
2298 texImage->Data = MESA_PBUFFER_ALLOC(sizeInBytes);
2299 if (!texImage->Data) {
2300 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
2301 return;
2302 }
2303
2304 pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type,
2305 pixels, packing, "glTexImage2D");
2306 if (!pixels) {
2307 /* Note: we check for a NULL image pointer here, _after_ we allocated
2308 * memory for the texture. That's what the GL spec calls for.
2309 */
2310 return;
2311 }
2312 else {
2313 GLint dstRowStride, dstImageStride = 0;
2314 GLboolean success;
2315 if (texImage->IsCompressed) {
2316 dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,width);
2317 }
2318 else {
2319 dstRowStride = postConvWidth * texImage->TexFormat->TexelBytes;
2320 }
2321 ASSERT(texImage->TexFormat->StoreImage);
2322 success = texImage->TexFormat->StoreImage(ctx, 2, texImage->Format,
2323 texImage->TexFormat,
2324 texImage->Data,
2325 0, 0, 0, /* dstX/Y/Zoffset */
2326 dstRowStride, dstImageStride,
2327 width, height, 1,
2328 format, type, pixels, packing);
2329 if (!success) {
2330 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
2331 }
2332 }
2333
2334 /* GL_SGIS_generate_mipmap */
2335 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
2336 _mesa_generate_mipmap(ctx, target,
2337 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
2338 texObj);
2339 }
2340
2341 _mesa_unmap_teximage_pbo(ctx, packing);
2342 }
2343
2344
2345
2346 /**
2347 * This is the software fallback for Driver.TexImage3D()
2348 * and Driver.CopyTexImage3D().
2349 * \sa _mesa_store_teximage2d()
2350 */
2351 void
2352 _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level,
2353 GLint internalFormat,
2354 GLint width, GLint height, GLint depth, GLint border,
2355 GLenum format, GLenum type, const void *pixels,
2356 const struct gl_pixelstore_attrib *packing,
2357 struct gl_texture_object *texObj,
2358 struct gl_texture_image *texImage)
2359 {
2360 GLint texelBytes, sizeInBytes;
2361 (void) border;
2362
2363 /* choose the texture format */
2364 assert(ctx->Driver.ChooseTextureFormat);
2365 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
2366 internalFormat, format, type);
2367 assert(texImage->TexFormat);
2368 texImage->FetchTexelc = texImage->TexFormat->FetchTexel3D;
2369 texImage->FetchTexelf = texImage->TexFormat->FetchTexel3Df;
2370
2371 texelBytes = texImage->TexFormat->TexelBytes;
2372
2373 /* allocate memory */
2374 if (texImage->IsCompressed)
2375 sizeInBytes = texImage->CompressedSize;
2376 else
2377 sizeInBytes = width * height * depth * texelBytes;
2378 texImage->Data = MESA_PBUFFER_ALLOC(sizeInBytes);
2379 if (!texImage->Data) {
2380 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
2381 return;
2382 }
2383
2384 pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, format,
2385 type, pixels, packing, "glTexImage3D");
2386 if (!pixels) {
2387 /* Note: we check for a NULL image pointer here, _after_ we allocated
2388 * memory for the texture. That's what the GL spec calls for.
2389 */
2390 return;
2391 }
2392 else {
2393 GLint dstRowStride, dstImageStride;
2394 GLboolean success;
2395 if (texImage->IsCompressed) {
2396 dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,width);
2397 dstImageStride = 0;
2398 }
2399 else {
2400 dstRowStride = width * texImage->TexFormat->TexelBytes;
2401 dstImageStride = dstRowStride * height;
2402 }
2403 ASSERT(texImage->TexFormat->StoreImage);
2404 success = texImage->TexFormat->StoreImage(ctx, 3, texImage->Format,
2405 texImage->TexFormat,
2406 texImage->Data,
2407 0, 0, 0, /* dstX/Y/Zoffset */
2408 dstRowStride, dstImageStride,
2409 width, height, depth,
2410 format, type, pixels, packing);
2411 if (!success) {
2412 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
2413 }
2414 }
2415
2416 /* GL_SGIS_generate_mipmap */
2417 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
2418 _mesa_generate_mipmap(ctx, target,
2419 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
2420 texObj);
2421 }
2422
2423 _mesa_unmap_teximage_pbo(ctx, packing);
2424 }
2425
2426
2427
2428
2429 /*
2430 * This is the software fallback for Driver.TexSubImage1D()
2431 * and Driver.CopyTexSubImage1D().
2432 */
2433 void
2434 _mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level,
2435 GLint xoffset, GLint width,
2436 GLenum format, GLenum type, const void *pixels,
2437 const struct gl_pixelstore_attrib *packing,
2438 struct gl_texture_object *texObj,
2439 struct gl_texture_image *texImage)
2440 {
2441 pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type,
2442 pixels, packing, "glTexSubImage1D");
2443 if (!pixels)
2444 return;
2445
2446 {
2447 const GLint dstRowStride = 0, dstImageStride = 0;
2448 GLboolean success;
2449 ASSERT(texImage->TexFormat->StoreImage);
2450 success = texImage->TexFormat->StoreImage(ctx, 1, texImage->Format,
2451 texImage->TexFormat,
2452 texImage->Data,
2453 xoffset, 0, 0, /* offsets */
2454 dstRowStride, dstImageStride,
2455 width, 1, 1,
2456 format, type, pixels, packing);
2457 if (!success) {
2458 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
2459 }
2460 }
2461
2462 /* GL_SGIS_generate_mipmap */
2463 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
2464 _mesa_generate_mipmap(ctx, target,
2465 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
2466 texObj);
2467 }
2468
2469 _mesa_unmap_teximage_pbo(ctx, packing);
2470 }
2471
2472
2473
2474 /**
2475 * This is the software fallback for Driver.TexSubImage2D()
2476 * and Driver.CopyTexSubImage2D().
2477 */
2478 void
2479 _mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level,
2480 GLint xoffset, GLint yoffset,
2481 GLint width, GLint height,
2482 GLenum format, GLenum type, const void *pixels,
2483 const struct gl_pixelstore_attrib *packing,
2484 struct gl_texture_object *texObj,
2485 struct gl_texture_image *texImage)
2486 {
2487 pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type,
2488 pixels, packing, "glTexSubImage2D");
2489 if (!pixels)
2490 return;
2491
2492 {
2493 GLint dstRowStride = 0, dstImageStride = 0;
2494 GLboolean success;
2495 if (texImage->IsCompressed) {
2496 dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
2497 texImage->Width);
2498 }
2499 else {
2500 dstRowStride = texImage->Width * texImage->TexFormat->TexelBytes;
2501 }
2502 ASSERT(texImage->TexFormat->StoreImage);
2503 success = texImage->TexFormat->StoreImage(ctx, 2, texImage->Format,
2504 texImage->TexFormat,
2505 texImage->Data,
2506 xoffset, yoffset, 0,
2507 dstRowStride, dstImageStride,
2508 width, height, 1,
2509 format, type, pixels, packing);
2510 if (!success) {
2511 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
2512 }
2513 }
2514
2515 /* GL_SGIS_generate_mipmap */
2516 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
2517 _mesa_generate_mipmap(ctx, target,
2518 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
2519 texObj);
2520 }
2521
2522 _mesa_unmap_teximage_pbo(ctx, packing);
2523 }
2524
2525
2526 /*
2527 * This is the software fallback for Driver.TexSubImage3D().
2528 * and Driver.CopyTexSubImage3D().
2529 */
2530 void
2531 _mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level,
2532 GLint xoffset, GLint yoffset, GLint zoffset,
2533 GLint width, GLint height, GLint depth,
2534 GLenum format, GLenum type, const void *pixels,
2535 const struct gl_pixelstore_attrib *packing,
2536 struct gl_texture_object *texObj,
2537 struct gl_texture_image *texImage)
2538 {
2539 pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, format,
2540 type, pixels, packing,
2541 "glTexSubImage3D");
2542 if (!pixels)
2543 return;
2544
2545 {
2546 GLint dstRowStride, dstImageStride;
2547 GLboolean success;
2548 if (texImage->IsCompressed) {
2549 dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
2550 texImage->Width);
2551 dstImageStride = 0; /* XXX fix */
2552 }
2553 else {
2554 dstRowStride = texImage->Width * texImage->TexFormat->TexelBytes;
2555 dstImageStride = dstRowStride * texImage->Height;
2556 }
2557 ASSERT(texImage->TexFormat->StoreImage);
2558 success = texImage->TexFormat->StoreImage(ctx, 3, texImage->Format,
2559 texImage->TexFormat,
2560 texImage->Data,
2561 xoffset, yoffset, zoffset,
2562 dstRowStride, dstImageStride,
2563 width, height, depth,
2564 format, type, pixels, packing);
2565 if (!success) {
2566 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D");
2567 }
2568 }
2569
2570 /* GL_SGIS_generate_mipmap */
2571 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
2572 _mesa_generate_mipmap(ctx, target,
2573 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
2574 texObj);
2575 }
2576
2577 _mesa_unmap_teximage_pbo(ctx, packing);
2578 }
2579
2580
2581 /*
2582 * Fallback for Driver.CompressedTexImage1D()
2583 */
2584 void
2585 _mesa_store_compressed_teximage1d(GLcontext *ctx, GLenum target, GLint level,
2586 GLint internalFormat,
2587 GLint width, GLint border,
2588 GLsizei imageSize, const GLvoid *data,
2589 struct gl_texture_object *texObj,
2590 struct gl_texture_image *texImage)
2591 {
2592 /* this space intentionally left blank */
2593 (void) ctx;
2594 (void) target; (void) level;
2595 (void) internalFormat;
2596 (void) width; (void) border;
2597 (void) imageSize; (void) data;
2598 (void) texObj;
2599 (void) texImage;
2600 }
2601
2602
2603
2604 /*
2605 * Fallback for Driver.CompressedTexImage2D()
2606 */
2607 void
2608 _mesa_store_compressed_teximage2d(GLcontext *ctx, GLenum target, GLint level,
2609 GLint internalFormat,
2610 GLint width, GLint height, GLint border,
2611 GLsizei imageSize, const GLvoid *data,
2612 struct gl_texture_object *texObj,
2613 struct gl_texture_image *texImage)
2614 {
2615 (void) width; (void) height; (void) border;
2616
2617 /* This is pretty simple, basically just do a memcpy without worrying
2618 * about the usual image unpacking or image transfer operations.
2619 */
2620 ASSERT(texObj);
2621 ASSERT(texImage);
2622 ASSERT(texImage->Width > 0);
2623 ASSERT(texImage->Height > 0);
2624 ASSERT(texImage->Depth == 1);
2625 ASSERT(texImage->Data == NULL); /* was freed in glCompressedTexImage2DARB */
2626
2627 /* choose the texture format */
2628 assert(ctx->Driver.ChooseTextureFormat);
2629 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
2630 internalFormat, 0, 0);
2631 assert(texImage->TexFormat);
2632 texImage->FetchTexelc = texImage->TexFormat->FetchTexel2D;
2633 texImage->FetchTexelf = texImage->TexFormat->FetchTexel2Df;
2634
2635 /* allocate storage */
2636 texImage->Data = MESA_PBUFFER_ALLOC(imageSize);
2637 if (!texImage->Data) {
2638 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB");
2639 return;
2640 }
2641
2642 data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data,
2643 &ctx->Unpack,
2644 "glCompressedTexImage2D");
2645 if (!data)
2646 return;
2647
2648 /* copy the data */
2649 ASSERT(texImage->CompressedSize == (GLuint) imageSize);
2650 MEMCPY(texImage->Data, data, imageSize);
2651
2652 /* GL_SGIS_generate_mipmap */
2653 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
2654 _mesa_generate_mipmap(ctx, target,
2655 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
2656 texObj);
2657 }
2658
2659 _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack);
2660 }
2661
2662
2663
2664 /*
2665 * Fallback for Driver.CompressedTexImage3D()
2666 */
2667 void
2668 _mesa_store_compressed_teximage3d(GLcontext *ctx, GLenum target, GLint level,
2669 GLint internalFormat,
2670 GLint width, GLint height, GLint depth,
2671 GLint border,
2672 GLsizei imageSize, const GLvoid *data,
2673 struct gl_texture_object *texObj,
2674 struct gl_texture_image *texImage)
2675 {
2676 /* this space intentionally left blank */
2677 (void) ctx;
2678 (void) target; (void) level;
2679 (void) internalFormat;
2680 (void) width; (void) height; (void) depth;
2681 (void) border;
2682 (void) imageSize; (void) data;
2683 (void) texObj;
2684 (void) texImage;
2685 }
2686
2687
2688
2689 /**
2690 * Fallback for Driver.CompressedTexSubImage1D()
2691 */
2692 void
2693 _mesa_store_compressed_texsubimage1d(GLcontext *ctx, GLenum target,
2694 GLint level,
2695 GLint xoffset, GLsizei width,
2696 GLenum format,
2697 GLsizei imageSize, const GLvoid *data,
2698 struct gl_texture_object *texObj,
2699 struct gl_texture_image *texImage)
2700 {
2701 /* this space intentionally left blank */
2702 (void) ctx;
2703 (void) target; (void) level;
2704 (void) xoffset; (void) width;
2705 (void) format;
2706 (void) imageSize; (void) data;
2707 (void) texObj;
2708 (void) texImage;
2709 }
2710
2711
2712 /**
2713 * Fallback for Driver.CompressedTexSubImage2D()
2714 */
2715 void
2716 _mesa_store_compressed_texsubimage2d(GLcontext *ctx, GLenum target,
2717 GLint level,
2718 GLint xoffset, GLint yoffset,
2719 GLsizei width, GLsizei height,
2720 GLenum format,
2721 GLsizei imageSize, const GLvoid *data,
2722 struct gl_texture_object *texObj,
2723 struct gl_texture_image *texImage)
2724 {
2725 GLint bytesPerRow, destRowStride, srcRowStride;
2726 GLint i, rows;
2727 GLubyte *dest;
2728 const GLubyte *src;
2729 (void) format;
2730
2731 /* these should have been caught sooner */
2732 ASSERT((width & 3) == 0 || width == 2 || width == 1);
2733 ASSERT((height & 3) == 0 || height == 2 || height == 1);
2734 ASSERT((xoffset & 3) == 0);
2735 ASSERT((yoffset & 3) == 0);
2736
2737 data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data,
2738 &ctx->Unpack,
2739 "glCompressedTexSubImage2D");
2740 if (!data)
2741 return;
2742
2743 srcRowStride = _mesa_compressed_row_stride(texImage->IntFormat, width);
2744 src = (const GLubyte *) data;
2745
2746 destRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
2747 texImage->Width);
2748 dest = _mesa_compressed_image_address(xoffset, yoffset, 0,
2749 texImage->IntFormat,
2750 texImage->Width,
2751 (GLubyte*) texImage->Data);
2752
2753 bytesPerRow = srcRowStride;
2754 rows = height / 4;
2755
2756 for (i = 0; i < rows; i++) {
2757 MEMCPY(dest, src, bytesPerRow);
2758 dest += destRowStride;
2759 src += srcRowStride;
2760 }
2761
2762 /* GL_SGIS_generate_mipmap */
2763 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
2764 _mesa_generate_mipmap(ctx, target,
2765 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
2766 texObj);
2767 }
2768
2769 _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack);
2770 }
2771
2772
2773 /**
2774 * Fallback for Driver.CompressedTexSubImage3D()
2775 */
2776 void
2777 _mesa_store_compressed_texsubimage3d(GLcontext *ctx, GLenum target,
2778 GLint level,
2779 GLint xoffset, GLint yoffset, GLint zoffset,
2780 GLsizei width, GLsizei height, GLsizei depth,
2781 GLenum format,
2782 GLsizei imageSize, const GLvoid *data,
2783 struct gl_texture_object *texObj,
2784 struct gl_texture_image *texImage)
2785 {
2786 /* this space intentionally left blank */
2787 (void) ctx;
2788 (void) target; (void) level;
2789 (void) xoffset; (void) yoffset; (void) zoffset;
2790 (void) width; (void) height; (void) depth;
2791 (void) format;
2792 (void) imageSize; (void) data;
2793 (void) texObj;
2794 (void) texImage;
2795 }
2796
2797
2798 /*
2799 * Average together two rows of a source image to produce a single new
2800 * row in the dest image. It's legal for the two source rows to point
2801 * to the same data. The source width must be equal to either the
2802 * dest width or two times the dest width.
2803 */
2804 static void
2805 do_row(const struct gl_texture_format *format, GLint srcWidth,
2806 const GLvoid *srcRowA, const GLvoid *srcRowB,
2807 GLint dstWidth, GLvoid *dstRow)
2808 {
2809 const GLuint k0 = (srcWidth == dstWidth) ? 0 : 1;
2810 const GLuint colStride = (srcWidth == dstWidth) ? 1 : 2;
2811
2812 /* This assertion is no longer valid with non-power-of-2 textures
2813 assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
2814 */
2815
2816 switch (format->MesaFormat) {
2817 case MESA_FORMAT_RGBA:
2818 {
2819 GLuint i, j, k;
2820 const GLchan (*rowA)[4] = (const GLchan (*)[4]) srcRowA;
2821 const GLchan (*rowB)[4] = (const GLchan (*)[4]) srcRowB;
2822 GLchan (*dst)[4] = (GLchan (*)[4]) dstRow;
2823 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
2824 i++, j += colStride, k += colStride) {
2825 dst[i][0] = (rowA[j][0] + rowA[k][0] +
2826 rowB[j][0] + rowB[k][0]) / 4;
2827 dst[i][1] = (rowA[j][1] + rowA[k][1] +
2828 rowB[j][1] + rowB[k][1]) / 4;
2829 dst[i][2] = (rowA[j][2] + rowA[k][2] +
2830 rowB[j][2] + rowB[k][2]) / 4;
2831 dst[i][3] = (rowA[j][3] + rowA[k][3] +
2832 rowB[j][3] + rowB[k][3]) / 4;
2833 }
2834 }
2835 return;
2836 case MESA_FORMAT_RGB:
2837 {
2838 GLuint i, j, k;
2839 const GLchan (*rowA)[3] = (const GLchan (*)[3]) srcRowA;
2840 const GLchan (*rowB)[3] = (const GLchan (*)[3]) srcRowB;
2841 GLchan (*dst)[3] = (GLchan (*)[3]) dstRow;
2842 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
2843 i++, j += colStride, k += colStride) {
2844 dst[i][0] = (rowA[j][0] + rowA[k][0] +
2845 rowB[j][0] + rowB[k][0]) / 4;
2846 dst[i][1] = (rowA[j][1] + rowA[k][1] +
2847 rowB[j][1] + rowB[k][1]) / 4;
2848 dst[i][2] = (rowA[j][2] + rowA[k][2] +
2849 rowB[j][2] + rowB[k][2]) / 4;
2850 }
2851 }
2852 return;
2853 case MESA_FORMAT_ALPHA:
2854 case MESA_FORMAT_LUMINANCE:
2855 case MESA_FORMAT_INTENSITY:
2856 {
2857 GLuint i, j, k;
2858 const GLchan *rowA = (const GLchan *) srcRowA;
2859 const GLchan *rowB = (const GLchan *) srcRowB;
2860 GLchan *dst = (GLchan *) dstRow;
2861 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
2862 i++, j += colStride, k += colStride) {
2863 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
2864 }
2865 }
2866 return;
2867 case MESA_FORMAT_LUMINANCE_ALPHA:
2868 {
2869 GLuint i, j, k;
2870 const GLchan (*rowA)[2] = (const GLchan (*)[2]) srcRowA;
2871 const GLchan (*rowB)[2] = (const GLchan (*)[2]) srcRowB;
2872 GLchan (*dst)[2] = (GLchan (*)[2]) dstRow;
2873 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
2874 i++, j += colStride, k += colStride) {
2875 dst[i][0] = (rowA[j][0] + rowA[k][0] +
2876 rowB[j][0] + rowB[k][0]) / 4;
2877 dst[i][1] = (rowA[j][1] + rowA[k][1] +
2878 rowB[j][1] + rowB[k][1]) / 4;
2879 }
2880 }
2881 return;
2882 case MESA_FORMAT_DEPTH_COMPONENT_FLOAT32:
2883 {
2884 GLuint i, j, k;
2885 const GLfloat *rowA = (const GLfloat *) srcRowA;
2886 const GLfloat *rowB = (const GLfloat *) srcRowB;
2887 GLfloat *dst = (GLfloat *) dstRow;
2888 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
2889 i++, j += colStride, k += colStride) {
2890 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F;
2891 }
2892 }
2893 return;
2894 case MESA_FORMAT_DEPTH_COMPONENT16:
2895 {
2896 GLuint i, j, k;
2897 const GLushort *rowA = (const GLushort *) srcRowA;
2898 const GLushort *rowB = (const GLushort *) srcRowB;
2899 GLushort *dst = (GLushort *) dstRow;
2900 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
2901 i++, j += colStride, k += colStride) {
2902 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
2903 }
2904 }
2905 return;
2906 /* Begin hardware formats */
2907 case MESA_FORMAT_RGBA8888:
2908 case MESA_FORMAT_RGBA8888_REV:
2909 case MESA_FORMAT_ARGB8888:
2910 case MESA_FORMAT_ARGB8888_REV:
2911 {
2912 GLuint i, j, k;
2913 const GLubyte (*rowA)[4] = (const GLubyte (*)[4]) srcRowA;
2914 const GLubyte (*rowB)[4] = (const GLubyte (*)[4]) srcRowB;
2915 GLubyte (*dst)[4] = (GLubyte (*)[4]) dstRow;
2916 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
2917 i++, j += colStride, k += colStride) {
2918 dst[i][0] = (rowA[j][0] + rowA[k][0] +
2919 rowB[j][0] + rowB[k][0]) / 4;
2920 dst[i][1] = (rowA[j][1] + rowA[k][1] +
2921 rowB[j][1] + rowB[k][1]) / 4;
2922 dst[i][2] = (rowA[j][2] + rowA[k][2] +
2923 rowB[j][2] + rowB[k][2]) / 4;
2924 dst[i][3] = (rowA[j][3] + rowA[k][3] +
2925 rowB[j][3] + rowB[k][3]) / 4;
2926 }
2927 }
2928 return;
2929 case MESA_FORMAT_RGB888:
2930 case MESA_FORMAT_BGR888:
2931 {
2932 GLuint i, j, k;
2933 const GLubyte (*rowA)[3] = (const GLubyte (*)[3]) srcRowA;
2934 const GLubyte (*rowB)[3] = (const GLubyte (*)[3]) srcRowB;
2935 GLubyte (*dst)[3] = (GLubyte (*)[3]) dstRow;
2936 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
2937 i++, j += colStride, k += colStride) {
2938 dst[i][0] = (rowA[j][0] + rowA[k][0] +
2939 rowB[j][0] + rowB[k][0]) / 4;
2940 dst[i][1] = (rowA[j][1] + rowA[k][1] +
2941 rowB[j][1] + rowB[k][1]) / 4;
2942 dst[i][2] = (rowA[j][2] + rowA[k][2] +
2943 rowB[j][2] + rowB[k][2]) / 4;
2944 }
2945 }
2946 return;
2947 case MESA_FORMAT_RGB565:
2948 case MESA_FORMAT_RGB565_REV:
2949 {
2950 GLuint i, j, k;
2951 const GLushort *rowA = (const GLushort *) srcRowA;
2952 const GLushort *rowB = (const GLushort *) srcRowB;
2953 GLushort *dst = (GLushort *) dstRow;
2954 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
2955 i++, j += colStride, k += colStride) {
2956 const GLint rowAr0 = rowA[j] & 0x1f;
2957 const GLint rowAr1 = rowA[k] & 0x1f;
2958 const GLint rowBr0 = rowB[j] & 0x1f;
2959 const GLint rowBr1 = rowB[k] & 0x1f;
2960 const GLint rowAg0 = (rowA[j] >> 5) & 0x3f;
2961 const GLint rowAg1 = (rowA[k] >> 5) & 0x3f;
2962 const GLint rowBg0 = (rowB[j] >> 5) & 0x3f;
2963 const GLint rowBg1 = (rowB[k] >> 5) & 0x3f;
2964 const GLint rowAb0 = (rowA[j] >> 11) & 0x1f;
2965 const GLint rowAb1 = (rowA[k] >> 11) & 0x1f;
2966 const GLint rowBb0 = (rowB[j] >> 11) & 0x1f;
2967 const GLint rowBb1 = (rowB[k] >> 11) & 0x1f;
2968 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
2969 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
2970 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
2971 dst[i] = (blue << 11) | (green << 5) | red;
2972 }
2973 }
2974 return;
2975 case MESA_FORMAT_ARGB4444:
2976 case MESA_FORMAT_ARGB4444_REV:
2977 {
2978 GLuint i, j, k;
2979 const GLushort *rowA = (const GLushort *) srcRowA;
2980 const GLushort *rowB = (const GLushort *) srcRowB;
2981 GLushort *dst = (GLushort *) dstRow;
2982 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
2983 i++, j += colStride, k += colStride) {
2984 const GLint rowAr0 = rowA[j] & 0xf;
2985 const GLint rowAr1 = rowA[k] & 0xf;
2986 const GLint rowBr0 = rowB[j] & 0xf;
2987 const GLint rowBr1 = rowB[k] & 0xf;
2988 const GLint rowAg0 = (rowA[j] >> 4) & 0xf;
2989 const GLint rowAg1 = (rowA[k] >> 4) & 0xf;
2990 const GLint rowBg0 = (rowB[j] >> 4) & 0xf;
2991 const GLint rowBg1 = (rowB[k] >> 4) & 0xf;
2992 const GLint rowAb0 = (rowA[j] >> 8) & 0xf;
2993 const GLint rowAb1 = (rowA[k] >> 8) & 0xf;
2994 const GLint rowBb0 = (rowB[j] >> 8) & 0xf;
2995 const GLint rowBb1 = (rowB[k] >> 8) & 0xf;
2996 const GLint rowAa0 = (rowA[j] >> 12) & 0xf;
2997 const GLint rowAa1 = (rowA[k] >> 12) & 0xf;
2998 const GLint rowBa0 = (rowB[j] >> 12) & 0xf;
2999 const GLint rowBa1 = (rowB[k] >> 12) & 0xf;
3000 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
3001 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
3002 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
3003 const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
3004 dst[i] = (alpha << 12) | (blue << 8) | (green << 4) | red;
3005 }
3006 }
3007 return;
3008 case MESA_FORMAT_ARGB1555:
3009 case MESA_FORMAT_ARGB1555_REV: /* XXX broken? */
3010 {
3011 GLuint i, j, k;
3012 const GLushort *rowA = (const GLushort *) srcRowA;
3013 const GLushort *rowB = (const GLushort *) srcRowB;
3014 GLushort *dst = (GLushort *) dstRow;
3015 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3016 i++, j += colStride, k += colStride) {
3017 const GLint rowAr0 = rowA[j] & 0x1f;
3018 const GLint rowAr1 = rowA[k] & 0x1f;
3019 const GLint rowBr0 = rowB[j] & 0x1f;
3020 const GLint rowBr1 = rowB[k] & 0xf;
3021 const GLint rowAg0 = (rowA[j] >> 5) & 0x1f;
3022 const GLint rowAg1 = (rowA[k] >> 5) & 0x1f;
3023 const GLint rowBg0 = (rowB[j] >> 5) & 0x1f;
3024 const GLint rowBg1 = (rowB[k] >> 5) & 0x1f;
3025 const GLint rowAb0 = (rowA[j] >> 10) & 0x1f;
3026 const GLint rowAb1 = (rowA[k] >> 10) & 0x1f;
3027 const GLint rowBb0 = (rowB[j] >> 10) & 0x1f;
3028 const GLint rowBb1 = (rowB[k] >> 10) & 0x1f;
3029 const GLint rowAa0 = (rowA[j] >> 15) & 0x1;
3030 const GLint rowAa1 = (rowA[k] >> 15) & 0x1;
3031 const GLint rowBa0 = (rowB[j] >> 15) & 0x1;
3032 const GLint rowBa1 = (rowB[k] >> 15) & 0x1;
3033 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
3034 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
3035 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
3036 const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
3037 dst[i] = (alpha << 15) | (blue << 10) | (green << 5) | red;
3038 }
3039 }
3040 return;
3041 case MESA_FORMAT_AL88:
3042 case MESA_FORMAT_AL88_REV:
3043 {
3044 GLuint i, j, k;
3045 const GLubyte (*rowA)[2] = (const GLubyte (*)[2]) srcRowA;
3046 const GLubyte (*rowB)[2] = (const GLubyte (*)[2]) srcRowB;
3047 GLubyte (*dst)[2] = (GLubyte (*)[2]) dstRow;
3048 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3049 i++, j += colStride, k += colStride) {
3050 dst[i][0] = (rowA[j][0] + rowA[k][0] +
3051 rowB[j][0] + rowB[k][0]) >> 2;
3052 dst[i][1] = (rowA[j][1] + rowA[k][1] +
3053 rowB[j][1] + rowB[k][1]) >> 2;
3054 }
3055 }
3056 return;
3057 case MESA_FORMAT_RGB332:
3058 {
3059 GLuint i, j, k;
3060 const GLubyte *rowA = (const GLubyte *) srcRowA;
3061 const GLubyte *rowB = (const GLubyte *) srcRowB;
3062 GLubyte *dst = (GLubyte *) dstRow;
3063 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3064 i++, j += colStride, k += colStride) {
3065 const GLint rowAr0 = rowA[j] & 0x3;
3066 const GLint rowAr1 = rowA[k] & 0x3;
3067 const GLint rowBr0 = rowB[j] & 0x3;
3068 const GLint rowBr1 = rowB[k] & 0x3;
3069 const GLint rowAg0 = (rowA[j] >> 2) & 0x7;
3070 const GLint rowAg1 = (rowA[k] >> 2) & 0x7;
3071 const GLint rowBg0 = (rowB[j] >> 2) & 0x7;
3072 const GLint rowBg1 = (rowB[k] >> 2) & 0x7;
3073 const GLint rowAb0 = (rowA[j] >> 5) & 0x7;
3074 const GLint rowAb1 = (rowA[k] >> 5) & 0x7;
3075 const GLint rowBb0 = (rowB[j] >> 5) & 0x7;
3076 const GLint rowBb1 = (rowB[k] >> 5) & 0x7;
3077 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
3078 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
3079 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
3080 dst[i] = (blue << 5) | (green << 2) | red;
3081 }
3082 }
3083 return;
3084 case MESA_FORMAT_A8:
3085 case MESA_FORMAT_L8:
3086 case MESA_FORMAT_I8:
3087 case MESA_FORMAT_CI8:
3088 {
3089 GLuint i, j, k;
3090 const GLubyte *rowA = (const GLubyte *) srcRowA;
3091 const GLubyte *rowB = (const GLubyte *) srcRowB;
3092 GLubyte *dst = (GLubyte *) dstRow;
3093 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3094 i++, j += colStride, k += colStride) {
3095 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) >> 2;
3096 }
3097 }
3098 return;
3099 case MESA_FORMAT_RGBA_FLOAT32:
3100 {
3101 GLuint i, j, k;
3102 const GLfloat (*rowA)[4] = (const GLfloat (*)[4]) srcRowA;
3103 const GLfloat (*rowB)[4] = (const GLfloat (*)[4]) srcRowB;
3104 GLfloat (*dst)[4] = (GLfloat (*)[4]) dstRow;
3105 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3106 i++, j += colStride, k += colStride) {
3107 dst[i][0] = (rowA[j][0] + rowA[k][0] +
3108 rowB[j][0] + rowB[k][0]) * 0.25F;
3109 dst[i][1] = (rowA[j][1] + rowA[k][1] +
3110 rowB[j][1] + rowB[k][1]) * 0.25F;
3111 dst[i][2] = (rowA[j][2] + rowA[k][2] +
3112 rowB[j][2] + rowB[k][2]) * 0.25F;
3113 dst[i][3] = (rowA[j][3] + rowA[k][3] +
3114 rowB[j][3] + rowB[k][3]) * 0.25F;
3115 }
3116 }
3117 return;
3118 case MESA_FORMAT_RGBA_FLOAT16:
3119 {
3120 GLuint i, j, k, comp;
3121 const GLhalfARB (*rowA)[4] = (const GLhalfARB (*)[4]) srcRowA;
3122 const GLhalfARB (*rowB)[4] = (const GLhalfARB (*)[4]) srcRowB;
3123 GLhalfARB (*dst)[4] = (GLhalfARB (*)[4]) dstRow;
3124 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3125 i++, j += colStride, k += colStride) {
3126 for (comp = 0; comp < 4; comp++) {
3127 GLfloat aj, ak, bj, bk;
3128 aj = _mesa_half_to_float(rowA[j][comp]);
3129 ak = _mesa_half_to_float(rowA[k][comp]);
3130 bj = _mesa_half_to_float(rowB[j][comp]);
3131 bk = _mesa_half_to_float(rowB[k][comp]);
3132 dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
3133 }
3134 }
3135 }
3136 return;
3137 case MESA_FORMAT_RGB_FLOAT32:
3138 {
3139 GLuint i, j, k;
3140 const GLfloat (*rowA)[3] = (const GLfloat (*)[3]) srcRowA;
3141 const GLfloat (*rowB)[3] = (const GLfloat (*)[3]) srcRowB;
3142 GLfloat (*dst)[3] = (GLfloat (*)[3]) dstRow;
3143 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3144 i++, j += colStride, k += colStride) {
3145 dst[i][0] = (rowA[j][0] + rowA[k][0] +
3146 rowB[j][0] + rowB[k][0]) * 0.25F;
3147 dst[i][1] = (rowA[j][1] + rowA[k][1] +
3148 rowB[j][1] + rowB[k][1]) * 0.25F;
3149 dst[i][2] = (rowA[j][2] + rowA[k][2] +
3150 rowB[j][2] + rowB[k][2]) * 0.25F;
3151 }
3152 }
3153 return;
3154 case MESA_FORMAT_RGB_FLOAT16:
3155 {
3156 GLuint i, j, k, comp;
3157 const GLhalfARB (*rowA)[3] = (const GLhalfARB (*)[3]) srcRowA;
3158 const GLhalfARB (*rowB)[3] = (const GLhalfARB (*)[3]) srcRowB;
3159 GLhalfARB (*dst)[3] = (GLhalfARB (*)[3]) dstRow;
3160 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3161 i++, j += colStride, k += colStride) {
3162 for (comp = 0; comp < 3; comp++) {
3163 GLfloat aj, ak, bj, bk;
3164 aj = _mesa_half_to_float(rowA[j][comp]);
3165 ak = _mesa_half_to_float(rowA[k][comp]);
3166 bj = _mesa_half_to_float(rowB[j][comp]);
3167 bk = _mesa_half_to_float(rowB[k][comp]);
3168 dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
3169 }
3170 }
3171 }
3172 return;
3173 case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32:
3174 {
3175 GLuint i, j, k;
3176 const GLfloat (*rowA)[2] = (const GLfloat (*)[2]) srcRowA;
3177 const GLfloat (*rowB)[2] = (const GLfloat (*)[2]) srcRowB;
3178 GLfloat (*dst)[2] = (GLfloat (*)[2]) dstRow;
3179 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3180 i++, j += colStride, k += colStride) {
3181 dst[i][0] = (rowA[j][0] + rowA[k][0] +
3182 rowB[j][0] + rowB[k][0]) * 0.25F;
3183 dst[i][1] = (rowA[j][1] + rowA[k][1] +
3184 rowB[j][1] + rowB[k][1]) * 0.25F;
3185 }
3186 }
3187 return;
3188 case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16:
3189 {
3190 GLuint i, j, k, comp;
3191 const GLhalfARB (*rowA)[2] = (const GLhalfARB (*)[2]) srcRowA;
3192 const GLhalfARB (*rowB)[2] = (const GLhalfARB (*)[2]) srcRowB;
3193 GLhalfARB (*dst)[2] = (GLhalfARB (*)[2]) dstRow;
3194 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3195 i++, j += colStride, k += colStride) {
3196 for (comp = 0; comp < 2; comp++) {
3197 GLfloat aj, ak, bj, bk;
3198 aj = _mesa_half_to_float(rowA[j][comp]);
3199 ak = _mesa_half_to_float(rowA[k][comp]);
3200 bj = _mesa_half_to_float(rowB[j][comp]);
3201 bk = _mesa_half_to_float(rowB[k][comp]);
3202 dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
3203 }
3204 }
3205 }
3206 return;
3207 case MESA_FORMAT_ALPHA_FLOAT32:
3208 case MESA_FORMAT_LUMINANCE_FLOAT32:
3209 case MESA_FORMAT_INTENSITY_FLOAT32:
3210 {
3211 GLuint i, j, k;
3212 const GLfloat *rowA = (const GLfloat *) srcRowA;
3213 const GLfloat *rowB = (const GLfloat *) srcRowB;
3214 GLfloat *dst = (GLfloat *) dstRow;
3215 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3216 i++, j += colStride, k += colStride) {
3217 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F;
3218 }
3219 }
3220 return;
3221 case MESA_FORMAT_ALPHA_FLOAT16:
3222 case MESA_FORMAT_LUMINANCE_FLOAT16:
3223 case MESA_FORMAT_INTENSITY_FLOAT16:
3224 {
3225 GLuint i, j, k;
3226 const GLhalfARB *rowA = (const GLhalfARB *) srcRowA;
3227 const GLhalfARB *rowB = (const GLhalfARB *) srcRowB;
3228 GLhalfARB *dst = (GLhalfARB *) dstRow;
3229 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3230 i++, j += colStride, k += colStride) {
3231 GLfloat aj, ak, bj, bk;
3232 aj = _mesa_half_to_float(rowA[j]);
3233 ak = _mesa_half_to_float(rowA[k]);
3234 bj = _mesa_half_to_float(rowB[j]);
3235 bk = _mesa_half_to_float(rowB[k]);
3236 dst[i] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
3237 }
3238 }
3239 return;
3240
3241 default:
3242 _mesa_problem(NULL, "bad format in do_row()");
3243 }
3244 }
3245
3246
3247 /*
3248 * These functions generate a 1/2-size mipmap image from a source image.
3249 * Texture borders are handled by copying or averaging the source image's
3250 * border texels, depending on the scale-down factor.
3251 */
3252
3253 static void
3254 make_1d_mipmap(const struct gl_texture_format *format, GLint border,
3255 GLint srcWidth, const GLubyte *srcPtr,
3256 GLint dstWidth, GLubyte *dstPtr)
3257 {
3258 const GLint bpt = format->TexelBytes;
3259 const GLubyte *src;
3260 GLubyte *dst;
3261
3262 /* skip the border pixel, if any */
3263 src = srcPtr + border * bpt;
3264 dst = dstPtr + border * bpt;
3265
3266 /* we just duplicate the input row, kind of hack, saves code */
3267 do_row(format, srcWidth - 2 * border, src, src,
3268 dstWidth - 2 * border, dst);
3269
3270 if (border) {
3271 /* copy left-most pixel from source */
3272 MEMCPY(dstPtr, srcPtr, bpt);
3273 /* copy right-most pixel from source */
3274 MEMCPY(dstPtr + (dstWidth - 1) * bpt,
3275 srcPtr + (srcWidth - 1) * bpt,
3276 bpt);
3277 }
3278 }
3279
3280
3281 static void
3282 make_2d_mipmap(const struct gl_texture_format *format, GLint border,
3283 GLint srcWidth, GLint srcHeight, const GLubyte *srcPtr,
3284 GLint dstWidth, GLint dstHeight, GLubyte *dstPtr)
3285 {
3286 const GLint bpt = format->TexelBytes;
3287 const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */
3288 const GLint dstWidthNB = dstWidth - 2 * border;
3289 const GLint dstHeightNB = dstHeight - 2 * border;
3290 const GLint srcRowStride = bpt * srcWidth;
3291 const GLint dstRowStride = bpt * dstWidth;
3292 const GLubyte *srcA, *srcB;
3293 GLubyte *dst;
3294 GLint row;
3295
3296 /* Compute src and dst pointers, skipping any border */
3297 srcA = srcPtr + border * ((srcWidth + 1) * bpt);
3298 if (srcHeight > 1)
3299 srcB = srcA + srcRowStride;
3300 else
3301 srcB = srcA;
3302 dst = dstPtr + border * ((dstWidth + 1) * bpt);
3303
3304 for (row = 0; row < dstHeightNB; row++) {
3305 do_row(format, srcWidthNB, srcA, srcB,
3306 dstWidthNB, dst);
3307 srcA += 2 * srcRowStride;
3308 srcB += 2 * srcRowStride;
3309 dst += dstRowStride;
3310 }
3311
3312 /* This is ugly but probably won't be used much */
3313 if (border > 0) {
3314 /* fill in dest border */
3315 /* lower-left border pixel */
3316 MEMCPY(dstPtr, srcPtr, bpt);
3317 /* lower-right border pixel */
3318 MEMCPY(dstPtr + (dstWidth - 1) * bpt,
3319 srcPtr + (srcWidth - 1) * bpt, bpt);
3320 /* upper-left border pixel */
3321 MEMCPY(dstPtr + dstWidth * (dstHeight - 1) * bpt,
3322 srcPtr + srcWidth * (srcHeight - 1) * bpt, bpt);
3323 /* upper-right border pixel */
3324 MEMCPY(dstPtr + (dstWidth * dstHeight - 1) * bpt,
3325 srcPtr + (srcWidth * srcHeight - 1) * bpt, bpt);
3326 /* lower border */
3327 do_row(format, srcWidthNB,
3328 srcPtr + bpt,
3329 srcPtr + bpt,
3330 dstWidthNB, dstPtr + bpt);
3331 /* upper border */
3332 do_row(format, srcWidthNB,
3333 srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
3334 srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
3335 dstWidthNB,
3336 dstPtr + (dstWidth * (dstHeight - 1) + 1) * bpt);
3337 /* left and right borders */
3338 if (srcHeight == dstHeight) {
3339 /* copy border pixel from src to dst */
3340 for (row = 1; row < srcHeight; row++) {
3341 MEMCPY(dstPtr + dstWidth * row * bpt,
3342 srcPtr + srcWidth * row * bpt, bpt);
3343 MEMCPY(dstPtr + (dstWidth * row + dstWidth - 1) * bpt,
3344 srcPtr + (srcWidth * row + srcWidth - 1) * bpt, bpt);
3345 }
3346 }
3347 else {
3348 /* average two src pixels each dest pixel */
3349 for (row = 0; row < dstHeightNB; row += 2) {
3350 do_row(format, 1,
3351 srcPtr + (srcWidth * (row * 2 + 1)) * bpt,
3352 srcPtr + (srcWidth * (row * 2 + 2)) * bpt,
3353 1, dstPtr + (dstWidth * row + 1) * bpt);
3354 do_row(format, 1,
3355 srcPtr + (srcWidth * (row * 2 + 1) + srcWidth - 1) * bpt,
3356 srcPtr + (srcWidth * (row * 2 + 2) + srcWidth - 1) * bpt,
3357 1, dstPtr + (dstWidth * row + 1 + dstWidth - 1) * bpt);
3358 }
3359 }
3360 }
3361 }
3362
3363
3364 static void
3365 make_3d_mipmap(const struct gl_texture_format *format, GLint border,
3366 GLint srcWidth, GLint srcHeight, GLint srcDepth,
3367 const GLubyte *srcPtr,
3368 GLint dstWidth, GLint dstHeight, GLint dstDepth,
3369 GLubyte *dstPtr)
3370 {
3371 const GLint bpt = format->TexelBytes;
3372 const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */
3373 const GLint srcDepthNB = srcDepth - 2 * border;
3374 const GLint dstWidthNB = dstWidth - 2 * border;
3375 const GLint dstHeightNB = dstHeight - 2 * border;
3376 const GLint dstDepthNB = dstDepth - 2 * border;
3377 GLvoid *tmpRowA, *tmpRowB;
3378 GLint img, row;
3379 GLint bytesPerSrcImage, bytesPerDstImage;
3380 GLint bytesPerSrcRow, bytesPerDstRow;
3381 GLint srcImageOffset, srcRowOffset;
3382
3383 (void) srcDepthNB; /* silence warnings */
3384
3385 /* Need two temporary row buffers */
3386 tmpRowA = MALLOC(srcWidth * bpt);
3387 if (!tmpRowA)
3388 return;
3389 tmpRowB = MALLOC(srcWidth * bpt);
3390 if (!tmpRowB) {
3391 FREE(tmpRowA);
3392 return;
3393 }
3394
3395 bytesPerSrcImage = srcWidth * srcHeight * bpt;
3396 bytesPerDstImage = dstWidth * dstHeight * bpt;
3397
3398 bytesPerSrcRow = srcWidth * bpt;
3399 bytesPerDstRow = dstWidth * bpt;
3400
3401 /* Offset between adjacent src images to be averaged together */
3402 srcImageOffset = (srcDepth == dstDepth) ? 0 : bytesPerSrcImage;
3403
3404 /* Offset between adjacent src rows to be averaged together */
3405 srcRowOffset = (srcHeight == dstHeight) ? 0 : srcWidth * bpt;
3406
3407 /*
3408 * Need to average together up to 8 src pixels for each dest pixel.
3409 * Break that down into 3 operations:
3410 * 1. take two rows from source image and average them together.
3411 * 2. take two rows from next source image and average them together.
3412 * 3. take the two averaged rows and average them for the final dst row.
3413 */
3414
3415 /*
3416 _mesa_printf("mip3d %d x %d x %d -> %d x %d x %d\n",
3417 srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth);
3418 */
3419
3420 for (img = 0; img < dstDepthNB; img++) {
3421 /* first source image pointer, skipping border */
3422 const GLubyte *imgSrcA = srcPtr
3423 + (bytesPerSrcImage + bytesPerSrcRow + border) * bpt * border
3424 + img * (bytesPerSrcImage + srcImageOffset);
3425 /* second source image pointer, skipping border */
3426 const GLubyte *imgSrcB = imgSrcA + srcImageOffset;
3427 /* address of the dest image, skipping border */
3428 GLubyte *imgDst = dstPtr
3429 + (bytesPerDstImage + bytesPerDstRow + border) * bpt * border
3430 + img * bytesPerDstImage;
3431
3432 /* setup the four source row pointers and the dest row pointer */
3433 const GLubyte *srcImgARowA = imgSrcA;
3434 const GLubyte *srcImgARowB = imgSrcA + srcRowOffset;
3435 const GLubyte *srcImgBRowA = imgSrcB;
3436 const GLubyte *srcImgBRowB = imgSrcB + srcRowOffset;
3437 GLubyte *dstImgRow = imgDst;
3438
3439 for (row = 0; row < dstHeightNB; row++) {
3440 /* Average together two rows from first src image */
3441 do_row(format, srcWidthNB, srcImgARowA, srcImgARowB,
3442 srcWidthNB, tmpRowA);
3443 /* Average together two rows from second src image */
3444 do_row(format, srcWidthNB, srcImgBRowA, srcImgBRowB,
3445 srcWidthNB, tmpRowB);
3446 /* Average together the temp rows to make the final row */
3447 do_row(format, srcWidthNB, tmpRowA, tmpRowB,
3448 dstWidthNB, dstImgRow);
3449 /* advance to next rows */
3450 srcImgARowA += bytesPerSrcRow + srcRowOffset;
3451 srcImgARowB += bytesPerSrcRow + srcRowOffset;
3452 srcImgBRowA += bytesPerSrcRow + srcRowOffset;
3453 srcImgBRowB += bytesPerSrcRow + srcRowOffset;
3454 dstImgRow += bytesPerDstRow;
3455 }
3456 }
3457
3458 FREE(tmpRowA);
3459 FREE(tmpRowB);
3460
3461 /* Luckily we can leverage the make_2d_mipmap() function here! */
3462 if (border > 0) {
3463 /* do front border image */
3464 make_2d_mipmap(format, 1, srcWidth, srcHeight, srcPtr,
3465 dstWidth, dstHeight, dstPtr);
3466 /* do back border image */
3467 make_2d_mipmap(format, 1, srcWidth, srcHeight,
3468 srcPtr + bytesPerSrcImage * (srcDepth - 1),
3469 dstWidth, dstHeight,
3470 dstPtr + bytesPerDstImage * (dstDepth - 1));
3471 /* do four remaining border edges that span the image slices */
3472 if (srcDepth == dstDepth) {
3473 /* just copy border pixels from src to dst */
3474 for (img = 0; img < dstDepthNB; img++) {
3475 const GLubyte *src;
3476 GLubyte *dst;
3477
3478 /* do border along [img][row=0][col=0] */
3479 src = srcPtr + (img + 1) * bytesPerSrcImage;
3480 dst = dstPtr + (img + 1) * bytesPerDstImage;
3481 MEMCPY(dst, src, bpt);
3482
3483 /* do border along [img][row=dstHeight-1][col=0] */
3484 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
3485 + (srcHeight - 1) * bytesPerSrcRow;
3486 dst = dstPtr + (img + 1) * bytesPerDstImage
3487 + (dstHeight - 1) * bytesPerDstRow;
3488 MEMCPY(dst, src, bpt);
3489
3490 /* do border along [img][row=0][col=dstWidth-1] */
3491 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
3492 + (srcWidth - 1) * bpt;
3493 dst = dstPtr + (img + 1) * bytesPerDstImage
3494 + (dstWidth - 1) * bpt;
3495 MEMCPY(dst, src, bpt);
3496
3497 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
3498 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
3499 + (bytesPerSrcImage - bpt);
3500 dst = dstPtr + (img + 1) * bytesPerDstImage
3501 + (bytesPerDstImage - bpt);
3502 MEMCPY(dst, src, bpt);
3503 }
3504 }
3505 else {
3506 /* average border pixels from adjacent src image pairs */
3507 ASSERT(srcDepthNB == 2 * dstDepthNB);
3508 for (img = 0; img < dstDepthNB; img++) {
3509 const GLubyte *src;
3510 GLubyte *dst;
3511
3512 /* do border along [img][row=0][col=0] */
3513 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage;
3514 dst = dstPtr + (img + 1) * bytesPerDstImage;
3515 do_row(format, 1, src, src + srcImageOffset, 1, dst);
3516
3517 /* do border along [img][row=dstHeight-1][col=0] */
3518 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
3519 + (srcHeight - 1) * bytesPerSrcRow;
3520 dst = dstPtr + (img + 1) * bytesPerDstImage
3521 + (dstHeight - 1) * bytesPerDstRow;
3522 do_row(format, 1, src, src + srcImageOffset, 1, dst);
3523
3524 /* do border along [img][row=0][col=dstWidth-1] */
3525 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
3526 + (srcWidth - 1) * bpt;
3527 dst = dstPtr + (img + 1) * bytesPerDstImage
3528 + (dstWidth - 1) * bpt;
3529 do_row(format, 1, src, src + srcImageOffset, 1, dst);
3530
3531 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
3532 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
3533 + (bytesPerSrcImage - bpt);
3534 dst = dstPtr + (img + 1) * bytesPerDstImage
3535 + (bytesPerDstImage - bpt);
3536 do_row(format, 1, src, src + srcImageOffset, 1, dst);
3537 }
3538 }
3539 }
3540 }
3541
3542
3543 /*
3544 * For GL_SGIX_generate_mipmap:
3545 * Generate a complete set of mipmaps from texObj's base-level image.
3546 * Stop at texObj's MaxLevel or when we get to the 1x1 texture.
3547 */
3548 void
3549 _mesa_generate_mipmap(GLcontext *ctx, GLenum target,
3550 const struct gl_texture_unit *texUnit,
3551 struct gl_texture_object *texObj)
3552 {
3553 const struct gl_texture_image *srcImage;
3554 const struct gl_texture_format *convertFormat;
3555 const GLubyte *srcData = NULL;
3556 GLubyte *dstData = NULL;
3557 GLint level, maxLevels;
3558
3559 ASSERT(texObj);
3560 /* XXX choose cube map face here??? */
3561 srcImage = texObj->Image[0][texObj->BaseLevel];
3562 ASSERT(srcImage);
3563
3564 maxLevels = _mesa_max_texture_levels(ctx, texObj->Target);
3565 ASSERT(maxLevels > 0); /* bad target */
3566
3567 /* Find convertFormat - the format that do_row() will process */
3568 if (srcImage->IsCompressed) {
3569 /* setup for compressed textures */
3570 GLuint row;
3571 GLint components, size;
3572 GLchan *dst;
3573
3574 assert(texObj->Target == GL_TEXTURE_2D);
3575
3576 if (srcImage->Format == GL_RGB) {
3577 convertFormat = &_mesa_texformat_rgb;
3578 components = 3;
3579 }
3580 else if (srcImage->Format == GL_RGBA) {
3581 convertFormat = &_mesa_texformat_rgba;
3582 components = 4;
3583 }
3584 else {
3585 _mesa_problem(ctx, "bad srcImage->Format in _mesa_generate_mipmaps");
3586 return;
3587 }
3588
3589 /* allocate storage for uncompressed GL_RGB or GL_RGBA images */
3590 size = _mesa_bytes_per_pixel(srcImage->Format, CHAN_TYPE)
3591 * srcImage->Width * srcImage->Height * srcImage->Depth + 20;
3592 /* 20 extra bytes, just be safe when calling last FetchTexel */
3593 srcData = (GLubyte *) MALLOC(size);
3594 if (!srcData) {
3595 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
3596 return;
3597 }
3598 dstData = (GLubyte *) MALLOC(size / 2); /* 1/4 would probably be OK */
3599 if (!dstData) {
3600 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
3601 FREE((void *) srcData);
3602 return;
3603 }
3604
3605 /* decompress base image here */
3606 dst = (GLchan *) srcData;
3607 for (row = 0; row < srcImage->Height; row++) {
3608 GLuint col;
3609 for (col = 0; col < srcImage->Width; col++) {
3610 srcImage->FetchTexelc(srcImage, col, row, 0, dst);
3611 dst += components;
3612 }
3613 }
3614 }
3615 else {
3616 /* uncompressed */
3617 convertFormat = srcImage->TexFormat;
3618 }
3619
3620 for (level = texObj->BaseLevel; level < texObj->MaxLevel
3621 && level < maxLevels - 1; level++) {
3622 /* generate image[level+1] from image[level] */
3623 const struct gl_texture_image *srcImage;
3624 struct gl_texture_image *dstImage;
3625 GLint srcWidth, srcHeight, srcDepth;
3626 GLint dstWidth, dstHeight, dstDepth;
3627 GLint border, bytesPerTexel;
3628
3629 /* get src image parameters */
3630 srcImage = _mesa_select_tex_image(ctx, texUnit, target, level);
3631 ASSERT(srcImage);
3632 srcWidth = srcImage->Width;
3633 srcHeight = srcImage->Height;
3634 srcDepth = srcImage->Depth;
3635 border = srcImage->Border;
3636
3637 /* compute next (level+1) image size */
3638 if (srcWidth - 2 * border > 1) {
3639 dstWidth = (srcWidth - 2 * border) / 2 + 2 * border;
3640 }
3641 else {
3642 dstWidth = srcWidth; /* can't go smaller */
3643 }
3644 if (srcHeight - 2 * border > 1) {
3645 dstHeight = (srcHeight - 2 * border) / 2 + 2 * border;
3646 }
3647 else {
3648 dstHeight = srcHeight; /* can't go smaller */
3649 }
3650 if (srcDepth - 2 * border > 1) {
3651 dstDepth = (srcDepth - 2 * border) / 2 + 2 * border;
3652 }
3653 else {
3654 dstDepth = srcDepth; /* can't go smaller */
3655 }
3656
3657 if (dstWidth == srcWidth &&
3658 dstHeight == srcHeight &&
3659 dstDepth == srcDepth) {
3660 /* all done */
3661 if (srcImage->IsCompressed) {
3662 FREE((void *) srcData);
3663 FREE(dstData);
3664 }
3665 return;
3666 }
3667
3668 /* get dest gl_texture_image */
3669 dstImage = _mesa_get_tex_image(ctx, texUnit, target, level + 1);
3670 if (!dstImage) {
3671 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
3672 return;
3673 }
3674
3675 /* Free old image data */
3676 if (dstImage->Data)
3677 MESA_PBUFFER_FREE(dstImage->Data);
3678
3679 /* initialize new image */
3680 _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight,
3681 dstDepth, border, srcImage->IntFormat);
3682 dstImage->DriverData = NULL;
3683 dstImage->TexFormat = srcImage->TexFormat;
3684 dstImage->FetchTexelc = srcImage->FetchTexelc;
3685 dstImage->FetchTexelf = srcImage->FetchTexelf;
3686 ASSERT(dstImage->TexFormat);
3687 ASSERT(dstImage->FetchTexelc);
3688 ASSERT(dstImage->FetchTexelf);
3689
3690 /* Alloc new teximage data buffer.
3691 * Setup src and dest data pointers.
3692 */
3693 if (dstImage->IsCompressed) {
3694 ASSERT(dstImage->CompressedSize > 0); /* set by init_teximage_fields*/
3695 dstImage->Data = MESA_PBUFFER_ALLOC(dstImage->CompressedSize);
3696 if (!dstImage->Data) {
3697 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
3698 return;
3699 }
3700 /* srcData and dstData are already set */
3701 ASSERT(srcData);
3702 ASSERT(dstData);
3703 }
3704 else {
3705 bytesPerTexel = srcImage->TexFormat->TexelBytes;
3706 ASSERT(dstWidth * dstHeight * dstDepth * bytesPerTexel > 0);
3707 dstImage->Data = MESA_PBUFFER_ALLOC(dstWidth * dstHeight * dstDepth
3708 * bytesPerTexel);
3709 if (!dstImage->Data) {
3710 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
3711 return;
3712 }
3713 srcData = (const GLubyte *) srcImage->Data;
3714 dstData = (GLubyte *) dstImage->Data;
3715 }
3716
3717 /*
3718 * We use simple 2x2 averaging to compute the next mipmap level.
3719 */
3720 switch (target) {
3721 case GL_TEXTURE_1D:
3722 make_1d_mipmap(convertFormat, border,
3723 srcWidth, srcData,
3724 dstWidth, dstData);
3725 break;
3726 case GL_TEXTURE_2D:
3727 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
3728 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
3729 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
3730 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
3731 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
3732 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
3733 make_2d_mipmap(convertFormat, border,
3734 srcWidth, srcHeight, srcData,
3735 dstWidth, dstHeight, dstData);
3736 break;
3737 case GL_TEXTURE_3D:
3738 make_3d_mipmap(convertFormat, border,
3739 srcWidth, srcHeight, srcDepth, srcData,
3740 dstWidth, dstHeight, dstDepth, dstData);
3741 break;
3742 case GL_TEXTURE_RECTANGLE_NV:
3743 /* no mipmaps, do nothing */
3744 break;
3745 default:
3746 _mesa_problem(ctx, "bad dimensions in _mesa_generate_mipmaps");
3747 return;
3748 }
3749
3750 if (dstImage->IsCompressed) {
3751 GLubyte *temp;
3752 /* compress image from dstData into dstImage->Data */
3753 const GLenum srcFormat = convertFormat->BaseFormat;
3754 GLint dstRowStride = _mesa_compressed_row_stride(srcImage->IntFormat,
3755 dstWidth);
3756 ASSERT(srcFormat == GL_RGB || srcFormat == GL_RGBA);
3757 dstImage->TexFormat->StoreImage(ctx, 2, dstImage->Format,
3758 dstImage->TexFormat,
3759 dstImage->Data,
3760 0, 0, 0, /* dstX/Y/Zoffset */
3761 dstRowStride, 0, /* strides */
3762 dstWidth, dstHeight, 1, /* size */
3763 srcFormat, CHAN_TYPE,
3764 dstData, /* src data, actually */
3765 &ctx->DefaultPacking);
3766 /* swap src and dest pointers */
3767 temp = (GLubyte *) srcData;
3768 srcData = dstData;
3769 dstData = temp;
3770 }
3771
3772 } /* loop over mipmap levels */
3773 }
3774
3775
3776 /**
3777 * Helper function for drivers which need to rescale texture images to
3778 * certain aspect ratios.
3779 * Nearest filtering only (for broken hardware that can't support
3780 * all aspect ratios). This can be made a lot faster, but I don't
3781 * really care enough...
3782 */
3783 void
3784 _mesa_rescale_teximage2d (GLuint bytesPerPixel,
3785 GLuint srcStrideInPixels,
3786 GLuint dstRowStride,
3787 GLint srcWidth, GLint srcHeight,
3788 GLint dstWidth, GLint dstHeight,
3789 const GLvoid *srcImage, GLvoid *dstImage)
3790 {
3791 GLint row, col;
3792
3793 #define INNER_LOOP( TYPE, HOP, WOP ) \
3794 for ( row = 0 ; row < dstHeight ; row++ ) { \
3795 GLint srcRow = row HOP hScale; \
3796 for ( col = 0 ; col < dstWidth ; col++ ) { \
3797 GLint srcCol = col WOP wScale; \
3798 dst[col] = src[srcRow * srcStrideInPixels + srcCol]; \
3799 } \
3800 dst = (TYPE *) ((GLubyte *) dst + dstRowStride); \
3801 } \
3802
3803 #define RESCALE_IMAGE( TYPE ) \
3804 do { \
3805 const TYPE *src = (const TYPE *)srcImage; \
3806 TYPE *dst = (TYPE *)dstImage; \
3807 \
3808 if ( srcHeight < dstHeight ) { \
3809 const GLint hScale = dstHeight / srcHeight; \
3810 if ( srcWidth < dstWidth ) { \
3811 const GLint wScale = dstWidth / srcWidth; \
3812 INNER_LOOP( TYPE, /, / ); \
3813 } \
3814 else { \
3815 const GLint wScale = srcWidth / dstWidth; \
3816 INNER_LOOP( TYPE, /, * ); \
3817 } \
3818 } \
3819 else { \
3820 const GLint hScale = srcHeight / dstHeight; \
3821 if ( srcWidth < dstWidth ) { \
3822 const GLint wScale = dstWidth / srcWidth; \
3823 INNER_LOOP( TYPE, *, / ); \
3824 } \
3825 else { \
3826 const GLint wScale = srcWidth / dstWidth; \
3827 INNER_LOOP( TYPE, *, * ); \
3828 } \
3829 } \
3830 } while (0)
3831
3832 switch ( bytesPerPixel ) {
3833 case 4:
3834 RESCALE_IMAGE( GLuint );
3835 break;
3836
3837 case 2:
3838 RESCALE_IMAGE( GLushort );
3839 break;
3840
3841 case 1:
3842 RESCALE_IMAGE( GLubyte );
3843 break;
3844 default:
3845 _mesa_problem(NULL,"unexpected bytes/pixel in _mesa_rescale_teximage2d");
3846 }
3847 }
3848
3849
3850 /**
3851 * Upscale an image by replication, not (typical) stretching.
3852 * We use this when the image width or height is less than a
3853 * certain size (4, 8) and we need to upscale an image.
3854 */
3855 void
3856 _mesa_upscale_teximage2d (GLsizei inWidth, GLsizei inHeight,
3857 GLsizei outWidth, GLsizei outHeight,
3858 GLint comps, const GLchan *src, GLint srcRowStride,
3859 GLchan *dest )
3860 {
3861 GLint i, j, k;
3862
3863 ASSERT(outWidth >= inWidth);
3864 ASSERT(outHeight >= inHeight);
3865 #if 0
3866 ASSERT(inWidth == 1 || inWidth == 2 || inHeight == 1 || inHeight == 2);
3867 ASSERT((outWidth & 3) == 0);
3868 ASSERT((outHeight & 3) == 0);
3869 #endif
3870
3871 for (i = 0; i < outHeight; i++) {
3872 const GLint ii = i % inHeight;
3873 for (j = 0; j < outWidth; j++) {
3874 const GLint jj = j % inWidth;
3875 for (k = 0; k < comps; k++) {
3876 dest[(i * outWidth + j) * comps + k]
3877 = src[ii * srcRowStride + jj * comps + k];
3878 }
3879 }
3880 }
3881 }
3882
3883
3884
3885 /**
3886 * This is the software fallback for Driver.GetTexImage().
3887 * All error checking will have been done before this routine is called.
3888 */
3889 void
3890 _mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level,
3891 GLenum format, GLenum type, GLvoid *pixels,
3892 const struct gl_texture_object *texObj,
3893 const struct gl_texture_image *texImage)
3894 {
3895 GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
3896
3897 if (ctx->Pack.BufferObj->Name) {
3898 /* pack texture image into a PBO */
3899 GLubyte *buf;
3900 if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width,
3901 texImage->Height, texImage->Depth,
3902 format, type, pixels)) {
3903 _mesa_error(ctx, GL_INVALID_OPERATION,
3904 "glGetTexImage(invalid PBO access)");
3905 return;
3906 }
3907 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
3908 GL_WRITE_ONLY_ARB,
3909 ctx->Pack.BufferObj);
3910 if (!buf) {
3911 /* buffer is already mapped - that's an error */
3912 _mesa_error(ctx, GL_INVALID_OPERATION,"glGetTexImage(PBO is mapped)");
3913 return;
3914 }
3915 pixels = ADD_POINTERS(buf, pixels);
3916 }
3917 else if (!pixels) {
3918 /* not an error */
3919 return;
3920 }
3921
3922 {
3923 const GLint width = texImage->Width;
3924 const GLint height = texImage->Height;
3925 const GLint depth = texImage->Depth;
3926 GLint img, row;
3927 for (img = 0; img < depth; img++) {
3928 for (row = 0; row < height; row++) {
3929 /* compute destination address in client memory */
3930 GLvoid *dest = _mesa_image_address( dimensions, &ctx->Pack, pixels,
3931 width, height, format, type,
3932 img, row, 0);
3933 assert(dest);
3934
3935 if (format == GL_COLOR_INDEX) {
3936 GLuint indexRow[MAX_WIDTH];
3937 GLint col;
3938 /* Can't use FetchTexel here because that returns RGBA */
3939 if (texImage->TexFormat->IndexBits == 8) {
3940 const GLubyte *src = (const GLubyte *) texImage->Data;
3941 for (col = 0; col < width; col++) {
3942 indexRow[col] = src[texImage->Width *
3943 (img * texImage->Height + row) + col];
3944 }
3945 }
3946 else if (texImage->TexFormat->IndexBits == 16) {
3947 const GLushort *src = (const GLushort *) texImage->Data;
3948 for (col = 0; col < width; col++) {
3949 indexRow[col] = src[texImage->Width *
3950 (img * texImage->Height + row) + col];
3951 }
3952 }
3953 else {
3954 _mesa_problem(ctx,
3955 "Color index problem in _mesa_GetTexImage");
3956 }
3957 _mesa_pack_index_span(ctx, width, type, dest,
3958 indexRow, &ctx->Pack,
3959 0 /* no image transfer */);
3960 }
3961 else if (format == GL_DEPTH_COMPONENT) {
3962 GLfloat depthRow[MAX_WIDTH];
3963 GLint col;
3964 for (col = 0; col < width; col++) {
3965 (*texImage->FetchTexelf)(texImage, col, row, img,
3966 depthRow + col);
3967 }
3968 _mesa_pack_depth_span(ctx, width, dest, type,
3969 depthRow, &ctx->Pack);
3970 }
3971 else if (format == GL_YCBCR_MESA) {
3972 /* No pixel transfer */
3973 const GLint rowstride = texImage->RowStride;
3974 MEMCPY(dest,
3975 (const GLushort *) texImage->Data + row * rowstride,
3976 width * sizeof(GLushort));
3977 /* check for byte swapping */
3978 if ((texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR
3979 && type == GL_UNSIGNED_SHORT_8_8_REV_MESA) ||
3980 (texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV
3981 && type == GL_UNSIGNED_SHORT_8_8_MESA)) {
3982 if (!ctx->Pack.SwapBytes)
3983 _mesa_swap2((GLushort *) dest, width);
3984 }
3985 else if (ctx->Pack.SwapBytes) {
3986 _mesa_swap2((GLushort *) dest, width);
3987 }
3988 }
3989 else {
3990 /* general case: convert row to RGBA format */
3991 GLfloat rgba[MAX_WIDTH][4];
3992 GLint col;
3993 for (col = 0; col < width; col++) {
3994 (*texImage->FetchTexelf)(texImage, col, row, img, rgba[col]);
3995 }
3996 _mesa_pack_rgba_span_float(ctx, width,
3997 (const GLfloat (*)[4]) rgba,
3998 format, type, dest, &ctx->Pack,
3999 0 /* no image transfer */);
4000 } /* format */
4001 } /* row */
4002 } /* img */
4003 }
4004
4005 if (ctx->Pack.BufferObj->Name) {
4006 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
4007 ctx->Pack.BufferObj);
4008 }
4009 }
4010
4011
4012
4013 /**
4014 * This is the software fallback for Driver.GetCompressedTexImage().
4015 * All error checking will have been done before this routine is called.
4016 */
4017 void
4018 _mesa_get_compressed_teximage(GLcontext *ctx, GLenum target, GLint level,
4019 GLvoid *img,
4020 const struct gl_texture_object *texObj,
4021 const struct gl_texture_image *texImage)
4022 {
4023 if (ctx->Pack.BufferObj->Name) {
4024 /* pack texture image into a PBO */
4025 GLubyte *buf;
4026 if ((const GLubyte *) img + texImage->CompressedSize >
4027 (const GLubyte *) ctx->Pack.BufferObj->Size) {
4028 _mesa_error(ctx, GL_INVALID_OPERATION,
4029 "glGetCompressedTexImage(invalid PBO access)");
4030 return;
4031 }
4032 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
4033 GL_WRITE_ONLY_ARB,
4034 ctx->Pack.BufferObj);
4035 if (!buf) {
4036 /* buffer is already mapped - that's an error */
4037 _mesa_error(ctx, GL_INVALID_OPERATION,
4038 "glGetCompressedTexImage(PBO is mapped)");
4039 return;
4040 }
4041 img = ADD_POINTERS(buf, img);
4042 }
4043 else if (!img) {
4044 /* not an error */
4045 return;
4046 }
4047
4048 /* just memcpy, no pixelstore or pixel transfer */
4049 MEMCPY(img, texImage->Data, texImage->CompressedSize);
4050
4051 if (ctx->Pack.BufferObj->Name) {
4052 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
4053 ctx->Pack.BufferObj);
4054 }
4055 }