b36f686e6d238f2a79ede1d4cb76aa6dbe1e1cb8
[mesa.git] / src / mesa / main / teximage.c
1 /*
2 * mesa 3-D graphics library
3 * Version: 7.6
4 *
5 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
6 * Copyright (C) 2009 VMware, Inc. All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included
16 * in all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26
27 /**
28 * \file teximage.c
29 * Texture image-related functions.
30 */
31
32
33 #include "glheader.h"
34 #include "bufferobj.h"
35 #include "context.h"
36 #include "convolve.h"
37 #include "enums.h"
38 #include "fbobject.h"
39 #include "framebuffer.h"
40 #include "hash.h"
41 #include "image.h"
42 #include "imports.h"
43 #include "macros.h"
44 #include "state.h"
45 #include "texcompress.h"
46 #include "texfetch.h"
47 #include "teximage.h"
48 #include "texstate.h"
49 #include "mtypes.h"
50
51
52 /**
53 * State changes which we care about for glCopyTex[Sub]Image() calls.
54 * In particular, we care about pixel transfer state and buffer state
55 * (such as glReadBuffer to make sure we read from the right renderbuffer).
56 */
57 #define NEW_COPY_TEX_STATE (_MESA_NEW_TRANSFER_STATE | \
58 _NEW_BUFFERS | \
59 _NEW_PIXEL)
60
61
62
63 /**
64 * We allocate texture memory on 512-byte boundaries so we can use MMX/SSE
65 * elsewhere.
66 */
67 void *
68 _mesa_alloc_texmemory(GLsizei bytes)
69 {
70 return _mesa_align_malloc(bytes, 512);
71 }
72
73
74 /**
75 * Free texture memory allocated with _mesa_alloc_texmemory()
76 */
77 void
78 _mesa_free_texmemory(void *m)
79 {
80 _mesa_align_free(m);
81 }
82
83
84 /*
85 * Compute floor(log_base_2(n)).
86 * If n < 0 return -1.
87 */
88 static int
89 logbase2( int n )
90 {
91 GLint i = 1;
92 GLint log2 = 0;
93
94 if (n < 0)
95 return -1;
96
97 if (n == 0)
98 return 0;
99
100 while ( n > i ) {
101 i *= 2;
102 log2++;
103 }
104 if (i != n) {
105 return log2 - 1;
106 }
107 else {
108 return log2;
109 }
110 }
111
112
113
114 /**
115 * Return the simple base format for a given internal texture format.
116 * For example, given GL_LUMINANCE12_ALPHA4, return GL_LUMINANCE_ALPHA.
117 *
118 * \param ctx GL context.
119 * \param internalFormat the internal texture format token or 1, 2, 3, or 4.
120 *
121 * \return the corresponding \u base internal format (GL_ALPHA, GL_LUMINANCE,
122 * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA), or -1 if invalid enum.
123 *
124 * This is the format which is used during texture application (i.e. the
125 * texture format and env mode determine the arithmetic used.
126 *
127 * XXX this could be static
128 */
129 GLint
130 _mesa_base_tex_format( GLcontext *ctx, GLint internalFormat )
131 {
132 switch (internalFormat) {
133 case GL_ALPHA:
134 case GL_ALPHA4:
135 case GL_ALPHA8:
136 case GL_ALPHA12:
137 case GL_ALPHA16:
138 return GL_ALPHA;
139 case 1:
140 case GL_LUMINANCE:
141 case GL_LUMINANCE4:
142 case GL_LUMINANCE8:
143 case GL_LUMINANCE12:
144 case GL_LUMINANCE16:
145 return GL_LUMINANCE;
146 case 2:
147 case GL_LUMINANCE_ALPHA:
148 case GL_LUMINANCE4_ALPHA4:
149 case GL_LUMINANCE6_ALPHA2:
150 case GL_LUMINANCE8_ALPHA8:
151 case GL_LUMINANCE12_ALPHA4:
152 case GL_LUMINANCE12_ALPHA12:
153 case GL_LUMINANCE16_ALPHA16:
154 return GL_LUMINANCE_ALPHA;
155 case GL_INTENSITY:
156 case GL_INTENSITY4:
157 case GL_INTENSITY8:
158 case GL_INTENSITY12:
159 case GL_INTENSITY16:
160 return GL_INTENSITY;
161 case 3:
162 case GL_RGB:
163 case GL_R3_G3_B2:
164 case GL_RGB4:
165 case GL_RGB5:
166 case GL_RGB8:
167 case GL_RGB10:
168 case GL_RGB12:
169 case GL_RGB16:
170 return GL_RGB;
171 case 4:
172 case GL_RGBA:
173 case GL_RGBA2:
174 case GL_RGBA4:
175 case GL_RGB5_A1:
176 case GL_RGBA8:
177 case GL_RGB10_A2:
178 case GL_RGBA12:
179 case GL_RGBA16:
180 return GL_RGBA;
181 default:
182 ; /* fallthrough */
183 }
184
185 if (ctx->Extensions.EXT_paletted_texture) {
186 switch (internalFormat) {
187 case GL_COLOR_INDEX:
188 case GL_COLOR_INDEX1_EXT:
189 case GL_COLOR_INDEX2_EXT:
190 case GL_COLOR_INDEX4_EXT:
191 case GL_COLOR_INDEX8_EXT:
192 case GL_COLOR_INDEX12_EXT:
193 case GL_COLOR_INDEX16_EXT:
194 return GL_COLOR_INDEX;
195 default:
196 ; /* fallthrough */
197 }
198 }
199
200 if (ctx->Extensions.ARB_depth_texture) {
201 switch (internalFormat) {
202 case GL_DEPTH_COMPONENT:
203 case GL_DEPTH_COMPONENT16:
204 case GL_DEPTH_COMPONENT24:
205 case GL_DEPTH_COMPONENT32:
206 return GL_DEPTH_COMPONENT;
207 default:
208 ; /* fallthrough */
209 }
210 }
211
212 switch (internalFormat) {
213 case GL_COMPRESSED_ALPHA:
214 return GL_ALPHA;
215 case GL_COMPRESSED_LUMINANCE:
216 return GL_LUMINANCE;
217 case GL_COMPRESSED_LUMINANCE_ALPHA:
218 return GL_LUMINANCE_ALPHA;
219 case GL_COMPRESSED_INTENSITY:
220 return GL_INTENSITY;
221 case GL_COMPRESSED_RGB:
222 return GL_RGB;
223 case GL_COMPRESSED_RGBA:
224 return GL_RGBA;
225 default:
226 ; /* fallthrough */
227 }
228
229 if (ctx->Extensions.TDFX_texture_compression_FXT1) {
230 switch (internalFormat) {
231 case GL_COMPRESSED_RGB_FXT1_3DFX:
232 return GL_RGB;
233 case GL_COMPRESSED_RGBA_FXT1_3DFX:
234 return GL_RGBA;
235 default:
236 ; /* fallthrough */
237 }
238 }
239
240 if (ctx->Extensions.EXT_texture_compression_s3tc) {
241 switch (internalFormat) {
242 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
243 return GL_RGB;
244 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
245 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
246 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
247 return GL_RGBA;
248 default:
249 ; /* fallthrough */
250 }
251 }
252
253 if (ctx->Extensions.S3_s3tc) {
254 switch (internalFormat) {
255 case GL_RGB_S3TC:
256 case GL_RGB4_S3TC:
257 return GL_RGB;
258 case GL_RGBA_S3TC:
259 case GL_RGBA4_S3TC:
260 return GL_RGBA;
261 default:
262 ; /* fallthrough */
263 }
264 }
265
266 if (ctx->Extensions.MESA_ycbcr_texture) {
267 if (internalFormat == GL_YCBCR_MESA)
268 return GL_YCBCR_MESA;
269 }
270
271 if (ctx->Extensions.ARB_texture_float) {
272 switch (internalFormat) {
273 case GL_ALPHA16F_ARB:
274 case GL_ALPHA32F_ARB:
275 return GL_ALPHA;
276 case GL_RGBA16F_ARB:
277 case GL_RGBA32F_ARB:
278 return GL_RGBA;
279 case GL_RGB16F_ARB:
280 case GL_RGB32F_ARB:
281 return GL_RGB;
282 case GL_INTENSITY16F_ARB:
283 case GL_INTENSITY32F_ARB:
284 return GL_INTENSITY;
285 case GL_LUMINANCE16F_ARB:
286 case GL_LUMINANCE32F_ARB:
287 return GL_LUMINANCE;
288 case GL_LUMINANCE_ALPHA16F_ARB:
289 case GL_LUMINANCE_ALPHA32F_ARB:
290 return GL_LUMINANCE_ALPHA;
291 default:
292 ; /* fallthrough */
293 }
294 }
295
296 if (ctx->Extensions.ATI_envmap_bumpmap) {
297 switch (internalFormat) {
298 case GL_DUDV_ATI:
299 case GL_DU8DV8_ATI:
300 return GL_DUDV_ATI;
301 default:
302 ; /* fallthrough */
303 }
304 }
305
306 if (ctx->Extensions.MESA_texture_signed_rgba) {
307 switch (internalFormat) {
308 case GL_RGBA_SNORM:
309 case GL_RGBA8_SNORM:
310 return GL_RGBA;
311 default:
312 ; /* fallthrough */
313 }
314 }
315
316 if (ctx->Extensions.EXT_packed_depth_stencil) {
317 switch (internalFormat) {
318 case GL_DEPTH_STENCIL_EXT:
319 case GL_DEPTH24_STENCIL8_EXT:
320 return GL_DEPTH_STENCIL_EXT;
321 default:
322 ; /* fallthrough */
323 }
324 }
325
326 #if FEATURE_EXT_texture_sRGB
327 if (ctx->Extensions.EXT_texture_sRGB) {
328 switch (internalFormat) {
329 case GL_SRGB_EXT:
330 case GL_SRGB8_EXT:
331 case GL_COMPRESSED_SRGB_EXT:
332 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
333 return GL_RGB;
334 case GL_SRGB_ALPHA_EXT:
335 case GL_SRGB8_ALPHA8_EXT:
336 case GL_COMPRESSED_SRGB_ALPHA_EXT:
337 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
338 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
339 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
340 return GL_RGBA;
341 case GL_SLUMINANCE_ALPHA_EXT:
342 case GL_SLUMINANCE8_ALPHA8_EXT:
343 case GL_COMPRESSED_SLUMINANCE_EXT:
344 case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT:
345 return GL_LUMINANCE_ALPHA;
346 case GL_SLUMINANCE_EXT:
347 case GL_SLUMINANCE8_EXT:
348 return GL_LUMINANCE;
349 default:
350 ; /* fallthrough */
351 }
352 }
353
354 #endif /* FEATURE_EXT_texture_sRGB */
355
356 return -1; /* error */
357 }
358
359
360 /**
361 * For cube map faces, return a face index in [0,5].
362 * For other targets return 0;
363 */
364 GLuint
365 _mesa_tex_target_to_face(GLenum target)
366 {
367 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
368 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)
369 return (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X;
370 else
371 return 0;
372 }
373
374
375
376 /**
377 * Store a gl_texture_image pointer in a gl_texture_object structure
378 * according to the target and level parameters.
379 *
380 * \param tObj texture object.
381 * \param target texture target.
382 * \param level image level.
383 * \param texImage texture image.
384 *
385 * This was basically prompted by the introduction of cube maps.
386 */
387 void
388 _mesa_set_tex_image(struct gl_texture_object *tObj,
389 GLenum target, GLint level,
390 struct gl_texture_image *texImage)
391 {
392 const GLuint face = _mesa_tex_target_to_face(target);
393
394 ASSERT(tObj);
395 ASSERT(texImage);
396 ASSERT(target != GL_TEXTURE_RECTANGLE_NV || level == 0);
397
398 tObj->Image[face][level] = texImage;
399
400 /* Set the 'back' pointer */
401 texImage->TexObject = tObj;
402 }
403
404
405 /**
406 * Allocate a texture image structure.
407 *
408 * Called via ctx->Driver.NewTextureImage() unless overriden by a device
409 * driver.
410 *
411 * \return a pointer to gl_texture_image struct with all fields initialized to
412 * zero.
413 */
414 struct gl_texture_image *
415 _mesa_new_texture_image( GLcontext *ctx )
416 {
417 (void) ctx;
418 return CALLOC_STRUCT(gl_texture_image);
419 }
420
421
422 /**
423 * Free texture image data.
424 * This function is a fallback called via ctx->Driver.FreeTexImageData().
425 *
426 * \param texImage texture image.
427 *
428 * Free the texture image data if it's not marked as client data.
429 */
430 void
431 _mesa_free_texture_image_data(GLcontext *ctx,
432 struct gl_texture_image *texImage)
433 {
434 (void) ctx;
435
436 if (texImage->Data && !texImage->IsClientData) {
437 /* free the old texture data */
438 _mesa_free_texmemory(texImage->Data);
439 }
440
441 texImage->Data = NULL;
442 }
443
444
445 /**
446 * Free texture image.
447 *
448 * \param texImage texture image.
449 *
450 * Free the texture image structure and the associated image data.
451 */
452 void
453 _mesa_delete_texture_image( GLcontext *ctx, struct gl_texture_image *texImage )
454 {
455 /* Free texImage->Data and/or any other driver-specific texture
456 * image storage.
457 */
458 ASSERT(ctx->Driver.FreeTexImageData);
459 ctx->Driver.FreeTexImageData( ctx, texImage );
460
461 ASSERT(texImage->Data == NULL);
462 if (texImage->ImageOffsets)
463 free(texImage->ImageOffsets);
464 free(texImage);
465 }
466
467
468 /**
469 * Test if a target is a proxy target.
470 *
471 * \param target texture target.
472 *
473 * \return GL_TRUE if the target is a proxy target, GL_FALSE otherwise.
474 */
475 GLboolean
476 _mesa_is_proxy_texture(GLenum target)
477 {
478 /* NUM_TEXTURE_TARGETS should match number of terms below */
479 assert(NUM_TEXTURE_TARGETS == 7);
480
481 return (target == GL_PROXY_TEXTURE_1D ||
482 target == GL_PROXY_TEXTURE_2D ||
483 target == GL_PROXY_TEXTURE_3D ||
484 target == GL_PROXY_TEXTURE_CUBE_MAP_ARB ||
485 target == GL_PROXY_TEXTURE_RECTANGLE_NV ||
486 target == GL_PROXY_TEXTURE_1D_ARRAY_EXT ||
487 target == GL_PROXY_TEXTURE_2D_ARRAY_EXT);
488 }
489
490
491 /**
492 * Get the texture object that corresponds to the target of the given texture unit.
493 *
494 * \param ctx GL context.
495 * \param texUnit texture unit.
496 * \param target texture target.
497 *
498 * \return pointer to the texture object on success, or NULL on failure.
499 *
500 * \sa gl_texture_unit.
501 */
502 struct gl_texture_object *
503 _mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit,
504 GLenum target)
505 {
506 switch (target) {
507 case GL_TEXTURE_1D:
508 return texUnit->CurrentTex[TEXTURE_1D_INDEX];
509 case GL_PROXY_TEXTURE_1D:
510 return ctx->Texture.ProxyTex[TEXTURE_1D_INDEX];
511 case GL_TEXTURE_2D:
512 return texUnit->CurrentTex[TEXTURE_2D_INDEX];
513 case GL_PROXY_TEXTURE_2D:
514 return ctx->Texture.ProxyTex[TEXTURE_2D_INDEX];
515 case GL_TEXTURE_3D:
516 return texUnit->CurrentTex[TEXTURE_3D_INDEX];
517 case GL_PROXY_TEXTURE_3D:
518 return ctx->Texture.ProxyTex[TEXTURE_3D_INDEX];
519 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
520 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
521 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
522 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
523 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
524 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
525 case GL_TEXTURE_CUBE_MAP_ARB:
526 return ctx->Extensions.ARB_texture_cube_map
527 ? texUnit->CurrentTex[TEXTURE_CUBE_INDEX] : NULL;
528 case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
529 return ctx->Extensions.ARB_texture_cube_map
530 ? ctx->Texture.ProxyTex[TEXTURE_CUBE_INDEX] : NULL;
531 case GL_TEXTURE_RECTANGLE_NV:
532 return ctx->Extensions.NV_texture_rectangle
533 ? texUnit->CurrentTex[TEXTURE_RECT_INDEX] : NULL;
534 case GL_PROXY_TEXTURE_RECTANGLE_NV:
535 return ctx->Extensions.NV_texture_rectangle
536 ? ctx->Texture.ProxyTex[TEXTURE_RECT_INDEX] : NULL;
537 case GL_TEXTURE_1D_ARRAY_EXT:
538 return ctx->Extensions.MESA_texture_array
539 ? texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX] : NULL;
540 case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
541 return ctx->Extensions.MESA_texture_array
542 ? ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX] : NULL;
543 case GL_TEXTURE_2D_ARRAY_EXT:
544 return ctx->Extensions.MESA_texture_array
545 ? texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX] : NULL;
546 case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
547 return ctx->Extensions.MESA_texture_array
548 ? ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX] : NULL;
549 default:
550 _mesa_problem(NULL, "bad target in _mesa_select_tex_object()");
551 return NULL;
552 }
553 }
554
555
556 /**
557 * Return pointer to texture object for given target on current texture unit.
558 */
559 struct gl_texture_object *
560 _mesa_get_current_tex_object(GLcontext *ctx, GLenum target)
561 {
562 struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
563 return _mesa_select_tex_object(ctx, texUnit, target);
564 }
565
566
567 /**
568 * Get a texture image pointer from a texture object, given a texture
569 * target and mipmap level. The target and level parameters should
570 * have already been error-checked.
571 *
572 * \param ctx GL context.
573 * \param texObj texture unit.
574 * \param target texture target.
575 * \param level image level.
576 *
577 * \return pointer to the texture image structure, or NULL on failure.
578 */
579 struct gl_texture_image *
580 _mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_object *texObj,
581 GLenum target, GLint level)
582 {
583 const GLuint face = _mesa_tex_target_to_face(target);
584
585 ASSERT(texObj);
586 ASSERT(level >= 0);
587 ASSERT(level < MAX_TEXTURE_LEVELS);
588
589 return texObj->Image[face][level];
590 }
591
592
593 /**
594 * Like _mesa_select_tex_image() but if the image doesn't exist, allocate
595 * it and install it. Only return NULL if passed a bad parameter or run
596 * out of memory.
597 */
598 struct gl_texture_image *
599 _mesa_get_tex_image(GLcontext *ctx, struct gl_texture_object *texObj,
600 GLenum target, GLint level)
601 {
602 struct gl_texture_image *texImage;
603
604 if (!texObj)
605 return NULL;
606
607 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
608 if (!texImage) {
609 texImage = ctx->Driver.NewTextureImage(ctx);
610 if (!texImage) {
611 _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture image allocation");
612 return NULL;
613 }
614
615 _mesa_set_tex_image(texObj, target, level, texImage);
616 }
617
618 return texImage;
619 }
620
621
622 /**
623 * Return pointer to the specified proxy texture image.
624 * Note that proxy textures are per-context, not per-texture unit.
625 * \return pointer to texture image or NULL if invalid target, invalid
626 * level, or out of memory.
627 */
628 struct gl_texture_image *
629 _mesa_get_proxy_tex_image(GLcontext *ctx, GLenum target, GLint level)
630 {
631 struct gl_texture_image *texImage;
632 GLuint texIndex;
633
634 if (level < 0 )
635 return NULL;
636
637 switch (target) {
638 case GL_PROXY_TEXTURE_1D:
639 if (level >= ctx->Const.MaxTextureLevels)
640 return NULL;
641 texIndex = TEXTURE_1D_INDEX;
642 break;
643 case GL_PROXY_TEXTURE_2D:
644 if (level >= ctx->Const.MaxTextureLevels)
645 return NULL;
646 texIndex = TEXTURE_2D_INDEX;
647 break;
648 case GL_PROXY_TEXTURE_3D:
649 if (level >= ctx->Const.Max3DTextureLevels)
650 return NULL;
651 texIndex = TEXTURE_3D_INDEX;
652 break;
653 case GL_PROXY_TEXTURE_CUBE_MAP:
654 if (level >= ctx->Const.MaxCubeTextureLevels)
655 return NULL;
656 texIndex = TEXTURE_CUBE_INDEX;
657 break;
658 case GL_PROXY_TEXTURE_RECTANGLE_NV:
659 if (level > 0)
660 return NULL;
661 texIndex = TEXTURE_RECT_INDEX;
662 break;
663 case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
664 if (level >= ctx->Const.MaxTextureLevels)
665 return NULL;
666 texIndex = TEXTURE_1D_ARRAY_INDEX;
667 break;
668 case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
669 if (level >= ctx->Const.MaxTextureLevels)
670 return NULL;
671 texIndex = TEXTURE_2D_ARRAY_INDEX;
672 break;
673 default:
674 return NULL;
675 }
676
677 texImage = ctx->Texture.ProxyTex[texIndex]->Image[0][level];
678 if (!texImage) {
679 texImage = ctx->Driver.NewTextureImage(ctx);
680 if (!texImage) {
681 _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
682 return NULL;
683 }
684 ctx->Texture.ProxyTex[texIndex]->Image[0][level] = texImage;
685 /* Set the 'back' pointer */
686 texImage->TexObject = ctx->Texture.ProxyTex[texIndex];
687 }
688 return texImage;
689 }
690
691
692 /**
693 * Get the maximum number of allowed mipmap levels.
694 *
695 * \param ctx GL context.
696 * \param target texture target.
697 *
698 * \return the maximum number of allowed mipmap levels for the given
699 * texture target, or zero if passed a bad target.
700 *
701 * \sa gl_constants.
702 */
703 GLint
704 _mesa_max_texture_levels(GLcontext *ctx, GLenum target)
705 {
706 switch (target) {
707 case GL_TEXTURE_1D:
708 case GL_PROXY_TEXTURE_1D:
709 case GL_TEXTURE_2D:
710 case GL_PROXY_TEXTURE_2D:
711 return ctx->Const.MaxTextureLevels;
712 case GL_TEXTURE_3D:
713 case GL_PROXY_TEXTURE_3D:
714 return ctx->Const.Max3DTextureLevels;
715 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
716 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
717 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
718 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
719 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
720 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
721 case GL_TEXTURE_CUBE_MAP_ARB:
722 case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
723 return ctx->Extensions.ARB_texture_cube_map
724 ? ctx->Const.MaxCubeTextureLevels : 0;
725 case GL_TEXTURE_RECTANGLE_NV:
726 case GL_PROXY_TEXTURE_RECTANGLE_NV:
727 return ctx->Extensions.NV_texture_rectangle ? 1 : 0;
728 case GL_TEXTURE_1D_ARRAY_EXT:
729 case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
730 case GL_TEXTURE_2D_ARRAY_EXT:
731 case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
732 return ctx->Extensions.MESA_texture_array
733 ? ctx->Const.MaxTextureLevels : 0;
734 default:
735 return 0; /* bad target */
736 }
737 }
738
739
740
741 #if 000 /* not used anymore */
742 /*
743 * glTexImage[123]D can accept a NULL image pointer. In this case we
744 * create a texture image with unspecified image contents per the OpenGL
745 * spec.
746 */
747 static GLubyte *
748 make_null_texture(GLint width, GLint height, GLint depth, GLenum format)
749 {
750 const GLint components = _mesa_components_in_format(format);
751 const GLint numPixels = width * height * depth;
752 GLubyte *data = (GLubyte *) MALLOC(numPixels * components * sizeof(GLubyte));
753
754 #ifdef DEBUG
755 /*
756 * Let's see if anyone finds this. If glTexImage2D() is called with
757 * a NULL image pointer then load the texture image with something
758 * interesting instead of leaving it indeterminate.
759 */
760 if (data) {
761 static const char message[8][32] = {
762 " X X XXXXX XXX X ",
763 " XX XX X X X X X ",
764 " X X X X X X X ",
765 " X X XXXX XXX XXXXX ",
766 " X X X X X X ",
767 " X X X X X X X ",
768 " X X XXXXX XXX X X ",
769 " "
770 };
771
772 GLubyte *imgPtr = data;
773 GLint h, i, j, k;
774 for (h = 0; h < depth; h++) {
775 for (i = 0; i < height; i++) {
776 GLint srcRow = 7 - (i % 8);
777 for (j = 0; j < width; j++) {
778 GLint srcCol = j % 32;
779 GLubyte texel = (message[srcRow][srcCol]=='X') ? 255 : 70;
780 for (k = 0; k < components; k++) {
781 *imgPtr++ = texel;
782 }
783 }
784 }
785 }
786 }
787 #endif
788
789 return data;
790 }
791 #endif
792
793
794
795 /**
796 * Reset the fields of a gl_texture_image struct to zero.
797 *
798 * \param img texture image structure.
799 *
800 * This is called when a proxy texture test fails, we set all the
801 * image members (except DriverData) to zero.
802 * It's also used in glTexImage[123]D as a safeguard to be sure all
803 * required fields get initialized properly by the Driver.TexImage[123]D
804 * functions.
805 */
806 static void
807 clear_teximage_fields(struct gl_texture_image *img)
808 {
809 ASSERT(img);
810 img->_BaseFormat = 0;
811 img->InternalFormat = 0;
812 img->Border = 0;
813 img->Width = 0;
814 img->Height = 0;
815 img->Depth = 0;
816 img->RowStride = 0;
817 if (img->ImageOffsets) {
818 free(img->ImageOffsets);
819 img->ImageOffsets = NULL;
820 }
821 img->Width2 = 0;
822 img->Height2 = 0;
823 img->Depth2 = 0;
824 img->WidthLog2 = 0;
825 img->HeightLog2 = 0;
826 img->DepthLog2 = 0;
827 img->Data = NULL;
828 img->TexFormat = MESA_FORMAT_NONE;
829 img->FetchTexelc = NULL;
830 img->FetchTexelf = NULL;
831 }
832
833
834 /**
835 * Initialize basic fields of the gl_texture_image struct.
836 *
837 * \param ctx GL context.
838 * \param target texture target (GL_TEXTURE_1D, GL_TEXTURE_RECTANGLE, etc).
839 * \param img texture image structure to be initialized.
840 * \param width image width.
841 * \param height image height.
842 * \param depth image depth.
843 * \param border image border.
844 * \param internalFormat internal format.
845 *
846 * Fills in the fields of \p img with the given information.
847 * Note: width, height and depth include the border.
848 */
849 void
850 _mesa_init_teximage_fields(GLcontext *ctx, GLenum target,
851 struct gl_texture_image *img,
852 GLsizei width, GLsizei height, GLsizei depth,
853 GLint border, GLenum internalFormat)
854 {
855 GLint i;
856
857 ASSERT(img);
858 ASSERT(width >= 0);
859 ASSERT(height >= 0);
860 ASSERT(depth >= 0);
861
862 img->_BaseFormat = _mesa_base_tex_format( ctx, internalFormat );
863 ASSERT(img->_BaseFormat > 0);
864 img->InternalFormat = internalFormat;
865 img->Border = border;
866 img->Width = width;
867 img->Height = height;
868 img->Depth = depth;
869
870 img->Width2 = width - 2 * border; /* == 1 << img->WidthLog2; */
871 img->WidthLog2 = logbase2(img->Width2);
872
873 if (height == 1) { /* 1-D texture */
874 img->Height2 = 1;
875 img->HeightLog2 = 0;
876 }
877 else {
878 img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */
879 img->HeightLog2 = logbase2(img->Height2);
880 }
881
882 if (depth == 1) { /* 2-D texture */
883 img->Depth2 = 1;
884 img->DepthLog2 = 0;
885 }
886 else {
887 img->Depth2 = depth - 2 * border; /* == 1 << img->DepthLog2; */
888 img->DepthLog2 = logbase2(img->Depth2);
889 }
890
891 img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2);
892
893 if ((width == 1 || _mesa_is_pow_two(img->Width2)) &&
894 (height == 1 || _mesa_is_pow_two(img->Height2)) &&
895 (depth == 1 || _mesa_is_pow_two(img->Depth2)))
896 img->_IsPowerOfTwo = GL_TRUE;
897 else
898 img->_IsPowerOfTwo = GL_FALSE;
899
900 /* RowStride and ImageOffsets[] describe how to address texels in 'Data' */
901 img->RowStride = width;
902 /* Allocate the ImageOffsets array and initialize to typical values.
903 * We allocate the array for 1D/2D textures too in order to avoid special-
904 * case code in the texstore routines.
905 */
906 if (img->ImageOffsets)
907 free(img->ImageOffsets);
908 img->ImageOffsets = (GLuint *) malloc(depth * sizeof(GLuint));
909 for (i = 0; i < depth; i++) {
910 img->ImageOffsets[i] = i * width * height;
911 }
912
913 /* Compute Width/Height/DepthScale for mipmap lod computation */
914 if (target == GL_TEXTURE_RECTANGLE_NV) {
915 /* scale = 1.0 since texture coords directly map to texels */
916 img->WidthScale = 1.0;
917 img->HeightScale = 1.0;
918 img->DepthScale = 1.0;
919 }
920 else {
921 img->WidthScale = (GLfloat) img->Width;
922 img->HeightScale = (GLfloat) img->Height;
923 img->DepthScale = (GLfloat) img->Depth;
924 }
925
926 img->FetchTexelc = NULL;
927 img->FetchTexelf = NULL;
928 }
929
930
931 /**
932 * Free and clear fields of the gl_texture_image struct.
933 *
934 * \param ctx GL context.
935 * \param texImage texture image structure to be cleared.
936 *
937 * After the call, \p texImage will have no data associated with it. Its
938 * fields are cleared so that its parent object will test incomplete.
939 */
940 void
941 _mesa_clear_texture_image(GLcontext *ctx, struct gl_texture_image *texImage)
942 {
943 ctx->Driver.FreeTexImageData(ctx, texImage);
944 clear_teximage_fields(texImage);
945 }
946
947
948 /**
949 * This is the fallback for Driver.TestProxyTexImage(). Test the texture
950 * level, width, height and depth against the ctx->Const limits for textures.
951 *
952 * A hardware driver might override this function if, for example, the
953 * max 3D texture size is 512x512x64 (i.e. not a cube).
954 *
955 * Note that width, height, depth == 0 is not an error. However, a
956 * texture with zero width/height/depth will be considered "incomplete"
957 * and texturing will effectively be disabled.
958 *
959 * \param target one of GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D,
960 * GL_PROXY_TEXTURE_3D, GL_PROXY_TEXTURE_RECTANGLE_NV,
961 * GL_PROXY_TEXTURE_CUBE_MAP_ARB.
962 * \param level as passed to glTexImage
963 * \param internalFormat as passed to glTexImage
964 * \param format as passed to glTexImage
965 * \param type as passed to glTexImage
966 * \param width as passed to glTexImage
967 * \param height as passed to glTexImage
968 * \param depth as passed to glTexImage
969 * \param border as passed to glTexImage
970 * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable.
971 */
972 GLboolean
973 _mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level,
974 GLint internalFormat, GLenum format, GLenum type,
975 GLint width, GLint height, GLint depth, GLint border)
976 {
977 GLint maxSize;
978
979 (void) internalFormat;
980 (void) format;
981 (void) type;
982
983 switch (target) {
984 case GL_PROXY_TEXTURE_1D:
985 maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
986 if (width < 2 * border || width > 2 + maxSize ||
987 (!ctx->Extensions.ARB_texture_non_power_of_two &&
988 width >0 && !_mesa_is_pow_two(width - 2 * border)) ||
989 level >= ctx->Const.MaxTextureLevels) {
990 /* bad width or level */
991 return GL_FALSE;
992 }
993 return GL_TRUE;
994 case GL_PROXY_TEXTURE_2D:
995 maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
996 if (width < 2 * border || width > 2 + maxSize ||
997 (!ctx->Extensions.ARB_texture_non_power_of_two &&
998 width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
999 height < 2 * border || height > 2 + maxSize ||
1000 (!ctx->Extensions.ARB_texture_non_power_of_two &&
1001 height > 0 && !_mesa_is_pow_two(height - 2 * border)) ||
1002 level >= ctx->Const.MaxTextureLevels) {
1003 /* bad width or height or level */
1004 return GL_FALSE;
1005 }
1006 return GL_TRUE;
1007 case GL_PROXY_TEXTURE_3D:
1008 maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
1009 if (width < 2 * border || width > 2 + maxSize ||
1010 (!ctx->Extensions.ARB_texture_non_power_of_two &&
1011 width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
1012 height < 2 * border || height > 2 + maxSize ||
1013 (!ctx->Extensions.ARB_texture_non_power_of_two &&
1014 height > 0 && !_mesa_is_pow_two(height - 2 * border)) ||
1015 depth < 2 * border || depth > 2 + maxSize ||
1016 (!ctx->Extensions.ARB_texture_non_power_of_two &&
1017 depth > 0 && !_mesa_is_pow_two(depth - 2 * border)) ||
1018 level >= ctx->Const.Max3DTextureLevels) {
1019 /* bad width or height or depth or level */
1020 return GL_FALSE;
1021 }
1022 return GL_TRUE;
1023 case GL_PROXY_TEXTURE_RECTANGLE_NV:
1024 if (width < 0 || width > ctx->Const.MaxTextureRectSize ||
1025 height < 0 || height > ctx->Const.MaxTextureRectSize ||
1026 level != 0) {
1027 /* bad width or height or level */
1028 return GL_FALSE;
1029 }
1030 return GL_TRUE;
1031 case GL_PROXY_TEXTURE_CUBE_MAP_ARB:
1032 maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1);
1033 if (width < 2 * border || width > 2 + maxSize ||
1034 (!ctx->Extensions.ARB_texture_non_power_of_two &&
1035 width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
1036 height < 2 * border || height > 2 + maxSize ||
1037 (!ctx->Extensions.ARB_texture_non_power_of_two &&
1038 height > 0 && !_mesa_is_pow_two(height - 2 * border)) ||
1039 level >= ctx->Const.MaxCubeTextureLevels) {
1040 /* bad width or height */
1041 return GL_FALSE;
1042 }
1043 return GL_TRUE;
1044 case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
1045 maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
1046 if (width < 2 * border || width > 2 + maxSize ||
1047 (!ctx->Extensions.ARB_texture_non_power_of_two &&
1048 width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
1049 level >= ctx->Const.MaxTextureLevels) {
1050 /* bad width or level */
1051 return GL_FALSE;
1052 }
1053
1054 if (height < 1 || height > ctx->Const.MaxArrayTextureLayers) {
1055 return GL_FALSE;
1056 }
1057 return GL_TRUE;
1058 case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
1059 maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
1060 if (width < 2 * border || width > 2 + maxSize ||
1061 (!ctx->Extensions.ARB_texture_non_power_of_two &&
1062 width > 0 && !_mesa_is_pow_two(width - 2 * border)) ||
1063 height < 2 * border || height > 2 + maxSize ||
1064 (!ctx->Extensions.ARB_texture_non_power_of_two &&
1065 height > 0 && !_mesa_is_pow_two(height - 2 * border)) ||
1066 level >= ctx->Const.MaxTextureLevels) {
1067 /* bad width or height or level */
1068 return GL_FALSE;
1069 }
1070 if (depth < 1 || depth > ctx->Const.MaxArrayTextureLayers) {
1071 return GL_FALSE;
1072 }
1073 return GL_TRUE;
1074 default:
1075 _mesa_problem(ctx, "Invalid target in _mesa_test_proxy_teximage");
1076 return GL_FALSE;
1077 }
1078 }
1079
1080
1081 /**
1082 * Helper function to determine whether a target supports compressed textures
1083 */
1084 static GLboolean
1085 target_can_be_compressed(GLcontext *ctx, GLenum target)
1086 {
1087 return (((target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D))
1088 || ((ctx->Extensions.ARB_texture_cube_map &&
1089 (target == GL_PROXY_TEXTURE_CUBE_MAP ||
1090 (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X &&
1091 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z))))
1092 || ((ctx->Extensions.MESA_texture_array &&
1093 ((target == GL_PROXY_TEXTURE_2D_ARRAY_EXT) ||
1094 (target == GL_TEXTURE_2D_ARRAY_EXT)))));
1095 }
1096
1097
1098 /**
1099 * Test the glTexImage[123]D() parameters for errors.
1100 *
1101 * \param ctx GL context.
1102 * \param target texture target given by the user.
1103 * \param level image level given by the user.
1104 * \param internalFormat internal format given by the user.
1105 * \param format pixel data format given by the user.
1106 * \param type pixel data type given by the user.
1107 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1108 * \param width image width given by the user.
1109 * \param height image height given by the user.
1110 * \param depth image depth given by the user.
1111 * \param border image border given by the user.
1112 *
1113 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1114 *
1115 * Verifies each of the parameters against the constants specified in
1116 * __GLcontextRec::Const and the supported extensions, and according to the
1117 * OpenGL specification.
1118 */
1119 static GLboolean
1120 texture_error_check( GLcontext *ctx, GLenum target,
1121 GLint level, GLint internalFormat,
1122 GLenum format, GLenum type,
1123 GLuint dimensions,
1124 GLint width, GLint height,
1125 GLint depth, GLint border )
1126 {
1127 const GLboolean isProxy = _mesa_is_proxy_texture(target);
1128 GLboolean sizeOK = GL_TRUE;
1129 GLboolean colorFormat, indexFormat;
1130 GLenum proxy_target;
1131
1132 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
1133 if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
1134 if (!isProxy) {
1135 _mesa_error(ctx, GL_INVALID_VALUE,
1136 "glTexImage%dD(level=%d)", dimensions, level);
1137 }
1138 return GL_TRUE;
1139 }
1140
1141 /* Check border */
1142 if (border < 0 || border > 1 ||
1143 ((target == GL_TEXTURE_RECTANGLE_NV ||
1144 target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) {
1145 if (!isProxy) {
1146 _mesa_error(ctx, GL_INVALID_VALUE,
1147 "glTexImage%dD(border=%d)", dimensions, border);
1148 }
1149 return GL_TRUE;
1150 }
1151
1152 if (width < 0 || height < 0 || depth < 0) {
1153 if (!isProxy) {
1154 _mesa_error(ctx, GL_INVALID_VALUE,
1155 "glTexImage%dD(width, height or depth < 0)", dimensions);
1156 }
1157 return GL_TRUE;
1158 }
1159
1160 /* Check target and call ctx->Driver.TestProxyTexImage() to check the
1161 * level, width, height and depth.
1162 */
1163 if (dimensions == 1) {
1164 if (target == GL_PROXY_TEXTURE_1D || target == GL_TEXTURE_1D) {
1165 proxy_target = GL_PROXY_TEXTURE_1D;
1166 height = 1;
1167 depth = 1;
1168 }
1169 else {
1170 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
1171 return GL_TRUE;
1172 }
1173 }
1174 else if (dimensions == 2) {
1175 depth = 1;
1176 if (target == GL_PROXY_TEXTURE_2D || target == GL_TEXTURE_2D) {
1177 proxy_target = GL_PROXY_TEXTURE_2D;
1178 }
1179 else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB ||
1180 (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1181 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
1182 if (!ctx->Extensions.ARB_texture_cube_map) {
1183 _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
1184 return GL_TRUE;
1185 }
1186 proxy_target = GL_PROXY_TEXTURE_CUBE_MAP_ARB;
1187 sizeOK = (width == height);
1188 }
1189 else if (target == GL_PROXY_TEXTURE_RECTANGLE_NV ||
1190 target == GL_TEXTURE_RECTANGLE_NV) {
1191 if (!ctx->Extensions.NV_texture_rectangle) {
1192 _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
1193 return GL_TRUE;
1194 }
1195 proxy_target = GL_PROXY_TEXTURE_RECTANGLE_NV;
1196 }
1197 else if (target == GL_PROXY_TEXTURE_1D_ARRAY_EXT ||
1198 target == GL_TEXTURE_1D_ARRAY_EXT) {
1199 proxy_target = GL_PROXY_TEXTURE_1D_ARRAY_EXT;
1200 }
1201 else {
1202 _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)");
1203 return GL_TRUE;
1204 }
1205 }
1206 else if (dimensions == 3) {
1207 if (target == GL_PROXY_TEXTURE_3D || target == GL_TEXTURE_3D) {
1208 proxy_target = GL_PROXY_TEXTURE_3D;
1209 }
1210 else if (target == GL_PROXY_TEXTURE_2D_ARRAY_EXT ||
1211 target == GL_TEXTURE_2D_ARRAY_EXT) {
1212 proxy_target = GL_PROXY_TEXTURE_2D_ARRAY_EXT;
1213 }
1214 else {
1215 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
1216 return GL_TRUE;
1217 }
1218 }
1219 else {
1220 _mesa_problem( ctx, "bad dims in texture_error_check" );
1221 return GL_TRUE;
1222 }
1223
1224 sizeOK = sizeOK && ctx->Driver.TestProxyTexImage(ctx, proxy_target, level,
1225 internalFormat, format,
1226 type, width, height,
1227 depth, border);
1228 if (!sizeOK) {
1229 if (!isProxy) {
1230 _mesa_error(ctx, GL_INVALID_VALUE,
1231 "glTexImage%dD(level=%d, width=%d, height=%d, depth=%d)",
1232 dimensions, level, width, height, depth);
1233 }
1234 return GL_TRUE;
1235 }
1236
1237 /* Check internalFormat */
1238 if (_mesa_base_tex_format(ctx, internalFormat) < 0) {
1239 if (!isProxy) {
1240 _mesa_error(ctx, GL_INVALID_VALUE,
1241 "glTexImage%dD(internalFormat=%s)",
1242 dimensions, _mesa_lookup_enum_by_nr(internalFormat));
1243 }
1244 return GL_TRUE;
1245 }
1246
1247 /* Check incoming image format and type */
1248 if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
1249 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there
1250 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4.
1251 */
1252 if (!isProxy) {
1253 _mesa_error(ctx, GL_INVALID_OPERATION,
1254 "glTexImage%dD(incompatible format 0x%x, type 0x%x)",
1255 dimensions, format, type);
1256 }
1257 return GL_TRUE;
1258 }
1259
1260 /* make sure internal format and format basically agree */
1261 colorFormat = _mesa_is_color_format(format);
1262 indexFormat = _mesa_is_index_format(format);
1263 if ((_mesa_is_color_format(internalFormat) && !colorFormat && !indexFormat) ||
1264 (_mesa_is_index_format(internalFormat) && !indexFormat) ||
1265 (_mesa_is_depth_format(internalFormat) != _mesa_is_depth_format(format)) ||
1266 (_mesa_is_ycbcr_format(internalFormat) != _mesa_is_ycbcr_format(format)) ||
1267 (_mesa_is_depthstencil_format(internalFormat) != _mesa_is_depthstencil_format(format)) ||
1268 (_mesa_is_dudv_format(internalFormat) != _mesa_is_dudv_format(format))) {
1269 if (!isProxy)
1270 _mesa_error(ctx, GL_INVALID_OPERATION,
1271 "glTexImage%dD(incompatible internalFormat 0x%x, format 0x%x)",
1272 dimensions, internalFormat, format);
1273 return GL_TRUE;
1274 }
1275
1276 /* additional checks for ycbcr textures */
1277 if (internalFormat == GL_YCBCR_MESA) {
1278 ASSERT(ctx->Extensions.MESA_ycbcr_texture);
1279 if (type != GL_UNSIGNED_SHORT_8_8_MESA &&
1280 type != GL_UNSIGNED_SHORT_8_8_REV_MESA) {
1281 char message[100];
1282 _mesa_snprintf(message, sizeof(message),
1283 "glTexImage%d(format/type YCBCR mismatch", dimensions);
1284 _mesa_error(ctx, GL_INVALID_ENUM, message);
1285 return GL_TRUE; /* error */
1286 }
1287 if (target != GL_TEXTURE_2D &&
1288 target != GL_PROXY_TEXTURE_2D &&
1289 target != GL_TEXTURE_RECTANGLE_NV &&
1290 target != GL_PROXY_TEXTURE_RECTANGLE_NV) {
1291 if (!isProxy)
1292 _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage(target)");
1293 return GL_TRUE;
1294 }
1295 if (border != 0) {
1296 if (!isProxy) {
1297 char message[100];
1298 _mesa_snprintf(message, sizeof(message),
1299 "glTexImage%d(format=GL_YCBCR_MESA and border=%d)",
1300 dimensions, border);
1301 _mesa_error(ctx, GL_INVALID_VALUE, message);
1302 }
1303 return GL_TRUE;
1304 }
1305 }
1306
1307 /* additional checks for depth textures */
1308 if (_mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_COMPONENT) {
1309 /* Only 1D, 2D and rectangular textures supported, not 3D or cubes */
1310 if (target != GL_TEXTURE_1D &&
1311 target != GL_PROXY_TEXTURE_1D &&
1312 target != GL_TEXTURE_2D &&
1313 target != GL_PROXY_TEXTURE_2D &&
1314 target != GL_TEXTURE_RECTANGLE_ARB &&
1315 target != GL_PROXY_TEXTURE_RECTANGLE_ARB) {
1316 if (!isProxy)
1317 _mesa_error(ctx, GL_INVALID_ENUM,
1318 "glTexImage(target/internalFormat)");
1319 return GL_TRUE;
1320 }
1321 }
1322
1323 /* additional checks for compressed textures */
1324 if (_mesa_is_compressed_format(ctx, internalFormat)) {
1325 if (!target_can_be_compressed(ctx, target) && !isProxy) {
1326 _mesa_error(ctx, GL_INVALID_ENUM,
1327 "glTexImage%d(target)", dimensions);
1328 return GL_TRUE;
1329 }
1330 if (border != 0) {
1331 if (!isProxy) {
1332 _mesa_error(ctx, GL_INVALID_OPERATION,
1333 "glTexImage%dD(border!=0)", dimensions);
1334 }
1335 return GL_TRUE;
1336 }
1337 }
1338
1339 /* if we get here, the parameters are OK */
1340 return GL_FALSE;
1341 }
1342
1343
1344 /**
1345 * Test glTexSubImage[123]D() parameters for errors.
1346 *
1347 * \param ctx GL context.
1348 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1349 * \param target texture target given by the user.
1350 * \param level image level given by the user.
1351 * \param xoffset sub-image x offset given by the user.
1352 * \param yoffset sub-image y offset given by the user.
1353 * \param zoffset sub-image z offset given by the user.
1354 * \param format pixel data format given by the user.
1355 * \param type pixel data type given by the user.
1356 * \param width image width given by the user.
1357 * \param height image height given by the user.
1358 * \param depth image depth given by the user.
1359 *
1360 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1361 *
1362 * Verifies each of the parameters against the constants specified in
1363 * __GLcontextRec::Const and the supported extensions, and according to the
1364 * OpenGL specification.
1365 */
1366 static GLboolean
1367 subtexture_error_check( GLcontext *ctx, GLuint dimensions,
1368 GLenum target, GLint level,
1369 GLint xoffset, GLint yoffset, GLint zoffset,
1370 GLint width, GLint height, GLint depth,
1371 GLenum format, GLenum type )
1372 {
1373 /* Check target */
1374 if (dimensions == 1) {
1375 if (target != GL_TEXTURE_1D) {
1376 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" );
1377 return GL_TRUE;
1378 }
1379 }
1380 else if (dimensions == 2) {
1381 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1382 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1383 if (!ctx->Extensions.ARB_texture_cube_map) {
1384 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1385 return GL_TRUE;
1386 }
1387 }
1388 else if (target == GL_TEXTURE_RECTANGLE_NV) {
1389 if (!ctx->Extensions.NV_texture_rectangle) {
1390 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1391 return GL_TRUE;
1392 }
1393 }
1394 else if (target == GL_TEXTURE_1D_ARRAY_EXT) {
1395 if (!ctx->Extensions.MESA_texture_array) {
1396 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1397 return GL_TRUE;
1398 }
1399 }
1400 else if (target != GL_TEXTURE_2D) {
1401 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" );
1402 return GL_TRUE;
1403 }
1404 }
1405 else if (dimensions == 3) {
1406 if (target == GL_TEXTURE_2D_ARRAY_EXT) {
1407 if (!ctx->Extensions.MESA_texture_array) {
1408 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
1409 return GL_TRUE;
1410 }
1411 }
1412 else if (target != GL_TEXTURE_3D) {
1413 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" );
1414 return GL_TRUE;
1415 }
1416 }
1417 else {
1418 _mesa_problem( ctx, "invalid dims in texture_error_check" );
1419 return GL_TRUE;
1420 }
1421
1422 /* Basic level check */
1423 if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
1424 _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level=%d)", level);
1425 return GL_TRUE;
1426 }
1427
1428 if (width < 0) {
1429 _mesa_error(ctx, GL_INVALID_VALUE,
1430 "glTexSubImage%dD(width=%d)", dimensions, width);
1431 return GL_TRUE;
1432 }
1433 if (height < 0 && dimensions > 1) {
1434 _mesa_error(ctx, GL_INVALID_VALUE,
1435 "glTexSubImage%dD(height=%d)", dimensions, height);
1436 return GL_TRUE;
1437 }
1438 if (depth < 0 && dimensions > 2) {
1439 _mesa_error(ctx, GL_INVALID_VALUE,
1440 "glTexSubImage%dD(depth=%d)", dimensions, depth);
1441 return GL_TRUE;
1442 }
1443
1444 if (!_mesa_is_legal_format_and_type(ctx, format, type)) {
1445 _mesa_error(ctx, GL_INVALID_ENUM,
1446 "glTexSubImage%dD(incompatible format 0x%x, type 0x%x)",
1447 dimensions, format, type);
1448 return GL_TRUE;
1449 }
1450
1451 return GL_FALSE;
1452 }
1453
1454
1455 /**
1456 * Do second part of glTexSubImage which depends on the destination texture.
1457 * \return GL_TRUE if error recorded, GL_FALSE otherwise
1458 */
1459 static GLboolean
1460 subtexture_error_check2( GLcontext *ctx, GLuint dimensions,
1461 GLenum target, GLint level,
1462 GLint xoffset, GLint yoffset, GLint zoffset,
1463 GLint width, GLint height, GLint depth,
1464 GLenum format, GLenum type,
1465 const struct gl_texture_image *destTex )
1466 {
1467 if (!destTex) {
1468 /* undefined image level */
1469 _mesa_error(ctx, GL_INVALID_OPERATION, "glTexSubImage%dD", dimensions);
1470 return GL_TRUE;
1471 }
1472
1473 if (xoffset < -((GLint)destTex->Border)) {
1474 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset)",
1475 dimensions);
1476 return GL_TRUE;
1477 }
1478 if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) {
1479 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset+width)",
1480 dimensions);
1481 return GL_TRUE;
1482 }
1483 if (dimensions > 1) {
1484 if (yoffset < -((GLint)destTex->Border)) {
1485 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset)",
1486 dimensions);
1487 return GL_TRUE;
1488 }
1489 if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) {
1490 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset+height)",
1491 dimensions);
1492 return GL_TRUE;
1493 }
1494 }
1495 if (dimensions > 2) {
1496 if (zoffset < -((GLint)destTex->Border)) {
1497 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)");
1498 return GL_TRUE;
1499 }
1500 if (zoffset + depth > (GLint) (destTex->Depth + destTex->Border)) {
1501 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)");
1502 return GL_TRUE;
1503 }
1504 }
1505
1506 if (_mesa_is_format_compressed(destTex->TexFormat)) {
1507 GLuint bw, bh;
1508
1509 if (!target_can_be_compressed(ctx, target)) {
1510 _mesa_error(ctx, GL_INVALID_ENUM,
1511 "glTexSubImage%dD(target=%s)", dimensions,
1512 _mesa_lookup_enum_by_nr(target));
1513 return GL_TRUE;
1514 }
1515
1516 /* do tests which depend on compression block size */
1517 _mesa_get_format_block_size(destTex->TexFormat, &bw, &bh);
1518
1519 /* offset must be multiple of block size */
1520 if ((xoffset % bw != 0) || (yoffset % bh != 0)) {
1521 _mesa_error(ctx, GL_INVALID_OPERATION,
1522 "glTexSubImage%dD(xoffset = %d, yoffset = %d)",
1523 dimensions, xoffset, yoffset);
1524 return GL_TRUE;
1525 }
1526 /* size must be multiple of bw by bh or equal to whole texture size */
1527 if ((width % bw != 0) && (GLuint) width != destTex->Width) {
1528 _mesa_error(ctx, GL_INVALID_OPERATION,
1529 "glTexSubImage%dD(width = %d)", dimensions, width);
1530 return GL_TRUE;
1531 }
1532 if ((height % bh != 0) && (GLuint) height != destTex->Height) {
1533 _mesa_error(ctx, GL_INVALID_OPERATION,
1534 "glTexSubImage%dD(height = %d)", dimensions, height);
1535 return GL_TRUE;
1536 }
1537 }
1538
1539 return GL_FALSE;
1540 }
1541
1542
1543 /**
1544 * Test glCopyTexImage[12]D() parameters for errors.
1545 *
1546 * \param ctx GL context.
1547 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1548 * \param target texture target given by the user.
1549 * \param level image level given by the user.
1550 * \param internalFormat internal format given by the user.
1551 * \param width image width given by the user.
1552 * \param height image height given by the user.
1553 * \param border texture border.
1554 *
1555 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1556 *
1557 * Verifies each of the parameters against the constants specified in
1558 * __GLcontextRec::Const and the supported extensions, and according to the
1559 * OpenGL specification.
1560 */
1561 static GLboolean
1562 copytexture_error_check( GLcontext *ctx, GLuint dimensions,
1563 GLenum target, GLint level, GLint internalFormat,
1564 GLint width, GLint height, GLint border )
1565 {
1566 GLenum type;
1567 GLboolean sizeOK;
1568 GLint format;
1569
1570 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */
1571 if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
1572 _mesa_error(ctx, GL_INVALID_VALUE,
1573 "glCopyTexImage%dD(level=%d)", dimensions, level);
1574 return GL_TRUE;
1575 }
1576
1577 /* Check that the source buffer is complete */
1578 if (ctx->ReadBuffer->Name) {
1579 _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer);
1580 if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
1581 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
1582 "glCopyTexImage%dD(invalid readbuffer)", dimensions);
1583 return GL_TRUE;
1584 }
1585 }
1586
1587 /* Check border */
1588 if (border < 0 || border > 1 ||
1589 ((target == GL_TEXTURE_RECTANGLE_NV ||
1590 target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) {
1591 return GL_TRUE;
1592 }
1593
1594 format = _mesa_base_tex_format(ctx, internalFormat);
1595 if (format < 0) {
1596 _mesa_error(ctx, GL_INVALID_VALUE,
1597 "glCopyTexImage%dD(internalFormat)", dimensions);
1598 return GL_TRUE;
1599 }
1600
1601 if (!_mesa_source_buffer_exists(ctx, format)) {
1602 _mesa_error(ctx, GL_INVALID_OPERATION,
1603 "glCopyTexImage%dD(missing readbuffer)", dimensions);
1604 return GL_TRUE;
1605 }
1606
1607 /* NOTE: the format and type aren't really significant for
1608 * TestProxyTexImage(). Only the internalformat really matters.
1609 */
1610 type = GL_FLOAT;
1611
1612 /* Check target and call ctx->Driver.TestProxyTexImage() to check the
1613 * level, width, height and depth.
1614 */
1615 if (dimensions == 1) {
1616 if (target == GL_TEXTURE_1D) {
1617 sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_1D,
1618 level, internalFormat,
1619 format, type,
1620 width, 1, 1, border);
1621 }
1622 else {
1623 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" );
1624 return GL_TRUE;
1625 }
1626 }
1627 else if (dimensions == 2) {
1628 if (target == GL_TEXTURE_2D) {
1629 sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_2D,
1630 level, internalFormat,
1631 format, type,
1632 width, height, 1, border);
1633 }
1634 else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1635 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1636 if (!ctx->Extensions.ARB_texture_cube_map) {
1637 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1638 return GL_TRUE;
1639 }
1640 sizeOK = (width == height) &&
1641 ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_CUBE_MAP_ARB,
1642 level, internalFormat, format, type,
1643 width, height, 1, border);
1644 }
1645 else if (target == GL_TEXTURE_RECTANGLE_NV) {
1646 if (!ctx->Extensions.NV_texture_rectangle) {
1647 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1648 return GL_TRUE;
1649 }
1650 sizeOK = ctx->Driver.TestProxyTexImage(ctx,
1651 GL_PROXY_TEXTURE_RECTANGLE_NV,
1652 level, internalFormat,
1653 format, type,
1654 width, height, 1, border);
1655 }
1656 else if (target == GL_TEXTURE_1D_ARRAY_EXT) {
1657 if (!ctx->Extensions.MESA_texture_array) {
1658 _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)");
1659 return GL_TRUE;
1660 }
1661 sizeOK = ctx->Driver.TestProxyTexImage(ctx,
1662 GL_PROXY_TEXTURE_1D_ARRAY_EXT,
1663 level, internalFormat,
1664 format, type,
1665 width, height, 1, border);
1666 }
1667 else {
1668 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" );
1669 return GL_TRUE;
1670 }
1671 }
1672 else {
1673 _mesa_problem(ctx, "invalid dimensions in copytexture_error_check");
1674 return GL_TRUE;
1675 }
1676
1677 if (!sizeOK) {
1678 if (dimensions == 1) {
1679 _mesa_error(ctx, GL_INVALID_VALUE,
1680 "glCopyTexImage1D(width=%d)", width);
1681 }
1682 else {
1683 ASSERT(dimensions == 2);
1684 _mesa_error(ctx, GL_INVALID_VALUE,
1685 "glCopyTexImage2D(width=%d, height=%d)", width, height);
1686 }
1687 return GL_TRUE;
1688 }
1689
1690 if (_mesa_is_compressed_format(ctx, internalFormat)) {
1691 if (!target_can_be_compressed(ctx, target)) {
1692 _mesa_error(ctx, GL_INVALID_ENUM,
1693 "glCopyTexImage%d(target)", dimensions);
1694 return GL_TRUE;
1695 }
1696 if (border != 0) {
1697 _mesa_error(ctx, GL_INVALID_OPERATION,
1698 "glCopyTexImage%dD(border!=0)", dimensions);
1699 return GL_TRUE;
1700 }
1701 }
1702 else if (_mesa_is_depth_format(internalFormat)) {
1703 /* make sure we have depth/stencil buffers */
1704 if (!ctx->ReadBuffer->_DepthBuffer) {
1705 _mesa_error(ctx, GL_INVALID_OPERATION,
1706 "glCopyTexImage%dD(no depth)", dimensions);
1707 return GL_TRUE;
1708 }
1709 }
1710 else if (_mesa_is_depthstencil_format(internalFormat)) {
1711 /* make sure we have depth/stencil buffers */
1712 if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) {
1713 _mesa_error(ctx, GL_INVALID_OPERATION,
1714 "glCopyTexImage%dD(no depth/stencil buffer)", dimensions);
1715 return GL_TRUE;
1716 }
1717 }
1718
1719 /* if we get here, the parameters are OK */
1720 return GL_FALSE;
1721 }
1722
1723
1724 /**
1725 * Test glCopyTexSubImage[12]D() parameters for errors.
1726 * Note that this is the first part of error checking.
1727 * See also copytexsubimage_error_check2() below for the second part.
1728 *
1729 * \param ctx GL context.
1730 * \param dimensions texture image dimensions (must be 1, 2 or 3).
1731 * \param target texture target given by the user.
1732 * \param level image level given by the user.
1733 *
1734 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
1735 */
1736 static GLboolean
1737 copytexsubimage_error_check1( GLcontext *ctx, GLuint dimensions,
1738 GLenum target, GLint level)
1739 {
1740 /* Check that the source buffer is complete */
1741 if (ctx->ReadBuffer->Name) {
1742 _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer);
1743 if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
1744 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
1745 "glCopyTexImage%dD(invalid readbuffer)", dimensions);
1746 return GL_TRUE;
1747 }
1748 }
1749
1750 /* Check target */
1751 if (dimensions == 1) {
1752 if (target != GL_TEXTURE_1D) {
1753 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" );
1754 return GL_TRUE;
1755 }
1756 }
1757 else if (dimensions == 2) {
1758 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
1759 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
1760 if (!ctx->Extensions.ARB_texture_cube_map) {
1761 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1762 return GL_TRUE;
1763 }
1764 }
1765 else if (target == GL_TEXTURE_RECTANGLE_NV) {
1766 if (!ctx->Extensions.NV_texture_rectangle) {
1767 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1768 return GL_TRUE;
1769 }
1770 }
1771 else if (target == GL_TEXTURE_1D_ARRAY_EXT) {
1772 if (!ctx->Extensions.MESA_texture_array) {
1773 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1774 return GL_TRUE;
1775 }
1776 }
1777 else if (target != GL_TEXTURE_2D) {
1778 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" );
1779 return GL_TRUE;
1780 }
1781 }
1782 else if (dimensions == 3) {
1783 if (((target != GL_TEXTURE_2D_ARRAY_EXT) ||
1784 (!ctx->Extensions.MESA_texture_array))
1785 && (target != GL_TEXTURE_3D)) {
1786 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" );
1787 return GL_TRUE;
1788 }
1789 }
1790
1791 /* Check level */
1792 if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
1793 _mesa_error(ctx, GL_INVALID_VALUE,
1794 "glCopyTexSubImage%dD(level=%d)", dimensions, level);
1795 return GL_TRUE;
1796 }
1797
1798 return GL_FALSE;
1799 }
1800
1801
1802 /**
1803 * Second part of error checking for glCopyTexSubImage[12]D().
1804 * \param xoffset sub-image x offset given by the user.
1805 * \param yoffset sub-image y offset given by the user.
1806 * \param zoffset sub-image z offset given by the user.
1807 * \param width image width given by the user.
1808 * \param height image height given by the user.
1809 */
1810 static GLboolean
1811 copytexsubimage_error_check2( GLcontext *ctx, GLuint dimensions,
1812 GLenum target, GLint level,
1813 GLint xoffset, GLint yoffset, GLint zoffset,
1814 GLsizei width, GLsizei height,
1815 const struct gl_texture_image *teximage )
1816 {
1817 /* check that dest tex image exists */
1818 if (!teximage) {
1819 _mesa_error(ctx, GL_INVALID_OPERATION,
1820 "glCopyTexSubImage%dD(undefined texture level: %d)",
1821 dimensions, level);
1822 return GL_TRUE;
1823 }
1824
1825 /* Check size */
1826 if (width < 0) {
1827 _mesa_error(ctx, GL_INVALID_VALUE,
1828 "glCopyTexSubImage%dD(width=%d)", dimensions, width);
1829 return GL_TRUE;
1830 }
1831 if (dimensions > 1 && height < 0) {
1832 _mesa_error(ctx, GL_INVALID_VALUE,
1833 "glCopyTexSubImage%dD(height=%d)", dimensions, height);
1834 return GL_TRUE;
1835 }
1836
1837 /* check x/y offsets */
1838 if (xoffset < -((GLint)teximage->Border)) {
1839 _mesa_error(ctx, GL_INVALID_VALUE,
1840 "glCopyTexSubImage%dD(xoffset=%d)", dimensions, xoffset);
1841 return GL_TRUE;
1842 }
1843 if (xoffset + width > (GLint) (teximage->Width + teximage->Border)) {
1844 _mesa_error(ctx, GL_INVALID_VALUE,
1845 "glCopyTexSubImage%dD(xoffset+width)", dimensions);
1846 return GL_TRUE;
1847 }
1848 if (dimensions > 1) {
1849 if (yoffset < -((GLint)teximage->Border)) {
1850 _mesa_error(ctx, GL_INVALID_VALUE,
1851 "glCopyTexSubImage%dD(yoffset=%d)", dimensions, yoffset);
1852 return GL_TRUE;
1853 }
1854 /* NOTE: we're adding the border here, not subtracting! */
1855 if (yoffset + height > (GLint) (teximage->Height + teximage->Border)) {
1856 _mesa_error(ctx, GL_INVALID_VALUE,
1857 "glCopyTexSubImage%dD(yoffset+height)", dimensions);
1858 return GL_TRUE;
1859 }
1860 }
1861
1862 /* check z offset */
1863 if (dimensions > 2) {
1864 if (zoffset < -((GLint)teximage->Border)) {
1865 _mesa_error(ctx, GL_INVALID_VALUE,
1866 "glCopyTexSubImage%dD(zoffset)", dimensions);
1867 return GL_TRUE;
1868 }
1869 if (zoffset > (GLint) (teximage->Depth + teximage->Border)) {
1870 _mesa_error(ctx, GL_INVALID_VALUE,
1871 "glCopyTexSubImage%dD(zoffset+depth)", dimensions);
1872 return GL_TRUE;
1873 }
1874 }
1875
1876 if (_mesa_is_format_compressed(teximage->TexFormat)) {
1877 if (!target_can_be_compressed(ctx, target)) {
1878 _mesa_error(ctx, GL_INVALID_ENUM,
1879 "glCopyTexSubImage%d(target)", dimensions);
1880 return GL_TRUE;
1881 }
1882 /* offset must be multiple of 4 */
1883 if ((xoffset & 3) || (yoffset & 3)) {
1884 _mesa_error(ctx, GL_INVALID_VALUE,
1885 "glCopyTexSubImage%dD(xoffset or yoffset)", dimensions);
1886 return GL_TRUE;
1887 }
1888 /* size must be multiple of 4 */
1889 if ((width & 3) != 0 && (GLuint) width != teximage->Width) {
1890 _mesa_error(ctx, GL_INVALID_VALUE,
1891 "glCopyTexSubImage%dD(width)", dimensions);
1892 return GL_TRUE;
1893 }
1894 if ((height & 3) != 0 && (GLuint) height != teximage->Height) {
1895 _mesa_error(ctx, GL_INVALID_VALUE,
1896 "glCopyTexSubImage%dD(height)", dimensions);
1897 return GL_TRUE;
1898 }
1899 }
1900
1901 if (teximage->InternalFormat == GL_YCBCR_MESA) {
1902 _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTexSubImage2D");
1903 return GL_TRUE;
1904 }
1905
1906 if (!_mesa_source_buffer_exists(ctx, teximage->_BaseFormat)) {
1907 _mesa_error(ctx, GL_INVALID_OPERATION,
1908 "glCopyTexSubImage%dD(missing readbuffer, format=0x%x)",
1909 dimensions, teximage->_BaseFormat);
1910 return GL_TRUE;
1911 }
1912
1913 if (teximage->_BaseFormat == GL_DEPTH_COMPONENT) {
1914 if (!ctx->ReadBuffer->_DepthBuffer) {
1915 _mesa_error(ctx, GL_INVALID_OPERATION,
1916 "glCopyTexSubImage%dD(no depth buffer)",
1917 dimensions);
1918 return GL_TRUE;
1919 }
1920 }
1921 else if (teximage->_BaseFormat == GL_DEPTH_STENCIL_EXT) {
1922 if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) {
1923 _mesa_error(ctx, GL_INVALID_OPERATION,
1924 "glCopyTexSubImage%dD(no depth/stencil buffer)",
1925 dimensions);
1926 return GL_TRUE;
1927 }
1928 }
1929
1930 /* if we get here, the parameters are OK */
1931 return GL_FALSE;
1932 }
1933
1934
1935 /** Callback info for walking over FBO hash table */
1936 struct cb_info
1937 {
1938 GLcontext *ctx;
1939 struct gl_texture_object *texObj;
1940 GLuint level, face;
1941 };
1942
1943
1944 /**
1945 * Check render to texture callback. Called from _mesa_HashWalk().
1946 */
1947 static void
1948 check_rtt_cb(GLuint key, void *data, void *userData)
1949 {
1950 struct gl_framebuffer *fb = (struct gl_framebuffer *) data;
1951 const struct cb_info *info = (struct cb_info *) userData;
1952 GLcontext *ctx = info->ctx;
1953 const struct gl_texture_object *texObj = info->texObj;
1954 const GLuint level = info->level, face = info->face;
1955
1956 /* If this is a user-created FBO */
1957 if (fb->Name) {
1958 GLuint i;
1959 /* check if any of the FBO's attachments point to 'texObj' */
1960 for (i = 0; i < BUFFER_COUNT; i++) {
1961 struct gl_renderbuffer_attachment *att = fb->Attachment + i;
1962 if (att->Type == GL_TEXTURE &&
1963 att->Texture == texObj &&
1964 att->TextureLevel == level &&
1965 att->CubeMapFace == face) {
1966 ASSERT(att->Texture->Image[att->CubeMapFace][att->TextureLevel]);
1967 /* Tell driver about the new renderbuffer texture */
1968 ctx->Driver.RenderTexture(ctx, ctx->DrawBuffer, att);
1969 /* Mark fb status as indeterminate to force re-validation */
1970 fb->_Status = 0;
1971 }
1972 }
1973 }
1974 }
1975
1976
1977 /**
1978 * When a texture image is specified we have to check if it's bound to
1979 * any framebuffer objects (render to texture) in order to detect changes
1980 * in size or format since that effects FBO completeness.
1981 * Any FBOs rendering into the texture must be re-validated.
1982 */
1983 static void
1984 update_fbo_texture(GLcontext *ctx, struct gl_texture_object *texObj,
1985 GLuint face, GLuint level)
1986 {
1987 /* Only check this texture if it's been marked as RenderToTexture */
1988 if (texObj->_RenderToTexture) {
1989 struct cb_info info;
1990 info.ctx = ctx;
1991 info.texObj = texObj;
1992 info.level = level;
1993 info.face = face;
1994 _mesa_HashWalk(ctx->Shared->FrameBuffers, check_rtt_cb, &info);
1995 }
1996 }
1997
1998
1999 /**
2000 * If the texture object's GenerateMipmap flag is set and we've
2001 * changed the texture base level image, regenerate the rest of the
2002 * mipmap levels now.
2003 */
2004 static INLINE void
2005 check_gen_mipmap(GLcontext *ctx, GLenum target,
2006 struct gl_texture_object *texObj, GLint level)
2007 {
2008 ASSERT(target != GL_TEXTURE_CUBE_MAP);
2009 if (texObj->GenerateMipmap &&
2010 level == texObj->BaseLevel &&
2011 level < texObj->MaxLevel) {
2012 ASSERT(ctx->Driver.GenerateMipmap);
2013 ctx->Driver.GenerateMipmap(ctx, target, texObj);
2014 }
2015 }
2016
2017
2018 /** Debug helper: override the user-requested internal format */
2019 static GLenum
2020 override_internal_format(GLenum internalFormat, GLint width, GLint height)
2021 {
2022 #if 0
2023 if (internalFormat == GL_RGBA16F_ARB ||
2024 internalFormat == GL_RGBA32F_ARB) {
2025 printf("Convert rgba float tex to int %d x %d\n", width, height);
2026 return GL_RGBA;
2027 }
2028 else if (internalFormat == GL_RGB16F_ARB ||
2029 internalFormat == GL_RGB32F_ARB) {
2030 printf("Convert rgb float tex to int %d x %d\n", width, height);
2031 return GL_RGB;
2032 }
2033 else if (internalFormat == GL_LUMINANCE_ALPHA16F_ARB ||
2034 internalFormat == GL_LUMINANCE_ALPHA32F_ARB) {
2035 printf("Convert luminance float tex to int %d x %d\n", width, height);
2036 return GL_LUMINANCE_ALPHA;
2037 }
2038 else if (internalFormat == GL_LUMINANCE16F_ARB ||
2039 internalFormat == GL_LUMINANCE32F_ARB) {
2040 printf("Convert luminance float tex to int %d x %d\n", width, height);
2041 return GL_LUMINANCE;
2042 }
2043 else if (internalFormat == GL_ALPHA16F_ARB ||
2044 internalFormat == GL_ALPHA32F_ARB) {
2045 printf("Convert luminance float tex to int %d x %d\n", width, height);
2046 return GL_ALPHA;
2047 }
2048 /*
2049 else if (internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) {
2050 internalFormat = GL_RGBA;
2051 }
2052 */
2053 else {
2054 return internalFormat;
2055 }
2056 #else
2057 return internalFormat;
2058 #endif
2059 }
2060
2061
2062 /*
2063 * Called from the API. Note that width includes the border.
2064 */
2065 void GLAPIENTRY
2066 _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
2067 GLsizei width, GLint border, GLenum format,
2068 GLenum type, const GLvoid *pixels )
2069 {
2070 GLsizei postConvWidth = width;
2071 GET_CURRENT_CONTEXT(ctx);
2072 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2073
2074 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2075 _mesa_debug(ctx, "glTexImage1D %s %d %s %d %d %s %s %p\n",
2076 _mesa_lookup_enum_by_nr(target), level,
2077 _mesa_lookup_enum_by_nr(internalFormat), width, border,
2078 _mesa_lookup_enum_by_nr(format),
2079 _mesa_lookup_enum_by_nr(type), pixels);
2080
2081 internalFormat = override_internal_format(internalFormat, width, 1);
2082
2083 #if FEATURE_convolve
2084 if (_mesa_is_color_format(internalFormat)) {
2085 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2086 }
2087 #endif
2088
2089 if (target == GL_TEXTURE_1D) {
2090 /* non-proxy target */
2091 struct gl_texture_object *texObj;
2092 struct gl_texture_image *texImage;
2093 const GLuint face = _mesa_tex_target_to_face(target);
2094
2095 if (texture_error_check(ctx, target, level, internalFormat,
2096 format, type, 1, postConvWidth, 1, 1, border)) {
2097 return; /* error was recorded */
2098 }
2099
2100 if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
2101 _mesa_update_state(ctx);
2102
2103 texObj = _mesa_get_current_tex_object(ctx, target);
2104 _mesa_lock_texture(ctx, texObj);
2105 {
2106 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
2107 if (!texImage) {
2108 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
2109 }
2110 else {
2111 if (texImage->Data) {
2112 ctx->Driver.FreeTexImageData( ctx, texImage );
2113 }
2114
2115 ASSERT(texImage->Data == NULL);
2116
2117 clear_teximage_fields(texImage); /* not really needed, but helpful */
2118 _mesa_init_teximage_fields(ctx, target, texImage,
2119 postConvWidth, 1, 1,
2120 border, internalFormat);
2121
2122 /* Choose actual texture format */
2123 texImage->TexFormat =
2124 ctx->Driver.ChooseTextureFormat(ctx, internalFormat,
2125 format, type);
2126 ASSERT(texImage->TexFormat != MESA_FORMAT_NONE);
2127
2128 /* Give the texture to the driver. <pixels> may be null. */
2129 ASSERT(ctx->Driver.TexImage1D);
2130 ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
2131 width, border, format, type, pixels,
2132 &ctx->Unpack, texObj, texImage);
2133
2134 ASSERT(texImage->TexFormat);
2135
2136 _mesa_set_fetch_functions(texImage, 1);
2137
2138 check_gen_mipmap(ctx, target, texObj, level);
2139
2140 update_fbo_texture(ctx, texObj, face, level);
2141
2142 /* state update */
2143 texObj->_Complete = GL_FALSE;
2144 ctx->NewState |= _NEW_TEXTURE;
2145 }
2146 }
2147 _mesa_unlock_texture(ctx, texObj);
2148 }
2149 else if (target == GL_PROXY_TEXTURE_1D) {
2150 /* Proxy texture: check for errors and update proxy state */
2151 struct gl_texture_image *texImage;
2152 texImage = _mesa_get_proxy_tex_image(ctx, target, level);
2153 if (texture_error_check(ctx, target, level, internalFormat,
2154 format, type, 1, postConvWidth, 1, 1, border)) {
2155 /* when error, clear all proxy texture image parameters */
2156 if (texImage)
2157 clear_teximage_fields(texImage);
2158 }
2159 else {
2160 /* no error, set the tex image parameters */
2161 ASSERT(texImage);
2162 _mesa_init_teximage_fields(ctx, target, texImage,
2163 postConvWidth, 1, 1,
2164 border, internalFormat);
2165 texImage->TexFormat =
2166 ctx->Driver.ChooseTextureFormat(ctx, internalFormat, format, type);
2167 }
2168 }
2169 else {
2170 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" );
2171 return;
2172 }
2173 }
2174
2175
2176 void GLAPIENTRY
2177 _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
2178 GLsizei width, GLsizei height, GLint border,
2179 GLenum format, GLenum type,
2180 const GLvoid *pixels )
2181 {
2182 GLsizei postConvWidth = width, postConvHeight = height;
2183 GET_CURRENT_CONTEXT(ctx);
2184 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2185
2186 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2187 _mesa_debug(ctx, "glTexImage2D %s %d %s %d %d %d %s %s %p\n",
2188 _mesa_lookup_enum_by_nr(target), level,
2189 _mesa_lookup_enum_by_nr(internalFormat), width, height,
2190 border, _mesa_lookup_enum_by_nr(format),
2191 _mesa_lookup_enum_by_nr(type), pixels);
2192
2193 internalFormat = override_internal_format(internalFormat, width, height);
2194
2195 #if FEATURE_convolve
2196 if (_mesa_is_color_format(internalFormat)) {
2197 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
2198 &postConvHeight);
2199 }
2200 #endif
2201
2202 if (target == GL_TEXTURE_2D ||
2203 (ctx->Extensions.ARB_texture_cube_map &&
2204 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
2205 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) ||
2206 (ctx->Extensions.NV_texture_rectangle &&
2207 target == GL_TEXTURE_RECTANGLE_NV) ||
2208 (ctx->Extensions.MESA_texture_array &&
2209 target == GL_TEXTURE_1D_ARRAY_EXT)) {
2210 /* non-proxy target */
2211 struct gl_texture_object *texObj;
2212 struct gl_texture_image *texImage;
2213 const GLuint face = _mesa_tex_target_to_face(target);
2214
2215 if (texture_error_check(ctx, target, level, internalFormat,
2216 format, type, 2, postConvWidth, postConvHeight,
2217 1, border)) {
2218 return; /* error was recorded */
2219 }
2220
2221 if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
2222 _mesa_update_state(ctx);
2223
2224 texObj = _mesa_get_current_tex_object(ctx, target);
2225 _mesa_lock_texture(ctx, texObj);
2226 {
2227 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
2228 if (!texImage) {
2229 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
2230 }
2231 else {
2232 if (texImage->Data) {
2233 ctx->Driver.FreeTexImageData( ctx, texImage );
2234 }
2235
2236 ASSERT(texImage->Data == NULL);
2237 clear_teximage_fields(texImage); /* not really needed, but helpful */
2238 _mesa_init_teximage_fields(ctx, target, texImage,
2239 postConvWidth, postConvHeight, 1,
2240 border, internalFormat);
2241
2242 /* Choose actual texture format */
2243 texImage->TexFormat =
2244 ctx->Driver.ChooseTextureFormat(ctx, internalFormat,
2245 format, type);
2246 ASSERT(texImage->TexFormat != MESA_FORMAT_NONE);
2247
2248 /* Give the texture to the driver. <pixels> may be null. */
2249 ASSERT(ctx->Driver.TexImage2D);
2250 ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
2251 width, height, border, format, type,
2252 pixels, &ctx->Unpack, texObj, texImage);
2253
2254 ASSERT(texImage->TexFormat);
2255
2256 _mesa_set_fetch_functions(texImage, 2);
2257
2258 check_gen_mipmap(ctx, target, texObj, level);
2259
2260 update_fbo_texture(ctx, texObj, face, level);
2261
2262 /* state update */
2263 texObj->_Complete = GL_FALSE;
2264 ctx->NewState |= _NEW_TEXTURE;
2265 }
2266 }
2267 _mesa_unlock_texture(ctx, texObj);
2268 }
2269 else if (target == GL_PROXY_TEXTURE_2D ||
2270 (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB &&
2271 ctx->Extensions.ARB_texture_cube_map) ||
2272 (target == GL_PROXY_TEXTURE_RECTANGLE_NV &&
2273 ctx->Extensions.NV_texture_rectangle) ||
2274 (ctx->Extensions.MESA_texture_array &&
2275 target == GL_PROXY_TEXTURE_1D_ARRAY_EXT)) {
2276 /* Proxy texture: check for errors and update proxy state */
2277 struct gl_texture_image *texImage;
2278 texImage = _mesa_get_proxy_tex_image(ctx, target, level);
2279 if (texture_error_check(ctx, target, level, internalFormat,
2280 format, type, 2, postConvWidth, postConvHeight,
2281 1, border)) {
2282 /* when error, clear all proxy texture image parameters */
2283 if (texImage)
2284 clear_teximage_fields(texImage);
2285 }
2286 else {
2287 /* no error, set the tex image parameters */
2288 _mesa_init_teximage_fields(ctx, target, texImage,
2289 postConvWidth, postConvHeight, 1,
2290 border, internalFormat);
2291 texImage->TexFormat =
2292 ctx->Driver.ChooseTextureFormat(ctx, internalFormat, format, type);
2293 }
2294 }
2295 else {
2296 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" );
2297 return;
2298 }
2299 }
2300
2301
2302 /*
2303 * Called by the API or display list executor.
2304 * Note that width and height include the border.
2305 */
2306 void GLAPIENTRY
2307 _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
2308 GLsizei width, GLsizei height, GLsizei depth,
2309 GLint border, GLenum format, GLenum type,
2310 const GLvoid *pixels )
2311 {
2312 GET_CURRENT_CONTEXT(ctx);
2313 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2314
2315 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2316 _mesa_debug(ctx, "glTexImage3D %s %d %s %d %d %d %d %s %s %p\n",
2317 _mesa_lookup_enum_by_nr(target), level,
2318 _mesa_lookup_enum_by_nr(internalFormat), width, height,
2319 depth, border, _mesa_lookup_enum_by_nr(format),
2320 _mesa_lookup_enum_by_nr(type), pixels);
2321
2322 internalFormat = override_internal_format(internalFormat, width, height);
2323
2324 if (target == GL_TEXTURE_3D ||
2325 (ctx->Extensions.MESA_texture_array &&
2326 target == GL_TEXTURE_2D_ARRAY_EXT)) {
2327 /* non-proxy target */
2328 struct gl_texture_object *texObj;
2329 struct gl_texture_image *texImage;
2330 const GLuint face = _mesa_tex_target_to_face(target);
2331
2332 if (texture_error_check(ctx, target, level, (GLint) internalFormat,
2333 format, type, 3, width, height, depth, border)) {
2334 return; /* error was recorded */
2335 }
2336
2337 if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
2338 _mesa_update_state(ctx);
2339
2340 texObj = _mesa_get_current_tex_object(ctx, target);
2341 _mesa_lock_texture(ctx, texObj);
2342 {
2343 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
2344 if (!texImage) {
2345 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D");
2346 }
2347 else {
2348 if (texImage->Data) {
2349 ctx->Driver.FreeTexImageData( ctx, texImage );
2350 }
2351
2352 ASSERT(texImage->Data == NULL);
2353 clear_teximage_fields(texImage); /* not really needed, but helpful */
2354 _mesa_init_teximage_fields(ctx, target, texImage,
2355 width, height, depth,
2356 border, internalFormat);
2357
2358 /* Choose actual texture format */
2359 texImage->TexFormat =
2360 ctx->Driver.ChooseTextureFormat(ctx, internalFormat,
2361 format, type);
2362 ASSERT(texImage->TexFormat != MESA_FORMAT_NONE);
2363
2364 /* Give the texture to the driver. <pixels> may be null. */
2365 ASSERT(ctx->Driver.TexImage3D);
2366 ctx->Driver.TexImage3D(ctx, target, level, internalFormat,
2367 width, height, depth, border, format, type,
2368 pixels, &ctx->Unpack, texObj, texImage);
2369
2370 ASSERT(texImage->TexFormat);
2371
2372 _mesa_set_fetch_functions(texImage, 3);
2373
2374 check_gen_mipmap(ctx, target, texObj, level);
2375
2376 update_fbo_texture(ctx, texObj, face, level);
2377
2378 /* state update */
2379 texObj->_Complete = GL_FALSE;
2380 ctx->NewState |= _NEW_TEXTURE;
2381 }
2382 }
2383 _mesa_unlock_texture(ctx, texObj);
2384 }
2385 else if (target == GL_PROXY_TEXTURE_3D ||
2386 (ctx->Extensions.MESA_texture_array &&
2387 target == GL_PROXY_TEXTURE_2D_ARRAY_EXT)) {
2388 /* Proxy texture: check for errors and update proxy state */
2389 struct gl_texture_image *texImage;
2390 texImage = _mesa_get_proxy_tex_image(ctx, target, level);
2391 if (texture_error_check(ctx, target, level, internalFormat,
2392 format, type, 3, width, height, depth, border)) {
2393 /* when error, clear all proxy texture image parameters */
2394 if (texImage)
2395 clear_teximage_fields(texImage);
2396 }
2397 else {
2398 /* no error, set the tex image parameters */
2399 _mesa_init_teximage_fields(ctx, target, texImage, width, height,
2400 depth, border, internalFormat);
2401 texImage->TexFormat =
2402 ctx->Driver.ChooseTextureFormat(ctx, internalFormat, format, type);
2403 }
2404 }
2405 else {
2406 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" );
2407 return;
2408 }
2409 }
2410
2411
2412 void GLAPIENTRY
2413 _mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
2414 GLsizei width, GLsizei height, GLsizei depth,
2415 GLint border, GLenum format, GLenum type,
2416 const GLvoid *pixels )
2417 {
2418 _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height,
2419 depth, border, format, type, pixels);
2420 }
2421
2422
2423 #if FEATURE_OES_EGL_image
2424 void GLAPIENTRY
2425 _mesa_EGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image)
2426 {
2427 struct gl_texture_object *texObj;
2428 struct gl_texture_image *texImage;
2429 GET_CURRENT_CONTEXT(ctx);
2430 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2431
2432 if (!ctx->Extensions.OES_EGL_image) {
2433 _mesa_error(ctx, GL_INVALID_OPERATION,
2434 "glEGLImageTargetTexture2DOES(unsupported)");
2435 return;
2436 }
2437
2438 if (target != GL_TEXTURE_2D) {
2439 _mesa_error(ctx, GL_INVALID_ENUM,
2440 "glEGLImageTargetTexture2D(target=%d)", target);
2441 return;
2442 }
2443
2444 if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
2445 _mesa_update_state(ctx);
2446
2447 texObj = _mesa_get_current_tex_object(ctx, target);
2448 _mesa_lock_texture(ctx, texObj);
2449
2450 texImage = _mesa_get_tex_image(ctx, texObj, target, 0);
2451 if (!texImage) {
2452 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glEGLImageTargetTexture2D");
2453 } else {
2454 if (texImage->Data)
2455 ctx->Driver.FreeTexImageData( ctx, texImage );
2456
2457 ASSERT(texImage->Data == NULL);
2458 ctx->Driver.EGLImageTargetTexture2D(ctx, target,
2459 texObj, texImage, image);
2460
2461 /* state update */
2462 texObj->_Complete = GL_FALSE;
2463 ctx->NewState |= _NEW_TEXTURE;
2464 }
2465 _mesa_unlock_texture(ctx, texObj);
2466
2467 }
2468 #endif
2469
2470
2471 void GLAPIENTRY
2472 _mesa_TexSubImage1D( GLenum target, GLint level,
2473 GLint xoffset, GLsizei width,
2474 GLenum format, GLenum type,
2475 const GLvoid *pixels )
2476 {
2477 GLsizei postConvWidth = width;
2478 struct gl_texture_object *texObj;
2479 struct gl_texture_image *texImage;
2480 GET_CURRENT_CONTEXT(ctx);
2481 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2482
2483 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2484 _mesa_debug(ctx, "glTexSubImage1D %s %d %d %d %s %s %p\n",
2485 _mesa_lookup_enum_by_nr(target), level,
2486 xoffset, width, _mesa_lookup_enum_by_nr(format),
2487 _mesa_lookup_enum_by_nr(type), pixels);
2488
2489 if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
2490 _mesa_update_state(ctx);
2491
2492 #if FEATURE_convolve
2493 /* XXX should test internal format */
2494 if (_mesa_is_color_format(format)) {
2495 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2496 }
2497 #endif
2498
2499 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0,
2500 postConvWidth, 1, 1, format, type)) {
2501 return; /* error was detected */
2502 }
2503
2504
2505 texObj = _mesa_get_current_tex_object(ctx, target);
2506 assert(texObj);
2507
2508 _mesa_lock_texture(ctx, texObj);
2509 {
2510 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2511
2512 if (subtexture_error_check2(ctx, 1, target, level, xoffset, 0, 0,
2513 postConvWidth, 1, 1,
2514 format, type, texImage)) {
2515 /* error was recorded */
2516 }
2517 else if (width > 0) {
2518 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2519 xoffset += texImage->Border;
2520
2521 ASSERT(ctx->Driver.TexSubImage1D);
2522 ctx->Driver.TexSubImage1D(ctx, target, level, xoffset, width,
2523 format, type, pixels, &ctx->Unpack,
2524 texObj, texImage);
2525
2526 check_gen_mipmap(ctx, target, texObj, level);
2527
2528 ctx->NewState |= _NEW_TEXTURE;
2529 }
2530 }
2531 _mesa_unlock_texture(ctx, texObj);
2532 }
2533
2534
2535 void GLAPIENTRY
2536 _mesa_TexSubImage2D( GLenum target, GLint level,
2537 GLint xoffset, GLint yoffset,
2538 GLsizei width, GLsizei height,
2539 GLenum format, GLenum type,
2540 const GLvoid *pixels )
2541 {
2542 GLsizei postConvWidth = width, postConvHeight = height;
2543 struct gl_texture_object *texObj;
2544 struct gl_texture_image *texImage;
2545 GET_CURRENT_CONTEXT(ctx);
2546 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2547
2548 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2549 _mesa_debug(ctx, "glTexSubImage2D %s %d %d %d %d %d %s %s %p\n",
2550 _mesa_lookup_enum_by_nr(target), level,
2551 xoffset, yoffset, width, height,
2552 _mesa_lookup_enum_by_nr(format),
2553 _mesa_lookup_enum_by_nr(type), pixels);
2554
2555 if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
2556 _mesa_update_state(ctx);
2557
2558 #if FEATURE_convolve
2559 /* XXX should test internal format */
2560 if (_mesa_is_color_format(format)) {
2561 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
2562 &postConvHeight);
2563 }
2564 #endif
2565
2566 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0,
2567 postConvWidth, postConvHeight, 1, format, type)) {
2568 return; /* error was detected */
2569 }
2570
2571 texObj = _mesa_get_current_tex_object(ctx, target);
2572
2573 _mesa_lock_texture(ctx, texObj);
2574 {
2575 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2576
2577 if (subtexture_error_check2(ctx, 2, target, level, xoffset, yoffset, 0,
2578 postConvWidth, postConvHeight, 1,
2579 format, type, texImage)) {
2580 /* error was recorded */
2581 }
2582 else if (width > 0 && height >= 0) {
2583 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2584 xoffset += texImage->Border;
2585 yoffset += texImage->Border;
2586
2587 ASSERT(ctx->Driver.TexSubImage2D);
2588 ctx->Driver.TexSubImage2D(ctx, target, level, xoffset, yoffset,
2589 width, height, format, type, pixels,
2590 &ctx->Unpack, texObj, texImage);
2591
2592 check_gen_mipmap(ctx, target, texObj, level);
2593
2594 ctx->NewState |= _NEW_TEXTURE;
2595 }
2596 }
2597 _mesa_unlock_texture(ctx, texObj);
2598 }
2599
2600
2601
2602 void GLAPIENTRY
2603 _mesa_TexSubImage3D( GLenum target, GLint level,
2604 GLint xoffset, GLint yoffset, GLint zoffset,
2605 GLsizei width, GLsizei height, GLsizei depth,
2606 GLenum format, GLenum type,
2607 const GLvoid *pixels )
2608 {
2609 struct gl_texture_object *texObj;
2610 struct gl_texture_image *texImage;
2611 GET_CURRENT_CONTEXT(ctx);
2612 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2613
2614 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2615 _mesa_debug(ctx, "glTexSubImage3D %s %d %d %d %d %d %d %d %s %s %p\n",
2616 _mesa_lookup_enum_by_nr(target), level,
2617 xoffset, yoffset, zoffset, width, height, depth,
2618 _mesa_lookup_enum_by_nr(format),
2619 _mesa_lookup_enum_by_nr(type), pixels);
2620
2621 if (ctx->NewState & _MESA_NEW_TRANSFER_STATE)
2622 _mesa_update_state(ctx);
2623
2624 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset,
2625 width, height, depth, format, type)) {
2626 return; /* error was detected */
2627 }
2628
2629 texObj = _mesa_get_current_tex_object(ctx, target);
2630
2631 _mesa_lock_texture(ctx, texObj);
2632 {
2633 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2634
2635 if (subtexture_error_check2(ctx, 3, target, level,
2636 xoffset, yoffset, zoffset,
2637 width, height, depth,
2638 format, type, texImage)) {
2639 /* error was recorded */
2640 }
2641 else if (width > 0 && height > 0 && height > 0) {
2642 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2643 xoffset += texImage->Border;
2644 yoffset += texImage->Border;
2645 zoffset += texImage->Border;
2646
2647 ASSERT(ctx->Driver.TexSubImage3D);
2648 ctx->Driver.TexSubImage3D(ctx, target, level,
2649 xoffset, yoffset, zoffset,
2650 width, height, depth,
2651 format, type, pixels,
2652 &ctx->Unpack, texObj, texImage );
2653
2654 check_gen_mipmap(ctx, target, texObj, level);
2655
2656 ctx->NewState |= _NEW_TEXTURE;
2657 }
2658 }
2659 _mesa_unlock_texture(ctx, texObj);
2660 }
2661
2662
2663
2664 void GLAPIENTRY
2665 _mesa_CopyTexImage1D( GLenum target, GLint level,
2666 GLenum internalFormat,
2667 GLint x, GLint y,
2668 GLsizei width, GLint border )
2669 {
2670 struct gl_texture_object *texObj;
2671 struct gl_texture_image *texImage;
2672 GLsizei postConvWidth = width;
2673 const GLuint face = _mesa_tex_target_to_face(target);
2674 GET_CURRENT_CONTEXT(ctx);
2675 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2676
2677 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2678 _mesa_debug(ctx, "glCopyTexImage1D %s %d %s %d %d %d %d\n",
2679 _mesa_lookup_enum_by_nr(target), level,
2680 _mesa_lookup_enum_by_nr(internalFormat),
2681 x, y, width, border);
2682
2683 if (ctx->NewState & NEW_COPY_TEX_STATE)
2684 _mesa_update_state(ctx);
2685
2686 #if FEATURE_convolve
2687 if (_mesa_is_color_format(internalFormat)) {
2688 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2689 }
2690 #endif
2691
2692 if (copytexture_error_check(ctx, 1, target, level, internalFormat,
2693 postConvWidth, 1, border))
2694 return;
2695
2696 texObj = _mesa_get_current_tex_object(ctx, target);
2697
2698 _mesa_lock_texture(ctx, texObj);
2699 {
2700 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
2701 if (!texImage) {
2702 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D");
2703 }
2704 else {
2705 if (texImage->Data) {
2706 ctx->Driver.FreeTexImageData( ctx, texImage );
2707 }
2708
2709 ASSERT(texImage->Data == NULL);
2710
2711 clear_teximage_fields(texImage); /* not really needed, but helpful */
2712 _mesa_init_teximage_fields(ctx, target, texImage, postConvWidth, 1, 1,
2713 border, internalFormat);
2714
2715 /* Choose actual texture format */
2716 texImage->TexFormat =
2717 ctx->Driver.ChooseTextureFormat(ctx, internalFormat,
2718 GL_NONE, GL_NONE);
2719 ASSERT(texImage->TexFormat != MESA_FORMAT_NONE);
2720
2721 ASSERT(ctx->Driver.CopyTexImage1D);
2722 ctx->Driver.CopyTexImage1D(ctx, target, level, internalFormat,
2723 x, y, width, border);
2724
2725 ASSERT(texImage->TexFormat);
2726
2727 _mesa_set_fetch_functions(texImage, 1);
2728
2729 check_gen_mipmap(ctx, target, texObj, level);
2730
2731 update_fbo_texture(ctx, texObj, face, level);
2732
2733 /* state update */
2734 texObj->_Complete = GL_FALSE;
2735 ctx->NewState |= _NEW_TEXTURE;
2736 }
2737 }
2738 _mesa_unlock_texture(ctx, texObj);
2739 }
2740
2741
2742
2743 void GLAPIENTRY
2744 _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
2745 GLint x, GLint y, GLsizei width, GLsizei height,
2746 GLint border )
2747 {
2748 struct gl_texture_object *texObj;
2749 struct gl_texture_image *texImage;
2750 GLsizei postConvWidth = width, postConvHeight = height;
2751 const GLuint face = _mesa_tex_target_to_face(target);
2752 GET_CURRENT_CONTEXT(ctx);
2753 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2754
2755 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2756 _mesa_debug(ctx, "glCopyTexImage2D %s %d %s %d %d %d %d %d\n",
2757 _mesa_lookup_enum_by_nr(target), level,
2758 _mesa_lookup_enum_by_nr(internalFormat),
2759 x, y, width, height, border);
2760
2761 if (ctx->NewState & NEW_COPY_TEX_STATE)
2762 _mesa_update_state(ctx);
2763
2764 #if FEATURE_convolve
2765 if (_mesa_is_color_format(internalFormat)) {
2766 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth,
2767 &postConvHeight);
2768 }
2769 #endif
2770
2771 if (copytexture_error_check(ctx, 2, target, level, internalFormat,
2772 postConvWidth, postConvHeight, border))
2773 return;
2774
2775 texObj = _mesa_get_current_tex_object(ctx, target);
2776
2777 _mesa_lock_texture(ctx, texObj);
2778 {
2779 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
2780
2781 if (!texImage) {
2782 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D");
2783 }
2784 else {
2785 if (texImage->Data) {
2786 ctx->Driver.FreeTexImageData( ctx, texImage );
2787 }
2788
2789 ASSERT(texImage->Data == NULL);
2790
2791 clear_teximage_fields(texImage); /* not really needed, but helpful */
2792 _mesa_init_teximage_fields(ctx, target, texImage,
2793 postConvWidth, postConvHeight, 1,
2794 border, internalFormat);
2795
2796 /* Choose actual texture format */
2797 texImage->TexFormat =
2798 ctx->Driver.ChooseTextureFormat(ctx, internalFormat,
2799 GL_NONE, GL_NONE);
2800 ASSERT(texImage->TexFormat != MESA_FORMAT_NONE);
2801
2802 ASSERT(ctx->Driver.CopyTexImage2D);
2803 ctx->Driver.CopyTexImage2D(ctx, target, level, internalFormat,
2804 x, y, width, height, border);
2805
2806 ASSERT(texImage->TexFormat);
2807
2808 _mesa_set_fetch_functions(texImage, 2);
2809
2810 check_gen_mipmap(ctx, target, texObj, level);
2811
2812 update_fbo_texture(ctx, texObj, face, level);
2813
2814 /* state update */
2815 texObj->_Complete = GL_FALSE;
2816 ctx->NewState |= _NEW_TEXTURE;
2817 }
2818 }
2819 _mesa_unlock_texture(ctx, texObj);
2820 }
2821
2822
2823 void GLAPIENTRY
2824 _mesa_CopyTexSubImage1D( GLenum target, GLint level,
2825 GLint xoffset, GLint x, GLint y, GLsizei width )
2826 {
2827 struct gl_texture_object *texObj;
2828 struct gl_texture_image *texImage;
2829 GLsizei postConvWidth = width;
2830 GLint yoffset = 0;
2831 GLsizei height = 1;
2832
2833 GET_CURRENT_CONTEXT(ctx);
2834 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2835
2836 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2837 _mesa_debug(ctx, "glCopyTexSubImage1D %s %d %d %d %d %d\n",
2838 _mesa_lookup_enum_by_nr(target),
2839 level, xoffset, x, y, width);
2840
2841 if (ctx->NewState & NEW_COPY_TEX_STATE)
2842 _mesa_update_state(ctx);
2843
2844 if (copytexsubimage_error_check1(ctx, 1, target, level))
2845 return;
2846
2847 texObj = _mesa_get_current_tex_object(ctx, target);
2848
2849 _mesa_lock_texture(ctx, texObj);
2850 {
2851 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2852
2853 #if FEATURE_convolve
2854 if (texImage && _mesa_is_color_format(texImage->InternalFormat)) {
2855 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL);
2856 }
2857 #endif
2858
2859 if (copytexsubimage_error_check2(ctx, 1, target, level,
2860 xoffset, 0, 0, postConvWidth, 1,
2861 texImage)) {
2862 /* error was recorded */
2863 }
2864 else {
2865 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2866 xoffset += texImage->Border;
2867
2868 if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y,
2869 &width, &height)) {
2870 ASSERT(ctx->Driver.CopyTexSubImage1D);
2871 ctx->Driver.CopyTexSubImage1D(ctx, target, level,
2872 xoffset, x, y, width);
2873
2874 check_gen_mipmap(ctx, target, texObj, level);
2875
2876 ctx->NewState |= _NEW_TEXTURE;
2877 }
2878 }
2879 }
2880 _mesa_unlock_texture(ctx, texObj);
2881 }
2882
2883
2884
2885 void GLAPIENTRY
2886 _mesa_CopyTexSubImage2D( GLenum target, GLint level,
2887 GLint xoffset, GLint yoffset,
2888 GLint x, GLint y, GLsizei width, GLsizei height )
2889 {
2890 struct gl_texture_object *texObj;
2891 struct gl_texture_image *texImage;
2892 GLsizei postConvWidth = width, postConvHeight = height;
2893 GET_CURRENT_CONTEXT(ctx);
2894 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2895
2896 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2897 _mesa_debug(ctx, "glCopyTexSubImage2D %s %d %d %d %d %d %d %d\n",
2898 _mesa_lookup_enum_by_nr(target),
2899 level, xoffset, yoffset, x, y, width, height);
2900
2901 if (ctx->NewState & NEW_COPY_TEX_STATE)
2902 _mesa_update_state(ctx);
2903
2904 if (copytexsubimage_error_check1(ctx, 2, target, level))
2905 return;
2906
2907 texObj = _mesa_get_current_tex_object(ctx, target);
2908
2909 _mesa_lock_texture(ctx, texObj);
2910 {
2911 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2912
2913 #if FEATURE_convolve
2914 if (texImage && _mesa_is_color_format(texImage->InternalFormat)) {
2915 _mesa_adjust_image_for_convolution(ctx, 2,
2916 &postConvWidth, &postConvHeight);
2917 }
2918 #endif
2919
2920 if (copytexsubimage_error_check2(ctx, 2, target, level,
2921 xoffset, yoffset, 0,
2922 postConvWidth, postConvHeight,
2923 texImage)) {
2924 /* error was recorded */
2925 }
2926 else {
2927 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2928 xoffset += texImage->Border;
2929 yoffset += texImage->Border;
2930
2931 if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y,
2932 &width, &height)) {
2933 ASSERT(ctx->Driver.CopyTexSubImage2D);
2934 ctx->Driver.CopyTexSubImage2D(ctx, target, level, xoffset, yoffset,
2935 x, y, width, height);
2936
2937 check_gen_mipmap(ctx, target, texObj, level);
2938
2939 ctx->NewState |= _NEW_TEXTURE;
2940 }
2941 }
2942 }
2943 _mesa_unlock_texture(ctx, texObj);
2944 }
2945
2946
2947
2948 void GLAPIENTRY
2949 _mesa_CopyTexSubImage3D( GLenum target, GLint level,
2950 GLint xoffset, GLint yoffset, GLint zoffset,
2951 GLint x, GLint y, GLsizei width, GLsizei height )
2952 {
2953 struct gl_texture_object *texObj;
2954 struct gl_texture_image *texImage;
2955 GLsizei postConvWidth = width, postConvHeight = height;
2956 GET_CURRENT_CONTEXT(ctx);
2957 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
2958
2959 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
2960 _mesa_debug(ctx, "glCopyTexSubImage3D %s %d %d %d %d %d %d %d %d\n",
2961 _mesa_lookup_enum_by_nr(target),
2962 level, xoffset, yoffset, zoffset, x, y, width, height);
2963
2964 if (ctx->NewState & NEW_COPY_TEX_STATE)
2965 _mesa_update_state(ctx);
2966
2967 if (copytexsubimage_error_check1(ctx, 3, target, level))
2968 return;
2969
2970 texObj = _mesa_get_current_tex_object(ctx, target);
2971
2972 _mesa_lock_texture(ctx, texObj);
2973 {
2974 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
2975
2976 #if FEATURE_convolve
2977 if (texImage && _mesa_is_color_format(texImage->InternalFormat)) {
2978 _mesa_adjust_image_for_convolution(ctx, 2,
2979 &postConvWidth, &postConvHeight);
2980 }
2981 #endif
2982
2983 if (copytexsubimage_error_check2(ctx, 3, target, level, xoffset, yoffset,
2984 zoffset, postConvWidth, postConvHeight,
2985 texImage)) {
2986 /* error was recored */
2987 }
2988 else {
2989 /* If we have a border, xoffset=-1 is legal. Bias by border width */
2990 xoffset += texImage->Border;
2991 yoffset += texImage->Border;
2992 zoffset += texImage->Border;
2993
2994 if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y,
2995 &width, &height)) {
2996 ASSERT(ctx->Driver.CopyTexSubImage3D);
2997 ctx->Driver.CopyTexSubImage3D(ctx, target, level,
2998 xoffset, yoffset, zoffset,
2999 x, y, width, height);
3000
3001 check_gen_mipmap(ctx, target, texObj, level);
3002
3003 ctx->NewState |= _NEW_TEXTURE;
3004 }
3005 }
3006 }
3007 _mesa_unlock_texture(ctx, texObj);
3008 }
3009
3010
3011
3012
3013 /**********************************************************************/
3014 /****** Compressed Textures ******/
3015 /**********************************************************************/
3016
3017
3018 /**
3019 * Return expected size of a compressed texture.
3020 */
3021 static GLuint
3022 compressed_tex_size(GLsizei width, GLsizei height, GLsizei depth,
3023 GLenum glformat)
3024 {
3025 gl_format mesaFormat = _mesa_glenum_to_compressed_format(glformat);
3026 return _mesa_format_image_size(mesaFormat, width, height, depth);
3027 }
3028
3029
3030 /*
3031 * Return compressed texture block size, in pixels.
3032 */
3033 static void
3034 get_compressed_block_size(GLenum glformat, GLuint *bw, GLuint *bh)
3035 {
3036 gl_format mesaFormat = _mesa_glenum_to_compressed_format(glformat);
3037 _mesa_get_format_block_size(mesaFormat, bw, bh);
3038 }
3039
3040
3041 /**
3042 * Error checking for glCompressedTexImage[123]D().
3043 * \return error code or GL_NO_ERROR.
3044 */
3045 static GLenum
3046 compressed_texture_error_check(GLcontext *ctx, GLint dimensions,
3047 GLenum target, GLint level,
3048 GLenum internalFormat, GLsizei width,
3049 GLsizei height, GLsizei depth, GLint border,
3050 GLsizei imageSize)
3051 {
3052 GLint expectedSize, maxLevels = 0, maxTextureSize;
3053
3054 if (dimensions == 1) {
3055 /* 1D compressed textures not allowed */
3056 return GL_INVALID_ENUM;
3057 }
3058 else if (dimensions == 2) {
3059 if (target == GL_PROXY_TEXTURE_2D) {
3060 maxLevels = ctx->Const.MaxTextureLevels;
3061 }
3062 else if (target == GL_TEXTURE_2D) {
3063 maxLevels = ctx->Const.MaxTextureLevels;
3064 }
3065 else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
3066 if (!ctx->Extensions.ARB_texture_cube_map)
3067 return GL_INVALID_ENUM; /*target*/
3068 maxLevels = ctx->Const.MaxCubeTextureLevels;
3069 }
3070 else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3071 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
3072 if (!ctx->Extensions.ARB_texture_cube_map)
3073 return GL_INVALID_ENUM; /*target*/
3074 maxLevels = ctx->Const.MaxCubeTextureLevels;
3075 }
3076 else {
3077 return GL_INVALID_ENUM; /*target*/
3078 }
3079 }
3080 else if (dimensions == 3) {
3081 /* 3D compressed textures not allowed */
3082 return GL_INVALID_ENUM;
3083 }
3084
3085 maxTextureSize = 1 << (maxLevels - 1);
3086
3087 /* This will detect any invalid internalFormat value */
3088 if (!_mesa_is_compressed_format(ctx, internalFormat))
3089 return GL_INVALID_ENUM;
3090
3091 /* This should really never fail */
3092 if (_mesa_base_tex_format(ctx, internalFormat) < 0)
3093 return GL_INVALID_ENUM;
3094
3095 if (border != 0)
3096 return GL_INVALID_VALUE;
3097
3098 /*
3099 * XXX We should probably use the proxy texture error check function here.
3100 */
3101 if (width < 1 || width > maxTextureSize ||
3102 (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(width)))
3103 return GL_INVALID_VALUE;
3104
3105 if ((height < 1 || height > maxTextureSize ||
3106 (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(height)))
3107 && dimensions > 1)
3108 return GL_INVALID_VALUE;
3109
3110 if ((depth < 1 || depth > maxTextureSize ||
3111 (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(depth)))
3112 && dimensions > 2)
3113 return GL_INVALID_VALUE;
3114
3115 /* For cube map, width must equal height */
3116 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3117 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB && width != height)
3118 return GL_INVALID_VALUE;
3119
3120 if (level < 0 || level >= maxLevels)
3121 return GL_INVALID_VALUE;
3122
3123 expectedSize = compressed_tex_size(width, height, depth, internalFormat);
3124 if (expectedSize != imageSize)
3125 return GL_INVALID_VALUE;
3126
3127 #if FEATURE_EXT_texture_sRGB
3128 if ((internalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT ||
3129 internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT ||
3130 internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT ||
3131 internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT)
3132 && border != 0) {
3133 return GL_INVALID_OPERATION;
3134 }
3135 #endif
3136
3137 return GL_NO_ERROR;
3138 }
3139
3140
3141 /**
3142 * Error checking for glCompressedTexSubImage[123]D().
3143 * \warning There are some bad assumptions here about the size of compressed
3144 * texture tiles (multiple of 4) used to test the validity of the
3145 * offset and size parameters.
3146 * \return error code or GL_NO_ERROR.
3147 */
3148 static GLenum
3149 compressed_subtexture_error_check(GLcontext *ctx, GLint dimensions,
3150 GLenum target, GLint level,
3151 GLint xoffset, GLint yoffset, GLint zoffset,
3152 GLsizei width, GLsizei height, GLsizei depth,
3153 GLenum format, GLsizei imageSize)
3154 {
3155 GLint expectedSize, maxLevels = 0, maxTextureSize;
3156 GLuint bw, bh;
3157 (void) zoffset;
3158
3159 if (dimensions == 1) {
3160 /* 1D compressed textures not allowed */
3161 return GL_INVALID_ENUM;
3162 }
3163 else if (dimensions == 2) {
3164 if (target == GL_PROXY_TEXTURE_2D) {
3165 maxLevels = ctx->Const.MaxTextureLevels;
3166 }
3167 else if (target == GL_TEXTURE_2D) {
3168 maxLevels = ctx->Const.MaxTextureLevels;
3169 }
3170 else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) {
3171 if (!ctx->Extensions.ARB_texture_cube_map)
3172 return GL_INVALID_ENUM; /*target*/
3173 maxLevels = ctx->Const.MaxCubeTextureLevels;
3174 }
3175 else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3176 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) {
3177 if (!ctx->Extensions.ARB_texture_cube_map)
3178 return GL_INVALID_ENUM; /*target*/
3179 maxLevels = ctx->Const.MaxCubeTextureLevels;
3180 }
3181 else {
3182 return GL_INVALID_ENUM; /*target*/
3183 }
3184 }
3185 else if (dimensions == 3) {
3186 /* 3D compressed textures not allowed */
3187 return GL_INVALID_ENUM;
3188 }
3189
3190 maxTextureSize = 1 << (maxLevels - 1);
3191
3192 /* this will catch any invalid compressed format token */
3193 if (!_mesa_is_compressed_format(ctx, format))
3194 return GL_INVALID_ENUM;
3195
3196 if (width < 1 || width > maxTextureSize)
3197 return GL_INVALID_VALUE;
3198
3199 if ((height < 1 || height > maxTextureSize)
3200 && dimensions > 1)
3201 return GL_INVALID_VALUE;
3202
3203 if (level < 0 || level >= maxLevels)
3204 return GL_INVALID_VALUE;
3205
3206 /*
3207 * do checks which depend on compression block size
3208 */
3209 get_compressed_block_size(format, &bw, &bh);
3210
3211 if ((xoffset % bw != 0) || (yoffset % bh != 0))
3212 return GL_INVALID_VALUE;
3213
3214 if ((width % bw != 0) && width != 2 && width != 1)
3215 return GL_INVALID_VALUE;
3216
3217 if ((height % bh != 0) && height != 2 && height != 1)
3218 return GL_INVALID_VALUE;
3219
3220 expectedSize = compressed_tex_size(width, height, depth, format);
3221 if (expectedSize != imageSize)
3222 return GL_INVALID_VALUE;
3223
3224 return GL_NO_ERROR;
3225 }
3226
3227
3228 /**
3229 * Do second part of glCompressedTexSubImage error checking.
3230 * \return GL_TRUE if error found, GL_FALSE otherwise.
3231 */
3232 static GLboolean
3233 compressed_subtexture_error_check2(GLcontext *ctx, GLuint dims,
3234 GLsizei width, GLsizei height,
3235 GLsizei depth, GLenum format,
3236 struct gl_texture_image *texImage)
3237 {
3238
3239 if ((GLint) format != texImage->InternalFormat) {
3240 _mesa_error(ctx, GL_INVALID_OPERATION,
3241 "glCompressedTexSubImage%uD(format=0x%x)", dims, format);
3242 return GL_TRUE;
3243 }
3244
3245 if (((width == 1 || width == 2) &&
3246 width != (GLsizei) texImage->Width) ||
3247 (width > (GLsizei) texImage->Width)) {
3248 _mesa_error(ctx, GL_INVALID_VALUE,
3249 "glCompressedTexSubImage%uD(width=%d)", dims, width);
3250 return GL_TRUE;
3251 }
3252
3253 if (dims >= 2) {
3254 if (((height == 1 || height == 2) &&
3255 height != (GLsizei) texImage->Height) ||
3256 (height > (GLsizei) texImage->Height)) {
3257 _mesa_error(ctx, GL_INVALID_VALUE,
3258 "glCompressedTexSubImage%uD(height=%d)", dims, height);
3259 return GL_TRUE;
3260 }
3261 }
3262
3263 if (dims >= 3) {
3264 if (((depth == 1 || depth == 2) &&
3265 depth != (GLsizei) texImage->Depth) ||
3266 (depth > (GLsizei) texImage->Depth)) {
3267 _mesa_error(ctx, GL_INVALID_VALUE,
3268 "glCompressedTexSubImage%uD(depth=%d)", dims, depth);
3269 return GL_TRUE;
3270 }
3271 }
3272
3273 return GL_FALSE;
3274 }
3275
3276
3277
3278 void GLAPIENTRY
3279 _mesa_CompressedTexImage1DARB(GLenum target, GLint level,
3280 GLenum internalFormat, GLsizei width,
3281 GLint border, GLsizei imageSize,
3282 const GLvoid *data)
3283 {
3284 GET_CURRENT_CONTEXT(ctx);
3285 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3286
3287 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
3288 _mesa_debug(ctx, "glCompressedTexImage1DARB %s %d %s %d %d %d %p\n",
3289 _mesa_lookup_enum_by_nr(target), level,
3290 _mesa_lookup_enum_by_nr(internalFormat),
3291 width, border, imageSize, data);
3292
3293 if (target == GL_TEXTURE_1D) {
3294 /* non-proxy target */
3295 struct gl_texture_object *texObj;
3296 struct gl_texture_image *texImage;
3297 GLenum error = compressed_texture_error_check(ctx, 1, target, level,
3298 internalFormat, width, 1, 1, border, imageSize);
3299 if (error) {
3300 _mesa_error(ctx, error, "glCompressedTexImage1D");
3301 return;
3302 }
3303
3304 texObj = _mesa_get_current_tex_object(ctx, target);
3305
3306 _mesa_lock_texture(ctx, texObj);
3307 {
3308 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
3309 if (!texImage) {
3310 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1D");
3311 }
3312 else {
3313 if (texImage->Data) {
3314 ctx->Driver.FreeTexImageData( ctx, texImage );
3315 }
3316 ASSERT(texImage->Data == NULL);
3317
3318 _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
3319 border, internalFormat);
3320
3321 /* Choose actual texture format */
3322 texImage->TexFormat =
3323 ctx->Driver.ChooseTextureFormat(ctx, internalFormat,
3324 GL_NONE, GL_NONE);
3325 ASSERT(texImage->TexFormat != MESA_FORMAT_NONE);
3326
3327 ASSERT(ctx->Driver.CompressedTexImage1D);
3328 ctx->Driver.CompressedTexImage1D(ctx, target, level,
3329 internalFormat, width, border,
3330 imageSize, data,
3331 texObj, texImage);
3332
3333 _mesa_set_fetch_functions(texImage, 1);
3334
3335 check_gen_mipmap(ctx, target, texObj, level);
3336
3337 /* state update */
3338 texObj->_Complete = GL_FALSE;
3339 ctx->NewState |= _NEW_TEXTURE;
3340 }
3341 }
3342 _mesa_unlock_texture(ctx, texObj);
3343 }
3344 else if (target == GL_PROXY_TEXTURE_1D) {
3345 /* Proxy texture: check for errors and update proxy state */
3346 GLenum error = compressed_texture_error_check(ctx, 1, target, level,
3347 internalFormat, width, 1, 1, border, imageSize);
3348 if (!error) {
3349 ASSERT(ctx->Driver.TestProxyTexImage);
3350 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3351 internalFormat, GL_NONE, GL_NONE,
3352 width, 1, 1, border);
3353 }
3354 if (error) {
3355 /* if error, clear all proxy texture image parameters */
3356 struct gl_texture_image *texImage;
3357 texImage = _mesa_get_proxy_tex_image(ctx, target, level);
3358 if (texImage)
3359 clear_teximage_fields(texImage);
3360 }
3361 else {
3362 /* store the teximage parameters */
3363 struct gl_texture_object *texObj;
3364 struct gl_texture_image *texImage;
3365
3366 texObj = _mesa_get_current_tex_object(ctx, target);
3367
3368 _mesa_lock_texture(ctx, texObj);
3369 {
3370 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3371 _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1,
3372 border, internalFormat);
3373 }
3374 _mesa_unlock_texture(ctx, texObj);
3375 }
3376 }
3377 else {
3378 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1D(target)");
3379 return;
3380 }
3381 }
3382
3383
3384 void GLAPIENTRY
3385 _mesa_CompressedTexImage2DARB(GLenum target, GLint level,
3386 GLenum internalFormat, GLsizei width,
3387 GLsizei height, GLint border, GLsizei imageSize,
3388 const GLvoid *data)
3389 {
3390 GET_CURRENT_CONTEXT(ctx);
3391 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3392
3393 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
3394 _mesa_debug(ctx, "glCompressedTexImage2DARB %s %d %s %d %d %d %d %p\n",
3395 _mesa_lookup_enum_by_nr(target), level,
3396 _mesa_lookup_enum_by_nr(internalFormat),
3397 width, height, border, imageSize, data);
3398
3399 if (target == GL_TEXTURE_2D ||
3400 (ctx->Extensions.ARB_texture_cube_map &&
3401 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB &&
3402 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) {
3403 /* non-proxy target */
3404 struct gl_texture_object *texObj;
3405 struct gl_texture_image *texImage;
3406
3407 GLenum error = compressed_texture_error_check(ctx, 2, target, level,
3408 internalFormat, width, height, 1, border, imageSize);
3409 if (error) {
3410 _mesa_error(ctx, error, "glCompressedTexImage2D");
3411 return;
3412 }
3413
3414 texObj = _mesa_get_current_tex_object(ctx, target);
3415
3416 _mesa_lock_texture(ctx, texObj);
3417 {
3418 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
3419 if (!texImage) {
3420 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D");
3421 }
3422 else {
3423 if (texImage->Data) {
3424 ctx->Driver.FreeTexImageData( ctx, texImage );
3425 }
3426 ASSERT(texImage->Data == NULL);
3427
3428 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
3429 border, internalFormat);
3430
3431 /* Choose actual texture format */
3432 texImage->TexFormat =
3433 ctx->Driver.ChooseTextureFormat(ctx, internalFormat,
3434 GL_NONE, GL_NONE);
3435 ASSERT(texImage->TexFormat != MESA_FORMAT_NONE);
3436
3437 ASSERT(ctx->Driver.CompressedTexImage2D);
3438 ctx->Driver.CompressedTexImage2D(ctx, target, level,
3439 internalFormat, width, height,
3440 border, imageSize, data,
3441 texObj, texImage);
3442
3443 _mesa_set_fetch_functions(texImage, 2);
3444
3445 check_gen_mipmap(ctx, target, texObj, level);
3446
3447 /* state update */
3448 texObj->_Complete = GL_FALSE;
3449 ctx->NewState |= _NEW_TEXTURE;
3450 }
3451 }
3452 _mesa_unlock_texture(ctx, texObj);
3453 }
3454 else if (target == GL_PROXY_TEXTURE_2D ||
3455 (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB &&
3456 ctx->Extensions.ARB_texture_cube_map)) {
3457 /* Proxy texture: check for errors and update proxy state */
3458 GLenum error = compressed_texture_error_check(ctx, 2, target, level,
3459 internalFormat, width, height, 1, border, imageSize);
3460 if (!error) {
3461 ASSERT(ctx->Driver.TestProxyTexImage);
3462 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3463 internalFormat, GL_NONE, GL_NONE,
3464 width, height, 1, border);
3465 }
3466 if (error) {
3467 /* if error, clear all proxy texture image parameters */
3468 struct gl_texture_image *texImage;
3469 texImage = _mesa_get_proxy_tex_image(ctx, target, level);
3470 if (texImage)
3471 clear_teximage_fields(texImage);
3472 }
3473 else {
3474 /* store the teximage parameters */
3475 struct gl_texture_object *texObj;
3476 struct gl_texture_image *texImage;
3477
3478 texObj = _mesa_get_current_tex_object(ctx, target);
3479
3480 _mesa_lock_texture(ctx, texObj);
3481 {
3482 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3483 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1,
3484 border, internalFormat);
3485 }
3486 _mesa_unlock_texture(ctx, texObj);
3487 }
3488 }
3489 else {
3490 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2D(target)");
3491 return;
3492 }
3493 }
3494
3495
3496 void GLAPIENTRY
3497 _mesa_CompressedTexImage3DARB(GLenum target, GLint level,
3498 GLenum internalFormat, GLsizei width,
3499 GLsizei height, GLsizei depth, GLint border,
3500 GLsizei imageSize, const GLvoid *data)
3501 {
3502 GET_CURRENT_CONTEXT(ctx);
3503 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3504
3505 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
3506 _mesa_debug(ctx, "glCompressedTexImage3DARB %s %d %s %d %d %d %d %d %p\n",
3507 _mesa_lookup_enum_by_nr(target), level,
3508 _mesa_lookup_enum_by_nr(internalFormat),
3509 width, height, depth, border, imageSize, data);
3510
3511 if (target == GL_TEXTURE_3D) {
3512 /* non-proxy target */
3513 struct gl_texture_object *texObj;
3514 struct gl_texture_image *texImage;
3515 GLenum error = compressed_texture_error_check(ctx, 3, target, level,
3516 internalFormat, width, height, depth, border, imageSize);
3517 if (error) {
3518 _mesa_error(ctx, error, "glCompressedTexImage3D");
3519 return;
3520 }
3521
3522 texObj = _mesa_get_current_tex_object(ctx, target);
3523
3524 _mesa_lock_texture(ctx, texObj);
3525 {
3526 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
3527 if (!texImage) {
3528 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3D");
3529 }
3530 else {
3531 if (texImage->Data) {
3532 ctx->Driver.FreeTexImageData( ctx, texImage );
3533 }
3534 ASSERT(texImage->Data == NULL);
3535
3536 _mesa_init_teximage_fields(ctx, target, texImage,
3537 width, height, depth,
3538 border, internalFormat);
3539
3540 /* Choose actual texture format */
3541 texImage->TexFormat =
3542 ctx->Driver.ChooseTextureFormat(ctx, internalFormat,
3543 GL_NONE, GL_NONE);
3544 ASSERT(texImage->TexFormat != MESA_FORMAT_NONE);
3545
3546 ASSERT(ctx->Driver.CompressedTexImage3D);
3547 ctx->Driver.CompressedTexImage3D(ctx, target, level,
3548 internalFormat,
3549 width, height, depth,
3550 border, imageSize, data,
3551 texObj, texImage);
3552
3553 _mesa_set_fetch_functions(texImage, 3);
3554
3555 check_gen_mipmap(ctx, target, texObj, level);
3556
3557 /* state update */
3558 texObj->_Complete = GL_FALSE;
3559 ctx->NewState |= _NEW_TEXTURE;
3560 }
3561 }
3562 _mesa_unlock_texture(ctx, texObj);
3563 }
3564 else if (target == GL_PROXY_TEXTURE_3D) {
3565 /* Proxy texture: check for errors and update proxy state */
3566 GLenum error = compressed_texture_error_check(ctx, 3, target, level,
3567 internalFormat, width, height, depth, border, imageSize);
3568 if (!error) {
3569 ASSERT(ctx->Driver.TestProxyTexImage);
3570 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level,
3571 internalFormat, GL_NONE, GL_NONE,
3572 width, height, depth, border);
3573 }
3574 if (error) {
3575 /* if error, clear all proxy texture image parameters */
3576 struct gl_texture_image *texImage;
3577 texImage = _mesa_get_proxy_tex_image(ctx, target, level);
3578 if (texImage)
3579 clear_teximage_fields(texImage);
3580 }
3581 else {
3582 /* store the teximage parameters */
3583 struct gl_texture_object *texObj;
3584 struct gl_texture_image *texImage;
3585
3586 texObj = _mesa_get_current_tex_object(ctx, target);
3587
3588 _mesa_lock_texture(ctx, texObj);
3589 {
3590 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3591 _mesa_init_teximage_fields(ctx, target, texImage, width, height,
3592 depth, border, internalFormat);
3593 }
3594 _mesa_unlock_texture(ctx, texObj);
3595 }
3596 }
3597 else {
3598 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3D(target)");
3599 return;
3600 }
3601 }
3602
3603
3604 /**
3605 * Common helper for glCompressedTexSubImage1/2/3D().
3606 */
3607 static void
3608 compressed_tex_sub_image(GLuint dims, GLenum target, GLint level,
3609 GLint xoffset, GLint yoffset, GLint zoffset,
3610 GLsizei width, GLsizei height, GLsizei depth,
3611 GLenum format, GLsizei imageSize, const GLvoid *data)
3612 {
3613 struct gl_texture_object *texObj;
3614 struct gl_texture_image *texImage;
3615 GLenum error;
3616 GET_CURRENT_CONTEXT(ctx);
3617 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx);
3618
3619 error = compressed_subtexture_error_check(ctx, dims, target, level,
3620 xoffset, 0, 0, /* pos */
3621 width, height, depth, /* size */
3622 format, imageSize);
3623 if (error) {
3624 _mesa_error(ctx, error, "glCompressedTexSubImage%uD", dims);
3625 return;
3626 }
3627
3628 texObj = _mesa_get_current_tex_object(ctx, target);
3629
3630 _mesa_lock_texture(ctx, texObj);
3631 {
3632 texImage = _mesa_select_tex_image(ctx, texObj, target, level);
3633 assert(texImage);
3634
3635 if (compressed_subtexture_error_check2(ctx, dims, width, height, depth,
3636 format, texImage)) {
3637 /* error was recorded */
3638 }
3639 else if (width > 0 && height > 0 && depth > 0) {
3640 switch (dims) {
3641 case 1:
3642 if (ctx->Driver.CompressedTexSubImage1D) {
3643 ctx->Driver.CompressedTexSubImage1D(ctx, target, level,
3644 xoffset, width,
3645 format, imageSize, data,
3646 texObj, texImage);
3647 }
3648 break;
3649 case 2:
3650 if (ctx->Driver.CompressedTexSubImage2D) {
3651 ctx->Driver.CompressedTexSubImage2D(ctx, target, level,
3652 xoffset, yoffset,
3653 width, height,
3654 format, imageSize, data,
3655 texObj, texImage);
3656 }
3657 break;
3658 case 3:
3659 if (ctx->Driver.CompressedTexSubImage3D) {
3660 ctx->Driver.CompressedTexSubImage3D(ctx, target, level,
3661 xoffset, yoffset, zoffset,
3662 width, height, depth,
3663 format, imageSize, data,
3664 texObj, texImage);
3665 }
3666 break;
3667 default:
3668 ;
3669 }
3670
3671 check_gen_mipmap(ctx, target, texObj, level);
3672
3673 ctx->NewState |= _NEW_TEXTURE;
3674 }
3675 }
3676 _mesa_unlock_texture(ctx, texObj);
3677 }
3678
3679
3680 void GLAPIENTRY
3681 _mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset,
3682 GLsizei width, GLenum format,
3683 GLsizei imageSize, const GLvoid *data)
3684 {
3685 compressed_tex_sub_image(1, target, level, xoffset, 0, 0, width, 1, 1,
3686 format, imageSize, data);
3687 }
3688
3689
3690 void GLAPIENTRY
3691 _mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset,
3692 GLint yoffset, GLsizei width, GLsizei height,
3693 GLenum format, GLsizei imageSize,
3694 const GLvoid *data)
3695 {
3696 compressed_tex_sub_image(2, target, level, xoffset, yoffset, 0,
3697 width, height, 1, format, imageSize, data);
3698 }
3699
3700
3701 void GLAPIENTRY
3702 _mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset,
3703 GLint yoffset, GLint zoffset, GLsizei width,
3704 GLsizei height, GLsizei depth, GLenum format,
3705 GLsizei imageSize, const GLvoid *data)
3706 {
3707 compressed_tex_sub_image(3, target, level, xoffset, yoffset, zoffset,
3708 width, height, depth, format, imageSize, data);
3709 }
3710
3711