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