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