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