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