Replace the flags Mesa was using for ctx->NewState with a new set
[mesa.git] / src / mesa / main / teximage.c
1 /* $Id: teximage.c,v 1.56 2000/10/30 13:32:01 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 "span.h"
39 #include "state.h"
40 #include "teximage.h"
41 #include "texstate.h"
42 #include "types.h"
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->CurrentD[1];
548 case GL_PROXY_TEXTURE_1D:
549 return ctx->Texture.Proxy1D;
550 case GL_TEXTURE_2D:
551 return texUnit->CurrentD[2];
552 case GL_PROXY_TEXTURE_2D:
553 return ctx->Texture.Proxy2D;
554 case GL_TEXTURE_3D:
555 return texUnit->CurrentD[3];
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->CurrentD[1]->Image[level];
588 case GL_PROXY_TEXTURE_1D:
589 return ctx->Texture.Proxy1D->Image[level];
590 case GL_TEXTURE_2D:
591 return texUnit->CurrentD[2]->Image[level];
592 case GL_PROXY_TEXTURE_2D:
593 return ctx->Texture.Proxy2D->Image[level];
594 case GL_TEXTURE_3D:
595 return texUnit->CurrentD[3]->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->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE) {
928 _mesa_update_image_transfer_state(ctx);
929 }
930
931 if (ctx->ImageTransferState & IMAGE_CONVOLUTION_BIT) {
932 adjust_texture_size_for_convolution(ctx, dimensions,
933 &convWidth, &convHeight);
934 }
935
936 texImage->Data = (GLchan *) MALLOC(convWidth * convHeight * depth
937 * components * sizeof(GLchan) + EXTRA_BYTE);
938 if (!texImage->Data)
939 return; /* out of memory */
940
941 fill_texture_image(ctx, dimensions, texImage->Format, texImage->Data,
942 width, height, depth, 0, 0, 0,
943 convWidth * components * sizeof(GLchan),
944 convWidth * convHeight * components * sizeof(GLchan),
945 srcFormat, srcType, pixels, srcPacking);
946 }
947
948
949
950 /*
951 * glTexImage[123]D can accept a NULL image pointer. In this case we
952 * create a texture image with unspecified image contents per the OpenGL
953 * spec. This function creates an empty image for the given texture image.
954 */
955 static void
956 make_null_texture( struct gl_texture_image *texImage )
957 {
958 GLint components;
959 GLint numPixels;
960
961 ASSERT(texImage);
962 ASSERT(!texImage->Data);
963
964 components = components_in_intformat(texImage->IntFormat);
965 numPixels = texImage->Width * texImage->Height * texImage->Depth;
966
967 texImage->Data = (GLchan *) MALLOC( numPixels * components * sizeof(GLchan)
968 + EXTRA_BYTE );
969
970 /*
971 * Let's see if anyone finds this. If glTexImage2D() is called with
972 * a NULL image pointer then load the texture image with something
973 * interesting instead of leaving it indeterminate.
974 */
975 if (texImage->Data) {
976 static const char message[8][32] = {
977 " X X XXXXX XXX X ",
978 " XX XX X X X X X ",
979 " X X X X X X X ",
980 " X X XXXX XXX XXXXX ",
981 " X X X X X X ",
982 " X X X X X X X ",
983 " X X XXXXX XXX X X ",
984 " "
985 };
986
987 GLchan *imgPtr = texImage->Data;
988 GLint i, j, k;
989 for (i = 0; i < texImage->Height; i++) {
990 GLint srcRow = 7 - i % 8;
991 for (j = 0; j < texImage->Width; j++) {
992 GLint srcCol = j % 32;
993 GLint texel = (message[srcRow][srcCol]=='X') ? CHAN_MAX : 70;
994 for (k=0;k<components;k++) {
995 *imgPtr++ = (GLchan) texel;
996 }
997 }
998 }
999 }
1000 }
1001
1002
1003
1004 /*
1005 * This is called when a proxy texture test fails, we set all the
1006 * image members (except DriverData) to zero.
1007 */
1008 static void
1009 clear_proxy_teximage(struct gl_texture_image *img)
1010 {
1011 ASSERT(img);
1012 img->Format = 0;
1013 img->IntFormat = 0;
1014 img->RedBits = 0;
1015 img->GreenBits = 0;
1016 img->BlueBits = 0;
1017 img->AlphaBits = 0;
1018 img->IntensityBits = 0;
1019 img->LuminanceBits = 0;
1020 img->IndexBits = 0;
1021 img->Border = 0;
1022 img->Width = 0;
1023 img->Height = 0;
1024 img->Depth = 0;
1025 img->Width2 = 0;
1026 img->Height2 = 0;
1027 img->Depth2 = 0;
1028 img->WidthLog2 = 0;
1029 img->HeightLog2 = 0;
1030 img->DepthLog2 = 0;
1031 img->Data = NULL;
1032 img->IsCompressed = 0;
1033 img->CompressedSize = 0;
1034 }
1035
1036
1037
1038 /*
1039 * Test glTexImage[123]D() parameters for errors.
1040 * Input:
1041 * dimensions - must be 1 or 2 or 3
1042 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
1043 */
1044 static GLboolean
1045 texture_error_check( GLcontext *ctx, GLenum target,
1046 GLint level, GLint internalFormat,
1047 GLenum format, GLenum type,
1048 GLuint dimensions,
1049 GLint width, GLint height,
1050 GLint depth, GLint border )
1051 {
1052 GLboolean isProxy;
1053 GLint iformat;
1054
1055 if (dimensions == 1) {
1056 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_1D);
1057 if (target != GL_TEXTURE_1D && !isProxy) {
1058 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1059 return GL_TRUE;
1060 }
1061 }
1062 else if (dimensions == 2) {
1063 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_2D);
1064 if (target != GL_TEXTURE_2D && !isProxy &&
1065 !(ctx->Extensions.ARB_texture_cube_map &&
1066 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1067 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
1068 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
1069 return GL_TRUE;
1070 }
1071 }
1072 else if (dimensions == 3) {
1073 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_3D);
1074 if (target != GL_TEXTURE_3D && !isProxy) {
1075 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
1076 return GL_TRUE;
1077 }
1078 }
1079 else {
1080 gl_problem( ctx, "bad dims in texture_error_check" );
1081 return GL_TRUE;
1082 }
1083
1084 /* Border */
1085 if (border != 0 && border != 1) {
1086 if (!isProxy) {
1087 char message[100];
1088 sprintf(message, "glTexImage%dD(border)", dimensions);
1089 gl_error(ctx, GL_INVALID_VALUE, message);
1090 }
1091 return GL_TRUE;
1092 }
1093
1094 /* Width */
1095 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
1096 || logbase2( width - 2 * border ) < 0) {
1097 if (!isProxy) {
1098 char message[100];
1099 sprintf(message, "glTexImage%dD(width)", dimensions);
1100 gl_error(ctx, GL_INVALID_VALUE, message);
1101 }
1102 return GL_TRUE;
1103 }
1104
1105 /* Height */
1106 if (dimensions >= 2) {
1107 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
1108 || logbase2( height - 2 * border ) < 0) {
1109 if (!isProxy) {
1110 char message[100];
1111 sprintf(message, "glTexImage%dD(height)", dimensions);
1112 gl_error(ctx, GL_INVALID_VALUE, message);
1113 }
1114 return GL_TRUE;
1115 }
1116 }
1117
1118 /* For cube map, width must equal height */
1119 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1120 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1121 if (width != height) {
1122 if (!isProxy) {
1123 gl_error(ctx, GL_INVALID_VALUE, "glTexImage2D(width != height)");
1124 }
1125 return GL_TRUE;
1126 }
1127 }
1128
1129 /* Depth */
1130 if (dimensions >= 3) {
1131 if (depth < 2 * border || depth > 2 + ctx->Const.MaxTextureSize
1132 || logbase2( depth - 2 * border ) < 0) {
1133 if (!isProxy) {
1134 gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(depth)" );
1135 }
1136 return GL_TRUE;
1137 }
1138 }
1139
1140 /* Level */
1141 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1142 if (!isProxy) {
1143 char message[100];
1144 sprintf(message, "glTexImage%dD(level)", dimensions);
1145 gl_error(ctx, GL_INVALID_VALUE, message);
1146 }
1147 return GL_TRUE;
1148 }
1149
1150 iformat = _mesa_base_tex_format( ctx, internalFormat );
1151 if (iformat < 0) {
1152 if (!isProxy) {
1153 char message[100];
1154 sprintf(message, "glTexImage%dD(internalFormat)", dimensions);
1155 gl_error(ctx, GL_INVALID_VALUE, message);
1156 }
1157 return GL_TRUE;
1158 }
1159
1160 if (!is_compressed_format(ctx, internalFormat)) {
1161 if (!_mesa_is_legal_format_and_type( format, type )) {
1162 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
1163 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
1164 */
1165 if (!isProxy) {
1166 char message[100];
1167 sprintf(message, "glTexImage%dD(format or type)", dimensions);
1168 gl_error(ctx, GL_INVALID_OPERATION, message);
1169 }
1170 return GL_TRUE;
1171 }
1172 }
1173
1174 /* if we get here, the parameters are OK */
1175 return GL_FALSE;
1176 }
1177
1178
1179
1180 /*
1181 * Test glTexSubImage[123]D() parameters for errors.
1182 * Input:
1183 * dimensions - must be 1 or 2 or 3
1184 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
1185 */
1186 static GLboolean
1187 subtexture_error_check( GLcontext *ctx, GLuint dimensions,
1188 GLenum target, GLint level,
1189 GLint xoffset, GLint yoffset, GLint zoffset,
1190 GLint width, GLint height, GLint depth,
1191 GLenum format, GLenum type )
1192 {
1193 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1194 struct gl_texture_image *destTex;
1195
1196 if (dimensions == 1) {
1197 if (target != GL_TEXTURE_1D) {
1198 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
1199 return GL_TRUE;
1200 }
1201 }
1202 else if (dimensions == 2) {
1203 if (ctx->Extensions.ARB_texture_cube_map) {
1204 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1205 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1206 target != GL_TEXTURE_2D) {
1207 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1208 return GL_TRUE;
1209 }
1210 }
1211 else if (target != GL_TEXTURE_2D) {
1212 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1213 return GL_TRUE;
1214 }
1215 }
1216 else if (dimensions == 3) {
1217 if (target != GL_TEXTURE_3D) {
1218 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
1219 return GL_TRUE;
1220 }
1221 }
1222 else {
1223 gl_problem( ctx, "bad dims in texture_error_check" );
1224 return GL_TRUE;
1225 }
1226
1227 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1228 gl_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level)");
1229 return GL_TRUE;
1230 }
1231
1232 if (width < 0) {
1233 char message[100];
1234 sprintf(message, "glTexSubImage%dD(width)", dimensions);
1235 gl_error(ctx, GL_INVALID_VALUE, message);
1236 return GL_TRUE;
1237 }
1238 if (height < 0 && dimensions > 1) {
1239 char message[100];
1240 sprintf(message, "glTexSubImage%dD(height)", dimensions);
1241 gl_error(ctx, GL_INVALID_VALUE, message);
1242 return GL_TRUE;
1243 }
1244 if (depth < 0 && dimensions > 2) {
1245 char message[100];
1246 sprintf(message, "glTexSubImage%dD(depth)", dimensions);
1247 gl_error(ctx, GL_INVALID_VALUE, message);
1248 return GL_TRUE;
1249 }
1250
1251 destTex = texUnit->CurrentD[2]->Image[level];
1252 if (!destTex) {
1253 gl_error(ctx, GL_INVALID_OPERATION, "glTexSubImage2D");
1254 return GL_TRUE;
1255 }
1256
1257 if (xoffset < -((GLint)destTex->Border)) {
1258 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset)");
1259 return GL_TRUE;
1260 }
1261 if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
1262 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset+width)");
1263 return GL_TRUE;
1264 }
1265 if (dimensions > 1) {
1266 if (yoffset < -((GLint)destTex->Border)) {
1267 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset)");
1268 return GL_TRUE;
1269 }
1270 if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) {
1271 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset+height)");
1272 return GL_TRUE;
1273 }
1274 }
1275 if (dimensions > 2) {
1276 if (zoffset < -((GLint)destTex->Border)) {
1277 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)");
1278 return GL_TRUE;
1279 }
1280 if (zoffset + depth > (GLint) (destTex->Depth+destTex->Border)) {
1281 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)");
1282 return GL_TRUE;
1283 }
1284 }
1285
1286 if (!is_compressed_format(ctx, destTex->IntFormat)) {
1287 if (!_mesa_is_legal_format_and_type(format, type)) {
1288 char message[100];
1289 sprintf(message, "glTexSubImage%dD(format or type)", dimensions);
1290 gl_error(ctx, GL_INVALID_ENUM, message);
1291 return GL_TRUE;
1292 }
1293 }
1294
1295 return GL_FALSE;
1296 }
1297
1298
1299 /*
1300 * Test glCopyTexImage[12]D() parameters for errors.
1301 * Input: dimensions - must be 1 or 2 or 3
1302 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
1303 */
1304 static GLboolean
1305 copytexture_error_check( GLcontext *ctx, GLuint dimensions,
1306 GLenum target, GLint level, GLint internalFormat,
1307 GLint width, GLint height, GLint border )
1308 {
1309 GLint iformat;
1310
1311 if (dimensions == 1) {
1312 if (target != GL_TEXTURE_1D) {
1313 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
1314 return GL_TRUE;
1315 }
1316 }
1317 else if (dimensions == 2) {
1318 if (ctx->Extensions.ARB_texture_cube_map) {
1319 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1320 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1321 target != GL_TEXTURE_2D) {
1322 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1323 return GL_TRUE;
1324 }
1325 }
1326 else if (target != GL_TEXTURE_2D) {
1327 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1328 return GL_TRUE;
1329 }
1330 }
1331
1332 /* Border */
1333 if (border!=0 && border!=1) {
1334 char message[100];
1335 sprintf(message, "glCopyTexImage%dD(border)", dimensions);
1336 gl_error(ctx, GL_INVALID_VALUE, message);
1337 return GL_TRUE;
1338 }
1339
1340 /* Width */
1341 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
1342 || logbase2( width - 2 * border ) < 0) {
1343 char message[100];
1344 sprintf(message, "glCopyTexImage%dD(width)", dimensions);
1345 gl_error(ctx, GL_INVALID_VALUE, message);
1346 return GL_TRUE;
1347 }
1348
1349 /* Height */
1350 if (dimensions >= 2) {
1351 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
1352 || logbase2( height - 2 * border ) < 0) {
1353 char message[100];
1354 sprintf(message, "glCopyTexImage%dD(height)", dimensions);
1355 gl_error(ctx, GL_INVALID_VALUE, message);
1356 return GL_TRUE;
1357 }
1358 }
1359
1360 /* For cube map, width must equal height */
1361 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1362 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1363 if (width != height) {
1364 gl_error(ctx, GL_INVALID_VALUE, "glCopyTexImage2D(width != height)");
1365 return GL_TRUE;
1366 }
1367 }
1368
1369 /* Level */
1370 if (level<0 || level>=ctx->Const.MaxTextureLevels) {
1371 char message[100];
1372 sprintf(message, "glCopyTexImage%dD(level)", dimensions);
1373 gl_error(ctx, GL_INVALID_VALUE, message);
1374 return GL_TRUE;
1375 }
1376
1377 iformat = _mesa_base_tex_format( ctx, internalFormat );
1378 if (iformat < 0) {
1379 char message[100];
1380 sprintf(message, "glCopyTexImage%dD(internalFormat)", dimensions);
1381 gl_error(ctx, GL_INVALID_VALUE, message);
1382 return GL_TRUE;
1383 }
1384
1385 /* if we get here, the parameters are OK */
1386 return GL_FALSE;
1387 }
1388
1389
1390 static GLboolean
1391 copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
1392 GLenum target, GLint level,
1393 GLint xoffset, GLint yoffset, GLint zoffset,
1394 GLsizei width, GLsizei height )
1395 {
1396 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1397 struct gl_texture_image *teximage;
1398
1399 if (dimensions == 1) {
1400 if (target != GL_TEXTURE_1D) {
1401 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
1402 return GL_TRUE;
1403 }
1404 }
1405 else if (dimensions == 2) {
1406 if (ctx->Extensions.ARB_texture_cube_map) {
1407 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1408 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1409 target != GL_TEXTURE_2D) {
1410 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1411 return GL_TRUE;
1412 }
1413 }
1414 else if (target != GL_TEXTURE_2D) {
1415 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1416 return GL_TRUE;
1417 }
1418 }
1419 else if (dimensions == 3) {
1420 if (target != GL_TEXTURE_3D) {
1421 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" );
1422 return GL_TRUE;
1423 }
1424 }
1425
1426 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1427 char message[100];
1428 sprintf(message, "glCopyTexSubImage%dD(level)", dimensions);
1429 gl_error(ctx, GL_INVALID_VALUE, message);
1430 return GL_TRUE;
1431 }
1432
1433 if (width < 0) {
1434 char message[100];
1435 sprintf(message, "glCopyTexSubImage%dD(width)", dimensions );
1436 gl_error(ctx, GL_INVALID_VALUE, message);
1437 return GL_TRUE;
1438 }
1439 if (dimensions > 1 && height < 0) {
1440 char message[100];
1441 sprintf(message, "glCopyTexSubImage%dD(height)", dimensions );
1442 gl_error(ctx, GL_INVALID_VALUE, message);
1443 return GL_TRUE;
1444 }
1445
1446 teximage = texUnit->CurrentD[dimensions]->Image[level];
1447 if (!teximage) {
1448 char message[100];
1449 sprintf(message, "glCopyTexSubImage%dD(undefined texture)", dimensions);
1450 gl_error(ctx, GL_INVALID_OPERATION, message);
1451 return GL_TRUE;
1452 }
1453
1454 if (xoffset < -((GLint)teximage->Border)) {
1455 char message[100];
1456 sprintf(message, "glCopyTexSubImage%dD(xoffset)", dimensions);
1457 gl_error(ctx, GL_INVALID_VALUE, message);
1458 return GL_TRUE;
1459 }
1460 if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) {
1461 char message[100];
1462 sprintf(message, "glCopyTexSubImage%dD(xoffset+width)", dimensions);
1463 gl_error(ctx, GL_INVALID_VALUE, message);
1464 return GL_TRUE;
1465 }
1466 if (dimensions > 1) {
1467 if (yoffset < -((GLint)teximage->Border)) {
1468 char message[100];
1469 sprintf(message, "glCopyTexSubImage%dD(yoffset)", dimensions);
1470 gl_error(ctx, GL_INVALID_VALUE, message);
1471 return GL_TRUE;
1472 }
1473 /* NOTE: we're adding the border here, not subtracting! */
1474 if (yoffset+height > (GLint) (teximage->Height+teximage->Border)) {
1475 char message[100];
1476 sprintf(message, "glCopyTexSubImage%dD(yoffset+height)", dimensions);
1477 gl_error(ctx, GL_INVALID_VALUE, message);
1478 return GL_TRUE;
1479 }
1480 }
1481
1482 if (dimensions > 2) {
1483 if (zoffset < -((GLint)teximage->Border)) {
1484 char message[100];
1485 sprintf(message, "glCopyTexSubImage%dD(zoffset)", dimensions);
1486 gl_error(ctx, GL_INVALID_VALUE, message);
1487 return GL_TRUE;
1488 }
1489 if (zoffset > (GLint) (teximage->Depth+teximage->Border)) {
1490 char message[100];
1491 sprintf(message, "glCopyTexSubImage%dD(zoffset+depth)", dimensions);
1492 gl_error(ctx, GL_INVALID_VALUE, message);
1493 return GL_TRUE;
1494 }
1495 }
1496
1497 /* if we get here, the parameters are OK */
1498 return GL_FALSE;
1499 }
1500
1501
1502
1503
1504 /*
1505 * Turn generic compressed formats into specific compressed format.
1506 * Some of the compressed formats we don't support, so we
1507 * fall back to the uncompressed format. (See issue 15 of
1508 * the GL_ARB_texture_compression specification.)
1509 */
1510 static GLint
1511 get_specific_compressed_tex_format(GLcontext *ctx,
1512 GLint ifmt, GLint numDimensions,
1513 GLint *levelp,
1514 GLsizei *widthp,
1515 GLsizei *heightp,
1516 GLsizei *depthp,
1517 GLint *borderp,
1518 GLenum *formatp,
1519 GLenum *typep)
1520 {
1521 char message[100];
1522 GLint internalFormat = ifmt;
1523
1524 if (ctx->Extensions.ARB_texture_compression
1525 && ctx->Driver.SpecificCompressedTexFormat) {
1526 /*
1527 * First, ask the driver for the specific format.
1528 * We do this for all formats, since we may want to
1529 * fake one compressed format for another.
1530 */
1531 internalFormat = (*ctx->Driver.SpecificCompressedTexFormat)
1532 (ctx, internalFormat, numDimensions,
1533 levelp,
1534 widthp, heightp, depthp,
1535 borderp, formatp, typep);
1536 }
1537
1538 /*
1539 * Now, convert any generic format left to an uncompressed
1540 * specific format. If the driver does not support compression
1541 * of the format, we must drop back to the uncompressed format.
1542 * See issue 15 of the GL_ARB_texture_compression specification.
1543 */
1544 switch (internalFormat) {
1545 case GL_COMPRESSED_ALPHA_ARB:
1546 if (ctx && !ctx->Extensions.ARB_texture_compression) {
1547 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1548 gl_error(ctx, GL_INVALID_VALUE, message);
1549 return -1;
1550 }
1551 internalFormat = GL_ALPHA;
1552 break;
1553 case GL_COMPRESSED_LUMINANCE_ARB:
1554 if (ctx && !ctx->Extensions.ARB_texture_compression) {
1555 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1556 gl_error(ctx, GL_INVALID_VALUE, message);
1557 return -1;
1558 }
1559 internalFormat = GL_LUMINANCE;
1560 break;
1561 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
1562 if (ctx && !ctx->Extensions.ARB_texture_compression) {
1563 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1564 gl_error(ctx, GL_INVALID_VALUE, message);
1565 return -1;
1566 }
1567 internalFormat = GL_LUMINANCE_ALPHA;
1568 break;
1569 case GL_COMPRESSED_INTENSITY_ARB:
1570 if (ctx && !ctx->Extensions.ARB_texture_compression) {
1571 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1572 gl_error(ctx, GL_INVALID_VALUE, message);
1573 return -1;
1574 }
1575 internalFormat = GL_INTENSITY;
1576 break;
1577 case GL_COMPRESSED_RGB_ARB:
1578 if (ctx && !ctx->Extensions.ARB_texture_compression) {
1579 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1580 gl_error(ctx, GL_INVALID_VALUE, message);
1581 return -1;
1582 }
1583 internalFormat = GL_RGB;
1584 break;
1585 case GL_COMPRESSED_RGBA_ARB:
1586 if (ctx && !ctx->Extensions.ARB_texture_compression) {
1587 sprintf(message, "glTexImage%dD(internalFormat)", numDimensions);
1588 gl_error(ctx, GL_INVALID_VALUE, message);
1589 return -1;
1590 }
1591 internalFormat = GL_RGBA;
1592 break;
1593 default:
1594 /* silence compiler warning */
1595 ;
1596 }
1597 return internalFormat;
1598 }
1599
1600
1601 /*
1602 * Called from the API. Note that width includes the border.
1603 */
1604 void
1605 _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
1606 GLsizei width, GLint border, GLenum format,
1607 GLenum type, const GLvoid *pixels )
1608 {
1609 GLsizei postConvWidth;
1610 GET_CURRENT_CONTEXT(ctx);
1611 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage1D");
1612
1613 postConvWidth = width;
1614 adjust_texture_size_for_convolution(ctx, 1, &postConvWidth, NULL);
1615
1616 if (target==GL_TEXTURE_1D) {
1617 struct gl_texture_unit *texUnit;
1618 struct gl_texture_object *texObj;
1619 struct gl_texture_image *texImage;
1620 GLint ifmt;
1621
1622 ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 1,
1623 &level,
1624 &width, 0, 0,
1625 &border, &format, &type);
1626 if (ifmt < 0) {
1627 /*
1628 * The error here is that we were sent a generic compressed
1629 * format, but the extension is not supported.
1630 */
1631 return;
1632 }
1633 else {
1634 internalFormat = ifmt;
1635 }
1636
1637 if (texture_error_check(ctx, target, level, internalFormat,
1638 format, type, 1, postConvWidth, 1, 1, border)) {
1639 return; /* error in texture image was detected */
1640 }
1641
1642 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1643 texObj = texUnit->CurrentD[1];
1644 texImage = texObj->Image[level];
1645
1646 if (!texImage) {
1647 texImage = _mesa_alloc_texture_image();
1648 texObj->Image[level] = texImage;
1649 if (!texImage) {
1650 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
1651 return;
1652 }
1653 }
1654 else if (texImage->Data) {
1655 FREE(texImage->Data);
1656 texImage->Data = NULL;
1657 }
1658
1659 /* setup the teximage struct's fields */
1660 init_texture_image(ctx, texImage, postConvWidth, 1, 1, border, internalFormat);
1661
1662 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
1663 _mesa_update_image_transfer_state(ctx);
1664
1665 /* process the texture image */
1666 if (pixels) {
1667 GLboolean retain = GL_TRUE;
1668 GLboolean success = GL_FALSE;
1669 if (!ctx->ImageTransferState && ctx->Driver.TexImage1D) {
1670 /* let device driver try to use raw image */
1671 success = (*ctx->Driver.TexImage1D)( ctx, target, level, format,
1672 type, pixels, &ctx->Unpack,
1673 texObj, texImage, &retain);
1674 }
1675 if (retain || !success) {
1676 /* make internal copy of the texture image */
1677 make_texture_image(ctx, 1, texImage, width, 1, 1,
1678 format, type, pixels, &ctx->Unpack);
1679 if (!success && ctx->Driver.TexImage1D) {
1680 /* let device driver try to use unpacked image */
1681 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1682 GL_UNSIGNED_BYTE, texImage->Data,
1683 &_mesa_native_packing,
1684 texObj, texImage, &retain);
1685 }
1686 }
1687 if (!retain && texImage->Data) {
1688 FREE(texImage->Data);
1689 texImage->Data = NULL;
1690 }
1691 }
1692 else {
1693 make_null_texture(texImage);
1694 if (ctx->Driver.TexImage1D) {
1695 GLboolean retain;
1696 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1697 GL_UNSIGNED_BYTE, texImage->Data,
1698 &_mesa_native_packing,
1699 texObj, texImage, &retain);
1700 }
1701 }
1702
1703 /* state update */
1704 gl_put_texobj_on_dirty_list( ctx, texObj );
1705 ctx->NewState |= _NEW_TEXTURE;
1706 }
1707 else if (target == GL_PROXY_TEXTURE_1D) {
1708 /* Proxy texture: check for errors and update proxy state */
1709 GLenum error = texture_error_check(ctx, target, level, internalFormat,
1710 format, type, 1, width, 1, 1, border);
1711 if (!error && ctx->Driver.TestProxyTexImage) {
1712 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
1713 internalFormat, format, type,
1714 width, 1, 1, border);
1715 }
1716 if (error) {
1717 /* if error, clear all proxy texture image parameters */
1718 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1719 clear_proxy_teximage(ctx->Texture.Proxy1D->Image[level]);
1720 }
1721 }
1722 else {
1723 /* if no error, update proxy texture image parameters */
1724 init_texture_image(ctx, ctx->Texture.Proxy1D->Image[level],
1725 width, 1, 1, border, internalFormat);
1726 }
1727 }
1728 else {
1729 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1730 return;
1731 }
1732 }
1733
1734
1735 void
1736 _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
1737 GLsizei width, GLsizei height, GLint border,
1738 GLenum format, GLenum type,
1739 const GLvoid *pixels )
1740 {
1741 GLsizei postConvWidth, postConvHeight;
1742 GET_CURRENT_CONTEXT(ctx);
1743 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage2D");
1744
1745 postConvWidth = width;
1746 postConvHeight = height;
1747 adjust_texture_size_for_convolution(ctx, 2, &postConvWidth,&postConvHeight);
1748
1749 if (target==GL_TEXTURE_2D ||
1750 (ctx->Extensions.ARB_texture_cube_map &&
1751 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1752 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
1753 struct gl_texture_unit *texUnit;
1754 struct gl_texture_object *texObj;
1755 struct gl_texture_image *texImage;
1756 GLint ifmt;
1757
1758 ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 2,
1759 &level,
1760 &width, &height, 0,
1761 &border, &format, &type);
1762 if (ifmt < 0) {
1763 /*
1764 * The error here is that we were sent a generic compressed
1765 * format, but the extension is not supported.
1766 */
1767 return;
1768 }
1769 else {
1770 internalFormat = ifmt;
1771 }
1772
1773 if (texture_error_check(ctx, target, level, internalFormat,
1774 format, type, 2, postConvWidth, postConvHeight,
1775 1, border)) {
1776 return; /* error in texture image was detected */
1777 }
1778
1779 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1780 texObj = _mesa_select_tex_object(ctx, texUnit, target);
1781 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1782
1783 if (!texImage) {
1784 texImage = _mesa_alloc_texture_image();
1785 set_tex_image(texObj, target, level, texImage);
1786 /*texObj->Image[level] = texImage;*/
1787 if (!texImage) {
1788 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1789 return;
1790 }
1791 }
1792 else if (texImage->Data) {
1793 FREE(texImage->Data);
1794 texImage->Data = NULL;
1795 }
1796
1797 /* setup the teximage struct's fields */
1798 init_texture_image(ctx, texImage, postConvWidth, postConvHeight,
1799 1, border, internalFormat);
1800
1801 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
1802 _mesa_update_image_transfer_state(ctx);
1803
1804 /* process the texture image */
1805 if (pixels) {
1806 GLboolean retain = GL_TRUE;
1807 GLboolean success = GL_FALSE;
1808 if (!ctx->ImageTransferState && ctx->Driver.TexImage2D) {
1809 /* let device driver try to use raw image */
1810 success = (*ctx->Driver.TexImage2D)( ctx, target, level, format,
1811 type, pixels, &ctx->Unpack,
1812 texObj, texImage, &retain);
1813 }
1814 if (retain || !success) {
1815 /* make internal copy of the texture image */
1816 make_texture_image(ctx, 2, texImage, width, height, 1,
1817 format, type, pixels, &ctx->Unpack);
1818 if (!success && ctx->Driver.TexImage2D) {
1819 /* let device driver try to use unpacked image */
1820 (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1821 GL_UNSIGNED_BYTE, texImage->Data,
1822 &_mesa_native_packing,
1823 texObj, texImage, &retain);
1824 }
1825 }
1826 if (!retain && texImage->Data) {
1827 FREE(texImage->Data);
1828 texImage->Data = NULL;
1829 }
1830 }
1831 else {
1832 make_null_texture(texImage);
1833 if (ctx->Driver.TexImage2D) {
1834 GLboolean retain;
1835 (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1836 GL_UNSIGNED_BYTE, texImage->Data,
1837 &_mesa_native_packing,
1838 texObj, texImage, &retain);
1839 }
1840 }
1841
1842 #define OLD_DD_TEXTURE
1843 #ifdef OLD_DD_TEXTURE
1844 /* XXX this will be removed in the future */
1845 if (ctx->Driver.TexImage) {
1846 (*ctx->Driver.TexImage)( ctx, target, texObj, level, internalFormat,
1847 texImage );
1848 }
1849 #endif
1850
1851 /* state update */
1852 gl_put_texobj_on_dirty_list( ctx, texObj );
1853 ctx->NewState |= _NEW_TEXTURE;
1854 }
1855 else if (target == GL_PROXY_TEXTURE_2D) {
1856 /* Proxy texture: check for errors and update proxy state */
1857 GLenum error = texture_error_check(ctx, target, level, internalFormat,
1858 format, type, 2, width, height, 1, border);
1859 if (!error && ctx->Driver.TestProxyTexImage) {
1860 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
1861 internalFormat, format, type,
1862 width, height, 1, border);
1863 }
1864 if (error) {
1865 /* if error, clear all proxy texture image parameters */
1866 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1867 clear_proxy_teximage(ctx->Texture.Proxy2D->Image[level]);
1868 }
1869 }
1870 else {
1871 /* if no error, update proxy texture image parameters */
1872 init_texture_image(ctx,
1873 ctx->Texture.Proxy2D->Image[level],
1874 width, height, 1, border, internalFormat);
1875 }
1876 }
1877 else {
1878 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
1879 return;
1880 }
1881 }
1882
1883
1884 /*
1885 * Called by the API or display list executor.
1886 * Note that width and height include the border.
1887 */
1888 void
1889 _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
1890 GLsizei width, GLsizei height, GLsizei depth,
1891 GLint border, GLenum format, GLenum type,
1892 const GLvoid *pixels )
1893 {
1894 GET_CURRENT_CONTEXT(ctx);
1895 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage3D");
1896
1897 if (target==GL_TEXTURE_3D_EXT) {
1898 struct gl_texture_unit *texUnit;
1899 struct gl_texture_object *texObj;
1900 struct gl_texture_image *texImage;
1901 GLint ifmt;
1902
1903 ifmt = get_specific_compressed_tex_format(ctx, internalFormat, 3,
1904 &level,
1905 &width, &height, &depth,
1906 &border, &format, &type);
1907 if (ifmt < 0) {
1908 /*
1909 * The error here is that we were sent a generic compressed
1910 * format, but the extension is not supported.
1911 */
1912 return;
1913 }
1914 else {
1915 internalFormat = ifmt;
1916 }
1917
1918 if (texture_error_check(ctx, target, level, internalFormat,
1919 format, type, 3, width, height, depth, border)) {
1920 return; /* error in texture image was detected */
1921 }
1922
1923 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1924 texObj = texUnit->CurrentD[3];
1925 texImage = texObj->Image[level];
1926
1927 if (!texImage) {
1928 texImage = _mesa_alloc_texture_image();
1929 texObj->Image[level] = texImage;
1930 if (!texImage) {
1931 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
1932 return;
1933 }
1934 }
1935 else if (texImage->Data) {
1936 FREE(texImage->Data);
1937 texImage->Data = NULL;
1938 }
1939
1940 /* setup the teximage struct's fields */
1941 init_texture_image(ctx, texImage, width, height, depth,
1942 border, internalFormat);
1943
1944 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
1945 _mesa_update_image_transfer_state(ctx);
1946
1947 /* process the texture image */
1948 if (pixels) {
1949 GLboolean retain = GL_TRUE;
1950 GLboolean success = GL_FALSE;
1951 if (!ctx->ImageTransferState && ctx->Driver.TexImage3D) {
1952 /* let device driver try to use raw image */
1953 success = (*ctx->Driver.TexImage3D)( ctx, target, level, format,
1954 type, pixels, &ctx->Unpack,
1955 texObj, texImage, &retain);
1956 }
1957 if (retain || !success) {
1958 /* make internal copy of the texture image */
1959 make_texture_image(ctx, 3, texImage, width, height, depth,
1960 format, type, pixels, &ctx->Unpack);
1961 if (!success && ctx->Driver.TexImage3D) {
1962 /* let device driver try to use unpacked image */
1963 (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1964 GL_UNSIGNED_BYTE, texImage->Data,
1965 &_mesa_native_packing,
1966 texObj, texImage, &retain);
1967 }
1968 }
1969 if (!retain && texImage->Data) {
1970 FREE(texImage->Data);
1971 texImage->Data = NULL;
1972 }
1973 }
1974 else {
1975 make_null_texture(texImage);
1976 if (ctx->Driver.TexImage3D) {
1977 GLboolean retain;
1978 (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1979 GL_UNSIGNED_BYTE, texImage->Data,
1980 &_mesa_native_packing,
1981 texObj, texImage, &retain);
1982 }
1983 }
1984
1985 /* state update */
1986 gl_put_texobj_on_dirty_list( ctx, texObj );
1987 ctx->NewState |= _NEW_TEXTURE;
1988 }
1989 else if (target == GL_PROXY_TEXTURE_3D) {
1990 /* Proxy texture: check for errors and update proxy state */
1991 GLenum error = texture_error_check(ctx, target, level, internalFormat,
1992 format, type, 3, width, height, depth, border);
1993 if (!error && ctx->Driver.TestProxyTexImage) {
1994 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
1995 internalFormat, format, type,
1996 width, height, depth, border);
1997 }
1998 if (error) {
1999 /* if error, clear all proxy texture image parameters */
2000 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
2001 clear_proxy_teximage(ctx->Texture.Proxy3D->Image[level]);
2002 }
2003 }
2004 else {
2005 /* if no error, update proxy texture image parameters */
2006 init_texture_image(ctx, ctx->Texture.Proxy3D->Image[level],
2007 width, height, depth, border, internalFormat);
2008 }
2009 }
2010 else {
2011 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
2012 return;
2013 }
2014 }
2015
2016
2017 void
2018 _mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
2019 GLsizei width, GLsizei height, GLsizei depth,
2020 GLint border, GLenum format, GLenum type,
2021 const GLvoid *pixels )
2022 {
2023 _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height,
2024 depth, border, format, type, pixels);
2025 }
2026
2027
2028 /*
2029 * Fetch a texture image from the device driver.
2030 * Store the results in the given texture object at the given mipmap level.
2031 */
2032 void
2033 _mesa_get_teximage_from_driver( GLcontext *ctx, GLenum target, GLint level,
2034 const struct gl_texture_object *texObj )
2035 {
2036 GLvoid *image;
2037 GLenum imgFormat, imgType;
2038 GLboolean freeImage;
2039 struct gl_texture_image *texImage;
2040 GLint destComponents, numPixels, srcBytesPerTexel;
2041
2042 if (!ctx->Driver.GetTexImage)
2043 return;
2044
2045 image = (*ctx->Driver.GetTexImage)( ctx, target, level, texObj,
2046 &imgFormat, &imgType, &freeImage);
2047 if (!image)
2048 return;
2049
2050 texImage = texObj->Image[level];
2051 ASSERT(texImage);
2052 if (!texImage)
2053 return;
2054
2055 destComponents = components_in_intformat(texImage->Format);
2056 assert(destComponents > 0);
2057 numPixels = texImage->Width * texImage->Height * texImage->Depth;
2058 assert(numPixels > 0);
2059 srcBytesPerTexel = _mesa_bytes_per_pixel(imgFormat, imgType);
2060 assert(srcBytesPerTexel > 0);
2061
2062 if (!texImage->Data) {
2063 /* Allocate memory for the texture image data */
2064 texImage->Data = (GLchan *) MALLOC(numPixels * destComponents
2065 * sizeof(GLchan) + EXTRA_BYTE);
2066 }
2067
2068 if (imgFormat == texImage->Format && imgType == GL_UNSIGNED_BYTE) {
2069 /* We got lucky! The driver's format and type match Mesa's format. */
2070 if (texImage->Data) {
2071 MEMCPY(texImage->Data, image, numPixels * destComponents);
2072 }
2073 }
2074 else {
2075 /* Convert the texture image from the driver's format to Mesa's
2076 * internal format.
2077 */
2078 const GLint width = texImage->Width;
2079 const GLint height = texImage->Height;
2080 const GLint depth = texImage->Depth;
2081 const GLint destBytesPerRow = width * destComponents * sizeof(GLchan);
2082 const GLint srcBytesPerRow = width * srcBytesPerTexel;
2083 const GLenum dstType = GL_UNSIGNED_BYTE;
2084 const GLenum dstFormat = texImage->Format;
2085 const GLchan *srcPtr = (const GLchan *) image;
2086 GLchan *destPtr = texImage->Data;
2087
2088 if (texImage->Format == GL_COLOR_INDEX) {
2089 /* color index texture */
2090 GLint img, row;
2091 assert(imgFormat == GL_COLOR_INDEX);
2092 for (img = 0; img < depth; img++) {
2093 for (row = 0; row < height; row++) {
2094 _mesa_unpack_index_span(ctx, width, dstType, destPtr,
2095 imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
2096 destPtr += destBytesPerRow;
2097 srcPtr += srcBytesPerRow;
2098 }
2099 }
2100 }
2101 else {
2102 /* color texture */
2103 GLint img, row;
2104 for (img = 0; img < depth; img++) {
2105 for (row = 0; row < height; row++) {
2106 _mesa_unpack_chan_color_span(ctx, width, dstFormat, destPtr,
2107 imgFormat, imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
2108 destPtr += destBytesPerRow;
2109 srcPtr += srcBytesPerRow;
2110 }
2111 }
2112 }
2113 }
2114
2115 if (freeImage)
2116 FREE(image);
2117 }
2118
2119
2120 /*
2121 * Get all the mipmap images for a texture object from the device driver.
2122 * Actually, only get mipmap images if we're using a mipmap filter.
2123 */
2124 GLboolean
2125 _mesa_get_teximages_from_driver(GLcontext *ctx,
2126 struct gl_texture_object *texObj)
2127 {
2128 if (ctx->Driver.GetTexImage) {
2129 static const GLenum targets[] = {
2130 GL_TEXTURE_1D,
2131 GL_TEXTURE_2D,
2132 GL_TEXTURE_3D,
2133 GL_TEXTURE_CUBE_MAP_ARB,
2134 GL_TEXTURE_CUBE_MAP_ARB,
2135 GL_TEXTURE_CUBE_MAP_ARB
2136 };
2137 GLboolean needLambda = (texObj->MinFilter != texObj->MagFilter);
2138 GLenum target = targets[texObj->Dimensions - 1];
2139 if (needLambda) {
2140 GLint level;
2141 /* Get images for all mipmap levels. We might not need them
2142 * all but this is easier. We're on a (slow) software path
2143 * anyway.
2144 */
2145 for (level = 0; level <= texObj->P; level++) {
2146 struct gl_texture_image *texImg = texObj->Image[level];
2147 if (texImg && !texImg->Data) {
2148 _mesa_get_teximage_from_driver(ctx, target, level, texObj);
2149 if (!texImg->Data)
2150 return GL_FALSE; /* out of memory */
2151 }
2152 }
2153 }
2154 else {
2155 GLint level = texObj->BaseLevel;
2156 struct gl_texture_image *texImg = texObj->Image[level];
2157 if (texImg && !texImg->Data) {
2158 _mesa_get_teximage_from_driver(ctx, target, level, texObj);
2159 if (!texImg->Data)
2160 return GL_FALSE; /* out of memory */
2161 }
2162 }
2163 return GL_TRUE;
2164 }
2165 return GL_FALSE;
2166 }
2167
2168
2169
2170 void
2171 _mesa_GetTexImage( GLenum target, GLint level, GLenum format,
2172 GLenum type, GLvoid *pixels )
2173 {
2174 GET_CURRENT_CONTEXT(ctx);
2175 const struct gl_texture_unit *texUnit;
2176 const struct gl_texture_object *texObj;
2177 struct gl_texture_image *texImage;
2178 GLboolean discardImage;
2179
2180 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetTexImage");
2181
2182 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
2183 gl_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
2184 return;
2185 }
2186
2187 if (_mesa_sizeof_type(type) <= 0) {
2188 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
2189 return;
2190 }
2191
2192 if (_mesa_components_in_format(format) <= 0) {
2193 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
2194 return;
2195 }
2196
2197 if (!pixels)
2198 return;
2199
2200 texUnit = &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]);
2201 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2202 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
2203 if (!texObj || !texImage ||
2204 target == GL_PROXY_TEXTURE_1D ||
2205 target == GL_PROXY_TEXTURE_2D ||
2206 target == GL_PROXY_TEXTURE_3D) {
2207 gl_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)");
2208 return;
2209 }
2210
2211 if (!texImage) {
2212 /* invalid mipmap level */
2213 return;
2214 }
2215
2216 if (!texImage->Data) {
2217 /* try to get the texture image from the device driver */
2218 _mesa_get_teximage_from_driver(ctx, target, level, texObj);
2219 discardImage = GL_TRUE;
2220 }
2221 else {
2222 discardImage = GL_FALSE;
2223 }
2224
2225 if (texImage->Data) {
2226 GLint width = texImage->Width;
2227 GLint height = texImage->Height;
2228 GLint depth = texImage->Depth;
2229 GLint img, row;
2230
2231 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2232 _mesa_update_image_transfer_state(ctx);
2233
2234 if (ctx->ImageTransferState & IMAGE_CONVOLUTION_BIT) {
2235 /* convert texture image to GL_RGBA, GL_FLOAT */
2236 GLfloat *tmpImage, *convImage;
2237 const GLint comps = components_in_intformat(texImage->Format);
2238
2239 tmpImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
2240 if (!tmpImage) {
2241 gl_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
2242 return;
2243 }
2244 convImage = (GLfloat *) MALLOC(width * height * 4 * sizeof(GLfloat));
2245 if (!convImage) {
2246 FREE(tmpImage);
2247 gl_error(ctx, GL_OUT_OF_MEMORY, "glGetTexImage");
2248 return;
2249 }
2250
2251 for (img = 0; img < depth; img++) {
2252 GLint convWidth, convHeight;
2253
2254 /* convert to GL_RGBA */
2255 for (row = 0; row < height; row++) {
2256 const GLchan *src = texImage->Data
2257 + (img * height + row ) * width * comps;
2258 GLfloat *dst = tmpImage + row * width * 4;
2259 _mesa_unpack_float_color_span(ctx, width, GL_RGBA, dst,
2260 texImage->Format, GL_UNSIGNED_BYTE,
2261 src, &_mesa_native_packing,
2262 ctx->ImageTransferState & IMAGE_PRE_CONVOLUTION_BITS,
2263 GL_FALSE);
2264 }
2265
2266 convWidth = width;
2267 convHeight = height;
2268
2269 /* convolve */
2270 if (target == GL_TEXTURE_1D) {
2271 if (ctx->Pixel.Convolution1DEnabled) {
2272 _mesa_convolve_1d_image(ctx, &convWidth, tmpImage, convImage);
2273 }
2274 }
2275 else {
2276 if (ctx->Pixel.Convolution2DEnabled) {
2277 _mesa_convolve_2d_image(ctx, &convWidth, &convHeight,
2278 tmpImage, convImage);
2279 }
2280 else if (ctx->Pixel.Separable2DEnabled) {
2281 _mesa_convolve_sep_image(ctx, &convWidth, &convHeight,
2282 tmpImage, convImage);
2283 }
2284 }
2285
2286 /* pack convolved image */
2287 for (row = 0; row < convHeight; row++) {
2288 const GLfloat *src = convImage + row * convWidth * 4;
2289 GLvoid *dest = _mesa_image_address(&ctx->Pack, pixels,
2290 convWidth, convHeight,
2291 format, type, img, row, 0);
2292 _mesa_pack_float_rgba_span(ctx, convWidth,
2293 (const GLfloat(*)[4]) src,
2294 format, type, dest, &ctx->Pack,
2295 ctx->ImageTransferState & IMAGE_POST_CONVOLUTION_BITS);
2296 }
2297 }
2298
2299 FREE(tmpImage);
2300 FREE(convImage);
2301 }
2302 else {
2303 /* no convolution */
2304 for (img = 0; img < depth; img++) {
2305 for (row = 0; row < height; row++) {
2306 /* compute destination address in client memory */
2307 GLvoid *dest = _mesa_image_address( &ctx->Unpack, pixels,
2308 width, height, format, type, img, row, 0);
2309 assert(dest);
2310 if (texImage->Format == GL_RGBA) {
2311 /* simple case */
2312 const GLchan *src = texImage->Data
2313 + (img * height + row ) * width * 4;
2314 _mesa_pack_rgba_span( ctx, width, (CONST GLchan (*)[4]) src,
2315 format, type, dest, &ctx->Pack,
2316 ctx->ImageTransferState );
2317 }
2318 else {
2319 /* general case: convert row to RGBA format */
2320 GLchan rgba[MAX_WIDTH][4];
2321 GLint i;
2322 const GLchan *src;
2323 switch (texImage->Format) {
2324 case GL_ALPHA:
2325 src = texImage->Data + row * width;
2326 for (i = 0; i < width; i++) {
2327 rgba[i][RCOMP] = CHAN_MAX;
2328 rgba[i][GCOMP] = CHAN_MAX;
2329 rgba[i][BCOMP] = CHAN_MAX;
2330 rgba[i][ACOMP] = src[i];
2331 }
2332 break;
2333 case GL_LUMINANCE:
2334 src = texImage->Data + row * width;
2335 for (i = 0; i < width; i++) {
2336 rgba[i][RCOMP] = src[i];
2337 rgba[i][GCOMP] = src[i];
2338 rgba[i][BCOMP] = src[i];
2339 rgba[i][ACOMP] = CHAN_MAX;
2340 }
2341 break;
2342 case GL_LUMINANCE_ALPHA:
2343 src = texImage->Data + row * 2 * width;
2344 for (i = 0; i < width; i++) {
2345 rgba[i][RCOMP] = src[i*2+0];
2346 rgba[i][GCOMP] = src[i*2+0];
2347 rgba[i][BCOMP] = src[i*2+0];
2348 rgba[i][ACOMP] = src[i*2+1];
2349 }
2350 break;
2351 case GL_INTENSITY:
2352 src = texImage->Data + row * width;
2353 for (i = 0; i < width; i++) {
2354 rgba[i][RCOMP] = src[i];
2355 rgba[i][GCOMP] = src[i];
2356 rgba[i][BCOMP] = src[i];
2357 rgba[i][ACOMP] = CHAN_MAX;
2358 }
2359 break;
2360 case GL_RGB:
2361 src = texImage->Data + row * 3 * width;
2362 for (i = 0; i < width; i++) {
2363 rgba[i][RCOMP] = src[i*3+0];
2364 rgba[i][GCOMP] = src[i*3+1];
2365 rgba[i][BCOMP] = src[i*3+2];
2366 rgba[i][ACOMP] = CHAN_MAX;
2367 }
2368 break;
2369 case GL_COLOR_INDEX:
2370 gl_problem( ctx, "GL_COLOR_INDEX not implemented in gl_GetTexImage" );
2371 break;
2372 case GL_RGBA:
2373 default:
2374 gl_problem( ctx, "bad format in gl_GetTexImage" );
2375 }
2376 _mesa_pack_rgba_span( ctx, width, (const GLchan (*)[4])rgba,
2377 format, type, dest, &ctx->Pack,
2378 ctx->ImageTransferState );
2379 } /* format */
2380 } /* row */
2381 } /* img */
2382 } /* convolution */
2383
2384 /* if we got the teximage from the device driver we'll discard it now */
2385 if (discardImage) {
2386 FREE(texImage->Data);
2387 texImage->Data = NULL;
2388 }
2389 }
2390 }
2391
2392
2393
2394 void
2395 _mesa_TexSubImage1D( GLenum target, GLint level,
2396 GLint xoffset, GLsizei width,
2397 GLenum format, GLenum type,
2398 const GLvoid *pixels )
2399 {
2400 GET_CURRENT_CONTEXT(ctx);
2401 struct gl_texture_unit *texUnit;
2402 struct gl_texture_object *texObj;
2403 struct gl_texture_image *texImage;
2404 GLboolean success = GL_FALSE;
2405 GLsizei postConvWidth;
2406
2407 postConvWidth = width;
2408 adjust_texture_size_for_convolution(ctx, 1, &postConvWidth, NULL);
2409
2410 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
2411 postConvWidth, 1, 1, format, type)) {
2412 return; /* error was detected */
2413 }
2414
2415 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2416 texObj = texUnit->CurrentD[1];
2417 texImage = texObj->Image[level];
2418 assert(texImage);
2419
2420 if (width == 0 || !pixels)
2421 return; /* no-op, not an error */
2422
2423 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2424 _mesa_update_image_transfer_state(ctx);
2425
2426 if (!ctx->ImageTransferState && ctx->Driver.TexSubImage1D) {
2427 success = (*ctx->Driver.TexSubImage1D)( ctx, target, level, xoffset,
2428 width, format, type, pixels,
2429 &ctx->Unpack, texObj, texImage );
2430 }
2431 if (!success) {
2432 /* XXX if Driver.TexSubImage1D, unpack image and try again? */
2433 GLboolean retain = GL_TRUE;
2434 if (!texImage->Data) {
2435 _mesa_get_teximage_from_driver( ctx, target, level, texObj );
2436 if (!texImage->Data) {
2437 make_null_texture(texImage);
2438 }
2439 if (!texImage->Data)
2440 return; /* we're really out of luck! */
2441 }
2442
2443 fill_texture_image(ctx, 1, texImage->Format, texImage->Data,
2444 width, 1, 1, xoffset, 0, 0, /* size and offsets */
2445 0, 0, /* strides */
2446 format, type, pixels, &ctx->Unpack);
2447
2448 if (ctx->Driver.TexImage1D) {
2449 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
2450 GL_UNSIGNED_BYTE, texImage->Data,
2451 &_mesa_native_packing, texObj, texImage,
2452 &retain );
2453 }
2454
2455 if (!retain && texImage->Data) {
2456 FREE(texImage->Data);
2457 texImage->Data = NULL;
2458 }
2459 }
2460 }
2461
2462
2463 void
2464 _mesa_TexSubImage2D( GLenum target, GLint level,
2465 GLint xoffset, GLint yoffset,
2466 GLsizei width, GLsizei height,
2467 GLenum format, GLenum type,
2468 const GLvoid *pixels )
2469 {
2470 GET_CURRENT_CONTEXT(ctx);
2471 struct gl_texture_unit *texUnit;
2472 struct gl_texture_object *texObj;
2473 struct gl_texture_image *texImage;
2474 GLboolean success = GL_FALSE;
2475 GLsizei postConvWidth, postConvHeight;
2476
2477 postConvWidth = width;
2478 postConvHeight = height;
2479 adjust_texture_size_for_convolution(ctx, 2, &postConvWidth,&postConvHeight);
2480
2481 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
2482 postConvWidth, postConvHeight, 1, format, type)) {
2483 return; /* error was detected */
2484 }
2485
2486 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2487 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2488 texImage = texObj->Image[level];
2489 assert(texImage);
2490
2491 if (width == 0 || height == 0 || !pixels)
2492 return; /* no-op, not an error */
2493
2494 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2495 _mesa_update_image_transfer_state(ctx);
2496
2497 if (!ctx->ImageTransferState && ctx->Driver.TexSubImage2D) {
2498 success = (*ctx->Driver.TexSubImage2D)( ctx, target, level, xoffset,
2499 yoffset, width, height, format, type,
2500 pixels, &ctx->Unpack, texObj, texImage );
2501 }
2502 if (!success) {
2503 /* XXX if Driver.TexSubImage2D, unpack image and try again? */
2504 const GLint texComps = components_in_intformat(texImage->Format);
2505 const GLint texRowStride = texImage->Width * texComps;
2506 GLboolean retain = GL_TRUE;
2507
2508 if (!texImage->Data) {
2509 _mesa_get_teximage_from_driver( ctx, target, level, texObj );
2510 if (!texImage->Data) {
2511 make_null_texture(texImage);
2512 }
2513 if (!texImage->Data)
2514 return; /* we're really out of luck! */
2515 }
2516
2517 fill_texture_image(ctx, 2, texImage->Format, texImage->Data,
2518 width, height, 1, xoffset, yoffset, 0,
2519 texRowStride, 0,
2520 format, type, pixels, &ctx->Unpack);
2521
2522 if (ctx->Driver.TexImage2D) {
2523 (*ctx->Driver.TexImage2D)(ctx, target, level, texImage->Format,
2524 GL_UNSIGNED_BYTE, texImage->Data,
2525 &_mesa_native_packing, texObj, texImage,
2526 &retain);
2527 }
2528
2529 if (!retain && texImage->Data) {
2530 FREE(texImage->Data);
2531 texImage->Data = NULL;
2532 }
2533
2534 #ifdef OLD_DD_TEXTURE
2535 /* XXX this will be removed in the future */
2536 if (ctx->Driver.TexSubImage) {
2537 (*ctx->Driver.TexSubImage)(ctx, target, texObj, level,
2538 xoffset, yoffset, width, height,
2539 texImage->IntFormat, texImage);
2540 }
2541 else if (ctx->Driver.TexImage) {
2542 (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_2D, texObj,
2543 level, texImage->IntFormat, texImage );
2544 }
2545 #endif
2546 }
2547 }
2548
2549
2550
2551 void
2552 _mesa_TexSubImage3D( GLenum target, GLint level,
2553 GLint xoffset, GLint yoffset, GLint zoffset,
2554 GLsizei width, GLsizei height, GLsizei depth,
2555 GLenum format, GLenum type,
2556 const GLvoid *pixels )
2557 {
2558 GET_CURRENT_CONTEXT(ctx);
2559 struct gl_texture_unit *texUnit;
2560 struct gl_texture_object *texObj;
2561 struct gl_texture_image *texImage;
2562 GLboolean success = GL_FALSE;
2563
2564 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
2565 width, height, depth, format, type)) {
2566 return; /* error was detected */
2567 }
2568
2569 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2570 texObj = texUnit->CurrentD[3];
2571 texImage = texObj->Image[level];
2572 assert(texImage);
2573
2574 if (width == 0 || height == 0 || height == 0 || !pixels)
2575 return; /* no-op, not an error */
2576
2577 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2578 _mesa_update_image_transfer_state(ctx);
2579
2580 if (!ctx->ImageTransferState && ctx->Driver.TexSubImage3D) {
2581 success = (*ctx->Driver.TexSubImage3D)( ctx, target, level, xoffset,
2582 yoffset, zoffset, width, height, depth, format,
2583 type, pixels, &ctx->Unpack, texObj, texImage );
2584 }
2585 if (!success) {
2586 /* XXX if Driver.TexSubImage3D, unpack image and try again? */
2587 const GLint texComps = components_in_intformat(texImage->Format);
2588 const GLint texRowStride = texImage->Width * texComps;
2589 const GLint texImgStride = texRowStride * texImage->Height;
2590 GLboolean retain = GL_TRUE;
2591
2592 if (!texImage->Data) {
2593 _mesa_get_teximage_from_driver( ctx, target, level, texObj );
2594 if (!texImage->Data) {
2595 make_null_texture(texImage);
2596 }
2597 if (!texImage->Data)
2598 return; /* we're really out of luck! */
2599 }
2600
2601 fill_texture_image(ctx, 3, texImage->Format, texImage->Data,
2602 width, height, depth, xoffset, yoffset, zoffset,
2603 texRowStride, texImgStride,
2604 format, type, pixels, &ctx->Unpack);
2605
2606 if (ctx->Driver.TexImage3D) {
2607 (*ctx->Driver.TexImage3D)(ctx, target, level, texImage->Format,
2608 GL_UNSIGNED_BYTE, texImage->Data,
2609 &_mesa_native_packing, texObj, texImage,
2610 &retain);
2611 }
2612
2613 if (!retain && texImage->Data) {
2614 FREE(texImage->Data);
2615 texImage->Data = NULL;
2616 }
2617 }
2618 }
2619
2620
2621
2622 /*
2623 * Read an RGBA image from the frame buffer.
2624 * This is used by glCopyTex[Sub]Image[12]D().
2625 * Input: ctx - the context
2626 * x, y - lower left corner
2627 * width, height - size of region to read
2628 * Return: pointer to block of GL_RGBA, GLchan data.
2629 */
2630 static GLchan *
2631 read_color_image( GLcontext *ctx, GLint x, GLint y,
2632 GLsizei width, GLsizei height )
2633 {
2634 GLint stride, i;
2635 GLchan *image, *dst;
2636
2637 image = (GLchan *) MALLOC(width * height * 4 * sizeof(GLchan));
2638 if (!image)
2639 return NULL;
2640
2641 /* Select buffer to read from */
2642 (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
2643 ctx->Pixel.DriverReadBuffer );
2644
2645 dst = image;
2646 stride = width * 4;
2647 for (i = 0; i < height; i++) {
2648 gl_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y + i,
2649 (GLchan (*)[4]) dst );
2650 dst += stride;
2651 }
2652
2653 /* Read from draw buffer (the default) */
2654 (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
2655 ctx->Color.DriverDrawBuffer );
2656
2657 return image;
2658 }
2659
2660
2661
2662 void
2663 _mesa_CopyTexImage1D( GLenum target, GLint level,
2664 GLenum internalFormat,
2665 GLint x, GLint y,
2666 GLsizei width, GLint border )
2667 {
2668 GET_CURRENT_CONTEXT(ctx);
2669 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage1D");
2670
2671 if (copytexture_error_check(ctx, 1, target, level, internalFormat,
2672 width, 1, border))
2673 return;
2674
2675 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2676 _mesa_update_image_transfer_state(ctx);
2677
2678 if (ctx->ImageTransferState || !ctx->Driver.CopyTexImage1D
2679 || !(*ctx->Driver.CopyTexImage1D)(ctx, target, level,
2680 internalFormat, x, y, width, border)) {
2681 struct gl_pixelstore_attrib unpackSave;
2682
2683 /* get image from framebuffer */
2684 GLchan *image = read_color_image( ctx, x, y, width, 1 );
2685 if (!image) {
2686 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D" );
2687 return;
2688 }
2689
2690 /* call glTexImage1D to redefine the texture */
2691 unpackSave = ctx->Unpack;
2692 ctx->Unpack = _mesa_native_packing;
2693 (*ctx->Exec->TexImage1D)( target, level, internalFormat, width,
2694 border, GL_RGBA, GL_UNSIGNED_BYTE, image );
2695 ctx->Unpack = unpackSave;
2696
2697 FREE(image);
2698 }
2699 }
2700
2701
2702
2703 void
2704 _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
2705 GLint x, GLint y, GLsizei width, GLsizei height,
2706 GLint border )
2707 {
2708 GET_CURRENT_CONTEXT(ctx);
2709 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage2D");
2710
2711 if (copytexture_error_check(ctx, 2, target, level, internalFormat,
2712 width, height, border))
2713 return;
2714
2715 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2716 _mesa_update_image_transfer_state(ctx);
2717
2718 if (ctx->ImageTransferState || !ctx->Driver.CopyTexImage2D
2719 || !(*ctx->Driver.CopyTexImage2D)(ctx, target, level,
2720 internalFormat, x, y, width, height, border)) {
2721 struct gl_pixelstore_attrib unpackSave;
2722
2723 /* get image from framebuffer */
2724 GLchan *image = read_color_image( ctx, x, y, width, height );
2725 if (!image) {
2726 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D" );
2727 return;
2728 }
2729
2730 /* call glTexImage2D to redefine the texture */
2731 unpackSave = ctx->Unpack;
2732 ctx->Unpack = _mesa_native_packing;
2733 (ctx->Exec->TexImage2D)( target, level, internalFormat, width,
2734 height, border, GL_RGBA, GL_UNSIGNED_BYTE, image );
2735 ctx->Unpack = unpackSave;
2736
2737 FREE(image);
2738 }
2739 }
2740
2741
2742
2743 void
2744 _mesa_CopyTexSubImage1D( GLenum target, GLint level,
2745 GLint xoffset, GLint x, GLint y, GLsizei width )
2746 {
2747 GET_CURRENT_CONTEXT(ctx);
2748 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage1D");
2749
2750 if (copytexsubimage_error_check(ctx, 1, target, level,
2751 xoffset, 0, 0, width, 1))
2752 return;
2753
2754 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2755 _mesa_update_image_transfer_state(ctx);
2756
2757 if (ctx->ImageTransferState || !ctx->Driver.CopyTexSubImage1D
2758 || !(*ctx->Driver.CopyTexSubImage1D)(ctx, target, level,
2759 xoffset, x, y, width)) {
2760 struct gl_texture_unit *texUnit;
2761 struct gl_texture_image *teximage;
2762 struct gl_pixelstore_attrib unpackSave;
2763 GLchan *image;
2764
2765 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2766 teximage = texUnit->CurrentD[1]->Image[level];
2767 assert(teximage);
2768
2769 /* get image from frame buffer */
2770 image = read_color_image(ctx, x, y, width, 1);
2771 if (!image) {
2772 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
2773 return;
2774 }
2775
2776 /* now call glTexSubImage1D to do the real work */
2777 unpackSave = ctx->Unpack;
2778 ctx->Unpack = _mesa_native_packing;
2779 _mesa_TexSubImage1D(target, level, xoffset, width,
2780 GL_RGBA, GL_UNSIGNED_BYTE, image);
2781 ctx->Unpack = unpackSave;
2782
2783 FREE(image);
2784 }
2785 }
2786
2787
2788
2789 void
2790 _mesa_CopyTexSubImage2D( GLenum target, GLint level,
2791 GLint xoffset, GLint yoffset,
2792 GLint x, GLint y, GLsizei width, GLsizei height )
2793 {
2794 GET_CURRENT_CONTEXT(ctx);
2795 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage2D");
2796
2797 if (copytexsubimage_error_check(ctx, 2, target, level,
2798 xoffset, yoffset, 0, width, height))
2799 return;
2800
2801 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2802 _mesa_update_image_transfer_state(ctx);
2803
2804 if (ctx->ImageTransferState || !ctx->Driver.CopyTexSubImage2D
2805 || !(*ctx->Driver.CopyTexSubImage2D)(ctx, target, level,
2806 xoffset, yoffset, x, y, width, height )) {
2807 struct gl_texture_unit *texUnit;
2808 struct gl_texture_image *teximage;
2809 struct gl_pixelstore_attrib unpackSave;
2810 GLchan *image;
2811
2812 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2813 teximage = texUnit->CurrentD[2]->Image[level];
2814 assert(teximage);
2815
2816 /* get image from frame buffer */
2817 image = read_color_image(ctx, x, y, width, height);
2818 if (!image) {
2819 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
2820 return;
2821 }
2822
2823 /* now call glTexSubImage2D to do the real work */
2824 unpackSave = ctx->Unpack;
2825 ctx->Unpack = _mesa_native_packing;
2826 _mesa_TexSubImage2D(target, level, xoffset, yoffset, width, height,
2827 GL_RGBA, GL_UNSIGNED_BYTE, image);
2828 ctx->Unpack = unpackSave;
2829
2830 FREE(image);
2831 }
2832 }
2833
2834
2835
2836 void
2837 _mesa_CopyTexSubImage3D( GLenum target, GLint level,
2838 GLint xoffset, GLint yoffset, GLint zoffset,
2839 GLint x, GLint y, GLsizei width, GLsizei height )
2840 {
2841 GET_CURRENT_CONTEXT(ctx);
2842 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage3D");
2843
2844 if (copytexsubimage_error_check(ctx, 3, target, level,
2845 xoffset, yoffset, zoffset, width, height))
2846 return;
2847
2848 if (ctx->ImageTransferState == UPDATE_IMAGE_TRANSFER_STATE)
2849 _mesa_update_image_transfer_state(ctx);
2850
2851 if (ctx->ImageTransferState || !ctx->Driver.CopyTexSubImage3D
2852 || !(*ctx->Driver.CopyTexSubImage3D)(ctx, target, level,
2853 xoffset, yoffset, zoffset, x, y, width, height )) {
2854 struct gl_texture_unit *texUnit;
2855 struct gl_texture_image *teximage;
2856 struct gl_pixelstore_attrib unpackSave;
2857 GLchan *image;
2858
2859 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2860 teximage = texUnit->CurrentD[3]->Image[level];
2861 assert(teximage);
2862
2863 /* get image from frame buffer */
2864 image = read_color_image(ctx, x, y, width, height);
2865 if (!image) {
2866 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage2D" );
2867 return;
2868 }
2869
2870 /* now call glTexSubImage2D to do the real work */
2871 unpackSave = ctx->Unpack;
2872 ctx->Unpack = _mesa_native_packing;
2873 _mesa_TexSubImage3D(target, level, xoffset, yoffset, zoffset,
2874 width, height, 1, GL_RGBA, GL_UNSIGNED_BYTE, image);
2875 ctx->Unpack = unpackSave;
2876
2877 FREE(image);
2878 }
2879 }
2880
2881
2882
2883 void
2884 _mesa_CompressedTexImage1DARB(GLenum target, GLint level,
2885 GLenum internalFormat, GLsizei width,
2886 GLint border, GLsizei imageSize,
2887 const GLvoid *data)
2888 {
2889 GET_CURRENT_CONTEXT(ctx);
2890 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage1DARB");
2891
2892 switch (internalFormat) {
2893 case GL_COMPRESSED_ALPHA_ARB:
2894 case GL_COMPRESSED_LUMINANCE_ARB:
2895 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
2896 case GL_COMPRESSED_INTENSITY_ARB:
2897 case GL_COMPRESSED_RGB_ARB:
2898 case GL_COMPRESSED_RGBA_ARB:
2899 gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB");
2900 return;
2901 default:
2902 /* silence compiler warning */
2903 ;
2904 }
2905
2906 if (target == GL_TEXTURE_1D) {
2907 struct gl_texture_unit *texUnit;
2908 struct gl_texture_object *texObj;
2909 struct gl_texture_image *texImage;
2910 GLsizei computedImageSize;
2911
2912 if (texture_error_check(ctx, target, level, internalFormat,
2913 GL_NONE, GL_NONE, 1, width, 1, 1, border)) {
2914 return; /* error in texture image was detected */
2915 }
2916
2917 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2918 texObj = texUnit->CurrentD[1];
2919 texImage = texObj->Image[level];
2920
2921 if (!texImage) {
2922 texImage = _mesa_alloc_texture_image();
2923 texObj->Image[level] = texImage;
2924 if (!texImage) {
2925 gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1DARB");
2926 return;
2927 }
2928 }
2929 else if (texImage->Data) {
2930 FREE(texImage->Data);
2931 texImage->Data = NULL;
2932 }
2933
2934 /* setup the teximage struct's fields */
2935 init_texture_image(ctx, texImage, width, 1, 1,
2936 border, internalFormat);
2937
2938 /* process the texture image */
2939 if (data) {
2940 GLboolean retain = GL_TRUE;
2941 GLboolean success = GL_FALSE;
2942 if (ctx->Driver.CompressedTexImage1D) {
2943 success = (*ctx->Driver.CompressedTexImage1D)(ctx, target, level,
2944 imageSize, data, texObj, texImage, &retain);
2945 }
2946 if (retain || !success) {
2947 /* make internal copy of the texture image */
2948 computedImageSize = _mesa_compressed_image_size(ctx,
2949 internalFormat,
2950 1, /* num dims */
2951 width,
2952 1, /* height */
2953 1); /* depth */
2954 if (computedImageSize != imageSize) {
2955 gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage1DARB(imageSize)");
2956 return;
2957 }
2958 texImage->Data = MALLOC(computedImageSize);
2959 if (texImage->Data) {
2960 MEMCPY(texImage->Data, data, computedImageSize);
2961 }
2962 }
2963 if (!retain && texImage->Data) {
2964 FREE(texImage->Data);
2965 texImage->Data = NULL;
2966 }
2967 }
2968 else {
2969 make_null_texture(texImage);
2970 if (ctx->Driver.CompressedTexImage1D) {
2971 GLboolean retain;
2972 (*ctx->Driver.CompressedTexImage1D)(ctx, target, level, 0,
2973 texImage->Data, texObj,
2974 texImage, &retain);
2975 }
2976 }
2977
2978 /* state update */
2979 gl_put_texobj_on_dirty_list( ctx, texObj );
2980 ctx->NewState |= _NEW_TEXTURE;
2981 }
2982 else if (target == GL_PROXY_TEXTURE_1D) {
2983 /* Proxy texture: check for errors and update proxy state */
2984 GLenum error = texture_error_check(ctx, target, level, internalFormat,
2985 GL_NONE, GL_NONE, 1, width, 1, 1, border);
2986 if (!error && ctx->Driver.TestProxyTexImage) {
2987 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
2988 internalFormat, GL_NONE, GL_NONE,
2989 width, 1, 1, border);
2990 }
2991 if (error) {
2992 /* if error, clear all proxy texture image parameters */
2993 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
2994 clear_proxy_teximage(ctx->Texture.Proxy1D->Image[level]);
2995 }
2996 }
2997 else {
2998 /* if no error, update proxy texture image parameters */
2999 init_texture_image(ctx, ctx->Texture.Proxy1D->Image[level],
3000 width, 1, 1, border, internalFormat);
3001 }
3002 }
3003 else {
3004 gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB(target)" );
3005 return;
3006 }
3007 }
3008
3009
3010 void
3011 _mesa_CompressedTexImage2DARB(GLenum target, GLint level,
3012 GLenum internalFormat, GLsizei width,
3013 GLsizei height, GLint border, GLsizei imageSize,
3014 const GLvoid *data)
3015 {
3016 GET_CURRENT_CONTEXT(ctx);
3017 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage2DARB");
3018
3019 switch (internalFormat) {
3020 case GL_COMPRESSED_ALPHA_ARB:
3021 case GL_COMPRESSED_LUMINANCE_ARB:
3022 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
3023 case GL_COMPRESSED_INTENSITY_ARB:
3024 case GL_COMPRESSED_RGB_ARB:
3025 case GL_COMPRESSED_RGBA_ARB:
3026 gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB");
3027 return;
3028 default:
3029 /* silence compiler warning */
3030 ;
3031 }
3032
3033 if (target==GL_TEXTURE_2D ||
3034 (ctx->Extensions.ARB_texture_cube_map &&
3035 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3036 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
3037 struct gl_texture_unit *texUnit;
3038 struct gl_texture_object *texObj;
3039 struct gl_texture_image *texImage;
3040 GLsizei computedImageSize;
3041
3042 if (texture_error_check(ctx, target, level, internalFormat,
3043 GL_NONE, GL_NONE, 1, width, height, 1, border)) {
3044 return; /* error in texture image was detected */
3045 }
3046
3047 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3048 texObj = texUnit->CurrentD[2];
3049 texImage = texObj->Image[level];
3050
3051 if (!texImage) {
3052 texImage = _mesa_alloc_texture_image();
3053 texObj->Image[level] = texImage;
3054 if (!texImage) {
3055 gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB");
3056 return;
3057 }
3058 }
3059 else if (texImage->Data) {
3060 FREE(texImage->Data);
3061 texImage->Data = NULL;
3062 }
3063
3064 /* setup the teximage struct's fields */
3065 init_texture_image(ctx, texImage, width, height, 1, border, internalFormat);
3066
3067 /* process the texture image */
3068 if (data) {
3069 GLboolean retain = GL_TRUE;
3070 GLboolean success = GL_FALSE;
3071 if (ctx->Driver.CompressedTexImage2D) {
3072 success = (*ctx->Driver.CompressedTexImage2D)( ctx,
3073 target,
3074 level,
3075 imageSize,
3076 data,
3077 texObj,
3078 texImage,
3079 &retain);
3080 }
3081 if (retain || !success) {
3082 /* make internal copy of the texture image */
3083 computedImageSize = _mesa_compressed_image_size(ctx,
3084 internalFormat,
3085 2, /* num dims */
3086 width,
3087 height,
3088 1); /* depth */
3089 if (computedImageSize != imageSize) {
3090 gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage2DARB(imageSize)");
3091 return;
3092 }
3093 texImage->Data = MALLOC(computedImageSize);
3094 if (texImage->Data) {
3095 MEMCPY(texImage->Data, data, computedImageSize);
3096 }
3097 }
3098 if (!retain && texImage->Data) {
3099 FREE(texImage->Data);
3100 texImage->Data = NULL;
3101 }
3102 }
3103 else {
3104 make_null_texture(texImage);
3105 if (ctx->Driver.CompressedTexImage2D) {
3106 GLboolean retain;
3107 (*ctx->Driver.CompressedTexImage2D)( ctx, target, level, 0,
3108 texImage->Data, texObj,
3109 texImage, &retain);
3110 }
3111 }
3112
3113 /* state update */
3114 gl_put_texobj_on_dirty_list( ctx, texObj );
3115 ctx->NewState |= _NEW_TEXTURE;
3116 }
3117 else if (target == GL_PROXY_TEXTURE_2D) {
3118 /* Proxy texture: check for errors and update proxy state */
3119 GLenum error = texture_error_check(ctx, target, level, internalFormat,
3120 GL_NONE, GL_NONE, 2, width, height, 1, border);
3121 if (!error && ctx->Driver.TestProxyTexImage) {
3122 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3123 internalFormat, GL_NONE, GL_NONE,
3124 width, height, 1, border);
3125 }
3126 if (error) {
3127 /* if error, clear all proxy texture image parameters */
3128 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
3129 clear_proxy_teximage(ctx->Texture.Proxy2D->Image[level]);
3130 }
3131 }
3132 else {
3133 /* if no error, update proxy texture image parameters */
3134 init_texture_image(ctx, ctx->Texture.Proxy2D->Image[level],
3135 width, 1, 1, border, internalFormat);
3136 }
3137 }
3138 else {
3139 gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB(target)" );
3140 return;
3141 }
3142 }
3143
3144
3145 void
3146 _mesa_CompressedTexImage3DARB(GLenum target, GLint level,
3147 GLenum internalFormat, GLsizei width,
3148 GLsizei height, GLsizei depth, GLint border,
3149 GLsizei imageSize, const GLvoid *data)
3150 {
3151 GET_CURRENT_CONTEXT(ctx);
3152 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage3DARB");
3153
3154 switch (internalFormat) {
3155 case GL_COMPRESSED_ALPHA_ARB:
3156 case GL_COMPRESSED_LUMINANCE_ARB:
3157 case GL_COMPRESSED_LUMINANCE_ALPHA_ARB:
3158 case GL_COMPRESSED_INTENSITY_ARB:
3159 case GL_COMPRESSED_RGB_ARB:
3160 case GL_COMPRESSED_RGBA_ARB:
3161 gl_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB");
3162 return;
3163 default:
3164 /* silence compiler warning */
3165 ;
3166 }
3167
3168 if (target == GL_TEXTURE_3D) {
3169 struct gl_texture_unit *texUnit;
3170 struct gl_texture_object *texObj;
3171 struct gl_texture_image *texImage;
3172 GLsizei computedImageSize;
3173
3174 if (texture_error_check(ctx, target, level, internalFormat,
3175 GL_NONE, GL_NONE, 1, width, height, depth, border)) {
3176 return; /* error in texture image was detected */
3177 }
3178
3179 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3180 texObj = texUnit->CurrentD[3];
3181 texImage = texObj->Image[level];
3182
3183 if (!texImage) {
3184 texImage = _mesa_alloc_texture_image();
3185 texObj->Image[level] = texImage;
3186 if (!texImage) {
3187 gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3DARB");
3188 return;
3189 }
3190 }
3191 else if (texImage->Data) {
3192 FREE(texImage->Data);
3193 texImage->Data = NULL;
3194 }
3195
3196 /* setup the teximage struct's fields */
3197 init_texture_image(ctx, texImage, width, height, depth,
3198 border, internalFormat);
3199
3200 /* process the texture image */
3201 if (data) {
3202 GLboolean retain = GL_TRUE;
3203 GLboolean success = GL_FALSE;
3204 if (ctx->Driver.CompressedTexImage3D) {
3205 success = (*ctx->Driver.CompressedTexImage3D)(ctx, target, level,
3206 imageSize, data,
3207 texObj, texImage,
3208 &retain);
3209 }
3210 if (retain || !success) {
3211 /* make internal copy of the texture image */
3212 computedImageSize = _mesa_compressed_image_size(ctx,
3213 internalFormat,
3214 3, /* num dims */
3215 width,
3216 height,
3217 depth);
3218 if (computedImageSize != imageSize) {
3219 gl_error(ctx, GL_INVALID_VALUE, "glCompressedTexImage3DARB(imageSize)");
3220 return;
3221 }
3222 texImage->Data = MALLOC(computedImageSize);
3223 if (texImage->Data) {
3224 MEMCPY(texImage->Data, data, computedImageSize);
3225 }
3226 }
3227 if (!retain && texImage->Data) {
3228 FREE(texImage->Data);
3229 texImage->Data = NULL;
3230 }
3231 }
3232 else {
3233 make_null_texture(texImage);
3234 if (ctx->Driver.CompressedTexImage3D) {
3235 GLboolean retain;
3236 (*ctx->Driver.CompressedTexImage3D)( ctx, target, level, 0,
3237 texImage->Data, texObj,
3238 texImage, &retain);
3239 }
3240 }
3241
3242 /* state update */
3243 gl_put_texobj_on_dirty_list( ctx, texObj );
3244 ctx->NewState |= _NEW_TEXTURE;
3245 }
3246 else if (target == GL_PROXY_TEXTURE_3D) {
3247 /* Proxy texture: check for errors and update proxy state */
3248 GLenum error = texture_error_check(ctx, target, level, internalFormat,
3249 GL_NONE, GL_NONE, 1, width, height, depth, border);
3250 if (!error && ctx->Driver.TestProxyTexImage) {
3251 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3252 internalFormat, GL_NONE, GL_NONE,
3253 width, height, depth, border);
3254 }
3255 if (error) {
3256 /* if error, clear all proxy texture image parameters */
3257 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
3258 clear_proxy_teximage(ctx->Texture.Proxy3D->Image[level]);
3259 }
3260 }
3261 else {
3262 /* if no error, update proxy texture image parameters */
3263 init_texture_image(ctx, ctx->Texture.Proxy3D->Image[level],
3264 width, 1, 1, border, internalFormat);
3265 }
3266 }
3267 else {
3268 gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB(target)" );
3269 return;
3270 }
3271 }
3272
3273
3274 void
3275 _mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
3276 GLsizei width, GLenum format,
3277 GLsizei imageSize, const GLvoid *data)
3278 {
3279 GET_CURRENT_CONTEXT(ctx);
3280 struct gl_texture_unit *texUnit;
3281 struct gl_texture_object *texObj;
3282 struct gl_texture_image *texImage;
3283 GLboolean success = GL_FALSE;
3284
3285 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
3286 width, 1, 1, format, GL_NONE)) {
3287 return; /* error was detected */
3288 }
3289
3290 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3291 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3292 texImage = texObj->Image[level];
3293 assert(texImage);
3294
3295 if (width == 0 || !data)
3296 return; /* no-op, not an error */
3297
3298 if (ctx->Driver.CompressedTexSubImage1D) {
3299 success = (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level,
3300 xoffset, width, format, imageSize, data, texObj, texImage);
3301 }
3302 if (!success) {
3303 /* XXX what else can we do? */
3304 gl_problem(ctx, "glCompressedTexSubImage1DARB failed!");
3305 return;
3306 }
3307 }
3308
3309
3310 void
3311 _mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
3312 GLint yoffset, GLsizei width, GLsizei height,
3313 GLenum format, GLsizei imageSize,
3314 const GLvoid *data)
3315 {
3316 GET_CURRENT_CONTEXT(ctx);
3317 struct gl_texture_unit *texUnit;
3318 struct gl_texture_object *texObj;
3319 struct gl_texture_image *texImage;
3320 GLboolean success = GL_FALSE;
3321
3322 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
3323 width, height, 1, format, GL_NONE)) {
3324 return; /* error was detected */
3325 }
3326
3327 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3328 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3329 texImage = texObj->Image[level];
3330 assert(texImage);
3331
3332 if (width == 0 || height == 0 || !data)
3333 return; /* no-op, not an error */
3334
3335 if (ctx->Driver.CompressedTexSubImage2D) {
3336 success = (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level,
3337 xoffset, yoffset, width, height, format,
3338 imageSize, data, texObj, texImage);
3339 }
3340 if (!success) {
3341 /* XXX what else can we do? */
3342 gl_problem(ctx, "glCompressedTexSubImage2DARB failed!");
3343 return;
3344 }
3345 }
3346
3347
3348 void
3349 _mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
3350 GLint yoffset, GLint zoffset, GLsizei width,
3351 GLsizei height, GLsizei depth, GLenum format,
3352 GLsizei imageSize, const GLvoid *data)
3353 {
3354 GET_CURRENT_CONTEXT(ctx);
3355 struct gl_texture_unit *texUnit;
3356 struct gl_texture_object *texObj;
3357 struct gl_texture_image *texImage;
3358 GLboolean success = GL_FALSE;
3359
3360 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
3361 width, height, depth, format, GL_NONE)) {
3362 return; /* error was detected */
3363 }
3364
3365 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
3366 texObj = _mesa_select_tex_object(ctx, texUnit, target);
3367 texImage = texObj->Image[level];
3368 assert(texImage);
3369
3370 if (width == 0 || height == 0 || depth == 0 || !data)
3371 return; /* no-op, not an error */
3372
3373 if (ctx->Driver.CompressedTexSubImage3D) {
3374 success = (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level,
3375 xoffset, yoffset, zoffset, width, height, depth,
3376 format, imageSize, data, texObj, texImage);
3377 }
3378 if (!success) {
3379 /* XXX what else can we do? */
3380 gl_problem(ctx, "glCompressedTexSubImage3DARB failed!");
3381 return;
3382 }
3383 }
3384
3385
3386 void
3387 _mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img)
3388 {
3389 GET_CURRENT_CONTEXT(ctx);
3390 const struct gl_texture_object *texObj;
3391 struct gl_texture_image *texImage;
3392
3393 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetCompressedTexImageARB");
3394
3395 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
3396 gl_error( ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)" );
3397 return;
3398 }
3399
3400 switch (target) {
3401 case GL_TEXTURE_1D:
3402 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[1];
3403 texImage = texObj->Image[level];
3404 break;
3405 case GL_TEXTURE_2D:
3406 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[2];
3407 texImage = texObj->Image[level];
3408 break;
3409 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
3410 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3411 texImage = texObj->Image[level];
3412 break;
3413 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
3414 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3415 texImage = texObj->NegX[level];
3416 break;
3417 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
3418 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3419 texImage = texObj->PosY[level];
3420 break;
3421 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
3422 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3423 texImage = texObj->NegY[level];
3424 break;
3425 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
3426 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3427 texImage = texObj->PosZ[level];
3428 break;
3429 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
3430 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentCubeMap;
3431 texImage = texObj->NegZ[level];
3432 break;
3433 case GL_TEXTURE_3D:
3434 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[3];
3435 texImage = texObj->Image[level];
3436 break;
3437 default:
3438 gl_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)");
3439 return;
3440 }
3441
3442 if (!texImage) {
3443 /* invalid mipmap level */
3444 gl_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)");
3445 return;
3446 }
3447
3448 if (!texImage->IsCompressed) {
3449 gl_error(ctx, GL_INVALID_OPERATION, "glGetCompressedTexImageARB");
3450 return;
3451 }
3452
3453 if (!img)
3454 return;
3455
3456 if (ctx->Driver.GetCompressedTexImage) {
3457 (*ctx->Driver.GetCompressedTexImage)(ctx, target, level, img, texObj,
3458 texImage);
3459 }
3460 else {
3461 gl_problem(ctx, "Driver doesn't implement GetCompressedTexImage");
3462 }
3463 }