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