init secondary color to (0,0,0,1). remove some redundant initializations.
[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 "colormac.h"
56 #include "context.h"
57 #include "convolve.h"
58 #include "image.h"
59 #include "macros.h"
60 #include "imports.h"
61 #include "texcompress.h"
62 #include "texformat.h"
63 #include "teximage.h"
64 #include "texstore.h"
65 #include "texutil.h"
66
67
68 /*
69 * Given an internal texture format enum or 1, 2, 3, 4 return the
70 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
71 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. Return the
72 * number of components for the format. Return -1 if invalid enum.
73 */
74 static GLint
75 components_in_intformat( GLint format )
76 {
77 switch (format) {
78 case GL_ALPHA:
79 case GL_ALPHA4:
80 case GL_ALPHA8:
81 case GL_ALPHA12:
82 case GL_ALPHA16:
83 return 1;
84 case 1:
85 case GL_LUMINANCE:
86 case GL_LUMINANCE4:
87 case GL_LUMINANCE8:
88 case GL_LUMINANCE12:
89 case GL_LUMINANCE16:
90 return 1;
91 case 2:
92 case GL_LUMINANCE_ALPHA:
93 case GL_LUMINANCE4_ALPHA4:
94 case GL_LUMINANCE6_ALPHA2:
95 case GL_LUMINANCE8_ALPHA8:
96 case GL_LUMINANCE12_ALPHA4:
97 case GL_LUMINANCE12_ALPHA12:
98 case GL_LUMINANCE16_ALPHA16:
99 return 2;
100 case GL_INTENSITY:
101 case GL_INTENSITY4:
102 case GL_INTENSITY8:
103 case GL_INTENSITY12:
104 case GL_INTENSITY16:
105 return 1;
106 case 3:
107 case GL_RGB:
108 case GL_R3_G3_B2:
109 case GL_RGB4:
110 case GL_RGB5:
111 case GL_RGB8:
112 case GL_RGB10:
113 case GL_RGB12:
114 case GL_RGB16:
115 return 3;
116 case 4:
117 case GL_RGBA:
118 case GL_RGBA2:
119 case GL_RGBA4:
120 case GL_RGB5_A1:
121 case GL_RGBA8:
122 case GL_RGB10_A2:
123 case GL_RGBA12:
124 case GL_RGBA16:
125 return 4;
126 case GL_COLOR_INDEX:
127 case GL_COLOR_INDEX1_EXT:
128 case GL_COLOR_INDEX2_EXT:
129 case GL_COLOR_INDEX4_EXT:
130 case GL_COLOR_INDEX8_EXT:
131 case GL_COLOR_INDEX12_EXT:
132 case GL_COLOR_INDEX16_EXT:
133 return 1;
134 case GL_DEPTH_COMPONENT:
135 case GL_DEPTH_COMPONENT16_SGIX:
136 case GL_DEPTH_COMPONENT24_SGIX:
137 case GL_DEPTH_COMPONENT32_SGIX:
138 return 1;
139 case GL_YCBCR_MESA:
140 return 2; /* Y + (Cb or Cr) */
141 default:
142 return -1; /* error */
143 }
144 }
145
146
147 /*
148 * This function is used to transfer the user's image data into a texture
149 * image buffer. We handle both full texture images and subtexture images.
150 * We also take care of all image transfer operations here, including
151 * convolution, scale/bias, colortables, etc.
152 *
153 * The destination texel type is always GLchan.
154 * The destination texel format is one of the 6 basic types.
155 *
156 * A hardware driver may use this as a helper routine to unpack and
157 * apply pixel transfer ops into a temporary image buffer. Then,
158 * convert the temporary image into the special hardware format.
159 *
160 * \param
161 * dimensions - 1, 2, or 3
162 * texDestFormat - GL_LUMINANCE, GL_INTENSITY, GL_LUMINANCE_ALPHA, GL_ALPHA,
163 * GL_RGB or GL_RGBA (the destination format)
164 * texDestAddr - destination image address
165 * srcWidth, srcHeight, srcDepth - size (in pixels) of src and dest images
166 * dstXoffset, dstYoffset, dstZoffset - position to store the image within
167 * the destination 3D texture
168 * dstRowStride, dstImageStride - dest image strides in bytes
169 * srcFormat - source image format (GL_ALPHA, GL_RED, GL_RGB, etc)
170 * srcType - GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_6_5, GL_FLOAT, etc
171 * srcPacking - describes packing of incoming image.
172 * transferOps - mask of pixel transfer operations
173 */
174 static void
175 transfer_teximage(GLcontext *ctx, GLuint dimensions,
176 GLenum texDestFormat, GLvoid *texDestAddr,
177 GLint srcWidth, GLint srcHeight, GLint srcDepth,
178 GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
179 GLint dstRowStride, GLint dstImageStride,
180 GLenum srcFormat, GLenum srcType,
181 const GLvoid *srcAddr,
182 const struct gl_pixelstore_attrib *srcPacking,
183 GLuint transferOps)
184 {
185 GLint texComponents;
186
187 ASSERT(ctx);
188 ASSERT(dimensions >= 1 && dimensions <= 3);
189 ASSERT(texDestFormat == GL_LUMINANCE ||
190 texDestFormat == GL_INTENSITY ||
191 texDestFormat == GL_LUMINANCE_ALPHA ||
192 texDestFormat == GL_ALPHA ||
193 texDestFormat == GL_RGB ||
194 texDestFormat == GL_RGBA ||
195 texDestFormat == GL_COLOR_INDEX ||
196 texDestFormat == GL_DEPTH_COMPONENT);
197 ASSERT(texDestAddr);
198 ASSERT(srcWidth >= 0);
199 ASSERT(srcHeight >= 0);
200 ASSERT(srcDepth >= 0);
201 ASSERT(dstXoffset >= 0);
202 ASSERT(dstYoffset >= 0);
203 ASSERT(dstZoffset >= 0);
204 ASSERT(dstRowStride >= 0);
205 ASSERT(dstImageStride >= 0);
206 ASSERT(srcAddr);
207 ASSERT(srcPacking);
208
209 texComponents = components_in_intformat(texDestFormat);
210
211 /* try common 2D texture cases first */
212 if (!transferOps && dimensions == 2 && srcType == CHAN_TYPE) {
213
214 if (srcFormat == texDestFormat) {
215 /* This will cover the common GL_RGB, GL_RGBA, GL_ALPHA,
216 * GL_LUMINANCE_ALPHA, etc. texture formats. Use memcpy().
217 */
218 const GLchan *src = (const GLchan *) _mesa_image_address(
219 srcPacking, srcAddr, srcWidth, srcHeight,
220 srcFormat, srcType, 0, 0, 0);
221 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
222 srcWidth, srcFormat, srcType);
223 const GLint widthInBytes = srcWidth * texComponents * sizeof(GLchan);
224 GLchan *dst = (GLchan *) texDestAddr
225 + dstYoffset * (dstRowStride / sizeof(GLchan))
226 + dstXoffset * texComponents;
227 if (srcRowStride == widthInBytes && dstRowStride == widthInBytes) {
228 MEMCPY(dst, src, srcHeight * widthInBytes);
229 }
230 else {
231 GLint i;
232 for (i = 0; i < srcHeight; i++) {
233 MEMCPY(dst, src, widthInBytes);
234 src += (srcRowStride / sizeof(GLchan));
235 dst += (dstRowStride / sizeof(GLchan));
236 }
237 }
238 return; /* all done */
239 }
240 else if (srcFormat == GL_RGBA && texDestFormat == GL_RGB) {
241 /* commonly used by Quake */
242 const GLchan *src = (const GLchan *) _mesa_image_address(
243 srcPacking, srcAddr, srcWidth, srcHeight,
244 srcFormat, srcType, 0, 0, 0);
245 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
246 srcWidth, srcFormat, srcType);
247 GLchan *dst = (GLchan *) texDestAddr
248 + dstYoffset * (dstRowStride / sizeof(GLchan))
249 + dstXoffset * texComponents;
250 GLint i, j;
251 for (i = 0; i < srcHeight; i++) {
252 const GLchan *s = src;
253 GLchan *d = dst;
254 for (j = 0; j < srcWidth; j++) {
255 *d++ = *s++; /*red*/
256 *d++ = *s++; /*green*/
257 *d++ = *s++; /*blue*/
258 s++; /*alpha*/
259 }
260 src += (srcRowStride / sizeof(GLchan));
261 dst += (dstRowStride / sizeof(GLchan));
262 }
263 return; /* all done */
264 }
265 }
266
267 /*
268 * General case solutions
269 */
270 if (texDestFormat == GL_COLOR_INDEX) {
271 /* color index texture */
272 const GLenum texType = CHAN_TYPE;
273 GLint img, row;
274 GLchan *dest = (GLchan *) texDestAddr
275 + dstZoffset * (dstImageStride / sizeof(GLchan))
276 + dstYoffset * (dstRowStride / sizeof(GLchan))
277 + dstXoffset * texComponents;
278 for (img = 0; img < srcDepth; img++) {
279 GLchan *destRow = dest;
280 for (row = 0; row < srcHeight; row++) {
281 const GLvoid *src = _mesa_image_address(srcPacking,
282 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
283 _mesa_unpack_index_span(ctx, srcWidth, texType, destRow,
284 srcType, src, srcPacking, transferOps);
285 destRow += (dstRowStride / sizeof(GLchan));
286 }
287 dest += dstImageStride;
288 }
289 }
290 else if (texDestFormat == GL_YCBCR_MESA) {
291 /* YCbCr texture */
292 GLint img, row;
293 GLushort *dest = (GLushort *) texDestAddr
294 + dstZoffset * (dstImageStride / sizeof(GLushort))
295 + dstYoffset * (dstRowStride / sizeof(GLushort))
296 + dstXoffset * texComponents;
297 ASSERT(ctx->Extensions.MESA_ycbcr_texture);
298 for (img = 0; img < srcDepth; img++) {
299 GLushort *destRow = dest;
300 for (row = 0; row < srcHeight; row++) {
301 const GLvoid *srcRow = _mesa_image_address(srcPacking,
302 srcAddr, srcWidth, srcHeight,
303 srcFormat, srcType, img, row, 0);
304 MEMCPY(destRow, srcRow, srcWidth * sizeof(GLushort));
305 destRow += (dstRowStride / sizeof(GLushort));
306 }
307 dest += dstImageStride / sizeof(GLushort);
308 }
309 }
310 else if (texDestFormat == GL_DEPTH_COMPONENT) {
311 /* Depth texture (shadow maps) */
312 GLint img, row;
313 GLubyte *dest = (GLubyte *) texDestAddr
314 + dstZoffset * dstImageStride
315 + dstYoffset * (dstRowStride / sizeof(GLchan))
316 + dstXoffset * texComponents;
317 for (img = 0; img < srcDepth; img++) {
318 GLubyte *destRow = dest;
319 for (row = 0; row < srcHeight; row++) {
320 const GLvoid *src = _mesa_image_address(srcPacking,
321 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
322 _mesa_unpack_depth_span(ctx, srcWidth, (GLfloat *) destRow,
323 srcType, src, srcPacking);
324 destRow += (dstRowStride / sizeof(GLchan));
325 }
326 dest += dstImageStride;
327 }
328 }
329 else {
330 /* regular, color texture */
331 if ((dimensions == 1 && ctx->Pixel.Convolution1DEnabled) ||
332 (dimensions >= 2 && ctx->Pixel.Convolution2DEnabled) ||
333 (dimensions >= 2 && ctx->Pixel.Separable2DEnabled)) {
334 /*
335 * Fill texture image with convolution
336 */
337 GLint img, row;
338 GLint convWidth = srcWidth, convHeight = srcHeight;
339 GLfloat *tmpImage, *convImage;
340 tmpImage = (GLfloat *) MALLOC(srcWidth * srcHeight * 4 * sizeof(GLfloat));
341 if (!tmpImage) {
342 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
343 return;
344 }
345 convImage = (GLfloat *) MALLOC(srcWidth * srcHeight * 4 * sizeof(GLfloat));
346 if (!convImage) {
347 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
348 FREE(tmpImage);
349 return;
350 }
351
352 for (img = 0; img < srcDepth; img++) {
353 const GLfloat *srcf;
354 GLfloat *dstf = tmpImage;
355 GLchan *dest;
356
357 /* unpack and do transfer ops up to convolution */
358 for (row = 0; row < srcHeight; row++) {
359 const GLvoid *src = _mesa_image_address(srcPacking,
360 srcAddr, srcWidth, srcHeight,
361 srcFormat, srcType, img, row, 0);
362 _mesa_unpack_float_color_span(ctx, srcWidth, GL_RGBA, dstf,
363 srcFormat, srcType, src, srcPacking,
364 transferOps & IMAGE_PRE_CONVOLUTION_BITS,
365 GL_TRUE);
366 dstf += srcWidth * 4;
367 }
368
369 /* convolve */
370 if (dimensions == 1) {
371 ASSERT(ctx->Pixel.Convolution1DEnabled);
372 _mesa_convolve_1d_image(ctx, &convWidth, tmpImage, convImage);
373 }
374 else {
375 if (ctx->Pixel.Convolution2DEnabled) {
376 _mesa_convolve_2d_image(ctx, &convWidth, &convHeight,
377 tmpImage, convImage);
378 }
379 else {
380 ASSERT(ctx->Pixel.Separable2DEnabled);
381 _mesa_convolve_sep_image(ctx, &convWidth, &convHeight,
382 tmpImage, convImage);
383 }
384 }
385
386 /* packing and transfer ops after convolution */
387 srcf = convImage;
388 dest = (GLchan *) texDestAddr
389 + (dstZoffset + img) * (dstImageStride / sizeof(GLchan))
390 + dstYoffset * (dstRowStride / sizeof(GLchan));
391 for (row = 0; row < convHeight; row++) {
392 _mesa_pack_float_rgba_span(ctx, convWidth,
393 (const GLfloat (*)[4]) srcf,
394 texDestFormat, CHAN_TYPE,
395 dest, &_mesa_native_packing,
396 transferOps
397 & IMAGE_POST_CONVOLUTION_BITS);
398 srcf += convWidth * 4;
399 dest += (dstRowStride / sizeof(GLchan));
400 }
401 }
402
403 FREE(convImage);
404 FREE(tmpImage);
405 }
406 else {
407 /*
408 * no convolution
409 */
410 GLint img, row;
411 GLchan *dest = (GLchan *) texDestAddr
412 + dstZoffset * (dstImageStride / sizeof(GLchan))
413 + dstYoffset * (dstRowStride / sizeof(GLchan))
414 + dstXoffset * texComponents;
415 for (img = 0; img < srcDepth; img++) {
416 GLchan *destRow = dest;
417 for (row = 0; row < srcHeight; row++) {
418 const GLvoid *srcRow = _mesa_image_address(srcPacking,
419 srcAddr, srcWidth, srcHeight,
420 srcFormat, srcType, img, row, 0);
421 _mesa_unpack_chan_color_span(ctx, srcWidth, texDestFormat,
422 destRow, srcFormat, srcType, srcRow,
423 srcPacking, transferOps);
424 destRow += (dstRowStride / sizeof(GLchan));
425 }
426 dest += dstImageStride / sizeof(GLchan);
427 }
428 }
429 }
430 }
431
432
433
434 /*
435 * Transfer a texture image from user space to <destAddr> applying all
436 * needed image transfer operations and storing the result in the format
437 * specified by <dstFormat>. <dstFormat> may be any format from texformat.h.
438 * \param
439 * dimensions - 1, 2 or 3
440 * baseInternalFormat - base format of the internal texture format
441 * specified by the user. This is very important, see below.
442 * dstFormat - destination image format
443 * dstAddr - destination address
444 * srcWidth, srcHeight, srcDepth - size of source iamge
445 * dstX/Y/Zoffset - as specified by glTexSubImage
446 * dstRowStride - stride between dest rows in bytes
447 * dstImageStride - stride between dest images in bytes
448 * srcFormat, srcType - incoming image format and data type
449 * srcAddr - source image address
450 * srcPacking - packing params of source image
451 *
452 * XXX this function is a bit more complicated than it should be. If
453 * _mesa_convert_texsubimage[123]d could handle any dest/source formats
454 * or if transfer_teximage() could store in any MESA_FORMAT_* format, we
455 * could simplify things here.
456 */
457 void
458 _mesa_transfer_teximage(GLcontext *ctx, GLuint dimensions,
459 GLenum baseInternalFormat,
460 const struct gl_texture_format *dstFormat,
461 GLvoid *dstAddr,
462 GLint srcWidth, GLint srcHeight, GLint srcDepth,
463 GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
464 GLint dstRowStride, GLint dstImageStride,
465 GLenum srcFormat, GLenum srcType,
466 const GLvoid *srcAddr,
467 const struct gl_pixelstore_attrib *srcPacking)
468 {
469 const GLint dstRowStridePixels = dstRowStride / dstFormat->TexelBytes;
470 const GLint dstImageStridePixels = dstImageStride / dstFormat->TexelBytes;
471 GLboolean makeTemp;
472 GLuint transferOps = ctx->_ImageTransferState;
473 GLboolean freeSourceData = GL_FALSE;
474 GLint postConvWidth = srcWidth, postConvHeight = srcHeight;
475
476 assert(baseInternalFormat > 0);
477 ASSERT(baseInternalFormat == GL_LUMINANCE ||
478 baseInternalFormat == GL_INTENSITY ||
479 baseInternalFormat == GL_LUMINANCE_ALPHA ||
480 baseInternalFormat == GL_ALPHA ||
481 baseInternalFormat == GL_RGB ||
482 baseInternalFormat == GL_RGBA ||
483 baseInternalFormat == GL_YCBCR_MESA ||
484 baseInternalFormat == GL_COLOR_INDEX ||
485 baseInternalFormat == GL_DEPTH_COMPONENT);
486
487 if (transferOps & IMAGE_CONVOLUTION_BIT) {
488 _mesa_adjust_image_for_convolution(ctx, dimensions, &postConvWidth,
489 &postConvHeight);
490 }
491
492 /*
493 * Consider this scenario: The user's source image is GL_RGB and the
494 * requested internal format is GL_LUMINANCE. Now suppose the device
495 * driver doesn't support GL_LUMINANCE and instead uses RGB16 as the
496 * texture format. In that case we still need to do an intermediate
497 * conversion to luminance format so that the incoming red channel gets
498 * replicated into the dest red, green and blue channels. The following
499 * code takes care of that.
500 */
501 if (dstFormat->BaseFormat != baseInternalFormat) {
502 /* Allocate storage for temporary image in the baseInternalFormat */
503 const GLint texelSize = _mesa_components_in_format(baseInternalFormat)
504 * sizeof(GLchan);
505 const GLint bytes = texelSize * postConvWidth * postConvHeight *srcDepth;
506 const GLint tmpRowStride = texelSize * postConvWidth;
507 const GLint tmpImgStride = texelSize * postConvWidth * postConvHeight;
508 GLvoid *tmpImage = MALLOC(bytes);
509 if (!tmpImage)
510 return;
511 transfer_teximage(ctx, dimensions, baseInternalFormat, tmpImage,
512 srcWidth, srcHeight, srcDepth,
513 0, 0, 0, /* x/y/zoffset */
514 tmpRowStride, tmpImgStride,
515 srcFormat, srcType, srcAddr, srcPacking, transferOps);
516
517 /* this is our new source image */
518 srcWidth = postConvWidth;
519 srcHeight = postConvHeight;
520 srcFormat = baseInternalFormat;
521 srcType = CHAN_TYPE;
522 srcAddr = tmpImage;
523 srcPacking = &_mesa_native_packing;
524 freeSourceData = GL_TRUE;
525 transferOps = 0; /* image transfer ops were completed */
526 }
527
528 /* Let the optimized tex conversion functions take a crack at the
529 * image conversion if the dest format is a h/w format.
530 */
531 if (_mesa_is_hardware_tex_format(dstFormat)) {
532 if (transferOps) {
533 makeTemp = GL_TRUE;
534 }
535 else {
536 if (dimensions == 1) {
537 makeTemp = !_mesa_convert_texsubimage1d(dstFormat->MesaFormat,
538 dstXoffset,
539 srcWidth,
540 srcFormat, srcType,
541 srcPacking, srcAddr,
542 dstAddr);
543 }
544 else if (dimensions == 2) {
545 makeTemp = !_mesa_convert_texsubimage2d(dstFormat->MesaFormat,
546 dstXoffset, dstYoffset,
547 srcWidth, srcHeight,
548 dstRowStridePixels,
549 srcFormat, srcType,
550 srcPacking, srcAddr,
551 dstAddr);
552 }
553 else {
554 assert(dimensions == 3);
555 makeTemp = !_mesa_convert_texsubimage3d(dstFormat->MesaFormat,
556 dstXoffset, dstYoffset, dstZoffset,
557 srcWidth, srcHeight, srcDepth,
558 dstRowStridePixels, dstImageStridePixels,
559 srcFormat, srcType,
560 srcPacking, srcAddr, dstAddr);
561 }
562 if (!makeTemp) {
563 /* all done! */
564 if (freeSourceData)
565 FREE((void *) srcAddr);
566 return;
567 }
568 }
569 }
570 else {
571 /* software texture format */
572 makeTemp = GL_FALSE;
573 }
574
575 if (makeTemp) {
576 GLint postConvWidth = srcWidth, postConvHeight = srcHeight;
577 GLenum tmpFormat;
578 GLuint tmpComps, tmpTexelSize;
579 GLint tmpRowStride, tmpImageStride;
580 GLubyte *tmpImage;
581
582 if (transferOps & IMAGE_CONVOLUTION_BIT) {
583 _mesa_adjust_image_for_convolution(ctx, dimensions, &postConvWidth,
584 &postConvHeight);
585 }
586
587 tmpFormat = dstFormat->BaseFormat;
588 tmpComps = _mesa_components_in_format(tmpFormat);
589 tmpTexelSize = tmpComps * sizeof(GLchan);
590 tmpRowStride = postConvWidth * tmpTexelSize;
591 tmpImageStride = postConvWidth * postConvHeight * tmpTexelSize;
592 tmpImage = (GLubyte *) MALLOC(postConvWidth * postConvHeight *
593 srcDepth * tmpTexelSize);
594 if (!tmpImage) {
595 if (freeSourceData)
596 FREE((void *) srcAddr);
597 return;
598 }
599
600 transfer_teximage(ctx, dimensions, tmpFormat, tmpImage,
601 srcWidth, srcHeight, srcDepth,
602 0, 0, 0, /* x/y/zoffset */
603 tmpRowStride, tmpImageStride,
604 srcFormat, srcType, srcAddr, srcPacking, transferOps);
605
606 if (freeSourceData)
607 FREE((void *) srcAddr);
608
609 /* the temp image is our new source image */
610 srcWidth = postConvWidth;
611 srcHeight = postConvHeight;
612 srcFormat = tmpFormat;
613 srcType = CHAN_TYPE;
614 srcAddr = tmpImage;
615 srcPacking = &_mesa_native_packing;
616 freeSourceData = GL_TRUE;
617 }
618
619 if (_mesa_is_hardware_tex_format(dstFormat)) {
620 assert(makeTemp);
621 if (dimensions == 1) {
622 GLboolean b;
623 b = _mesa_convert_texsubimage1d(dstFormat->MesaFormat,
624 dstXoffset,
625 srcWidth,
626 srcFormat, srcType,
627 srcPacking, srcAddr,
628 dstAddr);
629 assert(b);
630 (void) b;
631 }
632 else if (dimensions == 2) {
633 GLboolean b;
634 b = _mesa_convert_texsubimage2d(dstFormat->MesaFormat,
635 dstXoffset, dstYoffset,
636 srcWidth, srcHeight,
637 dstRowStridePixels,
638 srcFormat, srcType,
639 srcPacking, srcAddr,
640 dstAddr);
641 assert(b);
642 (void) b;
643 }
644 else {
645 GLboolean b;
646 b = _mesa_convert_texsubimage3d(dstFormat->MesaFormat,
647 dstXoffset, dstYoffset, dstZoffset,
648 srcWidth, srcHeight, srcDepth,
649 dstRowStridePixels, dstImageStridePixels,
650 srcFormat, srcType,
651 srcPacking, srcAddr, dstAddr);
652 assert(b);
653 (void) b;
654 }
655 }
656 else {
657 /* software format */
658 assert(!makeTemp);
659 transfer_teximage(ctx, dimensions, dstFormat->BaseFormat, dstAddr,
660 srcWidth, srcHeight, srcDepth,
661 dstXoffset, dstYoffset, dstZoffset,
662 dstRowStride, dstImageStride,
663 srcFormat, srcType, srcAddr, srcPacking, transferOps);
664 }
665
666 if (freeSourceData)
667 FREE((void *) srcAddr); /* the temp image */
668 }
669
670
671
672 /**
673 * Given a user's uncompressed texture image, this function takes care of
674 * pixel unpacking, pixel transfer, format conversion and compression.
675 */
676 static void
677 transfer_compressed_teximage(GLcontext *ctx, GLuint dimensions,
678 GLsizei width, GLsizei height, GLsizei depth,
679 GLenum srcFormat, GLenum srcType,
680 const struct gl_pixelstore_attrib *unpacking,
681 const GLvoid *source,
682 const struct gl_texture_format *dstFormat,
683 GLubyte *dest,
684 GLint dstRowStride)
685 {
686 GLchan *tempImage = NULL;
687 GLint srcRowStride;
688 GLenum baseFormat;
689
690 ASSERT(dimensions == 2);
691 /* TexelBytes is zero if and only if it's a compressed format */
692 ASSERT(dstFormat->TexelBytes == 0);
693
694 baseFormat = dstFormat->BaseFormat;
695
696 if (srcFormat != baseFormat || srcType != CHAN_TYPE ||
697 ctx->_ImageTransferState != 0 || unpacking->SwapBytes) {
698 /* need to convert user's image to texImage->Format, GLchan */
699 GLint comps = components_in_intformat(baseFormat);
700 GLint postConvWidth = width, postConvHeight = height;
701
702 /* XXX convolution untested */
703 if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
704 _mesa_adjust_image_for_convolution(ctx, dimensions, &postConvWidth,
705 &postConvHeight);
706 }
707
708 tempImage = (GLchan*) MALLOC(width * height * comps * sizeof(GLchan));
709 if (!tempImage) {
710 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
711 return;
712 }
713 transfer_teximage(ctx, dimensions,
714 baseFormat, /* dest format */
715 tempImage, /* dst address */
716 width, height, depth, /* src size */
717 0, 0, 0, /* x/y/zoffset */
718 comps * width, /* dst row stride */
719 comps * width * height, /* dst image stride */
720 srcFormat, srcType, /* src format, type */
721 source, unpacking, /* src and src packing */
722 ctx->_ImageTransferState);
723 source = tempImage;
724 width = postConvWidth;
725 height = postConvHeight;
726 srcRowStride = width;
727 }
728 else {
729 if (unpacking->RowLength)
730 srcRowStride = unpacking->RowLength;
731 else
732 srcRowStride = width;
733 }
734
735 _mesa_compress_teximage(ctx, width, height, baseFormat,
736 (const GLchan *) source, srcRowStride,
737 dstFormat, dest, dstRowStride);
738 if (tempImage) {
739 FREE(tempImage);
740 }
741 }
742
743
744
745 /*
746 * This is the software fallback for Driver.TexImage1D()
747 * and Driver.CopyTexImage2D().
748 * The texture image type will be GLchan.
749 * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY,
750 * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA.
751 */
752 void
753 _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level,
754 GLint internalFormat,
755 GLint width, GLint border,
756 GLenum format, GLenum type, const GLvoid *pixels,
757 const struct gl_pixelstore_attrib *packing,
758 struct gl_texture_object *texObj,
759 struct gl_texture_image *texImage)
760 {
761 GLint postConvWidth = width;
762 GLint texelBytes, sizeInBytes;
763
764 if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
765 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
766 }
767
768 /* choose the texture format */
769 assert(ctx->Driver.ChooseTextureFormat);
770 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
771 internalFormat, format, type);
772 assert(texImage->TexFormat);
773 texImage->FetchTexelc = texImage->TexFormat->FetchTexel1D;
774 texImage->FetchTexelf = texImage->TexFormat->FetchTexel1Df;
775
776 texelBytes = texImage->TexFormat->TexelBytes;
777
778 /* allocate memory */
779 if (texImage->IsCompressed)
780 sizeInBytes = texImage->CompressedSize;
781 else
782 sizeInBytes = postConvWidth * texelBytes;
783 texImage->Data = MESA_PBUFFER_ALLOC(sizeInBytes);
784 if (!texImage->Data) {
785 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
786 return;
787 }
788
789 if (!pixels)
790 return;
791
792 /* unpack image, apply transfer ops and store in texImage->Data */
793 if (texImage->IsCompressed) {
794 GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
795 width);
796 transfer_compressed_teximage(ctx, 1, width, 1, 1,
797 format, type, packing,
798 pixels, texImage->TexFormat,
799 (GLubyte *) texImage->Data, dstRowStride);
800 }
801 else {
802 _mesa_transfer_teximage(ctx, 1,
803 texImage->Format, /* base format */
804 texImage->TexFormat, texImage->Data,
805 width, 1, 1, /* src size */
806 0, 0, 0, /* dstX/Y/Zoffset */
807 0, /* dstRowStride */
808 0, /* dstImageStride */
809 format, type, pixels, packing);
810 }
811
812 /* GL_SGIS_generate_mipmap */
813 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
814 _mesa_generate_mipmap(ctx, target,
815 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
816 texObj);
817 }
818 }
819
820
821 /*
822 * This is the software fallback for Driver.TexImage2D()
823 * and Driver.CopyTexImage2D().
824 * The texture image type will be GLchan.
825 * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY,
826 * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA.
827 */
828 void
829 _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level,
830 GLint internalFormat,
831 GLint width, GLint height, GLint border,
832 GLenum format, GLenum type, const void *pixels,
833 const struct gl_pixelstore_attrib *packing,
834 struct gl_texture_object *texObj,
835 struct gl_texture_image *texImage)
836 {
837 GLint postConvWidth = width, postConvHeight = height;
838 GLint texelBytes, sizeInBytes;
839
840 if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
841 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
842 &postConvHeight);
843 }
844
845 /* choose the texture format */
846 assert(ctx->Driver.ChooseTextureFormat);
847 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
848 internalFormat, format, type);
849 assert(texImage->TexFormat);
850 texImage->FetchTexelc = texImage->TexFormat->FetchTexel2D;
851 texImage->FetchTexelf = texImage->TexFormat->FetchTexel2Df;
852
853 texelBytes = texImage->TexFormat->TexelBytes;
854
855 /* allocate memory */
856 if (texImage->IsCompressed)
857 sizeInBytes = texImage->CompressedSize;
858 else
859 sizeInBytes = postConvWidth * postConvHeight * texelBytes;
860 texImage->Data = MESA_PBUFFER_ALLOC(sizeInBytes);
861 if (!texImage->Data) {
862 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
863 return;
864 }
865
866 if (!pixels)
867 return;
868
869 /* unpack image, apply transfer ops and store in texImage->Data */
870 if (texImage->IsCompressed) {
871 GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
872 width);
873 transfer_compressed_teximage(ctx, 2, width, height, 1,
874 format, type, packing,
875 pixels, texImage->TexFormat,
876 (GLubyte *) texImage->Data, dstRowStride);
877 }
878 else {
879 _mesa_transfer_teximage(ctx, 2,
880 texImage->Format,
881 texImage->TexFormat, texImage->Data,
882 width, height, 1, /* src size */
883 0, 0, 0, /* dstX/Y/Zoffset */
884 texImage->Width * texelBytes, /* dstRowStride */
885 0, /* dstImageStride */
886 format, type, pixels, packing);
887 }
888
889 /* GL_SGIS_generate_mipmap */
890 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
891 _mesa_generate_mipmap(ctx, target,
892 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
893 texObj);
894 }
895 }
896
897
898
899 /*
900 * This is the software fallback for Driver.TexImage3D()
901 * and Driver.CopyTexImage3D().
902 * The texture image type will be GLchan.
903 * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY,
904 * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA.
905 */
906 void
907 _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level,
908 GLint internalFormat,
909 GLint width, GLint height, GLint depth, GLint border,
910 GLenum format, GLenum type, const void *pixels,
911 const struct gl_pixelstore_attrib *packing,
912 struct gl_texture_object *texObj,
913 struct gl_texture_image *texImage)
914 {
915 GLint texelBytes, sizeInBytes;
916
917 /* choose the texture format */
918 assert(ctx->Driver.ChooseTextureFormat);
919 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
920 internalFormat, format, type);
921 assert(texImage->TexFormat);
922 texImage->FetchTexelc = texImage->TexFormat->FetchTexel3D;
923 texImage->FetchTexelf = texImage->TexFormat->FetchTexel3Df;
924
925 texelBytes = texImage->TexFormat->TexelBytes;
926
927 /* allocate memory */
928 if (texImage->IsCompressed)
929 sizeInBytes = texImage->CompressedSize;
930 else
931 sizeInBytes = width * height * depth * texelBytes;
932 texImage->Data = MESA_PBUFFER_ALLOC(sizeInBytes);
933 if (!texImage->Data) {
934 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
935 return;
936 }
937
938 if (!pixels)
939 return;
940
941 /* unpack image, apply transfer ops and store in texImage->Data */
942 if (texImage->IsCompressed) {
943 GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
944 width);
945 transfer_compressed_teximage(ctx, 3, width, height, depth,
946 format, type, packing,
947 pixels, texImage->TexFormat,
948 (GLubyte *) texImage->Data, dstRowStride);
949 }
950 else {
951 _mesa_transfer_teximage(ctx, 3,
952 texImage->Format,
953 texImage->TexFormat, texImage->Data,
954 width, height, depth, /* src size */
955 0, 0, 0, /* dstX/Y/Zoffset */
956 texImage->Width * texelBytes, /* dstRowStride */
957 texImage->Width * texImage->Height * texelBytes,
958 format, type, pixels, packing);
959 }
960
961 /* GL_SGIS_generate_mipmap */
962 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
963 _mesa_generate_mipmap(ctx, target,
964 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
965 texObj);
966 }
967 }
968
969
970
971
972 /*
973 * This is the software fallback for Driver.TexSubImage1D()
974 * and Driver.CopyTexSubImage1D().
975 */
976 void
977 _mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level,
978 GLint xoffset, GLint width,
979 GLenum format, GLenum type, const void *pixels,
980 const struct gl_pixelstore_attrib *packing,
981 struct gl_texture_object *texObj,
982 struct gl_texture_image *texImage)
983 {
984 if (texImage->IsCompressed) {
985 GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
986 texImage->Width);
987 GLubyte *dest = _mesa_compressed_image_address(xoffset, 0, 0,
988 texImage->IntFormat,
989 texImage->Width,
990 (GLubyte*) texImage->Data);
991 transfer_compressed_teximage(ctx, 1, /* dimensions */
992 width, 1, 1, /* size to replace */
993 format, type, /* source format/type */
994 packing, /* source packing */
995 pixels, /* source data */
996 texImage->TexFormat,/* dest format */
997 dest, dstRowStride);
998 }
999 else {
1000 _mesa_transfer_teximage(ctx, 1,
1001 texImage->Format,
1002 texImage->TexFormat, texImage->Data,
1003 width, 1, 1, /* src size */
1004 xoffset, 0, 0, /* dest offsets */
1005 0, /* dstRowStride */
1006 0, /* dstImageStride */
1007 format, type, pixels, packing);
1008 }
1009
1010 /* GL_SGIS_generate_mipmap */
1011 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
1012 _mesa_generate_mipmap(ctx, target,
1013 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
1014 texObj);
1015 }
1016 }
1017
1018
1019
1020 /*
1021 * This is the software fallback for Driver.TexSubImage2D()
1022 * and Driver.CopyTexSubImage2D().
1023 */
1024 void
1025 _mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level,
1026 GLint xoffset, GLint yoffset,
1027 GLint width, GLint height,
1028 GLenum format, GLenum type, const void *pixels,
1029 const struct gl_pixelstore_attrib *packing,
1030 struct gl_texture_object *texObj,
1031 struct gl_texture_image *texImage)
1032 {
1033 if (texImage->IsCompressed) {
1034 GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
1035 texImage->Width);
1036 GLubyte *dest = _mesa_compressed_image_address(xoffset, yoffset, 0,
1037 texImage->IntFormat,
1038 texImage->Width,
1039 (GLubyte*) texImage->Data);
1040 transfer_compressed_teximage(ctx, 2, /* dimensions */
1041 width, height, 1, /* size to replace */
1042 format, type, /* source format/type */
1043 packing, /* source packing */
1044 pixels, /* source data */
1045 texImage->TexFormat,/* dest format */
1046 dest, dstRowStride);
1047 }
1048 else {
1049 _mesa_transfer_teximage(ctx, 2,
1050 texImage->Format,
1051 texImage->TexFormat, texImage->Data,
1052 width, height, 1, /* src size */
1053 xoffset, yoffset, 0, /* dest offsets */
1054 texImage->Width *texImage->TexFormat->TexelBytes,
1055 0, /* dstImageStride */
1056 format, type, pixels, packing);
1057 }
1058
1059 /* GL_SGIS_generate_mipmap */
1060 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
1061 _mesa_generate_mipmap(ctx, target,
1062 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
1063 texObj);
1064 }
1065 }
1066
1067
1068 /*
1069 * This is the software fallback for Driver.TexSubImage3D().
1070 * and Driver.CopyTexSubImage3D().
1071 */
1072 void
1073 _mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level,
1074 GLint xoffset, GLint yoffset, GLint zoffset,
1075 GLint width, GLint height, GLint depth,
1076 GLenum format, GLenum type, const void *pixels,
1077 const struct gl_pixelstore_attrib *packing,
1078 struct gl_texture_object *texObj,
1079 struct gl_texture_image *texImage)
1080 {
1081 if (texImage->IsCompressed) {
1082 GLint dstRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
1083 texImage->Width);
1084 GLubyte *dest = _mesa_compressed_image_address(xoffset, yoffset, zoffset,
1085 texImage->IntFormat,
1086 texImage->Width,
1087 (GLubyte*) texImage->Data);
1088 transfer_compressed_teximage(ctx, 3, /* dimensions */
1089 width, height, depth,/* size to replace */
1090 format, type, /* source format/type */
1091 packing, /* source packing */
1092 pixels, /* source data */
1093 texImage->TexFormat,/* dest format */
1094 dest, dstRowStride);
1095 }
1096 else {
1097 const GLint texelBytes = texImage->TexFormat->TexelBytes;
1098 _mesa_transfer_teximage(ctx, 3,
1099 texImage->Format,
1100 texImage->TexFormat, texImage->Data,
1101 width, height, depth, /* src size */
1102 xoffset, yoffset, zoffset, /* dest offsets */
1103 texImage->Width * texelBytes, /* dst row stride */
1104 texImage->Width * texImage->Height * texelBytes,
1105 format, type, pixels, packing);
1106 }
1107
1108 /* GL_SGIS_generate_mipmap */
1109 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
1110 _mesa_generate_mipmap(ctx, target,
1111 &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
1112 texObj);
1113 }
1114 }
1115
1116
1117
1118
1119 /*
1120 * Fallback for Driver.CompressedTexImage1D()
1121 */
1122 void
1123 _mesa_store_compressed_teximage1d(GLcontext *ctx, GLenum target, GLint level,
1124 GLint internalFormat,
1125 GLint width, GLint border,
1126 GLsizei imageSize, const GLvoid *data,
1127 struct gl_texture_object *texObj,
1128 struct gl_texture_image *texImage)
1129 {
1130 /* this space intentionally left blank */
1131 }
1132
1133
1134
1135 /*
1136 * Fallback for Driver.CompressedTexImage2D()
1137 */
1138 void
1139 _mesa_store_compressed_teximage2d(GLcontext *ctx, GLenum target, GLint level,
1140 GLint internalFormat,
1141 GLint width, GLint height, GLint border,
1142 GLsizei imageSize, const GLvoid *data,
1143 struct gl_texture_object *texObj,
1144 struct gl_texture_image *texImage)
1145 {
1146 /* This is pretty simple, basically just do a memcpy without worrying
1147 * about the usual image unpacking or image transfer operations.
1148 */
1149 ASSERT(texObj);
1150 ASSERT(texImage);
1151 ASSERT(texImage->Width > 0);
1152 ASSERT(texImage->Height > 0);
1153 ASSERT(texImage->Depth == 1);
1154 ASSERT(texImage->Data == NULL); /* was freed in glCompressedTexImage2DARB */
1155
1156 /* choose the texture format */
1157 assert(ctx->Driver.ChooseTextureFormat);
1158 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
1159 internalFormat, 0, 0);
1160 assert(texImage->TexFormat);
1161 texImage->FetchTexelc = texImage->TexFormat->FetchTexel2D;
1162 texImage->FetchTexelf = texImage->TexFormat->FetchTexel2Df;
1163
1164 /* allocate storage */
1165 texImage->Data = MESA_PBUFFER_ALLOC(imageSize);
1166 if (!texImage->Data) {
1167 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB");
1168 return;
1169 }
1170
1171 /* copy the data */
1172 ASSERT(texImage->CompressedSize == (GLuint) imageSize);
1173 MEMCPY(texImage->Data, data, imageSize);
1174 }
1175
1176
1177
1178 /*
1179 * Fallback for Driver.CompressedTexImage3D()
1180 */
1181 void
1182 _mesa_store_compressed_teximage3d(GLcontext *ctx, GLenum target, GLint level,
1183 GLint internalFormat,
1184 GLint width, GLint height, GLint depth,
1185 GLint border,
1186 GLsizei imageSize, const GLvoid *data,
1187 struct gl_texture_object *texObj,
1188 struct gl_texture_image *texImage)
1189 {
1190 /* this space intentionally left blank */
1191 }
1192
1193
1194
1195 /**
1196 * Fallback for Driver.CompressedTexSubImage1D()
1197 */
1198 void
1199 _mesa_store_compressed_texsubimage1d(GLcontext *ctx, GLenum target,
1200 GLint level,
1201 GLint xoffset, GLsizei width,
1202 GLenum format,
1203 GLsizei imageSize, const GLvoid *data,
1204 struct gl_texture_object *texObj,
1205 struct gl_texture_image *texImage)
1206 {
1207 /* this space intentionally left blank */
1208 }
1209
1210
1211 /**
1212 * Fallback for Driver.CompressedTexSubImage2D()
1213 */
1214 void
1215 _mesa_store_compressed_texsubimage2d(GLcontext *ctx, GLenum target,
1216 GLint level,
1217 GLint xoffset, GLint yoffset,
1218 GLsizei width, GLsizei height,
1219 GLenum format,
1220 GLsizei imageSize, const GLvoid *data,
1221 struct gl_texture_object *texObj,
1222 struct gl_texture_image *texImage)
1223 {
1224 GLint bytesPerRow, destRowStride, srcRowStride;
1225 GLint i, rows;
1226 GLubyte *dest;
1227 const GLubyte *src;
1228
1229 /* these should have been caught sooner */
1230 ASSERT((width & 3) == 0 || width == 2 || width == 1);
1231 ASSERT((height & 3) == 0 || height == 2 || height == 1);
1232 ASSERT((xoffset & 3) == 0);
1233 ASSERT((yoffset & 3) == 0);
1234
1235 srcRowStride = _mesa_compressed_row_stride(texImage->IntFormat, width);
1236 src = (const GLubyte *) data;
1237
1238 destRowStride = _mesa_compressed_row_stride(texImage->IntFormat,
1239 texImage->Width);
1240 dest = _mesa_compressed_image_address(xoffset, yoffset, 0,
1241 texImage->IntFormat,
1242 texImage->Width,
1243 (GLubyte*) texImage->Data);
1244
1245 bytesPerRow = srcRowStride;
1246 rows = height / 4;
1247
1248 for (i = 0; i < rows; i++) {
1249 MEMCPY(dest, src, bytesPerRow);
1250 dest += destRowStride;
1251 src += srcRowStride;
1252 }
1253 }
1254
1255
1256 /**
1257 * Fallback for Driver.CompressedTexSubImage3D()
1258 */
1259 void
1260 _mesa_store_compressed_texsubimage3d(GLcontext *ctx, GLenum target,
1261 GLint level,
1262 GLint xoffset, GLint yoffset, GLint zoffset,
1263 GLsizei width, GLsizei height, GLsizei depth,
1264 GLenum format,
1265 GLsizei imageSize, const GLvoid *data,
1266 struct gl_texture_object *texObj,
1267 struct gl_texture_image *texImage)
1268 {
1269 /* this space intentionally left blank */
1270 }
1271
1272
1273 /*
1274 * Average together two rows of a source image to produce a single new
1275 * row in the dest image. It's legal for the two source rows to point
1276 * to the same data. The source width must be equal to either the
1277 * dest width or two times the dest width.
1278 */
1279 static void
1280 do_row(const struct gl_texture_format *format, GLint srcWidth,
1281 const GLvoid *srcRowA, const GLvoid *srcRowB,
1282 GLint dstWidth, GLvoid *dstRow)
1283 {
1284 const GLuint k0 = (srcWidth == dstWidth) ? 0 : 1;
1285 const GLuint colStride = (srcWidth == dstWidth) ? 1 : 2;
1286
1287 /* This assertion is no longer valid with non-power-of-2 textures
1288 assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
1289 */
1290
1291 switch (format->MesaFormat) {
1292 case MESA_FORMAT_RGBA:
1293 {
1294 GLuint i, j, k;
1295 const GLchan (*rowA)[4] = (const GLchan (*)[4]) srcRowA;
1296 const GLchan (*rowB)[4] = (const GLchan (*)[4]) srcRowB;
1297 GLchan (*dst)[4] = (GLchan (*)[4]) dstRow;
1298 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
1299 i++, j += colStride, k += colStride) {
1300 dst[i][0] = (rowA[j][0] + rowA[k][0] +
1301 rowB[j][0] + rowB[k][0]) / 4;
1302 dst[i][1] = (rowA[j][1] + rowA[k][1] +
1303 rowB[j][1] + rowB[k][1]) / 4;
1304 dst[i][2] = (rowA[j][2] + rowA[k][2] +
1305 rowB[j][2] + rowB[k][2]) / 4;
1306 dst[i][3] = (rowA[j][3] + rowA[k][3] +
1307 rowB[j][3] + rowB[k][3]) / 4;
1308 }
1309 }
1310 return;
1311 case MESA_FORMAT_RGB:
1312 {
1313 GLuint i, j, k;
1314 const GLchan (*rowA)[3] = (const GLchan (*)[3]) srcRowA;
1315 const GLchan (*rowB)[3] = (const GLchan (*)[3]) srcRowB;
1316 GLchan (*dst)[3] = (GLchan (*)[3]) dstRow;
1317 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
1318 i++, j += colStride, k += colStride) {
1319 dst[i][0] = (rowA[j][0] + rowA[k][0] +
1320 rowB[j][0] + rowB[k][0]) / 4;
1321 dst[i][1] = (rowA[j][1] + rowA[k][1] +
1322 rowB[j][1] + rowB[k][1]) / 4;
1323 dst[i][2] = (rowA[j][2] + rowA[k][2] +
1324 rowB[j][2] + rowB[k][2]) / 4;
1325 }
1326 }
1327 return;
1328 case MESA_FORMAT_ALPHA:
1329 case MESA_FORMAT_LUMINANCE:
1330 case MESA_FORMAT_INTENSITY:
1331 case MESA_FORMAT_COLOR_INDEX:
1332 {
1333 GLuint i, j, k;
1334 const GLchan *rowA = (const GLchan *) srcRowA;
1335 const GLchan *rowB = (const GLchan *) srcRowB;
1336 GLchan *dst = (GLchan *) dstRow;
1337 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
1338 i++, j += colStride, k += colStride) {
1339 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
1340 }
1341 }
1342 return;
1343 case MESA_FORMAT_LUMINANCE_ALPHA:
1344 {
1345 GLuint i, j, k;
1346 const GLchan (*rowA)[2] = (const GLchan (*)[2]) srcRowA;
1347 const GLchan (*rowB)[2] = (const GLchan (*)[2]) srcRowB;
1348 GLchan (*dst)[2] = (GLchan (*)[2]) dstRow;
1349 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
1350 i++, j += colStride, k += colStride) {
1351 dst[i][0] = (rowA[j][0] + rowA[k][0] +
1352 rowB[j][0] + rowB[k][0]) / 4;
1353 dst[i][1] = (rowA[j][1] + rowA[k][1] +
1354 rowB[j][1] + rowB[k][1]) / 4;
1355 }
1356 }
1357 return;
1358 case MESA_FORMAT_DEPTH_COMPONENT:
1359 {
1360 GLuint i, j, k;
1361 const GLfloat *rowA = (const GLfloat *) srcRowA;
1362 const GLfloat *rowB = (const GLfloat *) srcRowB;
1363 GLfloat *dst = (GLfloat *) dstRow;
1364 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
1365 i++, j += colStride, k += colStride) {
1366 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F;
1367 }
1368 }
1369 return;
1370 /* Begin hardware formats */
1371 case MESA_FORMAT_RGBA8888:
1372 case MESA_FORMAT_ARGB8888:
1373 {
1374 GLuint i, j, k;
1375 const GLubyte (*rowA)[4] = (const GLubyte (*)[4]) srcRowA;
1376 const GLubyte (*rowB)[4] = (const GLubyte (*)[4]) srcRowB;
1377 GLubyte (*dst)[4] = (GLubyte (*)[4]) dstRow;
1378 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
1379 i++, j += colStride, k += colStride) {
1380 dst[i][0] = (rowA[j][0] + rowA[k][0] +
1381 rowB[j][0] + rowB[k][0]) / 4;
1382 dst[i][1] = (rowA[j][1] + rowA[k][1] +
1383 rowB[j][1] + rowB[k][1]) / 4;
1384 dst[i][2] = (rowA[j][2] + rowA[k][2] +
1385 rowB[j][2] + rowB[k][2]) / 4;
1386 dst[i][3] = (rowA[j][3] + rowA[k][3] +
1387 rowB[j][3] + rowB[k][3]) / 4;
1388 }
1389 }
1390 return;
1391 case MESA_FORMAT_RGB888:
1392 {
1393 GLuint i, j, k;
1394 const GLubyte (*rowA)[3] = (const GLubyte (*)[3]) srcRowA;
1395 const GLubyte (*rowB)[3] = (const GLubyte (*)[3]) srcRowB;
1396 GLubyte (*dst)[3] = (GLubyte (*)[3]) dstRow;
1397 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
1398 i++, j += colStride, k += colStride) {
1399 dst[i][0] = (rowA[j][0] + rowA[k][0] +
1400 rowB[j][0] + rowB[k][0]) / 4;
1401 dst[i][1] = (rowA[j][1] + rowA[k][1] +
1402 rowB[j][1] + rowB[k][1]) / 4;
1403 dst[i][2] = (rowA[j][2] + rowA[k][2] +
1404 rowB[j][2] + rowB[k][2]) / 4;
1405 }
1406 }
1407 return;
1408 case MESA_FORMAT_RGB565:
1409 {
1410 GLuint i, j, k;
1411 const GLushort *rowA = (const GLushort *) srcRowA;
1412 const GLushort *rowB = (const GLushort *) srcRowB;
1413 GLushort *dst = (GLushort *) dstRow;
1414 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
1415 i++, j += colStride, k += colStride) {
1416 const GLint rowAr0 = rowA[j] & 0x1f;
1417 const GLint rowAr1 = rowA[k] & 0x1f;
1418 const GLint rowBr0 = rowB[j] & 0x1f;
1419 const GLint rowBr1 = rowB[k] & 0x1f;
1420 const GLint rowAg0 = (rowA[j] >> 5) & 0x3f;
1421 const GLint rowAg1 = (rowA[k] >> 5) & 0x3f;
1422 const GLint rowBg0 = (rowB[j] >> 5) & 0x3f;
1423 const GLint rowBg1 = (rowB[k] >> 5) & 0x3f;
1424 const GLint rowAb0 = (rowA[j] >> 11) & 0x1f;
1425 const GLint rowAb1 = (rowA[k] >> 11) & 0x1f;
1426 const GLint rowBb0 = (rowB[j] >> 11) & 0x1f;
1427 const GLint rowBb1 = (rowB[k] >> 11) & 0x1f;
1428 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
1429 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
1430 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
1431 dst[i] = (blue << 11) | (green << 5) | red;
1432 }
1433 }
1434 return;
1435 case MESA_FORMAT_ARGB4444:
1436 {
1437 GLuint i, j, k;
1438 const GLushort *rowA = (const GLushort *) srcRowA;
1439 const GLushort *rowB = (const GLushort *) srcRowB;
1440 GLushort *dst = (GLushort *) dstRow;
1441 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
1442 i++, j += colStride, k += colStride) {
1443 const GLint rowAr0 = rowA[j] & 0xf;
1444 const GLint rowAr1 = rowA[k] & 0xf;
1445 const GLint rowBr0 = rowB[j] & 0xf;
1446 const GLint rowBr1 = rowB[k] & 0xf;
1447 const GLint rowAg0 = (rowA[j] >> 4) & 0xf;
1448 const GLint rowAg1 = (rowA[k] >> 4) & 0xf;
1449 const GLint rowBg0 = (rowB[j] >> 4) & 0xf;
1450 const GLint rowBg1 = (rowB[k] >> 4) & 0xf;
1451 const GLint rowAb0 = (rowA[j] >> 8) & 0xf;
1452 const GLint rowAb1 = (rowA[k] >> 8) & 0xf;
1453 const GLint rowBb0 = (rowB[j] >> 8) & 0xf;
1454 const GLint rowBb1 = (rowB[k] >> 8) & 0xf;
1455 const GLint rowAa0 = (rowA[j] >> 12) & 0xf;
1456 const GLint rowAa1 = (rowA[k] >> 12) & 0xf;
1457 const GLint rowBa0 = (rowB[j] >> 12) & 0xf;
1458 const GLint rowBa1 = (rowB[k] >> 12) & 0xf;
1459 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
1460 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
1461 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
1462 const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
1463 dst[i] = (alpha << 12) | (blue << 8) | (green << 4) | red;
1464 }
1465 }
1466 return;
1467 case MESA_FORMAT_ARGB1555:
1468 {
1469 GLuint i, j, k;
1470 const GLushort *rowA = (const GLushort *) srcRowA;
1471 const GLushort *rowB = (const GLushort *) srcRowB;
1472 GLushort *dst = (GLushort *) dstRow;
1473 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
1474 i++, j += colStride, k += colStride) {
1475 const GLint rowAr0 = rowA[j] & 0x1f;
1476 const GLint rowAr1 = rowA[k] & 0x1f;
1477 const GLint rowBr0 = rowB[j] & 0x1f;
1478 const GLint rowBr1 = rowB[k] & 0xf;
1479 const GLint rowAg0 = (rowA[j] >> 5) & 0x1f;
1480 const GLint rowAg1 = (rowA[k] >> 5) & 0x1f;
1481 const GLint rowBg0 = (rowB[j] >> 5) & 0x1f;
1482 const GLint rowBg1 = (rowB[k] >> 5) & 0x1f;
1483 const GLint rowAb0 = (rowA[j] >> 10) & 0x1f;
1484 const GLint rowAb1 = (rowA[k] >> 10) & 0x1f;
1485 const GLint rowBb0 = (rowB[j] >> 10) & 0x1f;
1486 const GLint rowBb1 = (rowB[k] >> 10) & 0x1f;
1487 const GLint rowAa0 = (rowA[j] >> 15) & 0x1;
1488 const GLint rowAa1 = (rowA[k] >> 15) & 0x1;
1489 const GLint rowBa0 = (rowB[j] >> 15) & 0x1;
1490 const GLint rowBa1 = (rowB[k] >> 15) & 0x1;
1491 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
1492 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
1493 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
1494 const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
1495 dst[i] = (alpha << 15) | (blue << 10) | (green << 5) | red;
1496 }
1497 }
1498 return;
1499 case MESA_FORMAT_AL88:
1500 {
1501 GLuint i, j, k;
1502 const GLubyte (*rowA)[2] = (const GLubyte (*)[2]) srcRowA;
1503 const GLubyte (*rowB)[2] = (const GLubyte (*)[2]) srcRowB;
1504 GLubyte (*dst)[2] = (GLubyte (*)[2]) dstRow;
1505 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
1506 i++, j += colStride, k += colStride) {
1507 dst[i][0] = (rowA[j][0] + rowA[k][0] +
1508 rowB[j][0] + rowB[k][0]) >> 2;
1509 dst[i][1] = (rowA[j][1] + rowA[k][1] +
1510 rowB[j][1] + rowB[k][1]) >> 2;
1511 }
1512 }
1513 return;
1514 case MESA_FORMAT_RGB332:
1515 {
1516 GLuint i, j, k;
1517 const GLubyte *rowA = (const GLubyte *) srcRowA;
1518 const GLubyte *rowB = (const GLubyte *) srcRowB;
1519 GLubyte *dst = (GLubyte *) dstRow;
1520 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
1521 i++, j += colStride, k += colStride) {
1522 const GLint rowAr0 = rowA[j] & 0x3;
1523 const GLint rowAr1 = rowA[k] & 0x3;
1524 const GLint rowBr0 = rowB[j] & 0x3;
1525 const GLint rowBr1 = rowB[k] & 0x3;
1526 const GLint rowAg0 = (rowA[j] >> 2) & 0x7;
1527 const GLint rowAg1 = (rowA[k] >> 2) & 0x7;
1528 const GLint rowBg0 = (rowB[j] >> 2) & 0x7;
1529 const GLint rowBg1 = (rowB[k] >> 2) & 0x7;
1530 const GLint rowAb0 = (rowA[j] >> 5) & 0x7;
1531 const GLint rowAb1 = (rowA[k] >> 5) & 0x7;
1532 const GLint rowBb0 = (rowB[j] >> 5) & 0x7;
1533 const GLint rowBb1 = (rowB[k] >> 5) & 0x7;
1534 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
1535 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
1536 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
1537 dst[i] = (blue << 5) | (green << 2) | red;
1538 }
1539 }
1540 return;
1541 case MESA_FORMAT_A8:
1542 case MESA_FORMAT_L8:
1543 case MESA_FORMAT_I8:
1544 case MESA_FORMAT_CI8:
1545 {
1546 GLuint i, j, k;
1547 const GLubyte *rowA = (const GLubyte *) srcRowA;
1548 const GLubyte *rowB = (const GLubyte *) srcRowB;
1549 GLubyte *dst = (GLubyte *) dstRow;
1550 for (i = j = 0, k = k0; i < (GLuint) dstWidth;
1551 i++, j += colStride, k += colStride) {
1552 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) >> 2;
1553 }
1554 }
1555 return;
1556 default:
1557 _mesa_problem(NULL, "bad format in do_row()");
1558 }
1559 }
1560
1561
1562 /*
1563 * These functions generate a 1/2-size mipmap image from a source image.
1564 * Texture borders are handled by copying or averaging the source image's
1565 * border texels, depending on the scale-down factor.
1566 */
1567
1568 static void
1569 make_1d_mipmap(const struct gl_texture_format *format, GLint border,
1570 GLint srcWidth, const GLubyte *srcPtr,
1571 GLint dstWidth, GLubyte *dstPtr)
1572 {
1573 const GLint bpt = format->TexelBytes;
1574 const GLubyte *src;
1575 GLubyte *dst;
1576
1577 /* skip the border pixel, if any */
1578 src = srcPtr + border * bpt;
1579 dst = dstPtr + border * bpt;
1580
1581 /* we just duplicate the input row, kind of hack, saves code */
1582 do_row(format, srcWidth - 2 * border, src, src,
1583 dstWidth - 2 * border, dst);
1584
1585 if (border) {
1586 /* copy left-most pixel from source */
1587 MEMCPY(dstPtr, srcPtr, bpt);
1588 /* copy right-most pixel from source */
1589 MEMCPY(dstPtr + (dstWidth - 1) * bpt,
1590 srcPtr + (srcWidth - 1) * bpt,
1591 bpt);
1592 }
1593 }
1594
1595
1596 static void
1597 make_2d_mipmap(const struct gl_texture_format *format, GLint border,
1598 GLint srcWidth, GLint srcHeight, const GLubyte *srcPtr,
1599 GLint dstWidth, GLint dstHeight, GLubyte *dstPtr)
1600 {
1601 const GLint bpt = format->TexelBytes;
1602 const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */
1603 const GLint dstWidthNB = dstWidth - 2 * border;
1604 const GLint dstHeightNB = dstHeight - 2 * border;
1605 const GLint srcRowStride = bpt * srcWidth;
1606 const GLint dstRowStride = bpt * dstWidth;
1607 const GLubyte *srcA, *srcB;
1608 GLubyte *dst;
1609 GLint row, colStride;
1610
1611 colStride = (srcWidth == dstWidth) ? 1 : 2;
1612
1613 /* Compute src and dst pointers, skipping any border */
1614 srcA = srcPtr + border * ((srcWidth + 1) * bpt);
1615 if (srcHeight > 1)
1616 srcB = srcA + srcRowStride;
1617 else
1618 srcB = srcA;
1619 dst = dstPtr + border * ((dstWidth + 1) * bpt);
1620
1621 for (row = 0; row < dstHeightNB; row++) {
1622 do_row(format, srcWidthNB, srcA, srcB,
1623 dstWidthNB, dst);
1624 srcA += 2 * srcRowStride;
1625 srcB += 2 * srcRowStride;
1626 dst += dstRowStride;
1627 }
1628
1629 /* This is ugly but probably won't be used much */
1630 if (border > 0) {
1631 /* fill in dest border */
1632 /* lower-left border pixel */
1633 MEMCPY(dstPtr, srcPtr, bpt);
1634 /* lower-right border pixel */
1635 MEMCPY(dstPtr + (dstWidth - 1) * bpt,
1636 srcPtr + (srcWidth - 1) * bpt, bpt);
1637 /* upper-left border pixel */
1638 MEMCPY(dstPtr + dstWidth * (dstHeight - 1) * bpt,
1639 srcPtr + srcWidth * (srcHeight - 1) * bpt, bpt);
1640 /* upper-right border pixel */
1641 MEMCPY(dstPtr + (dstWidth * dstHeight - 1) * bpt,
1642 srcPtr + (srcWidth * srcHeight - 1) * bpt, bpt);
1643 /* lower border */
1644 do_row(format, srcWidthNB,
1645 srcPtr + bpt,
1646 srcPtr + bpt,
1647 dstWidthNB, dstPtr + bpt);
1648 /* upper border */
1649 do_row(format, srcWidthNB,
1650 srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
1651 srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
1652 dstWidthNB,
1653 dstPtr + (dstWidth * (dstHeight - 1) + 1) * bpt);
1654 /* left and right borders */
1655 if (srcHeight == dstHeight) {
1656 /* copy border pixel from src to dst */
1657 for (row = 1; row < srcHeight; row++) {
1658 MEMCPY(dstPtr + dstWidth * row * bpt,
1659 srcPtr + srcWidth * row * bpt, bpt);
1660 MEMCPY(dstPtr + (dstWidth * row + dstWidth - 1) * bpt,
1661 srcPtr + (srcWidth * row + srcWidth - 1) * bpt, bpt);
1662 }
1663 }
1664 else {
1665 /* average two src pixels each dest pixel */
1666 for (row = 0; row < dstHeightNB; row += 2) {
1667 do_row(format, 1,
1668 srcPtr + (srcWidth * (row * 2 + 1)) * bpt,
1669 srcPtr + (srcWidth * (row * 2 + 2)) * bpt,
1670 1, dstPtr + (dstWidth * row + 1) * bpt);
1671 do_row(format, 1,
1672 srcPtr + (srcWidth * (row * 2 + 1) + srcWidth - 1) * bpt,
1673 srcPtr + (srcWidth * (row * 2 + 2) + srcWidth - 1) * bpt,
1674 1, dstPtr + (dstWidth * row + 1 + dstWidth - 1) * bpt);
1675 }
1676 }
1677 }
1678 }
1679
1680
1681 static void
1682 make_3d_mipmap(const struct gl_texture_format *format, GLint border,
1683 GLint srcWidth, GLint srcHeight, GLint srcDepth,
1684 const GLubyte *srcPtr,
1685 GLint dstWidth, GLint dstHeight, GLint dstDepth,
1686 GLubyte *dstPtr)
1687 {
1688 const GLint bpt = format->TexelBytes;
1689 const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */
1690 const GLint srcDepthNB = srcDepth - 2 * border;
1691 const GLint dstWidthNB = dstWidth - 2 * border;
1692 const GLint dstHeightNB = dstHeight - 2 * border;
1693 const GLint dstDepthNB = dstDepth - 2 * border;
1694 GLvoid *tmpRowA, *tmpRowB;
1695 GLint img, row;
1696 GLint bytesPerSrcImage, bytesPerDstImage;
1697 GLint bytesPerSrcRow, bytesPerDstRow;
1698 GLint srcImageOffset, srcRowOffset;
1699
1700 (void) srcDepthNB; /* silence warnings */
1701
1702 /* Need two temporary row buffers */
1703 tmpRowA = MALLOC(srcWidth * bpt);
1704 if (!tmpRowA)
1705 return;
1706 tmpRowB = MALLOC(srcWidth * bpt);
1707 if (!tmpRowB) {
1708 FREE(tmpRowA);
1709 return;
1710 }
1711
1712 bytesPerSrcImage = srcWidth * srcHeight * bpt;
1713 bytesPerDstImage = dstWidth * dstHeight * bpt;
1714
1715 bytesPerSrcRow = srcWidth * bpt;
1716 bytesPerDstRow = dstWidth * bpt;
1717
1718 /* Offset between adjacent src images to be averaged together */
1719 srcImageOffset = (srcDepth == dstDepth) ? 0 : bytesPerSrcImage;
1720
1721 /* Offset between adjacent src rows to be averaged together */
1722 srcRowOffset = (srcHeight == dstHeight) ? 0 : srcWidth * bpt;
1723
1724 /*
1725 * Need to average together up to 8 src pixels for each dest pixel.
1726 * Break that down into 3 operations:
1727 * 1. take two rows from source image and average them together.
1728 * 2. take two rows from next source image and average them together.
1729 * 3. take the two averaged rows and average them for the final dst row.
1730 */
1731
1732 /*
1733 _mesa_printf("mip3d %d x %d x %d -> %d x %d x %d\n",
1734 srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth);
1735 */
1736
1737 for (img = 0; img < dstDepthNB; img++) {
1738 /* first source image pointer, skipping border */
1739 const GLubyte *imgSrcA = srcPtr
1740 + (bytesPerSrcImage + bytesPerSrcRow + border) * bpt * border
1741 + img * (bytesPerSrcImage + srcImageOffset);
1742 /* second source image pointer, skipping border */
1743 const GLubyte *imgSrcB = imgSrcA + srcImageOffset;
1744 /* address of the dest image, skipping border */
1745 GLubyte *imgDst = dstPtr
1746 + (bytesPerDstImage + bytesPerDstRow + border) * bpt * border
1747 + img * bytesPerDstImage;
1748
1749 /* setup the four source row pointers and the dest row pointer */
1750 const GLubyte *srcImgARowA = imgSrcA;
1751 const GLubyte *srcImgARowB = imgSrcA + srcRowOffset;
1752 const GLubyte *srcImgBRowA = imgSrcB;
1753 const GLubyte *srcImgBRowB = imgSrcB + srcRowOffset;
1754 GLubyte *dstImgRow = imgDst;
1755
1756 for (row = 0; row < dstHeightNB; row++) {
1757 /* Average together two rows from first src image */
1758 do_row(format, srcWidthNB, srcImgARowA, srcImgARowB,
1759 srcWidthNB, tmpRowA);
1760 /* Average together two rows from second src image */
1761 do_row(format, srcWidthNB, srcImgBRowA, srcImgBRowB,
1762 srcWidthNB, tmpRowB);
1763 /* Average together the temp rows to make the final row */
1764 do_row(format, srcWidthNB, tmpRowA, tmpRowB,
1765 dstWidthNB, dstImgRow);
1766 /* advance to next rows */
1767 srcImgARowA += bytesPerSrcRow + srcRowOffset;
1768 srcImgARowB += bytesPerSrcRow + srcRowOffset;
1769 srcImgBRowA += bytesPerSrcRow + srcRowOffset;
1770 srcImgBRowB += bytesPerSrcRow + srcRowOffset;
1771 dstImgRow += bytesPerDstRow;
1772 }
1773 }
1774
1775 FREE(tmpRowA);
1776 FREE(tmpRowB);
1777
1778 /* Luckily we can leverage the make_2d_mipmap() function here! */
1779 if (border > 0) {
1780 /* do front border image */
1781 make_2d_mipmap(format, 1, srcWidth, srcHeight, srcPtr,
1782 dstWidth, dstHeight, dstPtr);
1783 /* do back border image */
1784 make_2d_mipmap(format, 1, srcWidth, srcHeight,
1785 srcPtr + bytesPerSrcImage * (srcDepth - 1),
1786 dstWidth, dstHeight,
1787 dstPtr + bytesPerDstImage * (dstDepth - 1));
1788 /* do four remaining border edges that span the image slices */
1789 if (srcDepth == dstDepth) {
1790 /* just copy border pixels from src to dst */
1791 for (img = 0; img < dstDepthNB; img++) {
1792 const GLubyte *src;
1793 GLubyte *dst;
1794
1795 /* do border along [img][row=0][col=0] */
1796 src = srcPtr + (img + 1) * bytesPerSrcImage;
1797 dst = dstPtr + (img + 1) * bytesPerDstImage;
1798 MEMCPY(dst, src, bpt);
1799
1800 /* do border along [img][row=dstHeight-1][col=0] */
1801 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
1802 + (srcHeight - 1) * bytesPerSrcRow;
1803 dst = dstPtr + (img + 1) * bytesPerDstImage
1804 + (dstHeight - 1) * bytesPerDstRow;
1805 MEMCPY(dst, src, bpt);
1806
1807 /* do border along [img][row=0][col=dstWidth-1] */
1808 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
1809 + (srcWidth - 1) * bpt;
1810 dst = dstPtr + (img + 1) * bytesPerDstImage
1811 + (dstWidth - 1) * bpt;
1812 MEMCPY(dst, src, bpt);
1813
1814 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
1815 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
1816 + (bytesPerSrcImage - bpt);
1817 dst = dstPtr + (img + 1) * bytesPerDstImage
1818 + (bytesPerDstImage - bpt);
1819 MEMCPY(dst, src, bpt);
1820 }
1821 }
1822 else {
1823 /* average border pixels from adjacent src image pairs */
1824 ASSERT(srcDepthNB == 2 * dstDepthNB);
1825 for (img = 0; img < dstDepthNB; img++) {
1826 const GLubyte *src;
1827 GLubyte *dst;
1828
1829 /* do border along [img][row=0][col=0] */
1830 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage;
1831 dst = dstPtr + (img + 1) * bytesPerDstImage;
1832 do_row(format, 1, src, src + srcImageOffset, 1, dst);
1833
1834 /* do border along [img][row=dstHeight-1][col=0] */
1835 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
1836 + (srcHeight - 1) * bytesPerSrcRow;
1837 dst = dstPtr + (img + 1) * bytesPerDstImage
1838 + (dstHeight - 1) * bytesPerDstRow;
1839 do_row(format, 1, src, src + srcImageOffset, 1, dst);
1840
1841 /* do border along [img][row=0][col=dstWidth-1] */
1842 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
1843 + (srcWidth - 1) * bpt;
1844 dst = dstPtr + (img + 1) * bytesPerDstImage
1845 + (dstWidth - 1) * bpt;
1846 do_row(format, 1, src, src + srcImageOffset, 1, dst);
1847
1848 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
1849 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
1850 + (bytesPerSrcImage - bpt);
1851 dst = dstPtr + (img + 1) * bytesPerDstImage
1852 + (bytesPerDstImage - bpt);
1853 do_row(format, 1, src, src + srcImageOffset, 1, dst);
1854 }
1855 }
1856 }
1857 }
1858
1859
1860 /*
1861 * For GL_SGIX_generate_mipmap:
1862 * Generate a complete set of mipmaps from texObj's base-level image.
1863 * Stop at texObj's MaxLevel or when we get to the 1x1 texture.
1864 */
1865 void
1866 _mesa_generate_mipmap(GLcontext *ctx, GLenum target,
1867 const struct gl_texture_unit *texUnit,
1868 struct gl_texture_object *texObj)
1869 {
1870 const struct gl_texture_image *srcImage;
1871 const struct gl_texture_format *convertFormat;
1872 const GLubyte *srcData = NULL;
1873 GLubyte *dstData = NULL;
1874 GLint level, maxLevels;
1875
1876 ASSERT(texObj);
1877 srcImage = texObj->Image[0][texObj->BaseLevel];
1878 ASSERT(srcImage);
1879
1880 maxLevels = _mesa_max_texture_levels(ctx, texObj->Target);
1881 ASSERT(maxLevels > 0); /* bad target */
1882
1883 /* Find convertFormat - the format that do_row() will process */
1884 if (srcImage->IsCompressed) {
1885 /* setup for compressed textures */
1886 GLuint row;
1887 GLint components, size;
1888 GLchan *dst;
1889
1890 assert(texObj->Target == GL_TEXTURE_2D);
1891
1892 if (srcImage->Format == GL_RGB) {
1893 convertFormat = &_mesa_texformat_rgb;
1894 components = 3;
1895 }
1896 else if (srcImage->Format == GL_RGBA) {
1897 convertFormat = &_mesa_texformat_rgba;
1898 components = 4;
1899 }
1900 else {
1901 _mesa_problem(ctx, "bad srcImage->Format in _mesa_generate_mipmaps");
1902 return;
1903 }
1904
1905 /* allocate storage for uncompressed GL_RGB or GL_RGBA images */
1906 size = _mesa_bytes_per_pixel(srcImage->Format, CHAN_TYPE)
1907 * srcImage->Width * srcImage->Height * srcImage->Depth + 20;
1908 /* 20 extra bytes, just be safe when calling last FetchTexel */
1909 srcData = (GLubyte *) MALLOC(size);
1910 if (!srcData) {
1911 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
1912 return;
1913 }
1914 dstData = (GLubyte *) MALLOC(size / 2); /* 1/4 would probably be OK */
1915 if (!dstData) {
1916 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generate mipmaps");
1917 FREE((void *) srcData);
1918 return;
1919 }
1920
1921 /* decompress base image here */
1922 dst = (GLchan *) srcData;
1923 for (row = 0; row < srcImage->Height; row++) {
1924 GLuint col;
1925 for (col = 0; col < srcImage->Width; col++) {
1926 srcImage->FetchTexelc(srcImage, col, row, 0, dst);
1927 dst += components;
1928 }
1929 }
1930 }
1931 else {
1932 /* uncompressed */
1933 convertFormat = srcImage->TexFormat;
1934 }
1935
1936 for (level = texObj->BaseLevel; level < texObj->MaxLevel
1937 && level < maxLevels - 1; level++) {
1938 /* generate image[level+1] from image[level] */
1939 const struct gl_texture_image *srcImage;
1940 struct gl_texture_image *dstImage;
1941 GLint srcWidth, srcHeight, srcDepth;
1942 GLint dstWidth, dstHeight, dstDepth;
1943 GLint border, bytesPerTexel;
1944
1945 /* get src image parameters */
1946 srcImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1947 ASSERT(srcImage);
1948 srcWidth = srcImage->Width;
1949 srcHeight = srcImage->Height;
1950 srcDepth = srcImage->Depth;
1951 border = srcImage->Border;
1952
1953 /* compute next (level+1) image size */
1954 if (srcWidth - 2 * border > 1) {
1955 dstWidth = (srcWidth - 2 * border) / 2 + 2 * border;
1956 }
1957 else {
1958 dstWidth = srcWidth; /* can't go smaller */
1959 }
1960 if (srcHeight - 2 * border > 1) {
1961 dstHeight = (srcHeight - 2 * border) / 2 + 2 * border;
1962 }
1963 else {
1964 dstHeight = srcHeight; /* can't go smaller */
1965 }
1966 if (srcDepth - 2 * border > 1) {
1967 dstDepth = (srcDepth - 2 * border) / 2 + 2 * border;
1968 }
1969 else {
1970 dstDepth = srcDepth; /* can't go smaller */
1971 }
1972
1973 if (dstWidth == srcWidth &&
1974 dstHeight == srcHeight &&
1975 dstDepth == srcDepth) {
1976 /* all done */
1977 if (srcImage->IsCompressed) {
1978 FREE((void *) srcData);
1979 FREE(dstData);
1980 }
1981 return;
1982 }
1983
1984 /* get dest gl_texture_image */
1985 dstImage = _mesa_get_tex_image(ctx, texUnit, target, level + 1);
1986 if (!dstImage) {
1987 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
1988 return;
1989 }
1990
1991 /* Free old image data */
1992 if (dstImage->Data)
1993 MESA_PBUFFER_FREE(dstImage->Data);
1994
1995 /* initialize new image */
1996 _mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight,
1997 dstDepth, border, srcImage->IntFormat);
1998 dstImage->DriverData = NULL;
1999 dstImage->TexFormat = srcImage->TexFormat;
2000 dstImage->FetchTexelc = srcImage->FetchTexelc;
2001 dstImage->FetchTexelf = srcImage->FetchTexelf;
2002 ASSERT(dstImage->TexFormat);
2003 ASSERT(dstImage->FetchTexelc);
2004 ASSERT(dstImage->FetchTexelf);
2005
2006 /* Alloc new teximage data buffer.
2007 * Setup src and dest data pointers.
2008 */
2009 if (dstImage->IsCompressed) {
2010 ASSERT(dstImage->CompressedSize > 0); /* set by init_teximage_fields*/
2011 dstImage->Data = MESA_PBUFFER_ALLOC(dstImage->CompressedSize);
2012 if (!dstImage->Data) {
2013 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
2014 return;
2015 }
2016 /* srcData and dstData are already set */
2017 ASSERT(srcData);
2018 ASSERT(dstData);
2019 }
2020 else {
2021 bytesPerTexel = srcImage->TexFormat->TexelBytes;
2022 ASSERT(dstWidth * dstHeight * dstDepth * bytesPerTexel > 0);
2023 dstImage->Data = MESA_PBUFFER_ALLOC(dstWidth * dstHeight * dstDepth
2024 * bytesPerTexel);
2025 if (!dstImage->Data) {
2026 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
2027 return;
2028 }
2029 srcData = (const GLubyte *) srcImage->Data;
2030 dstData = (GLubyte *) dstImage->Data;
2031 }
2032
2033 /*
2034 * We use simple 2x2 averaging to compute the next mipmap level.
2035 */
2036 switch (target) {
2037 case GL_TEXTURE_1D:
2038 make_1d_mipmap(convertFormat, border,
2039 srcWidth, srcData,
2040 dstWidth, dstData);
2041 break;
2042 case GL_TEXTURE_2D:
2043 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
2044 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
2045 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
2046 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
2047 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
2048 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
2049 make_2d_mipmap(convertFormat, border,
2050 srcWidth, srcHeight, srcData,
2051 dstWidth, dstHeight, dstData);
2052 break;
2053 case GL_TEXTURE_3D:
2054 make_3d_mipmap(convertFormat, border,
2055 srcWidth, srcHeight, srcDepth, srcData,
2056 dstWidth, dstHeight, dstDepth, dstData);
2057 break;
2058 case GL_TEXTURE_RECTANGLE_NV:
2059 /* no mipmaps, do nothing */
2060 break;
2061 default:
2062 _mesa_problem(ctx, "bad dimensions in _mesa_generate_mipmaps");
2063 return;
2064 }
2065
2066 if (dstImage->IsCompressed) {
2067 GLubyte *temp;
2068 /* compress image from dstData into dstImage->Data */
2069 const GLenum srcFormat = convertFormat->BaseFormat;
2070 GLint dstRowStride = _mesa_compressed_row_stride(srcImage->IntFormat,
2071 dstWidth);
2072 ASSERT(srcFormat == GL_RGB || srcFormat == GL_RGBA);
2073 _mesa_compress_teximage(ctx,
2074 dstWidth, dstHeight, /* size */
2075 srcFormat, /* source format */
2076 (const GLchan *) dstData, /* source buffer */
2077 dstWidth, /* source row stride */
2078 dstImage->TexFormat, /* dest format */
2079 (GLubyte*) dstImage->Data, /* dest buffer */
2080 dstRowStride ); /* dest row stride */
2081
2082 /* swap src and dest pointers */
2083 temp = (GLubyte *) srcData;
2084 srcData = dstData;
2085 dstData = temp;
2086 }
2087
2088 } /* loop over mipmap levels */
2089 }