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