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