Major rework of tnl module
[mesa.git] / src / mesa / main / teximage.c
1 /* $Id: teximage.c,v 1.69 2000/12/26 05:09:29 keithw Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2000 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 #ifdef PC_HEADER
29 #include "all.h"
30 #else
31 #include "glheader.h"
32 #include "context.h"
33 #include "convolve.h"
34 #include "image.h"
35 #include "macros.h"
36 #include "mem.h"
37 #include "mmath.h"
38 #include "state.h"
39 #include "teximage.h"
40 #include "texstate.h"
41 #include "mtypes.h"
42 #include "swrast/s_span.h" /* XXX SWRAST hack */
43 #endif
44
45
46 /*
47 * NOTES:
48 *
49 * Mesa's native texture datatype is GLchan. Native formats are
50 * GL_ALPHA, GL_LUMINANCE, GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, GL_RGBA,
51 * and GL_COLOR_INDEX.
52 * Device drivers are free to implement any internal format they want.
53 */
54
55
56 #ifdef DEBUG
57 static void PrintTexture(const struct gl_texture_image *img)
58 {
59 int i, j, c;
60 GLchan *data = img->Data;
61
62 if (!data) {
63 printf("No texture data\n");
64 return;
65 }
66
67 switch (img->Format) {
68 case GL_ALPHA:
69 case GL_LUMINANCE:
70 case GL_INTENSITY:
71 case GL_COLOR_INDEX:
72 c = 1;
73 break;
74 case GL_LUMINANCE_ALPHA:
75 c = 2;
76 break;
77 case GL_RGB:
78 c = 3;
79 break;
80 case GL_RGBA:
81 c = 4;
82 break;
83 default:
84 gl_problem(NULL, "error in PrintTexture\n");
85 return;
86 }
87
88
89 for (i = 0; i < img->Height; i++) {
90 for (j = 0; j < img->Width; j++) {
91 if (c==1)
92 printf("%02x ", data[0]);
93 else if (c==2)
94 printf("%02x%02x ", data[0], data[1]);
95 else if (c==3)
96 printf("%02x%02x%02x ", data[0], data[1], data[2]);
97 else if (c==4)
98 printf("%02x%02x%02x%02x ", data[0], data[1], data[2], data[3]);
99 data += c;
100 }
101 printf("\n");
102 }
103 }
104 #endif
105
106
107
108 /*
109 * Compute log base 2 of n.
110 * If n isn't an exact power of two return -1.
111 * If n<0 return -1.
112 */
113 static int
114 logbase2( int n )
115 {
116 GLint i = 1;
117 GLint log2 = 0;
118
119 if (n<0) {
120 return -1;
121 }
122
123 while ( n > i ) {
124 i *= 2;
125 log2++;
126 }
127 if (i != n) {
128 return -1;
129 }
130 else {
131 return log2;
132 }
133 }
134
135
136
137 /*
138 * Given an internal texture format enum or 1, 2, 3, 4 return the
139 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
140 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA.
141 * Return -1 if invalid enum.
142 */
143 GLint
144 _mesa_base_tex_format( GLcontext *ctx, GLint format )
145 {
146 /*
147 * Ask the driver for the base format, if it doesn't
148 * know, it will return -1;
149 */
150 if (ctx->Driver.BaseCompressedTexFormat) {
151 GLint ifmt = (*ctx->Driver.BaseCompressedTexFormat)(ctx, format);
152 if (ifmt >= 0) {
153 return ifmt;
154 }
155 }
156 switch (format) {
157 case GL_ALPHA:
158 case GL_ALPHA4:
159 case GL_ALPHA8:
160 case GL_ALPHA12:
161 case GL_ALPHA16:
162 return GL_ALPHA;
163 case 1:
164 case GL_LUMINANCE:
165 case GL_LUMINANCE4:
166 case GL_LUMINANCE8:
167 case GL_LUMINANCE12:
168 case GL_LUMINANCE16:
169 return GL_LUMINANCE;
170 case 2:
171 case GL_LUMINANCE_ALPHA:
172 case GL_LUMINANCE4_ALPHA4:
173 case GL_LUMINANCE6_ALPHA2:
174 case GL_LUMINANCE8_ALPHA8:
175 case GL_LUMINANCE12_ALPHA4:
176 case GL_LUMINANCE12_ALPHA12:
177 case GL_LUMINANCE16_ALPHA16:
178 return GL_LUMINANCE_ALPHA;
179 case GL_INTENSITY:
180 case GL_INTENSITY4:
181 case GL_INTENSITY8:
182 case GL_INTENSITY12:
183 case GL_INTENSITY16:
184 return GL_INTENSITY;
185 case 3:
186 case GL_RGB:
187 case GL_R3_G3_B2:
188 case GL_RGB4:
189 case GL_RGB5:
190 case GL_RGB8:
191 case GL_RGB10:
192 case GL_RGB12:
193 case GL_RGB16:
194 return GL_RGB;
195 case 4:
196 case GL_RGBA:
197 case GL_RGBA2:
198 case GL_RGBA4:
199 case GL_RGB5_A1:
200 case GL_RGBA8:
201 case GL_RGB10_A2:
202 case GL_RGBA12:
203 case GL_RGBA16:
204 return GL_RGBA;
205 case GL_COLOR_INDEX:
206 case GL_COLOR_INDEX1_EXT:
207 case GL_COLOR_INDEX2_EXT:
208 case GL_COLOR_INDEX4_EXT:
209 case GL_COLOR_INDEX8_EXT:
210 case GL_COLOR_INDEX12_EXT:
211 case GL_COLOR_INDEX16_EXT:
212 return GL_COLOR_INDEX;
213 default:
214 return -1; /* error */
215 }
216 }
217
218
219
220 /*
221 * Given an internal texture format enum or 1, 2, 3, 4 return the
222 * corresponding _base_ internal format: GL_ALPHA, GL_LUMINANCE,
223 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA. Return the
224 * number of components for the format. Return -1 if invalid enum.
225 */
226 static GLint
227 components_in_intformat( GLint format )
228 {
229 switch (format) {
230 case GL_ALPHA:
231 case GL_ALPHA4:
232 case GL_ALPHA8:
233 case GL_ALPHA12:
234 case GL_ALPHA16:
235 return 1;
236 case 1:
237 case GL_LUMINANCE:
238 case GL_LUMINANCE4:
239 case GL_LUMINANCE8:
240 case GL_LUMINANCE12:
241 case GL_LUMINANCE16:
242 return 1;
243 case 2:
244 case GL_LUMINANCE_ALPHA:
245 case GL_LUMINANCE4_ALPHA4:
246 case GL_LUMINANCE6_ALPHA2:
247 case GL_LUMINANCE8_ALPHA8:
248 case GL_LUMINANCE12_ALPHA4:
249 case GL_LUMINANCE12_ALPHA12:
250 case GL_LUMINANCE16_ALPHA16:
251 return 2;
252 case GL_INTENSITY:
253 case GL_INTENSITY4:
254 case GL_INTENSITY8:
255 case GL_INTENSITY12:
256 case GL_INTENSITY16:
257 return 1;
258 case 3:
259 case GL_RGB:
260 case GL_R3_G3_B2:
261 case GL_RGB4:
262 case GL_RGB5:
263 case GL_RGB8:
264 case GL_RGB10:
265 case GL_RGB12:
266 case GL_RGB16:
267 return 3;
268 case 4:
269 case GL_RGBA:
270 case GL_RGBA2:
271 case GL_RGBA4:
272 case GL_RGB5_A1:
273 case GL_RGBA8:
274 case GL_RGB10_A2:
275 case GL_RGBA12:
276 case GL_RGBA16:
277 return 4;
278 case GL_COLOR_INDEX:
279 case GL_COLOR_INDEX1_EXT:
280 case GL_COLOR_INDEX2_EXT:
281 case GL_COLOR_INDEX4_EXT:
282 case GL_COLOR_INDEX8_EXT:
283 case GL_COLOR_INDEX12_EXT:
284 case GL_COLOR_INDEX16_EXT:
285 return 1;
286 default:
287 return -1; /* error */
288 }
289 }
290
291
292 /*
293 * Return GL_TRUE if internalFormat is a compressed format, return GL_FALSE
294 * otherwise.
295 */
296 static GLboolean
297 is_compressed_format(GLcontext *ctx, GLenum internalFormat)
298 {
299 if (ctx->Driver.IsCompressedFormat) {
300 return (*ctx->Driver.IsCompressedFormat)(ctx, internalFormat);
301 }
302 return GL_FALSE;
303 }
304
305
306
307 /*
308 * Examine the texImage->Format field and set the Red, Green, Blue, etc
309 * texel component sizes to default values.
310 * These fields are set only here by core Mesa but device drivers may
311 * overwritting these fields to indicate true texel resolution.
312 */
313 static void
314 set_teximage_component_sizes( struct gl_texture_image *texImage )
315 {
316 switch (texImage->Format) {
317 case GL_ALPHA:
318 texImage->RedBits = 0;
319 texImage->GreenBits = 0;
320 texImage->BlueBits = 0;
321 texImage->AlphaBits = 8;
322 texImage->IntensityBits = 0;
323 texImage->LuminanceBits = 0;
324 texImage->IndexBits = 0;
325 break;
326 case GL_LUMINANCE:
327 texImage->RedBits = 0;
328 texImage->GreenBits = 0;
329 texImage->BlueBits = 0;
330 texImage->AlphaBits = 0;
331 texImage->IntensityBits = 0;
332 texImage->LuminanceBits = 8;
333 texImage->IndexBits = 0;
334 break;
335 case GL_LUMINANCE_ALPHA:
336 texImage->RedBits = 0;
337 texImage->GreenBits = 0;
338 texImage->BlueBits = 0;
339 texImage->AlphaBits = 8;
340 texImage->IntensityBits = 0;
341 texImage->LuminanceBits = 8;
342 texImage->IndexBits = 0;
343 break;
344 case GL_INTENSITY:
345 texImage->RedBits = 0;
346 texImage->GreenBits = 0;
347 texImage->BlueBits = 0;
348 texImage->AlphaBits = 0;
349 texImage->IntensityBits = 8;
350 texImage->LuminanceBits = 0;
351 texImage->IndexBits = 0;
352 break;
353 case GL_RED:
354 texImage->RedBits = 8;
355 texImage->GreenBits = 0;
356 texImage->BlueBits = 0;
357 texImage->AlphaBits = 0;
358 texImage->IntensityBits = 0;
359 texImage->LuminanceBits = 0;
360 texImage->IndexBits = 0;
361 break;
362 case GL_GREEN:
363 texImage->RedBits = 0;
364 texImage->GreenBits = 8;
365 texImage->BlueBits = 0;
366 texImage->AlphaBits = 0;
367 texImage->IntensityBits = 0;
368 texImage->LuminanceBits = 0;
369 texImage->IndexBits = 0;
370 break;
371 case GL_BLUE:
372 texImage->RedBits = 0;
373 texImage->GreenBits = 0;
374 texImage->BlueBits = 8;
375 texImage->AlphaBits = 0;
376 texImage->IntensityBits = 0;
377 texImage->LuminanceBits = 0;
378 texImage->IndexBits = 0;
379 break;
380 case GL_RGB:
381 case GL_BGR:
382 texImage->RedBits = 8;
383 texImage->GreenBits = 8;
384 texImage->BlueBits = 8;
385 texImage->AlphaBits = 0;
386 texImage->IntensityBits = 0;
387 texImage->LuminanceBits = 0;
388 texImage->IndexBits = 0;
389 break;
390 case GL_RGBA:
391 case GL_BGRA:
392 case GL_ABGR_EXT:
393 texImage->RedBits = 8;
394 texImage->GreenBits = 8;
395 texImage->BlueBits = 8;
396 texImage->AlphaBits = 8;
397 texImage->IntensityBits = 0;
398 texImage->LuminanceBits = 0;
399 texImage->IndexBits = 0;
400 break;
401 case GL_COLOR_INDEX:
402 texImage->RedBits = 0;
403 texImage->GreenBits = 0;
404 texImage->BlueBits = 0;
405 texImage->AlphaBits = 0;
406 texImage->IntensityBits = 0;
407 texImage->LuminanceBits = 0;
408 texImage->IndexBits = 8;
409 break;
410 default:
411 gl_problem(NULL, "unexpected format in set_teximage_component_sizes");
412 }
413 }
414
415
416 static void
417 set_tex_image(struct gl_texture_object *tObj,
418 GLenum target, GLint level,
419 struct gl_texture_image *texImage)
420 {
421 ASSERT(tObj);
422 ASSERT(texImage);
423 switch (target) {
424 case GL_TEXTURE_2D:
425 tObj->Image[level] = texImage;
426 return;
427 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
428 tObj->Image[level] = texImage;
429 return;
430 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
431 tObj->NegX[level] = texImage;
432 return;
433 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
434 tObj->PosY[level] = texImage;
435 return;
436 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
437 tObj->NegY[level] = texImage;
438 return;
439 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
440 tObj->PosZ[level] = texImage;
441 return;
442 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
443 tObj->NegZ[level] = texImage;
444 return;
445 default:
446 gl_problem(NULL, "bad target in set_tex_image()");
447 return;
448 }
449 }
450
451
452 /*
453 * Return new gl_texture_image struct with all fields initialized to zero.
454 */
455 struct gl_texture_image *
456 _mesa_alloc_texture_image( void )
457 {
458 return CALLOC_STRUCT(gl_texture_image);
459 }
460
461
462
463 /*
464 * Initialize most fields of a gl_texture_image struct.
465 */
466 static void
467 init_texture_image( GLcontext *ctx,
468 struct gl_texture_image *img,
469 GLsizei width, GLsizei height, GLsizei depth,
470 GLint border, GLenum internalFormat )
471 {
472 ASSERT(img);
473 ASSERT(!img->Data);
474 img->Format = (GLenum) _mesa_base_tex_format(ctx, internalFormat);
475 set_teximage_component_sizes( img );
476 img->IntFormat = (GLenum) internalFormat;
477 img->Border = border;
478 img->Width = width;
479 img->Height = height;
480 img->Depth = depth;
481 img->WidthLog2 = logbase2(width - 2 * border);
482 if (height == 1) /* 1-D texture */
483 img->HeightLog2 = 0;
484 else
485 img->HeightLog2 = logbase2(height - 2 * border);
486 if (depth == 1) /* 2-D texture */
487 img->DepthLog2 = 0;
488 else
489 img->DepthLog2 = logbase2(depth - 2 * border);
490 img->Width2 = 1 << img->WidthLog2;
491 img->Height2 = 1 << img->HeightLog2;
492 img->Depth2 = 1 << img->DepthLog2;
493 img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2);
494 img->IsCompressed = is_compressed_format(ctx, internalFormat);
495 }
496
497
498
499 void
500 _mesa_free_texture_image( struct gl_texture_image *teximage )
501 {
502 if (teximage->Data) {
503 FREE( teximage->Data );
504 teximage->Data = NULL;
505 }
506 FREE( teximage );
507 }
508
509
510
511 /*
512 * Return number of bytes of storage needed to store a compressed texture
513 * image. Only the driver knows for sure. If the driver can't help us,
514 * we must return 0.
515 */
516 GLuint
517 _mesa_compressed_image_size(GLcontext *ctx,
518 GLenum internalFormat,
519 GLint numDimensions,
520 GLint width,
521 GLint height,
522 GLint depth)
523 {
524 if (ctx->Driver.CompressedImageSize) {
525 return (*ctx->Driver.CompressedImageSize)(ctx, internalFormat,
526 numDimensions,
527 width, height, depth);
528 }
529 else {
530 /* Shouldn't this be an internal error of some sort? */
531 return 0;
532 }
533 }
534
535
536
537 /*
538 * Given a texture unit and a texture target, return the corresponding
539 * texture object.
540 */
541 struct gl_texture_object *
542 _mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit,
543 GLenum target)
544 {
545 switch (target) {
546 case GL_TEXTURE_1D:
547 return texUnit->Current1D;
548 case GL_PROXY_TEXTURE_1D:
549 return ctx->Texture.Proxy1D;
550 case GL_TEXTURE_2D:
551 return texUnit->Current2D;
552 case GL_PROXY_TEXTURE_2D:
553 return ctx->Texture.Proxy2D;
554 case GL_TEXTURE_3D:
555 return texUnit->Current3D;
556 case GL_PROXY_TEXTURE_3D:
557 return ctx->Texture.Proxy3D;
558 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
559 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
560 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
561 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
562 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
563 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
564 return ctx->Extensions.ARB_texture_cube_map
565 ? texUnit->CurrentCubeMap : NULL;
566 case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
567 return ctx->Extensions.ARB_texture_cube_map
568 ? ctx->Texture.ProxyCubeMap : NULL;
569 default:
570 gl_problem(NULL, "bad target in _mesa_select_tex_object()");
571 return NULL;
572 }
573 }
574
575
576 /*
577 * Return the texture image struct which corresponds to target and level
578 * for the given texture unit.
579 */
580 struct gl_texture_image *
581 _mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_unit *texUnit,
582 GLenum target, GLint level)
583 {
584 ASSERT(texUnit);
585 switch (target) {
586 case GL_TEXTURE_1D:
587 return texUnit->Current1D->Image[level];
588 case GL_PROXY_TEXTURE_1D:
589 return ctx->Texture.Proxy1D->Image[level];
590 case GL_TEXTURE_2D:
591 return texUnit->Current2D->Image[level];
592 case GL_PROXY_TEXTURE_2D:
593 return ctx->Texture.Proxy2D->Image[level];
594 case GL_TEXTURE_3D:
595 return texUnit->Current3D->Image[level];
596 case GL_PROXY_TEXTURE_3D:
597 return ctx->Texture.Proxy3D->Image[level];
598 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
599 if (ctx->Extensions.ARB_texture_cube_map)
600 return texUnit->CurrentCubeMap->Image[level];
601 else
602 return NULL;
603 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
604 if (ctx->Extensions.ARB_texture_cube_map)
605 return texUnit->CurrentCubeMap->NegX[level];
606 else
607 return NULL;
608 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
609 if (ctx->Extensions.ARB_texture_cube_map)
610 return texUnit->CurrentCubeMap->PosY[level];
611 else
612 return NULL;
613 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
614 if (ctx->Extensions.ARB_texture_cube_map)
615 return texUnit->CurrentCubeMap->NegY[level];
616 else
617 return NULL;
618 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
619 if (ctx->Extensions.ARB_texture_cube_map)
620 return texUnit->CurrentCubeMap->PosZ[level];
621 else
622 return NULL;
623 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
624 if (ctx->Extensions.ARB_texture_cube_map)
625 return texUnit->CurrentCubeMap->NegZ[level];
626 else
627 return NULL;
628 case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
629 if (ctx->Extensions.ARB_texture_cube_map)
630 return ctx->Texture.ProxyCubeMap->Image[level];
631 else
632 return NULL;
633 default:
634 gl_problem(ctx, "bad target in _mesa_select_tex_image()");
635 return NULL;
636 }
637 }
638
639
640
641 /*
642 * Calling glTexImage and related functions when convolution is enabled
643 * with GL_REDUCE border mode causes some complications.
644 * The incoming image must be extra large so that the post-convolution
645 * image size is reduced to a power of two size (plus 2 * border).
646 * This function adjusts a texture width and height accordingly if
647 * convolution with GL_REDUCE is enabled.
648 */
649 static void
650 adjust_texture_size_for_convolution(const GLcontext *ctx, GLuint dimensions,
651 GLsizei *width, GLsizei *height)
652 {
653 if (ctx->Pixel.Convolution1DEnabled
654 && dimensions == 1
655 && ctx->Pixel.ConvolutionBorderMode[0] == GL_REDUCE) {
656 *width = *width - (MAX2(ctx->Convolution1D.Width, 1) - 1);
657 }
658 else if (ctx->Pixel.Convolution2DEnabled
659 && dimensions > 1
660 && ctx->Pixel.ConvolutionBorderMode[1] == GL_REDUCE) {
661 *width = *width - (MAX2(ctx->Convolution2D.Width, 1) - 1);
662 *height = *height - (MAX2(ctx->Convolution2D.Height, 1) - 1);
663 }
664 else if (ctx->Pixel.Separable2DEnabled
665 && dimensions > 1
666 && ctx->Pixel.ConvolutionBorderMode[2] == GL_REDUCE) {
667 *width = *width - (MAX2(ctx->Separable2D.Width, 1) - 1);
668 *height = *height - (MAX2(ctx->Separable2D.Height, 1) - 1);
669 }
670 }
671
672
673
674 /*
675 * This function is used to move user image data into a texture image.
676 * We handle full texture images and subtexture images. We also take
677 * care of all image transfer operations here, including convolution.
678 * Input:
679 * dstXoffset, dstYoffset, dstZoffset - offsets in pixels
680 * dstRowStride, dstImageStride - strides in GLchan's
681 */
682 static void
683 fill_texture_image( GLcontext *ctx, GLuint dimensions,
684 GLenum texFormat, GLchan *texAddr,
685 GLint srcWidth, GLint srcHeight, GLint srcDepth,
686 GLint dstXoffset, GLint dstYoffset, GLint dstZoffset,
687 GLint dstRowStride, GLint dstImageStride,
688 GLenum srcFormat, GLenum srcType, const GLvoid *srcAddr,
689 const struct gl_pixelstore_attrib *srcPacking)
690 {
691 GLint texComponents;
692
693 ASSERT(ctx);
694 ASSERT(dimensions >= 1 && dimensions <= 3);
695 ASSERT(texAddr);
696 ASSERT(srcWidth >= 1);
697 ASSERT(srcHeight >= 1);
698 ASSERT(srcDepth >= 1);
699 ASSERT(dstXoffset >= 0);
700 ASSERT(dstYoffset >= 0);
701 ASSERT(dstZoffset >= 0);
702 ASSERT(dstRowStride >= 0);
703 ASSERT(dstImageStride >= 0);
704 ASSERT(srcAddr);
705 ASSERT(srcPacking);
706
707 texComponents = components_in_intformat(texFormat);
708
709 /* try common 2D texture cases first */
710 if (!ctx->_ImageTransferState && dimensions == 2
711 && srcType == GL_UNSIGNED_BYTE) {
712
713 if (srcFormat == texFormat) {
714 /* This will cover the common GL_RGB, GL_RGBA, GL_ALPHA,
715 * GL_LUMINANCE_ALPHA, etc. texture formats. Use memcpy().
716 */
717 const GLchan *src = (const GLchan *) _mesa_image_address(
718 srcPacking, srcAddr, srcWidth, srcHeight,
719 srcFormat, srcType, 0, 0, 0);
720 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
721 srcWidth, srcFormat, srcType);
722 const GLint widthInBytes = srcWidth * texComponents * sizeof(GLchan);
723 GLchan *dst = texAddr + dstYoffset * dstRowStride
724 + dstXoffset * texComponents;
725 if (srcRowStride == widthInBytes && dstRowStride == widthInBytes) {
726 MEMCPY(dst, src, srcHeight * widthInBytes);
727 }
728 else {
729 GLint i;
730 for (i = 0; i < srcHeight; i++) {
731 MEMCPY(dst, src, widthInBytes);
732 src += srcRowStride;
733 dst += dstRowStride;
734 }
735 }
736 return; /* all done */
737 }
738 else if (srcFormat == GL_RGBA && texFormat == GL_RGB) {
739 /* commonly used by Quake */
740 const GLchan *src = (const GLchan *) _mesa_image_address(
741 srcPacking, srcAddr, srcWidth, srcHeight,
742 srcFormat, srcType, 0, 0, 0);
743 const GLint srcRowStride = _mesa_image_row_stride(srcPacking,
744 srcWidth, srcFormat, srcType);
745 GLchan *dst = texAddr + dstYoffset * dstRowStride
746 + dstXoffset * texComponents;
747 GLint i, j;
748 for (i = 0; i < srcHeight; i++) {
749 const GLchan *s = src;
750 GLchan *d = dst;
751 for (j = 0; j < srcWidth; j++) {
752 *d++ = *s++; /*red*/
753 *d++ = *s++; /*green*/
754 *d++ = *s++; /*blue*/
755 s++; /*alpha*/
756 }
757 src += srcRowStride;
758 dst += dstRowStride;
759 }
760 return; /* all done */
761 }
762 }
763
764 /*
765 * General case solutions
766 */
767 if (texFormat == GL_COLOR_INDEX) {
768 /* color index texture */
769 const GLenum texType = GL_UNSIGNED_BYTE;
770 GLint img, row;
771 GLchan *dest = texAddr + dstZoffset * dstImageStride
772 + dstYoffset * dstRowStride
773 + dstXoffset * texComponents;
774 for (img = 0; img < srcDepth; img++) {
775 GLchan *destRow = dest;
776 for (row = 0; row < srcHeight; row++) {
777 const GLvoid *src = _mesa_image_address(srcPacking,
778 srcAddr, srcWidth, srcHeight, srcFormat, srcType, img, row, 0);
779 _mesa_unpack_index_span(ctx, srcWidth, texType, destRow,
780 srcType, src, srcPacking,
781 ctx->_ImageTransferState);
782 destRow += dstRowStride;
783 }
784 dest += dstImageStride;
785 }
786 }
787 else {
788 /* regular, color texture */
789 if ((dimensions == 1 && ctx->Pixel.Convolution1DEnabled) ||
790 (dimensions >= 2 && ctx->Pixel.Convolution2DEnabled) ||
791 (dimensions >= 2 && ctx->Pixel.Separable2DEnabled)) {
792 /*
793 * Fill texture image with convolution
794 */
795 GLint img, row;
796 GLint convWidth = srcWidth, convHeight = srcHeight;
797 GLfloat *tmpImage, *convImage;
798 tmpImage = (GLfloat *) MALLOC(srcWidth * srcHeight * 4 * sizeof(GLfloat));
799 if (!tmpImage) {
800 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
801 return;
802 }
803 convImage = (GLfloat *) MALLOC(srcWidth * srcHeight * 4 * sizeof(GLfloat));
804 if (!convImage) {
805 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
806 FREE(tmpImage);
807 return;
808 }
809
810 for (img = 0; img < srcDepth; img++) {
811 const GLfloat *srcf;
812 GLfloat *dstf = tmpImage;
813 GLchan *dest;
814
815 /* unpack and do transfer ops up to convolution */
816 for (row = 0; row < srcHeight; row++) {
817 const GLvoid *src = _mesa_image_address(srcPacking,
818 srcAddr, srcWidth, srcHeight,
819 srcFormat, srcType, img, row, 0);
820 _mesa_unpack_float_color_span(ctx, srcWidth, GL_RGBA, dstf,
821 srcFormat, srcType, src, srcPacking,
822 ctx->_ImageTransferState & IMAGE_PRE_CONVOLUTION_BITS,
823 GL_TRUE);
824 dstf += srcWidth * 4;
825 }
826
827 /* convolve */
828 if (dimensions == 1) {
829 ASSERT(ctx->Pixel.Convolution1DEnabled);
830 _mesa_convolve_1d_image(ctx, &convWidth, tmpImage, convImage);
831 }
832 else {
833 if (ctx->Pixel.Convolution2DEnabled) {
834 _mesa_convolve_2d_image(ctx, &convWidth, &convHeight,
835 tmpImage, convImage);
836 }
837 else {
838 ASSERT(ctx->Pixel.Separable2DEnabled);
839 _mesa_convolve_sep_image(ctx, &convWidth, &convHeight,
840 tmpImage, convImage);
841 }
842 }
843
844 /* packing and transfer ops after convolution */
845 srcf = convImage;
846 dest = texAddr + (dstZoffset + img) * dstImageStride
847 + dstYoffset * dstRowStride;
848 for (row = 0; row < convHeight; row++) {
849 _mesa_pack_float_rgba_span(ctx, convWidth,
850 (const GLfloat (*)[4]) srcf,
851 texFormat, GL_UNSIGNED_BYTE,
852 dest, &_mesa_native_packing,
853 ctx->_ImageTransferState
854 & IMAGE_POST_CONVOLUTION_BITS);
855 srcf += convWidth * 4;
856 dest += dstRowStride;
857 }
858 }
859
860 FREE(convImage);
861 FREE(tmpImage);
862 }
863 else {
864 /*
865 * no convolution
866 */
867 GLint img, row;
868 GLchan *dest = texAddr + dstZoffset * dstImageStride
869 + dstYoffset * dstRowStride
870 + dstXoffset * texComponents;
871 for (img = 0; img < srcDepth; img++) {
872 GLchan *destRow = dest;
873 for (row = 0; row < srcHeight; row++) {
874 const GLvoid *srcRow = _mesa_image_address(srcPacking,
875 srcAddr, srcWidth, srcHeight,
876 srcFormat, srcType, img, row, 0);
877 _mesa_unpack_chan_color_span(ctx, srcWidth, texFormat, destRow,
878 srcFormat, srcType, srcRow, srcPacking,
879 ctx->_ImageTransferState);
880 destRow += dstRowStride;
881 }
882 dest += dstImageStride;
883 }
884 }
885 }
886 }
887
888
889
890 /* Need this to prevent an out-of-bounds memory access when using
891 * X86 optimized code.
892 */
893 #ifdef USE_X86_ASM
894 # define EXTRA_BYTE sizeof(GLchan)
895 #else
896 # define EXTRA_BYTE 0
897 #endif
898
899
900
901 /*
902 * Called by glTexImage[123]D. Fill in a texture image with data given
903 * by the client. All pixel transfer and unpack modes are handled here.
904 * Input: dimensions (1, 2, or 3)
905 * texImage - destination texture image (we'll malloc the memory)
906 * width, height, depth - size of source image
907 * srcFormat, srcType - source image format and type
908 * pixels - source image data
909 * srcPacking - source image packing parameters
910 *
911 * NOTE: All texture image parameters should have already been error checked.
912 *
913 * NOTE: the texImage dimensions and source image dimensions must be correct
914 * with respect to convolution with border mode = reduce.
915 */
916 static void
917 make_texture_image( GLcontext *ctx, GLuint dimensions,
918 struct gl_texture_image *texImage,
919 GLint width, GLint height, GLint depth,
920 GLenum srcFormat, GLenum srcType, const GLvoid *pixels,
921 const struct gl_pixelstore_attrib *srcPacking)
922 {
923 const GLint internalFormat = texImage->IntFormat;
924 const GLint components = components_in_intformat(internalFormat);
925 GLint convWidth = width, convHeight = height;
926
927 if (ctx->NewState & _NEW_PIXEL)
928 gl_update_state(ctx);
929
930 if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
931 adjust_texture_size_for_convolution(ctx, dimensions,
932 &convWidth, &convHeight);
933 }
934
935 texImage->Data = (GLchan *) MALLOC(convWidth * convHeight * depth
936 * components * sizeof(GLchan) + EXTRA_BYTE);
937 if (!texImage->Data)
938 return; /* out of memory */
939
940 fill_texture_image(ctx, dimensions, texImage->Format, texImage->Data,
941 width, height, depth, 0, 0, 0,
942 convWidth * components * sizeof(GLchan),
943 convWidth * convHeight * components * sizeof(GLchan),
944 srcFormat, srcType, pixels, srcPacking);
945 }
946
947
948
949 /*
950 * glTexImage[123]D can accept a NULL image pointer. In this case we
951 * create a texture image with unspecified image contents per the OpenGL
952 * spec. This function creates an empty image for the given texture image.
953 */
954 static void
955 make_null_texture( struct gl_texture_image *texImage )
956 {
957 GLint components;
958 GLint numPixels;
959
960 ASSERT(texImage);
961 ASSERT(!texImage->Data);
962
963 components = components_in_intformat(texImage->IntFormat);
964 numPixels = texImage->Width * texImage->Height * texImage->Depth;
965
966 texImage->Data = (GLchan *) MALLOC( numPixels * components * sizeof(GLchan)
967 + EXTRA_BYTE );
968
969 /*
970 * Let's see if anyone finds this. If glTexImage2D() is called with
971 * a NULL image pointer then load the texture image with something
972 * interesting instead of leaving it indeterminate.
973 */
974 if (texImage->Data) {
975 static const char message[8][32] = {
976 " X X XXXXX XXX X ",
977 " XX XX X X X X X ",
978 " X X X X X X X ",
979 " X X XXXX XXX XXXXX ",
980 " X X X X X X ",
981 " X X X X X X X ",
982 " X X XXXXX XXX X X ",
983 " "
984 };
985
986 GLchan *imgPtr = texImage->Data;
987 GLint i, j, k;
988 for (i = 0; i < texImage->Height; i++) {
989 GLint srcRow = 7 - i % 8;
990 for (j = 0; j < texImage->Width; j++) {
991 GLint srcCol = j % 32;
992 GLint texel = (message[srcRow][srcCol]=='X') ? CHAN_MAX : 70;
993 for (k=0;k<components;k++) {
994 *imgPtr++ = (GLchan) texel;
995 }
996 }
997 }
998 }
999 }
1000
1001
1002
1003 /*
1004 * This is called when a proxy texture test fails, we set all the
1005 * image members (except DriverData) to zero.
1006 */
1007 static void
1008 clear_proxy_teximage(struct gl_texture_image *img)
1009 {
1010 ASSERT(img);
1011 img->Format = 0;
1012 img->IntFormat = 0;
1013 img->RedBits = 0;
1014 img->GreenBits = 0;
1015 img->BlueBits = 0;
1016 img->AlphaBits = 0;
1017 img->IntensityBits = 0;
1018 img->LuminanceBits = 0;
1019 img->IndexBits = 0;
1020 img->Border = 0;
1021 img->Width = 0;
1022 img->Height = 0;
1023 img->Depth = 0;
1024 img->Width2 = 0;
1025 img->Height2 = 0;
1026 img->Depth2 = 0;
1027 img->WidthLog2 = 0;
1028 img->HeightLog2 = 0;
1029 img->DepthLog2 = 0;
1030 img->Data = NULL;
1031 img->IsCompressed = 0;
1032 img->CompressedSize = 0;
1033 }
1034
1035
1036
1037 /*
1038 * Test glTexImage[123]D() parameters for errors.
1039 * Input:
1040 * dimensions - must be 1 or 2 or 3
1041 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
1042 */
1043 static GLboolean
1044 texture_error_check( GLcontext *ctx, GLenum target,
1045 GLint level, GLint internalFormat,
1046 GLenum format, GLenum type,
1047 GLuint dimensions,
1048 GLint width, GLint height,
1049 GLint depth, GLint border )
1050 {
1051 GLboolean isProxy;
1052 GLint iformat;
1053
1054 if (dimensions == 1) {
1055 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_1D);
1056 if (target != GL_TEXTURE_1D && !isProxy) {
1057 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1058 return GL_TRUE;
1059 }
1060 }
1061 else if (dimensions == 2) {
1062 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_2D);
1063 if (target != GL_TEXTURE_2D && !isProxy &&
1064 !(ctx->Extensions.ARB_texture_cube_map &&
1065 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1066 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
1067 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
1068 return GL_TRUE;
1069 }
1070 }
1071 else if (dimensions == 3) {
1072 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_3D);
1073 if (target != GL_TEXTURE_3D && !isProxy) {
1074 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
1075 return GL_TRUE;
1076 }
1077 }
1078 else {
1079 gl_problem( ctx, "bad dims in texture_error_check" );
1080 return GL_TRUE;
1081 }
1082
1083 /* Border */
1084 if (border != 0 && border != 1) {
1085 if (!isProxy) {
1086 char message[100];
1087 sprintf(message, "glTexImage%dD(border=%d)", dimensions, border);
1088 gl_error(ctx, GL_INVALID_VALUE, message);
1089 }
1090 return GL_TRUE;
1091 }
1092
1093 /* Width */
1094 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
1095 || logbase2( width - 2 * border ) < 0) {
1096 if (!isProxy) {
1097 char message[100];
1098 sprintf(message, "glTexImage%dD(width=%d)", dimensions, width);
1099 gl_error(ctx, GL_INVALID_VALUE, message);
1100 }
1101 return GL_TRUE;
1102 }
1103
1104 /* Height */
1105 if (dimensions >= 2) {
1106 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
1107 || logbase2( height - 2 * border ) < 0) {
1108 if (!isProxy) {
1109 char message[100];
1110 sprintf(message, "glTexImage%dD(height=%d)", dimensions, height);
1111 gl_error(ctx, GL_INVALID_VALUE, message);
1112 }
1113 return GL_TRUE;
1114 }
1115 }
1116
1117 /* For cube map, width must equal height */
1118 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1119 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1120 if (width != height) {
1121 if (!isProxy) {
1122 gl_error(ctx, GL_INVALID_VALUE, "glTexImage2D(width != height)");
1123 }
1124 return GL_TRUE;
1125 }
1126 }
1127
1128 /* Depth */
1129 if (dimensions >= 3) {
1130 if (depth < 2 * border || depth > 2 + ctx->Const.MaxTextureSize
1131 || logbase2( depth - 2 * border ) < 0) {
1132 if (!isProxy) {
1133 char message[100];
1134 sprintf(message, "glTexImage3D(depth=%d)", depth );
1135 gl_error( ctx, GL_INVALID_VALUE, message );
1136 }
1137 return GL_TRUE;
1138 }
1139 }
1140
1141 /* Level */
1142 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1143 if (!isProxy) {
1144 char message[100];
1145 sprintf(message, "glTexImage%dD(level=%d)", dimensions, level);
1146 gl_error(ctx, GL_INVALID_VALUE, message);
1147 }
1148 return GL_TRUE;
1149 }
1150
1151 iformat = _mesa_base_tex_format( ctx, internalFormat );
1152 if (iformat < 0) {
1153 if (!isProxy) {
1154 char message[100];
1155 sprintf(message, "glTexImage%dD(internalFormat=0x%x)", dimensions,
1156 internalFormat);
1157 gl_error(ctx, GL_INVALID_VALUE, message);
1158 }
1159 return GL_TRUE;
1160 }
1161
1162 if (!is_compressed_format(ctx, internalFormat)) {
1163 if (!_mesa_is_legal_format_and_type( format, type )) {
1164 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
1165 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
1166 */
1167 if (!isProxy) {
1168 char message[100];
1169 sprintf(message, "glTexImage%dD(format or type)", dimensions);
1170 gl_error(ctx, GL_INVALID_OPERATION, message);
1171 }
1172 return GL_TRUE;
1173 }
1174 }
1175
1176 /* if we get here, the parameters are OK */
1177 return GL_FALSE;
1178 }
1179
1180
1181
1182 /*
1183 * Test glTexSubImage[123]D() parameters for errors.
1184 * Input:
1185 * dimensions - must be 1 or 2 or 3
1186 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
1187 */
1188 static GLboolean
1189 subtexture_error_check( GLcontext *ctx, GLuint dimensions,
1190 GLenum target, GLint level,
1191 GLint xoffset, GLint yoffset, GLint zoffset,
1192 GLint width, GLint height, GLint depth,
1193 GLenum format, GLenum type )
1194 {
1195 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1196 struct gl_texture_image *destTex;
1197
1198 if (dimensions == 1) {
1199 if (target != GL_TEXTURE_1D) {
1200 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
1201 return GL_TRUE;
1202 }
1203 }
1204 else if (dimensions == 2) {
1205 if (ctx->Extensions.ARB_texture_cube_map) {
1206 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1207 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1208 target != GL_TEXTURE_2D) {
1209 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1210 return GL_TRUE;
1211 }
1212 }
1213 else if (target != GL_TEXTURE_2D) {
1214 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1215 return GL_TRUE;
1216 }
1217 }
1218 else if (dimensions == 3) {
1219 if (target != GL_TEXTURE_3D) {
1220 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
1221 return GL_TRUE;
1222 }
1223 }
1224 else {
1225 gl_problem( ctx, "bad dims in texture_error_check" );
1226 return GL_TRUE;
1227 }
1228
1229 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1230 char message[100];
1231 sprintf(message, "glTexSubImage2D(level=%d)", level);
1232 gl_error(ctx, GL_INVALID_ENUM, message);
1233 return GL_TRUE;
1234 }
1235
1236 if (width < 0) {
1237 char message[100];
1238 sprintf(message, "glTexSubImage%dD(width=%d)", dimensions, width);
1239 gl_error(ctx, GL_INVALID_VALUE, message);
1240 return GL_TRUE;
1241 }
1242 if (height < 0 && dimensions > 1) {
1243 char message[100];
1244 sprintf(message, "glTexSubImage%dD(height=%d)", dimensions, height);
1245 gl_error(ctx, GL_INVALID_VALUE, message);
1246 return GL_TRUE;
1247 }
1248 if (depth < 0 && dimensions > 2) {
1249 char message[100];
1250 sprintf(message, "glTexSubImage%dD(depth=%d)", dimensions, depth);
1251 gl_error(ctx, GL_INVALID_VALUE, message);
1252 return GL_TRUE;
1253 }
1254
1255 destTex = texUnit->Current2D->Image[level];
1256 if (!destTex) {
1257 gl_error(ctx, GL_INVALID_OPERATION, "glTexSubImage2D");
1258 return GL_TRUE;
1259 }
1260
1261 if (xoffset < -((GLint)destTex->Border)) {
1262 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset)");
1263 return GL_TRUE;
1264 }
1265 if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
1266 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset+width)");
1267 return GL_TRUE;
1268 }
1269 if (dimensions > 1) {
1270 if (yoffset < -((GLint)destTex->Border)) {
1271 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset)");
1272 return GL_TRUE;
1273 }
1274 if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) {
1275 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset+height)");
1276 return GL_TRUE;
1277 }
1278 }
1279 if (dimensions > 2) {
1280 if (zoffset < -((GLint)destTex->Border)) {
1281 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)");
1282 return GL_TRUE;
1283 }
1284 if (zoffset + depth > (GLint) (destTex->Depth+destTex->Border)) {
1285 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)");
1286 return GL_TRUE;
1287 }
1288 }
1289
1290 if (!is_compressed_format(ctx, destTex->IntFormat)) {
1291 if (!_mesa_is_legal_format_and_type(format, type)) {
1292 char message[100];
1293 sprintf(message, "glTexSubImage%dD(format or type)", dimensions);
1294 gl_error(ctx, GL_INVALID_ENUM, message);
1295 return GL_TRUE;
1296 }
1297 }
1298
1299 return GL_FALSE;
1300 }
1301
1302
1303 /*
1304 * Test glCopyTexImage[12]D() parameters for errors.
1305 * Input: dimensions - must be 1 or 2 or 3
1306 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
1307 */
1308 static GLboolean
1309 copytexture_error_check( GLcontext *ctx, GLuint dimensions,
1310 GLenum target, GLint level, GLint internalFormat,
1311 GLint width, GLint height, GLint border )
1312 {
1313 GLint iformat;
1314
1315 if (dimensions == 1) {
1316 if (target != GL_TEXTURE_1D) {
1317 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
1318 return GL_TRUE;
1319 }
1320 }
1321 else if (dimensions == 2) {
1322 if (ctx->Extensions.ARB_texture_cube_map) {
1323 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1324 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1325 target != GL_TEXTURE_2D) {
1326 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1327 return GL_TRUE;
1328 }
1329 }
1330 else if (target != GL_TEXTURE_2D) {
1331 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1332 return GL_TRUE;
1333 }
1334 }
1335
1336 /* Border */
1337 if (border!=0 && border!=1) {
1338 char message[100];
1339 sprintf(message, "glCopyTexImage%dD(border)", dimensions);
1340 gl_error(ctx, GL_INVALID_VALUE, message);
1341 return GL_TRUE;
1342 }
1343
1344 /* Width */
1345 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
1346 || logbase2( width - 2 * border ) < 0) {
1347 char message[100];
1348 sprintf(message, "glCopyTexImage%dD(width=%d)", dimensions, width);
1349 gl_error(ctx, GL_INVALID_VALUE, message);
1350 return GL_TRUE;
1351 }
1352
1353 /* Height */
1354 if (dimensions >= 2) {
1355 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
1356 || logbase2( height - 2 * border ) < 0) {
1357 char message[100];
1358 sprintf(message, "glCopyTexImage%dD(height=%d)", dimensions, height);
1359 gl_error(ctx, GL_INVALID_VALUE, message);
1360 return GL_TRUE;
1361 }
1362 }
1363
1364 /* For cube map, width must equal height */
1365 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1366 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1367 if (width != height) {
1368 gl_error(ctx, GL_INVALID_VALUE, "glCopyTexImage2D(width != height)");
1369 return GL_TRUE;
1370 }
1371 }
1372
1373 /* Level */
1374 if (level<0 || level>=ctx->Const.MaxTextureLevels) {
1375 char message[100];
1376 sprintf(message, "glCopyTexImage%dD(level=%d)", dimensions, level);
1377 gl_error(ctx, GL_INVALID_VALUE, message);
1378 return GL_TRUE;
1379 }
1380
1381 iformat = _mesa_base_tex_format( ctx, internalFormat );
1382 if (iformat < 0) {
1383 char message[100];
1384 sprintf(message, "glCopyTexImage%dD(internalFormat)", dimensions);
1385 gl_error(ctx, GL_INVALID_VALUE, message);
1386 return GL_TRUE;
1387 }
1388
1389 /* if we get here, the parameters are OK */
1390 return GL_FALSE;
1391 }
1392
1393
1394 static GLboolean
1395 copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
1396 GLenum target, GLint level,
1397 GLint xoffset, GLint yoffset, GLint zoffset,
1398 GLsizei width, GLsizei height )
1399 {
1400 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1401 struct gl_texture_image *teximage;
1402
1403 if (dimensions == 1) {
1404 if (target != GL_TEXTURE_1D) {
1405 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
1406 return GL_TRUE;
1407 }
1408 }
1409 else if (dimensions == 2) {
1410 if (ctx->Extensions.ARB_texture_cube_map) {
1411 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1412 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1413 target != GL_TEXTURE_2D) {
1414 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1415 return GL_TRUE;
1416 }
1417 }
1418 else if (target != GL_TEXTURE_2D) {
1419 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1420 return GL_TRUE;
1421 }
1422 }
1423 else if (dimensions == 3) {
1424 if (target != GL_TEXTURE_3D) {
1425 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" );
1426 return GL_TRUE;
1427 }
1428 }
1429
1430 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1431 char message[100];
1432 sprintf(message, "glCopyTexSubImage%dD(level=%d)", dimensions, level);
1433 gl_error(ctx, GL_INVALID_VALUE, message);
1434 return GL_TRUE;
1435 }
1436
1437 if (width < 0) {
1438 char message[100];
1439 sprintf(message, "glCopyTexSubImage%dD(width=%d)", dimensions, width);
1440 gl_error(ctx, GL_INVALID_VALUE, message);
1441 return GL_TRUE;
1442 }
1443 if (dimensions > 1 && height < 0) {
1444 char message[100];
1445 sprintf(message, "glCopyTexSubImage%dD(height=%d)", dimensions, height);
1446 gl_error(ctx, GL_INVALID_VALUE, message);
1447 return GL_TRUE;
1448 }
1449
1450 teximage = _mesa_select_tex_image(ctx, texUnit, target, level);
1451 if (!teximage) {
1452 char message[100];
1453 sprintf(message, "glCopyTexSubImage%dD(undefined texture)", dimensions);
1454 gl_error(ctx, GL_INVALID_OPERATION, message);
1455 return GL_TRUE;
1456 }
1457
1458 if (xoffset < -((GLint)teximage->Border)) {
1459 char message[100];
1460 sprintf(message, "glCopyTexSubImage%dD(xoffset=%d)", dimensions, xoffset);
1461 gl_error(ctx, GL_INVALID_VALUE, message);
1462 return GL_TRUE;
1463 }
1464 if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) {
1465 char message[100];
1466 sprintf(message, "glCopyTexSubImage%dD(xoffset+width)", dimensions);
1467 gl_error(ctx, GL_INVALID_VALUE, message);
1468 return GL_TRUE;
1469 }
1470 if (dimensions > 1) {
1471 if (yoffset < -((GLint)teximage->Border)) {
1472 char message[100];
1473 sprintf(message, "glCopyTexSubImage%dD(yoffset=%d)", dimensions, yoffset);
1474 gl_error(ctx, GL_INVALID_VALUE, message);
1475 return GL_TRUE;
1476 }
1477 /* NOTE: we're adding the border here, not subtracting! */
1478 if (yoffset+height > (GLint) (teximage->Height+teximage->Border)) {
1479 char message[100];
1480 sprintf(message, "glCopyTexSubImage%dD(yoffset+height)", dimensions);
1481 gl_error(ctx, GL_INVALID_VALUE, message);
1482 return GL_TRUE;
1483 }
1484 }
1485
1486 if (dimensions > 2) {
1487 if (zoffset < -((GLint)teximage->Border)) {
1488 char message[100];
1489 sprintf(message, "glCopyTexSubImage%dD(zoffset)", dimensions);
1490 gl_error(ctx, GL_INVALID_VALUE, message);
1491 return GL_TRUE;
1492 }
1493 if (zoffset > (GLint) (teximage->Depth+teximage->Border)) {
1494 char message[100];
1495 sprintf(message, "glCopyTexSubImage%dD(zoffset+depth)", dimensions);
1496 gl_error(ctx, GL_INVALID_VALUE, message);
1497 return GL_TRUE;
1498 }
1499 }
1500
1501 /* if we get here, the parameters are OK */
1502 return GL_FALSE;
1503 }
1504
1505
1506
1507
1508 /*
1509 * Turn generic compressed formats into specific compressed format.
1510 * Some of the compressed formats we don't support, so we
1511 * fall back to the uncompressed format. (See issue 15 of
1512 * the GL_ARB_texture_compression specification.)
1513 */
1514 static GLint
1515 get_specific_compressed_tex_format(GLcontext *ctx,
1516 GLint ifmt, GLint numDimensions,
1517 GLint *levelp,
1518 GLsizei *widthp,
1519 GLsizei *heightp,
1520 GLsizei *depthp,
1521 GLint *borderp,
1522 GLenum *formatp,
1523 GLenum *typep)
1524 {
1525 char message[100];
1526 GLint internalFormat = ifmt;
1527
1528 if (ctx->Extensions.ARB_texture_compression
1529 && ctx->Driver.SpecificCompressedTexFormat) {
1530 /*
1531 * First, ask the driver for the specific format.
1532 * We do this for all formats, since we may want to
1533 * fake one compressed format for another.
1534 */
1535 internalFormat = (*ctx->Driver.SpecificCompressedTexFormat)
1536 (ctx, internalFormat, numDimensions,
1537 levelp,
1538 widthp, heightp, depthp,
1539 borderp, formatp, typep);
1540 }
1541
1542 /*
1543 * Now, convert any generic format left to an uncompressed
1544 * specific format. If the driver does not support compression
1545 * of the format, we must drop back to the uncompressed format.
1546 * See issue 15 of the GL_ARB_texture_compression specification.
1547 */
1548 switch (internalFormat) {
1549 case GL_COMPRESSED_ALPHA_ARB:
1550 if (ctx && !ctx->Extensions.ARB_texture_compression) {
1551 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1552 gl_error(ctx, GL_INVALID_VALUE, message);
1553 return -1;
1554 }
1555 internalFormat = GL_ALPHA;
1556 break;
1557 case GL_COMPRESSED_LUMINANCE_ARB:
1558 if (ctx && !ctx->Extensions.ARB_texture_compression) {
1559 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1560 gl_error(ctx, GL_INVALID_VALUE, message);
1561 return -1;
1562 }
1563 internalFormat = GL_LUMINANCE;
1564 break;
1565 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
1566 if (ctx && !ctx->Extensions.ARB_texture_compression) {
1567 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1568 gl_error(ctx, GL_INVALID_VALUE, message);
1569 return -1;
1570 }
1571 internalFormat = GL_LUMINANCE_ALPHA;
1572 break;
1573 case GL_COMPRESSED_INTENSITY_ARB:
1574 if (ctx && !ctx->Extensions.ARB_texture_compression) {
1575 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1576 gl_error(ctx, GL_INVALID_VALUE, message);
1577 return -1;
1578 }
1579 internalFormat = GL_INTENSITY;
1580 break;
1581 case GL_COMPRESSED_RGB_ARB:
1582 if (ctx && !ctx->Extensions.ARB_texture_compression) {
1583 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1584 gl_error(ctx, GL_INVALID_VALUE, message);
1585 return -1;
1586 }
1587 internalFormat = GL_RGB;
1588 break;
1589 case GL_COMPRESSED_RGBA_ARB:
1590 if (ctx && !ctx->Extensions.ARB_texture_compression) {
1591 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1592 gl_error(ctx, GL_INVALID_VALUE, message);
1593 return -1;
1594 }
1595 internalFormat = GL_RGBA;
1596 break;
1597 default:
1598 /* silence compiler warning */
1599 ;
1600 }
1601 return internalFormat;
1602 }
1603
1604
1605 /*
1606 * Called from the API. Note that width includes the border.
1607 */
1608 void
1609 _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
1610 GLsizei width, GLint border, GLenum format,
1611 GLenum type, const GLvoid *pixels )
1612 {
1613 GLsizei postConvWidth = width;
1614 GET_CURRENT_CONTEXT(ctx);
1615 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1616
1617 adjust_texture_size_for_convolution(ctx, 1, &postConvWidth, NULL);
1618
1619 if (target==GL_TEXTURE_1D) {
1620 struct gl_texture_unit *texUnit;
1621 struct gl_texture_object *texObj;
1622 struct gl_texture_image *texImage;
1623 GLint ifmt;
1624
1625 ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 1,
1626 &level,
1627 &width, 0, 0,
1628 &border, &format, &type);
1629 if (ifmt < 0) {
1630 /*
1631 * The error here is that we were sent a generic compressed
1632 * format, but the extension is not supported.
1633 */
1634 return;
1635 }
1636 else {
1637 internalFormat = ifmt;
1638 }
1639
1640 if (texture_error_check(ctx, target, level, internalFormat,
1641 format, type, 1, postConvWidth, 1, 1, border)) {
1642 return; /* error in texture image was detected */
1643 }
1644
1645 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1646 texObj = texUnit->Current1D;
1647 texImage = texObj->Image[level];
1648
1649 if (!texImage) {
1650 texImage = _mesa_alloc_texture_image();
1651 texObj->Image[level] = texImage;
1652 if (!texImage) {
1653 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
1654 return;
1655 }
1656 }
1657 else if (texImage->Data) {
1658 FREE(texImage->Data);
1659 texImage->Data = NULL;
1660 }
1661
1662 /* setup the teximage struct's fields */
1663 init_texture_image(ctx, texImage, postConvWidth, 1, 1, border, internalFormat);
1664
1665 if (ctx->NewState & _NEW_PIXEL)
1666 gl_update_state(ctx);
1667
1668 /* process the texture image */
1669 if (pixels) {
1670 GLboolean retain = GL_TRUE;
1671 GLboolean success = GL_FALSE;
1672 if (!ctx->_ImageTransferState && ctx->Driver.TexImage1D) {
1673 /* let device driver try to use raw image */
1674 success = (*ctx->Driver.TexImage1D)( ctx, target, level, format,
1675 type, pixels, &ctx->Unpack,
1676 texObj, texImage, &retain);
1677 }
1678 if (retain || !success) {
1679 /* make internal copy of the texture image */
1680 make_texture_image(ctx, 1, texImage, width, 1, 1,
1681 format, type, pixels, &ctx->Unpack);
1682 if (!success && ctx->Driver.TexImage1D) {
1683 /* let device driver try to use unpacked image */
1684 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1685 GL_UNSIGNED_BYTE, texImage->Data,
1686 &_mesa_native_packing,
1687 texObj, texImage, &retain);
1688 }
1689 }
1690 if (!retain && texImage->Data) {
1691 FREE(texImage->Data);
1692 texImage->Data = NULL;
1693 }
1694 }
1695 else {
1696 make_null_texture(texImage);
1697 if (ctx->Driver.TexImage1D) {
1698 GLboolean retain;
1699 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1700 GL_UNSIGNED_BYTE, texImage->Data,
1701 &_mesa_native_packing,
1702 texObj, texImage, &retain);
1703 }
1704 }
1705
1706 /* state update */
1707 texObj->Complete = GL_FALSE;
1708 ctx->NewState |= _NEW_TEXTURE;
1709 }
1710 else if (target == GL_PROXY_TEXTURE_1D) {
1711 /* Proxy texture: check for errors and update proxy state */
1712 GLenum error = texture_error_check(ctx, target, level, internalFormat,
1713 format, type, 1, width, 1, 1, border);
1714 if (!error && ctx->Driver.TestProxyTexImage) {
1715 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
1716 internalFormat, format, type,
1717 width, 1, 1, border);
1718 }
1719 if (error) {
1720 /* if error, clear all proxy texture image parameters */
1721 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1722 clear_proxy_teximage(ctx->Texture.Proxy1D->Image[level]);
1723 }
1724 }
1725 else {
1726 /* if no error, update proxy texture image parameters */
1727 init_texture_image(ctx, ctx->Texture.Proxy1D->Image[level],
1728 width, 1, 1, border, internalFormat);
1729 }
1730 }
1731 else {
1732 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1733 return;
1734 }
1735 }
1736
1737
1738 void
1739 _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
1740 GLsizei width, GLsizei height, GLint border,
1741 GLenum format, GLenum type,
1742 const GLvoid *pixels )
1743 {
1744 GLsizei postConvWidth = width, postConvHeight = height;
1745 GET_CURRENT_CONTEXT(ctx);
1746 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1747
1748 adjust_texture_size_for_convolution(ctx, 2, &postConvWidth,&postConvHeight);
1749
1750 if (target==GL_TEXTURE_2D ||
1751 (ctx->Extensions.ARB_texture_cube_map &&
1752 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1753 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
1754 struct gl_texture_unit *texUnit;
1755 struct gl_texture_object *texObj;
1756 struct gl_texture_image *texImage;
1757 GLint ifmt;
1758
1759 ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 2,
1760 &level,
1761 &width, &height, 0,
1762 &border, &format, &type);
1763 if (ifmt < 0) {
1764 /*
1765 * The error here is that we were sent a generic compressed
1766 * format, but the extension is not supported.
1767 */
1768 return;
1769 }
1770 else {
1771 internalFormat = ifmt;
1772 }
1773
1774 if (texture_error_check(ctx, target, level, internalFormat,
1775 format, type, 2, postConvWidth, postConvHeight,
1776 1, border)) {
1777 return; /* error in texture image was detected */
1778 }
1779
1780 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1781 texObj = _mesa_select_tex_object(ctx, texUnit, target);
1782 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1783
1784 if (!texImage) {
1785 texImage = _mesa_alloc_texture_image();
1786 set_tex_image(texObj, target, level, texImage);
1787 /*texObj->Image[level] = texImage;*/
1788 if (!texImage) {
1789 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1790 return;
1791 }
1792 }
1793 else if (texImage->Data) {
1794 FREE(texImage->Data);
1795 texImage->Data = NULL;
1796 }
1797
1798 /* setup the teximage struct's fields */
1799 init_texture_image(ctx, texImage, postConvWidth, postConvHeight,
1800 1, border, internalFormat);
1801
1802 if (ctx->NewState & _NEW_PIXEL)
1803 gl_update_state(ctx);
1804
1805 /* process the texture image */
1806 if (pixels) {
1807 GLboolean retain = GL_TRUE;
1808 GLboolean success = GL_FALSE;
1809 if (!ctx->_ImageTransferState && ctx->Driver.TexImage2D) {
1810 /* let device driver try to use raw image */
1811 success = (*ctx->Driver.TexImage2D)( ctx, target, level, format,
1812 type, pixels, &ctx->Unpack,
1813 texObj, texImage, &retain);
1814 }
1815 if (retain || !success) {
1816 /* make internal copy of the texture image */
1817 make_texture_image(ctx, 2, texImage, width, height, 1,
1818 format, type, pixels, &ctx->Unpack);
1819 if (!success && ctx->Driver.TexImage2D) {
1820 /* let device driver try to use unpacked image */
1821 (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1822 GL_UNSIGNED_BYTE, texImage->Data,
1823 &_mesa_native_packing,
1824 texObj, texImage, &retain);
1825 }
1826 }
1827 if (!retain && texImage->Data) {
1828 FREE(texImage->Data);
1829 texImage->Data = NULL;
1830 }
1831 }
1832 else {
1833 make_null_texture(texImage);
1834 if (ctx->Driver.TexImage2D) {
1835 GLboolean retain;
1836 (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1837 GL_UNSIGNED_BYTE, texImage->Data,
1838 &_mesa_native_packing,
1839 texObj, texImage, &retain);
1840 }
1841 }
1842
1843 /* state update */
1844 texObj->Complete = GL_FALSE;
1845 ctx->NewState |= _NEW_TEXTURE;
1846 }
1847 else if (target == GL_PROXY_TEXTURE_2D) {
1848 /* Proxy texture: check for errors and update proxy state */
1849 GLenum error = texture_error_check(ctx, target, level, internalFormat,
1850 format, type, 2, width, height, 1, border);
1851 if (!error && ctx->Driver.TestProxyTexImage) {
1852 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
1853 internalFormat, format, type,
1854 width, height, 1, border);
1855 }
1856 if (error) {
1857 /* if error, clear all proxy texture image parameters */
1858 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1859 clear_proxy_teximage(ctx->Texture.Proxy2D->Image[level]);
1860 }
1861 }
1862 else {
1863 /* if no error, update proxy texture image parameters */
1864 init_texture_image(ctx,
1865 ctx->Texture.Proxy2D->Image[level],
1866 width, height, 1, border, internalFormat);
1867 }
1868 }
1869 else {
1870 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
1871 return;
1872 }
1873 }
1874
1875
1876 /*
1877 * Called by the API or display list executor.
1878 * Note that width and height include the border.
1879 */
1880 void
1881 _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
1882 GLsizei width, GLsizei height, GLsizei depth,
1883 GLint border, GLenum format, GLenum type,
1884 const GLvoid *pixels )
1885 {
1886 GET_CURRENT_CONTEXT(ctx);
1887 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
1888
1889 if (target==GL_TEXTURE_3D_EXT) {
1890 struct gl_texture_unit *texUnit;
1891 struct gl_texture_object *texObj;
1892 struct gl_texture_image *texImage;
1893 GLint ifmt;
1894
1895 ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 3,
1896 &level,
1897 &width, &height, &depth,
1898 &border, &format, &type);
1899 if (ifmt < 0) {
1900 /*
1901 * The error here is that we were sent a generic compressed
1902 * format, but the extension is not supported.
1903 */
1904 return;
1905 }
1906 else {
1907 internalFormat = ifmt;
1908 }
1909
1910 if (texture_error_check(ctx, target, level, internalFormat,
1911 format, type, 3, width, height, depth, border)) {
1912 return; /* error in texture image was detected */
1913 }
1914
1915 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1916 texObj = texUnit->Current3D;
1917 texImage = texObj->Image[level];
1918
1919 if (!texImage) {
1920 texImage = _mesa_alloc_texture_image();
1921 texObj->Image[level] = texImage;
1922 if (!texImage) {
1923 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
1924 return;
1925 }
1926 }
1927 else if (texImage->Data) {
1928 FREE(texImage->Data);
1929 texImage->Data = NULL;
1930 }
1931
1932 /* setup the teximage struct's fields */
1933 init_texture_image(ctx, texImage, width, height, depth,
1934 border, internalFormat);
1935
1936 if (ctx->NewState & _NEW_PIXEL)
1937 gl_update_state(ctx);
1938
1939 /* process the texture image */
1940 if (pixels) {
1941 GLboolean retain = GL_TRUE;
1942 GLboolean success = GL_FALSE;
1943 if (!ctx->_ImageTransferState && ctx->Driver.TexImage3D) {
1944 /* let device driver try to use raw image */
1945 success = (*ctx->Driver.TexImage3D)( ctx, target, level, format,
1946 type, pixels, &ctx->Unpack,
1947 texObj, texImage, &retain);
1948 }
1949 if (retain || !success) {
1950 /* make internal copy of the texture image */
1951 make_texture_image(ctx, 3, texImage, width, height, depth,
1952 format, type, pixels, &ctx->Unpack);
1953 if (!success && ctx->Driver.TexImage3D) {
1954 /* let device driver try to use unpacked image */
1955 (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1956 GL_UNSIGNED_BYTE, texImage->Data,
1957 &_mesa_native_packing,
1958 texObj, texImage, &retain);
1959 }
1960 }
1961 if (!retain && texImage->Data) {
1962 FREE(texImage->Data);
1963 texImage->Data = NULL;
1964 }
1965 }
1966 else {
1967 make_null_texture(texImage);
1968 if (ctx->Driver.TexImage3D) {
1969 GLboolean retain;
1970 (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1971 GL_UNSIGNED_BYTE, texImage->Data,
1972 &_mesa_native_packing,
1973 texObj, texImage, &retain);
1974 }
1975 }
1976
1977 /* state update */
1978 texObj->Complete = GL_FALSE;
1979 ctx->NewState |= _NEW_TEXTURE;
1980 }
1981 else if (target == GL_PROXY_TEXTURE_3D) {
1982 /* Proxy texture: check for errors and update proxy state */
1983 GLenum error = texture_error_check(ctx, target, level, internalFormat,
1984 format, type, 3, width, height, depth, border);
1985 if (!error && ctx->Driver.TestProxyTexImage) {
1986 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
1987 internalFormat, format, type,
1988 width, height, depth, border);
1989 }
1990 if (error) {
1991 /* if error, clear all proxy texture image parameters */
1992 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1993 clear_proxy_teximage(ctx->Texture.Proxy3D->Image[level]);
1994 }
1995 }
1996 else {
1997 /* if no error, update proxy texture image parameters */
1998 init_texture_image(ctx, ctx->Texture.Proxy3D->Image[level],
1999 width, height, depth, border, internalFormat);
2000 }
2001 }
2002 else {
2003 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
2004 return;
2005 }
2006 }
2007
2008
2009 void
2010 _mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
2011 GLsizei width, GLsizei height, GLsizei depth,
2012 GLint border, GLenum format, GLenum type,
2013 const GLvoid *pixels )
2014 {
2015 _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height,
2016 depth, border, format, type, pixels);
2017 }
2018
2019
2020 /*
2021 * Fetch a texture image from the device driver.
2022 * Store the results in the given texture object at the given mipmap level.
2023 */
2024 void
2025 _mesa_get_teximage_from_driver( GLcontext *ctx, GLenum target, GLint level,
2026 const struct gl_texture_object *texObj )
2027 {
2028 GLvoid *image;
2029 GLenum imgFormat, imgType;
2030 GLboolean freeImage;
2031 struct gl_texture_image *texImage;
2032 GLint destComponents, numPixels, srcBytesPerTexel;
2033
2034 if (!ctx->Driver.GetTexImage)
2035 return;
2036
2037 image = (*ctx->Driver.GetTexImage)( ctx, target, level, texObj,
2038 &imgFormat, &imgType, &freeImage);
2039 if (!image)
2040 return;
2041
2042 texImage = texObj->Image[level];
2043 ASSERT(texImage);
2044 if (!texImage)
2045 return;
2046
2047 destComponents = components_in_intformat(texImage->Format);
2048 assert(destComponents > 0);
2049 numPixels = texImage->Width * texImage->Height * texImage->Depth;
2050 assert(numPixels > 0);
2051 srcBytesPerTexel = _mesa_bytes_per_pixel(imgFormat, imgType);
2052 assert(srcBytesPerTexel > 0);
2053
2054 if (!texImage->Data) {
2055 /* Allocate memory for the texture image data */
2056 texImage->Data = (GLchan *) MALLOC(numPixels * destComponents
2057 * sizeof(GLchan) + EXTRA_BYTE);
2058 }
2059
2060 if (imgFormat == texImage->Format && imgType == GL_UNSIGNED_BYTE) {
2061 /* We got lucky! The driver's format and type match Mesa's format. */
2062 if (texImage->Data) {
2063 MEMCPY(texImage->Data, image, numPixels * destComponents);
2064 }
2065 }
2066 else {
2067 /* Convert the texture image from the driver's format to Mesa's
2068 * internal format.
2069 */
2070 const GLint width = texImage->Width;
2071 const GLint height = texImage->Height;
2072 const GLint depth = texImage->Depth;
2073 const GLint destBytesPerRow = width * destComponents * sizeof(GLchan);
2074 const GLint srcBytesPerRow = width * srcBytesPerTexel;
2075 const GLenum dstType = GL_UNSIGNED_BYTE;
2076 const GLenum dstFormat = texImage->Format;
2077 const GLchan *srcPtr = (const GLchan *) image;
2078 GLchan *destPtr = texImage->Data;
2079
2080 if (texImage->Format == GL_COLOR_INDEX) {
2081 /* color index texture */
2082 GLint img, row;
2083 assert(imgFormat == GL_COLOR_INDEX);
2084 for (img = 0; img < depth; img++) {
2085 for (row = 0; row < height; row++) {
2086 _mesa_unpack_index_span(ctx, width, dstType, destPtr,
2087 imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
2088 destPtr += destBytesPerRow;
2089 srcPtr += srcBytesPerRow;
2090 }
2091 }
2092 }
2093 else {
2094 /* color texture */
2095 GLint img, row;
2096 for (img = 0; img < depth; img++) {
2097 for (row = 0; row < height; row++) {
2098 _mesa_unpack_chan_color_span(ctx, width, dstFormat, destPtr,
2099 imgFormat, imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
2100 destPtr += destBytesPerRow;
2101 srcPtr += srcBytesPerRow;
2102 }
2103 }
2104 }
2105 }
2106
2107 if (freeImage)
2108 FREE(image);
2109 }
2110
2111
2112 /*
2113 * Get all the mipmap images for a texture object from the device driver.
2114 * Actually, only get mipmap images if we're using a mipmap filter.
2115 */
2116 GLboolean
2117 _mesa_get_teximages_from_driver(GLcontext *ctx,
2118 struct gl_texture_object *texObj)
2119 {
2120 if (ctx->Driver.GetTexImage) {
2121 static const GLenum targets[] = {
2122 GL_TEXTURE_1D,
2123 GL_TEXTURE_2D,
2124 GL_TEXTURE_3D,
2125 GL_TEXTURE_CUBE_MAP_ARB,
2126 GL_TEXTURE_CUBE_MAP_ARB,
2127 GL_TEXTURE_CUBE_MAP_ARB
2128 };
2129 GLboolean needLambda = (texObj->MinFilter != texObj->MagFilter);
2130 GLenum target = targets[texObj->Dimensions - 1];
2131 if (needLambda) {
2132 GLint level;
2133 /* Get images for all mipmap levels. We might not need them
2134 * all but this is easier. We're on a (slow) software path
2135 * anyway.
2136 */
2137 for (level = texObj->BaseLevel; level <= texObj->_MaxLevel; level++) {
2138 struct gl_texture_image *texImg = texObj->Image[level];
2139 if (texImg && !texImg->Data) {
2140 _mesa_get_teximage_from_driver(ctx, target, level, texObj);
2141 if (!texImg->Data)
2142 return GL_FALSE; /* out of memory */
2143 }
2144 }
2145 }
2146 else {
2147 GLint level = texObj->BaseLevel;
2148 struct gl_texture_image *texImg = texObj->Image[level];
2149 if (texImg && !texImg->Data) {
2150 _mesa_get_teximage_from_driver(ctx, target, level, texObj);
2151 if (!texImg->Data)
2152 return GL_FALSE; /* out of memory */
2153 }
2154 }
2155 return GL_TRUE;
2156 }
2157 return GL_FALSE;
2158 }
2159
2160
2161
2162 void
2163 _mesa_GetTexImage( GLenum target, GLint level, GLenum format,
2164 GLenum type, GLvoid *pixels )
2165 {
2166 GET_CURRENT_CONTEXT(ctx);
2167 const struct gl_texture_unit *texUnit;
2168 const struct gl_texture_object *texObj;
2169 struct gl_texture_image *texImage;
2170 GLboolean discardImage;
2171
2172 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2173
2174 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
2175 gl_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
2176 return;
2177 }
2178
2179 if (_mesa_sizeof_type(type) <= 0) {
2180 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
2181 return;
2182 }
2183
2184 if (_mesa_components_in_format(format) <= 0) {
2185 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
2186 return;
2187 }
2188
2189 if (!pixels)
2190 return;
2191
2192 texUnit = &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]);
2193 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2194 if (!texObj ||
2195 target == GL_PROXY_TEXTURE_1D ||
2196 target == GL_PROXY_TEXTURE_2D ||
2197 target == GL_PROXY_TEXTURE_3D) {
2198 gl_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");
2199 return;
2200 }
2201
2202 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2203 if (!texImage) {
2204 /* invalid mipmap level, not an error */
2205 return;
2206 }
2207
2208 if (!texImage->Data) {
2209 /* try to get the texture image from the device driver */
2210 _mesa_get_teximage_from_driver(ctx, target, level, texObj);
2211 discardImage = GL_TRUE;
2212 }
2213 else {
2214 discardImage = GL_FALSE;
2215 }
2216
2217 if (texImage->Data) {
2218 GLint width = texImage->Width;
2219 GLint height = texImage->Height;
2220 GLint depth = texImage->Depth;
2221 GLint img, row;
2222
2223 if (ctx->NewState & _NEW_PIXEL)
2224 gl_update_state(ctx);
2225
2226 if (ctx->_ImageTransferState & IMAGE_CONVOLUTION_BIT) {
2227 /* convert texture image to GL_RGBA, GL_FLOAT */
2228 GLfloat *tmpImage, *convImage;
2229 const GLint comps = components_in_intformat(texImage->Format);
2230
2231 tmpImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
2232 if (!tmpImage) {
2233 gl_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
2234 return;
2235 }
2236 convImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
2237 if (!convImage) {
2238 FREE(tmpImage);
2239 gl_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
2240 return;
2241 }
2242
2243 for (img = 0; img < depth; img++) {
2244 GLint convWidth, convHeight;
2245
2246 /* convert to GL_RGBA */
2247 for (row = 0; row < height; row++) {
2248 const GLchan *src = texImage->Data
2249 + (img * height + row ) * width * comps;
2250 GLfloat *dst = tmpImage + row * width * 4;
2251 _mesa_unpack_float_color_span(ctx, width, GL_RGBA, dst,
2252 texImage->Format, GL_UNSIGNED_BYTE,
2253 src, &_mesa_native_packing,
2254 ctx->_ImageTransferState & IMAGE_PRE_CONVOLUTION_BITS,
2255 GL_FALSE);
2256 }
2257
2258 convWidth = width;
2259 convHeight = height;
2260
2261 /* convolve */
2262 if (target == GL_TEXTURE_1D) {
2263 if (ctx->Pixel.Convolution1DEnabled) {
2264 _mesa_convolve_1d_image(ctx, &convWidth, tmpImage, convImage);
2265 }
2266 }
2267 else {
2268 if (ctx->Pixel.Convolution2DEnabled) {
2269 _mesa_convolve_2d_image(ctx, &convWidth, &convHeight,
2270 tmpImage, convImage);
2271 }
2272 else if (ctx->Pixel.Separable2DEnabled) {
2273 _mesa_convolve_sep_image(ctx, &convWidth, &convHeight,
2274 tmpImage, convImage);
2275 }
2276 }
2277
2278 /* pack convolved image */
2279 for (row = 0; row < convHeight; row++) {
2280 const GLfloat *src = convImage + row * convWidth * 4;
2281 GLvoid *dest = _mesa_image_address(&ctx->Pack, pixels,
2282 convWidth, convHeight,
2283 format, type, img, row, 0);
2284 _mesa_pack_float_rgba_span(ctx, convWidth,
2285 (const GLfloat(*)[4]) src,
2286 format, type, dest, &ctx->Pack,
2287 ctx->_ImageTransferState & IMAGE_POST_CONVOLUTION_BITS);
2288 }
2289 }
2290
2291 FREE(tmpImage);
2292 FREE(convImage);
2293 }
2294 else {
2295 /* no convolution */
2296 for (img = 0; img < depth; img++) {
2297 for (row = 0; row < height; row++) {
2298 /* compute destination address in client memory */
2299 GLvoid *dest = _mesa_image_address( &ctx->Unpack, pixels,
2300 width, height, format, type, img, row, 0);
2301 assert(dest);
2302 if (texImage->Format == GL_RGBA) {
2303 /* simple case */
2304 const GLchan *src = texImage->Data
2305 + (img * height + row ) * width * 4;
2306 _mesa_pack_rgba_span( ctx, width, (CONST GLchan (*)[4]) src,
2307 format, type, dest, &ctx->Pack,
2308 ctx->_ImageTransferState );
2309 }
2310 else {
2311 /* general case: convert row to RGBA format */
2312 GLchan rgba[MAX_WIDTH][4];
2313 GLint i;
2314 const GLchan *src;
2315 switch (texImage->Format) {
2316 case GL_ALPHA:
2317 src = texImage->Data + row * width;
2318 for (i = 0; i < width; i++) {
2319 rgba[i][RCOMP] = CHAN_MAX;
2320 rgba[i][GCOMP] = CHAN_MAX;
2321 rgba[i][BCOMP] = CHAN_MAX;
2322 rgba[i][ACOMP] = src[i];
2323 }
2324 break;
2325 case GL_LUMINANCE:
2326 src = texImage->Data + row * width;
2327 for (i = 0; i < width; i++) {
2328 rgba[i][RCOMP] = src[i];
2329 rgba[i][GCOMP] = src[i];
2330 rgba[i][BCOMP] = src[i];
2331 rgba[i][ACOMP] = CHAN_MAX;
2332 }
2333 break;
2334 case GL_LUMINANCE_ALPHA:
2335 src = texImage->Data + row * 2 * width;
2336 for (i = 0; i < width; i++) {
2337 rgba[i][RCOMP] = src[i*2+0];
2338 rgba[i][GCOMP] = src[i*2+0];
2339 rgba[i][BCOMP] = src[i*2+0];
2340 rgba[i][ACOMP] = src[i*2+1];
2341 }
2342 break;
2343 case GL_INTENSITY:
2344 src = texImage->Data + row * width;
2345 for (i = 0; i < width; i++) {
2346 rgba[i][RCOMP] = src[i];
2347 rgba[i][GCOMP] = src[i];
2348 rgba[i][BCOMP] = src[i];
2349 rgba[i][ACOMP] = CHAN_MAX;
2350 }
2351 break;
2352 case GL_RGB:
2353 src = texImage->Data + row * 3 * width;
2354 for (i = 0; i < width; i++) {
2355 rgba[i][RCOMP] = src[i*3+0];
2356 rgba[i][GCOMP] = src[i*3+1];
2357 rgba[i][BCOMP] = src[i*3+2];
2358 rgba[i][ACOMP] = CHAN_MAX;
2359 }
2360 break;
2361 case GL_COLOR_INDEX:
2362 gl_problem( ctx, "GL_COLOR_INDEX not implemented in gl_GetTexImage" );
2363 break;
2364 case GL_RGBA:
2365 default:
2366 gl_problem( ctx, "bad format in gl_GetTexImage" );
2367 }
2368 _mesa_pack_rgba_span( ctx, width, (const GLchan (*)[4])rgba,
2369 format, type, dest, &ctx->Pack,
2370 ctx->_ImageTransferState );
2371 } /* format */
2372 } /* row */
2373 } /* img */
2374 } /* convolution */
2375
2376 /* if we got the teximage from the device driver we'll discard it now */
2377 if (discardImage) {
2378 FREE(texImage->Data);
2379 texImage->Data = NULL;
2380 }
2381 }
2382 }
2383
2384
2385
2386 void
2387 _mesa_TexSubImage1D( GLenum target, GLint level,
2388 GLint xoffset, GLsizei width,
2389 GLenum format, GLenum type,
2390 const GLvoid *pixels )
2391 {
2392 GLsizei postConvWidth = width;
2393 GET_CURRENT_CONTEXT(ctx);
2394 struct gl_texture_unit *texUnit;
2395 struct gl_texture_object *texObj;
2396 struct gl_texture_image *texImage;
2397 GLboolean success = GL_FALSE;
2398
2399 adjust_texture_size_for_convolution(ctx, 1, &postConvWidth, NULL);
2400
2401 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
2402 postConvWidth, 1, 1, format, type)) {
2403 return; /* error was detected */
2404 }
2405
2406 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2407 texObj = texUnit->Current1D;
2408 texImage = texObj->Image[level];
2409 assert(texImage);
2410
2411 if (width == 0 || !pixels)
2412 return; /* no-op, not an error */
2413
2414 if (ctx->NewState & _NEW_PIXEL)
2415 gl_update_state(ctx);
2416
2417 if (!ctx->_ImageTransferState && ctx->Driver.TexSubImage1D) {
2418 success = (*ctx->Driver.TexSubImage1D)( ctx, target, level, xoffset,
2419 width, format, type, pixels,
2420 &ctx->Unpack, texObj, texImage );
2421 }
2422 if (!success) {
2423 /* XXX if Driver.TexSubImage1D, unpack image and try again? */
2424 GLboolean retain = GL_TRUE;
2425 if (!texImage->Data) {
2426 _mesa_get_teximage_from_driver( ctx, target, level, texObj );
2427 if (!texImage->Data) {
2428 make_null_texture(texImage);
2429 }
2430 if (!texImage->Data)
2431 return; /* we're really out of luck! */
2432 }
2433
2434 fill_texture_image(ctx, 1, texImage->Format, texImage->Data,
2435 width, 1, 1, xoffset + texImage->Border, 0, 0, /* size and offsets */
2436 0, 0, /* strides */
2437 format, type, pixels, &ctx->Unpack);
2438
2439 if (ctx->Driver.TexImage1D) {
2440 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
2441 GL_UNSIGNED_BYTE, texImage->Data,
2442 &_mesa_native_packing, texObj, texImage,
2443 &retain );
2444 }
2445
2446 if (!retain && texImage->Data) {
2447 FREE(texImage->Data);
2448 texImage->Data = NULL;
2449 }
2450 }
2451 }
2452
2453
2454 void
2455 _mesa_TexSubImage2D( GLenum target, GLint level,
2456 GLint xoffset, GLint yoffset,
2457 GLsizei width, GLsizei height,
2458 GLenum format, GLenum type,
2459 const GLvoid *pixels )
2460 {
2461 GLsizei postConvWidth = width, postConvHeight = height;
2462 GET_CURRENT_CONTEXT(ctx);
2463 struct gl_texture_unit *texUnit;
2464 struct gl_texture_object *texObj;
2465 struct gl_texture_image *texImage;
2466 GLboolean success = GL_FALSE;
2467
2468 adjust_texture_size_for_convolution(ctx, 2, &postConvWidth,&postConvHeight);
2469
2470 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
2471 postConvWidth, postConvHeight, 1, format, type)) {
2472 return; /* error was detected */
2473 }
2474
2475 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2476 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2477 texImage = texObj->Image[level];
2478 assert(texImage);
2479
2480 if (width == 0 || height == 0 || !pixels)
2481 return; /* no-op, not an error */
2482
2483 if (ctx->NewState & _NEW_PIXEL)
2484 gl_update_state(ctx);
2485
2486 if (!ctx->_ImageTransferState && ctx->Driver.TexSubImage2D) {
2487 success = (*ctx->Driver.TexSubImage2D)( ctx, target, level, xoffset,
2488 yoffset, width, height, format, type,
2489 pixels, &ctx->Unpack, texObj, texImage );
2490 }
2491 if (!success) {
2492 /* XXX if Driver.TexSubImage2D, unpack image and try again? */
2493 const GLint texComps = components_in_intformat(texImage->Format);
2494 const GLint texRowStride = texImage->Width * texComps;
2495 GLboolean retain = GL_TRUE;
2496
2497 if (!texImage->Data) {
2498 _mesa_get_teximage_from_driver( ctx, target, level, texObj );
2499 if (!texImage->Data) {
2500 make_null_texture(texImage);
2501 }
2502 if (!texImage->Data)
2503 return; /* we're really out of luck! */
2504 }
2505
2506 fill_texture_image(ctx, 2, texImage->Format, texImage->Data,
2507 width, height, 1, xoffset + texImage->Border,
2508 yoffset + texImage->Border, 0, texRowStride, 0,
2509 format, type, pixels, &ctx->Unpack);
2510
2511 if (ctx->Driver.TexImage2D) {
2512 (*ctx->Driver.TexImage2D)(ctx, target, level, texImage->Format,
2513 GL_UNSIGNED_BYTE, texImage->Data,
2514 &_mesa_native_packing, texObj, texImage,
2515 &retain);
2516 }
2517
2518 if (!retain && texImage->Data) {
2519 FREE(texImage->Data);
2520 texImage->Data = NULL;
2521 }
2522 }
2523 }
2524
2525
2526
2527 void
2528 _mesa_TexSubImage3D( GLenum target, GLint level,
2529 GLint xoffset, GLint yoffset, GLint zoffset,
2530 GLsizei width, GLsizei height, GLsizei depth,
2531 GLenum format, GLenum type,
2532 const GLvoid *pixels )
2533 {
2534 GET_CURRENT_CONTEXT(ctx);
2535 struct gl_texture_unit *texUnit;
2536 struct gl_texture_object *texObj;
2537 struct gl_texture_image *texImage;
2538 GLboolean success = GL_FALSE;
2539
2540 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
2541 width, height, depth, format, type)) {
2542 return; /* error was detected */
2543 }
2544
2545 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2546 texObj = texUnit->Current3D;
2547 texImage = texObj->Image[level];
2548 assert(texImage);
2549
2550 if (width == 0 || height == 0 || height == 0 || !pixels)
2551 return; /* no-op, not an error */
2552
2553 if (ctx->NewState & _NEW_PIXEL)
2554 gl_update_state(ctx);
2555
2556 if (!ctx->_ImageTransferState && ctx->Driver.TexSubImage3D) {
2557 success = (*ctx->Driver.TexSubImage3D)( ctx, target, level, xoffset,
2558 yoffset, zoffset, width, height, depth, format,
2559 type, pixels, &ctx->Unpack, texObj, texImage );
2560 }
2561 if (!success) {
2562 /* XXX if Driver.TexSubImage3D, unpack image and try again? */
2563 const GLint texComps = components_in_intformat(texImage->Format);
2564 const GLint texRowStride = texImage->Width * texComps;
2565 const GLint texImgStride = texRowStride * texImage->Height;
2566 GLboolean retain = GL_TRUE;
2567
2568 if (!texImage->Data) {
2569 _mesa_get_teximage_from_driver( ctx, target, level, texObj );
2570 if (!texImage->Data) {
2571 make_null_texture(texImage);
2572 }
2573 if (!texImage->Data)
2574 return; /* we're really out of luck! */
2575 }
2576
2577 fill_texture_image(ctx, 3, texImage->Format, texImage->Data,
2578 width, height, depth, xoffset + texImage->Border,
2579 yoffset + texImage->Border,
2580 zoffset + texImage->Border, texRowStride,
2581 texImgStride, format, type, pixels, &ctx->Unpack);
2582
2583 if (ctx->Driver.TexImage3D) {
2584 (*ctx->Driver.TexImage3D)(ctx, target, level, texImage->Format,
2585 GL_UNSIGNED_BYTE, texImage->Data,
2586 &_mesa_native_packing, texObj, texImage,
2587 &retain);
2588 }
2589
2590 if (!retain && texImage->Data) {
2591 FREE(texImage->Data);
2592 texImage->Data = NULL;
2593 }
2594 }
2595 }
2596
2597
2598
2599 /*
2600 * Read an RGBA image from the frame buffer.
2601 * This is used by glCopyTex[Sub]Image[12]D().
2602 * Input: ctx - the context
2603 * x, y - lower left corner
2604 * width, height - size of region to read
2605 * Return: pointer to block of GL_RGBA, GLchan data.
2606 */
2607 static GLchan *
2608 read_color_image( GLcontext *ctx, GLint x, GLint y,
2609 GLsizei width, GLsizei height )
2610 {
2611 GLint stride, i;
2612 GLchan *image, *dst;
2613
2614 image = (GLchan *) MALLOC(width * height * 4 * sizeof(GLchan));
2615 if (!image)
2616 return NULL;
2617
2618 /* Select buffer to read from */
2619 (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
2620 ctx->Pixel.DriverReadBuffer );
2621
2622 RENDER_START(ctx);
2623
2624 dst = image;
2625 stride = width * 4;
2626 for (i = 0; i < height; i++) {
2627 gl_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y + i,
2628 (GLchan (*)[4]) dst );
2629 dst += stride;
2630 }
2631
2632 RENDER_FINISH(ctx);
2633
2634 /* Read from draw buffer (the default) */
2635 (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
2636 ctx->Color.DriverDrawBuffer );
2637
2638 return image;
2639 }
2640
2641
2642
2643 void
2644 _mesa_CopyTexImage1D( GLenum target, GLint level,
2645 GLenum internalFormat,
2646 GLint x, GLint y,
2647 GLsizei width, GLint border )
2648 {
2649 GLsizei postConvWidth = width;
2650 GET_CURRENT_CONTEXT(ctx);
2651 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2652
2653 if (ctx->NewState & _NEW_PIXEL)
2654 gl_update_state(ctx);
2655
2656 adjust_texture_size_for_convolution(ctx, 1, &postConvWidth, NULL);
2657
2658 if (copytexture_error_check(ctx, 1, target, level, internalFormat,
2659 postConvWidth, 1, border))
2660 return;
2661
2662 if (ctx->_ImageTransferState || !ctx->Driver.CopyTexImage1D
2663 || !(*ctx->Driver.CopyTexImage1D)(ctx, target, level,
2664 internalFormat, x, y, width, border)) {
2665 struct gl_pixelstore_attrib unpackSave;
2666
2667 /* get image from framebuffer */
2668 GLchan *image = read_color_image( ctx, x, y, width, 1 );
2669 if (!image) {
2670 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D" );
2671 return;
2672 }
2673
2674 /* call glTexImage1D to redefine the texture */
2675 unpackSave = ctx->Unpack;
2676 ctx->Unpack = _mesa_native_packing;
2677 (*ctx->Exec->TexImage1D)( target, level, internalFormat, width,
2678 border, GL_RGBA, GL_UNSIGNED_BYTE, image );
2679 ctx->Unpack = unpackSave;
2680
2681 FREE(image);
2682 }
2683 }
2684
2685
2686
2687 void
2688 _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
2689 GLint x, GLint y, GLsizei width, GLsizei height,
2690 GLint border )
2691 {
2692 GLsizei postConvWidth = width, postConvHeight = height;
2693 GET_CURRENT_CONTEXT(ctx);
2694 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2695
2696 if (ctx->NewState & _NEW_PIXEL)
2697 gl_update_state(ctx);
2698
2699 adjust_texture_size_for_convolution(ctx, 2, &postConvWidth,&postConvHeight);
2700
2701 if (copytexture_error_check(ctx, 2, target, level, internalFormat,
2702 postConvWidth, postConvHeight, border))
2703 return;
2704
2705 if (ctx->_ImageTransferState || !ctx->Driver.CopyTexImage2D
2706 || !(*ctx->Driver.CopyTexImage2D)(ctx, target, level,
2707 internalFormat, x, y, width, height, border)) {
2708 struct gl_pixelstore_attrib unpackSave;
2709
2710 /* get image from framebuffer */
2711 GLchan *image = read_color_image( ctx, x, y, width, height );
2712 if (!image) {
2713 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D" );
2714 return;
2715 }
2716
2717 /* call glTexImage2D to redefine the texture */
2718 unpackSave = ctx->Unpack;
2719 ctx->Unpack = _mesa_native_packing;
2720 (ctx->Exec->TexImage2D)( target, level, internalFormat, width,
2721 height, border, GL_RGBA, GL_UNSIGNED_BYTE, image );
2722 ctx->Unpack = unpackSave;
2723
2724 FREE(image);
2725 }
2726 }
2727
2728
2729
2730 void
2731 _mesa_CopyTexSubImage1D( GLenum target, GLint level,
2732 GLint xoffset, GLint x, GLint y, GLsizei width )
2733 {
2734 GLsizei postConvWidth = width;
2735 GET_CURRENT_CONTEXT(ctx);
2736 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2737
2738 if (ctx->NewState & _NEW_PIXEL)
2739 gl_update_state(ctx);
2740
2741 adjust_texture_size_for_convolution(ctx, 1, &postConvWidth, NULL);
2742
2743 if (copytexsubimage_error_check(ctx, 1, target, level,
2744 xoffset, 0, 0, postConvWidth, 1))
2745 return;
2746
2747 if (ctx->_ImageTransferState || !ctx->Driver.CopyTexSubImage1D
2748 || !(*ctx->Driver.CopyTexSubImage1D)(ctx, target, level,
2749 xoffset, x, y, width)) {
2750 struct gl_texture_unit *texUnit;
2751 struct gl_texture_image *teximage;
2752 struct gl_pixelstore_attrib unpackSave;
2753 GLchan *image;
2754
2755 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2756 teximage = texUnit->Current1D->Image[level];
2757 assert(teximage);
2758
2759 /* get image from frame buffer */
2760 image = read_color_image(ctx, x, y, width, 1);
2761 if (!image) {
2762 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage1D" );
2763 return;
2764 }
2765
2766 /* now call glTexSubImage1D to do the real work */
2767 unpackSave = ctx->Unpack;
2768 ctx->Unpack = _mesa_native_packing;
2769 _mesa_TexSubImage1D(target, level, xoffset, width,
2770 GL_RGBA, GL_UNSIGNED_BYTE, image);
2771 ctx->Unpack = unpackSave;
2772
2773 FREE(image);
2774 }
2775 }
2776
2777
2778
2779 void
2780 _mesa_CopyTexSubImage2D( GLenum target, GLint level,
2781 GLint xoffset, GLint yoffset,
2782 GLint x, GLint y, GLsizei width, GLsizei height )
2783 {
2784 GLsizei postConvWidth = width, postConvHeight = height;
2785 GET_CURRENT_CONTEXT(ctx);
2786 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2787
2788 if (ctx->NewState & _NEW_PIXEL)
2789 gl_update_state(ctx);
2790
2791 adjust_texture_size_for_convolution(ctx, 2, &postConvWidth,&postConvHeight);
2792
2793 if (copytexsubimage_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
2794 postConvWidth, postConvHeight))
2795 return;
2796
2797 if (ctx->_ImageTransferState || !ctx->Driver.CopyTexSubImage2D
2798 || !(*ctx->Driver.CopyTexSubImage2D)(ctx, target, level,
2799 xoffset, yoffset, x, y, width, height )) {
2800 struct gl_texture_unit *texUnit;
2801 struct gl_texture_image *teximage;
2802 struct gl_pixelstore_attrib unpackSave;
2803 GLchan *image;
2804
2805 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2806 teximage = texUnit->Current2D->Image[level];
2807 assert(teximage);
2808
2809 /* get image from frame buffer */
2810 image = read_color_image(ctx, x, y, width, height);
2811 if (!image) {
2812 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
2813 return;
2814 }
2815
2816 /* now call glTexSubImage2D to do the real work */
2817 unpackSave = ctx->Unpack;
2818 ctx->Unpack = _mesa_native_packing;
2819 _mesa_TexSubImage2D(target, level, xoffset, yoffset, width, height,
2820 GL_RGBA, GL_UNSIGNED_BYTE, image);
2821 ctx->Unpack = unpackSave;
2822
2823 FREE(image);
2824 }
2825 }
2826
2827
2828
2829 void
2830 _mesa_CopyTexSubImage3D( GLenum target, GLint level,
2831 GLint xoffset, GLint yoffset, GLint zoffset,
2832 GLint x, GLint y, GLsizei width, GLsizei height )
2833 {
2834 GLsizei postConvWidth = width, postConvHeight = height;
2835 GET_CURRENT_CONTEXT(ctx);
2836 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2837
2838 if (ctx->NewState & _NEW_PIXEL)
2839 gl_update_state(ctx);
2840
2841 adjust_texture_size_for_convolution(ctx, 2, &postConvWidth,&postConvHeight);
2842
2843 if (copytexsubimage_error_check(ctx, 3, target, level, xoffset, yoffset,
2844 zoffset, postConvWidth, postConvHeight))
2845 return;
2846
2847 if (ctx->_ImageTransferState || !ctx->Driver.CopyTexSubImage3D
2848 || !(*ctx->Driver.CopyTexSubImage3D)(ctx, target, level,
2849 xoffset, yoffset, zoffset, x, y, width, height )) {
2850 struct gl_texture_unit *texUnit;
2851 struct gl_texture_image *teximage;
2852 struct gl_pixelstore_attrib unpackSave;
2853 GLchan *image;
2854
2855 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2856 teximage = texUnit->Current3D->Image[level];
2857 assert(teximage);
2858
2859 /* get image from frame buffer */
2860 image = read_color_image(ctx, x, y, width, height);
2861 if (!image) {
2862 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
2863 return;
2864 }
2865
2866 /* now call glTexSubImage2D to do the real work */
2867 unpackSave = ctx->Unpack;
2868 ctx->Unpack = _mesa_native_packing;
2869 _mesa_TexSubImage3D(target, level, xoffset, yoffset, zoffset,
2870 width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE, image);
2871 ctx->Unpack = unpackSave;
2872
2873 FREE(image);
2874 }
2875 }
2876
2877
2878
2879 void
2880 _mesa_CompressedTexImage1DARB(GLenum target, GLint level,
2881 GLenum internalFormat, GLsizei width,
2882 GLint border, GLsizei imageSize,
2883 const GLvoid *data)
2884 {
2885 GET_CURRENT_CONTEXT(ctx);
2886 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2887
2888 switch (internalFormat) {
2889 case GL_COMPRESSED_ALPHA_ARB:
2890 case GL_COMPRESSED_LUMINANCE_ARB:
2891 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
2892 case GL_COMPRESSED_INTENSITY_ARB:
2893 case GL_COMPRESSED_RGB_ARB:
2894 case GL_COMPRESSED_RGBA_ARB:
2895 gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB");
2896 return;
2897 default:
2898 /* silence compiler warning */
2899 ;
2900 }
2901
2902 if (target == GL_TEXTURE_1D) {
2903 struct gl_texture_unit *texUnit;
2904 struct gl_texture_object *texObj;
2905 struct gl_texture_image *texImage;
2906 GLsizei computedImageSize;
2907
2908 if (texture_error_check(ctx, target, level, internalFormat,
2909 GL_NONE, GL_NONE, 1, width, 1, 1, border)) {
2910 return; /* error in texture image was detected */
2911 }
2912
2913 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2914 texObj = texUnit->Current1D;
2915 texImage = texObj->Image[level];
2916
2917 if (!texImage) {
2918 texImage = _mesa_alloc_texture_image();
2919 texObj->Image[level] = texImage;
2920 if (!texImage) {
2921 gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1DARB");
2922 return;
2923 }
2924 }
2925 else if (texImage->Data) {
2926 FREE(texImage->Data);
2927 texImage->Data = NULL;
2928 }
2929
2930 /* setup the teximage struct's fields */
2931 init_texture_image(ctx, texImage, width, 1, 1,
2932 border, internalFormat);
2933
2934 /* process the texture image */
2935 if (data) {
2936 GLboolean retain = GL_TRUE;
2937 GLboolean success = GL_FALSE;
2938 if (ctx->Driver.CompressedTexImage1D) {
2939 success = (*ctx->Driver.CompressedTexImage1D)(ctx, target, level,
2940 imageSize, data, texObj, texImage, &retain);
2941 }
2942 if (retain || !success) {
2943 /* make internal copy of the texture image */
2944 computedImageSize = _mesa_compressed_image_size(ctx,
2945 internalFormat,
2946 1, /* num dims */
2947 width,
2948 1, /* height */
2949 1); /* depth */
2950 if (computedImageSize != imageSize) {
2951 gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage1DARB(imageSize)");
2952 return;
2953 }
2954 texImage->Data = MALLOC(computedImageSize);
2955 if (texImage->Data) {
2956 MEMCPY(texImage->Data, data, computedImageSize);
2957 }
2958 }
2959 if (!retain && texImage->Data) {
2960 FREE(texImage->Data);
2961 texImage->Data = NULL;
2962 }
2963 }
2964 else {
2965 make_null_texture(texImage);
2966 if (ctx->Driver.CompressedTexImage1D) {
2967 GLboolean retain;
2968 (*ctx->Driver.CompressedTexImage1D)(ctx, target, level, 0,
2969 texImage->Data, texObj,
2970 texImage, &retain);
2971 }
2972 }
2973
2974 /* state update */
2975 texObj->Complete = GL_FALSE;
2976 ctx->NewState |= _NEW_TEXTURE;
2977 }
2978 else if (target == GL_PROXY_TEXTURE_1D) {
2979 /* Proxy texture: check for errors and update proxy state */
2980 GLenum error = texture_error_check(ctx, target, level, internalFormat,
2981 GL_NONE, GL_NONE, 1, width, 1, 1, border);
2982 if (!error && ctx->Driver.TestProxyTexImage) {
2983 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
2984 internalFormat, GL_NONE, GL_NONE,
2985 width, 1, 1, border);
2986 }
2987 if (error) {
2988 /* if error, clear all proxy texture image parameters */
2989 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
2990 clear_proxy_teximage(ctx->Texture.Proxy1D->Image[level]);
2991 }
2992 }
2993 else {
2994 /* if no error, update proxy texture image parameters */
2995 init_texture_image(ctx, ctx->Texture.Proxy1D->Image[level],
2996 width, 1, 1, border, internalFormat);
2997 }
2998 }
2999 else {
3000 gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB(target)" );
3001 return;
3002 }
3003 }
3004
3005
3006 void
3007 _mesa_CompressedTexImage2DARB(GLenum target, GLint level,
3008 GLenum internalFormat, GLsizei width,
3009 GLsizei height, GLint border, GLsizei imageSize,
3010 const GLvoid *data)
3011 {
3012 GET_CURRENT_CONTEXT(ctx);
3013 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3014
3015 switch (internalFormat) {
3016 case GL_COMPRESSED_ALPHA_ARB:
3017 case GL_COMPRESSED_LUMINANCE_ARB:
3018 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
3019 case GL_COMPRESSED_INTENSITY_ARB:
3020 case GL_COMPRESSED_RGB_ARB:
3021 case GL_COMPRESSED_RGBA_ARB:
3022 gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB");
3023 return;
3024 default:
3025 /* silence compiler warning */
3026 ;
3027 }
3028
3029 if (target==GL_TEXTURE_2D ||
3030 (ctx->Extensions.ARB_texture_cube_map &&
3031 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3032 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
3033 struct gl_texture_unit *texUnit;
3034 struct gl_texture_object *texObj;
3035 struct gl_texture_image *texImage;
3036 GLsizei computedImageSize;
3037
3038 if (texture_error_check(ctx, target, level, internalFormat,
3039 GL_NONE, GL_NONE, 1, width, height, 1, border)) {
3040 return; /* error in texture image was detected */
3041 }
3042
3043 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3044 texObj = texUnit->Current2D;
3045 texImage = texObj->Image[level];
3046
3047 if (!texImage) {
3048 texImage = _mesa_alloc_texture_image();
3049 texObj->Image[level] = texImage;
3050 if (!texImage) {
3051 gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB");
3052 return;
3053 }
3054 }
3055 else if (texImage->Data) {
3056 FREE(texImage->Data);
3057 texImage->Data = NULL;
3058 }
3059
3060 /* setup the teximage struct's fields */
3061 init_texture_image(ctx, texImage, width, height, 1, border, internalFormat);
3062
3063 /* process the texture image */
3064 if (data) {
3065 GLboolean retain = GL_TRUE;
3066 GLboolean success = GL_FALSE;
3067 if (ctx->Driver.CompressedTexImage2D) {
3068 success = (*ctx->Driver.CompressedTexImage2D)( ctx,
3069 target,
3070 level,
3071 imageSize,
3072 data,
3073 texObj,
3074 texImage,
3075 &retain);
3076 }
3077 if (retain || !success) {
3078 /* make internal copy of the texture image */
3079 computedImageSize = _mesa_compressed_image_size(ctx,
3080 internalFormat,
3081 2, /* num dims */
3082 width,
3083 height,
3084 1); /* depth */
3085 if (computedImageSize != imageSize) {
3086 gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage2DARB(imageSize)");
3087 return;
3088 }
3089 texImage->Data = MALLOC(computedImageSize);
3090 if (texImage->Data) {
3091 MEMCPY(texImage->Data, data, computedImageSize);
3092 }
3093 }
3094 if (!retain && texImage->Data) {
3095 FREE(texImage->Data);
3096 texImage->Data = NULL;
3097 }
3098 }
3099 else {
3100 make_null_texture(texImage);
3101 if (ctx->Driver.CompressedTexImage2D) {
3102 GLboolean retain;
3103 (*ctx->Driver.CompressedTexImage2D)( ctx, target, level, 0,
3104 texImage->Data, texObj,
3105 texImage, &retain);
3106 }
3107 }
3108
3109 /* state update */
3110 texObj->Complete = GL_FALSE;
3111 ctx->NewState |= _NEW_TEXTURE;
3112 }
3113 else if (target == GL_PROXY_TEXTURE_2D) {
3114 /* Proxy texture: check for errors and update proxy state */
3115 GLenum error = texture_error_check(ctx, target, level, internalFormat,
3116 GL_NONE, GL_NONE, 2, width, height, 1, border);
3117 if (!error && ctx->Driver.TestProxyTexImage) {
3118 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3119 internalFormat, GL_NONE, GL_NONE,
3120 width, height, 1, border);
3121 }
3122 if (error) {
3123 /* if error, clear all proxy texture image parameters */
3124 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
3125 clear_proxy_teximage(ctx->Texture.Proxy2D->Image[level]);
3126 }
3127 }
3128 else {
3129 /* if no error, update proxy texture image parameters */
3130 init_texture_image(ctx, ctx->Texture.Proxy2D->Image[level],
3131 width, 1, 1, border, internalFormat);
3132 }
3133 }
3134 else {
3135 gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB(target)" );
3136 return;
3137 }
3138 }
3139
3140
3141 void
3142 _mesa_CompressedTexImage3DARB(GLenum target, GLint level,
3143 GLenum internalFormat, GLsizei width,
3144 GLsizei height, GLsizei depth, GLint border,
3145 GLsizei imageSize, const GLvoid *data)
3146 {
3147 GET_CURRENT_CONTEXT(ctx);
3148 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3149
3150 switch (internalFormat) {
3151 case GL_COMPRESSED_ALPHA_ARB:
3152 case GL_COMPRESSED_LUMINANCE_ARB:
3153 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
3154 case GL_COMPRESSED_INTENSITY_ARB:
3155 case GL_COMPRESSED_RGB_ARB:
3156 case GL_COMPRESSED_RGBA_ARB:
3157 gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB");
3158 return;
3159 default:
3160 /* silence compiler warning */
3161 ;
3162 }
3163
3164 if (target == GL_TEXTURE_3D) {
3165 struct gl_texture_unit *texUnit;
3166 struct gl_texture_object *texObj;
3167 struct gl_texture_image *texImage;
3168 GLsizei computedImageSize;
3169
3170 if (texture_error_check(ctx, target, level, internalFormat,
3171 GL_NONE, GL_NONE, 1, width, height, depth, border)) {
3172 return; /* error in texture image was detected */
3173 }
3174
3175 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3176 texObj = texUnit->Current3D;
3177 texImage = texObj->Image[level];
3178
3179 if (!texImage) {
3180 texImage = _mesa_alloc_texture_image();
3181 texObj->Image[level] = texImage;
3182 if (!texImage) {
3183 gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3DARB");
3184 return;
3185 }
3186 }
3187 else if (texImage->Data) {
3188 FREE(texImage->Data);
3189 texImage->Data = NULL;
3190 }
3191
3192 /* setup the teximage struct's fields */
3193 init_texture_image(ctx, texImage, width, height, depth,
3194 border, internalFormat);
3195
3196 /* process the texture image */
3197 if (data) {
3198 GLboolean retain = GL_TRUE;
3199 GLboolean success = GL_FALSE;
3200 if (ctx->Driver.CompressedTexImage3D) {
3201 success = (*ctx->Driver.CompressedTexImage3D)(ctx, target, level,
3202 imageSize, data,
3203 texObj, texImage,
3204 &retain);
3205 }
3206 if (retain || !success) {
3207 /* make internal copy of the texture image */
3208 computedImageSize = _mesa_compressed_image_size(ctx,
3209 internalFormat,
3210 3, /* num dims */
3211 width,
3212 height,
3213 depth);
3214 if (computedImageSize != imageSize) {
3215 gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage3DARB(imageSize)");
3216 return;
3217 }
3218 texImage->Data = MALLOC(computedImageSize);
3219 if (texImage->Data) {
3220 MEMCPY(texImage->Data, data, computedImageSize);
3221 }
3222 }
3223 if (!retain && texImage->Data) {
3224 FREE(texImage->Data);
3225 texImage->Data = NULL;
3226 }
3227 }
3228 else {
3229 make_null_texture(texImage);
3230 if (ctx->Driver.CompressedTexImage3D) {
3231 GLboolean retain;
3232 (*ctx->Driver.CompressedTexImage3D)( ctx, target, level, 0,
3233 texImage->Data, texObj,
3234 texImage, &retain);
3235 }
3236 }
3237
3238 /* state update */
3239 texObj->Complete = GL_FALSE;
3240 ctx->NewState |= _NEW_TEXTURE;
3241 }
3242 else if (target == GL_PROXY_TEXTURE_3D) {
3243 /* Proxy texture: check for errors and update proxy state */
3244 GLenum error = texture_error_check(ctx, target, level, internalFormat,
3245 GL_NONE, GL_NONE, 1, width, height, depth, border);
3246 if (!error && ctx->Driver.TestProxyTexImage) {
3247 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3248 internalFormat, GL_NONE, GL_NONE,
3249 width, height, depth, border);
3250 }
3251 if (error) {
3252 /* if error, clear all proxy texture image parameters */
3253 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
3254 clear_proxy_teximage(ctx->Texture.Proxy3D->Image[level]);
3255 }
3256 }
3257 else {
3258 /* if no error, update proxy texture image parameters */
3259 init_texture_image(ctx, ctx->Texture.Proxy3D->Image[level],
3260 width, 1, 1, border, internalFormat);
3261 }
3262 }
3263 else {
3264 gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB(target)" );
3265 return;
3266 }
3267 }
3268
3269
3270 void
3271 _mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
3272 GLsizei width, GLenum format,
3273 GLsizei imageSize, const GLvoid *data)
3274 {
3275 GET_CURRENT_CONTEXT(ctx);
3276 struct gl_texture_unit *texUnit;
3277 struct gl_texture_object *texObj;
3278 struct gl_texture_image *texImage;
3279 GLboolean success = GL_FALSE;
3280
3281 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
3282 width, 1, 1, format, GL_NONE)) {
3283 return; /* error was detected */
3284 }
3285
3286 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3287 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3288 texImage = texObj->Image[level];
3289 assert(texImage);
3290
3291 if (width == 0 || !data)
3292 return; /* no-op, not an error */
3293
3294 if (ctx->Driver.CompressedTexSubImage1D) {
3295 success = (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level,
3296 xoffset, width, format, imageSize, data, texObj, texImage);
3297 }
3298 if (!success) {
3299 /* XXX what else can we do? */
3300 gl_problem(ctx, "glCompressedTexSubImage1DARB failed!");
3301 return;
3302 }
3303 }
3304
3305
3306 void
3307 _mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
3308 GLint yoffset, GLsizei width, GLsizei height,
3309 GLenum format, GLsizei imageSize,
3310 const GLvoid *data)
3311 {
3312 GET_CURRENT_CONTEXT(ctx);
3313 struct gl_texture_unit *texUnit;
3314 struct gl_texture_object *texObj;
3315 struct gl_texture_image *texImage;
3316 GLboolean success = GL_FALSE;
3317
3318 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
3319 width, height, 1, format, GL_NONE)) {
3320 return; /* error was detected */
3321 }
3322
3323 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3324 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3325 texImage = texObj->Image[level];
3326 assert(texImage);
3327
3328 if (width == 0 || height == 0 || !data)
3329 return; /* no-op, not an error */
3330
3331 if (ctx->Driver.CompressedTexSubImage2D) {
3332 success = (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level,
3333 xoffset, yoffset, width, height, format,
3334 imageSize, data, texObj, texImage);
3335 }
3336 if (!success) {
3337 /* XXX what else can we do? */
3338 gl_problem(ctx, "glCompressedTexSubImage2DARB failed!");
3339 return;
3340 }
3341 }
3342
3343
3344 void
3345 _mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
3346 GLint yoffset, GLint zoffset, GLsizei width,
3347 GLsizei height, GLsizei depth, GLenum format,
3348 GLsizei imageSize, const GLvoid *data)
3349 {
3350 GET_CURRENT_CONTEXT(ctx);
3351 struct gl_texture_unit *texUnit;
3352 struct gl_texture_object *texObj;
3353 struct gl_texture_image *texImage;
3354 GLboolean success = GL_FALSE;
3355
3356 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
3357 width, height, depth, format, GL_NONE)) {
3358 return; /* error was detected */
3359 }
3360
3361 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3362 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3363 texImage = texObj->Image[level];
3364 assert(texImage);
3365
3366 if (width == 0 || height == 0 || depth == 0 || !data)
3367 return; /* no-op, not an error */
3368
3369 if (ctx->Driver.CompressedTexSubImage3D) {
3370 success = (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level,
3371 xoffset, yoffset, zoffset, width, height, depth,
3372 format, imageSize, data, texObj, texImage);
3373 }
3374 if (!success) {
3375 /* XXX what else can we do? */
3376 gl_problem(ctx, "glCompressedTexSubImage3DARB failed!");
3377 return;
3378 }
3379 }
3380
3381
3382 void
3383 _mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
3384 {
3385 GET_CURRENT_CONTEXT(ctx);
3386 const struct gl_texture_object *texObj;
3387 struct gl_texture_image *texImage;
3388
3389 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3390
3391 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
3392 gl_error( ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)" );
3393 return;
3394 }
3395
3396 switch (target) {
3397 case GL_TEXTURE_1D:
3398 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].Current1D;
3399 texImage = texObj->Image[level];
3400 break;
3401 case GL_TEXTURE_2D:
3402 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].Current2D;
3403 texImage = texObj->Image[level];
3404 break;
3405 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
3406 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3407 texImage = texObj->Image[level];
3408 break;
3409 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
3410 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3411 texImage = texObj->NegX[level];
3412 break;
3413 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
3414 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3415 texImage = texObj->PosY[level];
3416 break;
3417 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
3418 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3419 texImage = texObj->NegY[level];
3420 break;
3421 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
3422 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3423 texImage = texObj->PosZ[level];
3424 break;
3425 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
3426 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3427 texImage = texObj->NegZ[level];
3428 break;
3429 case GL_TEXTURE_3D:
3430 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].Current3D;
3431 texImage = texObj->Image[level];
3432 break;
3433 default:
3434 gl_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");
3435 return;
3436 }
3437
3438 if (!texImage) {
3439 /* invalid mipmap level */
3440 gl_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
3441 return;
3442 }
3443
3444 if (!texImage->IsCompressed) {
3445 gl_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB");
3446 return;
3447 }
3448
3449 if (!img)
3450 return;
3451
3452 if (ctx->Driver.GetCompressedTexImage) {
3453 (*ctx->Driver.GetCompressedTexImage)(ctx, target, level, img, texObj,
3454 texImage);
3455 }
3456 else {
3457 gl_problem(ctx, "Driver doesn't implement GetCompressedTexImage");
3458 }
3459 }