assorted changes for supporting GLfloat color channels (not done)
[mesa.git] / src / mesa / main / texstore.c
1 /* $Id: texstore.c,v 1.31 2001/07/13 20:07:37 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27 /*
28 * Authors:
29 * Brian Paul
30 */
31
32 #include "colormac.h"
33 #include "context.h"
34 #include "convolve.h"
35 #include "image.h"
36 #include "macros.h"
37 #include "mem.h"
38 #include "texformat.h"
39 #include "teximage.h"
40 #include "texstore.h"
41 #include "texutil.h"
42
43
44 /*
45 * Given an internal texture format enum or 1, 2, 3, 4 return the
46 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
47 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. Return the
48 * number of components for the format. Return -1 if invalid enum.
49 *
50 * GH: Do we really need this? We have the number of bytes per texel
51 * in the texture format structures, so why don't we just use that?
52 */
53 static GLint
54 components_in_intformat( GLint format )
55 {
56 switch (format) {
57 case GL_ALPHA:
58 case GL_ALPHA4:
59 case GL_ALPHA8:
60 case GL_ALPHA12:
61 case GL_ALPHA16:
62 return 1;
63 case 1:
64 case GL_LUMINANCE:
65 case GL_LUMINANCE4:
66 case GL_LUMINANCE8:
67 case GL_LUMINANCE12:
68 case GL_LUMINANCE16:
69 return 1;
70 case 2:
71 case GL_LUMINANCE_ALPHA:
72 case GL_LUMINANCE4_ALPHA4:
73 case GL_LUMINANCE6_ALPHA2:
74 case GL_LUMINANCE8_ALPHA8:
75 case GL_LUMINANCE12_ALPHA4:
76 case GL_LUMINANCE12_ALPHA12:
77 case GL_LUMINANCE16_ALPHA16:
78 return 2;
79 case GL_INTENSITY:
80 case GL_INTENSITY4:
81 case GL_INTENSITY8:
82 case GL_INTENSITY12:
83 case GL_INTENSITY16:
84 return 1;
85 case 3:
86 case GL_RGB:
87 case GL_R3_G3_B2:
88 case GL_RGB4:
89 case GL_RGB5:
90 case GL_RGB8:
91 case GL_RGB10:
92 case GL_RGB12:
93 case GL_RGB16:
94 return 3;
95 case 4:
96 case GL_RGBA:
97 case GL_RGBA2:
98 case GL_RGBA4:
99 case GL_RGB5_A1:
100 case GL_RGBA8:
101 case GL_RGB10_A2:
102 case GL_RGBA12:
103 case GL_RGBA16:
104 return 4;
105 case GL_COLOR_INDEX:
106 case GL_COLOR_INDEX1_EXT:
107 case GL_COLOR_INDEX2_EXT:
108 case GL_COLOR_INDEX4_EXT:
109 case GL_COLOR_INDEX8_EXT:
110 case GL_COLOR_INDEX12_EXT:
111 case GL_COLOR_INDEX16_EXT:
112 return 1;
113 case GL_DEPTH_COMPONENT:
114 case GL_DEPTH_COMPONENT16_SGIX:
115 case GL_DEPTH_COMPONENT24_SGIX:
116 case GL_DEPTH_COMPONENT32_SGIX:
117 return 1;
118 default:
119 return -1; /* error */
120 }
121 }
122
123
124 /*
125 * This function is used to transfer the user's image data into a texture
126 * image buffer. We handle both full texture images and subtexture images.
127 * We also take care of all image transfer operations here, including
128 * convolution, scale/bias, colortables, etc.
129 *
130 * The destination texel channel type is always GLchan.
131 *
132 * A hardware driver may use this as a helper routine to unpack and
133 * apply pixel transfer ops into a temporary image buffer. Then,
134 * convert the temporary image into the special hardware format.
135 *
136 * Input:
137 * dimensions - 1, 2, or 3
138 * texFormat - GL_LUMINANCE, GL_INTENSITY, GL_LUMINANCE_ALPHA, GL_ALPHA,
139 * GL_RGB or GL_RGBA
140 * texDestAddr - destination image address
141 * srcWidth, srcHeight, srcDepth - size (in pixels) of src and dest images
142 * dstXoffset, dstYoffset, dstZoffset - position to store the image within
143 * the destination 3D texture
144 * dstRowStride, dstImageStride - dest image strides in bytes
145 * srcFormat - source image format (GL_ALPHA, GL_RED, GL_RGB, etc)
146 * srcType - GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT_5_6_5, GL_FLOAT, etc
147 * srcPacking - describes packing of incoming image.
148 * transferOps - mask of pixel transfer operations
149 */
150 static void
151 transfer_teximage(GLcontext *ctx, GLuint dimensions,
152 GLenum texDestFormat, GLvoid *texDestAddr,
153 GLint srcWidth, GLint srcHeight, GLint srcDepth,
154 GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
155 GLint dstRowStride, GLint dstImageStride,
156 GLenum srcFormat, GLenum srcType,
157 const GLvoid *srcAddr,
158 const struct gl_pixelstore_attrib *srcPacking,
159 GLuint transferOps)
160 {
161 GLint texComponents;
162
163 ASSERT(ctx);
164 ASSERT(dimensions >= 1 && dimensions <= 3);
165 ASSERT(texDestAddr);
166 ASSERT(srcWidth >= 1);
167 ASSERT(srcHeight >= 1);
168 ASSERT(srcDepth >= 1);
169 ASSERT(dstXoffset >= 0);
170 ASSERT(dstYoffset >= 0);
171 ASSERT(dstZoffset >= 0);
172 ASSERT(dstRowStride >= 0);
173 ASSERT(dstImageStride >= 0);
174 ASSERT(srcAddr);
175 ASSERT(srcPacking);
176
177 texComponents = components_in_intformat(texDestFormat);
178
179 /* try common 2D texture cases first */
180 if (!transferOps && dimensions == 2 && srcType == CHAN_TYPE) {
181
182 if (srcFormat == texDestFormat) {
183 /* This will cover the common GL_RGB, GL_RGBA, GL_ALPHA,
184 * GL_LUMINANCE_ALPHA, etc. texture formats. Use memcpy().
185 */
186 const GLchan *src = (const GLchan *) _mesa_image_address(
187 srcPacking, srcAddr, srcWidth, srcHeight,
188 srcFormat, srcType, 0, 0, 0);
189 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
190 srcWidth, srcFormat, srcType);
191 const GLint widthInBytes = srcWidth * texComponents * sizeof(GLchan);
192 GLchan *dst = (GLchan *) texDestAddr + dstYoffset * dstRowStride
193 + dstXoffset * texComponents;
194 if (srcRowStride == widthInBytes && dstRowStride == widthInBytes) {
195 MEMCPY(dst, src, srcHeight * widthInBytes);
196 }
197 else {
198 GLint i;
199 for (i = 0; i < srcHeight; i++) {
200 MEMCPY(dst, src, widthInBytes);
201 src += srcRowStride;
202 dst += dstRowStride;
203 }
204 }
205 return; /* all done */
206 }
207 else if (srcFormat == GL_RGBA && texDestFormat == GL_RGB) {
208 /* commonly used by Quake */
209 const GLchan *src = (const GLchan *) _mesa_image_address(
210 srcPacking, srcAddr, srcWidth, srcHeight,
211 srcFormat, srcType, 0, 0, 0);
212 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
213 srcWidth, srcFormat, srcType);
214 GLchan *dst = (GLchan *) texDestAddr + dstYoffset * dstRowStride
215 + dstXoffset * texComponents;
216 GLint i, j;
217 for (i = 0; i < srcHeight; i++) {
218 const GLchan *s = src;
219 GLchan *d = dst;
220 for (j = 0; j < srcWidth; j++) {
221 *d++ = *s++; /*red*/
222 *d++ = *s++; /*green*/
223 *d++ = *s++; /*blue*/
224 s++; /*alpha*/
225 }
226 src += srcRowStride;
227 dst += dstRowStride;
228 }
229 return; /* all done */
230 }
231 }
232
233 /*
234 * General case solutions
235 */
236 if (texDestFormat == GL_COLOR_INDEX) {
237 /* color index texture */
238 const GLenum texType = CHAN_TYPE;
239 GLint img, row;
240 GLchan *dest = (GLchan *) texDestAddr + dstZoffset * dstImageStride
241 + dstYoffset * dstRowStride
242 + dstXoffset * texComponents;
243 for (img = 0; img < srcDepth; img++) {
244 GLchan *destRow = dest;
245 for (row = 0; row < srcHeight; row++) {
246 const GLvoid *src = _mesa_image_address(srcPacking,
247 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
248 _mesa_unpack_index_span(ctx, srcWidth, texType, destRow,
249 srcType, src, srcPacking, transferOps);
250 destRow += dstRowStride;
251 }
252 dest += dstImageStride;
253 }
254 }
255 else if (texDestFormat == GL_DEPTH_COMPONENT) {
256 /* Depth texture (shadow maps) */
257 GLint img, row;
258 GLubyte *dest = (GLubyte *) texDestAddr
259 + dstZoffset * dstImageStride
260 + dstYoffset * dstRowStride
261 + dstXoffset * texComponents;
262 for (img = 0; img < srcDepth; img++) {
263 GLubyte *destRow = dest;
264 for (row = 0; row < srcHeight; row++) {
265 const GLvoid *src = _mesa_image_address(srcPacking,
266 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
267 _mesa_unpack_depth_span(ctx, srcWidth, (GLfloat *) destRow,
268 srcType, src, srcPacking);
269 destRow += dstRowStride;
270 }
271 dest += dstImageStride;
272 }
273 }
274 else {
275 /* regular, color texture */
276 if ((dimensions == 1 && ctx->Pixel.Convolution1DEnabled) ||
277 (dimensions >= 2 && ctx->Pixel.Convolution2DEnabled) ||
278 (dimensions >= 2 && ctx->Pixel.Separable2DEnabled)) {
279 /*
280 * Fill texture image with convolution
281 */
282 GLint img, row;
283 GLint convWidth = srcWidth, convHeight = srcHeight;
284 GLfloat *tmpImage, *convImage;
285 tmpImage = (GLfloat *) MALLOC(srcWidth * srcHeight * 4 * sizeof(GLfloat));
286 if (!tmpImage) {
287 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
288 return;
289 }
290 convImage = (GLfloat *) MALLOC(srcWidth * srcHeight * 4 * sizeof(GLfloat));
291 if (!convImage) {
292 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
293 FREE(tmpImage);
294 return;
295 }
296
297 for (img = 0; img < srcDepth; img++) {
298 const GLfloat *srcf;
299 GLfloat *dstf = tmpImage;
300 GLchan *dest;
301
302 /* unpack and do transfer ops up to convolution */
303 for (row = 0; row < srcHeight; row++) {
304 const GLvoid *src = _mesa_image_address(srcPacking,
305 srcAddr, srcWidth, srcHeight,
306 srcFormat, srcType, img, row, 0);
307 _mesa_unpack_float_color_span(ctx, srcWidth, GL_RGBA, dstf,
308 srcFormat, srcType, src, srcPacking,
309 transferOps & IMAGE_PRE_CONVOLUTION_BITS,
310 GL_TRUE);
311 dstf += srcWidth * 4;
312 }
313
314 /* convolve */
315 if (dimensions == 1) {
316 ASSERT(ctx->Pixel.Convolution1DEnabled);
317 _mesa_convolve_1d_image(ctx, &convWidth, tmpImage, convImage);
318 }
319 else {
320 if (ctx->Pixel.Convolution2DEnabled) {
321 _mesa_convolve_2d_image(ctx, &convWidth, &convHeight,
322 tmpImage, convImage);
323 }
324 else {
325 ASSERT(ctx->Pixel.Separable2DEnabled);
326 _mesa_convolve_sep_image(ctx, &convWidth, &convHeight,
327 tmpImage, convImage);
328 }
329 }
330
331 /* packing and transfer ops after convolution */
332 srcf = convImage;
333 dest = (GLchan *) texDestAddr + (dstZoffset + img) * dstImageStride
334 + dstYoffset * dstRowStride;
335 for (row = 0; row < convHeight; row++) {
336 _mesa_pack_float_rgba_span(ctx, convWidth,
337 (const GLfloat (*)[4]) srcf,
338 texDestFormat, CHAN_TYPE,
339 dest, &_mesa_native_packing,
340 transferOps
341 & IMAGE_POST_CONVOLUTION_BITS);
342 srcf += convWidth * 4;
343 dest += dstRowStride;
344 }
345 }
346
347 FREE(convImage);
348 FREE(tmpImage);
349 }
350 else {
351 /*
352 * no convolution
353 */
354 GLint img, row;
355 GLchan *dest = (GLchan *) texDestAddr + dstZoffset * dstImageStride
356 + dstYoffset * dstRowStride
357 + dstXoffset * texComponents;
358 for (img = 0; img < srcDepth; img++) {
359 GLchan *destRow = dest;
360 for (row = 0; row < srcHeight; row++) {
361 const GLvoid *srcRow = _mesa_image_address(srcPacking,
362 srcAddr, srcWidth, srcHeight,
363 srcFormat, srcType, img, row, 0);
364 _mesa_unpack_chan_color_span(ctx, srcWidth, texDestFormat,
365 destRow, srcFormat, srcType, srcRow,
366 srcPacking, transferOps);
367 destRow += dstRowStride;
368 }
369 dest += dstImageStride;
370 }
371 }
372 }
373 }
374
375
376
377 /*
378 * Transfer a texture image from user space to <destAddr> applying all
379 * needed image transfer operations and storing the result in the format
380 * specified by <dstFormat>. <dstFormat> may be any format from texformat.h.
381 * Input:
382 * dimensions - 1, 2 or 3
383 * baseInternalFormat - base format of the internal texture format
384 * specified by the user. This is very important, see below.
385 * dstFormat - destination image format
386 * dstAddr - destination address
387 * srcWidth, srcHeight, srcDepth - size of source iamge
388 * dstX/Y/Zoffset - as specified by glTexSubImage
389 * dstRowStride - stride between dest rows in bytes
390 * dstImagetride - stride between dest images in bytes
391 * srcFormat, srcType - incoming image format and datatype
392 * srcAddr - source image address
393 * srcPacking - packing params of source image
394 *
395 * XXX this function is a bit more complicated than it should be. If
396 * _mesa_convert_texsubimage[123]d could handle any dest/source formats
397 * or if transfer_teximage() could store in any MESA_FORMAT_* format, we
398 * could simplify things here.
399 */
400 void
401 _mesa_transfer_teximage(GLcontext *ctx, GLuint dimensions,
402 GLenum baseInternalFormat,
403 const struct gl_texture_format *dstFormat,
404 GLvoid *dstAddr,
405 GLint srcWidth, GLint srcHeight, GLint srcDepth,
406 GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
407 GLint dstRowStride, GLint dstImageStride,
408 GLenum srcFormat, GLenum srcType,
409 const GLvoid *srcAddr,
410 const struct gl_pixelstore_attrib *srcPacking)
411 {
412 const GLint dstRowStridePixels = dstRowStride / dstFormat->TexelBytes;
413 const GLint dstImageStridePixels = dstImageStride / dstFormat->TexelBytes;
414 GLboolean makeTemp;
415 GLuint transferOps = ctx->_ImageTransferState;
416 GLboolean freeSourceData = GL_FALSE;
417 GLint postConvWidth = srcWidth, postConvHeight = srcHeight;
418
419 assert(baseInternalFormat > 0);
420
421 if (transferOps & IMAGE_CONVOLUTION_BIT) {
422 _mesa_adjust_image_for_convolution(ctx, dimensions, &postConvWidth,
423 &postConvHeight);
424 }
425
426 /*
427 * Consider this scenario: The user's source image is GL_RGB and the
428 * requested internal format is GL_LUMINANCE. Now suppose the device
429 * driver doesn't support GL_LUMINANCE and instead uses RGB16 as the
430 * texture format. In that case we still need to do an intermediate
431 * conversion to luminance format so that the incoming red channel gets
432 * replicated into the dest red, green and blue channels. The following
433 * code takes care of that.
434 */
435 if (dstFormat->BaseFormat != baseInternalFormat) {
436 /* Allocate storage for temporary image in the baseInternalFormat */
437 const GLint texelSize = _mesa_components_in_format(baseInternalFormat)
438 * sizeof(GLchan);
439 const GLint bytes = texelSize * postConvWidth * postConvHeight *srcDepth;
440 const GLint tmpRowStride = texelSize * postConvWidth;
441 const GLint tmpImgStride = texelSize * postConvWidth * postConvHeight;
442 GLvoid *tmpImage = MALLOC(bytes);
443 if (!tmpImage)
444 return;
445 transfer_teximage(ctx, dimensions, baseInternalFormat, tmpImage,
446 srcWidth, srcHeight, srcDepth,
447 0, 0, 0, /* x/y/zoffset */
448 tmpRowStride, tmpImgStride,
449 srcFormat, srcType, srcAddr, srcPacking, transferOps);
450
451 /* this is our new source image */
452 srcWidth = postConvWidth;
453 srcHeight = postConvHeight;
454 srcFormat = baseInternalFormat;
455 srcType = CHAN_TYPE;
456 srcAddr = tmpImage;
457 srcPacking = &_mesa_native_packing;
458 freeSourceData = GL_TRUE;
459 transferOps = 0; /* image transfer ops were completed */
460 }
461
462 /* Let the optimized tex conversion functions take a crack at the
463 * image conversion if the dest format is a h/w format.
464 */
465 if (_mesa_is_hardware_tex_format(dstFormat)) {
466 if (transferOps) {
467 makeTemp = GL_TRUE;
468 }
469 else {
470 if (dimensions == 1) {
471 makeTemp = !_mesa_convert_texsubimage1d(dstFormat->MesaFormat,
472 dstXoffset,
473 srcWidth,
474 srcFormat, srcType,
475 srcPacking, srcAddr,
476 dstAddr);
477 }
478 else if (dimensions == 2) {
479 makeTemp = !_mesa_convert_texsubimage2d(dstFormat->MesaFormat,
480 dstXoffset, dstYoffset,
481 srcWidth, srcHeight,
482 dstRowStridePixels,
483 srcFormat, srcType,
484 srcPacking, srcAddr,
485 dstAddr);
486 }
487 else {
488 assert(dimensions == 3);
489 makeTemp = !_mesa_convert_texsubimage3d(dstFormat->MesaFormat,
490 dstXoffset, dstYoffset, dstZoffset,
491 srcWidth, srcHeight, srcDepth,
492 dstRowStridePixels, dstImageStridePixels,
493 srcFormat, srcType,
494 srcPacking, srcAddr, dstAddr);
495 }
496 if (!makeTemp) {
497 /* all done! */
498 if (freeSourceData)
499 FREE((void *) srcAddr);
500 return;
501 }
502 }
503 }
504 else {
505 /* software texture format */
506 makeTemp = GL_FALSE;
507 }
508
509 if (makeTemp) {
510 GLint postConvWidth = srcWidth, postConvHeight = srcHeight;
511 GLenum tmpFormat;
512 GLuint tmpComps, tmpTexelSize;
513 GLint tmpRowStride, tmpImageStride;
514 GLubyte *tmpImage;
515
516 if (transferOps & IMAGE_CONVOLUTION_BIT) {
517 _mesa_adjust_image_for_convolution(ctx, dimensions, &postConvWidth,
518 &postConvHeight);
519 }
520
521 tmpFormat = dstFormat->BaseFormat;
522 tmpComps = _mesa_components_in_format(tmpFormat);
523 tmpTexelSize = tmpComps * sizeof(GLchan);
524 tmpRowStride = postConvWidth * tmpTexelSize;
525 tmpImageStride = postConvWidth * postConvHeight * tmpTexelSize;
526 tmpImage = (GLubyte *) MALLOC(postConvWidth * postConvHeight *
527 srcDepth * tmpTexelSize);
528 if (!tmpImage) {
529 if (freeSourceData)
530 FREE((void *) srcAddr);
531 return;
532 }
533
534 transfer_teximage(ctx, dimensions, tmpFormat, tmpImage,
535 srcWidth, srcHeight, srcDepth,
536 0, 0, 0, /* x/y/zoffset */
537 tmpRowStride, tmpImageStride,
538 srcFormat, srcType, srcAddr, srcPacking, transferOps);
539
540 if (freeSourceData)
541 FREE((void *) srcAddr);
542
543 /* the temp image is our new source image */
544 srcWidth = postConvWidth;
545 srcHeight = postConvHeight;
546 srcFormat = tmpFormat;
547 srcType = CHAN_TYPE;
548 srcAddr = tmpImage;
549 srcPacking = &_mesa_native_packing;
550 freeSourceData = GL_TRUE;
551 }
552
553 if (_mesa_is_hardware_tex_format(dstFormat)) {
554 assert(makeTemp);
555 if (dimensions == 1) {
556 GLboolean b;
557 b = _mesa_convert_texsubimage1d(dstFormat->MesaFormat,
558 dstXoffset,
559 srcWidth,
560 srcFormat, srcType,
561 srcPacking, srcAddr,
562 dstAddr);
563 assert(b);
564 }
565 else if (dimensions == 2) {
566 GLboolean b;
567 b = _mesa_convert_texsubimage2d(dstFormat->MesaFormat,
568 dstXoffset, dstYoffset,
569 srcWidth, srcHeight,
570 dstRowStridePixels,
571 srcFormat, srcType,
572 srcPacking, srcAddr,
573 dstAddr);
574 assert(b);
575 }
576 else {
577 GLboolean b;
578 b = _mesa_convert_texsubimage3d(dstFormat->MesaFormat,
579 dstXoffset, dstYoffset, dstZoffset,
580 srcWidth, srcHeight, srcDepth,
581 dstRowStridePixels, dstImageStridePixels,
582 srcFormat, srcType,
583 srcPacking, srcAddr, dstAddr);
584 assert(b);
585 }
586 }
587 else {
588 /* software format */
589 assert(!makeTemp);
590 transfer_teximage(ctx, dimensions, dstFormat->BaseFormat, dstAddr,
591 srcWidth, srcHeight, srcDepth,
592 dstXoffset, dstYoffset, dstZoffset,
593 dstRowStride, dstImageStride,
594 srcFormat, srcType, srcAddr, srcPacking, transferOps);
595 }
596
597 if (freeSourceData)
598 FREE((void *) srcAddr); /* the temp image */
599 }
600
601
602 /*
603 * This is the software fallback for Driver.TexImage1D().
604 * The texture image type will be GLchan.
605 * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY,
606 * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA.
607 *
608 */
609 void
610 _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level,
611 GLint internalFormat,
612 GLint width, GLint border,
613 GLenum format, GLenum type, const GLvoid *pixels,
614 const struct gl_pixelstore_attrib *packing,
615 struct gl_texture_object *texObj,
616 struct gl_texture_image *texImage)
617 {
618 GLint postConvWidth = width;
619 GLint texelBytes, sizeInBytes;
620
621 if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
622 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
623 }
624
625 /* choose the texture format */
626 assert(ctx->Driver.ChooseTextureFormat);
627 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
628 internalFormat, format, type);
629 assert(texImage->TexFormat);
630 texImage->FetchTexel = texImage->TexFormat->FetchTexel1D;
631
632 texelBytes = texImage->TexFormat->TexelBytes;
633
634 /* Compute image size, in bytes */
635 if (texImage->IsCompressed) {
636 assert(ctx->Driver.CompressedTextureSize);
637 sizeInBytes = ctx->Driver.CompressedTextureSize(ctx, texImage);
638 assert(sizeInBytes > 0);
639 texImage->CompressedSize = sizeInBytes;
640 }
641 else {
642 sizeInBytes = postConvWidth * texelBytes;
643 }
644
645 /* allocate memory */
646 texImage->Data = MALLOC(sizeInBytes);
647 if (!texImage->Data) {
648 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
649 return;
650 }
651
652 /* unpack image, apply transfer ops and store in texImage->Data */
653 _mesa_transfer_teximage(ctx, 1, _mesa_base_tex_format(ctx, internalFormat),
654 texImage->TexFormat, texImage->Data,
655 width, 1, 1, 0, 0, 0,
656 0, /* dstRowStride */
657 0, /* dstImageStride */
658 format, type, pixels, packing);
659
660 /* GL_SGIS_generate_mipmap */
661 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
662 _mesa_generate_mipmap(ctx, &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
663 texObj);
664 }
665 }
666
667
668 /*
669 * This is the software fallback for Driver.TexImage2D().
670 * The texture image type will be GLchan.
671 * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY,
672 * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA.
673 *
674 * NOTE: if real texture compression is supported, this whole function
675 * will need to be overridden.
676 */
677 void
678 _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level,
679 GLint internalFormat,
680 GLint width, GLint height, GLint border,
681 GLenum format, GLenum type, const void *pixels,
682 const struct gl_pixelstore_attrib *packing,
683 struct gl_texture_object *texObj,
684 struct gl_texture_image *texImage)
685 {
686 GLint postConvWidth = width, postConvHeight = height;
687 GLint texelBytes, sizeInBytes;
688
689 if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
690 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
691 &postConvHeight);
692 }
693
694 /* choose the texture format */
695 assert(ctx->Driver.ChooseTextureFormat);
696 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
697 internalFormat, format, type);
698 assert(texImage->TexFormat);
699 texImage->FetchTexel = texImage->TexFormat->FetchTexel2D;
700
701 texelBytes = texImage->TexFormat->TexelBytes;
702
703 /* Compute image size, in bytes */
704 if (texImage->IsCompressed) {
705 assert(ctx->Driver.CompressedTextureSize);
706 sizeInBytes = ctx->Driver.CompressedTextureSize(ctx, texImage);
707 assert(sizeInBytes > 0);
708 texImage->CompressedSize = sizeInBytes;
709 }
710 else {
711 sizeInBytes = postConvWidth * postConvHeight * texelBytes;
712 }
713
714 /* allocate memory */
715 texImage->Data = MALLOC(sizeInBytes);
716 if (!texImage->Data) {
717 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
718 return;
719 }
720
721 /* unpack image, apply transfer ops and store in texImage->Data */
722 _mesa_transfer_teximage(ctx, 2, _mesa_base_tex_format(ctx, internalFormat),
723 texImage->TexFormat, texImage->Data,
724 width, height, 1, 0, 0, 0,
725 texImage->Width * texelBytes,
726 0, /* dstImageStride */
727 format, type, pixels, packing);
728
729 /* GL_SGIS_generate_mipmap */
730 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
731 _mesa_generate_mipmap(ctx, &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
732 texObj);
733 }
734 }
735
736
737
738 /*
739 * This is the software fallback for Driver.TexImage3D().
740 * The texture image type will be GLchan.
741 * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY,
742 * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA.
743 *
744 */
745 void
746 _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level,
747 GLint internalFormat,
748 GLint width, GLint height, GLint depth, GLint border,
749 GLenum format, GLenum type, const void *pixels,
750 const struct gl_pixelstore_attrib *packing,
751 struct gl_texture_object *texObj,
752 struct gl_texture_image *texImage)
753 {
754 GLint texelBytes, sizeInBytes;
755
756 /* choose the texture format */
757 assert(ctx->Driver.ChooseTextureFormat);
758 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
759 internalFormat, format, type);
760 assert(texImage->TexFormat);
761 texImage->FetchTexel = texImage->TexFormat->FetchTexel3D;
762
763 texelBytes = texImage->TexFormat->TexelBytes;
764
765 /* Compute image size, in bytes */
766 if (texImage->IsCompressed) {
767 assert(ctx->Driver.CompressedTextureSize);
768 sizeInBytes = ctx->Driver.CompressedTextureSize(ctx, texImage);
769 assert(sizeInBytes > 0);
770 texImage->CompressedSize = sizeInBytes;
771 }
772 else {
773 sizeInBytes = width * height * depth * texelBytes;
774 }
775
776 /* allocate memory */
777 texImage->Data = MALLOC(sizeInBytes);
778 if (!texImage->Data) {
779 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
780 return;
781 }
782
783 /* unpack image, apply transfer ops and store in texImage->Data */
784 _mesa_transfer_teximage(ctx, 3, _mesa_base_tex_format(ctx, internalFormat),
785 texImage->TexFormat, texImage->Data,
786 width, height, depth, 0, 0, 0,
787 texImage->Width * texelBytes,
788 texImage->Width * texImage->Height * texelBytes,
789 format, type, pixels, packing);
790
791 /* GL_SGIS_generate_mipmap */
792 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
793 _mesa_generate_mipmap(ctx, &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
794 texObj);
795 }
796 }
797
798
799
800
801 /*
802 * This is the software fallback for Driver.TexSubImage1D().
803 */
804 void
805 _mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level,
806 GLint xoffset, GLint width,
807 GLenum format, GLenum type, const void *pixels,
808 const struct gl_pixelstore_attrib *packing,
809 struct gl_texture_object *texObj,
810 struct gl_texture_image *texImage)
811 {
812 _mesa_transfer_teximage(ctx, 1,
813 _mesa_base_tex_format(ctx, texImage->IntFormat),
814 texImage->TexFormat, texImage->Data,
815 width, 1, 1, /* src size */
816 xoffset, 0, 0, /* dest offsets */
817 0, /* dstRowStride */
818 0, /* dstImageStride */
819 format, type, pixels, packing);
820
821 /* GL_SGIS_generate_mipmap */
822 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
823 _mesa_generate_mipmap(ctx, &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
824 texObj);
825 }
826 }
827
828
829 /*
830 * This is the software fallback for Driver.TexSubImage2D().
831 */
832 void
833 _mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level,
834 GLint xoffset, GLint yoffset,
835 GLint width, GLint height,
836 GLenum format, GLenum type, const void *pixels,
837 const struct gl_pixelstore_attrib *packing,
838 struct gl_texture_object *texObj,
839 struct gl_texture_image *texImage)
840 {
841 _mesa_transfer_teximage(ctx, 2,
842 _mesa_base_tex_format(ctx, texImage->IntFormat),
843 texImage->TexFormat, texImage->Data,
844 width, height, 1, /* src size */
845 xoffset, yoffset, 0, /* dest offsets */
846 texImage->Width * texImage->TexFormat->TexelBytes,
847 0, /* dstImageStride */
848 format, type, pixels, packing);
849
850 /* GL_SGIS_generate_mipmap */
851 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
852 _mesa_generate_mipmap(ctx, &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
853 texObj);
854 }
855 }
856
857
858 /*
859 * This is the software fallback for Driver.TexSubImage3D().
860 */
861 void
862 _mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level,
863 GLint xoffset, GLint yoffset, GLint zoffset,
864 GLint width, GLint height, GLint depth,
865 GLenum format, GLenum type, const void *pixels,
866 const struct gl_pixelstore_attrib *packing,
867 struct gl_texture_object *texObj,
868 struct gl_texture_image *texImage)
869 {
870 const GLint texelBytes = texImage->TexFormat->TexelBytes;
871 _mesa_transfer_teximage(ctx, 3,
872 _mesa_base_tex_format(ctx, texImage->IntFormat),
873 texImage->TexFormat, texImage->Data,
874 width, height, depth, /* src size */
875 xoffset, yoffset, xoffset, /* dest offsets */
876 texImage->Width * texelBytes,
877 texImage->Width * texImage->Height * texelBytes,
878 format, type, pixels, packing);
879 /* GL_SGIS_generate_mipmap */
880 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
881 _mesa_generate_mipmap(ctx, &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
882 texObj);
883 }
884 }
885
886
887
888
889 /*
890 * Fallback for Driver.CompressedTexImage1D()
891 */
892 void
893 _mesa_store_compressed_teximage1d(GLcontext *ctx, GLenum target, GLint level,
894 GLint internalFormat,
895 GLint width, GLint border,
896 GLsizei imageSize, const GLvoid *data,
897 struct gl_texture_object *texObj,
898 struct gl_texture_image *texImage)
899 {
900 /* Nothing here.
901 * The device driver has to do it all.
902 */
903 }
904
905
906
907 /*
908 * Fallback for Driver.CompressedTexImage2D()
909 */
910 void
911 _mesa_store_compressed_teximage2d(GLcontext *ctx, GLenum target, GLint level,
912 GLint internalFormat,
913 GLint width, GLint height, GLint border,
914 GLsizei imageSize, const GLvoid *data,
915 struct gl_texture_object *texObj,
916 struct gl_texture_image *texImage)
917 {
918 /* Nothing here.
919 * The device driver has to do it all.
920 */
921 }
922
923
924
925 /*
926 * Fallback for Driver.CompressedTexImage3D()
927 */
928 void
929 _mesa_store_compressed_teximage3d(GLcontext *ctx, GLenum target, GLint level,
930 GLint internalFormat,
931 GLint width, GLint height, GLint depth,
932 GLint border,
933 GLsizei imageSize, const GLvoid *data,
934 struct gl_texture_object *texObj,
935 struct gl_texture_image *texImage)
936 {
937 /* Nothing here.
938 * The device driver has to do it all.
939 */
940 }
941
942
943
944 /*
945 * Fallback for Driver.GetCompressedTexImage3D()
946 * This will probably work find for hardware drivers. That is, hardware
947 * drivers won't have to override this function, unless the compressed
948 * texture must first be fetched from the TRAM.
949 */
950 void
951 _mesa_get_compressed_teximage(GLcontext *ctx, GLenum target,
952 GLint level, void *image,
953 const struct gl_texture_object *texObj,
954 struct gl_texture_image *texImage)
955 {
956 assert(texImage->IsCompressed);
957 assert(texImage->CompressedSize > 0);
958 MEMCPY(image, texImage->Data, texImage->CompressedSize);
959 }
960
961
962
963 /*
964 * This is the fallback for Driver.TestProxyTexImage().
965 */
966 GLboolean
967 _mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
968 GLint internalFormat, GLenum format, GLenum type,
969 GLint width, GLint height, GLint depth, GLint border)
970 {
971 struct gl_texture_unit *texUnit;
972 struct gl_texture_object *texObj;
973 struct gl_texture_image *texImage;
974
975 (void) format;
976 (void) type;
977
978 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
979 texObj = _mesa_select_tex_object(ctx, texUnit, target);
980 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
981
982 /* We always pass.
983 * The core Mesa code will have already tested the image size, etc.
984 * If a driver has more stringent texture limits to enforce it will
985 * have to override this function.
986 */
987 /* choose the texture format */
988 assert(ctx->Driver.ChooseTextureFormat);
989 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
990 internalFormat, format, type);
991 assert(texImage->TexFormat);
992
993 return GL_TRUE;
994 }
995
996
997
998 /*
999 * Average together two rows of a source image to produce a single new
1000 * row in the dest image. It's legal for the two source rows to point
1001 * to the same data. The source width must be equal to either the
1002 * dest width or two times the dest width.
1003 */
1004 static void
1005 do_row(const struct gl_texture_format *format, GLint srcWidth,
1006 const GLvoid *srcRowA, const GLvoid *srcRowB,
1007 GLint dstWidth, GLvoid *dstRow)
1008 {
1009 const GLuint k0 = (srcWidth == dstWidth) ? 0 : 1;
1010 const GLuint colStride = (srcWidth == dstWidth) ? 1 : 2;
1011
1012 assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
1013
1014 switch (format->MesaFormat) {
1015 case MESA_FORMAT_RGBA:
1016 {
1017 GLuint i, j, k;
1018 const GLchan (*rowA)[4] = (const GLchan (*)[4]) srcRowA;
1019 const GLchan (*rowB)[4] = (const GLchan (*)[4]) srcRowB;
1020 GLchan (*dst)[4] = (GLchan (*)[4]) dstRow;
1021 for (i = j = 0, k = k0; i < dstWidth;
1022 i++, j += colStride, k += colStride) {
1023 dst[i][0] = (rowA[j][0] + rowA[k][0] +
1024 rowB[j][0] + rowB[k][0]) / 4;
1025 dst[i][1] = (rowA[j][1] + rowA[k][1] +
1026 rowB[j][1] + rowB[k][1]) / 4;
1027 dst[i][2] = (rowA[j][2] + rowA[k][2] +
1028 rowB[j][2] + rowB[k][2]) / 4;
1029 dst[i][3] = (rowA[j][3] + rowA[k][3] +
1030 rowB[j][3] + rowB[k][3]) / 4;
1031 }
1032 }
1033 return;
1034 case MESA_FORMAT_RGB:
1035 {
1036 GLuint i, j, k;
1037 const GLchan (*rowA)[3] = (const GLchan (*)[3]) srcRowA;
1038 const GLchan (*rowB)[3] = (const GLchan (*)[3]) srcRowB;
1039 GLchan (*dst)[3] = (GLchan (*)[3]) dstRow;
1040 for (i = j = 0, k = k0; i < dstWidth;
1041 i++, j += colStride, k += colStride) {
1042 dst[i][0] = (rowA[j][0] + rowA[k][0] +
1043 rowB[j][0] + rowB[k][0]) / 4;
1044 dst[i][1] = (rowA[j][1] + rowA[k][1] +
1045 rowB[j][1] + rowB[k][1]) / 4;
1046 dst[i][2] = (rowA[j][2] + rowA[k][2] +
1047 rowB[j][2] + rowB[k][2]) / 4;
1048 }
1049 }
1050 return;
1051 case MESA_FORMAT_ALPHA:
1052 case MESA_FORMAT_LUMINANCE:
1053 case MESA_FORMAT_INTENSITY:
1054 case MESA_FORMAT_COLOR_INDEX:
1055 {
1056 GLuint i, j, k;
1057 const GLchan *rowA = (const GLchan *) srcRowA;
1058 const GLchan *rowB = (const GLchan *) srcRowB;
1059 GLchan *dst = (GLchan *) dstRow;
1060 for (i = j = 0, k = k0; i < dstWidth;
1061 i++, j += colStride, k += colStride) {
1062 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
1063 }
1064 }
1065 return;
1066 case MESA_FORMAT_LUMINANCE_ALPHA:
1067 {
1068 GLuint i, j, k;
1069 const GLchan (*rowA)[2] = (const GLchan (*)[2]) srcRowA;
1070 const GLchan (*rowB)[2] = (const GLchan (*)[2]) srcRowB;
1071 GLchan (*dst)[2] = (GLchan (*)[2]) dstRow;
1072 for (i = j = 0, k = k0; i < dstWidth;
1073 i++, j += colStride, k += colStride) {
1074 dst[i][0] = (rowA[j][0] + rowA[k][0] +
1075 rowB[j][0] + rowB[k][0]) / 4;
1076 dst[i][1] = (rowA[j][1] + rowA[k][1] +
1077 rowB[j][1] + rowB[k][1]) / 4;
1078 }
1079 }
1080 return;
1081 case MESA_FORMAT_DEPTH_COMPONENT:
1082 {
1083 GLuint i, j, k;
1084 const GLfloat *rowA = (const GLfloat *) srcRowA;
1085 const GLfloat *rowB = (const GLfloat *) srcRowB;
1086 GLfloat *dst = (GLfloat *) dstRow;
1087 for (i = j = 0, k = k0; i < dstWidth;
1088 i++, j += colStride, k += colStride) {
1089 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F;
1090 }
1091 }
1092 return;
1093 /* Begin hardware formats */
1094 case MESA_FORMAT_RGBA8888:
1095 case MESA_FORMAT_ARGB8888:
1096 {
1097 GLuint i, j, k;
1098 const GLubyte (*rowA)[4] = (const GLubyte (*)[4]) srcRowA;
1099 const GLubyte (*rowB)[4] = (const GLubyte (*)[4]) srcRowB;
1100 GLubyte (*dst)[4] = (GLubyte (*)[4]) dstRow;
1101 for (i = j = 0, k = k0; i < dstWidth;
1102 i++, j += colStride, k += colStride) {
1103 dst[i][0] = (rowA[j][0] + rowA[k][0] +
1104 rowB[j][0] + rowB[k][0]) / 4;
1105 dst[i][1] = (rowA[j][1] + rowA[k][1] +
1106 rowB[j][1] + rowB[k][1]) / 4;
1107 dst[i][2] = (rowA[j][2] + rowA[k][2] +
1108 rowB[j][2] + rowB[k][2]) / 4;
1109 dst[i][3] = (rowA[j][3] + rowA[k][3] +
1110 rowB[j][3] + rowB[k][3]) / 4;
1111 }
1112 }
1113 return;
1114 case MESA_FORMAT_RGB888:
1115 {
1116 GLuint i, j, k;
1117 const GLubyte (*rowA)[3] = (const GLubyte (*)[3]) srcRowA;
1118 const GLubyte (*rowB)[3] = (const GLubyte (*)[3]) srcRowB;
1119 GLubyte (*dst)[3] = (GLubyte (*)[3]) dstRow;
1120 for (i = j = 0, k = k0; i < dstWidth;
1121 i++, j += colStride, k += colStride) {
1122 dst[i][0] = (rowA[j][0] + rowA[k][0] +
1123 rowB[j][0] + rowB[k][0]) / 4;
1124 dst[i][1] = (rowA[j][1] + rowA[k][1] +
1125 rowB[j][1] + rowB[k][1]) / 4;
1126 dst[i][2] = (rowA[j][2] + rowA[k][2] +
1127 rowB[j][2] + rowB[k][2]) / 4;
1128 }
1129 }
1130 return;
1131 case MESA_FORMAT_RGB565:
1132 {
1133 GLuint i, j, k;
1134 const GLushort *rowA = (const GLushort *) srcRowA;
1135 const GLushort *rowB = (const GLushort *) srcRowB;
1136 GLushort *dst = (GLushort *) dstRow;
1137 for (i = j = 0, k = k0; i < dstWidth;
1138 i++, j += colStride, k += colStride) {
1139 const GLint rowAr0 = rowA[j] & 0x1f;
1140 const GLint rowAr1 = rowA[k] & 0x1f;
1141 const GLint rowBr0 = rowB[j] & 0x1f;
1142 const GLint rowBr1 = rowB[k] & 0x1f;
1143 const GLint rowAg0 = (rowA[j] >> 5) & 0x3f;
1144 const GLint rowAg1 = (rowA[k] >> 5) & 0x3f;
1145 const GLint rowBg0 = (rowB[j] >> 5) & 0x3f;
1146 const GLint rowBg1 = (rowB[k] >> 5) & 0x3f;
1147 const GLint rowAb0 = (rowA[j] >> 11) & 0x1f;
1148 const GLint rowAb1 = (rowA[k] >> 11) & 0x1f;
1149 const GLint rowBb0 = (rowB[j] >> 11) & 0x1f;
1150 const GLint rowBb1 = (rowB[k] >> 11) & 0x1f;
1151 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 4;
1152 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 4;
1153 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 4;
1154 dst[i] = (blue << 11) | (green << 5) | red;
1155 }
1156 }
1157 return;
1158 case MESA_FORMAT_ARGB4444:
1159 {
1160 GLuint i, j, k;
1161 const GLushort *rowA = (const GLushort *) srcRowA;
1162 const GLushort *rowB = (const GLushort *) srcRowB;
1163 GLushort *dst = (GLushort *) dstRow;
1164 for (i = j = 0, k = k0; i < dstWidth;
1165 i++, j += colStride, k += colStride) {
1166 const GLint rowAr0 = rowA[j] & 0xf;
1167 const GLint rowAr1 = rowA[k] & 0xf;
1168 const GLint rowBr0 = rowB[j] & 0xf;
1169 const GLint rowBr1 = rowB[k] & 0xf;
1170 const GLint rowAg0 = (rowA[j] >> 4) & 0xf;
1171 const GLint rowAg1 = (rowA[k] >> 4) & 0xf;
1172 const GLint rowBg0 = (rowB[j] >> 4) & 0xf;
1173 const GLint rowBg1 = (rowB[k] >> 4) & 0xf;
1174 const GLint rowAb0 = (rowA[j] >> 8) & 0xf;
1175 const GLint rowAb1 = (rowA[k] >> 8) & 0xf;
1176 const GLint rowBb0 = (rowB[j] >> 8) & 0xf;
1177 const GLint rowBb1 = (rowB[k] >> 8) & 0xf;
1178 const GLint rowAa0 = (rowA[j] >> 12) & 0xf;
1179 const GLint rowAa1 = (rowA[k] >> 12) & 0xf;
1180 const GLint rowBa0 = (rowB[j] >> 12) & 0xf;
1181 const GLint rowBa1 = (rowB[k] >> 12) & 0xf;
1182 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 4;
1183 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 4;
1184 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 4;
1185 const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 4;
1186 dst[i] = (alpha << 12) | (blue << 8) | (green << 4) | red;
1187 }
1188 }
1189 return;
1190 case MESA_FORMAT_ARGB1555:
1191 {
1192 GLuint i, j, k;
1193 const GLushort *rowA = (const GLushort *) srcRowA;
1194 const GLushort *rowB = (const GLushort *) srcRowB;
1195 GLushort *dst = (GLushort *) dstRow;
1196 for (i = j = 0, k = k0; i < dstWidth;
1197 i++, j += colStride, k += colStride) {
1198 const GLint rowAr0 = rowA[j] & 0x1f;
1199 const GLint rowAr1 = rowA[k] & 0x1f;
1200 const GLint rowBr0 = rowB[j] & 0x1f;
1201 const GLint rowBr1 = rowB[k] & 0xf;
1202 const GLint rowAg0 = (rowA[j] >> 5) & 0x1f;
1203 const GLint rowAg1 = (rowA[k] >> 5) & 0x1f;
1204 const GLint rowBg0 = (rowB[j] >> 5) & 0x1f;
1205 const GLint rowBg1 = (rowB[k] >> 5) & 0x1f;
1206 const GLint rowAb0 = (rowA[j] >> 10) & 0x1f;
1207 const GLint rowAb1 = (rowA[k] >> 10) & 0x1f;
1208 const GLint rowBb0 = (rowB[j] >> 10) & 0x1f;
1209 const GLint rowBb1 = (rowB[k] >> 10) & 0x1f;
1210 const GLint rowAa0 = (rowA[j] >> 15) & 0x1;
1211 const GLint rowAa1 = (rowA[k] >> 15) & 0x1;
1212 const GLint rowBa0 = (rowB[j] >> 15) & 0x1;
1213 const GLint rowBa1 = (rowB[k] >> 15) & 0x1;
1214 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 4;
1215 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 4;
1216 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 4;
1217 const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 4;
1218 dst[i] = (alpha << 15) | (blue << 10) | (green << 5) | red;
1219 }
1220 }
1221 return;
1222 case MESA_FORMAT_AL88:
1223 {
1224 GLuint i, j, k;
1225 const GLubyte (*rowA)[2] = (const GLubyte (*)[2]) srcRowA;
1226 const GLubyte (*rowB)[2] = (const GLubyte (*)[2]) srcRowB;
1227 GLubyte (*dst)[2] = (GLubyte (*)[2]) dstRow;
1228 for (i = j = 0, k = k0; i < dstWidth;
1229 i++, j += colStride, k += colStride) {
1230 dst[i][0] = (rowA[j][0] + rowA[k][0] +
1231 rowB[j][0] + rowB[k][0]) >> 2;
1232 dst[i][1] = (rowA[j][1] + rowA[k][1] +
1233 rowB[j][1] + rowB[k][1]) >> 2;
1234 }
1235 }
1236 return;
1237 case MESA_FORMAT_RGB332:
1238 {
1239 GLuint i, j, k;
1240 const GLubyte *rowA = (const GLubyte *) srcRowA;
1241 const GLubyte *rowB = (const GLubyte *) srcRowB;
1242 GLubyte *dst = (GLubyte *) dstRow;
1243 for (i = j = 0, k = k0; i < dstWidth;
1244 i++, j += colStride, k += colStride) {
1245 const GLint rowAr0 = rowA[j] & 0x3;
1246 const GLint rowAr1 = rowA[k] & 0x3;
1247 const GLint rowBr0 = rowB[j] & 0x3;
1248 const GLint rowBr1 = rowB[k] & 0x3;
1249 const GLint rowAg0 = (rowA[j] >> 2) & 0x7;
1250 const GLint rowAg1 = (rowA[k] >> 2) & 0x7;
1251 const GLint rowBg0 = (rowB[j] >> 2) & 0x7;
1252 const GLint rowBg1 = (rowB[k] >> 2) & 0x7;
1253 const GLint rowAb0 = (rowA[j] >> 5) & 0x7;
1254 const GLint rowAb1 = (rowA[k] >> 5) & 0x7;
1255 const GLint rowBb0 = (rowB[j] >> 5) & 0x7;
1256 const GLint rowBb1 = (rowB[k] >> 5) & 0x7;
1257 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 4;
1258 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 4;
1259 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 4;
1260 dst[i] = (blue << 5) | (green << 2) | red;
1261 }
1262 }
1263 return;
1264 case MESA_FORMAT_A8:
1265 case MESA_FORMAT_L8:
1266 case MESA_FORMAT_I8:
1267 case MESA_FORMAT_CI8:
1268 {
1269 GLuint i, j, k;
1270 const GLubyte *rowA = (const GLubyte *) srcRowA;
1271 const GLubyte *rowB = (const GLubyte *) srcRowB;
1272 GLubyte *dst = (GLubyte *) dstRow;
1273 for (i = j = 0, k = k0; i < dstWidth;
1274 i++, j += colStride, k += colStride) {
1275 dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) >> 2;
1276 }
1277 }
1278 return;
1279 default:
1280 _mesa_problem(NULL, "bad format in do_row()");
1281 }
1282 }
1283
1284
1285 /*
1286 * These functions generate a 1/2-size mipmap image from a source image.
1287 * Texture borders are handled by copying or averaging the source image's
1288 * border texels, depending on the scale-down factor.
1289 */
1290
1291 static void
1292 make_1d_mipmap(const struct gl_texture_format *format, GLint border,
1293 GLint srcWidth, const GLubyte *srcPtr,
1294 GLint dstWidth, GLubyte *dstPtr)
1295 {
1296 const GLint bpt = format->TexelBytes;
1297 const GLubyte *src;
1298 GLubyte *dst;
1299
1300 /* skip the border pixel, if any */
1301 src = srcPtr + border * bpt;
1302 dst = dstPtr + border * bpt;
1303
1304 /* we just duplicate the input row, kind of hack, saves code */
1305 do_row(format, srcWidth - 2 * border, src, src,
1306 dstWidth - 2 * border, dst);
1307
1308 if (border) {
1309 /* copy left-most pixel from source */
1310 MEMCPY(dstPtr, srcPtr, bpt);
1311 /* copy right-most pixel from source */
1312 MEMCPY(dstPtr + (dstWidth - 1) * bpt,
1313 srcPtr + (srcWidth - 1) * bpt,
1314 bpt);
1315 }
1316 }
1317
1318
1319 static void
1320 make_2d_mipmap(const struct gl_texture_format *format, GLint border,
1321 GLint srcWidth, GLint srcHeight, const GLubyte *srcPtr,
1322 GLint dstWidth, GLint dstHeight, GLubyte *dstPtr)
1323 {
1324 const GLint bpt = format->TexelBytes;
1325 const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */
1326 const GLint dstWidthNB = dstWidth - 2 * border;
1327 const GLint dstHeightNB = dstHeight - 2 * border;
1328 const GLint srcRowStride = bpt * srcWidth;
1329 const GLint dstRowStride = bpt * dstWidth;
1330 const GLubyte *srcA, *srcB;
1331 GLubyte *dst;
1332 GLint row, colStride;
1333
1334 colStride = (srcWidth == dstWidth) ? 1 : 2;
1335
1336 /* Compute src and dst pointers, skipping any border */
1337 srcA = srcPtr + border * ((srcWidth + 1) * bpt);
1338 if (srcHeight > 1)
1339 srcB = srcA + srcRowStride;
1340 else
1341 srcB = srcA;
1342 dst = dstPtr + border * ((dstWidth + 1) * bpt);
1343
1344 for (row = 0; row < dstHeightNB; row++) {
1345 do_row(format, srcWidthNB, srcA, srcB,
1346 dstWidthNB, dst);
1347 srcA += 2 * srcRowStride;
1348 srcB += 2 * srcRowStride;
1349 dst += dstRowStride;
1350 }
1351
1352 /* This is ugly but probably won't be used much */
1353 if (border > 0) {
1354 /* fill in dest border */
1355 /* lower-left border pixel */
1356 MEMCPY(dstPtr, srcPtr, bpt);
1357 /* lower-right border pixel */
1358 MEMCPY(dstPtr + (dstWidth - 1) * bpt,
1359 srcPtr + (srcWidth - 1) * bpt, bpt);
1360 /* upper-left border pixel */
1361 MEMCPY(dstPtr + dstWidth * (dstHeight - 1) * bpt,
1362 srcPtr + srcWidth * (srcHeight - 1) * bpt, bpt);
1363 /* upper-right border pixel */
1364 MEMCPY(dstPtr + (dstWidth * dstHeight - 1) * bpt,
1365 srcPtr + (srcWidth * srcHeight - 1) * bpt, bpt);
1366 /* lower border */
1367 do_row(format, srcWidthNB,
1368 srcPtr + bpt,
1369 srcPtr + bpt,
1370 dstWidthNB, dstPtr + bpt);
1371 /* upper border */
1372 do_row(format, srcWidthNB,
1373 srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
1374 srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
1375 dstWidthNB,
1376 dstPtr + (dstWidth * (dstHeight - 1) + 1) * bpt);
1377 /* left and right borders */
1378 if (srcHeight == dstHeight) {
1379 /* copy border pixel from src to dst */
1380 for (row = 1; row < srcHeight; row++) {
1381 MEMCPY(dstPtr + dstWidth * row * bpt,
1382 srcPtr + srcWidth * row * bpt, bpt);
1383 MEMCPY(dstPtr + (dstWidth * row + dstWidth - 1) * bpt,
1384 srcPtr + (srcWidth * row + srcWidth - 1) * bpt, bpt);
1385 }
1386 }
1387 else {
1388 /* average two src pixels each dest pixel */
1389 for (row = 0; row < dstHeightNB; row += 2) {
1390 do_row(format, 1,
1391 srcPtr + (srcWidth * (row * 2 + 1)) * bpt,
1392 srcPtr + (srcWidth * (row * 2 + 2)) * bpt,
1393 1, dstPtr + (dstWidth * row + 1) * bpt);
1394 do_row(format, 1,
1395 srcPtr + (srcWidth * (row * 2 + 1) + srcWidth - 1) * bpt,
1396 srcPtr + (srcWidth * (row * 2 + 2) + srcWidth - 1) * bpt,
1397 1, dstPtr + (dstWidth * row + 1 + dstWidth - 1) * bpt);
1398 }
1399 }
1400 }
1401 }
1402
1403
1404 static void
1405 make_3d_mipmap(const struct gl_texture_format *format, GLint border,
1406 GLint srcWidth, GLint srcHeight, GLint srcDepth,
1407 const GLubyte *srcPtr,
1408 GLint dstWidth, GLint dstHeight, GLint dstDepth,
1409 GLubyte *dstPtr)
1410 {
1411 const GLint bpt = format->TexelBytes;
1412 const GLint srcWidthNB = srcWidth - 2 * border; /* sizes w/out border */
1413 const GLint srcDepthNB = srcDepth - 2 * border;
1414 const GLint dstWidthNB = dstWidth - 2 * border;
1415 const GLint dstHeightNB = dstHeight - 2 * border;
1416 const GLint dstDepthNB = dstDepth - 2 * border;
1417 GLvoid *tmpRowA, *tmpRowB;
1418 GLint img, row;
1419 GLint bytesPerSrcImage, bytesPerDstImage;
1420 GLint bytesPerSrcRow, bytesPerDstRow;
1421 GLint srcImageOffset, srcRowOffset;
1422
1423 (void) srcDepthNB; /* silence warnings */
1424
1425 /* Need two temporary row buffers */
1426 tmpRowA = MALLOC(srcWidth * bpt);
1427 if (!tmpRowA)
1428 return;
1429 tmpRowB = MALLOC(srcWidth * bpt);
1430 if (!tmpRowB) {
1431 FREE(tmpRowA);
1432 return;
1433 }
1434
1435 bytesPerSrcImage = srcWidth * srcHeight * bpt;
1436 bytesPerDstImage = dstWidth * dstHeight * bpt;
1437
1438 bytesPerSrcRow = srcWidth * bpt;
1439 bytesPerDstRow = dstWidth * bpt;
1440
1441 /* Offset between adjacent src images to be averaged together */
1442 srcImageOffset = (srcDepth == dstDepth) ? 0 : bytesPerSrcImage;
1443
1444 /* Offset between adjacent src rows to be averaged together */
1445 srcRowOffset = (srcHeight == dstHeight) ? 0 : srcWidth * bpt;
1446
1447 /*
1448 * Need to average together up to 8 src pixels for each dest pixel.
1449 * Break that down into 3 operations:
1450 * 1. take two rows from source image and average them together.
1451 * 2. take two rows from next source image and average them together.
1452 * 3. take the two averaged rows and average them for the final dst row.
1453 */
1454
1455 /*
1456 printf("mip3d %d x %d x %d -> %d x %d x %d\n",
1457 srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth);
1458 */
1459
1460 for (img = 0; img < dstDepthNB; img++) {
1461 /* first source image pointer, skipping border */
1462 const GLubyte *imgSrcA = srcPtr
1463 + (bytesPerSrcImage + bytesPerSrcRow + border) * bpt * border
1464 + img * (bytesPerSrcImage + srcImageOffset);
1465 /* second source image pointer, skipping border */
1466 const GLubyte *imgSrcB = imgSrcA + srcImageOffset;
1467 /* address of the dest image, skipping border */
1468 GLubyte *imgDst = dstPtr
1469 + (bytesPerDstImage + bytesPerDstRow + border) * bpt * border
1470 + img * bytesPerDstImage;
1471
1472 /* setup the four source row pointers and the dest row pointer */
1473 const GLubyte *srcImgARowA = imgSrcA;
1474 const GLubyte *srcImgARowB = imgSrcA + srcRowOffset;
1475 const GLubyte *srcImgBRowA = imgSrcB;
1476 const GLubyte *srcImgBRowB = imgSrcB + srcRowOffset;
1477 GLubyte *dstImgRow = imgDst;
1478
1479 for (row = 0; row < dstHeightNB; row++) {
1480 /* Average together two rows from first src image */
1481 do_row(format, srcWidthNB, srcImgARowA, srcImgARowB,
1482 srcWidthNB, tmpRowA);
1483 /* Average together two rows from second src image */
1484 do_row(format, srcWidthNB, srcImgBRowA, srcImgBRowB,
1485 srcWidthNB, tmpRowB);
1486 /* Average together the temp rows to make the final row */
1487 do_row(format, srcWidthNB, tmpRowA, tmpRowB,
1488 dstWidthNB, dstImgRow);
1489 /* advance to next rows */
1490 srcImgARowA += bytesPerSrcRow + srcRowOffset;
1491 srcImgARowB += bytesPerSrcRow + srcRowOffset;
1492 srcImgBRowA += bytesPerSrcRow + srcRowOffset;
1493 srcImgBRowB += bytesPerSrcRow + srcRowOffset;
1494 dstImgRow += bytesPerDstRow;
1495 }
1496 }
1497
1498 FREE(tmpRowA);
1499 FREE(tmpRowB);
1500
1501 /* Luckily we can leverage the make_2d_mipmap() function here! */
1502 if (border > 0) {
1503 /* do front border image */
1504 make_2d_mipmap(format, 1, srcWidth, srcHeight, srcPtr,
1505 dstWidth, dstHeight, dstPtr);
1506 /* do back border image */
1507 make_2d_mipmap(format, 1, srcWidth, srcHeight,
1508 srcPtr + bytesPerSrcImage * (srcDepth - 1),
1509 dstWidth, dstHeight,
1510 dstPtr + bytesPerDstImage * (dstDepth - 1));
1511 /* do four remaining border edges that span the image slices */
1512 if (srcDepth == dstDepth) {
1513 /* just copy border pixels from src to dst */
1514 for (img = 0; img < dstDepthNB; img++) {
1515 const GLubyte *src;
1516 GLubyte *dst;
1517
1518 /* do border along [img][row=0][col=0] */
1519 src = srcPtr + (img + 1) * bytesPerSrcImage;
1520 dst = dstPtr + (img + 1) * bytesPerDstImage;
1521 MEMCPY(dst, src, bpt);
1522
1523 /* do border along [img][row=dstHeight-1][col=0] */
1524 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
1525 + (srcHeight - 1) * bytesPerSrcRow;
1526 dst = dstPtr + (img + 1) * bytesPerDstImage
1527 + (dstHeight - 1) * bytesPerDstRow;
1528 MEMCPY(dst, src, bpt);
1529
1530 /* do border along [img][row=0][col=dstWidth-1] */
1531 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
1532 + (srcWidth - 1) * bpt;
1533 dst = dstPtr + (img + 1) * bytesPerDstImage
1534 + (dstWidth - 1) * bpt;
1535 MEMCPY(dst, src, bpt);
1536
1537 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
1538 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
1539 + (bytesPerSrcImage - bpt);
1540 dst = dstPtr + (img + 1) * bytesPerDstImage
1541 + (bytesPerDstImage - bpt);
1542 MEMCPY(dst, src, bpt);
1543 }
1544 }
1545 else {
1546 /* average border pixels from adjacent src image pairs */
1547 ASSERT(srcDepthNB == 2 * dstDepthNB);
1548 for (img = 0; img < dstDepthNB; img++) {
1549 const GLubyte *src;
1550 GLubyte *dst;
1551
1552 /* do border along [img][row=0][col=0] */
1553 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage;
1554 dst = dstPtr + (img + 1) * bytesPerDstImage;
1555 do_row(format, 1, src, src + srcImageOffset, 1, dst);
1556
1557 /* do border along [img][row=dstHeight-1][col=0] */
1558 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
1559 + (srcHeight - 1) * bytesPerSrcRow;
1560 dst = dstPtr + (img + 1) * bytesPerDstImage
1561 + (dstHeight - 1) * bytesPerDstRow;
1562 do_row(format, 1, src, src + srcImageOffset, 1, dst);
1563
1564 /* do border along [img][row=0][col=dstWidth-1] */
1565 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
1566 + (srcWidth - 1) * bpt;
1567 dst = dstPtr + (img + 1) * bytesPerDstImage
1568 + (dstWidth - 1) * bpt;
1569 do_row(format, 1, src, src + srcImageOffset, 1, dst);
1570
1571 /* do border along [img][row=dstHeight-1][col=dstWidth-1] */
1572 src = srcPtr + (img * 2 + 1) * bytesPerSrcImage
1573 + (bytesPerSrcImage - bpt);
1574 dst = dstPtr + (img + 1) * bytesPerDstImage
1575 + (bytesPerDstImage - bpt);
1576 do_row(format, 1, src, src + srcImageOffset, 1, dst);
1577 }
1578 }
1579 }
1580 }
1581
1582
1583 /*
1584 * For GL_SGIX_generate_mipmap:
1585 * Generate a complete set of mipmaps from texObj's base-level image.
1586 * Stop at texObj's MaxLevel or when we get to the 1x1 texture.
1587 */
1588 void
1589 _mesa_generate_mipmap(GLcontext *ctx,
1590 const struct gl_texture_unit *texUnit,
1591 struct gl_texture_object *texObj)
1592 {
1593 const GLenum targets1D[] = { GL_TEXTURE_1D, 0 };
1594 const GLenum targets2D[] = { GL_TEXTURE_2D, 0 };
1595 const GLenum targets3D[] = { GL_TEXTURE_3D, 0 };
1596 const GLenum targetsCube[] = { GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
1597 GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,
1598 GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,
1599 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,
1600 GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,
1601 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB,
1602 0 };
1603 const GLenum *targets;
1604 GLuint level;
1605 GLint maxLevels = 0;
1606
1607 ASSERT(texObj);
1608 ASSERT(texObj->Image[texObj->BaseLevel]);
1609
1610 switch (texObj->Dimensions) {
1611 case 1:
1612 targets = targets1D;
1613 maxLevels = ctx->Const.MaxTextureLevels;
1614 break;
1615 case 2:
1616 targets = targets2D;
1617 maxLevels = ctx->Const.MaxTextureLevels;
1618 break;
1619 case 3:
1620 targets = targets3D;
1621 maxLevels = ctx->Const.Max3DTextureLevels;
1622 break;
1623 case 6:
1624 targets = targetsCube;
1625 maxLevels = ctx->Const.MaxCubeTextureLevels;
1626 break;
1627 default:
1628 _mesa_problem(ctx,
1629 "Bad texture object dimension in _mesa_generate_mipmaps");
1630 return;
1631 }
1632
1633 for (level = texObj->BaseLevel; level < texObj->MaxLevel
1634 && level < maxLevels - 1; level++) {
1635 /* generate image[level+1] from image[level] */
1636 const struct gl_texture_image *srcImage;
1637 struct gl_texture_image *dstImage;
1638 GLint srcWidth, srcHeight, srcDepth;
1639 GLint dstWidth, dstHeight, dstDepth;
1640 GLint border, bytesPerTexel;
1641 GLint t;
1642
1643 srcImage = texObj->Image[level];
1644 ASSERT(srcImage);
1645 srcWidth = srcImage->Width;
1646 srcHeight = srcImage->Height;
1647 srcDepth = srcImage->Depth;
1648 border = srcImage->Border;
1649 bytesPerTexel = srcImage->TexFormat->TexelBytes;
1650
1651 /* compute next (level+1) image size */
1652 if (srcWidth - 2 * border > 1) {
1653 dstWidth = (srcWidth - 2 * border) / 2 + 2 * border;
1654 }
1655 else {
1656 dstWidth = srcWidth; /* can't go smaller */
1657 }
1658 if (srcHeight - 2 * border > 1) {
1659 dstHeight = (srcHeight - 2 * border) / 2 + 2 * border;
1660 }
1661 else {
1662 dstHeight = srcHeight; /* can't go smaller */
1663 }
1664 if (srcDepth - 2 * border > 1) {
1665 dstDepth = (srcDepth - 2 * border) / 2 + 2 * border;
1666 }
1667 else {
1668 dstDepth = srcDepth; /* can't go smaller */
1669 }
1670
1671 if (dstWidth == srcWidth &&
1672 dstHeight == srcHeight &&
1673 dstDepth == srcDepth) {
1674 /* all done */
1675 return;
1676 }
1677
1678 /* Need this loop just because of cubemaps */
1679 for (t = 0; targets[t]; t++) {
1680 ASSERT(t < 6);
1681
1682 dstImage = _mesa_select_tex_image(ctx, texUnit, targets[t], level+1);
1683 if (!dstImage) {
1684 dstImage = _mesa_alloc_texture_image();
1685 if (!dstImage) {
1686 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
1687 return;
1688 }
1689 _mesa_set_tex_image(texObj, targets[t], level + 1, dstImage);
1690 }
1691
1692 /* Free old image data */
1693 if (dstImage->Data)
1694 FREE(dstImage->Data);
1695
1696 /* initialize new image */
1697 _mesa_init_teximage_fields(ctx, dstImage, dstWidth, dstHeight,
1698 dstDepth, border, srcImage->Format);
1699 dstImage->DriverData = NULL;
1700 dstImage->TexFormat = srcImage->TexFormat;
1701 dstImage->FetchTexel = srcImage->FetchTexel;
1702 ASSERT(dstImage->TexFormat);
1703 ASSERT(dstImage->FetchTexel);
1704
1705 ASSERT(dstWidth * dstHeight * dstDepth * bytesPerTexel > 0);
1706
1707 /* alloc new image buffer */
1708 dstImage->Data = MALLOC(dstWidth * dstHeight * dstDepth
1709 * bytesPerTexel);
1710 if (!dstImage->Data) {
1711 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
1712 return;
1713 }
1714
1715 /*
1716 * We use simple 2x2 averaging to compute the next mipmap level.
1717 */
1718 switch (texObj->Dimensions) {
1719 case 1:
1720 make_1d_mipmap(srcImage->TexFormat, border,
1721 srcWidth, (const GLubyte *) srcImage->Data,
1722 dstWidth, (GLubyte *) dstImage->Data);
1723 break;
1724 case 2:
1725 case 6:
1726 make_2d_mipmap(srcImage->TexFormat, border,
1727 srcWidth, srcHeight, (const GLubyte *) srcImage->Data,
1728 dstWidth, dstHeight, (GLubyte *) dstImage->Data);
1729 break;
1730 case 3:
1731 make_3d_mipmap(srcImage->TexFormat, border,
1732 srcWidth, srcHeight, srcDepth, (const GLubyte *) srcImage->Data,
1733 dstWidth, dstHeight, dstDepth, (GLubyte *) dstImage->Data);
1734 break;
1735 default:
1736 _mesa_problem(ctx, "bad dimensions in _mesa_generate_mipmaps");
1737 return;
1738 }
1739 } /* loop over tex image targets */
1740 } /* loop over tex levels */
1741 }