a little more work on GL_SGIS_generate_mipmap
[mesa.git] / src / mesa / main / texstore.c
1 /* $Id: texstore.c,v 1.26 2001/05/22 21:49:03 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 if (transferOps & IMAGE_CONVOLUTION_BIT) {
420 _mesa_adjust_image_for_convolution(ctx, dimensions, &postConvWidth,
421 &postConvHeight);
422 }
423
424 /*
425 * Consider this scenario: The user's source image is GL_RGB and the
426 * requested internal format is GL_LUMINANCE. Now suppose the device
427 * driver doesn't support GL_LUMINANCE and instead uses RGB16 as the
428 * texture format. In that case we still need to do an intermediate
429 * conversion to luminance format so that the incoming red channel gets
430 * replicated into the dest red, green and blue channels. The following
431 * code takes care of that.
432 */
433 if (dstFormat->BaseFormat != baseInternalFormat) {
434 /* Allocate storage for temporary image in the baseInternalFormat */
435 const GLint texelSize = _mesa_components_in_format(baseInternalFormat)
436 * sizeof(GLchan);
437 const GLint bytes = texelSize * postConvWidth * postConvHeight *srcDepth;
438 const GLint tmpRowStride = texelSize * postConvWidth;
439 const GLint tmpImgStride = texelSize * postConvWidth * postConvHeight;
440 GLvoid *tmpImage = MALLOC(bytes);
441 if (!tmpImage)
442 return;
443 transfer_teximage(ctx, dimensions, baseInternalFormat, tmpImage,
444 srcWidth, srcHeight, srcDepth,
445 0, 0, 0, /* x/y/zoffset */
446 tmpRowStride, tmpImgStride,
447 srcFormat, srcType, srcAddr, srcPacking, transferOps);
448
449 /* this is our new source image */
450 srcWidth = postConvWidth;
451 srcHeight = postConvHeight;
452 srcFormat = baseInternalFormat;
453 srcType = CHAN_TYPE;
454 srcAddr = tmpImage;
455 srcPacking = &_mesa_native_packing;
456 freeSourceData = GL_TRUE;
457 transferOps = 0; /* image transfer ops were completed */
458 }
459
460 /* Let the optimized tex conversion functions take a crack at the
461 * image conversion if the dest format is a h/w format.
462 */
463 if (_mesa_is_hardware_tex_format(dstFormat)) {
464 if (transferOps) {
465 makeTemp = GL_TRUE;
466 }
467 else {
468 if (dimensions == 1) {
469 makeTemp = !_mesa_convert_texsubimage1d(dstFormat->MesaFormat,
470 dstXoffset,
471 srcWidth,
472 srcFormat, srcType,
473 srcPacking, srcAddr,
474 dstAddr);
475 }
476 else if (dimensions == 2) {
477 makeTemp = !_mesa_convert_texsubimage2d(dstFormat->MesaFormat,
478 dstXoffset, dstYoffset,
479 srcWidth, srcHeight,
480 dstRowStridePixels,
481 srcFormat, srcType,
482 srcPacking, srcAddr,
483 dstAddr);
484 }
485 else {
486 assert(dimensions == 3);
487 makeTemp = !_mesa_convert_texsubimage3d(dstFormat->MesaFormat,
488 dstXoffset, dstYoffset, dstZoffset,
489 srcWidth, srcHeight, srcDepth,
490 dstRowStridePixels, dstImageStridePixels,
491 srcFormat, srcType,
492 srcPacking, srcAddr, dstAddr);
493 }
494 if (!makeTemp) {
495 /* all done! */
496 if (freeSourceData)
497 FREE((void *) srcAddr);
498 return;
499 }
500 }
501 }
502 else {
503 /* software texture format */
504 makeTemp = GL_FALSE;
505 }
506
507 if (makeTemp) {
508 GLint postConvWidth = srcWidth, postConvHeight = srcHeight;
509 GLenum tmpFormat;
510 GLuint tmpComps, tmpTexelSize;
511 GLint tmpRowStride, tmpImageStride;
512 GLubyte *tmpImage;
513
514 if (transferOps & IMAGE_CONVOLUTION_BIT) {
515 _mesa_adjust_image_for_convolution(ctx, dimensions, &postConvWidth,
516 &postConvHeight);
517 }
518
519 tmpFormat = dstFormat->BaseFormat;
520 tmpComps = _mesa_components_in_format(tmpFormat);
521 tmpTexelSize = tmpComps * sizeof(GLchan);
522 tmpRowStride = postConvWidth * tmpTexelSize;
523 tmpImageStride = postConvWidth * postConvHeight * tmpTexelSize;
524 tmpImage = (GLubyte *) MALLOC(postConvWidth * postConvHeight *
525 srcDepth * tmpTexelSize);
526 if (!tmpImage) {
527 if (freeSourceData)
528 FREE((void *) srcAddr);
529 return;
530 }
531
532 transfer_teximage(ctx, dimensions, tmpFormat, tmpImage,
533 srcWidth, srcHeight, srcDepth,
534 0, 0, 0, /* x/y/zoffset */
535 tmpRowStride, tmpImageStride,
536 srcFormat, srcType, srcAddr, srcPacking, transferOps);
537
538 if (freeSourceData)
539 FREE((void *) srcAddr);
540
541 /* the temp image is our new source image */
542 srcWidth = postConvWidth;
543 srcHeight = postConvHeight;
544 srcFormat = tmpFormat;
545 srcType = CHAN_TYPE;
546 srcAddr = tmpImage;
547 srcPacking = &_mesa_native_packing;
548 freeSourceData = GL_TRUE;
549 }
550
551 if (_mesa_is_hardware_tex_format(dstFormat)) {
552 assert(makeTemp);
553 if (dimensions == 1) {
554 GLboolean b;
555 b = _mesa_convert_texsubimage1d(dstFormat->MesaFormat,
556 dstXoffset,
557 srcWidth,
558 srcFormat, srcType,
559 srcPacking, srcAddr,
560 dstAddr);
561 assert(b);
562 }
563 else if (dimensions == 2) {
564 GLboolean b;
565 b = _mesa_convert_texsubimage2d(dstFormat->MesaFormat,
566 dstXoffset, dstYoffset,
567 srcWidth, srcHeight,
568 dstRowStridePixels,
569 srcFormat, srcType,
570 srcPacking, srcAddr,
571 dstAddr);
572 assert(b);
573 }
574 else {
575 GLboolean b;
576 b = _mesa_convert_texsubimage3d(dstFormat->MesaFormat,
577 dstXoffset, dstYoffset, dstZoffset,
578 srcWidth, srcHeight, srcDepth,
579 dstRowStridePixels, dstImageStridePixels,
580 srcFormat, srcType,
581 srcPacking, srcAddr, dstAddr);
582 assert(b);
583 }
584 }
585 else {
586 /* software format */
587 assert(!makeTemp);
588 transfer_teximage(ctx, dimensions, dstFormat->BaseFormat, dstAddr,
589 srcWidth, srcHeight, srcDepth,
590 dstXoffset, dstYoffset, dstZoffset,
591 dstRowStride, dstImageStride,
592 srcFormat, srcType, srcAddr, srcPacking, transferOps);
593 }
594
595 if (freeSourceData)
596 FREE((void *) srcAddr); /* the temp image */
597 }
598
599
600 /*
601 * This is the software fallback for Driver.TexImage1D().
602 * The texture image type will be GLchan.
603 * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY,
604 * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA.
605 *
606 */
607 void
608 _mesa_store_teximage1d(GLcontext *ctx, GLenum target, GLint level,
609 GLint internalFormat,
610 GLint width, GLint border,
611 GLenum format, GLenum type, const GLvoid *pixels,
612 const struct gl_pixelstore_attrib *packing,
613 struct gl_texture_object *texObj,
614 struct gl_texture_image *texImage)
615 {
616 GLint postConvWidth = width;
617 GLint texelBytes;
618
619 if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
620 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
621 }
622
623 /* choose the texture format */
624 assert(ctx->Driver.ChooseTextureFormat);
625 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
626 internalFormat, format, type);
627 assert(texImage->TexFormat);
628
629 texelBytes = texImage->TexFormat->TexelBytes;
630
631 /* allocate memory */
632 texImage->Data = MALLOC(postConvWidth * texelBytes);
633 if (!texImage->Data) {
634 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
635 return;
636 }
637
638 /* unpack image, apply transfer ops and store in texImage->Data */
639 _mesa_transfer_teximage(ctx, 1, _mesa_base_tex_format(ctx, internalFormat),
640 texImage->TexFormat, texImage->Data,
641 width, 1, 1, 0, 0, 0,
642 0, /* dstRowStride */
643 0, /* dstImageStride */
644 format, type, pixels, packing);
645
646 /* GL_SGIS_generate_mipmap */
647 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
648 _mesa_generate_mipmap(ctx, &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
649 texObj);
650 }
651 }
652
653
654 /*
655 * This is the software fallback for Driver.TexImage2D().
656 * The texture image type will be GLchan.
657 * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY,
658 * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA.
659 *
660 */
661 void
662 _mesa_store_teximage2d(GLcontext *ctx, GLenum target, GLint level,
663 GLint internalFormat,
664 GLint width, GLint height, GLint border,
665 GLenum format, GLenum type, const void *pixels,
666 const struct gl_pixelstore_attrib *packing,
667 struct gl_texture_object *texObj,
668 struct gl_texture_image *texImage)
669 {
670 GLint postConvWidth = width, postConvHeight = height;
671 GLint texelBytes;
672
673 if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
674 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
675 &postConvHeight);
676 }
677
678 /* choose the texture format */
679 assert(ctx->Driver.ChooseTextureFormat);
680 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
681 internalFormat, format, type);
682 assert(texImage->TexFormat);
683 texImage->FetchTexel = texImage->TexFormat->FetchTexel2D;
684
685 texelBytes = texImage->TexFormat->TexelBytes;
686
687 /* allocate memory */
688 texImage->Data = MALLOC(postConvWidth * postConvHeight * texelBytes);
689 if (!texImage->Data) {
690 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
691 return;
692 }
693
694 /* unpack image, apply transfer ops and store in texImage->Data */
695 _mesa_transfer_teximage(ctx, 2, _mesa_base_tex_format(ctx, internalFormat),
696 texImage->TexFormat, texImage->Data,
697 width, height, 1, 0, 0, 0,
698 texImage->Width * texelBytes,
699 0, /* dstImageStride */
700 format, type, pixels, packing);
701
702 /* GL_SGIS_generate_mipmap */
703 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
704 _mesa_generate_mipmap(ctx, &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
705 texObj);
706 }
707 }
708
709
710
711 /*
712 * This is the software fallback for Driver.TexImage3D().
713 * The texture image type will be GLchan.
714 * The texture image format will be GL_COLOR_INDEX, GL_INTENSITY,
715 * GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_ALPHA, GL_RGB or GL_RGBA.
716 *
717 */
718 void
719 _mesa_store_teximage3d(GLcontext *ctx, GLenum target, GLint level,
720 GLint internalFormat,
721 GLint width, GLint height, GLint depth, GLint border,
722 GLenum format, GLenum type, const void *pixels,
723 const struct gl_pixelstore_attrib *packing,
724 struct gl_texture_object *texObj,
725 struct gl_texture_image *texImage)
726 {
727 GLint texelBytes;
728
729 /* choose the texture format */
730 assert(ctx->Driver.ChooseTextureFormat);
731 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
732 internalFormat, format, type);
733 assert(texImage->TexFormat);
734
735 texelBytes = texImage->TexFormat->TexelBytes;
736
737 /* allocate memory */
738 texImage->Data = MALLOC(width * height * depth * texelBytes);
739 if (!texImage->Data) {
740 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
741 return;
742 }
743
744 /* unpack image, apply transfer ops and store in texImage->Data */
745 _mesa_transfer_teximage(ctx, 3, _mesa_base_tex_format(ctx, internalFormat),
746 texImage->TexFormat, texImage->Data,
747 width, height, depth, 0, 0, 0,
748 texImage->Width * texelBytes,
749 texImage->Width * texImage->Height * texelBytes,
750 format, type, pixels, packing);
751
752 /* GL_SGIS_generate_mipmap */
753 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
754 _mesa_generate_mipmap(ctx, &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
755 texObj);
756 }
757 }
758
759
760
761
762 /*
763 * This is the software fallback for Driver.TexSubImage1D().
764 */
765 void
766 _mesa_store_texsubimage1d(GLcontext *ctx, GLenum target, GLint level,
767 GLint xoffset, GLint width,
768 GLenum format, GLenum type, const void *pixels,
769 const struct gl_pixelstore_attrib *packing,
770 struct gl_texture_object *texObj,
771 struct gl_texture_image *texImage)
772 {
773 _mesa_transfer_teximage(ctx, 1,
774 _mesa_base_tex_format(ctx, texImage->IntFormat),
775 texImage->TexFormat, texImage->Data,
776 width, 1, 1, /* src size */
777 xoffset, 0, 0, /* dest offsets */
778 0, /* dstRowStride */
779 0, /* dstImageStride */
780 format, type, pixels, packing);
781
782 /* GL_SGIS_generate_mipmap */
783 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
784 _mesa_generate_mipmap(ctx, &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
785 texObj);
786 }
787 }
788
789
790 /*
791 * This is the software fallback for Driver.TexSubImage2D().
792 */
793 void
794 _mesa_store_texsubimage2d(GLcontext *ctx, GLenum target, GLint level,
795 GLint xoffset, GLint yoffset,
796 GLint width, GLint height,
797 GLenum format, GLenum type, const void *pixels,
798 const struct gl_pixelstore_attrib *packing,
799 struct gl_texture_object *texObj,
800 struct gl_texture_image *texImage)
801 {
802 _mesa_transfer_teximage(ctx, 2,
803 _mesa_base_tex_format(ctx, texImage->IntFormat),
804 texImage->TexFormat, texImage->Data,
805 width, height, 1, /* src size */
806 xoffset, yoffset, 0, /* dest offsets */
807 texImage->Width * texImage->TexFormat->TexelBytes,
808 0, /* dstImageStride */
809 format, type, pixels, packing);
810
811 /* GL_SGIS_generate_mipmap */
812 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
813 _mesa_generate_mipmap(ctx, &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
814 texObj);
815 }
816 }
817
818
819 /*
820 * This is the software fallback for Driver.TexSubImage3D().
821 */
822 void
823 _mesa_store_texsubimage3d(GLcontext *ctx, GLenum target, GLint level,
824 GLint xoffset, GLint yoffset, GLint zoffset,
825 GLint width, GLint height, GLint depth,
826 GLenum format, GLenum type, const void *pixels,
827 const struct gl_pixelstore_attrib *packing,
828 struct gl_texture_object *texObj,
829 struct gl_texture_image *texImage)
830 {
831 const GLint texelBytes = texImage->TexFormat->TexelBytes;
832 _mesa_transfer_teximage(ctx, 3,
833 _mesa_base_tex_format(ctx, texImage->IntFormat),
834 texImage->TexFormat, texImage->Data,
835 width, height, depth, /* src size */
836 xoffset, yoffset, xoffset, /* dest offsets */
837 texImage->Width * texelBytes,
838 texImage->Width * texImage->Height * texelBytes,
839 format, type, pixels, packing);
840 /* GL_SGIS_generate_mipmap */
841 if (level == texObj->BaseLevel && texObj->GenerateMipmap) {
842 _mesa_generate_mipmap(ctx, &ctx->Texture.Unit[ctx->Texture.CurrentUnit],
843 texObj);
844 }
845 }
846
847
848
849
850 /*
851 * Fallback for Driver.CompressedTexImage1D()
852 */
853 void
854 _mesa_store_compressed_teximage1d(GLcontext *ctx, GLenum target, GLint level,
855 GLint internalFormat,
856 GLint width, GLint border,
857 GLsizei imageSize, const GLvoid *data,
858 struct gl_texture_object *texObj,
859 struct gl_texture_image *texImage)
860 {
861 /* Nothing here.
862 * The device driver has to do it all.
863 */
864 }
865
866
867
868 /*
869 * Fallback for Driver.CompressedTexImage2D()
870 */
871 void
872 _mesa_store_compressed_teximage2d(GLcontext *ctx, GLenum target, GLint level,
873 GLint internalFormat,
874 GLint width, GLint height, GLint border,
875 GLsizei imageSize, const GLvoid *data,
876 struct gl_texture_object *texObj,
877 struct gl_texture_image *texImage)
878 {
879 /* Nothing here.
880 * The device driver has to do it all.
881 */
882 }
883
884
885
886 /*
887 * Fallback for Driver.CompressedTexImage3D()
888 */
889 void
890 _mesa_store_compressed_teximage3d(GLcontext *ctx, GLenum target, GLint level,
891 GLint internalFormat,
892 GLint width, GLint height, GLint depth,
893 GLint border,
894 GLsizei imageSize, const GLvoid *data,
895 struct gl_texture_object *texObj,
896 struct gl_texture_image *texImage)
897 {
898 /* Nothing here.
899 * The device driver has to do it all.
900 */
901 }
902
903
904
905 /*
906 * This is the fallback for Driver.TestProxyTexImage().
907 */
908 GLboolean
909 _mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
910 GLint internalFormat, GLenum format, GLenum type,
911 GLint width, GLint height, GLint depth, GLint border)
912 {
913 struct gl_texture_unit *texUnit;
914 struct gl_texture_object *texObj;
915 struct gl_texture_image *texImage;
916
917 (void) format;
918 (void) type;
919
920 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
921 texObj = _mesa_select_tex_object(ctx, texUnit, target);
922 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
923
924 /* We always pass.
925 * The core Mesa code will have already tested the image size, etc.
926 * Drivers may have more stringent texture limits to enforce and will
927 * have to override this function.
928 */
929 /* choose the texture format */
930 assert(ctx->Driver.ChooseTextureFormat);
931 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx,
932 internalFormat, format, type);
933 assert(texImage->TexFormat);
934
935 return GL_TRUE;
936 }
937
938
939
940 /*
941 * Average together two rows of a source image to produce a single new
942 * row in the dest image. It's legal for the two source rows to point
943 * to the same data. The source rows are to be twice as long as the
944 * dest row.
945 */
946 static void
947 do_row(const struct gl_texture_format *format, GLint dstWidth,
948 const GLvoid *srcRowA, const GLvoid *srcRowB, GLvoid *dstRow)
949 {
950 switch (format->MesaFormat) {
951 case MESA_FORMAT_RGBA:
952 {
953 GLuint i, j;
954 const GLchan (*rowA)[4] = (const GLchan (*)[4]) srcRowA;
955 const GLchan (*rowB)[4] = (const GLchan (*)[4]) srcRowB;
956 GLchan (*dst)[4] = (GLchan (*)[4]) dstRow;
957 for (i = j = 0; i < dstWidth; i++, j+=2) {
958 dst[i][0] = (rowA[j][0] + rowA[j+1][0] +
959 rowB[j][0] + rowB[j+1][0]) >> 2;
960 dst[i][1] = (rowA[j][1] + rowA[j+1][1] +
961 rowB[j][1] + rowB[j+1][1]) >> 2;
962 dst[i][2] = (rowA[j][2] + rowA[j+1][2] +
963 rowB[j][2] + rowB[j+1][2]) >> 2;
964 dst[i][3] = (rowA[j][3] + rowA[j+1][3] +
965 rowB[j][3] + rowB[j+1][3]) >> 2;
966 }
967 }
968 return;
969 case MESA_FORMAT_RGB:
970 {
971 GLuint i, j;
972 const GLchan (*rowA)[3] = (const GLchan (*)[3]) srcRowA;
973 const GLchan (*rowB)[3] = (const GLchan (*)[3]) srcRowB;
974 GLchan (*dst)[3] = (GLchan (*)[3]) dstRow;
975 for (i = j = 0; i < dstWidth; i++, j+=2) {
976 dst[i][0] = (rowA[j][0] + rowA[j+1][0] +
977 rowB[j][0] + rowB[j+1][0]) >> 2;
978 dst[i][1] = (rowA[j][1] + rowA[j+1][1] +
979 rowB[j][1] + rowB[j+1][1]) >> 2;
980 dst[i][2] = (rowA[j][2] + rowA[j+1][2] +
981 rowB[j][2] + rowB[j+1][2]) >> 2;
982 }
983 }
984 return;
985 case MESA_FORMAT_ALPHA:
986 case MESA_FORMAT_LUMINANCE:
987 case MESA_FORMAT_INTENSITY:
988 case MESA_FORMAT_COLOR_INDEX:
989 {
990 GLuint i, j;
991 const GLchan *rowA = (const GLchan *) srcRowA;
992 const GLchan *rowB = (const GLchan *) srcRowB;
993 GLchan *dst = (GLchan *) dstRow;
994 for (i = j = 0; i < dstWidth; i++, j+=2) {
995 dst[i] = (rowA[j] + rowA[j+1] + rowB[j] + rowB[j+1]) >> 2;
996 }
997 }
998 return;
999 case MESA_FORMAT_LUMINANCE_ALPHA:
1000 {
1001 GLuint i, j;
1002 const GLchan (*rowA)[2] = (const GLchan (*)[2]) srcRowA;
1003 const GLchan (*rowB)[2] = (const GLchan (*)[2]) srcRowB;
1004 GLchan (*dst)[2] = (GLchan (*)[2]) dstRow;
1005 for (i = j = 0; i < dstWidth; i++, j+=2) {
1006 dst[i][0] = (rowA[j][0] + rowA[j+1][0] +
1007 rowB[j][0] + rowB[j+1][0]) >> 2;
1008 dst[i][1] = (rowA[j][1] + rowA[j+1][1] +
1009 rowB[j][1] + rowB[j+1][1]) >> 2;
1010 }
1011 }
1012 return;
1013 case MESA_FORMAT_DEPTH_COMPONENT:
1014 {
1015 GLuint i, j;
1016 const GLfloat *rowA = (const GLfloat *) srcRowA;
1017 const GLfloat *rowB = (const GLfloat *) srcRowB;
1018 GLfloat *dst = (GLfloat *) dstRow;
1019 for (i = j = 0; i < dstWidth; i++, j+=2) {
1020 dst[i] = (rowA[j] + rowA[j+1] + rowB[j] + rowB[j+1]) * 0.25F;
1021 }
1022 }
1023 return;
1024 /* Begin hardware formats */
1025 case MESA_FORMAT_RGBA8888:
1026 case MESA_FORMAT_ARGB8888:
1027 {
1028 GLuint i, j;
1029 const GLubyte (*rowA)[4] = (const GLubyte (*)[4]) srcRowA;
1030 const GLubyte (*rowB)[4] = (const GLubyte (*)[4]) srcRowB;
1031 GLubyte (*dst)[4] = (GLubyte (*)[4]) dstRow;
1032 for (i = j = 0; i < dstWidth; i++, j+=2) {
1033 dst[i][0] = (rowA[j][0] + rowA[j+1][0] +
1034 rowB[j][0] + rowB[j+1][0]) >> 2;
1035 dst[i][1] = (rowA[j][1] + rowA[j+1][1] +
1036 rowB[j][1] + rowB[j+1][1]) >> 2;
1037 dst[i][2] = (rowA[j][2] + rowA[j+1][2] +
1038 rowB[j][2] + rowB[j+1][2]) >> 2;
1039 dst[i][3] = (rowA[j][3] + rowA[j+1][3] +
1040 rowB[j][3] + rowB[j+1][3]) >> 2;
1041 }
1042 }
1043 return;
1044 case MESA_FORMAT_RGB888:
1045 {
1046 GLuint i, j;
1047 const GLubyte (*rowA)[3] = (const GLubyte (*)[3]) srcRowA;
1048 const GLubyte (*rowB)[3] = (const GLubyte (*)[3]) srcRowB;
1049 GLubyte (*dst)[3] = (GLubyte (*)[3]) dstRow;
1050 for (i = j = 0; i < dstWidth; i++, j+=2) {
1051 dst[i][0] = (rowA[j][0] + rowA[j+1][0] +
1052 rowB[j][0] + rowB[j+1][0]) >> 2;
1053 dst[i][1] = (rowA[j][1] + rowA[j+1][1] +
1054 rowB[j][1] + rowB[j+1][1]) >> 2;
1055 dst[i][2] = (rowA[j][2] + rowA[j+1][2] +
1056 rowB[j][2] + rowB[j+1][2]) >> 2;
1057 }
1058 }
1059 return;
1060 case MESA_FORMAT_RGB565:
1061 {
1062 GLuint i, j;
1063 const GLushort *rowA = (const GLushort *) srcRowA;
1064 const GLushort *rowB = (const GLushort *) srcRowB;
1065 GLushort *dst = (GLushort *) dstRow;
1066 for (i = j = 0; i < dstWidth; i++, j+=2) {
1067 const GLint rowAr0 = rowA[j] & 0x1f;
1068 const GLint rowAr1 = rowA[j+1] & 0x1f;
1069 const GLint rowBr0 = rowB[j] & 0x1f;
1070 const GLint rowBr1 = rowB[j+1] & 0x1f;
1071 const GLint rowAg0 = (rowA[j] >> 5) & 0x3f;
1072 const GLint rowAg1 = (rowA[j+1] >> 5) & 0x3f;
1073 const GLint rowBg0 = (rowB[j] >> 5) & 0x3f;
1074 const GLint rowBg1 = (rowB[j+1] >> 5) & 0x3f;
1075 const GLint rowAb0 = (rowA[j] >> 11) & 0x1f;
1076 const GLint rowAb1 = (rowA[j+1] >> 11) & 0x1f;
1077 const GLint rowBb0 = (rowB[j] >> 11) & 0x1f;
1078 const GLint rowBb1 = (rowB[j+1] >> 11) & 0x1f;
1079 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 4;
1080 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 4;
1081 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 4;
1082 dst[i] = (blue << 11) | (green << 5) | red;
1083 }
1084 }
1085 return;
1086 case MESA_FORMAT_ARGB4444:
1087 {
1088 GLuint i, j;
1089 const GLushort *rowA = (const GLushort *) srcRowA;
1090 const GLushort *rowB = (const GLushort *) srcRowB;
1091 GLushort *dst = (GLushort *) dstRow;
1092 for (i = j = 0; i < dstWidth; i++, j+=2) {
1093 const GLint rowAr0 = rowA[j] & 0xf;
1094 const GLint rowAr1 = rowA[j+1] & 0xf;
1095 const GLint rowBr0 = rowB[j] & 0xf;
1096 const GLint rowBr1 = rowB[j+1] & 0xf;
1097 const GLint rowAg0 = (rowA[j] >> 4) & 0xf;
1098 const GLint rowAg1 = (rowA[j+1] >> 4) & 0xf;
1099 const GLint rowBg0 = (rowB[j] >> 4) & 0xf;
1100 const GLint rowBg1 = (rowB[j+1] >> 4) & 0xf;
1101 const GLint rowAb0 = (rowA[j] >> 8) & 0xf;
1102 const GLint rowAb1 = (rowA[j+1] >> 8) & 0xf;
1103 const GLint rowBb0 = (rowB[j] >> 8) & 0xf;
1104 const GLint rowBb1 = (rowB[j+1] >> 8) & 0xf;
1105 const GLint rowAa0 = (rowA[j] >> 12) & 0xf;
1106 const GLint rowAa1 = (rowA[j+1] >> 12) & 0xf;
1107 const GLint rowBa0 = (rowB[j] >> 12) & 0xf;
1108 const GLint rowBa1 = (rowB[j+1] >> 12) & 0xf;
1109 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 4;
1110 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 4;
1111 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 4;
1112 const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 4;
1113 dst[i] = (alpha << 12) | (blue << 8) | (green << 4) | red;
1114 }
1115 }
1116 return;
1117 case MESA_FORMAT_ARGB1555:
1118 {
1119 GLuint i, j;
1120 const GLushort *rowA = (const GLushort *) srcRowA;
1121 const GLushort *rowB = (const GLushort *) srcRowB;
1122 GLushort *dst = (GLushort *) dstRow;
1123 for (i = j = 0; i < dstWidth; i++, j+=2) {
1124 const GLint rowAr0 = rowA[j] & 0x1f;
1125 const GLint rowAr1 = rowA[j+1] & 0x1f;
1126 const GLint rowBr0 = rowB[j] & 0x1f;
1127 const GLint rowBr1 = rowB[j+1] & 0xf;
1128 const GLint rowAg0 = (rowA[j] >> 5) & 0x1f;
1129 const GLint rowAg1 = (rowA[j+1] >> 5) & 0x1f;
1130 const GLint rowBg0 = (rowB[j] >> 5) & 0x1f;
1131 const GLint rowBg1 = (rowB[j+1] >> 5) & 0x1f;
1132 const GLint rowAb0 = (rowA[j] >> 10) & 0x1f;
1133 const GLint rowAb1 = (rowA[j+1] >> 10) & 0x1f;
1134 const GLint rowBb0 = (rowB[j] >> 10) & 0x1f;
1135 const GLint rowBb1 = (rowB[j+1] >> 10) & 0x1f;
1136 const GLint rowAa0 = (rowA[j] >> 15) & 0x1;
1137 const GLint rowAa1 = (rowA[j+1] >> 15) & 0x1;
1138 const GLint rowBa0 = (rowB[j] >> 15) & 0x1;
1139 const GLint rowBa1 = (rowB[j+1] >> 15) & 0x1;
1140 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 4;
1141 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 4;
1142 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 4;
1143 const GLint alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 4;
1144 dst[i] = (alpha << 15) | (blue << 10) | (green << 5) | red;
1145 }
1146 }
1147 return;
1148 case MESA_FORMAT_AL88:
1149 {
1150 GLuint i, j;
1151 const GLubyte (*rowA)[2] = (const GLubyte (*)[2]) srcRowA;
1152 const GLubyte (*rowB)[2] = (const GLubyte (*)[2]) srcRowB;
1153 GLubyte (*dst)[2] = (GLubyte (*)[2]) dstRow;
1154 for (i = j = 0; i < dstWidth; i++, j+=2) {
1155 dst[i][0] = (rowA[j][0] + rowA[j+1][0] +
1156 rowB[j][0] + rowB[j+1][0]) >> 2;
1157 dst[i][1] = (rowA[j][1] + rowA[j+1][1] +
1158 rowB[j][1] + rowB[j+1][1]) >> 2;
1159 }
1160 }
1161 return;
1162 case MESA_FORMAT_RGB332:
1163 {
1164 GLuint i, j;
1165 const GLubyte *rowA = (const GLubyte *) srcRowA;
1166 const GLubyte *rowB = (const GLubyte *) srcRowB;
1167 GLubyte *dst = (GLubyte *) dstRow;
1168 for (i = j = 0; i < dstWidth; i++, j+=2) {
1169 const GLint rowAr0 = rowA[j] & 0x3;
1170 const GLint rowAr1 = rowA[j+1] & 0x3;
1171 const GLint rowBr0 = rowB[j] & 0x3;
1172 const GLint rowBr1 = rowB[j+1] & 0x3;
1173 const GLint rowAg0 = (rowA[j] >> 2) & 0x7;
1174 const GLint rowAg1 = (rowA[j+1] >> 2) & 0x7;
1175 const GLint rowBg0 = (rowB[j] >> 2) & 0x7;
1176 const GLint rowBg1 = (rowB[j+1] >> 2) & 0x7;
1177 const GLint rowAb0 = (rowA[j] >> 5) & 0x7;
1178 const GLint rowAb1 = (rowA[j+1] >> 5) & 0x7;
1179 const GLint rowBb0 = (rowB[j] >> 5) & 0x7;
1180 const GLint rowBb1 = (rowB[j+1] >> 5) & 0x7;
1181 const GLint red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 4;
1182 const GLint green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 4;
1183 const GLint blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 4;
1184 dst[i] = (blue << 5) | (green << 2) | red;
1185 }
1186 }
1187 return;
1188 case MESA_FORMAT_A8:
1189 case MESA_FORMAT_L8:
1190 case MESA_FORMAT_I8:
1191 case MESA_FORMAT_CI8:
1192 {
1193 GLuint i, j;
1194 const GLubyte *rowA = (const GLubyte *) srcRowA;
1195 const GLubyte *rowB = (const GLubyte *) srcRowB;
1196 GLubyte *dst = (GLubyte *) dstRow;
1197 for (i = j = 0; i < dstWidth; i++, j+=2) {
1198 dst[i] = (rowA[j] + rowA[j+1] + rowB[j] + rowB[j+1]) >> 2;
1199 }
1200 }
1201 return;
1202 default:
1203 _mesa_problem(NULL, "bad format in do_row()");
1204 }
1205 }
1206
1207
1208
1209
1210 static void
1211 make_1d_mipmap(const struct gl_texture_format *format, GLint border,
1212 GLint srcWidth, const GLubyte *srcPtr,
1213 GLint dstWidth, GLubyte *dstPtr)
1214 {
1215 const GLint bpt = format->TexelBytes;
1216 const GLubyte *src;
1217 GLubyte *dst;
1218
1219 /* skip the border pixel, if any */
1220 src = srcPtr + border * bpt;
1221 dst = dstPtr + border * bpt;
1222
1223 /* we just duplicate the input row, kind of hack, saves code */
1224 do_row(format, dstWidth - 2 * border, src, src, dst);
1225
1226 if (border) {
1227 /* copy left-most pixel from source */
1228 MEMCPY(dstPtr, srcPtr, bpt);
1229 /* copy right-most pixel from source */
1230 MEMCPY(dstPtr + (dstWidth - 1) * bpt,
1231 srcPtr + (srcWidth - 1) * bpt,
1232 bpt);
1233 }
1234 }
1235
1236
1237 static void
1238 make_2d_mipmap(const struct gl_texture_format *format, GLint border,
1239 GLint srcWidth, GLint srcHeight, const GLubyte *srcPtr,
1240 GLint dstWidth, GLint dstHeight, GLubyte *dstPtr)
1241 {
1242 const GLint bpt = format->TexelBytes;
1243 const GLint srcRowStride = bpt * srcWidth;
1244 const GLint dstRowStride = bpt * dstWidth;
1245 const GLubyte *srcA, *srcB;
1246 GLubyte *dst;
1247 GLint row;
1248
1249 /* Compute src and dst pointers, skipping any border */
1250 srcA = srcPtr + border * ((srcWidth + 1) * bpt);
1251 if (srcHeight > 1)
1252 srcB = srcA + srcRowStride;
1253 else
1254 srcB = srcA;
1255 dst = dstPtr + border * ((dstWidth + 1) * bpt);
1256
1257 for (row = 0; row < dstHeight - 2 * border; row++) {
1258 do_row(format, dstWidth - 2 * border, srcA, srcB, dst);
1259 srcA += 2 * srcRowStride;
1260 srcB += 2 * srcRowStride;
1261 dst += dstRowStride;
1262 }
1263
1264 /* This is ugly but probably won't be used much */
1265 if (border > 0) {
1266 /* fill in dest border */
1267 /* lower-left border pixel */
1268 MEMCPY(dstPtr, srcPtr, bpt);
1269 /* lower-right border pixel */
1270 MEMCPY(dstPtr + (dstWidth - 1) * bpt,
1271 srcPtr + (srcWidth - 1) * bpt, bpt);
1272 /* upper-left border pixel */
1273 MEMCPY(dstPtr + dstWidth * (dstHeight - 1) * bpt,
1274 srcPtr + srcWidth * (srcHeight - 1) * bpt, bpt);
1275 /* upper-right border pixel */
1276 MEMCPY(dstPtr + (dstWidth * dstHeight - 1) * bpt,
1277 srcPtr + (srcWidth * srcHeight - 1) * bpt, bpt);
1278 /* lower border */
1279 do_row(format, dstWidth - 2 * border,
1280 srcPtr + bpt, srcPtr + bpt, dstPtr + bpt);
1281 /* upper border */
1282 do_row(format, dstWidth - 2 * border,
1283 srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
1284 srcPtr + (srcWidth * (srcHeight - 1) + 1) * bpt,
1285 dstPtr + (dstWidth * (dstHeight - 1) + 1) * bpt);
1286 /* left and right borders */
1287 for (row = 0; row < dstHeight - 2 * border; row += 2) {
1288 GLubyte tempPixel[32];
1289 GLint srcOffset;
1290 srcOffset = (srcWidth * (row * 2 + 1)) * bpt;
1291 MEMCPY(tempPixel, srcPtr + srcOffset, bpt);
1292 srcOffset = (srcWidth * (row * 2 + 2)) * bpt;
1293 MEMCPY(tempPixel + bpt, srcPtr + srcOffset, bpt);
1294 do_row(format, 1, tempPixel, tempPixel,
1295 dstPtr + (dstWidth * row + 1) * bpt);
1296 srcOffset = (srcWidth * (row * 2 + 1) + srcWidth - 1) * bpt;
1297 MEMCPY(tempPixel, srcPtr + srcOffset, bpt);
1298 srcOffset = (srcWidth * (row * 2 + 2) + srcWidth - 1) * bpt;
1299 MEMCPY(tempPixel, srcPtr + srcOffset, bpt);
1300 do_row(format, 1, tempPixel, tempPixel,
1301 dstPtr + (dstWidth * row + 1 + dstWidth - 1) * bpt);
1302 }
1303 }
1304 }
1305
1306
1307 static void
1308 make_3d_mipmap(const struct gl_texture_format *format, GLint border,
1309 GLint srcWidth, GLint srcHeight, GLint srcDepth,
1310 const GLubyte *srcPtr,
1311 GLint dstWidth, GLint dstHeight, GLint dstDepth,
1312 GLubyte *dstPtr)
1313 {
1314 GLvoid *tmpRowA = MALLOC(dstWidth * format->TexelBytes);
1315 GLvoid *tmpRowB = MALLOC(dstWidth * format->TexelBytes);
1316 const GLubyte *srcA, *srcB, *srcC, *srcD;
1317 GLint img, row;
1318
1319 if (!tmpRowA || !tmpRowB) {
1320 if (tmpRowA)
1321 FREE(tmpRowA);
1322 return;
1323 }
1324
1325 /*
1326 * XXX lots of work to do here yet
1327 */
1328
1329 for (img = 0; img < dstDepth - 2 * border; img++) {
1330
1331 for (row = 0; row < dstHeight - 2 * border; row++) {
1332 do_row(format, dstWidth - 2 * border, srcA, srcB, tmpRowA);
1333 do_row(format, dstWidth - 2 * border, srcC, srcD, tmpRowB);
1334
1335
1336 }
1337 }
1338
1339 FREE(tmpRowA);
1340 FREE(tmpRowB);
1341 }
1342
1343
1344 /*
1345 * For GL_SGIX_generate_mipmap:
1346 * Generate a complete set of mipmaps from texObj's base-level image.
1347 * Stop at texObj's MaxLevel or when we get to the 1x1 texture.
1348 */
1349 void
1350 _mesa_generate_mipmap(GLcontext *ctx,
1351 const struct gl_texture_unit *texUnit,
1352 struct gl_texture_object *texObj)
1353 {
1354 const GLenum targets1D[] = { GL_TEXTURE_1D, 0 };
1355 const GLenum targets2D[] = { GL_TEXTURE_2D, 0 };
1356 const GLenum targets3D[] = { GL_TEXTURE_3D, 0 };
1357 const GLenum targetsCube[] = { GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB,
1358 GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB,
1359 GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB,
1360 GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB,
1361 GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB,
1362 GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB,
1363 0 };
1364 const GLenum *targets;
1365 GLuint level;
1366
1367 ASSERT(texObj);
1368 ASSERT(texObj->Image[texObj->BaseLevel]);
1369
1370 switch (texObj->Dimensions) {
1371 case 1:
1372 targets = targets1D;
1373 break;
1374 case 2:
1375 targets = targets2D;
1376 break;
1377 case 3:
1378 targets = targets3D;
1379 break;
1380 case 6:
1381 targets = targetsCube;
1382 break;
1383 default:
1384 _mesa_problem(ctx,
1385 "Bad texture object dimension in _mesa_generate_mipmaps");
1386 return;
1387 }
1388
1389 for (level = texObj->BaseLevel; level < texObj->MaxLevel
1390 && level < ctx->Const.MaxTextureLevels; level++) {
1391 /* generate level+1 from level */
1392 const struct gl_texture_image *srcImage;
1393 struct gl_texture_image *dstImage;
1394 GLint srcWidth, srcHeight, srcDepth;
1395 GLint dstWidth, dstHeight, dstDepth;
1396 GLint border, bytesPerTexel;
1397 GLint t;
1398
1399 srcImage = texObj->Image[level];
1400 ASSERT(srcImage);
1401 srcWidth = srcImage->Width;
1402 srcHeight = srcImage->Height;
1403 srcDepth = srcImage->Depth;
1404 border = srcImage->Border;
1405 bytesPerTexel = srcImage->TexFormat->TexelBytes;
1406
1407 /* compute next (level+1) image size */
1408 if (srcWidth - 2 * border > 1) {
1409 dstWidth = (srcWidth - 2 * border) / 2 + 2 * border;
1410 }
1411 else {
1412 dstWidth = srcWidth; /* can't go smaller */
1413 }
1414 if (srcHeight - 2 * border > 1) {
1415 dstHeight = (srcHeight - 2 * border) / 2 + 2 * border;
1416 }
1417 else {
1418 dstHeight = srcHeight; /* can't go smaller */
1419 }
1420 if (srcDepth - 2 * border > 1) {
1421 dstDepth = (srcDepth - 2 * border) / 2 + 2 * border;
1422 }
1423 else {
1424 dstDepth = srcDepth; /* can't go smaller */
1425 }
1426
1427 if (dstWidth == srcWidth &&
1428 dstHeight == srcHeight &&
1429 dstDepth == srcDepth) {
1430 /* all done */
1431 return;
1432 }
1433
1434 /* Need this loop just because of cubemaps */
1435 for (t = 0; targets[t]; t++) {
1436 ASSERT(t < 6);
1437
1438 dstImage = _mesa_select_tex_image(ctx, texUnit, targets[t], level+1);
1439 if (!dstImage) {
1440 dstImage = _mesa_alloc_texture_image();
1441 if (!dstImage) {
1442 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
1443 return;
1444 }
1445 _mesa_set_tex_image(texObj, targets[t], level + 1, dstImage);
1446 }
1447
1448 /* Free old image data */
1449 if (dstImage->Data)
1450 FREE(dstImage->Data);
1451
1452 /* initialize new image */
1453 _mesa_init_teximage_fields(ctx, dstImage, dstWidth, dstHeight,
1454 dstDepth, border, srcImage->Format);
1455 dstImage->DriverData = NULL;
1456 dstImage->TexFormat = srcImage->TexFormat;
1457 dstImage->FetchTexel = srcImage->FetchTexel;
1458
1459 ASSERT(dstWidth * dstHeight * dstDepth * bytesPerTexel > 0);
1460
1461 /* alloc new image buffer */
1462 dstImage->Data = MALLOC(dstWidth * dstHeight * dstDepth
1463 * bytesPerTexel);
1464 if (!dstImage->Data) {
1465 _mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
1466 return;
1467 }
1468
1469 /*
1470 * We use simple 2x2 averaging to compute the next mipmap level.
1471 */
1472 switch (texObj->Dimensions) {
1473 case 1:
1474 make_1d_mipmap(srcImage->TexFormat, border,
1475 srcWidth, (const GLubyte *) srcImage->Data,
1476 dstWidth, (GLubyte *) dstImage->Data);
1477 break;
1478 case 2:
1479 case 6:
1480 make_2d_mipmap(srcImage->TexFormat, border,
1481 srcWidth, srcHeight, (const GLubyte *) srcImage->Data,
1482 dstWidth, dstHeight, (GLubyte *) dstImage->Data);
1483 break;
1484 case 3:
1485 make_3d_mipmap(srcImage->TexFormat, border,
1486 srcWidth, srcHeight, srcDepth, (const GLubyte *) srcImage->Data,
1487 dstWidth, dstHeight, dstDepth, (GLubyte *) dstImage->Data);
1488 break;
1489 default:
1490 _mesa_problem(ctx, "bad dimensions in _mesa_generate_mipmaps");
1491 return;
1492 }
1493 } /* loop over tex image targets */
1494 } /* loop over tex levels */
1495 }