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