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