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