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