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