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