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