merge from texman branch
[mesa.git] / src / mesa / main / texstore.c
1 /*
2 * Mesa 3-D graphics library
3 * Version: 6.5
4 *
5 * Copyright (C) 1999-2006 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,
885 GL_FLOAT, (GLfloat *) dstRow, 1.0F,
886 srcType, src, srcPacking);
887 dstRow += dstRowStride;
888 }
889 dstImage += dstImageStride;
890 }
891 }
892 return GL_TRUE;
893 }
894
895
896 /**
897 * Store a 16-bit integer depth component texture image.
898 */
899 GLboolean
900 _mesa_texstore_depth_component16(STORE_PARAMS)
901 {
902 (void) dims;
903 ASSERT(dstFormat == &_mesa_texformat_depth_component16);
904 ASSERT(dstFormat->TexelBytes == sizeof(GLushort));
905
906 if (!ctx->_ImageTransferState &&
907 !srcPacking->SwapBytes &&
908 baseInternalFormat == GL_DEPTH_COMPONENT &&
909 srcFormat == GL_DEPTH_COMPONENT &&
910 srcType == GL_UNSIGNED_SHORT) {
911 /* simple memcpy path */
912 memcpy_texture(ctx, dims,
913 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
914 dstRowStride, dstImageStride,
915 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
916 srcAddr, srcPacking);
917 }
918 else {
919 /* general path */
920 GLubyte *dstImage = (GLubyte *) dstAddr
921 + dstZoffset * dstImageStride
922 + dstYoffset * dstRowStride
923 + dstXoffset * dstFormat->TexelBytes;
924 GLint img, row;
925 for (img = 0; img < srcDepth; img++) {
926 GLubyte *dstRow = dstImage;
927 for (row = 0; row < srcHeight; row++) {
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,
932 GL_UNSIGNED_SHORT, dst16, 65535.0F,
933 srcType, src, srcPacking);
934 dstRow += dstRowStride;
935 }
936 dstImage += dstImageStride;
937 }
938 }
939 return GL_TRUE;
940 }
941
942
943 /**
944 * Store an rgb565 or rgb565_rev texture image.
945 */
946 GLboolean
947 _mesa_texstore_rgb565(STORE_PARAMS)
948 {
949 ASSERT(dstFormat == &_mesa_texformat_rgb565 ||
950 dstFormat == &_mesa_texformat_rgb565_rev);
951 ASSERT(dstFormat->TexelBytes == 2);
952
953 if (!ctx->_ImageTransferState &&
954 !srcPacking->SwapBytes &&
955 dstFormat == &_mesa_texformat_rgb565 &&
956 baseInternalFormat == GL_RGB &&
957 srcFormat == GL_RGB &&
958 srcType == GL_UNSIGNED_SHORT_5_6_5) {
959 /* simple memcpy path */
960 memcpy_texture(ctx, dims,
961 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
962 dstRowStride, dstImageStride,
963 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
964 srcAddr, srcPacking);
965 }
966 else if (!ctx->_ImageTransferState &&
967 !srcPacking->SwapBytes &&
968 baseInternalFormat == GL_RGB &&
969 srcFormat == GL_RGB &&
970 srcType == GL_UNSIGNED_BYTE &&
971 dims == 2) {
972 /* do optimized tex store */
973 const GLint srcRowStride = _mesa_image_row_stride(srcPacking, srcWidth,
974 srcFormat, srcType);
975 const GLubyte *src = (const GLubyte *)
976 _mesa_image_address(dims, srcPacking, srcAddr, srcWidth, srcHeight,
977 srcFormat, srcType, 0, 0, 0);
978 GLubyte *dst = (GLubyte *) dstAddr
979 + dstZoffset * dstImageStride
980 + dstYoffset * dstRowStride
981 + dstXoffset * dstFormat->TexelBytes;
982 GLint row, col;
983 for (row = 0; row < srcHeight; row++) {
984 const GLubyte *srcUB = (const GLubyte *) src;
985 GLushort *dstUS = (GLushort *) dst;
986 /* check for byteswapped format */
987 if (dstFormat == &_mesa_texformat_rgb565) {
988 for (col = 0; col < srcWidth; col++) {
989 dstUS[col] = PACK_COLOR_565( srcUB[0], srcUB[1], srcUB[2] );
990 srcUB += 3;
991 }
992 }
993 else {
994 for (col = 0; col < srcWidth; col++) {
995 dstUS[col] = PACK_COLOR_565_REV( srcUB[0], srcUB[1], srcUB[2] );
996 srcUB += 3;
997 }
998 }
999 dst += dstRowStride;
1000 src += srcRowStride;
1001 }
1002 }
1003 else {
1004 /* general path */
1005 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1006 baseInternalFormat,
1007 dstFormat->BaseFormat,
1008 srcWidth, srcHeight, srcDepth,
1009 srcFormat, srcType, srcAddr,
1010 srcPacking);
1011 const GLchan *src = tempImage;
1012 GLubyte *dstImage = (GLubyte *) dstAddr
1013 + dstZoffset * dstImageStride
1014 + dstYoffset * dstRowStride
1015 + dstXoffset * dstFormat->TexelBytes;
1016 GLint img, row, col;
1017 if (!tempImage)
1018 return GL_FALSE;
1019 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1020 for (img = 0; img < srcDepth; img++) {
1021 GLubyte *dstRow = dstImage;
1022 for (row = 0; row < srcHeight; row++) {
1023 GLushort *dstUS = (GLushort *) dstRow;
1024 /* check for byteswapped format */
1025 if (dstFormat == &_mesa_texformat_rgb565) {
1026 for (col = 0; col < srcWidth; col++) {
1027 dstUS[col] = PACK_COLOR_565( CHAN_TO_UBYTE(src[RCOMP]),
1028 CHAN_TO_UBYTE(src[GCOMP]),
1029 CHAN_TO_UBYTE(src[BCOMP]) );
1030 src += 3;
1031 }
1032 }
1033 else {
1034 for (col = 0; col < srcWidth; col++) {
1035 dstUS[col] = PACK_COLOR_565_REV( CHAN_TO_UBYTE(src[RCOMP]),
1036 CHAN_TO_UBYTE(src[GCOMP]),
1037 CHAN_TO_UBYTE(src[BCOMP]) );
1038 src += 3;
1039 }
1040 }
1041 dstRow += dstRowStride;
1042 }
1043 dstImage += dstImageStride;
1044 }
1045 _mesa_free((void *) tempImage);
1046 }
1047 return GL_TRUE;
1048 }
1049
1050
1051 GLboolean
1052 _mesa_texstore_rgba8888(STORE_PARAMS)
1053 {
1054 const GLuint ui = 1;
1055 const GLubyte littleEndian = *((const GLubyte *) &ui);
1056
1057 (void)littleEndian;
1058 ASSERT(dstFormat == &_mesa_texformat_rgba8888 ||
1059 dstFormat == &_mesa_texformat_rgba8888_rev);
1060 ASSERT(dstFormat->TexelBytes == 4);
1061
1062 if (!ctx->_ImageTransferState &&
1063 !srcPacking->SwapBytes &&
1064 dstFormat == &_mesa_texformat_rgba8888 &&
1065 baseInternalFormat == GL_RGBA &&
1066 ((srcFormat == GL_RGBA && srcType == GL_UNSIGNED_INT_8_8_8_8) ||
1067 (srcFormat == GL_ABGR_EXT && srcType == GL_UNSIGNED_INT_8_8_8_8_REV))) {
1068 /* simple memcpy path */
1069 memcpy_texture(ctx, dims,
1070 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1071 dstRowStride, dstImageStride,
1072 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1073 srcAddr, srcPacking);
1074 }
1075 #if 0
1076 else if (!ctx->_ImageTransferState &&
1077 !srcPacking->SwapBytes &&
1078 srcType == GL_UNSIGNED_BYTE &&
1079 dstFormat == &_mesa_texformat_rgba8888 &&
1080 littleEndian &&
1081 /* Three texture formats involved: srcFormat,
1082 * baseInternalFormat and destFormat (GL_RGBA). Only two
1083 * may differ. _mesa_swizzle_ubyte_image can't handle two
1084 * propagations at once correctly. */
1085 (srcFormat == baseInternalFormat ||
1086 baseInternalFormat == GL_RGBA) &&
1087 can_swizzle(srcFormat)) {
1088 GLubyte dstmap[4];
1089
1090 /* dstmap - how to swizzle from GL_RGBA to dst format:
1091 *
1092 * FIXME - add !litteEndian and _rev varients:
1093 */
1094 dstmap[3] = 0;
1095 dstmap[2] = 1;
1096 dstmap[1] = 2;
1097 dstmap[0] = 3;
1098
1099 _mesa_swizzle_ubyte_image(ctx, dims,
1100 srcFormat,
1101 dstmap, 4,
1102 dstAddr, dstXoffset, dstYoffset, dstZoffset,
1103 dstRowStride, dstImageStride,
1104 srcWidth, srcHeight, srcDepth, srcAddr,
1105 srcPacking);
1106 }
1107 #endif
1108 else {
1109 /* general path */
1110 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1111 baseInternalFormat,
1112 dstFormat->BaseFormat,
1113 srcWidth, srcHeight, srcDepth,
1114 srcFormat, srcType, srcAddr,
1115 srcPacking);
1116 const GLchan *src = tempImage;
1117 GLubyte *dstImage = (GLubyte *) dstAddr
1118 + dstZoffset * dstImageStride
1119 + dstYoffset * dstRowStride
1120 + dstXoffset * dstFormat->TexelBytes;
1121 GLint img, row, col;
1122 if (!tempImage)
1123 return GL_FALSE;
1124 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1125 for (img = 0; img < srcDepth; img++) {
1126 GLubyte *dstRow = dstImage;
1127 for (row = 0; row < srcHeight; row++) {
1128 GLuint *dstUI = (GLuint *) dstRow;
1129 if (dstFormat == &_mesa_texformat_rgba8888) {
1130 for (col = 0; col < srcWidth; col++) {
1131 dstUI[col] = PACK_COLOR_8888( CHAN_TO_UBYTE(src[RCOMP]),
1132 CHAN_TO_UBYTE(src[GCOMP]),
1133 CHAN_TO_UBYTE(src[BCOMP]),
1134 CHAN_TO_UBYTE(src[ACOMP]) );
1135 src += 4;
1136 }
1137 }
1138 else {
1139 for (col = 0; col < srcWidth; col++) {
1140 dstUI[col] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src[RCOMP]),
1141 CHAN_TO_UBYTE(src[GCOMP]),
1142 CHAN_TO_UBYTE(src[BCOMP]),
1143 CHAN_TO_UBYTE(src[ACOMP]) );
1144 src += 4;
1145 }
1146 }
1147 dstRow += dstRowStride;
1148 }
1149 dstImage += dstImageStride;
1150 }
1151 _mesa_free((void *) tempImage);
1152 }
1153 return GL_TRUE;
1154 }
1155
1156
1157 GLboolean
1158 _mesa_texstore_argb8888(STORE_PARAMS)
1159 {
1160 const GLuint ui = 1;
1161 const GLubyte littleEndian = *((const GLubyte *) &ui);
1162
1163 ASSERT(dstFormat == &_mesa_texformat_argb8888 ||
1164 dstFormat == &_mesa_texformat_argb8888_rev);
1165 ASSERT(dstFormat->TexelBytes == 4);
1166
1167 if (!ctx->_ImageTransferState &&
1168 !srcPacking->SwapBytes &&
1169 dstFormat == &_mesa_texformat_argb8888 &&
1170 baseInternalFormat == GL_RGBA &&
1171 srcFormat == GL_BGRA &&
1172 ((srcType == GL_UNSIGNED_BYTE && littleEndian) ||
1173 srcType == GL_UNSIGNED_INT_8_8_8_8_REV)) {
1174 /* simple memcpy path (little endian) */
1175 memcpy_texture(ctx, dims,
1176 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1177 dstRowStride, dstImageStride,
1178 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1179 srcAddr, srcPacking);
1180 }
1181 else if (!ctx->_ImageTransferState &&
1182 !srcPacking->SwapBytes &&
1183 dstFormat == &_mesa_texformat_argb8888_rev &&
1184 baseInternalFormat == GL_RGBA &&
1185 srcFormat == GL_BGRA &&
1186 ((srcType == GL_UNSIGNED_BYTE && !littleEndian) ||
1187 srcType == GL_UNSIGNED_INT_8_8_8_8)) {
1188 /* simple memcpy path (big endian) */
1189 memcpy_texture(ctx, dims,
1190 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1191 dstRowStride, dstImageStride,
1192 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1193 srcAddr, srcPacking);
1194 }
1195 else if (!ctx->_ImageTransferState &&
1196 !srcPacking->SwapBytes &&
1197 dstFormat == &_mesa_texformat_argb8888 &&
1198 srcFormat == GL_RGB &&
1199 srcType == GL_UNSIGNED_BYTE) {
1200
1201 int img, row, col;
1202 GLubyte *dstImage = (GLubyte *) dstAddr
1203 + dstZoffset * dstImageStride
1204 + dstYoffset * dstRowStride
1205 + dstXoffset * dstFormat->TexelBytes;
1206 for (img = 0; img < srcDepth; img++) {
1207 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
1208 srcWidth, srcFormat, srcType);
1209 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
1210 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
1211 GLubyte *dstRow = dstImage;
1212 for (row = 0; row < srcHeight; row++) {
1213 for (col = 0; col < srcWidth; col++) {
1214 dstRow[col * 4 + 0] = srcRow[col * 3 + BCOMP];
1215 dstRow[col * 4 + 1] = srcRow[col * 3 + GCOMP];
1216 dstRow[col * 4 + 2] = srcRow[col * 3 + RCOMP];
1217 dstRow[col * 4 + 3] = 0xff;
1218 }
1219 dstRow += dstRowStride;
1220 srcRow += srcRowStride;
1221 }
1222 dstImage += dstImageStride;
1223 }
1224 }
1225 else if (!ctx->_ImageTransferState &&
1226 !srcPacking->SwapBytes &&
1227 dstFormat == &_mesa_texformat_argb8888 &&
1228 srcFormat == GL_RGBA &&
1229 (srcType == GL_UNSIGNED_BYTE && littleEndian)) {
1230
1231 int img, row, col;
1232 GLubyte *dstImage = (GLubyte *) dstAddr
1233 + dstZoffset * dstImageStride
1234 + dstYoffset * dstRowStride
1235 + dstXoffset * dstFormat->TexelBytes;
1236
1237 /* For some reason, streaming copies to write-combined regions
1238 * are extremely sensitive to the characteristics of how the
1239 * source data is retrieved. By reordering the source reads to
1240 * be in-order, the speed of this operation increases by half.
1241 * Strangely the same isn't required for the RGB path, above.
1242 */
1243 for (img = 0; img < srcDepth; img++) {
1244 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
1245 srcWidth, srcFormat, srcType);
1246 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
1247 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
1248 GLubyte *dstRow = dstImage;
1249 for (row = 0; row < srcHeight; row++) {
1250 for (col = 0; col < srcWidth; col++) {
1251 *(GLuint *)(dstRow + col * 4) = (srcRow[col * 4 + RCOMP] << 16 |
1252 srcRow[col * 4 + GCOMP] << 8 |
1253 srcRow[col * 4 + BCOMP] << 0 |
1254 srcRow[col * 4 + ACOMP] << 24);
1255 }
1256 dstRow += dstRowStride;
1257 srcRow += srcRowStride;
1258 }
1259 dstImage += dstImageStride;
1260 }
1261 }
1262 else if (!ctx->_ImageTransferState &&
1263 !srcPacking->SwapBytes &&
1264 dstFormat == &_mesa_texformat_argb8888 &&
1265 srcFormat == GL_RGBA &&
1266 srcType == GL_UNSIGNED_BYTE) {
1267
1268 int img, row, col;
1269 GLubyte *dstImage = (GLubyte *) dstAddr
1270 + dstZoffset * dstImageStride
1271 + dstYoffset * dstRowStride
1272 + dstXoffset * dstFormat->TexelBytes;
1273 for (img = 0; img < srcDepth; img++) {
1274 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
1275 srcWidth, srcFormat, srcType);
1276 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
1277 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
1278 GLubyte *dstRow = dstImage;
1279 for (row = 0; row < srcHeight; row++) {
1280 for (col = 0; col < srcWidth; col++) {
1281 dstRow[col * 4 + 0] = srcRow[col * 4 + BCOMP];
1282 dstRow[col * 4 + 1] = srcRow[col * 4 + GCOMP];
1283 dstRow[col * 4 + 2] = srcRow[col * 4 + RCOMP];
1284 dstRow[col * 4 + 3] = srcRow[col * 4 + ACOMP];
1285 }
1286 dstRow += dstRowStride;
1287 srcRow += srcRowStride;
1288 }
1289 dstImage += dstImageStride;
1290 }
1291 }
1292 else if (!ctx->_ImageTransferState &&
1293 !srcPacking->SwapBytes &&
1294 dstFormat == &_mesa_texformat_argb8888 &&
1295 srcType == GL_UNSIGNED_BYTE &&
1296 littleEndian &&
1297 /* Three texture formats involved: srcFormat,
1298 * baseInternalFormat and destFormat (GL_RGBA). Only two
1299 * may differ. _mesa_swizzle_ubyte_image can't handle two
1300 * propagations at once correctly. */
1301 (srcFormat == baseInternalFormat ||
1302 baseInternalFormat == GL_RGBA) &&
1303 can_swizzle(srcFormat)) {
1304
1305 GLubyte dstmap[4];
1306
1307 /* dstmap - how to swizzle from GL_RGBA to dst format:
1308 */
1309 dstmap[3] = 3; /* alpha */
1310 dstmap[2] = 0; /* red */
1311 dstmap[1] = 1; /* green */
1312 dstmap[0] = 2; /* blue */
1313
1314 _mesa_swizzle_ubyte_image(ctx, dims,
1315 srcFormat,
1316 dstmap, 4,
1317 dstAddr, dstXoffset, dstYoffset, dstZoffset,
1318 dstRowStride, dstImageStride,
1319 srcWidth, srcHeight, srcDepth, srcAddr,
1320 srcPacking);
1321 }
1322 else {
1323 /* general path */
1324 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1325 baseInternalFormat,
1326 dstFormat->BaseFormat,
1327 srcWidth, srcHeight, srcDepth,
1328 srcFormat, srcType, srcAddr,
1329 srcPacking);
1330 const GLchan *src = tempImage;
1331 GLubyte *dstImage = (GLubyte *) dstAddr
1332 + dstZoffset * dstImageStride
1333 + dstYoffset * dstRowStride
1334 + dstXoffset * dstFormat->TexelBytes;
1335 GLint img, row, col;
1336 if (!tempImage)
1337 return GL_FALSE;
1338 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1339 for (img = 0; img < srcDepth; img++) {
1340 GLubyte *dstRow = dstImage;
1341 for (row = 0; row < srcHeight; row++) {
1342 GLuint *dstUI = (GLuint *) dstRow;
1343 if (dstFormat == &_mesa_texformat_argb8888) {
1344 for (col = 0; col < srcWidth; col++) {
1345 dstUI[col] = PACK_COLOR_8888( CHAN_TO_UBYTE(src[ACOMP]),
1346 CHAN_TO_UBYTE(src[RCOMP]),
1347 CHAN_TO_UBYTE(src[GCOMP]),
1348 CHAN_TO_UBYTE(src[BCOMP]) );
1349 src += 4;
1350 }
1351 }
1352 else {
1353 for (col = 0; col < srcWidth; col++) {
1354 dstUI[col] = PACK_COLOR_8888_REV( CHAN_TO_UBYTE(src[ACOMP]),
1355 CHAN_TO_UBYTE(src[RCOMP]),
1356 CHAN_TO_UBYTE(src[GCOMP]),
1357 CHAN_TO_UBYTE(src[BCOMP]) );
1358 src += 4;
1359 }
1360 }
1361 dstRow += dstRowStride;
1362 }
1363 dstImage += dstImageStride;
1364 }
1365 _mesa_free((void *) tempImage);
1366 }
1367 return GL_TRUE;
1368 }
1369
1370
1371 GLboolean
1372 _mesa_texstore_rgb888(STORE_PARAMS)
1373 {
1374 const GLuint ui = 1;
1375 const GLubyte littleEndian = *((const GLubyte *) &ui);
1376
1377 ASSERT(dstFormat == &_mesa_texformat_rgb888);
1378 ASSERT(dstFormat->TexelBytes == 3);
1379
1380 if (!ctx->_ImageTransferState &&
1381 !srcPacking->SwapBytes &&
1382 baseInternalFormat == GL_RGB &&
1383 srcFormat == GL_BGR &&
1384 srcType == GL_UNSIGNED_BYTE &&
1385 littleEndian) {
1386 /* simple memcpy path */
1387 memcpy_texture(ctx, dims,
1388 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1389 dstRowStride, dstImageStride,
1390 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1391 srcAddr, srcPacking);
1392 }
1393 else if (!ctx->_ImageTransferState &&
1394 !srcPacking->SwapBytes &&
1395 srcFormat == GL_RGBA &&
1396 srcType == GL_UNSIGNED_BYTE) {
1397 /* extract RGB from RGBA */
1398 int img, row, col;
1399 GLubyte *dstImage = (GLubyte *) dstAddr
1400 + dstZoffset * dstImageStride
1401 + dstYoffset * dstRowStride
1402 + dstXoffset * dstFormat->TexelBytes;
1403 for (img = 0; img < srcDepth; img++) {
1404 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
1405 srcWidth, srcFormat, srcType);
1406 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
1407 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
1408 GLubyte *dstRow = dstImage;
1409 for (row = 0; row < srcHeight; row++) {
1410 for (col = 0; col < srcWidth; col++) {
1411 dstRow[col * 3 + 0] = srcRow[col * 4 + BCOMP];
1412 dstRow[col * 3 + 1] = srcRow[col * 4 + GCOMP];
1413 dstRow[col * 3 + 2] = srcRow[col * 4 + RCOMP];
1414 }
1415 dstRow += dstRowStride;
1416 srcRow += srcRowStride;
1417 }
1418 dstImage += dstImageStride;
1419 }
1420 }
1421 else {
1422 /* general path */
1423 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1424 baseInternalFormat,
1425 dstFormat->BaseFormat,
1426 srcWidth, srcHeight, srcDepth,
1427 srcFormat, srcType, srcAddr,
1428 srcPacking);
1429 const GLchan *src = (const GLchan *) tempImage;
1430 GLubyte *dstImage = (GLubyte *) dstAddr
1431 + dstZoffset * dstImageStride
1432 + dstYoffset * dstRowStride
1433 + dstXoffset * dstFormat->TexelBytes;
1434 GLint img, row, col;
1435 if (!tempImage)
1436 return GL_FALSE;
1437 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1438 for (img = 0; img < srcDepth; img++) {
1439 GLubyte *dstRow = dstImage;
1440 for (row = 0; row < srcHeight; row++) {
1441 #if 0
1442 if (littleEndian) {
1443 for (col = 0; col < srcWidth; col++) {
1444 dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[RCOMP]);
1445 dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]);
1446 dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[BCOMP]);
1447 srcUB += 3;
1448 }
1449 }
1450 else {
1451 for (col = 0; col < srcWidth; col++) {
1452 dstRow[col * 3 + 0] = srcUB[BCOMP];
1453 dstRow[col * 3 + 1] = srcUB[GCOMP];
1454 dstRow[col * 3 + 2] = srcUB[RCOMP];
1455 srcUB += 3;
1456 }
1457 }
1458 #else
1459 for (col = 0; col < srcWidth; col++) {
1460 dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[BCOMP]);
1461 dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]);
1462 dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[RCOMP]);
1463 src += 3;
1464 }
1465 #endif
1466 dstRow += dstRowStride;
1467 }
1468 dstImage += dstImageStride;
1469 }
1470 _mesa_free((void *) tempImage);
1471 }
1472 return GL_TRUE;
1473 }
1474
1475
1476 GLboolean
1477 _mesa_texstore_bgr888(STORE_PARAMS)
1478 {
1479 const GLuint ui = 1;
1480 const GLubyte littleEndian = *((const GLubyte *) &ui);
1481
1482 ASSERT(dstFormat == &_mesa_texformat_bgr888);
1483 ASSERT(dstFormat->TexelBytes == 3);
1484
1485 if (!ctx->_ImageTransferState &&
1486 !srcPacking->SwapBytes &&
1487 baseInternalFormat == GL_RGB &&
1488 srcFormat == GL_RGB &&
1489 srcType == GL_UNSIGNED_BYTE &&
1490 littleEndian) {
1491 /* simple memcpy path */
1492 memcpy_texture(ctx, dims,
1493 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1494 dstRowStride, dstImageStride,
1495 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1496 srcAddr, srcPacking);
1497 }
1498 else if (!ctx->_ImageTransferState &&
1499 !srcPacking->SwapBytes &&
1500 srcFormat == GL_RGBA &&
1501 srcType == GL_UNSIGNED_BYTE) {
1502 /* extract BGR from RGBA */
1503 int img, row, col;
1504 GLubyte *dstImage = (GLubyte *) dstAddr
1505 + dstZoffset * dstImageStride
1506 + dstYoffset * dstRowStride
1507 + dstXoffset * dstFormat->TexelBytes;
1508 for (img = 0; img < srcDepth; img++) {
1509 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
1510 srcWidth, srcFormat, srcType);
1511 GLubyte *srcRow = (GLubyte *) _mesa_image_address(dims, srcPacking,
1512 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, 0, 0);
1513 GLubyte *dstRow = dstImage;
1514 for (row = 0; row < srcHeight; row++) {
1515 for (col = 0; col < srcWidth; col++) {
1516 dstRow[col * 3 + 0] = srcRow[col * 4 + RCOMP];
1517 dstRow[col * 3 + 1] = srcRow[col * 4 + GCOMP];
1518 dstRow[col * 3 + 2] = srcRow[col * 4 + BCOMP];
1519 }
1520 dstRow += dstRowStride;
1521 srcRow += srcRowStride;
1522 }
1523 dstImage += dstImageStride;
1524 }
1525 }
1526 else {
1527 /* general path */
1528 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1529 baseInternalFormat,
1530 dstFormat->BaseFormat,
1531 srcWidth, srcHeight, srcDepth,
1532 srcFormat, srcType, srcAddr,
1533 srcPacking);
1534 const GLchan *src = (const GLchan *) tempImage;
1535 GLubyte *dstImage = (GLubyte *) dstAddr
1536 + dstZoffset * dstImageStride
1537 + dstYoffset * dstRowStride
1538 + dstXoffset * dstFormat->TexelBytes;
1539 GLint img, row, col;
1540 if (!tempImage)
1541 return GL_FALSE;
1542 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1543 for (img = 0; img < srcDepth; img++) {
1544 GLubyte *dstRow = dstImage;
1545 for (row = 0; row < srcHeight; row++) {
1546 for (col = 0; col < srcWidth; col++) {
1547 dstRow[col * 3 + 0] = CHAN_TO_UBYTE(src[RCOMP]);
1548 dstRow[col * 3 + 1] = CHAN_TO_UBYTE(src[GCOMP]);
1549 dstRow[col * 3 + 2] = CHAN_TO_UBYTE(src[BCOMP]);
1550 src += 3;
1551 }
1552 dstRow += dstRowStride;
1553 }
1554 dstImage += dstImageStride;
1555 }
1556 _mesa_free((void *) tempImage);
1557 }
1558 return GL_TRUE;
1559 }
1560
1561
1562 GLboolean
1563 _mesa_texstore_argb4444(STORE_PARAMS)
1564 {
1565 ASSERT(dstFormat == &_mesa_texformat_argb4444 ||
1566 dstFormat == &_mesa_texformat_argb4444_rev);
1567 ASSERT(dstFormat->TexelBytes == 2);
1568
1569 if (!ctx->_ImageTransferState &&
1570 !srcPacking->SwapBytes &&
1571 dstFormat == &_mesa_texformat_argb4444 &&
1572 baseInternalFormat == GL_RGBA &&
1573 srcFormat == GL_BGRA &&
1574 srcType == GL_UNSIGNED_SHORT_4_4_4_4_REV) {
1575 /* simple memcpy path */
1576 memcpy_texture(ctx, dims,
1577 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1578 dstRowStride, dstImageStride,
1579 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1580 srcAddr, srcPacking);
1581 }
1582 else {
1583 /* general path */
1584 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1585 baseInternalFormat,
1586 dstFormat->BaseFormat,
1587 srcWidth, srcHeight, srcDepth,
1588 srcFormat, srcType, srcAddr,
1589 srcPacking);
1590 const GLchan *src = tempImage;
1591 GLubyte *dstImage = (GLubyte *) dstAddr
1592 + dstZoffset * dstImageStride
1593 + dstYoffset * dstRowStride
1594 + dstXoffset * dstFormat->TexelBytes;
1595 GLint img, row, col;
1596 if (!tempImage)
1597 return GL_FALSE;
1598 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1599 for (img = 0; img < srcDepth; img++) {
1600 GLubyte *dstRow = dstImage;
1601 for (row = 0; row < srcHeight; row++) {
1602 GLushort *dstUS = (GLushort *) dstRow;
1603 if (dstFormat == &_mesa_texformat_argb4444) {
1604 for (col = 0; col < srcWidth; col++) {
1605 dstUS[col] = PACK_COLOR_4444( CHAN_TO_UBYTE(src[ACOMP]),
1606 CHAN_TO_UBYTE(src[RCOMP]),
1607 CHAN_TO_UBYTE(src[GCOMP]),
1608 CHAN_TO_UBYTE(src[BCOMP]) );
1609 src += 4;
1610 }
1611 }
1612 else {
1613 for (col = 0; col < srcWidth; col++) {
1614 dstUS[col] = PACK_COLOR_4444_REV( CHAN_TO_UBYTE(src[ACOMP]),
1615 CHAN_TO_UBYTE(src[RCOMP]),
1616 CHAN_TO_UBYTE(src[GCOMP]),
1617 CHAN_TO_UBYTE(src[BCOMP]) );
1618 src += 4;
1619 }
1620 }
1621 dstRow += dstRowStride;
1622 }
1623 dstImage += dstImageStride;
1624 }
1625 _mesa_free((void *) tempImage);
1626 }
1627 return GL_TRUE;
1628 }
1629
1630
1631
1632 GLboolean
1633 _mesa_texstore_argb1555(STORE_PARAMS)
1634 {
1635 ASSERT(dstFormat == &_mesa_texformat_argb1555 ||
1636 dstFormat == &_mesa_texformat_argb1555_rev);
1637 ASSERT(dstFormat->TexelBytes == 2);
1638
1639 if (!ctx->_ImageTransferState &&
1640 !srcPacking->SwapBytes &&
1641 dstFormat == &_mesa_texformat_argb1555 &&
1642 baseInternalFormat == GL_RGBA &&
1643 srcFormat == GL_BGRA &&
1644 srcType == GL_UNSIGNED_SHORT_1_5_5_5_REV) {
1645 /* simple memcpy path */
1646 memcpy_texture(ctx, dims,
1647 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1648 dstRowStride, dstImageStride,
1649 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1650 srcAddr, srcPacking);
1651 }
1652 else {
1653 /* general path */
1654 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1655 baseInternalFormat,
1656 dstFormat->BaseFormat,
1657 srcWidth, srcHeight, srcDepth,
1658 srcFormat, srcType, srcAddr,
1659 srcPacking);
1660 const GLchan *src =tempImage;
1661 GLubyte *dstImage = (GLubyte *) dstAddr
1662 + dstZoffset * dstImageStride
1663 + dstYoffset * dstRowStride
1664 + dstXoffset * dstFormat->TexelBytes;
1665 GLint img, row, col;
1666 if (!tempImage)
1667 return GL_FALSE;
1668 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1669 for (img = 0; img < srcDepth; img++) {
1670 GLubyte *dstRow = dstImage;
1671 for (row = 0; row < srcHeight; row++) {
1672 GLushort *dstUS = (GLushort *) dstRow;
1673 if (dstFormat == &_mesa_texformat_argb1555) {
1674 for (col = 0; col < srcWidth; col++) {
1675 dstUS[col] = PACK_COLOR_1555( CHAN_TO_UBYTE(src[ACOMP]),
1676 CHAN_TO_UBYTE(src[RCOMP]),
1677 CHAN_TO_UBYTE(src[GCOMP]),
1678 CHAN_TO_UBYTE(src[BCOMP]) );
1679 src += 4;
1680 }
1681 }
1682 else {
1683 for (col = 0; col < srcWidth; col++) {
1684 dstUS[col] = PACK_COLOR_1555_REV( CHAN_TO_UBYTE(src[ACOMP]),
1685 CHAN_TO_UBYTE(src[RCOMP]),
1686 CHAN_TO_UBYTE(src[GCOMP]),
1687 CHAN_TO_UBYTE(src[BCOMP]) );
1688 src += 4;
1689 }
1690 }
1691 dstRow += dstRowStride;
1692 }
1693 dstImage += dstImageStride;
1694 }
1695 _mesa_free((void *) tempImage);
1696 }
1697 return GL_TRUE;
1698 }
1699
1700
1701 GLboolean
1702 _mesa_texstore_al88(STORE_PARAMS)
1703 {
1704 const GLuint ui = 1;
1705 const GLubyte littleEndian = *((const GLubyte *) &ui);
1706
1707 ASSERT(dstFormat == &_mesa_texformat_al88 ||
1708 dstFormat == &_mesa_texformat_al88_rev);
1709 ASSERT(dstFormat->TexelBytes == 2);
1710
1711 if (!ctx->_ImageTransferState &&
1712 !srcPacking->SwapBytes &&
1713 dstFormat == &_mesa_texformat_al88 &&
1714 baseInternalFormat == GL_LUMINANCE_ALPHA &&
1715 srcFormat == GL_LUMINANCE_ALPHA &&
1716 srcType == GL_UNSIGNED_BYTE &&
1717 littleEndian) {
1718 /* simple memcpy path */
1719 memcpy_texture(ctx, dims,
1720 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1721 dstRowStride, dstImageStride,
1722 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1723 srcAddr, srcPacking);
1724 }
1725 else {
1726 /* general path */
1727 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1728 baseInternalFormat,
1729 dstFormat->BaseFormat,
1730 srcWidth, srcHeight, srcDepth,
1731 srcFormat, srcType, srcAddr,
1732 srcPacking);
1733 const GLchan *src = tempImage;
1734 GLubyte *dstImage = (GLubyte *) dstAddr
1735 + dstZoffset * dstImageStride
1736 + dstYoffset * dstRowStride
1737 + dstXoffset * dstFormat->TexelBytes;
1738 GLint img, row, col;
1739 if (!tempImage)
1740 return GL_FALSE;
1741 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1742 for (img = 0; img < srcDepth; img++) {
1743 GLubyte *dstRow = dstImage;
1744 for (row = 0; row < srcHeight; row++) {
1745 GLushort *dstUS = (GLushort *) dstRow;
1746 if (dstFormat == &_mesa_texformat_al88) {
1747 for (col = 0; col < srcWidth; col++) {
1748 /* src[0] is luminance, src[1] is alpha */
1749 dstUS[col] = PACK_COLOR_88( CHAN_TO_UBYTE(src[1]),
1750 CHAN_TO_UBYTE(src[0]) );
1751 src += 2;
1752 }
1753 }
1754 else {
1755 for (col = 0; col < srcWidth; col++) {
1756 /* src[0] is luminance, src[1] is alpha */
1757 dstUS[col] = PACK_COLOR_88_REV( CHAN_TO_UBYTE(src[1]),
1758 CHAN_TO_UBYTE(src[0]) );
1759 src += 2;
1760 }
1761 }
1762 dstRow += dstRowStride;
1763 }
1764 dstImage += dstImageStride;
1765 }
1766 _mesa_free((void *) tempImage);
1767 }
1768 return GL_TRUE;
1769 }
1770
1771
1772 GLboolean
1773 _mesa_texstore_rgb332(STORE_PARAMS)
1774 {
1775 ASSERT(dstFormat == &_mesa_texformat_rgb332);
1776 ASSERT(dstFormat->TexelBytes == 1);
1777
1778 if (!ctx->_ImageTransferState &&
1779 !srcPacking->SwapBytes &&
1780 baseInternalFormat == GL_RGB &&
1781 srcFormat == GL_RGB && srcType == GL_UNSIGNED_BYTE_3_3_2) {
1782 /* simple memcpy path */
1783 memcpy_texture(ctx, dims,
1784 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1785 dstRowStride, dstImageStride,
1786 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1787 srcAddr, srcPacking);
1788 }
1789 else {
1790 /* general path */
1791 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1792 baseInternalFormat,
1793 dstFormat->BaseFormat,
1794 srcWidth, srcHeight, srcDepth,
1795 srcFormat, srcType, srcAddr,
1796 srcPacking);
1797 const GLchan *src = tempImage;
1798 GLubyte *dstImage = (GLubyte *) dstAddr
1799 + dstZoffset * dstImageStride
1800 + dstYoffset * dstRowStride
1801 + dstXoffset * dstFormat->TexelBytes;
1802 GLint img, row, col;
1803 if (!tempImage)
1804 return GL_FALSE;
1805 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1806 for (img = 0; img < srcDepth; img++) {
1807 GLubyte *dstRow = dstImage;
1808 for (row = 0; row < srcHeight; row++) {
1809 for (col = 0; col < srcWidth; col++) {
1810 dstRow[col] = PACK_COLOR_332( CHAN_TO_UBYTE(src[RCOMP]),
1811 CHAN_TO_UBYTE(src[GCOMP]),
1812 CHAN_TO_UBYTE(src[BCOMP]) );
1813 src += 3;
1814 }
1815 dstRow += dstRowStride;
1816 }
1817 dstImage += dstImageStride;
1818 }
1819 _mesa_free((void *) tempImage);
1820 }
1821 return GL_TRUE;
1822 }
1823
1824
1825 /**
1826 * Texstore for _mesa_texformat_a8, _mesa_texformat_l8, _mesa_texformat_i8.
1827 */
1828 GLboolean
1829 _mesa_texstore_a8(STORE_PARAMS)
1830 {
1831 ASSERT(dstFormat == &_mesa_texformat_a8 ||
1832 dstFormat == &_mesa_texformat_l8 ||
1833 dstFormat == &_mesa_texformat_i8);
1834 ASSERT(dstFormat->TexelBytes == 1);
1835
1836 if (!ctx->_ImageTransferState &&
1837 !srcPacking->SwapBytes &&
1838 baseInternalFormat == srcFormat &&
1839 srcType == GL_UNSIGNED_BYTE) {
1840 /* simple memcpy path */
1841 memcpy_texture(ctx, dims,
1842 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1843 dstRowStride, dstImageStride,
1844 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1845 srcAddr, srcPacking);
1846 }
1847 else {
1848 /* general path */
1849 const GLchan *tempImage = _mesa_make_temp_chan_image(ctx, dims,
1850 baseInternalFormat,
1851 dstFormat->BaseFormat,
1852 srcWidth, srcHeight, srcDepth,
1853 srcFormat, srcType, srcAddr,
1854 srcPacking);
1855 const GLchan *src = tempImage;
1856 GLubyte *dstImage = (GLubyte *) dstAddr
1857 + dstZoffset * dstImageStride
1858 + dstYoffset * dstRowStride
1859 + dstXoffset * dstFormat->TexelBytes;
1860 GLint img, row, col;
1861 if (!tempImage)
1862 return GL_FALSE;
1863 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
1864 for (img = 0; img < srcDepth; img++) {
1865 GLubyte *dstRow = dstImage;
1866 for (row = 0; row < srcHeight; row++) {
1867 for (col = 0; col < srcWidth; col++) {
1868 dstRow[col] = CHAN_TO_UBYTE(src[col]);
1869 }
1870 dstRow += dstRowStride;
1871 src += srcWidth;
1872 }
1873 dstImage += dstImageStride;
1874 }
1875 _mesa_free((void *) tempImage);
1876 }
1877 return GL_TRUE;
1878 }
1879
1880
1881
1882 GLboolean
1883 _mesa_texstore_ci8(STORE_PARAMS)
1884 {
1885 (void) dims; (void) baseInternalFormat;
1886 ASSERT(dstFormat == &_mesa_texformat_ci8);
1887 ASSERT(dstFormat->TexelBytes == 1);
1888 ASSERT(baseInternalFormat == GL_COLOR_INDEX);
1889
1890 if (!ctx->_ImageTransferState &&
1891 !srcPacking->SwapBytes &&
1892 srcFormat == GL_COLOR_INDEX &&
1893 srcType == GL_UNSIGNED_BYTE) {
1894 /* simple memcpy path */
1895 memcpy_texture(ctx, dims,
1896 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1897 dstRowStride, dstImageStride,
1898 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1899 srcAddr, srcPacking);
1900 }
1901 else {
1902 /* general path */
1903 GLubyte *dstImage = (GLubyte *) dstAddr
1904 + dstZoffset * dstImageStride
1905 + dstYoffset * dstRowStride
1906 + dstXoffset * dstFormat->TexelBytes;
1907 GLint img, row;
1908 for (img = 0; img < srcDepth; img++) {
1909 GLubyte *dstRow = dstImage;
1910 for (row = 0; row < srcHeight; row++) {
1911 const GLvoid *src = _mesa_image_address(dims, srcPacking,
1912 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
1913 _mesa_unpack_index_span(ctx, srcWidth, GL_UNSIGNED_BYTE, dstRow,
1914 srcType, src, srcPacking,
1915 ctx->_ImageTransferState);
1916 dstRow += dstRowStride;
1917 }
1918 dstImage += dstImageStride;
1919 }
1920 }
1921 return GL_TRUE;
1922 }
1923
1924
1925 /**
1926 * Texstore for _mesa_texformat_ycbcr or _mesa_texformat_ycbcr_rev.
1927 */
1928 GLboolean
1929 _mesa_texstore_ycbcr(STORE_PARAMS)
1930 {
1931 const GLuint ui = 1;
1932 const GLubyte littleEndian = *((const GLubyte *) &ui);
1933 (void) ctx; (void) dims; (void) baseInternalFormat;
1934
1935 ASSERT((dstFormat == &_mesa_texformat_ycbcr) ||
1936 (dstFormat == &_mesa_texformat_ycbcr_rev));
1937 ASSERT(dstFormat->TexelBytes == 2);
1938 ASSERT(ctx->Extensions.MESA_ycbcr_texture);
1939 ASSERT(srcFormat == GL_YCBCR_MESA);
1940 ASSERT((srcType == GL_UNSIGNED_SHORT_8_8_MESA) ||
1941 (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA));
1942 ASSERT(baseInternalFormat == GL_YCBCR_MESA);
1943
1944 /* always just memcpy since no pixel transfer ops apply */
1945 memcpy_texture(ctx, dims,
1946 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1947 dstRowStride, dstImageStride,
1948 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1949 srcAddr, srcPacking);
1950
1951 /* Check if we need byte swapping */
1952 /* XXX the logic here _might_ be wrong */
1953 if (srcPacking->SwapBytes ^
1954 (srcType == GL_UNSIGNED_SHORT_8_8_REV_MESA) ^
1955 (dstFormat == &_mesa_texformat_ycbcr_rev) ^
1956 !littleEndian) {
1957 GLubyte *pImage = (GLubyte *) dstAddr
1958 + dstZoffset * dstImageStride
1959 + dstYoffset * dstRowStride
1960 + dstXoffset * dstFormat->TexelBytes;
1961 GLint img, row;
1962 for (img = 0; img < srcDepth; img++) {
1963 GLubyte *pRow = pImage;
1964 for (row = 0; row < srcHeight; row++) {
1965 _mesa_swap2((GLushort *) pRow, srcWidth);
1966 pRow += dstRowStride;
1967 }
1968 pImage += dstImageStride;
1969 }
1970 }
1971 return GL_TRUE;
1972 }
1973
1974
1975
1976 /**
1977 * Store a combined depth/stencil texture image.
1978 */
1979 GLboolean
1980 _mesa_texstore_z24_s8(STORE_PARAMS)
1981 {
1982 ASSERT(dstFormat == &_mesa_texformat_z24_s8);
1983 ASSERT(srcFormat == GL_DEPTH_STENCIL_EXT);
1984 ASSERT(srcType == GL_UNSIGNED_INT_24_8_EXT);
1985
1986 if (!ctx->_ImageTransferState &&
1987 !srcPacking->SwapBytes) {
1988 /* simple path */
1989 memcpy_texture(ctx, dims,
1990 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
1991 dstRowStride, dstImageStride,
1992 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
1993 srcAddr, srcPacking);
1994 }
1995 else {
1996 /* general path */
1997 const GLint srcRowStride
1998 = _mesa_image_row_stride(srcPacking, srcWidth, srcFormat, srcType)
1999 / sizeof(GLuint);
2000 GLuint *dstImage = (GLuint *) dstAddr;
2001 GLint img, row;
2002
2003 for (img = 0; img < srcDepth; img++) {
2004 GLuint *dst = dstImage;
2005 const GLuint *src
2006 = (const GLuint *) _mesa_image_address(dims, srcPacking, srcAddr,
2007 srcWidth, srcHeight,
2008 srcFormat, srcType,
2009 img, 0, 0);
2010 for (row = 0; row < srcHeight; row++) {
2011 GLubyte stencil[MAX_WIDTH];
2012 GLint i;
2013 /* the 24 depth bits will be in the high position: */
2014 _mesa_unpack_depth_span(ctx, srcWidth,
2015 GL_UNSIGNED_INT, /* dst type */
2016 dst, /* dst addr */
2017 (GLfloat) 0xffffff, /* depthScale */
2018 srcType, src, srcPacking);
2019 /* get the 8-bit stencil values */
2020 _mesa_unpack_stencil_span(ctx, srcWidth,
2021 GL_UNSIGNED_BYTE, /* dst type */
2022 stencil, /* dst addr */
2023 srcType, src, srcPacking,
2024 ctx->_ImageTransferState);
2025 /* merge stencil values into depth values */
2026 for (i = 0; i < srcWidth; i++)
2027 dst[i] |= stencil[i];
2028
2029 src += srcRowStride;
2030 dst += dstRowStride / sizeof(GLuint);
2031 }
2032 dstImage += dstImageStride / sizeof(GLuint);
2033 }
2034 }
2035
2036
2037 return GL_TRUE;
2038 }
2039
2040
2041
2042 /**
2043 * Store an image in any of the formats:
2044 * _mesa_texformat_rgba_float32
2045 * _mesa_texformat_rgb_float32
2046 * _mesa_texformat_alpha_float32
2047 * _mesa_texformat_luminance_float32
2048 * _mesa_texformat_luminance_alpha_float32
2049 * _mesa_texformat_intensity_float32
2050 */
2051 GLboolean
2052 _mesa_texstore_rgba_float32(STORE_PARAMS)
2053 {
2054 const GLint components = _mesa_components_in_format(baseInternalFormat);
2055
2056 ASSERT(dstFormat == &_mesa_texformat_rgba_float32 ||
2057 dstFormat == &_mesa_texformat_rgb_float32 ||
2058 dstFormat == &_mesa_texformat_alpha_float32 ||
2059 dstFormat == &_mesa_texformat_luminance_float32 ||
2060 dstFormat == &_mesa_texformat_luminance_alpha_float32 ||
2061 dstFormat == &_mesa_texformat_intensity_float32);
2062 ASSERT(baseInternalFormat == GL_RGBA ||
2063 baseInternalFormat == GL_RGB ||
2064 baseInternalFormat == GL_ALPHA ||
2065 baseInternalFormat == GL_LUMINANCE ||
2066 baseInternalFormat == GL_LUMINANCE_ALPHA ||
2067 baseInternalFormat == GL_INTENSITY);
2068 ASSERT(dstFormat->TexelBytes == components * sizeof(GLfloat));
2069
2070 if (!ctx->_ImageTransferState &&
2071 !srcPacking->SwapBytes &&
2072 baseInternalFormat == srcFormat &&
2073 srcType == GL_FLOAT) {
2074 /* simple memcpy path */
2075 memcpy_texture(ctx, dims,
2076 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2077 dstRowStride, dstImageStride,
2078 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2079 srcAddr, srcPacking);
2080 }
2081 else {
2082 /* general path */
2083 const GLfloat *tempImage = make_temp_float_image(ctx, dims,
2084 baseInternalFormat,
2085 dstFormat->BaseFormat,
2086 srcWidth, srcHeight, srcDepth,
2087 srcFormat, srcType, srcAddr,
2088 srcPacking);
2089 const GLfloat *src = tempImage;
2090 GLint bytesPerRow;
2091 GLubyte *dstImage = (GLubyte *) dstAddr
2092 + dstZoffset * dstImageStride
2093 + dstYoffset * dstRowStride
2094 + dstXoffset * dstFormat->TexelBytes;
2095 GLint img, row;
2096 if (!tempImage)
2097 return GL_FALSE;
2098 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
2099 bytesPerRow = srcWidth * components * sizeof(GLfloat);
2100 for (img = 0; img < srcDepth; img++) {
2101 GLubyte *dst = dstImage;
2102 for (row = 0; row < srcHeight; row++) {
2103 _mesa_memcpy(dst, src, bytesPerRow);
2104 dst += dstRowStride;
2105 src += srcWidth * components;
2106 }
2107 dstImage += dstImageStride;
2108 }
2109
2110 _mesa_free((void *) tempImage);
2111 }
2112 return GL_TRUE;
2113 }
2114
2115
2116 /**
2117 * As above, but store 16-bit floats.
2118 */
2119 GLboolean
2120 _mesa_texstore_rgba_float16(STORE_PARAMS)
2121 {
2122 const GLint components = _mesa_components_in_format(baseInternalFormat);
2123
2124 ASSERT(dstFormat == &_mesa_texformat_rgba_float16 ||
2125 dstFormat == &_mesa_texformat_rgb_float16 ||
2126 dstFormat == &_mesa_texformat_alpha_float16 ||
2127 dstFormat == &_mesa_texformat_luminance_float16 ||
2128 dstFormat == &_mesa_texformat_luminance_alpha_float16 ||
2129 dstFormat == &_mesa_texformat_intensity_float16);
2130 ASSERT(baseInternalFormat == GL_RGBA ||
2131 baseInternalFormat == GL_RGB ||
2132 baseInternalFormat == GL_ALPHA ||
2133 baseInternalFormat == GL_LUMINANCE ||
2134 baseInternalFormat == GL_LUMINANCE_ALPHA ||
2135 baseInternalFormat == GL_INTENSITY);
2136 ASSERT(dstFormat->TexelBytes == components * sizeof(GLhalfARB));
2137
2138 if (!ctx->_ImageTransferState &&
2139 !srcPacking->SwapBytes &&
2140 baseInternalFormat == srcFormat &&
2141 srcType == GL_HALF_FLOAT_ARB) {
2142 /* simple memcpy path */
2143 memcpy_texture(ctx, dims,
2144 dstFormat, dstAddr, dstXoffset, dstYoffset, dstZoffset,
2145 dstRowStride, dstImageStride,
2146 srcWidth, srcHeight, srcDepth, srcFormat, srcType,
2147 srcAddr, srcPacking);
2148 }
2149 else {
2150 /* general path */
2151 const GLfloat *tempImage = make_temp_float_image(ctx, dims,
2152 baseInternalFormat,
2153 dstFormat->BaseFormat,
2154 srcWidth, srcHeight, srcDepth,
2155 srcFormat, srcType, srcAddr,
2156 srcPacking);
2157 const GLfloat *src = tempImage;
2158 GLubyte *dstImage = (GLubyte *) dstAddr
2159 + dstZoffset * dstImageStride
2160 + dstYoffset * dstRowStride
2161 + dstXoffset * dstFormat->TexelBytes;
2162 GLint img, row;
2163 if (!tempImage)
2164 return GL_FALSE;
2165 _mesa_adjust_image_for_convolution(ctx, dims, &srcWidth, &srcHeight);
2166 for (img = 0; img < srcDepth; img++) {
2167 GLubyte *dstRow = dstImage;
2168 for (row = 0; row < srcHeight; row++) {
2169 GLhalfARB *dstTexel = (GLhalfARB *) dstRow;
2170 GLint i;
2171 for (i = 0; i < srcWidth * components; i++) {
2172 dstTexel[i] = _mesa_float_to_half(src[i]);
2173 }
2174 dstRow += dstRowStride;
2175 src += srcWidth * components;
2176 }
2177 dstImage += dstImageStride;
2178 }
2179
2180 _mesa_free((void *) tempImage);
2181 }
2182 return GL_TRUE;
2183 }
2184
2185
2186
2187 /**
2188 * Check if an unpack PBO is active prior to fetching a texture image.
2189 * If so, do bounds checking and map the buffer into main memory.
2190 * Any errors detected will be recorded.
2191 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2192 */
2193 const GLvoid *
2194 _mesa_validate_pbo_teximage(GLcontext *ctx, GLuint dimensions,
2195 GLsizei width, GLsizei height, GLsizei depth,
2196 GLenum format, GLenum type, const GLvoid *pixels,
2197 const struct gl_pixelstore_attrib *unpack,
2198 const char *funcName)
2199 {
2200 GLubyte *buf;
2201
2202 if (unpack->BufferObj->Name == 0) {
2203 /* no PBO */
2204 return pixels;
2205 }
2206 if (!_mesa_validate_pbo_access(dimensions, unpack, width, height, depth,
2207 format, type, pixels)) {
2208 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access");
2209 return NULL;
2210 }
2211
2212 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
2213 GL_READ_ONLY_ARB, unpack->BufferObj);
2214 if (!buf) {
2215 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped");
2216 return NULL;
2217 }
2218
2219 return ADD_POINTERS(buf, pixels);
2220 }
2221
2222
2223 /**
2224 * Check if an unpack PBO is active prior to fetching a compressed texture
2225 * image.
2226 * If so, do bounds checking and map the buffer into main memory.
2227 * Any errors detected will be recorded.
2228 * The caller _must_ call _mesa_unmap_teximage_pbo() too!
2229 */
2230 const GLvoid *
2231 _mesa_validate_pbo_compressed_teximage(GLcontext *ctx,
2232 GLsizei imageSize, const GLvoid *pixels,
2233 const struct gl_pixelstore_attrib *packing,
2234 const char *funcName)
2235 {
2236 GLubyte *buf;
2237
2238 if (packing->BufferObj->Name == 0) {
2239 /* not using a PBO - return pointer unchanged */
2240 return pixels;
2241 }
2242 if ((const GLubyte *) pixels + imageSize >
2243 ((const GLubyte *) 0) + packing->BufferObj->Size) {
2244 /* out of bounds read! */
2245 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(invalid PBO access");
2246 return NULL;
2247 }
2248
2249 buf = (GLubyte*) ctx->Driver.MapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
2250 GL_READ_ONLY_ARB, packing->BufferObj);
2251 if (!buf) {
2252 _mesa_error(ctx, GL_INVALID_OPERATION, funcName, "(PBO is mapped");
2253 return NULL;
2254 }
2255
2256 return ADD_POINTERS(buf, pixels);
2257 }
2258
2259
2260 /**
2261 * This function must be called after either of the validate_pbo_*_teximage()
2262 * functions. It unmaps the PBO buffer if it was mapped earlier.
2263 */
2264 void
2265 _mesa_unmap_teximage_pbo(GLcontext *ctx,
2266 const struct gl_pixelstore_attrib *unpack)
2267 {
2268 if (unpack->BufferObj->Name) {
2269 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_UNPACK_BUFFER_EXT,
2270 unpack->BufferObj);
2271 }
2272 }
2273
2274
2275
2276 /**
2277 * Adaptor for fetching a GLchan texel from a float-valued texture.
2278 */
2279 static void
2280 FetchTexelFloatToChan( const struct gl_texture_image *texImage,
2281 GLint i, GLint j, GLint k, GLchan *texelOut )
2282 {
2283 GLfloat temp[4];
2284 ASSERT(texImage->FetchTexelf);
2285 texImage->FetchTexelf(texImage, i, j, k, temp);
2286 if (texImage->TexFormat->BaseFormat == GL_DEPTH_COMPONENT) {
2287 /* just one channel */
2288 UNCLAMPED_FLOAT_TO_CHAN(texelOut[0], temp[0]);
2289 }
2290 else {
2291 /* four channels */
2292 UNCLAMPED_FLOAT_TO_CHAN(texelOut[0], temp[0]);
2293 UNCLAMPED_FLOAT_TO_CHAN(texelOut[1], temp[1]);
2294 UNCLAMPED_FLOAT_TO_CHAN(texelOut[2], temp[2]);
2295 UNCLAMPED_FLOAT_TO_CHAN(texelOut[3], temp[3]);
2296 }
2297 }
2298
2299
2300 /**
2301 * Adaptor for fetching a float texel from a GLchan-valued texture.
2302 */
2303 static void
2304 FetchTexelChanToFloat( const struct gl_texture_image *texImage,
2305 GLint i, GLint j, GLint k, GLfloat *texelOut )
2306 {
2307 GLchan temp[4];
2308 ASSERT(texImage->FetchTexelc);
2309 texImage->FetchTexelc(texImage, i, j, k, temp);
2310 if (texImage->TexFormat->BaseFormat == GL_DEPTH_COMPONENT) {
2311 /* just one channel */
2312 texelOut[0] = CHAN_TO_FLOAT(temp[0]);
2313 }
2314 else {
2315 /* four channels */
2316 texelOut[0] = CHAN_TO_FLOAT(temp[0]);
2317 texelOut[1] = CHAN_TO_FLOAT(temp[1]);
2318 texelOut[2] = CHAN_TO_FLOAT(temp[2]);
2319 texelOut[3] = CHAN_TO_FLOAT(temp[3]);
2320 }
2321 }
2322
2323
2324 /**
2325 * Initialize the texture image's FetchTexelc and FetchTexelf methods.
2326 */
2327 static void
2328 set_fetch_functions(struct gl_texture_image *texImage, GLuint dims)
2329 {
2330 ASSERT(dims == 1 || dims == 2 || dims == 3);
2331 ASSERT(texImage->TexFormat);
2332
2333 switch (dims) {
2334 case 1:
2335 texImage->FetchTexelc = texImage->TexFormat->FetchTexel1D;
2336 texImage->FetchTexelf = texImage->TexFormat->FetchTexel1Df;
2337 break;
2338 case 2:
2339 texImage->FetchTexelc = texImage->TexFormat->FetchTexel2D;
2340 texImage->FetchTexelf = texImage->TexFormat->FetchTexel2Df;
2341 break;
2342 case 3:
2343 texImage->FetchTexelc = texImage->TexFormat->FetchTexel3D;
2344 texImage->FetchTexelf = texImage->TexFormat->FetchTexel3Df;
2345 break;
2346 default:
2347 ;
2348 }
2349
2350 /* now check if we need to use a float/chan adaptor */
2351 if (!texImage->FetchTexelc) {
2352 texImage->FetchTexelc = FetchTexelFloatToChan;
2353 }
2354 else if (!texImage->FetchTexelf) {
2355 texImage->FetchTexelf = FetchTexelChanToFloat;
2356 }
2357
2358
2359 ASSERT(texImage->FetchTexelc);
2360 ASSERT(texImage->FetchTexelf);
2361 }
2362
2363
2364 /*
2365 * This is the software fallback for Driver.TexImage1D()
2366 * and Driver.CopyTexImage1D().
2367 * \sa _mesa_store_teximage2d()
2368 */
2369 void
2370 _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level,
2371 GLint internalFormat,
2372 GLint width, GLint border,
2373 GLenum format, GLenum type, const GLvoid *pixels,
2374 const struct gl_pixelstore_attrib *packing,
2375 struct gl_texture_object *texObj,
2376 struct gl_texture_image *texImage)
2377 {
2378 GLint postConvWidth = width;
2379 GLint sizeInBytes;
2380 (void) border;
2381
2382 if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
2383 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2384 }
2385
2386 /* choose the texture format */
2387 assert(ctx->Driver.ChooseTextureFormat);
2388 texImage->TexFormat = ctx->Driver.ChooseTextureFormat(ctx, internalFormat,
2389 format, type);
2390 assert(texImage->TexFormat);
2391 set_fetch_functions(texImage, 1);
2392
2393 /* allocate memory */
2394 if (texImage->IsCompressed)
2395 sizeInBytes = texImage->CompressedSize;
2396 else
2397 sizeInBytes = postConvWidth * texImage->TexFormat->TexelBytes;
2398 texImage->Data = _mesa_alloc_texmemory(sizeInBytes);
2399 if (!texImage->Data) {
2400 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
2401 return;
2402 }
2403
2404 pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type,
2405 pixels, packing, "glTexImage1D");
2406 if (!pixels) {
2407 /* Note: we check for a NULL image pointer here, _after_ we allocated
2408 * memory for the texture. That's what the GL spec calls for.
2409 */
2410 return;
2411 }
2412 else {
2413 const GLint dstRowStride = 0, dstImageStride = 0;
2414 GLboolean success;
2415 ASSERT(texImage->TexFormat->StoreImage);
2416 success = texImage->TexFormat->StoreImage(ctx, 1, texImage->_BaseFormat,
2417 texImage->TexFormat,
2418 texImage->Data,
2419 0, 0, 0, /* dstX/Y/Zoffset */
2420 dstRowStride, dstImageStride,
2421 width, 1, 1,
2422 format, type, pixels, packing);
2423 if (!success) {
2424 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
2425 }
2426 }
2427
2428 /* GL_SGIS_generate_mipmap */
2429 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
2430 _mesa_generate_mipmap(ctx, target,
2431 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
2432 texObj);
2433 }
2434
2435 _mesa_unmap_teximage_pbo(ctx, packing);
2436 }
2437
2438
2439 /**
2440 * This is the software fallback for Driver.TexImage2D()
2441 * and Driver.CopyTexImage2D().
2442 * We store the image in heap memory. We know nothing about on-board
2443 * VRAM here. But since most DRI drivers rely on keeping a copy of all
2444 * textures in main memory, this routine will typically be used by
2445 * hardware drivers too.
2446 *
2447 * Reasons why a driver might override this function:
2448 * - Special memory allocation needs (VRAM, AGP, etc)
2449 * - Unusual row/image strides or padding
2450 * - Special housekeeping
2451 * - Using VRAM-based Pixel Buffer Objects
2452 */
2453 void
2454 _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level,
2455 GLint internalFormat,
2456 GLint width, GLint height, GLint border,
2457 GLenum format, GLenum type, const void *pixels,
2458 const struct gl_pixelstore_attrib *packing,
2459 struct gl_texture_object *texObj,
2460 struct gl_texture_image *texImage)
2461 {
2462 GLint postConvWidth = width, postConvHeight = height;
2463 GLint texelBytes, sizeInBytes;
2464 (void) border;
2465
2466 if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
2467 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
2468 &postConvHeight);
2469 }
2470
2471 /* choose the texture format */
2472 assert(ctx->Driver.ChooseTextureFormat);
2473 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
2474 internalFormat, format, type);
2475 assert(texImage->TexFormat);
2476 set_fetch_functions(texImage, 2);
2477
2478 texelBytes = texImage->TexFormat->TexelBytes;
2479
2480 /* allocate memory */
2481 if (texImage->IsCompressed)
2482 sizeInBytes = texImage->CompressedSize;
2483 else
2484 sizeInBytes = postConvWidth * postConvHeight * texelBytes;
2485 texImage->Data = _mesa_alloc_texmemory(sizeInBytes);
2486 if (!texImage->Data) {
2487 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
2488 return;
2489 }
2490
2491 pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type,
2492 pixels, packing, "glTexImage2D");
2493 if (!pixels) {
2494 /* Note: we check for a NULL image pointer here, _after_ we allocated
2495 * memory for the texture. That's what the GL spec calls for.
2496 */
2497 return;
2498 }
2499 else {
2500 GLint dstRowStride, dstImageStride = 0;
2501 GLboolean success;
2502 if (texImage->IsCompressed) {
2503 dstRowStride
2504 = _mesa_compressed_row_stride(texImage->InternalFormat,width);
2505 }
2506 else {
2507 dstRowStride = postConvWidth * texImage->TexFormat->TexelBytes;
2508 }
2509 ASSERT(texImage->TexFormat->StoreImage);
2510 success = texImage->TexFormat->StoreImage(ctx, 2, texImage->_BaseFormat,
2511 texImage->TexFormat,
2512 texImage->Data,
2513 0, 0, 0, /* dstX/Y/Zoffset */
2514 dstRowStride, dstImageStride,
2515 width, height, 1,
2516 format, type, pixels, packing);
2517 if (!success) {
2518 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
2519 }
2520 }
2521
2522 /* GL_SGIS_generate_mipmap */
2523 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
2524 _mesa_generate_mipmap(ctx, target,
2525 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
2526 texObj);
2527 }
2528
2529 _mesa_unmap_teximage_pbo(ctx, packing);
2530 }
2531
2532
2533
2534 /**
2535 * This is the software fallback for Driver.TexImage3D()
2536 * and Driver.CopyTexImage3D().
2537 * \sa _mesa_store_teximage2d()
2538 */
2539 void
2540 _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level,
2541 GLint internalFormat,
2542 GLint width, GLint height, GLint depth, GLint border,
2543 GLenum format, GLenum type, const void *pixels,
2544 const struct gl_pixelstore_attrib *packing,
2545 struct gl_texture_object *texObj,
2546 struct gl_texture_image *texImage)
2547 {
2548 GLint texelBytes, sizeInBytes;
2549 (void) border;
2550
2551 /* choose the texture format */
2552 assert(ctx->Driver.ChooseTextureFormat);
2553 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
2554 internalFormat, format, type);
2555 assert(texImage->TexFormat);
2556 set_fetch_functions(texImage, 3);
2557
2558 texelBytes = texImage->TexFormat->TexelBytes;
2559
2560 /* allocate memory */
2561 if (texImage->IsCompressed)
2562 sizeInBytes = texImage->CompressedSize;
2563 else
2564 sizeInBytes = width * height * depth * texelBytes;
2565 texImage->Data = _mesa_alloc_texmemory(sizeInBytes);
2566 if (!texImage->Data) {
2567 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
2568 return;
2569 }
2570
2571 pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, format,
2572 type, pixels, packing, "glTexImage3D");
2573 if (!pixels) {
2574 /* Note: we check for a NULL image pointer here, _after_ we allocated
2575 * memory for the texture. That's what the GL spec calls for.
2576 */
2577 return;
2578 }
2579 else {
2580 GLint dstRowStride, dstImageStride;
2581 GLboolean success;
2582 if (texImage->IsCompressed) {
2583 dstRowStride
2584 = _mesa_compressed_row_stride(texImage->InternalFormat,width);
2585 dstImageStride = 0;
2586 }
2587 else {
2588 dstRowStride = width * texImage->TexFormat->TexelBytes;
2589 dstImageStride = dstRowStride * height;
2590 }
2591 ASSERT(texImage->TexFormat->StoreImage);
2592 success = texImage->TexFormat->StoreImage(ctx, 3, texImage->_BaseFormat,
2593 texImage->TexFormat,
2594 texImage->Data,
2595 0, 0, 0, /* dstX/Y/Zoffset */
2596 dstRowStride, dstImageStride,
2597 width, height, depth,
2598 format, type, pixels, packing);
2599 if (!success) {
2600 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
2601 }
2602 }
2603
2604 /* GL_SGIS_generate_mipmap */
2605 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
2606 _mesa_generate_mipmap(ctx, target,
2607 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
2608 texObj);
2609 }
2610
2611 _mesa_unmap_teximage_pbo(ctx, packing);
2612 }
2613
2614
2615
2616
2617 /*
2618 * This is the software fallback for Driver.TexSubImage1D()
2619 * and Driver.CopyTexSubImage1D().
2620 */
2621 void
2622 _mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level,
2623 GLint xoffset, GLint width,
2624 GLenum format, GLenum type, const void *pixels,
2625 const struct gl_pixelstore_attrib *packing,
2626 struct gl_texture_object *texObj,
2627 struct gl_texture_image *texImage)
2628 {
2629 pixels = _mesa_validate_pbo_teximage(ctx, 1, width, 1, 1, format, type,
2630 pixels, packing, "glTexSubImage1D");
2631 if (!pixels)
2632 return;
2633
2634 {
2635 const GLint dstRowStride = 0, dstImageStride = 0;
2636 GLboolean success;
2637 ASSERT(texImage->TexFormat->StoreImage);
2638 success = texImage->TexFormat->StoreImage(ctx, 1, texImage->_BaseFormat,
2639 texImage->TexFormat,
2640 texImage->Data,
2641 xoffset, 0, 0, /* offsets */
2642 dstRowStride, dstImageStride,
2643 width, 1, 1,
2644 format, type, pixels, packing);
2645 if (!success) {
2646 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
2647 }
2648 }
2649
2650 /* GL_SGIS_generate_mipmap */
2651 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
2652 _mesa_generate_mipmap(ctx, target,
2653 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
2654 texObj);
2655 }
2656
2657 _mesa_unmap_teximage_pbo(ctx, packing);
2658 }
2659
2660
2661
2662 /**
2663 * This is the software fallback for Driver.TexSubImage2D()
2664 * and Driver.CopyTexSubImage2D().
2665 */
2666 void
2667 _mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level,
2668 GLint xoffset, GLint yoffset,
2669 GLint width, GLint height,
2670 GLenum format, GLenum type, const void *pixels,
2671 const struct gl_pixelstore_attrib *packing,
2672 struct gl_texture_object *texObj,
2673 struct gl_texture_image *texImage)
2674 {
2675 pixels = _mesa_validate_pbo_teximage(ctx, 2, width, height, 1, format, type,
2676 pixels, packing, "glTexSubImage2D");
2677 if (!pixels)
2678 return;
2679
2680 {
2681 GLint dstRowStride = 0, dstImageStride = 0;
2682 GLboolean success;
2683 if (texImage->IsCompressed) {
2684 dstRowStride = _mesa_compressed_row_stride(texImage->InternalFormat,
2685 texImage->Width);
2686 }
2687 else {
2688 dstRowStride = texImage->Width * texImage->TexFormat->TexelBytes;
2689 }
2690 ASSERT(texImage->TexFormat->StoreImage);
2691 success = texImage->TexFormat->StoreImage(ctx, 2, texImage->_BaseFormat,
2692 texImage->TexFormat,
2693 texImage->Data,
2694 xoffset, yoffset, 0,
2695 dstRowStride, dstImageStride,
2696 width, height, 1,
2697 format, type, pixels, packing);
2698 if (!success) {
2699 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage2D");
2700 }
2701 }
2702
2703 /* GL_SGIS_generate_mipmap */
2704 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
2705 _mesa_generate_mipmap(ctx, target,
2706 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
2707 texObj);
2708 }
2709
2710 _mesa_unmap_teximage_pbo(ctx, packing);
2711 }
2712
2713
2714 /*
2715 * This is the software fallback for Driver.TexSubImage3D().
2716 * and Driver.CopyTexSubImage3D().
2717 */
2718 void
2719 _mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level,
2720 GLint xoffset, GLint yoffset, GLint zoffset,
2721 GLint width, GLint height, GLint depth,
2722 GLenum format, GLenum type, const void *pixels,
2723 const struct gl_pixelstore_attrib *packing,
2724 struct gl_texture_object *texObj,
2725 struct gl_texture_image *texImage)
2726 {
2727 pixels = _mesa_validate_pbo_teximage(ctx, 3, width, height, depth, format,
2728 type, pixels, packing,
2729 "glTexSubImage3D");
2730 if (!pixels)
2731 return;
2732
2733 {
2734 GLint dstRowStride, dstImageStride;
2735 GLboolean success;
2736 if (texImage->IsCompressed) {
2737 dstRowStride = _mesa_compressed_row_stride(texImage->InternalFormat,
2738 texImage->Width);
2739 dstImageStride = 0; /* XXX fix */
2740 }
2741 else {
2742 dstRowStride = texImage->Width * texImage->TexFormat->TexelBytes;
2743 dstImageStride = dstRowStride * texImage->Height;
2744 }
2745 ASSERT(texImage->TexFormat->StoreImage);
2746 success = texImage->TexFormat->StoreImage(ctx, 3, texImage->_BaseFormat,
2747 texImage->TexFormat,
2748 texImage->Data,
2749 xoffset, yoffset, zoffset,
2750 dstRowStride, dstImageStride,
2751 width, height, depth,
2752 format, type, pixels, packing);
2753 if (!success) {
2754 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage3D");
2755 }
2756 }
2757
2758 /* GL_SGIS_generate_mipmap */
2759 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
2760 _mesa_generate_mipmap(ctx, target,
2761 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
2762 texObj);
2763 }
2764
2765 _mesa_unmap_teximage_pbo(ctx, packing);
2766 }
2767
2768
2769 /*
2770 * Fallback for Driver.CompressedTexImage1D()
2771 */
2772 void
2773 _mesa_store_compressed_teximage1d(GLcontext *ctx, GLenum target, GLint level,
2774 GLint internalFormat,
2775 GLint width, GLint border,
2776 GLsizei imageSize, const GLvoid *data,
2777 struct gl_texture_object *texObj,
2778 struct gl_texture_image *texImage)
2779 {
2780 /* this space intentionally left blank */
2781 (void) ctx;
2782 (void) target; (void) level;
2783 (void) internalFormat;
2784 (void) width; (void) border;
2785 (void) imageSize; (void) data;
2786 (void) texObj;
2787 (void) texImage;
2788 }
2789
2790
2791
2792 /*
2793 * Fallback for Driver.CompressedTexImage2D()
2794 */
2795 void
2796 _mesa_store_compressed_teximage2d(GLcontext *ctx, GLenum target, GLint level,
2797 GLint internalFormat,
2798 GLint width, GLint height, GLint border,
2799 GLsizei imageSize, const GLvoid *data,
2800 struct gl_texture_object *texObj,
2801 struct gl_texture_image *texImage)
2802 {
2803 (void) width; (void) height; (void) border;
2804
2805 /* This is pretty simple, basically just do a memcpy without worrying
2806 * about the usual image unpacking or image transfer operations.
2807 */
2808 ASSERT(texObj);
2809 ASSERT(texImage);
2810 ASSERT(texImage->Width > 0);
2811 ASSERT(texImage->Height > 0);
2812 ASSERT(texImage->Depth == 1);
2813 ASSERT(texImage->Data == NULL); /* was freed in glCompressedTexImage2DARB */
2814
2815 /* choose the texture format */
2816 assert(ctx->Driver.ChooseTextureFormat);
2817 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
2818 internalFormat, 0, 0);
2819 assert(texImage->TexFormat);
2820 set_fetch_functions(texImage, 2);
2821
2822 /* allocate storage */
2823 texImage->Data = _mesa_alloc_texmemory(imageSize);
2824 if (!texImage->Data) {
2825 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB");
2826 return;
2827 }
2828
2829 data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data,
2830 &ctx->Unpack,
2831 "glCompressedTexImage2D");
2832 if (!data)
2833 return;
2834
2835 /* copy the data */
2836 ASSERT(texImage->CompressedSize == (GLuint) imageSize);
2837 MEMCPY(texImage->Data, data, imageSize);
2838
2839 /* GL_SGIS_generate_mipmap */
2840 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
2841 _mesa_generate_mipmap(ctx, target,
2842 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
2843 texObj);
2844 }
2845
2846 _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack);
2847 }
2848
2849
2850
2851 /*
2852 * Fallback for Driver.CompressedTexImage3D()
2853 */
2854 void
2855 _mesa_store_compressed_teximage3d(GLcontext *ctx, GLenum target, GLint level,
2856 GLint internalFormat,
2857 GLint width, GLint height, GLint depth,
2858 GLint border,
2859 GLsizei imageSize, const GLvoid *data,
2860 struct gl_texture_object *texObj,
2861 struct gl_texture_image *texImage)
2862 {
2863 /* this space intentionally left blank */
2864 (void) ctx;
2865 (void) target; (void) level;
2866 (void) internalFormat;
2867 (void) width; (void) height; (void) depth;
2868 (void) border;
2869 (void) imageSize; (void) data;
2870 (void) texObj;
2871 (void) texImage;
2872 }
2873
2874
2875
2876 /**
2877 * Fallback for Driver.CompressedTexSubImage1D()
2878 */
2879 void
2880 _mesa_store_compressed_texsubimage1d(GLcontext *ctx, GLenum target,
2881 GLint level,
2882 GLint xoffset, GLsizei width,
2883 GLenum format,
2884 GLsizei imageSize, const GLvoid *data,
2885 struct gl_texture_object *texObj,
2886 struct gl_texture_image *texImage)
2887 {
2888 /* this space intentionally left blank */
2889 (void) ctx;
2890 (void) target; (void) level;
2891 (void) xoffset; (void) width;
2892 (void) format;
2893 (void) imageSize; (void) data;
2894 (void) texObj;
2895 (void) texImage;
2896 }
2897
2898
2899 /**
2900 * Fallback for Driver.CompressedTexSubImage2D()
2901 */
2902 void
2903 _mesa_store_compressed_texsubimage2d(GLcontext *ctx, GLenum target,
2904 GLint level,
2905 GLint xoffset, GLint yoffset,
2906 GLsizei width, GLsizei height,
2907 GLenum format,
2908 GLsizei imageSize, const GLvoid *data,
2909 struct gl_texture_object *texObj,
2910 struct gl_texture_image *texImage)
2911 {
2912 GLint bytesPerRow, destRowStride, srcRowStride;
2913 GLint i, rows;
2914 GLubyte *dest;
2915 const GLubyte *src;
2916 (void) format;
2917
2918 /* these should have been caught sooner */
2919 ASSERT((width & 3) == 0 || width == 2 || width == 1);
2920 ASSERT((height & 3) == 0 || height == 2 || height == 1);
2921 ASSERT((xoffset & 3) == 0);
2922 ASSERT((yoffset & 3) == 0);
2923
2924 data = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, data,
2925 &ctx->Unpack,
2926 "glCompressedTexSubImage2D");
2927 if (!data)
2928 return;
2929
2930 srcRowStride = _mesa_compressed_row_stride(texImage->InternalFormat, width);
2931 src = (const GLubyte *) data;
2932
2933 destRowStride = _mesa_compressed_row_stride(texImage->InternalFormat,
2934 texImage->Width);
2935 dest = _mesa_compressed_image_address(xoffset, yoffset, 0,
2936 texImage->InternalFormat,
2937 texImage->Width,
2938 (GLubyte*) texImage->Data);
2939
2940 bytesPerRow = srcRowStride;
2941 rows = height / 4;
2942
2943 for (i = 0; i < rows; i++) {
2944 MEMCPY(dest, src, bytesPerRow);
2945 dest += destRowStride;
2946 src += srcRowStride;
2947 }
2948
2949 /* GL_SGIS_generate_mipmap */
2950 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
2951 _mesa_generate_mipmap(ctx, target,
2952 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
2953 texObj);
2954 }
2955
2956 _mesa_unmap_teximage_pbo(ctx, &ctx->Unpack);
2957 }
2958
2959
2960 /**
2961 * Fallback for Driver.CompressedTexSubImage3D()
2962 */
2963 void
2964 _mesa_store_compressed_texsubimage3d(GLcontext *ctx, GLenum target,
2965 GLint level,
2966 GLint xoffset, GLint yoffset, GLint zoffset,
2967 GLsizei width, GLsizei height, GLsizei depth,
2968 GLenum format,
2969 GLsizei imageSize, const GLvoid *data,
2970 struct gl_texture_object *texObj,
2971 struct gl_texture_image *texImage)
2972 {
2973 /* this space intentionally left blank */
2974 (void) ctx;
2975 (void) target; (void) level;
2976 (void) xoffset; (void) yoffset; (void) zoffset;
2977 (void) width; (void) height; (void) depth;
2978 (void) format;
2979 (void) imageSize; (void) data;
2980 (void) texObj;
2981 (void) texImage;
2982 }
2983
2984
2985 /*
2986 * Average together two rows of a source image to produce a single new
2987 * row in the dest image. It's legal for the two source rows to point
2988 * to the same data. The source width must be equal to either the
2989 * dest width or two times the dest width.
2990 */
2991 static void
2992 do_row(const struct gl_texture_format *format, GLint srcWidth,
2993 const GLvoid *srcRowA, const GLvoid *srcRowB,
2994 GLint dstWidth, GLvoid *dstRow)
2995 {
2996 const GLuint k0 = (srcWidth == dstWidth) ? 0 : 1;
2997 const GLuint colStride = (srcWidth == dstWidth) ? 1 : 2;
2998
2999 /* This assertion is no longer valid with non-power-of-2 textures
3000 assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
3001 */
3002
3003 switch (format->MesaFormat) {
3004 case MESA_FORMAT_RGBA:
3005 {
3006 GLuint i, j, k;
3007 const GLchan (*rowA)[4] = (const GLchan (*)[4]) srcRowA;
3008 const GLchan (*rowB)[4] = (const GLchan (*)[4]) srcRowB;
3009 GLchan (*dst)[4] = (GLchan (*)[4]) dstRow;
3010 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3011 i++, j += colStride, k += colStride) {
3012 dst[i][0] = (rowA[j][0] + rowA[k][0] +
3013 rowB[j][0] + rowB[k][0]) / 4;
3014 dst[i][1] = (rowA[j][1] + rowA[k][1] +
3015 rowB[j][1] + rowB[k][1]) / 4;
3016 dst[i][2] = (rowA[j][2] + rowA[k][2] +
3017 rowB[j][2] + rowB[k][2]) / 4;
3018 dst[i][3] = (rowA[j][3] + rowA[k][3] +
3019 rowB[j][3] + rowB[k][3]) / 4;
3020 }
3021 }
3022 return;
3023 case MESA_FORMAT_RGB:
3024 {
3025 GLuint i, j, k;
3026 const GLchan (*rowA)[3] = (const GLchan (*)[3]) srcRowA;
3027 const GLchan (*rowB)[3] = (const GLchan (*)[3]) srcRowB;
3028 GLchan (*dst)[3] = (GLchan (*)[3]) dstRow;
3029 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3030 i++, j += colStride, k += colStride) {
3031 dst[i][0] = (rowA[j][0] + rowA[k][0] +
3032 rowB[j][0] + rowB[k][0]) / 4;
3033 dst[i][1] = (rowA[j][1] + rowA[k][1] +
3034 rowB[j][1] + rowB[k][1]) / 4;
3035 dst[i][2] = (rowA[j][2] + rowA[k][2] +
3036 rowB[j][2] + rowB[k][2]) / 4;
3037 }
3038 }
3039 return;
3040 case MESA_FORMAT_ALPHA:
3041 case MESA_FORMAT_LUMINANCE:
3042 case MESA_FORMAT_INTENSITY:
3043 {
3044 GLuint i, j, k;
3045 const GLchan *rowA = (const GLchan *) srcRowA;
3046 const GLchan *rowB = (const GLchan *) srcRowB;
3047 GLchan *dst = (GLchan *) dstRow;
3048 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3049 i++, j += colStride, k += colStride) {
3050 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
3051 }
3052 }
3053 return;
3054 case MESA_FORMAT_LUMINANCE_ALPHA:
3055 {
3056 GLuint i, j, k;
3057 const GLchan (*rowA)[2] = (const GLchan (*)[2]) srcRowA;
3058 const GLchan (*rowB)[2] = (const GLchan (*)[2]) srcRowB;
3059 GLchan (*dst)[2] = (GLchan (*)[2]) dstRow;
3060 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3061 i++, j += colStride, k += colStride) {
3062 dst[i][0] = (rowA[j][0] + rowA[k][0] +
3063 rowB[j][0] + rowB[k][0]) / 4;
3064 dst[i][1] = (rowA[j][1] + rowA[k][1] +
3065 rowB[j][1] + rowB[k][1]) / 4;
3066 }
3067 }
3068 return;
3069 case MESA_FORMAT_DEPTH_COMPONENT_FLOAT32:
3070 {
3071 GLuint i, j, k;
3072 const GLfloat *rowA = (const GLfloat *) srcRowA;
3073 const GLfloat *rowB = (const GLfloat *) srcRowB;
3074 GLfloat *dst = (GLfloat *) dstRow;
3075 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3076 i++, j += colStride, k += colStride) {
3077 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F;
3078 }
3079 }
3080 return;
3081 case MESA_FORMAT_DEPTH_COMPONENT16:
3082 {
3083 GLuint i, j, k;
3084 const GLushort *rowA = (const GLushort *) srcRowA;
3085 const GLushort *rowB = (const GLushort *) srcRowB;
3086 GLushort *dst = (GLushort *) dstRow;
3087 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3088 i++, j += colStride, k += colStride) {
3089 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
3090 }
3091 }
3092 return;
3093 /* Begin hardware formats */
3094 case MESA_FORMAT_RGBA8888:
3095 case MESA_FORMAT_RGBA8888_REV:
3096 case MESA_FORMAT_ARGB8888:
3097 case MESA_FORMAT_ARGB8888_REV:
3098 {
3099 GLuint i, j, k;
3100 const GLubyte (*rowA)[4] = (const GLubyte (*)[4]) srcRowA;
3101 const GLubyte (*rowB)[4] = (const GLubyte (*)[4]) srcRowB;
3102 GLubyte (*dst)[4] = (GLubyte (*)[4]) dstRow;
3103 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3104 i++, j += colStride, k += colStride) {
3105 dst[i][0] = (rowA[j][0] + rowA[k][0] +
3106 rowB[j][0] + rowB[k][0]) / 4;
3107 dst[i][1] = (rowA[j][1] + rowA[k][1] +
3108 rowB[j][1] + rowB[k][1]) / 4;
3109 dst[i][2] = (rowA[j][2] + rowA[k][2] +
3110 rowB[j][2] + rowB[k][2]) / 4;
3111 dst[i][3] = (rowA[j][3] + rowA[k][3] +
3112 rowB[j][3] + rowB[k][3]) / 4;
3113 }
3114 }
3115 return;
3116 case MESA_FORMAT_RGB888:
3117 case MESA_FORMAT_BGR888:
3118 {
3119 GLuint i, j, k;
3120 const GLubyte (*rowA)[3] = (const GLubyte (*)[3]) srcRowA;
3121 const GLubyte (*rowB)[3] = (const GLubyte (*)[3]) srcRowB;
3122 GLubyte (*dst)[3] = (GLubyte (*)[3]) dstRow;
3123 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3124 i++, j += colStride, k += colStride) {
3125 dst[i][0] = (rowA[j][0] + rowA[k][0] +
3126 rowB[j][0] + rowB[k][0]) / 4;
3127 dst[i][1] = (rowA[j][1] + rowA[k][1] +
3128 rowB[j][1] + rowB[k][1]) / 4;
3129 dst[i][2] = (rowA[j][2] + rowA[k][2] +
3130 rowB[j][2] + rowB[k][2]) / 4;
3131 }
3132 }
3133 return;
3134 case MESA_FORMAT_RGB565:
3135 case MESA_FORMAT_RGB565_REV:
3136 {
3137 GLuint i, j, k;
3138 const GLushort *rowA = (const GLushort *) srcRowA;
3139 const GLushort *rowB = (const GLushort *) srcRowB;
3140 GLushort *dst = (GLushort *) dstRow;
3141 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3142 i++, j += colStride, k += colStride) {
3143 const GLint rowAr0 = rowA[j] & 0x1f;
3144 const GLint rowAr1 = rowA[k] & 0x1f;
3145 const GLint rowBr0 = rowB[j] & 0x1f;
3146 const GLint rowBr1 = rowB[k] & 0x1f;
3147 const GLint rowAg0 = (rowA[j] >> 5) & 0x3f;
3148 const GLint rowAg1 = (rowA[k] >> 5) & 0x3f;
3149 const GLint rowBg0 = (rowB[j] >> 5) & 0x3f;
3150 const GLint rowBg1 = (rowB[k] >> 5) & 0x3f;
3151 const GLint rowAb0 = (rowA[j] >> 11) & 0x1f;
3152 const GLint rowAb1 = (rowA[k] >> 11) & 0x1f;
3153 const GLint rowBb0 = (rowB[j] >> 11) & 0x1f;
3154 const GLint rowBb1 = (rowB[k] >> 11) & 0x1f;
3155 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
3156 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
3157 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
3158 dst[i] = (blue << 11) | (green << 5) | red;
3159 }
3160 }
3161 return;
3162 case MESA_FORMAT_ARGB4444:
3163 case MESA_FORMAT_ARGB4444_REV:
3164 {
3165 GLuint i, j, k;
3166 const GLushort *rowA = (const GLushort *) srcRowA;
3167 const GLushort *rowB = (const GLushort *) srcRowB;
3168 GLushort *dst = (GLushort *) dstRow;
3169 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3170 i++, j += colStride, k += colStride) {
3171 const GLint rowAr0 = rowA[j] & 0xf;
3172 const GLint rowAr1 = rowA[k] & 0xf;
3173 const GLint rowBr0 = rowB[j] & 0xf;
3174 const GLint rowBr1 = rowB[k] & 0xf;
3175 const GLint rowAg0 = (rowA[j] >> 4) & 0xf;
3176 const GLint rowAg1 = (rowA[k] >> 4) & 0xf;
3177 const GLint rowBg0 = (rowB[j] >> 4) & 0xf;
3178 const GLint rowBg1 = (rowB[k] >> 4) & 0xf;
3179 const GLint rowAb0 = (rowA[j] >> 8) & 0xf;
3180 const GLint rowAb1 = (rowA[k] >> 8) & 0xf;
3181 const GLint rowBb0 = (rowB[j] >> 8) & 0xf;
3182 const GLint rowBb1 = (rowB[k] >> 8) & 0xf;
3183 const GLint rowAa0 = (rowA[j] >> 12) & 0xf;
3184 const GLint rowAa1 = (rowA[k] >> 12) & 0xf;
3185 const GLint rowBa0 = (rowB[j] >> 12) & 0xf;
3186 const GLint rowBa1 = (rowB[k] >> 12) & 0xf;
3187 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
3188 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
3189 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
3190 const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
3191 dst[i] = (alpha << 12) | (blue << 8) | (green << 4) | red;
3192 }
3193 }
3194 return;
3195 case MESA_FORMAT_ARGB1555:
3196 case MESA_FORMAT_ARGB1555_REV: /* XXX broken? */
3197 {
3198 GLuint i, j, k;
3199 const GLushort *rowA = (const GLushort *) srcRowA;
3200 const GLushort *rowB = (const GLushort *) srcRowB;
3201 GLushort *dst = (GLushort *) dstRow;
3202 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3203 i++, j += colStride, k += colStride) {
3204 const GLint rowAr0 = rowA[j] & 0x1f;
3205 const GLint rowAr1 = rowA[k] & 0x1f;
3206 const GLint rowBr0 = rowB[j] & 0x1f;
3207 const GLint rowBr1 = rowB[k] & 0xf;
3208 const GLint rowAg0 = (rowA[j] >> 5) & 0x1f;
3209 const GLint rowAg1 = (rowA[k] >> 5) & 0x1f;
3210 const GLint rowBg0 = (rowB[j] >> 5) & 0x1f;
3211 const GLint rowBg1 = (rowB[k] >> 5) & 0x1f;
3212 const GLint rowAb0 = (rowA[j] >> 10) & 0x1f;
3213 const GLint rowAb1 = (rowA[k] >> 10) & 0x1f;
3214 const GLint rowBb0 = (rowB[j] >> 10) & 0x1f;
3215 const GLint rowBb1 = (rowB[k] >> 10) & 0x1f;
3216 const GLint rowAa0 = (rowA[j] >> 15) & 0x1;
3217 const GLint rowAa1 = (rowA[k] >> 15) & 0x1;
3218 const GLint rowBa0 = (rowB[j] >> 15) & 0x1;
3219 const GLint rowBa1 = (rowB[k] >> 15) & 0x1;
3220 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
3221 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
3222 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
3223 const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
3224 dst[i] = (alpha << 15) | (blue << 10) | (green << 5) | red;
3225 }
3226 }
3227 return;
3228 case MESA_FORMAT_AL88:
3229 case MESA_FORMAT_AL88_REV:
3230 {
3231 GLuint i, j, k;
3232 const GLubyte (*rowA)[2] = (const GLubyte (*)[2]) srcRowA;
3233 const GLubyte (*rowB)[2] = (const GLubyte (*)[2]) srcRowB;
3234 GLubyte (*dst)[2] = (GLubyte (*)[2]) dstRow;
3235 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3236 i++, j += colStride, k += colStride) {
3237 dst[i][0] = (rowA[j][0] + rowA[k][0] +
3238 rowB[j][0] + rowB[k][0]) >> 2;
3239 dst[i][1] = (rowA[j][1] + rowA[k][1] +
3240 rowB[j][1] + rowB[k][1]) >> 2;
3241 }
3242 }
3243 return;
3244 case MESA_FORMAT_RGB332:
3245 {
3246 GLuint i, j, k;
3247 const GLubyte *rowA = (const GLubyte *) srcRowA;
3248 const GLubyte *rowB = (const GLubyte *) srcRowB;
3249 GLubyte *dst = (GLubyte *) dstRow;
3250 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3251 i++, j += colStride, k += colStride) {
3252 const GLint rowAr0 = rowA[j] & 0x3;
3253 const GLint rowAr1 = rowA[k] & 0x3;
3254 const GLint rowBr0 = rowB[j] & 0x3;
3255 const GLint rowBr1 = rowB[k] & 0x3;
3256 const GLint rowAg0 = (rowA[j] >> 2) & 0x7;
3257 const GLint rowAg1 = (rowA[k] >> 2) & 0x7;
3258 const GLint rowBg0 = (rowB[j] >> 2) & 0x7;
3259 const GLint rowBg1 = (rowB[k] >> 2) & 0x7;
3260 const GLint rowAb0 = (rowA[j] >> 5) & 0x7;
3261 const GLint rowAb1 = (rowA[k] >> 5) & 0x7;
3262 const GLint rowBb0 = (rowB[j] >> 5) & 0x7;
3263 const GLint rowBb1 = (rowB[k] >> 5) & 0x7;
3264 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
3265 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
3266 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
3267 dst[i] = (blue << 5) | (green << 2) | red;
3268 }
3269 }
3270 return;
3271 case MESA_FORMAT_A8:
3272 case MESA_FORMAT_L8:
3273 case MESA_FORMAT_I8:
3274 case MESA_FORMAT_CI8:
3275 {
3276 GLuint i, j, k;
3277 const GLubyte *rowA = (const GLubyte *) srcRowA;
3278 const GLubyte *rowB = (const GLubyte *) srcRowB;
3279 GLubyte *dst = (GLubyte *) dstRow;
3280 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3281 i++, j += colStride, k += colStride) {
3282 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) >> 2;
3283 }
3284 }
3285 return;
3286 case MESA_FORMAT_RGBA_FLOAT32:
3287 {
3288 GLuint i, j, k;
3289 const GLfloat (*rowA)[4] = (const GLfloat (*)[4]) srcRowA;
3290 const GLfloat (*rowB)[4] = (const GLfloat (*)[4]) srcRowB;
3291 GLfloat (*dst)[4] = (GLfloat (*)[4]) dstRow;
3292 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3293 i++, j += colStride, k += colStride) {
3294 dst[i][0] = (rowA[j][0] + rowA[k][0] +
3295 rowB[j][0] + rowB[k][0]) * 0.25F;
3296 dst[i][1] = (rowA[j][1] + rowA[k][1] +
3297 rowB[j][1] + rowB[k][1]) * 0.25F;
3298 dst[i][2] = (rowA[j][2] + rowA[k][2] +
3299 rowB[j][2] + rowB[k][2]) * 0.25F;
3300 dst[i][3] = (rowA[j][3] + rowA[k][3] +
3301 rowB[j][3] + rowB[k][3]) * 0.25F;
3302 }
3303 }
3304 return;
3305 case MESA_FORMAT_RGBA_FLOAT16:
3306 {
3307 GLuint i, j, k, comp;
3308 const GLhalfARB (*rowA)[4] = (const GLhalfARB (*)[4]) srcRowA;
3309 const GLhalfARB (*rowB)[4] = (const GLhalfARB (*)[4]) srcRowB;
3310 GLhalfARB (*dst)[4] = (GLhalfARB (*)[4]) dstRow;
3311 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3312 i++, j += colStride, k += colStride) {
3313 for (comp = 0; comp < 4; comp++) {
3314 GLfloat aj, ak, bj, bk;
3315 aj = _mesa_half_to_float(rowA[j][comp]);
3316 ak = _mesa_half_to_float(rowA[k][comp]);
3317 bj = _mesa_half_to_float(rowB[j][comp]);
3318 bk = _mesa_half_to_float(rowB[k][comp]);
3319 dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
3320 }
3321 }
3322 }
3323 return;
3324 case MESA_FORMAT_RGB_FLOAT32:
3325 {
3326 GLuint i, j, k;
3327 const GLfloat (*rowA)[3] = (const GLfloat (*)[3]) srcRowA;
3328 const GLfloat (*rowB)[3] = (const GLfloat (*)[3]) srcRowB;
3329 GLfloat (*dst)[3] = (GLfloat (*)[3]) dstRow;
3330 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3331 i++, j += colStride, k += colStride) {
3332 dst[i][0] = (rowA[j][0] + rowA[k][0] +
3333 rowB[j][0] + rowB[k][0]) * 0.25F;
3334 dst[i][1] = (rowA[j][1] + rowA[k][1] +
3335 rowB[j][1] + rowB[k][1]) * 0.25F;
3336 dst[i][2] = (rowA[j][2] + rowA[k][2] +
3337 rowB[j][2] + rowB[k][2]) * 0.25F;
3338 }
3339 }
3340 return;
3341 case MESA_FORMAT_RGB_FLOAT16:
3342 {
3343 GLuint i, j, k, comp;
3344 const GLhalfARB (*rowA)[3] = (const GLhalfARB (*)[3]) srcRowA;
3345 const GLhalfARB (*rowB)[3] = (const GLhalfARB (*)[3]) srcRowB;
3346 GLhalfARB (*dst)[3] = (GLhalfARB (*)[3]) dstRow;
3347 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3348 i++, j += colStride, k += colStride) {
3349 for (comp = 0; comp < 3; comp++) {
3350 GLfloat aj, ak, bj, bk;
3351 aj = _mesa_half_to_float(rowA[j][comp]);
3352 ak = _mesa_half_to_float(rowA[k][comp]);
3353 bj = _mesa_half_to_float(rowB[j][comp]);
3354 bk = _mesa_half_to_float(rowB[k][comp]);
3355 dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
3356 }
3357 }
3358 }
3359 return;
3360 case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT32:
3361 {
3362 GLuint i, j, k;
3363 const GLfloat (*rowA)[2] = (const GLfloat (*)[2]) srcRowA;
3364 const GLfloat (*rowB)[2] = (const GLfloat (*)[2]) srcRowB;
3365 GLfloat (*dst)[2] = (GLfloat (*)[2]) dstRow;
3366 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3367 i++, j += colStride, k += colStride) {
3368 dst[i][0] = (rowA[j][0] + rowA[k][0] +
3369 rowB[j][0] + rowB[k][0]) * 0.25F;
3370 dst[i][1] = (rowA[j][1] + rowA[k][1] +
3371 rowB[j][1] + rowB[k][1]) * 0.25F;
3372 }
3373 }
3374 return;
3375 case MESA_FORMAT_LUMINANCE_ALPHA_FLOAT16:
3376 {
3377 GLuint i, j, k, comp;
3378 const GLhalfARB (*rowA)[2] = (const GLhalfARB (*)[2]) srcRowA;
3379 const GLhalfARB (*rowB)[2] = (const GLhalfARB (*)[2]) srcRowB;
3380 GLhalfARB (*dst)[2] = (GLhalfARB (*)[2]) dstRow;
3381 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3382 i++, j += colStride, k += colStride) {
3383 for (comp = 0; comp < 2; comp++) {
3384 GLfloat aj, ak, bj, bk;
3385 aj = _mesa_half_to_float(rowA[j][comp]);
3386 ak = _mesa_half_to_float(rowA[k][comp]);
3387 bj = _mesa_half_to_float(rowB[j][comp]);
3388 bk = _mesa_half_to_float(rowB[k][comp]);
3389 dst[i][comp] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
3390 }
3391 }
3392 }
3393 return;
3394 case MESA_FORMAT_ALPHA_FLOAT32:
3395 case MESA_FORMAT_LUMINANCE_FLOAT32:
3396 case MESA_FORMAT_INTENSITY_FLOAT32:
3397 {
3398 GLuint i, j, k;
3399 const GLfloat *rowA = (const GLfloat *) srcRowA;
3400 const GLfloat *rowB = (const GLfloat *) srcRowB;
3401 GLfloat *dst = (GLfloat *) dstRow;
3402 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3403 i++, j += colStride, k += colStride) {
3404 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F;
3405 }
3406 }
3407 return;
3408 case MESA_FORMAT_ALPHA_FLOAT16:
3409 case MESA_FORMAT_LUMINANCE_FLOAT16:
3410 case MESA_FORMAT_INTENSITY_FLOAT16:
3411 {
3412 GLuint i, j, k;
3413 const GLhalfARB *rowA = (const GLhalfARB *) srcRowA;
3414 const GLhalfARB *rowB = (const GLhalfARB *) srcRowB;
3415 GLhalfARB *dst = (GLhalfARB *) dstRow;
3416 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
3417 i++, j += colStride, k += colStride) {
3418 GLfloat aj, ak, bj, bk;
3419 aj = _mesa_half_to_float(rowA[j]);
3420 ak = _mesa_half_to_float(rowA[k]);
3421 bj = _mesa_half_to_float(rowB[j]);
3422 bk = _mesa_half_to_float(rowB[k]);
3423 dst[i] = _mesa_float_to_half((aj + ak + bj + bk) * 0.25F);
3424 }
3425 }
3426 return;
3427
3428 default:
3429 _mesa_problem(NULL, "bad format in do_row()");
3430 }
3431 }
3432
3433
3434 /*
3435 * These functions generate a 1/2-size mipmap image from a source image.
3436 * Texture borders are handled by copying or averaging the source image's
3437 * border texels, depending on the scale-down factor.
3438 */
3439
3440 static void
3441 make_1d_mipmap(const struct gl_texture_format *format, GLint border,
3442 GLint srcWidth, const GLubyte *srcPtr,
3443 GLint dstWidth, GLubyte *dstPtr)
3444 {
3445 const GLint bpt = format->TexelBytes;
3446 const GLubyte *src;
3447 GLubyte *dst;
3448
3449 /* skip the border pixel, if any */
3450 src = srcPtr + border * bpt;
3451 dst = dstPtr + border * bpt;
3452
3453 /* we just duplicate the input row, kind of hack, saves code */
3454 do_row(format, srcWidth - 2 * border, src, src,
3455 dstWidth - 2 * border, dst);
3456
3457 if (border) {
3458 /* copy left-most pixel from source */
3459 MEMCPY(dstPtr, srcPtr, bpt);
3460 /* copy right-most pixel from source */
3461 MEMCPY(dstPtr + (dstWidth - 1) * bpt,
3462 srcPtr + (srcWidth - 1) * bpt,
3463 bpt);
3464 }
3465 }
3466
3467
3468 static void
3469 make_2d_mipmap(const struct gl_texture_format *format, GLint border,
3470 GLint srcWidth, GLint srcHeight, const GLubyte *srcPtr,
3471 GLint dstWidth, GLint dstHeight, GLubyte *dstPtr)
3472 {
3473 const GLint bpt = format->TexelBytes;
3474 const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */
3475 const GLint dstWidthNB = dstWidth - 2 * border;
3476 const GLint dstHeightNB = dstHeight - 2 * border;
3477 const GLint srcRowStride = bpt * srcWidth;
3478 const GLint dstRowStride = bpt * dstWidth;
3479 const GLubyte *srcA, *srcB;
3480 GLubyte *dst;
3481 GLint row;
3482
3483 /* Compute src and dst pointers, skipping any border */
3484 srcA = srcPtr + border * ((srcWidth + 1) * bpt);
3485 if (srcHeight > 1)
3486 srcB = srcA + srcRowStride;
3487 else
3488 srcB = srcA;
3489 dst = dstPtr + border * ((dstWidth + 1) * bpt);
3490
3491 for (row = 0; row < dstHeightNB; row++) {
3492 do_row(format, srcWidthNB, srcA, srcB,
3493 dstWidthNB, dst);
3494 srcA += 2 * srcRowStride;
3495 srcB += 2 * srcRowStride;
3496 dst += dstRowStride;
3497 }
3498
3499 /* This is ugly but probably won't be used much */
3500 if (border > 0) {
3501 /* fill in dest border */
3502 /* lower-left border pixel */
3503 MEMCPY(dstPtr, srcPtr, bpt);
3504 /* lower-right border pixel */
3505 MEMCPY(dstPtr + (dstWidth - 1) * bpt,
3506 srcPtr + (srcWidth - 1) * bpt, bpt);
3507 /* upper-left border pixel */
3508 MEMCPY(dstPtr + dstWidth * (dstHeight - 1) * bpt,
3509 srcPtr + srcWidth * (srcHeight - 1) * bpt, bpt);
3510 /* upper-right border pixel */
3511 MEMCPY(dstPtr + (dstWidth * dstHeight - 1) * bpt,
3512 srcPtr + (srcWidth * srcHeight - 1) * bpt, bpt);
3513 /* lower border */
3514 do_row(format, srcWidthNB,
3515 srcPtr + bpt,
3516 srcPtr + bpt,
3517 dstWidthNB, dstPtr + bpt);
3518 /* upper border */
3519 do_row(format, srcWidthNB,
3520 srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
3521 srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
3522 dstWidthNB,
3523 dstPtr + (dstWidth * (dstHeight - 1) + 1) * bpt);
3524 /* left and right borders */
3525 if (srcHeight == dstHeight) {
3526 /* copy border pixel from src to dst */
3527 for (row = 1; row < srcHeight; row++) {
3528 MEMCPY(dstPtr + dstWidth * row * bpt,
3529 srcPtr + srcWidth * row * bpt, bpt);
3530 MEMCPY(dstPtr + (dstWidth * row + dstWidth - 1) * bpt,
3531 srcPtr + (srcWidth * row + srcWidth - 1) * bpt, bpt);
3532 }
3533 }
3534 else {
3535 /* average two src pixels each dest pixel */
3536 for (row = 0; row < dstHeightNB; row += 2) {
3537 do_row(format, 1,
3538 srcPtr + (srcWidth * (row * 2 + 1)) * bpt,
3539 srcPtr + (srcWidth * (row * 2 + 2)) * bpt,
3540 1, dstPtr + (dstWidth * row + 1) * bpt);
3541 do_row(format, 1,
3542 srcPtr + (srcWidth * (row * 2 + 1) + srcWidth - 1) * bpt,
3543 srcPtr + (srcWidth * (row * 2 + 2) + srcWidth - 1) * bpt,
3544 1, dstPtr + (dstWidth * row + 1 + dstWidth - 1) * bpt);
3545 }
3546 }
3547 }
3548 }
3549
3550
3551 static void
3552 make_3d_mipmap(const struct gl_texture_format *format, GLint border,
3553 GLint srcWidth, GLint srcHeight, GLint srcDepth,
3554 const GLubyte *srcPtr,
3555 GLint dstWidth, GLint dstHeight, GLint dstDepth,
3556 GLubyte *dstPtr)
3557 {
3558 const GLint bpt = format->TexelBytes;
3559 const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */
3560 const GLint srcDepthNB = srcDepth - 2 * border;
3561 const GLint dstWidthNB = dstWidth - 2 * border;
3562 const GLint dstHeightNB = dstHeight - 2 * border;
3563 const GLint dstDepthNB = dstDepth - 2 * border;
3564 GLvoid *tmpRowA, *tmpRowB;
3565 GLint img, row;
3566 GLint bytesPerSrcImage, bytesPerDstImage;
3567 GLint bytesPerSrcRow, bytesPerDstRow;
3568 GLint srcImageOffset, srcRowOffset;
3569
3570 (void) srcDepthNB; /* silence warnings */
3571
3572 /* Need two temporary row buffers */
3573 tmpRowA = _mesa_malloc(srcWidth * bpt);
3574 if (!tmpRowA)
3575 return;
3576 tmpRowB = _mesa_malloc(srcWidth * bpt);
3577 if (!tmpRowB) {
3578 _mesa_free(tmpRowA);
3579 return;
3580 }
3581
3582 bytesPerSrcImage = srcWidth * srcHeight * bpt;
3583 bytesPerDstImage = dstWidth * dstHeight * bpt;
3584
3585 bytesPerSrcRow = srcWidth * bpt;
3586 bytesPerDstRow = dstWidth * bpt;
3587
3588 /* Offset between adjacent src images to be averaged together */
3589 srcImageOffset = (srcDepth == dstDepth) ? 0 : bytesPerSrcImage;
3590
3591 /* Offset between adjacent src rows to be averaged together */
3592 srcRowOffset = (srcHeight == dstHeight) ? 0 : srcWidth * bpt;
3593
3594 /*
3595 * Need to average together up to 8 src pixels for each dest pixel.
3596 * Break that down into 3 operations:
3597 * 1. take two rows from source image and average them together.
3598 * 2. take two rows from next source image and average them together.
3599 * 3. take the two averaged rows and average them for the final dst row.
3600 */
3601
3602 /*
3603 _mesa_printf("mip3d %d x %d x %d -> %d x %d x %d\n",
3604 srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth);
3605 */
3606
3607 for (img = 0; img < dstDepthNB; img++) {
3608 /* first source image pointer, skipping border */
3609 const GLubyte *imgSrcA = srcPtr
3610 + (bytesPerSrcImage + bytesPerSrcRow + border) * bpt * border
3611 + img * (bytesPerSrcImage + srcImageOffset);
3612 /* second source image pointer, skipping border */
3613 const GLubyte *imgSrcB = imgSrcA + srcImageOffset;
3614 /* address of the dest image, skipping border */
3615 GLubyte *imgDst = dstPtr
3616 + (bytesPerDstImage + bytesPerDstRow + border) * bpt * border
3617 + img * bytesPerDstImage;
3618
3619 /* setup the four source row pointers and the dest row pointer */
3620 const GLubyte *srcImgARowA = imgSrcA;
3621 const GLubyte *srcImgARowB = imgSrcA + srcRowOffset;
3622 const GLubyte *srcImgBRowA = imgSrcB;
3623 const GLubyte *srcImgBRowB = imgSrcB + srcRowOffset;
3624 GLubyte *dstImgRow = imgDst;
3625
3626 for (row = 0; row < dstHeightNB; row++) {
3627 /* Average together two rows from first src image */
3628 do_row(format, srcWidthNB, srcImgARowA, srcImgARowB,
3629 srcWidthNB, tmpRowA);
3630 /* Average together two rows from second src image */
3631 do_row(format, srcWidthNB, srcImgBRowA, srcImgBRowB,
3632 srcWidthNB, tmpRowB);
3633 /* Average together the temp rows to make the final row */
3634 do_row(format, srcWidthNB, tmpRowA, tmpRowB,
3635 dstWidthNB, dstImgRow);
3636 /* advance to next rows */
3637 srcImgARowA += bytesPerSrcRow + srcRowOffset;
3638 srcImgARowB += bytesPerSrcRow + srcRowOffset;
3639 srcImgBRowA += bytesPerSrcRow + srcRowOffset;
3640 srcImgBRowB += bytesPerSrcRow + srcRowOffset;
3641 dstImgRow += bytesPerDstRow;
3642 }
3643 }
3644
3645 _mesa_free(tmpRowA);
3646 _mesa_free(tmpRowB);
3647
3648 /* Luckily we can leverage the make_2d_mipmap() function here! */
3649 if (border > 0) {
3650 /* do front border image */
3651 make_2d_mipmap(format, 1, srcWidth, srcHeight, srcPtr,
3652 dstWidth, dstHeight, dstPtr);
3653 /* do back border image */
3654 make_2d_mipmap(format, 1, srcWidth, srcHeight,
3655 srcPtr + bytesPerSrcImage * (srcDepth - 1),
3656 dstWidth, dstHeight,
3657 dstPtr + bytesPerDstImage * (dstDepth - 1));
3658 /* do four remaining border edges that span the image slices */
3659 if (srcDepth == dstDepth) {
3660 /* just copy border pixels from src to dst */
3661 for (img = 0; img < dstDepthNB; img++) {
3662 const GLubyte *src;
3663 GLubyte *dst;
3664
3665 /* do border along [img][row=0][col=0] */
3666 src = srcPtr + (img + 1) * bytesPerSrcImage;
3667 dst = dstPtr + (img + 1) * bytesPerDstImage;
3668 MEMCPY(dst, src, bpt);
3669
3670 /* do border along [img][row=dstHeight-1][col=0] */
3671 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
3672 + (srcHeight - 1) * bytesPerSrcRow;
3673 dst = dstPtr + (img + 1) * bytesPerDstImage
3674 + (dstHeight - 1) * bytesPerDstRow;
3675 MEMCPY(dst, src, bpt);
3676
3677 /* do border along [img][row=0][col=dstWidth-1] */
3678 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
3679 + (srcWidth - 1) * bpt;
3680 dst = dstPtr + (img + 1) * bytesPerDstImage
3681 + (dstWidth - 1) * bpt;
3682 MEMCPY(dst, src, bpt);
3683
3684 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
3685 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
3686 + (bytesPerSrcImage - bpt);
3687 dst = dstPtr + (img + 1) * bytesPerDstImage
3688 + (bytesPerDstImage - bpt);
3689 MEMCPY(dst, src, bpt);
3690 }
3691 }
3692 else {
3693 /* average border pixels from adjacent src image pairs */
3694 ASSERT(srcDepthNB == 2 * dstDepthNB);
3695 for (img = 0; img < dstDepthNB; img++) {
3696 const GLubyte *src;
3697 GLubyte *dst;
3698
3699 /* do border along [img][row=0][col=0] */
3700 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage;
3701 dst = dstPtr + (img + 1) * bytesPerDstImage;
3702 do_row(format, 1, src, src + srcImageOffset, 1, dst);
3703
3704 /* do border along [img][row=dstHeight-1][col=0] */
3705 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
3706 + (srcHeight - 1) * bytesPerSrcRow;
3707 dst = dstPtr + (img + 1) * bytesPerDstImage
3708 + (dstHeight - 1) * bytesPerDstRow;
3709 do_row(format, 1, src, src + srcImageOffset, 1, dst);
3710
3711 /* do border along [img][row=0][col=dstWidth-1] */
3712 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
3713 + (srcWidth - 1) * bpt;
3714 dst = dstPtr + (img + 1) * bytesPerDstImage
3715 + (dstWidth - 1) * bpt;
3716 do_row(format, 1, src, src + srcImageOffset, 1, dst);
3717
3718 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
3719 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
3720 + (bytesPerSrcImage - bpt);
3721 dst = dstPtr + (img + 1) * bytesPerDstImage
3722 + (bytesPerDstImage - bpt);
3723 do_row(format, 1, src, src + srcImageOffset, 1, dst);
3724 }
3725 }
3726 }
3727 }
3728
3729
3730 /*
3731 * For GL_SGIX_generate_mipmap:
3732 * Generate a complete set of mipmaps from texObj's base-level image.
3733 * Stop at texObj's MaxLevel or when we get to the 1x1 texture.
3734 */
3735 void
3736 _mesa_generate_mipmap(GLcontext *ctx, GLenum target,
3737 const struct gl_texture_unit *texUnit,
3738 struct gl_texture_object *texObj)
3739 {
3740 const struct gl_texture_image *srcImage;
3741 const struct gl_texture_format *convertFormat;
3742 const GLubyte *srcData = NULL;
3743 GLubyte *dstData = NULL;
3744 GLint level, maxLevels;
3745
3746 ASSERT(texObj);
3747 /* XXX choose cube map face here??? */
3748 srcImage = texObj->Image[0][texObj->BaseLevel];
3749 ASSERT(srcImage);
3750
3751 maxLevels = _mesa_max_texture_levels(ctx, texObj->Target);
3752 ASSERT(maxLevels > 0); /* bad target */
3753
3754 /* Find convertFormat - the format that do_row() will process */
3755 if (srcImage->IsCompressed) {
3756 /* setup for compressed textures */
3757 GLuint row;
3758 GLint components, size;
3759 GLchan *dst;
3760
3761 assert(texObj->Target == GL_TEXTURE_2D);
3762
3763 if (srcImage->_BaseFormat == GL_RGB) {
3764 convertFormat = &_mesa_texformat_rgb;
3765 components = 3;
3766 }
3767 else if (srcImage->_BaseFormat == GL_RGBA) {
3768 convertFormat = &_mesa_texformat_rgba;
3769 components = 4;
3770 }
3771 else {
3772 _mesa_problem(ctx, "bad srcImage->_BaseFormat in _mesa_generate_mipmaps");
3773 return;
3774 }
3775
3776 /* allocate storage for uncompressed GL_RGB or GL_RGBA images */
3777 size = _mesa_bytes_per_pixel(srcImage->_BaseFormat, CHAN_TYPE)
3778 * srcImage->Width * srcImage->Height * srcImage->Depth + 20;
3779 /* 20 extra bytes, just be safe when calling last FetchTexel */
3780 srcData = (GLubyte *) _mesa_malloc(size);
3781 if (!srcData) {
3782 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
3783 return;
3784 }
3785 dstData = (GLubyte *) _mesa_malloc(size / 2); /* 1/4 would probably be OK */
3786 if (!dstData) {
3787 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
3788 _mesa_free((void *) srcData);
3789 return;
3790 }
3791
3792 /* decompress base image here */
3793 dst = (GLchan *) srcData;
3794 for (row = 0; row < srcImage->Height; row++) {
3795 GLuint col;
3796 for (col = 0; col < srcImage->Width; col++) {
3797 srcImage->FetchTexelc(srcImage, col, row, 0, dst);
3798 dst += components;
3799 }
3800 }
3801 }
3802 else {
3803 /* uncompressed */
3804 convertFormat = srcImage->TexFormat;
3805 }
3806
3807 for (level = texObj->BaseLevel; level < texObj->MaxLevel
3808 && level < maxLevels - 1; level++) {
3809 /* generate image[level+1] from image[level] */
3810 const struct gl_texture_image *srcImage;
3811 struct gl_texture_image *dstImage;
3812 GLint srcWidth, srcHeight, srcDepth;
3813 GLint dstWidth, dstHeight, dstDepth;
3814 GLint border, bytesPerTexel;
3815
3816 /* get src image parameters */
3817 srcImage = _mesa_select_tex_image(ctx, texUnit, target, level);
3818 ASSERT(srcImage);
3819 srcWidth = srcImage->Width;
3820 srcHeight = srcImage->Height;
3821 srcDepth = srcImage->Depth;
3822 border = srcImage->Border;
3823
3824 /* compute next (level+1) image size */
3825 if (srcWidth - 2 * border > 1) {
3826 dstWidth = (srcWidth - 2 * border) / 2 + 2 * border;
3827 }
3828 else {
3829 dstWidth = srcWidth; /* can't go smaller */
3830 }
3831 if (srcHeight - 2 * border > 1) {
3832 dstHeight = (srcHeight - 2 * border) / 2 + 2 * border;
3833 }
3834 else {
3835 dstHeight = srcHeight; /* can't go smaller */
3836 }
3837 if (srcDepth - 2 * border > 1) {
3838 dstDepth = (srcDepth - 2 * border) / 2 + 2 * border;
3839 }
3840 else {
3841 dstDepth = srcDepth; /* can't go smaller */
3842 }
3843
3844 if (dstWidth == srcWidth &&
3845 dstHeight == srcHeight &&
3846 dstDepth == srcDepth) {
3847 /* all done */
3848 if (srcImage->IsCompressed) {
3849 _mesa_free((void *) srcData);
3850 _mesa_free(dstData);
3851 }
3852 return;
3853 }
3854
3855 /* get dest gl_texture_image */
3856 dstImage = _mesa_get_tex_image(ctx, texUnit, target, level + 1);
3857 if (!dstImage) {
3858 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
3859 return;
3860 }
3861
3862 /* Free old image data */
3863 if (dstImage->Data)
3864 ctx->Driver.FreeTexImageData(ctx, dstImage);
3865
3866 /* initialize new image */
3867 _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight,
3868 dstDepth, border, srcImage->InternalFormat);
3869 dstImage->DriverData = NULL;
3870 dstImage->TexFormat = srcImage->TexFormat;
3871 dstImage->FetchTexelc = srcImage->FetchTexelc;
3872 dstImage->FetchTexelf = srcImage->FetchTexelf;
3873 ASSERT(dstImage->TexFormat);
3874 ASSERT(dstImage->FetchTexelc);
3875 ASSERT(dstImage->FetchTexelf);
3876
3877 /* Alloc new teximage data buffer.
3878 * Setup src and dest data pointers.
3879 */
3880 if (dstImage->IsCompressed) {
3881 ASSERT(dstImage->CompressedSize > 0); /* set by init_teximage_fields*/
3882 dstImage->Data = _mesa_alloc_texmemory(dstImage->CompressedSize);
3883 if (!dstImage->Data) {
3884 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
3885 return;
3886 }
3887 /* srcData and dstData are already set */
3888 ASSERT(srcData);
3889 ASSERT(dstData);
3890 }
3891 else {
3892 bytesPerTexel = srcImage->TexFormat->TexelBytes;
3893 ASSERT(dstWidth * dstHeight * dstDepth * bytesPerTexel > 0);
3894 dstImage->Data = _mesa_alloc_texmemory(dstWidth * dstHeight
3895 * dstDepth * bytesPerTexel);
3896 if (!dstImage->Data) {
3897 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
3898 return;
3899 }
3900 srcData = (const GLubyte *) srcImage->Data;
3901 dstData = (GLubyte *) dstImage->Data;
3902 }
3903
3904 /*
3905 * We use simple 2x2 averaging to compute the next mipmap level.
3906 */
3907 switch (target) {
3908 case GL_TEXTURE_1D:
3909 make_1d_mipmap(convertFormat, border,
3910 srcWidth, srcData,
3911 dstWidth, dstData);
3912 break;
3913 case GL_TEXTURE_2D:
3914 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
3915 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
3916 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
3917 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
3918 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
3919 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
3920 make_2d_mipmap(convertFormat, border,
3921 srcWidth, srcHeight, srcData,
3922 dstWidth, dstHeight, dstData);
3923 break;
3924 case GL_TEXTURE_3D:
3925 make_3d_mipmap(convertFormat, border,
3926 srcWidth, srcHeight, srcDepth, srcData,
3927 dstWidth, dstHeight, dstDepth, dstData);
3928 break;
3929 case GL_TEXTURE_RECTANGLE_NV:
3930 /* no mipmaps, do nothing */
3931 break;
3932 default:
3933 _mesa_problem(ctx, "bad dimensions in _mesa_generate_mipmaps");
3934 return;
3935 }
3936
3937 if (dstImage->IsCompressed) {
3938 GLubyte *temp;
3939 /* compress image from dstData into dstImage->Data */
3940 const GLenum srcFormat = convertFormat->BaseFormat;
3941 GLint dstRowStride
3942 = _mesa_compressed_row_stride(srcImage->InternalFormat, dstWidth);
3943 ASSERT(srcFormat == GL_RGB || srcFormat == GL_RGBA);
3944 dstImage->TexFormat->StoreImage(ctx, 2, dstImage->_BaseFormat,
3945 dstImage->TexFormat,
3946 dstImage->Data,
3947 0, 0, 0, /* dstX/Y/Zoffset */
3948 dstRowStride, 0, /* strides */
3949 dstWidth, dstHeight, 1, /* size */
3950 srcFormat, CHAN_TYPE,
3951 dstData, /* src data, actually */
3952 &ctx->DefaultPacking);
3953 /* swap src and dest pointers */
3954 temp = (GLubyte *) srcData;
3955 srcData = dstData;
3956 dstData = temp;
3957 }
3958
3959 } /* loop over mipmap levels */
3960 }
3961
3962
3963 /**
3964 * Helper function for drivers which need to rescale texture images to
3965 * certain aspect ratios.
3966 * Nearest filtering only (for broken hardware that can't support
3967 * all aspect ratios). This can be made a lot faster, but I don't
3968 * really care enough...
3969 */
3970 void
3971 _mesa_rescale_teximage2d (GLuint bytesPerPixel,
3972 GLuint srcStrideInPixels,
3973 GLuint dstRowStride,
3974 GLint srcWidth, GLint srcHeight,
3975 GLint dstWidth, GLint dstHeight,
3976 const GLvoid *srcImage, GLvoid *dstImage)
3977 {
3978 GLint row, col;
3979
3980 #define INNER_LOOP( TYPE, HOP, WOP ) \
3981 for ( row = 0 ; row < dstHeight ; row++ ) { \
3982 GLint srcRow = row HOP hScale; \
3983 for ( col = 0 ; col < dstWidth ; col++ ) { \
3984 GLint srcCol = col WOP wScale; \
3985 dst[col] = src[srcRow * srcStrideInPixels + srcCol]; \
3986 } \
3987 dst = (TYPE *) ((GLubyte *) dst + dstRowStride); \
3988 } \
3989
3990 #define RESCALE_IMAGE( TYPE ) \
3991 do { \
3992 const TYPE *src = (const TYPE *)srcImage; \
3993 TYPE *dst = (TYPE *)dstImage; \
3994 \
3995 if ( srcHeight < dstHeight ) { \
3996 const GLint hScale = dstHeight / srcHeight; \
3997 if ( srcWidth < dstWidth ) { \
3998 const GLint wScale = dstWidth / srcWidth; \
3999 INNER_LOOP( TYPE, /, / ); \
4000 } \
4001 else { \
4002 const GLint wScale = srcWidth / dstWidth; \
4003 INNER_LOOP( TYPE, /, * ); \
4004 } \
4005 } \
4006 else { \
4007 const GLint hScale = srcHeight / dstHeight; \
4008 if ( srcWidth < dstWidth ) { \
4009 const GLint wScale = dstWidth / srcWidth; \
4010 INNER_LOOP( TYPE, *, / ); \
4011 } \
4012 else { \
4013 const GLint wScale = srcWidth / dstWidth; \
4014 INNER_LOOP( TYPE, *, * ); \
4015 } \
4016 } \
4017 } while (0)
4018
4019 switch ( bytesPerPixel ) {
4020 case 4:
4021 RESCALE_IMAGE( GLuint );
4022 break;
4023
4024 case 2:
4025 RESCALE_IMAGE( GLushort );
4026 break;
4027
4028 case 1:
4029 RESCALE_IMAGE( GLubyte );
4030 break;
4031 default:
4032 _mesa_problem(NULL,"unexpected bytes/pixel in _mesa_rescale_teximage2d");
4033 }
4034 }
4035
4036
4037 /**
4038 * Upscale an image by replication, not (typical) stretching.
4039 * We use this when the image width or height is less than a
4040 * certain size (4, 8) and we need to upscale an image.
4041 */
4042 void
4043 _mesa_upscale_teximage2d (GLsizei inWidth, GLsizei inHeight,
4044 GLsizei outWidth, GLsizei outHeight,
4045 GLint comps, const GLchan *src, GLint srcRowStride,
4046 GLchan *dest )
4047 {
4048 GLint i, j, k;
4049
4050 ASSERT(outWidth >= inWidth);
4051 ASSERT(outHeight >= inHeight);
4052 #if 0
4053 ASSERT(inWidth == 1 || inWidth == 2 || inHeight == 1 || inHeight == 2);
4054 ASSERT((outWidth & 3) == 0);
4055 ASSERT((outHeight & 3) == 0);
4056 #endif
4057
4058 for (i = 0; i < outHeight; i++) {
4059 const GLint ii = i % inHeight;
4060 for (j = 0; j < outWidth; j++) {
4061 const GLint jj = j % inWidth;
4062 for (k = 0; k < comps; k++) {
4063 dest[(i * outWidth + j) * comps + k]
4064 = src[ii * srcRowStride + jj * comps + k];
4065 }
4066 }
4067 }
4068 }
4069
4070
4071
4072 /**
4073 * This is the software fallback for Driver.GetTexImage().
4074 * All error checking will have been done before this routine is called.
4075 */
4076 void
4077 _mesa_get_teximage(GLcontext *ctx, GLenum target, GLint level,
4078 GLenum format, GLenum type, GLvoid *pixels,
4079 struct gl_texture_object *texObj,
4080 struct gl_texture_image *texImage)
4081 {
4082 GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2;
4083
4084 if (ctx->Pack.BufferObj->Name) {
4085 /* pack texture image into a PBO */
4086 GLubyte *buf;
4087 if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width,
4088 texImage->Height, texImage->Depth,
4089 format, type, pixels)) {
4090 _mesa_error(ctx, GL_INVALID_OPERATION,
4091 "glGetTexImage(invalid PBO access)");
4092 return;
4093 }
4094 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
4095 GL_WRITE_ONLY_ARB,
4096 ctx->Pack.BufferObj);
4097 if (!buf) {
4098 /* buffer is already mapped - that's an error */
4099 _mesa_error(ctx, GL_INVALID_OPERATION,"glGetTexImage(PBO is mapped)");
4100 return;
4101 }
4102 pixels = ADD_POINTERS(buf, pixels);
4103 }
4104 else if (!pixels) {
4105 /* not an error */
4106 return;
4107 }
4108
4109 {
4110 const GLint width = texImage->Width;
4111 const GLint height = texImage->Height;
4112 const GLint depth = texImage->Depth;
4113 GLint img, row;
4114 for (img = 0; img < depth; img++) {
4115 for (row = 0; row < height; row++) {
4116 /* compute destination address in client memory */
4117 GLvoid *dest = _mesa_image_address( dimensions, &ctx->Pack, pixels,
4118 width, height, format, type,
4119 img, row, 0);
4120 assert(dest);
4121
4122 if (format == GL_COLOR_INDEX) {
4123 GLuint indexRow[MAX_WIDTH];
4124 GLint col;
4125 /* Can't use FetchTexel here because that returns RGBA */
4126 if (texImage->TexFormat->IndexBits == 8) {
4127 const GLubyte *src = (const GLubyte *) texImage->Data;
4128 src += width * (img * texImage->Height + row);
4129 for (col = 0; col < width; col++) {
4130 indexRow[col] = src[col];
4131 }
4132 }
4133 else if (texImage->TexFormat->IndexBits == 16) {
4134 const GLushort *src = (const GLushort *) texImage->Data;
4135 src += width * (img * texImage->Height + row);
4136 for (col = 0; col < width; col++) {
4137 indexRow[col] = src[col];
4138 }
4139 }
4140 else {
4141 _mesa_problem(ctx,
4142 "Color index problem in _mesa_GetTexImage");
4143 }
4144 _mesa_pack_index_span(ctx, width, type, dest,
4145 indexRow, &ctx->Pack,
4146 0 /* no image transfer */);
4147 }
4148 else if (format == GL_DEPTH_COMPONENT) {
4149 GLfloat depthRow[MAX_WIDTH];
4150 GLint col;
4151 for (col = 0; col < width; col++) {
4152 (*texImage->FetchTexelf)(texImage, col, row, img,
4153 depthRow + col);
4154 }
4155 _mesa_pack_depth_span(ctx, width, dest, type,
4156 depthRow, &ctx->Pack);
4157 }
4158 else if (format == GL_DEPTH_STENCIL_EXT) {
4159 /* XXX Note: we're bypassing texImage->FetchTexel()! */
4160 const GLuint *src = (const GLuint *) texImage->Data;
4161 src += width * row + width * height * img;
4162 _mesa_memcpy(dest, src, width * sizeof(GLuint));
4163 if (ctx->Pack.SwapBytes) {
4164 _mesa_swap4((GLuint *) dest, width);
4165 }
4166 }
4167 else if (format == GL_YCBCR_MESA) {
4168 /* No pixel transfer */
4169 const GLint rowstride = texImage->RowStride;
4170 MEMCPY(dest,
4171 (const GLushort *) texImage->Data + row * rowstride,
4172 width * sizeof(GLushort));
4173 /* check for byte swapping */
4174 if ((texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR
4175 && type == GL_UNSIGNED_SHORT_8_8_REV_MESA) ||
4176 (texImage->TexFormat->MesaFormat == MESA_FORMAT_YCBCR_REV
4177 && type == GL_UNSIGNED_SHORT_8_8_MESA)) {
4178 if (!ctx->Pack.SwapBytes)
4179 _mesa_swap2((GLushort *) dest, width);
4180 }
4181 else if (ctx->Pack.SwapBytes) {
4182 _mesa_swap2((GLushort *) dest, width);
4183 }
4184 }
4185 else {
4186 /* general case: convert row to RGBA format */
4187 GLfloat rgba[MAX_WIDTH][4];
4188 GLint col;
4189 for (col = 0; col < width; col++) {
4190 (*texImage->FetchTexelf)(texImage, col, row, img, rgba[col]);
4191 }
4192 _mesa_pack_rgba_span_float(ctx, width,
4193 (const GLfloat (*)[4]) rgba,
4194 format, type, dest, &ctx->Pack,
4195 0 /* no image transfer */);
4196 } /* format */
4197 } /* row */
4198 } /* img */
4199 }
4200
4201 if (ctx->Pack.BufferObj->Name) {
4202 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
4203 ctx->Pack.BufferObj);
4204 }
4205 }
4206
4207
4208
4209 /**
4210 * This is the software fallback for Driver.GetCompressedTexImage().
4211 * All error checking will have been done before this routine is called.
4212 */
4213 void
4214 _mesa_get_compressed_teximage(GLcontext *ctx, GLenum target, GLint level,
4215 GLvoid *img,
4216 const struct gl_texture_object *texObj,
4217 const struct gl_texture_image *texImage)
4218 {
4219 if (ctx->Pack.BufferObj->Name) {
4220 /* pack texture image into a PBO */
4221 GLubyte *buf;
4222 if ((const GLubyte *) img + texImage->CompressedSize >
4223 (const GLubyte *) ctx->Pack.BufferObj->Size) {
4224 _mesa_error(ctx, GL_INVALID_OPERATION,
4225 "glGetCompressedTexImage(invalid PBO access)");
4226 return;
4227 }
4228 buf = (GLubyte *) ctx->Driver.MapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
4229 GL_WRITE_ONLY_ARB,
4230 ctx->Pack.BufferObj);
4231 if (!buf) {
4232 /* buffer is already mapped - that's an error */
4233 _mesa_error(ctx, GL_INVALID_OPERATION,
4234 "glGetCompressedTexImage(PBO is mapped)");
4235 return;
4236 }
4237 img = ADD_POINTERS(buf, img);
4238 }
4239 else if (!img) {
4240 /* not an error */
4241 return;
4242 }
4243
4244 /* just memcpy, no pixelstore or pixel transfer */
4245 MEMCPY(img, texImage->Data, texImage->CompressedSize);
4246
4247 if (ctx->Pack.BufferObj->Name) {
4248 ctx->Driver.UnmapBuffer(ctx, GL_PIXEL_PACK_BUFFER_EXT,
4249 ctx->Pack.BufferObj);
4250 }
4251 }