more work on GL_ARB_texture_compression
[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->PosX[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->PosX[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->PosX[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 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
908 return GL_TRUE;
909 }
910 }
911 else if (dimensions == 3) {
912 isProxy = (GLboolean) (target == GL_PROXY_TEXTURE_3D);
913 if (target != GL_TEXTURE_3D && !isProxy) {
914 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
915 return GL_TRUE;
916 }
917 }
918 else {
919 gl_problem( ctx, "bad dims in texture_error_check" );
920 return GL_TRUE;
921 }
922
923 /* Border */
924 if (border != 0 && border != 1) {
925 if (!isProxy) {
926 char message[100];
927 sprintf(message, "glTexImage%dD(border)", dimensions);
928 gl_error(ctx, GL_INVALID_VALUE, message);
929 }
930 return GL_TRUE;
931 }
932
933 /* Width */
934 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
935 || logbase2( width - 2 * border ) < 0) {
936 if (!isProxy) {
937 char message[100];
938 sprintf(message, "glTexImage%dD(width)", dimensions);
939 gl_error(ctx, GL_INVALID_VALUE, message);
940 }
941 return GL_TRUE;
942 }
943
944 /* Height */
945 if (dimensions >= 2) {
946 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
947 || logbase2( height - 2 * border ) < 0) {
948 if (!isProxy) {
949 char message[100];
950 sprintf(message, "glTexImage%dD(height)", dimensions);
951 gl_error(ctx, GL_INVALID_VALUE, message);
952 }
953 return GL_TRUE;
954 }
955 }
956
957 /* Depth */
958 if (dimensions >= 3) {
959 if (depth < 2 * border || depth > 2 + ctx->Const.MaxTextureSize
960 || logbase2( depth - 2 * border ) < 0) {
961 if (!isProxy) {
962 gl_error( ctx, GL_INVALID_VALUE, "glTexImage3D(depth)" );
963 }
964 return GL_TRUE;
965 }
966 }
967
968 /* Level */
969 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
970 if (!isProxy) {
971 char message[100];
972 sprintf(message, "glTexImage%dD(level)", dimensions);
973 gl_error(ctx, GL_INVALID_VALUE, message);
974 }
975 return GL_TRUE;
976 }
977
978 iformat = _mesa_base_tex_format( ctx, internalFormat );
979 if (iformat < 0) {
980 if (!isProxy) {
981 char message[100];
982 sprintf(message, "glTexImage%dD(internalFormat)", dimensions);
983 gl_error(ctx, GL_INVALID_VALUE, message);
984 }
985 return GL_TRUE;
986 }
987
988 if (!is_compressed_format(internalFormat)) {
989 if (!_mesa_is_legal_format_and_type( format, type )) {
990 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
991 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
992 */
993 if (!isProxy) {
994 char message[100];
995 sprintf(message, "glTexImage%dD(format or type)", dimensions);
996 gl_error(ctx, GL_INVALID_OPERATION, message);
997 }
998 return GL_TRUE;
999 }
1000 }
1001
1002 /* if we get here, the parameters are OK */
1003 return GL_FALSE;
1004 }
1005
1006
1007
1008 /*
1009 * Test glTexSubImage[123]D() parameters for errors.
1010 * Input:
1011 * dimensions - must be 1 or 2 or 3
1012 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
1013 */
1014 static GLboolean
1015 subtexture_error_check( GLcontext *ctx, GLuint dimensions,
1016 GLenum target, GLint level,
1017 GLint xoffset, GLint yoffset, GLint zoffset,
1018 GLint width, GLint height, GLint depth,
1019 GLenum format, GLenum type )
1020 {
1021 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1022 struct gl_texture_image *destTex;
1023
1024 if (dimensions == 1) {
1025 if (target != GL_TEXTURE_1D) {
1026 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
1027 return GL_TRUE;
1028 }
1029 }
1030 else if (dimensions == 2) {
1031 if (ctx->Extensions.HaveTextureCubeMap) {
1032 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1033 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1034 target != GL_TEXTURE_2D) {
1035 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1036 return GL_TRUE;
1037 }
1038 }
1039 else if (target != GL_TEXTURE_2D) {
1040 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1041 return GL_TRUE;
1042 }
1043 }
1044 else if (dimensions == 3) {
1045 if (target != GL_TEXTURE_3D) {
1046 gl_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
1047 return GL_TRUE;
1048 }
1049 }
1050 else {
1051 gl_problem( ctx, "bad dims in texture_error_check" );
1052 return GL_TRUE;
1053 }
1054
1055 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1056 gl_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level)");
1057 return GL_TRUE;
1058 }
1059
1060 if (width < 0) {
1061 char message[100];
1062 sprintf(message, "glTexSubImage%dD(width)", dimensions);
1063 gl_error(ctx, GL_INVALID_VALUE, message);
1064 return GL_TRUE;
1065 }
1066 if (height < 0 && dimensions > 1) {
1067 char message[100];
1068 sprintf(message, "glTexSubImage%dD(height)", dimensions);
1069 gl_error(ctx, GL_INVALID_VALUE, message);
1070 return GL_TRUE;
1071 }
1072 if (depth < 0 && dimensions > 2) {
1073 char message[100];
1074 sprintf(message, "glTexSubImage%dD(depth)", dimensions);
1075 gl_error(ctx, GL_INVALID_VALUE, message);
1076 return GL_TRUE;
1077 }
1078
1079 destTex = texUnit->CurrentD[2]->Image[level];
1080 if (!destTex) {
1081 gl_error(ctx, GL_INVALID_OPERATION, "glTexSubImage2D");
1082 return GL_TRUE;
1083 }
1084
1085 if (xoffset < -((GLint)destTex->Border)) {
1086 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset)");
1087 return GL_TRUE;
1088 }
1089 if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
1090 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage1/2/3D(xoffset+width)");
1091 return GL_TRUE;
1092 }
1093 if (dimensions > 1) {
1094 if (yoffset < -((GLint)destTex->Border)) {
1095 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset)");
1096 return GL_TRUE;
1097 }
1098 if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) {
1099 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage2/3D(yoffset+height)");
1100 return GL_TRUE;
1101 }
1102 }
1103 if (dimensions > 2) {
1104 if (zoffset < -((GLint)destTex->Border)) {
1105 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)");
1106 return GL_TRUE;
1107 }
1108 if (zoffset + depth > (GLint) (destTex->Depth+destTex->Border)) {
1109 gl_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)");
1110 return GL_TRUE;
1111 }
1112 }
1113
1114 if (!_mesa_is_legal_format_and_type(format, type)) {
1115 char message[100];
1116 sprintf(message, "glTexSubImage%dD(format or type)", dimensions);
1117 gl_error(ctx, GL_INVALID_ENUM, message);
1118 return GL_TRUE;
1119 }
1120
1121 return GL_FALSE;
1122 }
1123
1124
1125 /*
1126 * Test glCopyTexImage[12]D() parameters for errors.
1127 * Input: dimensions - must be 1 or 2 or 3
1128 * Return: GL_TRUE = an error was detected, GL_FALSE = no errors
1129 */
1130 static GLboolean
1131 copytexture_error_check( GLcontext *ctx, GLuint dimensions,
1132 GLenum target, GLint level, GLint internalFormat,
1133 GLint width, GLint height, GLint border )
1134 {
1135 GLint iformat;
1136
1137 if (dimensions == 1) {
1138 if (target != GL_TEXTURE_1D) {
1139 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
1140 return GL_TRUE;
1141 }
1142 }
1143 else if (dimensions == 2) {
1144 if (ctx->Extensions.HaveTextureCubeMap) {
1145 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1146 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1147 target != GL_TEXTURE_2D) {
1148 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1149 return GL_TRUE;
1150 }
1151 }
1152 else if (target != GL_TEXTURE_2D) {
1153 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1154 return GL_TRUE;
1155 }
1156 }
1157
1158 /* Border */
1159 if (border!=0 && border!=1) {
1160 char message[100];
1161 sprintf(message, "glCopyTexImage%dD(border)", dimensions);
1162 gl_error(ctx, GL_INVALID_VALUE, message);
1163 return GL_TRUE;
1164 }
1165
1166 /* Width */
1167 if (width < 2 * border || width > 2 + ctx->Const.MaxTextureSize
1168 || logbase2( width - 2 * border ) < 0) {
1169 char message[100];
1170 sprintf(message, "glCopyTexImage%dD(width)", dimensions);
1171 gl_error(ctx, GL_INVALID_VALUE, message);
1172 return GL_TRUE;
1173 }
1174
1175 /* Height */
1176 if (dimensions >= 2) {
1177 if (height < 2 * border || height > 2 + ctx->Const.MaxTextureSize
1178 || logbase2( height - 2 * border ) < 0) {
1179 char message[100];
1180 sprintf(message, "glCopyTexImage%dD(height)", dimensions);
1181 gl_error(ctx, GL_INVALID_VALUE, message);
1182 return GL_TRUE;
1183 }
1184 }
1185
1186 /* Level */
1187 if (level<0 || level>=ctx->Const.MaxTextureLevels) {
1188 char message[100];
1189 sprintf(message, "glCopyTexImage%dD(level)", dimensions);
1190 gl_error(ctx, GL_INVALID_VALUE, message);
1191 return GL_TRUE;
1192 }
1193
1194 iformat = _mesa_base_tex_format( ctx, internalFormat );
1195 if (iformat < 0) {
1196 char message[100];
1197 sprintf(message, "glCopyTexImage%dD(internalFormat)", dimensions);
1198 gl_error(ctx, GL_INVALID_VALUE, message);
1199 return GL_TRUE;
1200 }
1201
1202 /* if we get here, the parameters are OK */
1203 return GL_FALSE;
1204 }
1205
1206
1207 static GLboolean
1208 copytexsubimage_error_check( GLcontext *ctx, GLuint dimensions,
1209 GLenum target, GLint level,
1210 GLint xoffset, GLint yoffset, GLint zoffset,
1211 GLsizei width, GLsizei height )
1212 {
1213 struct gl_texture_unit *texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1214 struct gl_texture_image *teximage;
1215
1216 if (dimensions == 1) {
1217 if (target != GL_TEXTURE_1D) {
1218 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
1219 return GL_TRUE;
1220 }
1221 }
1222 else if (dimensions == 2) {
1223 if (ctx->Extensions.HaveTextureCubeMap) {
1224 if ((target < GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB ||
1225 target > GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) &&
1226 target != GL_TEXTURE_2D) {
1227 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1228 return GL_TRUE;
1229 }
1230 }
1231 else if (target != GL_TEXTURE_2D) {
1232 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1233 return GL_TRUE;
1234 }
1235 }
1236 else if (dimensions == 3) {
1237 if (target != GL_TEXTURE_3D) {
1238 gl_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" );
1239 return GL_TRUE;
1240 }
1241 }
1242
1243 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1244 char message[100];
1245 sprintf(message, "glCopyTexSubImage%dD(level)", dimensions);
1246 gl_error(ctx, GL_INVALID_VALUE, message);
1247 return GL_TRUE;
1248 }
1249
1250 if (width < 0) {
1251 char message[100];
1252 sprintf(message, "glCopyTexSubImage%dD(width)", dimensions );
1253 gl_error(ctx, GL_INVALID_VALUE, message);
1254 return GL_TRUE;
1255 }
1256 if (dimensions > 1 && height < 0) {
1257 char message[100];
1258 sprintf(message, "glCopyTexSubImage%dD(height)", dimensions );
1259 gl_error(ctx, GL_INVALID_VALUE, message);
1260 return GL_TRUE;
1261 }
1262
1263 teximage = texUnit->CurrentD[dimensions]->Image[level];
1264 if (!teximage) {
1265 char message[100];
1266 sprintf(message, "glCopyTexSubImage%dD(undefined texture)", dimensions);
1267 gl_error(ctx, GL_INVALID_OPERATION, message);
1268 return GL_TRUE;
1269 }
1270
1271 if (xoffset < -((GLint)teximage->Border)) {
1272 char message[100];
1273 sprintf(message, "glCopyTexSubImage%dD(xoffset)", dimensions);
1274 gl_error(ctx, GL_INVALID_VALUE, message);
1275 return GL_TRUE;
1276 }
1277 if (xoffset+width > (GLint) (teximage->Width+teximage->Border)) {
1278 char message[100];
1279 sprintf(message, "glCopyTexSubImage%dD(xoffset+width)", dimensions);
1280 gl_error(ctx, GL_INVALID_VALUE, message);
1281 return GL_TRUE;
1282 }
1283 if (dimensions > 1) {
1284 if (yoffset < -((GLint)teximage->Border)) {
1285 char message[100];
1286 sprintf(message, "glCopyTexSubImage%dD(yoffset)", dimensions);
1287 gl_error(ctx, GL_INVALID_VALUE, message);
1288 return GL_TRUE;
1289 }
1290 /* NOTE: we're adding the border here, not subtracting! */
1291 if (yoffset+height > (GLint) (teximage->Height+teximage->Border)) {
1292 char message[100];
1293 sprintf(message, "glCopyTexSubImage%dD(yoffset+height)", dimensions);
1294 gl_error(ctx, GL_INVALID_VALUE, message);
1295 return GL_TRUE;
1296 }
1297 }
1298
1299 if (dimensions > 2) {
1300 if (zoffset < -((GLint)teximage->Border)) {
1301 char message[100];
1302 sprintf(message, "glCopyTexSubImage%dD(zoffset)", dimensions);
1303 gl_error(ctx, GL_INVALID_VALUE, message);
1304 return GL_TRUE;
1305 }
1306 if (zoffset > (GLint) (teximage->Depth+teximage->Border)) {
1307 char message[100];
1308 sprintf(message, "glCopyTexSubImage%dD(zoffset+depth)", dimensions);
1309 gl_error(ctx, GL_INVALID_VALUE, message);
1310 return GL_TRUE;
1311 }
1312 }
1313
1314 /* if we get here, the parameters are OK */
1315 return GL_FALSE;
1316 }
1317
1318
1319
1320
1321 /*
1322 * Called from the API. Note that width includes the border.
1323 */
1324 void
1325 _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
1326 GLsizei width, GLint border, GLenum format,
1327 GLenum type, const GLvoid *pixels )
1328 {
1329 GET_CURRENT_CONTEXT(ctx);
1330 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage1D");
1331
1332 if (target==GL_TEXTURE_1D) {
1333 struct gl_texture_unit *texUnit;
1334 struct gl_texture_object *texObj;
1335 struct gl_texture_image *texImage;
1336
1337 if (texture_error_check(ctx, target, level, internalFormat,
1338 format, type, 1, width, 1, 1, border)) {
1339 return; /* error in texture image was detected */
1340 }
1341
1342 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1343 texObj = texUnit->CurrentD[1];
1344 texImage = texObj->Image[level];
1345
1346 if (!texImage) {
1347 texImage = _mesa_alloc_texture_image();
1348 texObj->Image[level] = texImage;
1349 if (!texImage) {
1350 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
1351 return;
1352 }
1353 }
1354 else if (texImage->Data) {
1355 FREE(texImage->Data);
1356 texImage->Data = NULL;
1357 }
1358
1359 /* setup the teximage struct's fields */
1360 init_texture_image(texImage, width, 1, 1, border, internalFormat);
1361
1362 /* process the texture image */
1363 if (pixels) {
1364 GLboolean retain = GL_TRUE;
1365 GLboolean success = GL_FALSE;
1366 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1367 && ctx->Driver.TexImage1D) {
1368 /* let device driver try to use raw image */
1369 success = (*ctx->Driver.TexImage1D)( ctx, target, level, format,
1370 type, pixels, &ctx->Unpack,
1371 texObj, texImage, &retain);
1372 }
1373 if (retain || !success) {
1374 /* make internal copy of the texture image */
1375 make_texture_image(ctx, texImage, format, type,
1376 pixels, &ctx->Unpack);
1377 if (!success && ctx->Driver.TexImage1D) {
1378 /* let device driver try to use unpacked image */
1379 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1380 GL_UNSIGNED_BYTE, texImage->Data,
1381 &_mesa_native_packing,
1382 texObj, texImage, &retain);
1383 }
1384 }
1385 if (!retain && texImage->Data) {
1386 FREE(texImage->Data);
1387 texImage->Data = NULL;
1388 }
1389 }
1390 else {
1391 make_null_texture(texImage);
1392 if (ctx->Driver.TexImage1D) {
1393 GLboolean retain;
1394 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1395 GL_UNSIGNED_BYTE, texImage->Data,
1396 &_mesa_native_packing,
1397 texObj, texImage, &retain);
1398 }
1399 }
1400
1401 /* state update */
1402 gl_put_texobj_on_dirty_list( ctx, texObj );
1403 ctx->NewState |= NEW_TEXTURING;
1404 }
1405 else if (target==GL_PROXY_TEXTURE_1D) {
1406 /* Proxy texture: check for errors and update proxy state */
1407 if (texture_error_check(ctx, target, level, internalFormat,
1408 format, type, 1, width, 1, 1, border)) {
1409 /* if error, clear all proxy texture image parameters */
1410 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1411 MEMSET( ctx->Texture.Proxy1D->Image[level], 0,
1412 sizeof(struct gl_texture_image) );
1413 }
1414 }
1415 else {
1416 /* if no error, update proxy texture image parameters */
1417 init_texture_image(ctx->Texture.Proxy1D->Image[level],
1418 width, 1, 1, border, internalFormat);
1419 }
1420 }
1421 else {
1422 gl_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1423 return;
1424 }
1425 }
1426
1427
1428 void
1429 _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
1430 GLsizei width, GLsizei height, GLint border,
1431 GLenum format, GLenum type,
1432 const GLvoid *pixels )
1433 {
1434 GET_CURRENT_CONTEXT(ctx);
1435 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage2D");
1436
1437 if (target==GL_TEXTURE_2D ||
1438 (ctx->Extensions.HaveTextureCubeMap &&
1439 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1440 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
1441 struct gl_texture_unit *texUnit;
1442 struct gl_texture_object *texObj;
1443 struct gl_texture_image *texImage;
1444
1445 if (texture_error_check(ctx, target, level, internalFormat,
1446 format, type, 2, width, height, 1, border)) {
1447 return; /* error in texture image was detected */
1448 }
1449
1450 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1451 texObj = _mesa_select_tex_object(ctx, texUnit, target);
1452 texImage = _mesa_select_tex_image(ctx, texUnit, target, level);
1453
1454 if (!texImage) {
1455 texImage = _mesa_alloc_texture_image();
1456 set_tex_image(texObj, target, level, texImage);
1457 /*texObj->Image[level] = texImage;*/
1458 if (!texImage) {
1459 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
1460 return;
1461 }
1462 }
1463 else if (texImage->Data) {
1464 FREE(texImage->Data);
1465 texImage->Data = NULL;
1466 }
1467
1468 /* setup the teximage struct's fields */
1469 init_texture_image(texImage, width, height, 1, border, internalFormat);
1470
1471 /* process the texture image */
1472 if (pixels) {
1473 GLboolean retain = GL_TRUE;
1474 GLboolean success = GL_FALSE;
1475 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1476 && ctx->Driver.TexImage2D) {
1477 /* let device driver try to use raw image */
1478 success = (*ctx->Driver.TexImage2D)( ctx, target, level, format,
1479 type, pixels, &ctx->Unpack,
1480 texObj, texImage, &retain);
1481 }
1482 if (retain || !success) {
1483 /* make internal copy of the texture image */
1484 make_texture_image(ctx, texImage, format, type,
1485 pixels, &ctx->Unpack);
1486 if (!success && ctx->Driver.TexImage2D) {
1487 /* let device driver try to use unpacked image */
1488 (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1489 GL_UNSIGNED_BYTE, texImage->Data,
1490 &_mesa_native_packing,
1491 texObj, texImage, &retain);
1492 }
1493 }
1494 if (!retain && texImage->Data) {
1495 FREE(texImage->Data);
1496 texImage->Data = NULL;
1497 }
1498 }
1499 else {
1500 make_null_texture(texImage);
1501 if (ctx->Driver.TexImage2D) {
1502 GLboolean retain;
1503 (*ctx->Driver.TexImage2D)( ctx, target, level, texImage->Format,
1504 GL_UNSIGNED_BYTE, texImage->Data,
1505 &_mesa_native_packing,
1506 texObj, texImage, &retain);
1507 }
1508 }
1509
1510 #define OLD_DD_TEXTURE
1511 #ifdef OLD_DD_TEXTURE
1512 /* XXX this will be removed in the future */
1513 if (ctx->Driver.TexImage) {
1514 (*ctx->Driver.TexImage)( ctx, target, texObj, level, internalFormat,
1515 texImage );
1516 }
1517 #endif
1518
1519 /* state update */
1520 gl_put_texobj_on_dirty_list( ctx, texObj );
1521 ctx->NewState |= NEW_TEXTURING;
1522 }
1523 else if (target==GL_PROXY_TEXTURE_2D) {
1524 /* Proxy texture: check for errors and update proxy state */
1525 if (texture_error_check(ctx, target, level, internalFormat,
1526 format, type, 2, width, height, 1, border)) {
1527 /* if error, clear all proxy texture image parameters */
1528 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1529 MEMSET( ctx->Texture.Proxy2D->Image[level], 0,
1530 sizeof(struct gl_texture_image) );
1531 }
1532 }
1533 else {
1534 /* if no error, update proxy texture image parameters */
1535 init_texture_image(ctx->Texture.Proxy1D->Image[level],
1536 width, height, 1, border, internalFormat);
1537 }
1538 }
1539 else {
1540 gl_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
1541 return;
1542 }
1543 }
1544
1545
1546
1547 /*
1548 * Called by the API or display list executor.
1549 * Note that width and height include the border.
1550 */
1551 void
1552 _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
1553 GLsizei width, GLsizei height, GLsizei depth,
1554 GLint border, GLenum format, GLenum type,
1555 const GLvoid *pixels )
1556 {
1557 GET_CURRENT_CONTEXT(ctx);
1558 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glTexImage3D");
1559
1560 if (target==GL_TEXTURE_3D_EXT) {
1561 struct gl_texture_unit *texUnit;
1562 struct gl_texture_object *texObj;
1563 struct gl_texture_image *texImage;
1564 if (texture_error_check(ctx, target, level, internalFormat,
1565 format, type, 3, width, height, depth, border)) {
1566 return; /* error in texture image was detected */
1567 }
1568
1569 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1570 texObj = texUnit->CurrentD[3];
1571 texImage = texObj->Image[level];
1572
1573 if (!texImage) {
1574 texImage = _mesa_alloc_texture_image();
1575 texObj->Image[level] = texImage;
1576 if (!texImage) {
1577 gl_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
1578 return;
1579 }
1580 }
1581 else if (texImage->Data) {
1582 FREE(texImage->Data);
1583 texImage->Data = NULL;
1584 }
1585
1586 /* setup the teximage struct's fields */
1587 init_texture_image(texImage, width, height, depth,
1588 border, internalFormat);
1589
1590 /* process the texture image */
1591 if (pixels) {
1592 GLboolean retain = GL_TRUE;
1593 GLboolean success = GL_FALSE;
1594 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1595 && ctx->Driver.TexImage3D) {
1596 /* let device driver try to use raw image */
1597 success = (*ctx->Driver.TexImage3D)( ctx, target, level, format,
1598 type, pixels, &ctx->Unpack,
1599 texObj, texImage, &retain);
1600 }
1601 if (retain || !success) {
1602 /* make internal copy of the texture image */
1603 make_texture_image(ctx, texImage, format, type,
1604 pixels, &ctx->Unpack);
1605 if (!success && ctx->Driver.TexImage3D) {
1606 /* let device driver try to use unpacked image */
1607 (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1608 GL_UNSIGNED_BYTE, texImage->Data,
1609 &_mesa_native_packing,
1610 texObj, texImage, &retain);
1611 }
1612 }
1613 if (!retain && texImage->Data) {
1614 FREE(texImage->Data);
1615 texImage->Data = NULL;
1616 }
1617 }
1618 else {
1619 make_null_texture(texImage);
1620 if (ctx->Driver.TexImage3D) {
1621 GLboolean retain;
1622 (*ctx->Driver.TexImage3D)( ctx, target, level, texImage->Format,
1623 GL_UNSIGNED_BYTE, texImage->Data,
1624 &_mesa_native_packing,
1625 texObj, texImage, &retain);
1626 }
1627 }
1628
1629 /* state update */
1630 gl_put_texobj_on_dirty_list( ctx, texObj );
1631 ctx->NewState |= NEW_TEXTURING;
1632 }
1633 else if (target==GL_PROXY_TEXTURE_3D) {
1634 /* Proxy texture: check for errors and update proxy state */
1635 if (texture_error_check(ctx, target, level, internalFormat,
1636 format, type, 3, width, height, depth, border)) {
1637 /* if error, clear all proxy texture image parameters */
1638 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
1639 MEMSET( ctx->Texture.Proxy3D->Image[level], 0,
1640 sizeof(struct gl_texture_image) );
1641 }
1642 }
1643 else {
1644 /* if no error, update proxy texture image parameters */
1645 init_texture_image(ctx->Texture.Proxy1D->Image[level],
1646 width, height, depth, border, internalFormat);
1647 }
1648 }
1649 else {
1650 gl_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
1651 return;
1652 }
1653 }
1654
1655
1656 void
1657 _mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
1658 GLsizei width, GLsizei height, GLsizei depth,
1659 GLint border, GLenum format, GLenum type,
1660 const GLvoid *pixels )
1661 {
1662 _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height,
1663 depth, border, format, type, pixels);
1664 }
1665
1666
1667 /*
1668 * Fetch a texture image from the device driver.
1669 * Store the results in the given texture object at the given mipmap level.
1670 */
1671 void
1672 _mesa_get_teximage_from_driver( GLcontext *ctx, GLenum target, GLint level,
1673 const struct gl_texture_object *texObj )
1674 {
1675 GLvoid *image;
1676 GLenum imgFormat, imgType;
1677 GLboolean freeImage;
1678 struct gl_texture_image *texImage;
1679 GLint destComponents, numPixels, srcBytesPerTexel;
1680
1681 if (!ctx->Driver.GetTexImage)
1682 return;
1683
1684 image = (*ctx->Driver.GetTexImage)( ctx, target, level, texObj,
1685 &imgFormat, &imgType, &freeImage);
1686 if (!image)
1687 return;
1688
1689 texImage = texObj->Image[level];
1690 ASSERT(texImage);
1691 if (!texImage)
1692 return;
1693
1694 destComponents = components_in_intformat(texImage->Format);
1695 assert(destComponents > 0);
1696 numPixels = texImage->Width * texImage->Height * texImage->Depth;
1697 assert(numPixels > 0);
1698 srcBytesPerTexel = _mesa_bytes_per_pixel(imgFormat, imgType);
1699 assert(srcBytesPerTexel > 0);
1700
1701 if (!texImage->Data) {
1702 /* Allocate memory for the texture image data */
1703 texImage->Data = (GLubyte *) MALLOC(numPixels * destComponents + EXTRA_BYTE);
1704 }
1705
1706 if (imgFormat == texImage->Format && imgType == GL_UNSIGNED_BYTE) {
1707 /* We got lucky! The driver's format and type match Mesa's format. */
1708 if (texImage->Data) {
1709 MEMCPY(texImage->Data, image, numPixels * destComponents);
1710 }
1711 }
1712 else {
1713 /* Convert the texture image from the driver's format to Mesa's
1714 * internal format.
1715 */
1716 const GLint width = texImage->Width;
1717 const GLint height = texImage->Height;
1718 const GLint depth = texImage->Depth;
1719 const GLint destBytesPerRow = width * destComponents * sizeof(GLchan);
1720 const GLint srcBytesPerRow = width * srcBytesPerTexel;
1721 const GLenum dstType = GL_UNSIGNED_BYTE;
1722 const GLenum dstFormat = texImage->Format;
1723 const GLubyte *srcPtr = (const GLubyte *) image;
1724 GLubyte *destPtr = texImage->Data;
1725
1726 if (texImage->Format == GL_COLOR_INDEX) {
1727 /* color index texture */
1728 GLint img, row;
1729 assert(imgFormat == GL_COLOR_INDEX);
1730 for (img = 0; img < depth; img++) {
1731 for (row = 0; row < height; row++) {
1732 _mesa_unpack_index_span(ctx, width, dstType, destPtr,
1733 imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
1734 destPtr += destBytesPerRow;
1735 srcPtr += srcBytesPerRow;
1736 }
1737 }
1738 }
1739 else {
1740 /* color texture */
1741 GLint img, row;
1742 for (img = 0; img < depth; img++) {
1743 for (row = 0; row < height; row++) {
1744 _mesa_unpack_ubyte_color_span(ctx, width, dstFormat, destPtr,
1745 imgFormat, imgType, srcPtr, &_mesa_native_packing, GL_FALSE);
1746 destPtr += destBytesPerRow;
1747 srcPtr += srcBytesPerRow;
1748 }
1749 }
1750 }
1751 }
1752
1753 if (freeImage)
1754 FREE(image);
1755 }
1756
1757
1758 void
1759 _mesa_GetTexImage( GLenum target, GLint level, GLenum format,
1760 GLenum type, GLvoid *pixels )
1761 {
1762 GET_CURRENT_CONTEXT(ctx);
1763 const struct gl_texture_object *texObj;
1764 struct gl_texture_image *texImage;
1765 GLboolean discardImage;
1766
1767 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glGetTexImage");
1768
1769 if (level < 0 || level >= ctx->Const.MaxTextureLevels) {
1770 gl_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" );
1771 return;
1772 }
1773
1774 if (_mesa_sizeof_type(type) <= 0) {
1775 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" );
1776 return;
1777 }
1778
1779 if (_mesa_components_in_format(format) <= 0) {
1780 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" );
1781 return;
1782 }
1783
1784 if (!pixels)
1785 return;
1786
1787 switch (target) {
1788 case GL_TEXTURE_1D:
1789 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[1];
1790 break;
1791 case GL_TEXTURE_2D:
1792 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[2];
1793 break;
1794 case GL_TEXTURE_3D:
1795 texObj = ctx->Texture.Unit[ctx->Texture.CurrentUnit].CurrentD[3];
1796 break;
1797 default:
1798 gl_error( ctx, GL_INVALID_ENUM, "glGetTexImage(target)" );
1799 return;
1800 }
1801
1802 texImage = texObj->Image[level];
1803 if (!texImage) {
1804 /* invalid mipmap level */
1805 return;
1806 }
1807
1808 if (!texImage->Data) {
1809 /* try to get the texture image from the device driver */
1810 _mesa_get_teximage_from_driver(ctx, target, level, texObj);
1811 discardImage = GL_TRUE;
1812 }
1813 else {
1814 discardImage = GL_FALSE;
1815 }
1816
1817 if (texImage->Data) {
1818 GLint width = texImage->Width;
1819 GLint height = texImage->Height;
1820 GLint row;
1821
1822 for (row = 0; row < height; row++) {
1823 /* compute destination address in client memory */
1824 GLvoid *dest = _mesa_image_address( &ctx->Unpack, pixels,
1825 width, height,
1826 format, type, 0, row, 0);
1827
1828 assert(dest);
1829 if (texImage->Format == GL_RGBA) {
1830 const GLubyte *src = texImage->Data + row * width * 4 * sizeof(GLubyte);
1831 _mesa_pack_rgba_span( ctx, width, (CONST GLubyte (*)[4]) src,
1832 format, type, dest, &ctx->Pack, GL_TRUE );
1833 }
1834 else {
1835 /* fetch RGBA row from texture image then pack it in client mem */
1836 GLubyte rgba[MAX_WIDTH][4];
1837 GLint i;
1838 const GLubyte *src;
1839 switch (texImage->Format) {
1840 case GL_ALPHA:
1841 src = texImage->Data + row * width * sizeof(GLubyte);
1842 for (i = 0; i < width; i++) {
1843 rgba[i][RCOMP] = 255;
1844 rgba[i][GCOMP] = 255;
1845 rgba[i][BCOMP] = 255;
1846 rgba[i][ACOMP] = src[i];
1847 }
1848 break;
1849 case GL_LUMINANCE:
1850 src = texImage->Data + row * width * sizeof(GLubyte);
1851 for (i = 0; i < width; i++) {
1852 rgba[i][RCOMP] = src[i];
1853 rgba[i][GCOMP] = src[i];
1854 rgba[i][BCOMP] = src[i];
1855 rgba[i][ACOMP] = 255;
1856 }
1857 break;
1858 case GL_LUMINANCE_ALPHA:
1859 src = texImage->Data + row * 2 * width * sizeof(GLubyte);
1860 for (i = 0; i < width; i++) {
1861 rgba[i][RCOMP] = src[i*2+0];
1862 rgba[i][GCOMP] = src[i*2+0];
1863 rgba[i][BCOMP] = src[i*2+0];
1864 rgba[i][ACOMP] = src[i*2+1];
1865 }
1866 break;
1867 case GL_INTENSITY:
1868 src = texImage->Data + row * width * sizeof(GLubyte);
1869 for (i = 0; i < width; i++) {
1870 rgba[i][RCOMP] = src[i];
1871 rgba[i][GCOMP] = src[i];
1872 rgba[i][BCOMP] = src[i];
1873 rgba[i][ACOMP] = 255;
1874 }
1875 break;
1876 case GL_RGB:
1877 src = texImage->Data + row * 3 * width * sizeof(GLubyte);
1878 for (i = 0; i < width; i++) {
1879 rgba[i][RCOMP] = src[i*3+0];
1880 rgba[i][GCOMP] = src[i*3+1];
1881 rgba[i][BCOMP] = src[i*3+2];
1882 rgba[i][ACOMP] = 255;
1883 }
1884 break;
1885 case GL_RGBA:
1886 /* this special case should have been handled above! */
1887 gl_problem( ctx, "error 1 in gl_GetTexImage" );
1888 break;
1889 case GL_COLOR_INDEX:
1890 gl_problem( ctx, "GL_COLOR_INDEX not implemented in gl_GetTexImage" );
1891 break;
1892 default:
1893 gl_problem( ctx, "bad format in gl_GetTexImage" );
1894 }
1895 _mesa_pack_rgba_span( ctx, width, (const GLubyte (*)[4])rgba,
1896 format, type, dest, &ctx->Pack, GL_TRUE );
1897 }
1898 }
1899
1900 /* if we got the teximage from the device driver we'll discard it now */
1901 if (discardImage) {
1902 FREE(texImage->Data);
1903 texImage->Data = NULL;
1904 }
1905 }
1906 }
1907
1908
1909
1910 void
1911 _mesa_TexSubImage1D( GLenum target, GLint level,
1912 GLint xoffset, GLsizei width,
1913 GLenum format, GLenum type,
1914 const GLvoid *pixels )
1915 {
1916 GET_CURRENT_CONTEXT(ctx);
1917 struct gl_texture_unit *texUnit;
1918 struct gl_texture_object *texObj;
1919 struct gl_texture_image *texImage;
1920 GLboolean success = GL_FALSE;
1921
1922 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
1923 width, 1, 1, format, type)) {
1924 return; /* error was detected */
1925 }
1926
1927 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
1928 texObj = texUnit->CurrentD[1];
1929 texImage = texObj->Image[level];
1930 assert(texImage);
1931
1932 if (width == 0 || !pixels)
1933 return; /* no-op, not an error */
1934
1935
1936 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
1937 && ctx->Driver.TexSubImage1D) {
1938 success = (*ctx->Driver.TexSubImage1D)( ctx, target, level, xoffset,
1939 width, format, type, pixels,
1940 &ctx->Unpack, texObj, texImage );
1941 }
1942 if (!success) {
1943 /* XXX if Driver.TexSubImage1D, unpack image and try again? */
1944
1945 const GLint texComponents = components_in_intformat(texImage->Format);
1946 const GLenum texFormat = texImage->Format;
1947 const GLint xoffsetb = xoffset + texImage->Border;
1948 GLboolean retain = GL_TRUE;
1949 if (!texImage->Data) {
1950 _mesa_get_teximage_from_driver( ctx, target, level, texObj );
1951 if (!texImage->Data) {
1952 make_null_texture(texImage);
1953 }
1954 if (!texImage->Data)
1955 return; /* we're really out of luck! */
1956 }
1957
1958 if (texFormat == GL_COLOR_INDEX) {
1959 /* color index texture */
1960 GLubyte *dst = texImage->Data + xoffsetb * texComponents;
1961 const GLvoid *src = _mesa_image_address(&ctx->Unpack, pixels, width,
1962 1, format, type, 0, 0, 0);
1963 _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst,
1964 type, src, &ctx->Unpack, GL_TRUE);
1965 }
1966 else {
1967 /* color texture */
1968 GLubyte *dst = texImage->Data + xoffsetb * texComponents;
1969 const GLvoid *src = _mesa_image_address(&ctx->Unpack, pixels, width,
1970 1, format, type, 0, 0, 0);
1971 _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst, format,
1972 type, src, &ctx->Unpack, GL_TRUE);
1973 }
1974
1975 if (ctx->Driver.TexImage1D) {
1976 (*ctx->Driver.TexImage1D)( ctx, target, level, texImage->Format,
1977 GL_UNSIGNED_BYTE, texImage->Data,
1978 &_mesa_native_packing, texObj, texImage,
1979 &retain );
1980 }
1981
1982 if (!retain && texImage->Data) {
1983 FREE(texImage->Data);
1984 texImage->Data = NULL;
1985 }
1986 }
1987
1988 /*gl_put_texobj_on_dirty_list( ctx, texUnit->CurrentD[1] );*/
1989 }
1990
1991
1992 void
1993 _mesa_TexSubImage2D( GLenum target, GLint level,
1994 GLint xoffset, GLint yoffset,
1995 GLsizei width, GLsizei height,
1996 GLenum format, GLenum type,
1997 const GLvoid *pixels )
1998 {
1999 GET_CURRENT_CONTEXT(ctx);
2000 struct gl_texture_unit *texUnit;
2001 struct gl_texture_object *texObj;
2002 struct gl_texture_image *texImage;
2003 GLboolean success = GL_FALSE;
2004
2005 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
2006 width, height, 1, format, type)) {
2007 return; /* error was detected */
2008 }
2009
2010 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2011 texObj = _mesa_select_tex_object(ctx, texUnit, target);
2012 texImage = texObj->Image[level];
2013 assert(texImage);
2014
2015 if (width == 0 || height == 0 || !pixels)
2016 return; /* no-op, not an error */
2017
2018 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
2019 && ctx->Driver.TexSubImage2D) {
2020 success = (*ctx->Driver.TexSubImage2D)( ctx, target, level, xoffset,
2021 yoffset, width, height, format, type,
2022 pixels, &ctx->Unpack, texObj, texImage );
2023 }
2024 if (!success) {
2025 /* XXX if Driver.TexSubImage2D, unpack image and try again? */
2026
2027 const GLint texComponents = components_in_intformat(texImage->Format);
2028 const GLenum texFormat = texImage->Format;
2029 const GLint xoffsetb = xoffset + texImage->Border;
2030 const GLint yoffsetb = yoffset + texImage->Border;
2031 const GLint srcStride = _mesa_image_row_stride(&ctx->Unpack, width,
2032 format, type);
2033 const GLint dstStride = texImage->Width * texComponents *sizeof(GLubyte);
2034 GLboolean retain = GL_TRUE;
2035
2036 if (!texImage->Data) {
2037 _mesa_get_teximage_from_driver( ctx, target, level, texObj );
2038 if (!texImage->Data) {
2039 make_null_texture(texImage);
2040 }
2041 if (!texImage->Data)
2042 return; /* we're really out of luck! */
2043 }
2044
2045 if (texFormat == GL_COLOR_INDEX) {
2046 /* color index texture */
2047 GLubyte *dst = texImage->Data
2048 + (yoffsetb * texImage->Width + xoffsetb) * texComponents;
2049 const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels,
2050 width, height, format, type, 0, 0, 0);
2051 GLint row;
2052 for (row = 0; row < height; row++) {
2053 _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst, type,
2054 (const GLvoid *) src, &ctx->Unpack, GL_TRUE);
2055 src += srcStride;
2056 dst += dstStride;
2057 }
2058 }
2059 else {
2060 /* color texture */
2061 GLubyte *dst = texImage->Data
2062 + (yoffsetb * texImage->Width + xoffsetb) * texComponents;
2063 const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels,
2064 width, height, format, type, 0, 0, 0);
2065 GLint row;
2066 for (row = 0; row < height; row++) {
2067 _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst, format,
2068 type, (const GLvoid *) src, &ctx->Unpack, GL_TRUE);
2069 src += srcStride;
2070 dst += dstStride;
2071 }
2072 }
2073
2074 if (ctx->Driver.TexImage2D) {
2075 (*ctx->Driver.TexImage2D)(ctx, target, level, texImage->Format,
2076 GL_UNSIGNED_BYTE, texImage->Data,
2077 &_mesa_native_packing, texObj, texImage,
2078 &retain);
2079 }
2080
2081 if (!retain && texImage->Data) {
2082 FREE(texImage->Data);
2083 texImage->Data = NULL;
2084 }
2085
2086 #ifdef OLD_DD_TEXTURE
2087 /* XXX this will be removed in the future */
2088 if (ctx->Driver.TexSubImage) {
2089 (*ctx->Driver.TexSubImage)(ctx, target, texObj, level,
2090 xoffset, yoffset, width, height,
2091 texImage->IntFormat, texImage);
2092 }
2093 else if (ctx->Driver.TexImage) {
2094 (*ctx->Driver.TexImage)(ctx, GL_TEXTURE_2D, texObj,
2095 level, texImage->IntFormat, texImage );
2096 }
2097 #endif
2098 }
2099 }
2100
2101
2102
2103 void
2104 _mesa_TexSubImage3D( GLenum target, GLint level,
2105 GLint xoffset, GLint yoffset, GLint zoffset,
2106 GLsizei width, GLsizei height, GLsizei depth,
2107 GLenum format, GLenum type,
2108 const GLvoid *pixels )
2109 {
2110 GET_CURRENT_CONTEXT(ctx);
2111 struct gl_texture_unit *texUnit;
2112 struct gl_texture_object *texObj;
2113 struct gl_texture_image *texImage;
2114 GLboolean success = GL_FALSE;
2115
2116 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
2117 width, height, depth, format, type)) {
2118 return; /* error was detected */
2119 }
2120
2121 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2122 texObj = texUnit->CurrentD[3];
2123 texImage = texObj->Image[level];
2124 assert(texImage);
2125
2126 if (width == 0 || height == 0 || height == 0 || !pixels)
2127 return; /* no-op, not an error */
2128
2129 if (!ctx->Pixel.MapColorFlag && !ctx->Pixel.ScaleOrBiasRGBA
2130 && ctx->Driver.TexSubImage3D) {
2131 success = (*ctx->Driver.TexSubImage3D)( ctx, target, level, xoffset,
2132 yoffset, zoffset, width, height, depth, format,
2133 type, pixels, &ctx->Unpack, texObj, texImage );
2134 }
2135 if (!success) {
2136 /* XXX if Driver.TexSubImage3D, unpack image and try again? */
2137
2138 const GLint texComponents = components_in_intformat(texImage->Format);
2139 const GLenum texFormat = texImage->Format;
2140 const GLint xoffsetb = xoffset + texImage->Border;
2141 const GLint yoffsetb = yoffset + texImage->Border;
2142 const GLint zoffsetb = zoffset + texImage->Border;
2143 const GLint texWidth = texImage->Width;
2144 const GLint dstRectArea = texWidth * texImage->Height;
2145 const GLint srcStride = _mesa_image_row_stride(&ctx->Unpack,
2146 width, format, type);
2147 const GLint dstStride = texWidth * texComponents * sizeof(GLubyte);
2148 GLboolean retain = GL_TRUE;
2149
2150 if (texFormat == GL_COLOR_INDEX) {
2151 /* color index texture */
2152 GLint img, row;
2153 for (img = 0; img < depth; img++) {
2154 const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels,
2155 width, height, format, type, img, 0, 0);
2156 GLubyte *dst = texImage->Data + ((zoffsetb + img) * dstRectArea
2157 + yoffsetb * texWidth + xoffsetb) * texComponents;
2158 for (row = 0; row < height; row++) {
2159 _mesa_unpack_index_span(ctx, width, GL_UNSIGNED_BYTE, dst,
2160 type, (const GLvoid *) src, &ctx->Unpack, GL_TRUE);
2161 src += srcStride;
2162 dst += dstStride;
2163 }
2164 }
2165 }
2166 else {
2167 /* color texture */
2168 GLint img, row;
2169 for (img = 0; img < depth; img++) {
2170 const GLubyte *src = _mesa_image_address(&ctx->Unpack, pixels,
2171 width, height, format, type, img, 0, 0);
2172 GLubyte *dst = texImage->Data + ((zoffsetb + img) * dstRectArea
2173 + yoffsetb * texWidth + xoffsetb) * texComponents;
2174 for (row = 0; row < height; row++) {
2175 _mesa_unpack_ubyte_color_span(ctx, width, texFormat, dst,
2176 format, type, (const GLvoid *) src, &ctx->Unpack, GL_TRUE);
2177 src += srcStride;
2178 dst += dstStride;
2179 }
2180 }
2181 }
2182
2183 if (ctx->Driver.TexImage3D) {
2184 (*ctx->Driver.TexImage3D)(ctx, target, level, texImage->Format,
2185 GL_UNSIGNED_BYTE, texImage->Data,
2186 &_mesa_native_packing, texObj, texImage,
2187 &retain);
2188 }
2189
2190 if (!retain && texImage->Data) {
2191 FREE(texImage->Data);
2192 texImage->Data = NULL;
2193 }
2194 }
2195 }
2196
2197
2198
2199 /*
2200 * Read an RGBA image from the frame buffer.
2201 * This is used by glCopyTexSubImage[12]D().
2202 * Input: ctx - the context
2203 * x, y - lower left corner
2204 * width, height - size of region to read
2205 * Return: pointer to block of GL_RGBA, GLubyte data.
2206 */
2207 static GLubyte *
2208 read_color_image( GLcontext *ctx, GLint x, GLint y,
2209 GLsizei width, GLsizei height )
2210 {
2211 GLint stride, i;
2212 GLubyte *image, *dst;
2213
2214 image = (GLubyte *) MALLOC(width * height * 4 * sizeof(GLubyte));
2215 if (!image)
2216 return NULL;
2217
2218 /* Select buffer to read from */
2219 (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
2220 ctx->Pixel.DriverReadBuffer );
2221
2222 dst = image;
2223 stride = width * 4 * sizeof(GLubyte);
2224 for (i = 0; i < height; i++) {
2225 gl_read_rgba_span( ctx, ctx->ReadBuffer, width, x, y + i,
2226 (GLubyte (*)[4]) dst );
2227 dst += stride;
2228 }
2229
2230 /* Read from draw buffer (the default) */
2231 (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
2232 ctx->Color.DriverDrawBuffer );
2233
2234 return image;
2235 }
2236
2237
2238
2239 void
2240 _mesa_CopyTexImage1D( GLenum target, GLint level,
2241 GLenum internalFormat,
2242 GLint x, GLint y,
2243 GLsizei width, GLint border )
2244 {
2245 GET_CURRENT_CONTEXT(ctx);
2246 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage1D");
2247
2248 if (copytexture_error_check(ctx, 1, target, level, internalFormat,
2249 width, 1, border))
2250 return;
2251
2252 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
2253 || !ctx->Driver.CopyTexImage1D
2254 || !(*ctx->Driver.CopyTexImage1D)(ctx, target, level,
2255 internalFormat, x, y, width, border))
2256 {
2257 GLubyte *image = read_color_image( ctx, x, y, width, 1 );
2258 if (!image) {
2259 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D" );
2260 return;
2261 }
2262 (*ctx->Exec->TexImage1D)( target, level, internalFormat, width,
2263 border, GL_RGBA, GL_UNSIGNED_BYTE, image );
2264 FREE(image);
2265 }
2266 }
2267
2268
2269
2270 void
2271 _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
2272 GLint x, GLint y, GLsizei width, GLsizei height,
2273 GLint border )
2274 {
2275 GET_CURRENT_CONTEXT(ctx);
2276 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexImage2D");
2277
2278 if (copytexture_error_check(ctx, 2, target, level, internalFormat,
2279 width, height, border))
2280 return;
2281
2282 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
2283 || !ctx->Driver.CopyTexImage2D
2284 || !(*ctx->Driver.CopyTexImage2D)(ctx, target, level,
2285 internalFormat, x, y, width, height, border))
2286 {
2287 GLubyte *image = read_color_image( ctx, x, y, width, height );
2288 if (!image) {
2289 gl_error( ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D" );
2290 return;
2291 }
2292 (ctx->Exec->TexImage2D)( target, level, internalFormat, width,
2293 height, border, GL_RGBA, GL_UNSIGNED_BYTE, image );
2294 FREE(image);
2295 }
2296 }
2297
2298
2299
2300 /*
2301 * Do the work of glCopyTexSubImage[123]D.
2302 */
2303 static void
2304 copy_tex_sub_image( GLcontext *ctx, struct gl_texture_image *dest,
2305 GLint width, GLint height,
2306 GLint srcx, GLint srcy,
2307 GLint dstx, GLint dsty, GLint dstz )
2308 {
2309 GLint i;
2310 GLint format, components, rectarea;
2311 GLint texwidth, texheight, zoffset;
2312
2313 /* dst[xyz] may be negative if we have a texture border! */
2314 dstx += dest->Border;
2315 dsty += dest->Border;
2316 dstz += dest->Border;
2317 texwidth = dest->Width;
2318 texheight = dest->Height;
2319 rectarea = texwidth * texheight;
2320 zoffset = dstz * rectarea;
2321 format = dest->Format;
2322 components = components_in_intformat( format );
2323
2324 /* Select buffer to read from */
2325 (*ctx->Driver.SetReadBuffer)( ctx, ctx->ReadBuffer,
2326 ctx->Pixel.DriverReadBuffer );
2327
2328 for (i = 0;i < height; i++) {
2329 GLubyte rgba[MAX_WIDTH][4];
2330 GLubyte *dst;
2331 gl_read_rgba_span( ctx, ctx->ReadBuffer, width, srcx, srcy + i, rgba );
2332 dst = dest->Data + ( zoffset + (dsty+i) * texwidth + dstx) * components;
2333 _mesa_unpack_ubyte_color_span(ctx, width, format, dst,
2334 GL_RGBA, GL_UNSIGNED_BYTE, rgba,
2335 &_mesa_native_packing, GL_TRUE);
2336 }
2337
2338 /* Read from draw buffer (the default) */
2339 (*ctx->Driver.SetReadBuffer)( ctx, ctx->DrawBuffer,
2340 ctx->Color.DriverDrawBuffer );
2341 }
2342
2343
2344
2345
2346 void
2347 _mesa_CopyTexSubImage1D( GLenum target, GLint level,
2348 GLint xoffset, GLint x, GLint y, GLsizei width )
2349 {
2350 GET_CURRENT_CONTEXT(ctx);
2351 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage1D");
2352
2353 if (copytexsubimage_error_check(ctx, 1, target, level,
2354 xoffset, 0, 0, width, 1))
2355 return;
2356
2357 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
2358 || !ctx->Driver.CopyTexSubImage1D
2359 || !(*ctx->Driver.CopyTexSubImage1D)(ctx, target, level,
2360 xoffset, x, y, width)) {
2361 struct gl_texture_unit *texUnit;
2362 struct gl_texture_image *teximage;
2363 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2364 teximage = texUnit->CurrentD[1]->Image[level];
2365 assert(teximage);
2366 if (teximage->Data) {
2367 copy_tex_sub_image(ctx, teximage, width, 1, x, y, xoffset, 0, 0);
2368 /* tell driver about the change */
2369 /* XXX this is obsolete */
2370 if (ctx->Driver.TexImage) {
2371 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_1D,
2372 texUnit->CurrentD[1],
2373 level, teximage->IntFormat, teximage );
2374 }
2375 }
2376 }
2377 }
2378
2379
2380
2381 void
2382 _mesa_CopyTexSubImage2D( GLenum target, GLint level,
2383 GLint xoffset, GLint yoffset,
2384 GLint x, GLint y, GLsizei width, GLsizei height )
2385 {
2386 GET_CURRENT_CONTEXT(ctx);
2387 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage2D");
2388
2389 if (copytexsubimage_error_check(ctx, 2, target, level,
2390 xoffset, yoffset, 0, width, height))
2391 return;
2392
2393 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
2394 || !ctx->Driver.CopyTexSubImage2D
2395 || !(*ctx->Driver.CopyTexSubImage2D)(ctx, target, level,
2396 xoffset, yoffset, x, y, width, height )) {
2397 struct gl_texture_unit *texUnit;
2398 struct gl_texture_image *teximage;
2399 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2400 teximage = texUnit->CurrentD[2]->Image[level];
2401 assert(teximage);
2402 if (teximage->Data) {
2403 copy_tex_sub_image(ctx, teximage, width, height,
2404 x, y, xoffset, yoffset, 0);
2405 /* tell driver about the change */
2406 /* XXX this is obsolete */
2407 if (ctx->Driver.TexImage) {
2408 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_2D,
2409 texUnit->CurrentD[2],
2410 level, teximage->IntFormat, teximage );
2411 }
2412 }
2413 }
2414 }
2415
2416
2417
2418 void
2419 _mesa_CopyTexSubImage3D( GLenum target, GLint level,
2420 GLint xoffset, GLint yoffset, GLint zoffset,
2421 GLint x, GLint y, GLsizei width, GLsizei height )
2422 {
2423 GET_CURRENT_CONTEXT(ctx);
2424 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCopyTexSubImage3D");
2425
2426 if (copytexsubimage_error_check(ctx, 3, target, level,
2427 xoffset, yoffset, zoffset, width, height))
2428 return;
2429
2430 if (ctx->Pixel.MapColorFlag || ctx->Pixel.ScaleOrBiasRGBA
2431 || !ctx->Driver.CopyTexSubImage3D
2432 || !(*ctx->Driver.CopyTexSubImage3D)(ctx, target, level,
2433 xoffset, yoffset, zoffset, x, y, width, height )) {
2434 struct gl_texture_unit *texUnit;
2435 struct gl_texture_image *teximage;
2436 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2437 teximage = texUnit->CurrentD[3]->Image[level];
2438 assert(teximage);
2439 if (teximage->Data) {
2440 copy_tex_sub_image(ctx, teximage, width, height,
2441 x, y, xoffset, yoffset, zoffset);
2442 /* tell driver about the change */
2443 /* XXX this is obsolete */
2444 if (ctx->Driver.TexImage) {
2445 (*ctx->Driver.TexImage)( ctx, GL_TEXTURE_3D,
2446 texUnit->CurrentD[3],
2447 level, teximage->IntFormat, teximage );
2448 }
2449 }
2450 }
2451 }
2452
2453
2454
2455 void
2456 _mesa_CompressedTexImage1DARB(GLenum target, GLint level,
2457 GLenum internalFormat, GLsizei width,
2458 GLint border, GLsizei imageSize,
2459 const GLvoid *data)
2460 {
2461 GET_CURRENT_CONTEXT(ctx);
2462 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage1DARB");
2463
2464 if (target == GL_TEXTURE_1D) {
2465 struct gl_texture_unit *texUnit;
2466 struct gl_texture_object *texObj;
2467 struct gl_texture_image *texImage;
2468
2469 if (texture_error_check(ctx, target, level, internalFormat,
2470 GL_NONE, GL_NONE, 1, width, 1, 1, border)) {
2471 return; /* error in texture image was detected */
2472 }
2473
2474 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2475 texObj = texUnit->CurrentD[1];
2476 texImage = texObj->Image[level];
2477
2478 if (!texImage) {
2479 texImage = _mesa_alloc_texture_image();
2480 texObj->Image[level] = texImage;
2481 if (!texImage) {
2482 gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1DARB");
2483 return;
2484 }
2485 }
2486 else if (texImage->Data) {
2487 FREE(texImage->Data);
2488 texImage->Data = NULL;
2489 }
2490
2491 /* setup the teximage struct's fields */
2492 init_texture_image(texImage, width, 1, 1, border, internalFormat);
2493
2494 /* process the texture image */
2495 if (data) {
2496 GLboolean retain = GL_TRUE;
2497 GLboolean success = GL_FALSE;
2498 if (ctx->Driver.CompressedTexImage1D) {
2499 success = (*ctx->Driver.CompressedTexImage1D)( ctx, target, level,
2500 data, texObj, texImage, &retain);
2501 }
2502 if (retain || !success) {
2503 /* make internal copy of the texture image */
2504 GLuint imageSize = _mesa_compressed_image_size(internalFormat,
2505 width, 1, 1);
2506 texImage->Data = MALLOC(imageSize);
2507 if (texImage->Data) {
2508 MEMCPY(texImage->Data, data, imageSize);
2509 }
2510 }
2511 if (!retain && texImage->Data) {
2512 FREE(texImage->Data);
2513 texImage->Data = NULL;
2514 }
2515 }
2516 else {
2517 make_null_texture(texImage);
2518 if (ctx->Driver.CompressedTexImage1D) {
2519 GLboolean retain;
2520 (*ctx->Driver.CompressedTexImage1D)( ctx, target, level,
2521 texImage->Data, texObj, texImage, &retain);
2522 }
2523 }
2524
2525 /* state update */
2526 gl_put_texobj_on_dirty_list( ctx, texObj );
2527 ctx->NewState |= NEW_TEXTURING;
2528 }
2529 else if (target == GL_PROXY_TEXTURE_1D) {
2530 /* Proxy texture: check for errors and update proxy state */
2531 if (texture_error_check(ctx, target, level, internalFormat,
2532 GL_NONE, GL_NONE, 1, width, 1, 1, border)) {
2533 /* if error, clear all proxy texture image parameters */
2534 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
2535 MEMSET( ctx->Texture.Proxy1D->Image[level], 0,
2536 sizeof(struct gl_texture_image) );
2537 }
2538 }
2539 else {
2540 /* if no error, update proxy texture image parameters */
2541 init_texture_image(ctx->Texture.Proxy1D->Image[level],
2542 width, 1, 1, border, internalFormat);
2543 }
2544 }
2545 else {
2546 gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage1DARB(target)" );
2547 return;
2548 }
2549 }
2550
2551
2552 void
2553 _mesa_CompressedTexImage2DARB(GLenum target, GLint level,
2554 GLenum internalFormat, GLsizei width,
2555 GLsizei height, GLint border, GLsizei imageSize,
2556 const GLvoid *data)
2557 {
2558 GET_CURRENT_CONTEXT(ctx);
2559 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage2DARB");
2560
2561 if (target == GL_TEXTURE_2D) {
2562 struct gl_texture_unit *texUnit;
2563 struct gl_texture_object *texObj;
2564 struct gl_texture_image *texImage;
2565
2566 if (texture_error_check(ctx, target, level, internalFormat,
2567 GL_NONE, GL_NONE, 1, width, height, 1, border)) {
2568 return; /* error in texture image was detected */
2569 }
2570
2571 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2572 texObj = texUnit->CurrentD[2];
2573 texImage = texObj->Image[level];
2574
2575 if (!texImage) {
2576 texImage = _mesa_alloc_texture_image();
2577 texObj->Image[level] = texImage;
2578 if (!texImage) {
2579 gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2DARB");
2580 return;
2581 }
2582 }
2583 else if (texImage->Data) {
2584 FREE(texImage->Data);
2585 texImage->Data = NULL;
2586 }
2587
2588 /* setup the teximage struct's fields */
2589 init_texture_image(texImage, width, height, 1, border, internalFormat);
2590
2591 /* process the texture image */
2592 if (data) {
2593 GLboolean retain = GL_TRUE;
2594 GLboolean success = GL_FALSE;
2595 if (ctx->Driver.CompressedTexImage2D) {
2596 success = (*ctx->Driver.CompressedTexImage2D)( ctx, target, level,
2597 data, texObj, texImage, &retain);
2598 }
2599 if (retain || !success) {
2600 /* make internal copy of the texture image */
2601 GLuint imageSize = _mesa_compressed_image_size(internalFormat,
2602 width, height, 1);
2603 texImage->Data = MALLOC(imageSize);
2604 if (texImage->Data) {
2605 MEMCPY(texImage->Data, data, imageSize);
2606 }
2607 }
2608 if (!retain && texImage->Data) {
2609 FREE(texImage->Data);
2610 texImage->Data = NULL;
2611 }
2612 }
2613 else {
2614 make_null_texture(texImage);
2615 if (ctx->Driver.CompressedTexImage2D) {
2616 GLboolean retain;
2617 (*ctx->Driver.CompressedTexImage2D)( ctx, target, level,
2618 texImage->Data, texObj, texImage, &retain);
2619 }
2620 }
2621
2622 /* state update */
2623 gl_put_texobj_on_dirty_list( ctx, texObj );
2624 ctx->NewState |= NEW_TEXTURING;
2625 }
2626 else if (target == GL_PROXY_TEXTURE_2D) {
2627 /* Proxy texture: check for errors and update proxy state */
2628 if (texture_error_check(ctx, target, level, internalFormat,
2629 GL_NONE, GL_NONE, 1, width, 1, 1, border)) {
2630 /* if error, clear all proxy texture image parameters */
2631 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
2632 MEMSET( ctx->Texture.Proxy2D->Image[level], 0,
2633 sizeof(struct gl_texture_image) );
2634 }
2635 }
2636 else {
2637 /* if no error, update proxy texture image parameters */
2638 init_texture_image(ctx->Texture.Proxy2D->Image[level],
2639 width, 1, 1, border, internalFormat);
2640 }
2641 }
2642 else {
2643 gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage2DARB(target)" );
2644 return;
2645 }
2646 }
2647
2648
2649 void
2650 _mesa_CompressedTexImage3DARB(GLenum target, GLint level,
2651 GLenum internalFormat, GLsizei width,
2652 GLsizei height, GLsizei depth, GLint border,
2653 GLsizei imageSize, const GLvoid *data)
2654 {
2655 GET_CURRENT_CONTEXT(ctx);
2656 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glCompressedTexImage3DARB");
2657
2658 if (target == GL_TEXTURE_1D) {
2659 struct gl_texture_unit *texUnit;
2660 struct gl_texture_object *texObj;
2661 struct gl_texture_image *texImage;
2662
2663 if (texture_error_check(ctx, target, level, internalFormat,
2664 GL_NONE, GL_NONE, 1, width, height, depth, border)) {
2665 return; /* error in texture image was detected */
2666 }
2667
2668 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
2669 texObj = texUnit->CurrentD[3];
2670 texImage = texObj->Image[level];
2671
2672 if (!texImage) {
2673 texImage = _mesa_alloc_texture_image();
2674 texObj->Image[level] = texImage;
2675 if (!texImage) {
2676 gl_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3DARB");
2677 return;
2678 }
2679 }
2680 else if (texImage->Data) {
2681 FREE(texImage->Data);
2682 texImage->Data = NULL;
2683 }
2684
2685 /* setup the teximage struct's fields */
2686 init_texture_image(texImage, width, height, depth, border, internalFormat);
2687
2688 /* process the texture image */
2689 if (data) {
2690 GLboolean retain = GL_TRUE;
2691 GLboolean success = GL_FALSE;
2692 if (ctx->Driver.CompressedTexImage3D) {
2693 success = (*ctx->Driver.CompressedTexImage3D)( ctx, target, level,
2694 data, texObj, texImage, &retain);
2695 }
2696 if (retain || !success) {
2697 /* make internal copy of the texture image */
2698 GLuint imageSize = _mesa_compressed_image_size(internalFormat,
2699 width, height, depth);
2700 texImage->Data = MALLOC(imageSize);
2701 if (texImage->Data) {
2702 MEMCPY(texImage->Data, data, imageSize);
2703 }
2704 }
2705 if (!retain && texImage->Data) {
2706 FREE(texImage->Data);
2707 texImage->Data = NULL;
2708 }
2709 }
2710 else {
2711 make_null_texture(texImage);
2712 if (ctx->Driver.CompressedTexImage3D) {
2713 GLboolean retain;
2714 (*ctx->Driver.CompressedTexImage3D)( ctx, target, level,
2715 texImage->Data, texObj, texImage, &retain);
2716 }
2717 }
2718
2719 /* state update */
2720 gl_put_texobj_on_dirty_list( ctx, texObj );
2721 ctx->NewState |= NEW_TEXTURING;
2722 }
2723 else if (target == GL_PROXY_TEXTURE_3D) {
2724 /* Proxy texture: check for errors and update proxy state */
2725 if (texture_error_check(ctx, target, level, internalFormat,
2726 GL_NONE, GL_NONE, 1, width, height, depth, border)) {
2727 /* if error, clear all proxy texture image parameters */
2728 if (level>=0 && level<ctx->Const.MaxTextureLevels) {
2729 MEMSET( ctx->Texture.Proxy3D->Image[level], 0,
2730 sizeof(struct gl_texture_image) );
2731 }
2732 }
2733 else {
2734 /* if no error, update proxy texture image parameters */
2735 init_texture_image(ctx->Texture.Proxy3D->Image[level],
2736 width, 1, 1, border, internalFormat);
2737 }
2738 }
2739 else {
2740 gl_error( ctx, GL_INVALID_ENUM, "glCompressedTexImage3DARB(target)" );
2741 return;
2742 }
2743 }
2744
2745
2746 void
2747 _mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
2748 GLsizei width, GLenum format,
2749 GLsizei imageSize, const GLvoid *data)
2750 {
2751 }
2752
2753
2754 void
2755 _mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
2756 GLint yoffset, GLsizei width, GLsizei height,
2757 GLenum format, GLsizei imageSize,
2758 const GLvoid *data)
2759 {
2760 }
2761
2762
2763 void
2764 _mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
2765 GLint yoffset, GLint zoffset, GLsizei width,
2766 GLsizei height, GLsizei depth, GLenum format,
2767 GLsizei imageSize, const GLvoid *data)
2768 {
2769 }
2770
2771
2772 void
2773 _mesa_GetCompressedTexImageARB(GLenum target, GLint lod, GLvoid *img)
2774 {
2775 }