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