• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23  * OTHER DEALINGS IN THE SOFTWARE.
24  */
25 
26 
27 /**
28  * \file teximage.c
29  * Texture image-related functions.
30  */
31 
32 #include <stdbool.h>
33 #include "glheader.h"
34 #include "bufferobj.h"
35 #include "context.h"
36 #include "enums.h"
37 #include "fbobject.h"
38 #include "framebuffer.h"
39 #include "hash.h"
40 #include "image.h"
41 #include "imports.h"
42 #include "macros.h"
43 #include "mipmap.h"
44 #include "multisample.h"
45 #include "pixelstore.h"
46 #include "state.h"
47 #include "texcompress.h"
48 #include "texcompress_cpal.h"
49 #include "teximage.h"
50 #include "texobj.h"
51 #include "texstate.h"
52 #include "texstorage.h"
53 #include "textureview.h"
54 #include "mtypes.h"
55 #include "glformats.h"
56 #include "texstore.h"
57 #include "pbo.h"
58 
59 
60 /**
61  * State changes which we care about for glCopyTex[Sub]Image() calls.
62  * In particular, we care about pixel transfer state and buffer state
63  * (such as glReadBuffer to make sure we read from the right renderbuffer).
64  */
65 #define NEW_COPY_TEX_STATE (_NEW_BUFFERS | _NEW_PIXEL)
66 
67 /**
68  * Returns a corresponding internal floating point format for a given base
69  * format as specifed by OES_texture_float. In case of GL_FLOAT, the internal
70  * format needs to be a 32 bit component and in case of GL_HALF_FLOAT_OES it
71  * needs to be a 16 bit component.
72  *
73  * For example, given base format GL_RGBA, type GL_FLOAT return GL_RGBA32F_ARB.
74  */
75 static GLenum
adjust_for_oes_float_texture(const struct gl_context * ctx,GLenum format,GLenum type)76 adjust_for_oes_float_texture(const struct gl_context *ctx,
77                              GLenum format, GLenum type)
78 {
79    switch (type) {
80    case GL_FLOAT:
81       if (ctx->Extensions.OES_texture_float) {
82          switch (format) {
83          case GL_RGBA:
84             return GL_RGBA32F;
85          case GL_RGB:
86             return GL_RGB32F;
87          case GL_ALPHA:
88             return GL_ALPHA32F_ARB;
89          case GL_LUMINANCE:
90             return GL_LUMINANCE32F_ARB;
91          case GL_LUMINANCE_ALPHA:
92             return GL_LUMINANCE_ALPHA32F_ARB;
93          default:
94             break;
95          }
96       }
97       break;
98 
99    case GL_HALF_FLOAT_OES:
100       if (ctx->Extensions.OES_texture_half_float) {
101          switch (format) {
102          case GL_RGBA:
103             return GL_RGBA16F;
104          case GL_RGB:
105             return GL_RGB16F;
106          case GL_ALPHA:
107             return GL_ALPHA16F_ARB;
108          case GL_LUMINANCE:
109             return GL_LUMINANCE16F_ARB;
110          case GL_LUMINANCE_ALPHA:
111             return GL_LUMINANCE_ALPHA16F_ARB;
112          default:
113             break;
114          }
115       }
116       break;
117 
118    default:
119       break;
120    }
121 
122    return format;
123 }
124 
125 
126 /**
127  * Install gl_texture_image in a gl_texture_object according to the target
128  * and level parameters.
129  *
130  * \param tObj texture object.
131  * \param target texture target.
132  * \param level image level.
133  * \param texImage texture image.
134  */
135 static void
set_tex_image(struct gl_texture_object * tObj,GLenum target,GLint level,struct gl_texture_image * texImage)136 set_tex_image(struct gl_texture_object *tObj,
137               GLenum target, GLint level,
138               struct gl_texture_image *texImage)
139 {
140    const GLuint face = _mesa_tex_target_to_face(target);
141 
142    assert(tObj);
143    assert(texImage);
144    if (target == GL_TEXTURE_RECTANGLE_NV || target == GL_TEXTURE_EXTERNAL_OES)
145       assert(level == 0);
146 
147    tObj->Image[face][level] = texImage;
148 
149    /* Set the 'back' pointer */
150    texImage->TexObject = tObj;
151    texImage->Level = level;
152    texImage->Face = face;
153 }
154 
155 
156 /**
157  * Allocate a texture image structure.
158  *
159  * Called via ctx->Driver.NewTextureImage() unless overriden by a device
160  * driver.
161  *
162  * \return a pointer to gl_texture_image struct with all fields initialized to
163  * zero.
164  */
165 struct gl_texture_image *
_mesa_new_texture_image(struct gl_context * ctx)166 _mesa_new_texture_image( struct gl_context *ctx )
167 {
168    (void) ctx;
169    return CALLOC_STRUCT(gl_texture_image);
170 }
171 
172 
173 /**
174  * Free a gl_texture_image and associated data.
175  * This function is a fallback called via ctx->Driver.DeleteTextureImage().
176  *
177  * \param texImage texture image.
178  *
179  * Free the texture image structure and the associated image data.
180  */
181 void
_mesa_delete_texture_image(struct gl_context * ctx,struct gl_texture_image * texImage)182 _mesa_delete_texture_image(struct gl_context *ctx,
183                            struct gl_texture_image *texImage)
184 {
185    /* Free texImage->Data and/or any other driver-specific texture
186     * image storage.
187     */
188    assert(ctx->Driver.FreeTextureImageBuffer);
189    ctx->Driver.FreeTextureImageBuffer( ctx, texImage );
190    free(texImage);
191 }
192 
193 
194 /**
195  * Test if a target is a proxy target.
196  *
197  * \param target texture target.
198  *
199  * \return GL_TRUE if the target is a proxy target, GL_FALSE otherwise.
200  */
201 GLboolean
_mesa_is_proxy_texture(GLenum target)202 _mesa_is_proxy_texture(GLenum target)
203 {
204    unsigned i;
205    static const GLenum targets[] = {
206       GL_PROXY_TEXTURE_1D,
207       GL_PROXY_TEXTURE_2D,
208       GL_PROXY_TEXTURE_3D,
209       GL_PROXY_TEXTURE_CUBE_MAP,
210       GL_PROXY_TEXTURE_RECTANGLE,
211       GL_PROXY_TEXTURE_1D_ARRAY,
212       GL_PROXY_TEXTURE_2D_ARRAY,
213       GL_PROXY_TEXTURE_CUBE_MAP_ARRAY,
214       GL_PROXY_TEXTURE_2D_MULTISAMPLE,
215       GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY
216    };
217    /*
218     * NUM_TEXTURE_TARGETS should match number of terms above, except there's no
219     * proxy for GL_TEXTURE_BUFFER and GL_TEXTURE_EXTERNAL_OES.
220     */
221    STATIC_ASSERT(NUM_TEXTURE_TARGETS == ARRAY_SIZE(targets) + 2);
222 
223    for (i = 0; i < ARRAY_SIZE(targets); ++i)
224       if (target == targets[i])
225          return GL_TRUE;
226    return GL_FALSE;
227 }
228 
229 
230 /**
231  * Test if a target is an array target.
232  *
233  * \param target texture target.
234  *
235  * \return true if the target is an array target, false otherwise.
236  */
237 bool
_mesa_is_array_texture(GLenum target)238 _mesa_is_array_texture(GLenum target)
239 {
240    switch (target) {
241    case GL_TEXTURE_1D_ARRAY:
242    case GL_TEXTURE_2D_ARRAY:
243    case GL_TEXTURE_CUBE_MAP_ARRAY:
244    case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
245       return true;
246    default:
247       return false;
248    };
249 }
250 
251 /**
252  * Test if a target is a cube map.
253  *
254  * \param target texture target.
255  *
256  * \return true if the target is a cube map, false otherwise.
257  */
258 bool
_mesa_is_cube_map_texture(GLenum target)259 _mesa_is_cube_map_texture(GLenum target)
260 {
261    switch(target) {
262    case GL_TEXTURE_CUBE_MAP:
263    case GL_TEXTURE_CUBE_MAP_ARRAY:
264       return true;
265    default:
266       return false;
267    }
268 }
269 
270 /**
271  * Return the proxy target which corresponds to the given texture target
272  */
273 static GLenum
proxy_target(GLenum target)274 proxy_target(GLenum target)
275 {
276    switch (target) {
277    case GL_TEXTURE_1D:
278    case GL_PROXY_TEXTURE_1D:
279       return GL_PROXY_TEXTURE_1D;
280    case GL_TEXTURE_2D:
281    case GL_PROXY_TEXTURE_2D:
282       return GL_PROXY_TEXTURE_2D;
283    case GL_TEXTURE_3D:
284    case GL_PROXY_TEXTURE_3D:
285       return GL_PROXY_TEXTURE_3D;
286    case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
287    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
288    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
289    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
290    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
291    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
292    case GL_TEXTURE_CUBE_MAP:
293    case GL_PROXY_TEXTURE_CUBE_MAP:
294       return GL_PROXY_TEXTURE_CUBE_MAP;
295    case GL_TEXTURE_RECTANGLE_NV:
296    case GL_PROXY_TEXTURE_RECTANGLE_NV:
297       return GL_PROXY_TEXTURE_RECTANGLE_NV;
298    case GL_TEXTURE_1D_ARRAY_EXT:
299    case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
300       return GL_PROXY_TEXTURE_1D_ARRAY_EXT;
301    case GL_TEXTURE_2D_ARRAY_EXT:
302    case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
303       return GL_PROXY_TEXTURE_2D_ARRAY_EXT;
304    case GL_TEXTURE_CUBE_MAP_ARRAY:
305    case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
306       return GL_PROXY_TEXTURE_CUBE_MAP_ARRAY;
307    case GL_TEXTURE_2D_MULTISAMPLE:
308    case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
309       return GL_PROXY_TEXTURE_2D_MULTISAMPLE;
310    case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
311    case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
312       return GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY;
313    default:
314       _mesa_problem(NULL, "unexpected target in proxy_target()");
315       return 0;
316    }
317 }
318 
319 
320 
321 
322 /**
323  * Get a texture image pointer from a texture object, given a texture
324  * target and mipmap level.  The target and level parameters should
325  * have already been error-checked.
326  *
327  * \param texObj texture unit.
328  * \param target texture target.
329  * \param level image level.
330  *
331  * \return pointer to the texture image structure, or NULL on failure.
332  */
333 struct gl_texture_image *
_mesa_select_tex_image(const struct gl_texture_object * texObj,GLenum target,GLint level)334 _mesa_select_tex_image(const struct gl_texture_object *texObj,
335 		                 GLenum target, GLint level)
336 {
337    const GLuint face = _mesa_tex_target_to_face(target);
338 
339    assert(texObj);
340    assert(level >= 0);
341    assert(level < MAX_TEXTURE_LEVELS);
342 
343    return texObj->Image[face][level];
344 }
345 
346 
347 /**
348  * Like _mesa_select_tex_image() but if the image doesn't exist, allocate
349  * it and install it.  Only return NULL if passed a bad parameter or run
350  * out of memory.
351  */
352 struct gl_texture_image *
_mesa_get_tex_image(struct gl_context * ctx,struct gl_texture_object * texObj,GLenum target,GLint level)353 _mesa_get_tex_image(struct gl_context *ctx, struct gl_texture_object *texObj,
354                     GLenum target, GLint level)
355 {
356    struct gl_texture_image *texImage;
357 
358    if (!texObj)
359       return NULL;
360 
361    texImage = _mesa_select_tex_image(texObj, target, level);
362    if (!texImage) {
363       texImage = ctx->Driver.NewTextureImage(ctx);
364       if (!texImage) {
365          _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture image allocation");
366          return NULL;
367       }
368 
369       set_tex_image(texObj, target, level, texImage);
370    }
371 
372    return texImage;
373 }
374 
375 
376 /**
377  * Return pointer to the specified proxy texture image.
378  * Note that proxy textures are per-context, not per-texture unit.
379  * \return pointer to texture image or NULL if invalid target, invalid
380  *         level, or out of memory.
381  */
382 static struct gl_texture_image *
get_proxy_tex_image(struct gl_context * ctx,GLenum target,GLint level)383 get_proxy_tex_image(struct gl_context *ctx, GLenum target, GLint level)
384 {
385    struct gl_texture_image *texImage;
386    GLuint texIndex;
387 
388    if (level < 0)
389       return NULL;
390 
391    switch (target) {
392    case GL_PROXY_TEXTURE_1D:
393       if (level >= ctx->Const.MaxTextureLevels)
394          return NULL;
395       texIndex = TEXTURE_1D_INDEX;
396       break;
397    case GL_PROXY_TEXTURE_2D:
398       if (level >= ctx->Const.MaxTextureLevels)
399          return NULL;
400       texIndex = TEXTURE_2D_INDEX;
401       break;
402    case GL_PROXY_TEXTURE_3D:
403       if (level >= ctx->Const.Max3DTextureLevels)
404          return NULL;
405       texIndex = TEXTURE_3D_INDEX;
406       break;
407    case GL_PROXY_TEXTURE_CUBE_MAP:
408       if (level >= ctx->Const.MaxCubeTextureLevels)
409          return NULL;
410       texIndex = TEXTURE_CUBE_INDEX;
411       break;
412    case GL_PROXY_TEXTURE_RECTANGLE_NV:
413       if (level > 0)
414          return NULL;
415       texIndex = TEXTURE_RECT_INDEX;
416       break;
417    case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
418       if (level >= ctx->Const.MaxTextureLevels)
419          return NULL;
420       texIndex = TEXTURE_1D_ARRAY_INDEX;
421       break;
422    case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
423       if (level >= ctx->Const.MaxTextureLevels)
424          return NULL;
425       texIndex = TEXTURE_2D_ARRAY_INDEX;
426       break;
427    case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
428       if (level >= ctx->Const.MaxCubeTextureLevels)
429          return NULL;
430       texIndex = TEXTURE_CUBE_ARRAY_INDEX;
431       break;
432    case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
433       if (level > 0)
434          return 0;
435       texIndex = TEXTURE_2D_MULTISAMPLE_INDEX;
436       break;
437    case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
438       if (level > 0)
439          return 0;
440       texIndex = TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX;
441       break;
442    default:
443       return NULL;
444    }
445 
446    texImage = ctx->Texture.ProxyTex[texIndex]->Image[0][level];
447    if (!texImage) {
448       texImage = ctx->Driver.NewTextureImage(ctx);
449       if (!texImage) {
450          _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation");
451          return NULL;
452       }
453       ctx->Texture.ProxyTex[texIndex]->Image[0][level] = texImage;
454       /* Set the 'back' pointer */
455       texImage->TexObject = ctx->Texture.ProxyTex[texIndex];
456    }
457    return texImage;
458 }
459 
460 
461 /**
462  * Get the maximum number of allowed mipmap levels.
463  *
464  * \param ctx GL context.
465  * \param target texture target.
466  *
467  * \return the maximum number of allowed mipmap levels for the given
468  * texture target, or zero if passed a bad target.
469  *
470  * \sa gl_constants.
471  */
472 GLint
_mesa_max_texture_levels(struct gl_context * ctx,GLenum target)473 _mesa_max_texture_levels(struct gl_context *ctx, GLenum target)
474 {
475    switch (target) {
476    case GL_TEXTURE_1D:
477    case GL_PROXY_TEXTURE_1D:
478    case GL_TEXTURE_2D:
479    case GL_PROXY_TEXTURE_2D:
480       return ctx->Const.MaxTextureLevels;
481    case GL_TEXTURE_3D:
482    case GL_PROXY_TEXTURE_3D:
483       return ctx->Const.Max3DTextureLevels;
484    case GL_TEXTURE_CUBE_MAP:
485    case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
486    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
487    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
488    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
489    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
490    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
491    case GL_PROXY_TEXTURE_CUBE_MAP:
492       return ctx->Extensions.ARB_texture_cube_map
493          ? ctx->Const.MaxCubeTextureLevels : 0;
494    case GL_TEXTURE_RECTANGLE_NV:
495    case GL_PROXY_TEXTURE_RECTANGLE_NV:
496       return ctx->Extensions.NV_texture_rectangle ? 1 : 0;
497    case GL_TEXTURE_1D_ARRAY_EXT:
498    case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
499    case GL_TEXTURE_2D_ARRAY_EXT:
500    case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
501       return ctx->Extensions.EXT_texture_array
502          ? ctx->Const.MaxTextureLevels : 0;
503    case GL_TEXTURE_CUBE_MAP_ARRAY:
504    case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
505       return _mesa_has_texture_cube_map_array(ctx)
506          ? ctx->Const.MaxCubeTextureLevels : 0;
507    case GL_TEXTURE_BUFFER:
508       return (_mesa_has_ARB_texture_buffer_object(ctx) ||
509               _mesa_has_OES_texture_buffer(ctx)) ? 1 : 0;
510    case GL_TEXTURE_2D_MULTISAMPLE:
511    case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
512    case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
513    case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
514       return (_mesa_is_desktop_gl(ctx) || _mesa_is_gles31(ctx))
515          && ctx->Extensions.ARB_texture_multisample
516          ? 1 : 0;
517    case GL_TEXTURE_EXTERNAL_OES:
518       /* fall-through */
519    default:
520       return 0; /* bad target */
521    }
522 }
523 
524 
525 /**
526  * Return number of dimensions per mipmap level for the given texture target.
527  */
528 GLint
_mesa_get_texture_dimensions(GLenum target)529 _mesa_get_texture_dimensions(GLenum target)
530 {
531    switch (target) {
532    case GL_TEXTURE_1D:
533    case GL_PROXY_TEXTURE_1D:
534       return 1;
535    case GL_TEXTURE_2D:
536    case GL_TEXTURE_RECTANGLE:
537    case GL_TEXTURE_CUBE_MAP:
538    case GL_PROXY_TEXTURE_2D:
539    case GL_PROXY_TEXTURE_RECTANGLE:
540    case GL_PROXY_TEXTURE_CUBE_MAP:
541    case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
542    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
543    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
544    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
545    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
546    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
547    case GL_TEXTURE_1D_ARRAY:
548    case GL_PROXY_TEXTURE_1D_ARRAY:
549    case GL_TEXTURE_EXTERNAL_OES:
550    case GL_TEXTURE_2D_MULTISAMPLE:
551    case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
552       return 2;
553    case GL_TEXTURE_3D:
554    case GL_PROXY_TEXTURE_3D:
555    case GL_TEXTURE_2D_ARRAY:
556    case GL_PROXY_TEXTURE_2D_ARRAY:
557    case GL_TEXTURE_CUBE_MAP_ARRAY:
558    case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
559    case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
560    case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
561       return 3;
562    case GL_TEXTURE_BUFFER:
563       /* fall-through */
564    default:
565       _mesa_problem(NULL, "invalid target 0x%x in get_texture_dimensions()",
566                     target);
567       return 2;
568    }
569 }
570 
571 
572 /**
573  * Check if a texture target can have more than one layer.
574  */
575 GLboolean
_mesa_tex_target_is_layered(GLenum target)576 _mesa_tex_target_is_layered(GLenum target)
577 {
578    switch (target) {
579    case GL_TEXTURE_1D:
580    case GL_PROXY_TEXTURE_1D:
581    case GL_TEXTURE_2D:
582    case GL_PROXY_TEXTURE_2D:
583    case GL_TEXTURE_RECTANGLE:
584    case GL_PROXY_TEXTURE_RECTANGLE:
585    case GL_TEXTURE_2D_MULTISAMPLE:
586    case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
587    case GL_TEXTURE_BUFFER:
588    case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
589    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
590    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
591    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
592    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
593    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
594    case GL_TEXTURE_EXTERNAL_OES:
595       return GL_FALSE;
596 
597    case GL_TEXTURE_3D:
598    case GL_PROXY_TEXTURE_3D:
599    case GL_TEXTURE_CUBE_MAP:
600    case GL_PROXY_TEXTURE_CUBE_MAP:
601    case GL_TEXTURE_1D_ARRAY:
602    case GL_PROXY_TEXTURE_1D_ARRAY:
603    case GL_TEXTURE_2D_ARRAY:
604    case GL_PROXY_TEXTURE_2D_ARRAY:
605    case GL_TEXTURE_CUBE_MAP_ARRAY:
606    case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
607    case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
608    case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
609       return GL_TRUE;
610 
611    default:
612       assert(!"Invalid texture target.");
613       return GL_FALSE;
614    }
615 }
616 
617 
618 /**
619  * Return the number of layers present in the given level of an array,
620  * cubemap or 3D texture.  If the texture is not layered return zero.
621  */
622 GLuint
_mesa_get_texture_layers(const struct gl_texture_object * texObj,GLint level)623 _mesa_get_texture_layers(const struct gl_texture_object *texObj, GLint level)
624 {
625    assert(level >= 0 && level < MAX_TEXTURE_LEVELS);
626 
627    switch (texObj->Target) {
628    case GL_TEXTURE_1D:
629    case GL_TEXTURE_2D:
630    case GL_TEXTURE_RECTANGLE:
631    case GL_TEXTURE_2D_MULTISAMPLE:
632    case GL_TEXTURE_BUFFER:
633    case GL_TEXTURE_EXTERNAL_OES:
634       return 0;
635 
636    case GL_TEXTURE_CUBE_MAP:
637       return 6;
638 
639    case GL_TEXTURE_1D_ARRAY: {
640       struct gl_texture_image *img = texObj->Image[0][level];
641       return img ? img->Height : 0;
642    }
643 
644    case GL_TEXTURE_3D:
645    case GL_TEXTURE_2D_ARRAY:
646    case GL_TEXTURE_CUBE_MAP_ARRAY:
647    case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: {
648       struct gl_texture_image *img = texObj->Image[0][level];
649       return img ? img->Depth : 0;
650    }
651 
652    default:
653       assert(!"Invalid texture target.");
654       return 0;
655    }
656 }
657 
658 
659 /**
660  * Return the maximum number of mipmap levels for the given target
661  * and the dimensions.
662  * The dimensions are expected not to include the border.
663  */
664 GLsizei
_mesa_get_tex_max_num_levels(GLenum target,GLsizei width,GLsizei height,GLsizei depth)665 _mesa_get_tex_max_num_levels(GLenum target, GLsizei width, GLsizei height,
666                              GLsizei depth)
667 {
668    GLsizei size;
669 
670    switch (target) {
671    case GL_TEXTURE_1D:
672    case GL_TEXTURE_1D_ARRAY:
673    case GL_PROXY_TEXTURE_1D:
674    case GL_PROXY_TEXTURE_1D_ARRAY:
675       size = width;
676       break;
677    case GL_TEXTURE_CUBE_MAP:
678    case GL_TEXTURE_CUBE_MAP_ARRAY:
679    case GL_PROXY_TEXTURE_CUBE_MAP:
680    case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
681       size = width;
682       break;
683    case GL_TEXTURE_2D:
684    case GL_TEXTURE_2D_ARRAY:
685    case GL_PROXY_TEXTURE_2D:
686    case GL_PROXY_TEXTURE_2D_ARRAY:
687       size = MAX2(width, height);
688       break;
689    case GL_TEXTURE_3D:
690    case GL_PROXY_TEXTURE_3D:
691       size = MAX3(width, height, depth);
692       break;
693    case GL_TEXTURE_RECTANGLE:
694    case GL_TEXTURE_EXTERNAL_OES:
695    case GL_TEXTURE_2D_MULTISAMPLE:
696    case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
697    case GL_PROXY_TEXTURE_RECTANGLE:
698    case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
699    case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
700       return 1;
701    default:
702       assert(0);
703       return 1;
704    }
705 
706    return _mesa_logbase2(size) + 1;
707 }
708 
709 
710 #if 000 /* not used anymore */
711 /*
712  * glTexImage[123]D can accept a NULL image pointer.  In this case we
713  * create a texture image with unspecified image contents per the OpenGL
714  * spec.
715  */
716 static GLubyte *
717 make_null_texture(GLint width, GLint height, GLint depth, GLenum format)
718 {
719    const GLint components = _mesa_components_in_format(format);
720    const GLint numPixels = width * height * depth;
721    GLubyte *data = (GLubyte *) malloc(numPixels * components * sizeof(GLubyte));
722 
723 #ifdef DEBUG
724    /*
725     * Let's see if anyone finds this.  If glTexImage2D() is called with
726     * a NULL image pointer then load the texture image with something
727     * interesting instead of leaving it indeterminate.
728     */
729    if (data) {
730       static const char message[8][32] = {
731          "   X   X  XXXXX   XXX     X    ",
732          "   XX XX  X      X   X   X X   ",
733          "   X X X  X      X      X   X  ",
734          "   X   X  XXXX    XXX   XXXXX  ",
735          "   X   X  X          X  X   X  ",
736          "   X   X  X      X   X  X   X  ",
737          "   X   X  XXXXX   XXX   X   X  ",
738          "                               "
739       };
740 
741       GLubyte *imgPtr = data;
742       GLint h, i, j, k;
743       for (h = 0; h < depth; h++) {
744          for (i = 0; i < height; i++) {
745             GLint srcRow = 7 - (i % 8);
746             for (j = 0; j < width; j++) {
747                GLint srcCol = j % 32;
748                GLubyte texel = (message[srcRow][srcCol]=='X') ? 255 : 70;
749                for (k = 0; k < components; k++) {
750                   *imgPtr++ = texel;
751                }
752             }
753          }
754       }
755    }
756 #endif
757 
758    return data;
759 }
760 #endif
761 
762 
763 
764 /**
765  * Set the size and format-related fields of a gl_texture_image struct
766  * to zero.  This is used when a proxy texture test fails.
767  */
768 static void
clear_teximage_fields(struct gl_texture_image * img)769 clear_teximage_fields(struct gl_texture_image *img)
770 {
771    assert(img);
772    img->_BaseFormat = 0;
773    img->InternalFormat = 0;
774    img->Border = 0;
775    img->Width = 0;
776    img->Height = 0;
777    img->Depth = 0;
778    img->Width2 = 0;
779    img->Height2 = 0;
780    img->Depth2 = 0;
781    img->WidthLog2 = 0;
782    img->HeightLog2 = 0;
783    img->DepthLog2 = 0;
784    img->TexFormat = MESA_FORMAT_NONE;
785    img->NumSamples = 0;
786    img->FixedSampleLocations = GL_TRUE;
787 }
788 
789 
790 /**
791  * Initialize basic fields of the gl_texture_image struct.
792  *
793  * \param ctx GL context.
794  * \param img texture image structure to be initialized.
795  * \param width image width.
796  * \param height image height.
797  * \param depth image depth.
798  * \param border image border.
799  * \param internalFormat internal format.
800  * \param format  the actual hardware format (one of MESA_FORMAT_*)
801  * \param numSamples  number of samples per texel, or zero for non-MS.
802  * \param fixedSampleLocations  are sample locations fixed?
803  *
804  * Fills in the fields of \p img with the given information.
805  * Note: width, height and depth include the border.
806  */
807 static void
init_teximage_fields_ms(struct gl_context * ctx,struct gl_texture_image * img,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum internalFormat,mesa_format format,GLuint numSamples,GLboolean fixedSampleLocations)808 init_teximage_fields_ms(struct gl_context *ctx,
809                         struct gl_texture_image *img,
810                         GLsizei width, GLsizei height, GLsizei depth,
811                         GLint border, GLenum internalFormat,
812                         mesa_format format,
813                         GLuint numSamples, GLboolean fixedSampleLocations)
814 {
815    GLenum target;
816    assert(img);
817    assert(width >= 0);
818    assert(height >= 0);
819    assert(depth >= 0);
820 
821    target = img->TexObject->Target;
822    img->_BaseFormat = _mesa_base_tex_format( ctx, internalFormat );
823    assert(img->_BaseFormat != -1);
824    img->InternalFormat = internalFormat;
825    img->Border = border;
826    img->Width = width;
827    img->Height = height;
828    img->Depth = depth;
829 
830    img->Width2 = width - 2 * border;   /* == 1 << img->WidthLog2; */
831    img->WidthLog2 = _mesa_logbase2(img->Width2);
832 
833    img->NumSamples = 0;
834    img->FixedSampleLocations = GL_TRUE;
835 
836    switch(target) {
837    case GL_TEXTURE_1D:
838    case GL_TEXTURE_BUFFER:
839    case GL_PROXY_TEXTURE_1D:
840       if (height == 0)
841          img->Height2 = 0;
842       else
843          img->Height2 = 1;
844       img->HeightLog2 = 0;
845       if (depth == 0)
846          img->Depth2 = 0;
847       else
848          img->Depth2 = 1;
849       img->DepthLog2 = 0;
850       break;
851    case GL_TEXTURE_1D_ARRAY:
852    case GL_PROXY_TEXTURE_1D_ARRAY:
853       img->Height2 = height; /* no border */
854       img->HeightLog2 = 0; /* not used */
855       if (depth == 0)
856          img->Depth2 = 0;
857       else
858          img->Depth2 = 1;
859       img->DepthLog2 = 0;
860       break;
861    case GL_TEXTURE_2D:
862    case GL_TEXTURE_RECTANGLE:
863    case GL_TEXTURE_CUBE_MAP:
864    case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
865    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
866    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
867    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
868    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
869    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
870    case GL_TEXTURE_EXTERNAL_OES:
871    case GL_PROXY_TEXTURE_2D:
872    case GL_PROXY_TEXTURE_RECTANGLE:
873    case GL_PROXY_TEXTURE_CUBE_MAP:
874    case GL_TEXTURE_2D_MULTISAMPLE:
875    case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
876       img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */
877       img->HeightLog2 = _mesa_logbase2(img->Height2);
878       if (depth == 0)
879          img->Depth2 = 0;
880       else
881          img->Depth2 = 1;
882       img->DepthLog2 = 0;
883       break;
884    case GL_TEXTURE_2D_ARRAY:
885    case GL_PROXY_TEXTURE_2D_ARRAY:
886    case GL_TEXTURE_CUBE_MAP_ARRAY:
887    case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
888    case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
889    case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
890       img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */
891       img->HeightLog2 = _mesa_logbase2(img->Height2);
892       img->Depth2 = depth; /* no border */
893       img->DepthLog2 = 0; /* not used */
894       break;
895    case GL_TEXTURE_3D:
896    case GL_PROXY_TEXTURE_3D:
897       img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */
898       img->HeightLog2 = _mesa_logbase2(img->Height2);
899       img->Depth2 = depth - 2 * border;   /* == 1 << img->DepthLog2; */
900       img->DepthLog2 = _mesa_logbase2(img->Depth2);
901       break;
902    default:
903       _mesa_problem(NULL, "invalid target 0x%x in _mesa_init_teximage_fields()",
904                     target);
905    }
906 
907    img->MaxNumLevels =
908       _mesa_get_tex_max_num_levels(target,
909                                    img->Width2, img->Height2, img->Depth2);
910    img->TexFormat = format;
911    img->NumSamples = numSamples;
912    img->FixedSampleLocations = fixedSampleLocations;
913 }
914 
915 
916 void
_mesa_init_teximage_fields(struct gl_context * ctx,struct gl_texture_image * img,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLenum internalFormat,mesa_format format)917 _mesa_init_teximage_fields(struct gl_context *ctx,
918                            struct gl_texture_image *img,
919                            GLsizei width, GLsizei height, GLsizei depth,
920                            GLint border, GLenum internalFormat,
921                            mesa_format format)
922 {
923    init_teximage_fields_ms(ctx, img, width, height, depth, border,
924                            internalFormat, format, 0, GL_TRUE);
925 }
926 
927 
928 /**
929  * Free and clear fields of the gl_texture_image struct.
930  *
931  * \param ctx GL context.
932  * \param texImage texture image structure to be cleared.
933  *
934  * After the call, \p texImage will have no data associated with it.  Its
935  * fields are cleared so that its parent object will test incomplete.
936  */
937 void
_mesa_clear_texture_image(struct gl_context * ctx,struct gl_texture_image * texImage)938 _mesa_clear_texture_image(struct gl_context *ctx,
939                           struct gl_texture_image *texImage)
940 {
941    ctx->Driver.FreeTextureImageBuffer(ctx, texImage);
942    clear_teximage_fields(texImage);
943 }
944 
945 
946 /**
947  * Check the width, height, depth and border of a texture image are legal.
948  * Used by all the glTexImage, glCompressedTexImage and glCopyTexImage
949  * functions.
950  * The target and level parameters will have already been validated.
951  * \return GL_TRUE if size is OK, GL_FALSE otherwise.
952  */
953 GLboolean
_mesa_legal_texture_dimensions(struct gl_context * ctx,GLenum target,GLint level,GLint width,GLint height,GLint depth,GLint border)954 _mesa_legal_texture_dimensions(struct gl_context *ctx, GLenum target,
955                                GLint level, GLint width, GLint height,
956                                GLint depth, GLint border)
957 {
958    GLint maxSize;
959 
960    switch (target) {
961    case GL_TEXTURE_1D:
962    case GL_PROXY_TEXTURE_1D:
963       maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); /* level zero size */
964       maxSize >>= level;  /* level size */
965       if (width < 2 * border || width > 2 * border + maxSize)
966          return GL_FALSE;
967       if (!ctx->Extensions.ARB_texture_non_power_of_two) {
968          if (width > 0 && !_mesa_is_pow_two(width - 2 * border))
969             return GL_FALSE;
970       }
971       return GL_TRUE;
972 
973    case GL_TEXTURE_2D:
974    case GL_PROXY_TEXTURE_2D:
975    case GL_TEXTURE_2D_MULTISAMPLE:
976    case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
977       maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
978       maxSize >>= level;
979       if (width < 2 * border || width > 2 * border + maxSize)
980          return GL_FALSE;
981       if (height < 2 * border || height > 2 * border + maxSize)
982          return GL_FALSE;
983       if (!ctx->Extensions.ARB_texture_non_power_of_two) {
984          if (width > 0 && !_mesa_is_pow_two(width - 2 * border))
985             return GL_FALSE;
986          if (height > 0 && !_mesa_is_pow_two(height - 2 * border))
987             return GL_FALSE;
988       }
989       return GL_TRUE;
990 
991    case GL_TEXTURE_3D:
992    case GL_PROXY_TEXTURE_3D:
993       maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1);
994       maxSize >>= level;
995       if (width < 2 * border || width > 2 * border + maxSize)
996          return GL_FALSE;
997       if (height < 2 * border || height > 2 * border + maxSize)
998          return GL_FALSE;
999       if (depth < 2 * border || depth > 2 * border + maxSize)
1000          return GL_FALSE;
1001       if (!ctx->Extensions.ARB_texture_non_power_of_two) {
1002          if (width > 0 && !_mesa_is_pow_two(width - 2 * border))
1003             return GL_FALSE;
1004          if (height > 0 && !_mesa_is_pow_two(height - 2 * border))
1005             return GL_FALSE;
1006          if (depth > 0 && !_mesa_is_pow_two(depth - 2 * border))
1007             return GL_FALSE;
1008       }
1009       return GL_TRUE;
1010 
1011    case GL_TEXTURE_RECTANGLE_NV:
1012    case GL_PROXY_TEXTURE_RECTANGLE_NV:
1013       if (level != 0)
1014          return GL_FALSE;
1015       maxSize = ctx->Const.MaxTextureRectSize;
1016       if (width < 0 || width > maxSize)
1017          return GL_FALSE;
1018       if (height < 0 || height > maxSize)
1019          return GL_FALSE;
1020       return GL_TRUE;
1021 
1022    case GL_TEXTURE_CUBE_MAP:
1023    case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1024    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1025    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1026    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1027    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1028    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1029    case GL_PROXY_TEXTURE_CUBE_MAP:
1030       maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1);
1031       maxSize >>= level;
1032       if (width != height)
1033          return GL_FALSE;
1034       if (width < 2 * border || width > 2 * border + maxSize)
1035          return GL_FALSE;
1036       if (height < 2 * border || height > 2 * border + maxSize)
1037          return GL_FALSE;
1038       if (!ctx->Extensions.ARB_texture_non_power_of_two) {
1039          if (width > 0 && !_mesa_is_pow_two(width - 2 * border))
1040             return GL_FALSE;
1041          if (height > 0 && !_mesa_is_pow_two(height - 2 * border))
1042             return GL_FALSE;
1043       }
1044       return GL_TRUE;
1045 
1046    case GL_TEXTURE_1D_ARRAY_EXT:
1047    case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
1048       maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
1049       maxSize >>= level;
1050       if (width < 2 * border || width > 2 * border + maxSize)
1051          return GL_FALSE;
1052       if (height < 0 || height > ctx->Const.MaxArrayTextureLayers)
1053          return GL_FALSE;
1054       if (!ctx->Extensions.ARB_texture_non_power_of_two) {
1055          if (width > 0 && !_mesa_is_pow_two(width - 2 * border))
1056             return GL_FALSE;
1057       }
1058       return GL_TRUE;
1059 
1060    case GL_TEXTURE_2D_ARRAY_EXT:
1061    case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
1062    case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
1063    case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
1064       maxSize = 1 << (ctx->Const.MaxTextureLevels - 1);
1065       maxSize >>= level;
1066       if (width < 2 * border || width > 2 * border + maxSize)
1067          return GL_FALSE;
1068       if (height < 2 * border || height > 2 * border + maxSize)
1069          return GL_FALSE;
1070       if (depth < 0 || depth > ctx->Const.MaxArrayTextureLayers)
1071          return GL_FALSE;
1072       if (!ctx->Extensions.ARB_texture_non_power_of_two) {
1073          if (width > 0 && !_mesa_is_pow_two(width - 2 * border))
1074             return GL_FALSE;
1075          if (height > 0 && !_mesa_is_pow_two(height - 2 * border))
1076             return GL_FALSE;
1077       }
1078       return GL_TRUE;
1079 
1080    case GL_TEXTURE_CUBE_MAP_ARRAY:
1081    case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
1082       maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1);
1083       if (width < 2 * border || width > 2 * border + maxSize)
1084          return GL_FALSE;
1085       if (height < 2 * border || height > 2 * border + maxSize)
1086          return GL_FALSE;
1087       if (depth < 0 || depth > ctx->Const.MaxArrayTextureLayers || depth % 6)
1088          return GL_FALSE;
1089       if (width != height)
1090          return GL_FALSE;
1091       if (level >= ctx->Const.MaxCubeTextureLevels)
1092          return GL_FALSE;
1093       if (!ctx->Extensions.ARB_texture_non_power_of_two) {
1094          if (width > 0 && !_mesa_is_pow_two(width - 2 * border))
1095             return GL_FALSE;
1096          if (height > 0 && !_mesa_is_pow_two(height - 2 * border))
1097             return GL_FALSE;
1098       }
1099       return GL_TRUE;
1100    default:
1101       _mesa_problem(ctx, "Invalid target in _mesa_legal_texture_dimensions()");
1102       return GL_FALSE;
1103    }
1104 }
1105 
1106 static bool
error_check_subtexture_negative_dimensions(struct gl_context * ctx,GLuint dims,GLsizei subWidth,GLsizei subHeight,GLsizei subDepth,const char * func)1107 error_check_subtexture_negative_dimensions(struct gl_context *ctx,
1108                                            GLuint dims,
1109                                            GLsizei subWidth,
1110                                            GLsizei subHeight,
1111                                            GLsizei subDepth,
1112                                            const char *func)
1113 {
1114    /* Check size */
1115    if (subWidth < 0) {
1116       _mesa_error(ctx, GL_INVALID_VALUE, "%s(width=%d)", func, subWidth);
1117       return true;
1118    }
1119 
1120    if (dims > 1 && subHeight < 0) {
1121       _mesa_error(ctx, GL_INVALID_VALUE, "%s(height=%d)", func, subHeight);
1122       return true;
1123    }
1124 
1125    if (dims > 2 && subDepth < 0) {
1126       _mesa_error(ctx, GL_INVALID_VALUE, "%s(depth=%d)", func, subDepth);
1127       return true;
1128    }
1129 
1130    return false;
1131 }
1132 
1133 /**
1134  * Do error checking of xoffset, yoffset, zoffset, width, height and depth
1135  * for glTexSubImage, glCopyTexSubImage and glCompressedTexSubImage.
1136  * \param destImage  the destination texture image.
1137  * \return GL_TRUE if error found, GL_FALSE otherwise.
1138  */
1139 static GLboolean
error_check_subtexture_dimensions(struct gl_context * ctx,GLuint dims,const struct gl_texture_image * destImage,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei subWidth,GLsizei subHeight,GLsizei subDepth,const char * func)1140 error_check_subtexture_dimensions(struct gl_context *ctx, GLuint dims,
1141                                   const struct gl_texture_image *destImage,
1142                                   GLint xoffset, GLint yoffset, GLint zoffset,
1143                                   GLsizei subWidth, GLsizei subHeight,
1144                                   GLsizei subDepth, const char *func)
1145 {
1146    const GLenum target = destImage->TexObject->Target;
1147    GLuint bw, bh, bd;
1148 
1149    /* check xoffset and width */
1150    if (xoffset < - (GLint) destImage->Border) {
1151       _mesa_error(ctx, GL_INVALID_VALUE, "%s(xoffset)", func);
1152       return GL_TRUE;
1153    }
1154 
1155    if (xoffset + subWidth > (GLint) destImage->Width) {
1156       _mesa_error(ctx, GL_INVALID_VALUE, "%s(xoffset+width)", func);
1157       return GL_TRUE;
1158    }
1159 
1160    /* check yoffset and height */
1161    if (dims > 1) {
1162       GLint yBorder = (target == GL_TEXTURE_1D_ARRAY) ? 0 : destImage->Border;
1163       if (yoffset < -yBorder) {
1164          _mesa_error(ctx, GL_INVALID_VALUE, "%s(yoffset)", func);
1165          return GL_TRUE;
1166       }
1167       if (yoffset + subHeight > (GLint) destImage->Height) {
1168          _mesa_error(ctx, GL_INVALID_VALUE, "%s(yoffset+height)", func);
1169          return GL_TRUE;
1170       }
1171    }
1172 
1173    /* check zoffset and depth */
1174    if (dims > 2) {
1175       GLint depth;
1176       GLint zBorder = (target == GL_TEXTURE_2D_ARRAY ||
1177                        target == GL_TEXTURE_CUBE_MAP_ARRAY) ?
1178                          0 : destImage->Border;
1179 
1180       if (zoffset < -zBorder) {
1181          _mesa_error(ctx, GL_INVALID_VALUE, "%s(zoffset)", func);
1182          return GL_TRUE;
1183       }
1184 
1185       depth = (GLint) destImage->Depth;
1186       if (target == GL_TEXTURE_CUBE_MAP)
1187          depth = 6;
1188       if (zoffset + subDepth  > depth) {
1189          _mesa_error(ctx, GL_INVALID_VALUE, "%s(zoffset+depth)", func);
1190          return GL_TRUE;
1191       }
1192    }
1193 
1194    /*
1195     * The OpenGL spec (and GL_ARB_texture_compression) says only whole
1196     * compressed texture images can be updated.  But, that restriction may be
1197     * relaxed for particular compressed formats.  At this time, all the
1198     * compressed formats supported by Mesa allow sub-textures to be updated
1199     * along compressed block boundaries.
1200     */
1201    _mesa_get_format_block_size_3d(destImage->TexFormat, &bw, &bh, &bd);
1202 
1203    if (bw != 1 || bh != 1 || bd != 1) {
1204       /* offset must be multiple of block size */
1205       if ((xoffset % bw != 0) || (yoffset % bh != 0) || (zoffset % bd != 0)) {
1206          _mesa_error(ctx, GL_INVALID_OPERATION,
1207                      "%s(xoffset = %d, yoffset = %d, zoffset = %d)",
1208                      func, xoffset, yoffset, zoffset);
1209          return GL_TRUE;
1210       }
1211 
1212       /* The size must be a multiple of bw x bh, or we must be using a
1213        * offset+size that exactly hits the edge of the image.  This
1214        * is important for small mipmap levels (1x1, 2x1, etc) and for
1215        * NPOT textures.
1216        */
1217       if ((subWidth % bw != 0) &&
1218           (xoffset + subWidth != (GLint) destImage->Width)) {
1219          _mesa_error(ctx, GL_INVALID_OPERATION,
1220                      "%s(width = %d)", func, subWidth);
1221          return GL_TRUE;
1222       }
1223 
1224       if ((subHeight % bh != 0) &&
1225           (yoffset + subHeight != (GLint) destImage->Height)) {
1226          _mesa_error(ctx, GL_INVALID_OPERATION,
1227                      "%s(height = %d)", func, subHeight);
1228          return GL_TRUE;
1229       }
1230 
1231       if ((subDepth % bd != 0) &&
1232           (zoffset + subDepth != (GLint) destImage->Depth)) {
1233          _mesa_error(ctx, GL_INVALID_OPERATION,
1234                      "%s(depth = %d)", func, subDepth);
1235          return GL_TRUE;
1236       }
1237    }
1238 
1239    return GL_FALSE;
1240 }
1241 
1242 
1243 
1244 
1245 /**
1246  * This is the fallback for Driver.TestProxyTexImage() for doing device-
1247  * specific texture image size checks.
1248  *
1249  * A hardware driver might override this function if, for example, the
1250  * max 3D texture size is 512x512x64 (i.e. not a cube).
1251  *
1252  * Note that width, height, depth == 0 is not an error.  However, a
1253  * texture with zero width/height/depth will be considered "incomplete"
1254  * and texturing will effectively be disabled.
1255  *
1256  * \param target  any texture target/type
1257  * \param numLevels  number of mipmap levels in the texture or 0 if not known
1258  * \param level  as passed to glTexImage
1259  * \param format  the MESA_FORMAT_x for the tex image
1260  * \param numSamples  number of samples per texel
1261  * \param width  as passed to glTexImage
1262  * \param height  as passed to glTexImage
1263  * \param depth  as passed to glTexImage
1264  * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable.
1265  */
1266 GLboolean
_mesa_test_proxy_teximage(struct gl_context * ctx,GLenum target,GLuint numLevels,GLint level,mesa_format format,GLuint numSamples,GLint width,GLint height,GLint depth)1267 _mesa_test_proxy_teximage(struct gl_context *ctx, GLenum target,
1268                           GLuint numLevels, GLint level,
1269                           mesa_format format, GLuint numSamples,
1270                           GLint width, GLint height, GLint depth)
1271 {
1272    uint64_t bytes, mbytes;
1273 
1274    if (numLevels > 0) {
1275       /* Compute total memory for a whole mipmap.  This is the path
1276        * taken for glTexStorage(GL_PROXY_TEXTURE_x).
1277        */
1278       unsigned l;
1279 
1280       assert(level == 0);
1281 
1282       bytes = 0;
1283 
1284       for (l = 0; l < numLevels; l++) {
1285          GLint nextWidth, nextHeight, nextDepth;
1286 
1287          bytes += _mesa_format_image_size64(format, width, height, depth);
1288 
1289          if (_mesa_next_mipmap_level_size(target, 0, width, height, depth,
1290                                           &nextWidth, &nextHeight,
1291                                           &nextDepth)) {
1292             width = nextWidth;
1293             height = nextHeight;
1294             depth = nextDepth;
1295          } else {
1296             break;
1297          }
1298       }
1299    } else {
1300       /* We just compute the size of one mipmap level.  This is the path
1301        * taken for glTexImage(GL_PROXY_TEXTURE_x).
1302        */
1303       bytes = _mesa_format_image_size64(format, width, height, depth);
1304    }
1305 
1306    bytes *= _mesa_num_tex_faces(target);
1307    bytes *= MAX2(1, numSamples);
1308 
1309    mbytes = bytes / (1024 * 1024); /* convert to MB */
1310 
1311    /* We just check if the image size is less than MaxTextureMbytes.
1312     * Some drivers may do more specific checks.
1313     */
1314    return mbytes <= (uint64_t) ctx->Const.MaxTextureMbytes;
1315 }
1316 
1317 
1318 /**
1319  * Return true if the format is only valid for glCompressedTexImage.
1320  */
1321 static bool
compressedteximage_only_format(const struct gl_context * ctx,GLenum format)1322 compressedteximage_only_format(const struct gl_context *ctx, GLenum format)
1323 {
1324    switch (format) {
1325    case GL_ETC1_RGB8_OES:
1326    case GL_PALETTE4_RGB8_OES:
1327    case GL_PALETTE4_RGBA8_OES:
1328    case GL_PALETTE4_R5_G6_B5_OES:
1329    case GL_PALETTE4_RGBA4_OES:
1330    case GL_PALETTE4_RGB5_A1_OES:
1331    case GL_PALETTE8_RGB8_OES:
1332    case GL_PALETTE8_RGBA8_OES:
1333    case GL_PALETTE8_R5_G6_B5_OES:
1334    case GL_PALETTE8_RGBA4_OES:
1335    case GL_PALETTE8_RGB5_A1_OES:
1336       return true;
1337    default:
1338       return false;
1339    }
1340 }
1341 
1342 /**
1343  * Return true if the format doesn't support online compression.
1344  */
1345 bool
_mesa_format_no_online_compression(const struct gl_context * ctx,GLenum format)1346 _mesa_format_no_online_compression(const struct gl_context *ctx, GLenum format)
1347 {
1348    return _mesa_is_astc_format(format) ||
1349           _mesa_is_etc2_format(format) ||
1350           compressedteximage_only_format(ctx, format);
1351 }
1352 
1353 /* Writes to an GL error pointer if non-null and returns whether or not the
1354  * error is GL_NO_ERROR */
1355 static bool
write_error(GLenum * err_ptr,GLenum error)1356 write_error(GLenum *err_ptr, GLenum error)
1357 {
1358    if (err_ptr)
1359       *err_ptr = error;
1360 
1361    return error == GL_NO_ERROR;
1362 }
1363 
1364 /**
1365  * Helper function to determine whether a target and specific compression
1366  * format are supported. The error parameter returns GL_NO_ERROR if the
1367  * target can be compressed. Otherwise it returns either GL_INVALID_OPERATION
1368  * or GL_INVALID_ENUM, whichever is more appropriate.
1369  */
1370 GLboolean
_mesa_target_can_be_compressed(const struct gl_context * ctx,GLenum target,GLenum intFormat,GLenum * error)1371 _mesa_target_can_be_compressed(const struct gl_context *ctx, GLenum target,
1372                                GLenum intFormat, GLenum *error)
1373 {
1374    GLboolean target_can_be_compresed = GL_FALSE;
1375    mesa_format format = _mesa_glenum_to_compressed_format(intFormat);
1376    enum mesa_format_layout layout = _mesa_get_format_layout(format);
1377 
1378    switch (target) {
1379    case GL_TEXTURE_2D:
1380    case GL_PROXY_TEXTURE_2D:
1381       target_can_be_compresed = GL_TRUE; /* true for any compressed format so far */
1382       break;
1383    case GL_PROXY_TEXTURE_CUBE_MAP:
1384    case GL_TEXTURE_CUBE_MAP:
1385    case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1386    case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1387    case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1388    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1389    case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1390    case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1391       target_can_be_compresed = ctx->Extensions.ARB_texture_cube_map;
1392       break;
1393    case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
1394    case GL_TEXTURE_2D_ARRAY_EXT:
1395       target_can_be_compresed = ctx->Extensions.EXT_texture_array;
1396       break;
1397    case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
1398    case GL_TEXTURE_CUBE_MAP_ARRAY:
1399       /* From the KHR_texture_compression_astc_hdr spec:
1400        *
1401        *     Add a second new column "3D Tex." which is empty for all non-ASTC
1402        *     formats. If only the LDR profile is supported by the
1403        *     implementation, this column is also empty for all ASTC formats. If
1404        *     both the LDR and HDR profiles are supported only, this column is
1405        *     checked for all ASTC formats.
1406        *
1407        *     Add a third new column "Cube Map Array Tex." which is empty for all
1408        *     non-ASTC formats, and checked for all ASTC formats.
1409        *
1410        * and,
1411        *
1412        *     'An INVALID_OPERATION error is generated by CompressedTexImage3D
1413        *      if <internalformat> is TEXTURE_CUBE_MAP_ARRAY and the
1414        *      "Cube Map Array" column of table 8.19 is *not* checked, or if
1415        *      <internalformat> is TEXTURE_3D and the "3D Tex." column of table
1416        *      8.19 is *not* checked'
1417        *
1418        * The instances of <internalformat> above should say <target>.
1419        *
1420        * ETC2/EAC formats are the only alternative in GLES and thus such errors
1421        * have already been handled by normal ETC2/EAC behavior.
1422        */
1423 
1424       /* From section 3.8.6, page 146 of OpenGL ES 3.0 spec:
1425        *
1426        *    "The ETC2/EAC texture compression algorithm supports only
1427        *     two-dimensional images. If internalformat is an ETC2/EAC format,
1428        *     glCompressedTexImage3D will generate an INVALID_OPERATION error if
1429        *     target is not TEXTURE_2D_ARRAY."
1430        *
1431        * This should also be applicable for glTexStorage3D(). Other available
1432        * targets for these functions are: TEXTURE_3D and TEXTURE_CUBE_MAP_ARRAY.
1433        */
1434       if (layout == MESA_FORMAT_LAYOUT_ETC2 && _mesa_is_gles3(ctx))
1435             return write_error(error, GL_INVALID_OPERATION);
1436       target_can_be_compresed = _mesa_has_texture_cube_map_array(ctx);
1437       break;
1438    case GL_TEXTURE_3D:
1439       switch (layout) {
1440       case MESA_FORMAT_LAYOUT_ETC2:
1441          /* See ETC2/EAC comment in case GL_TEXTURE_CUBE_MAP_ARRAY. */
1442          if (_mesa_is_gles3(ctx))
1443             return write_error(error, GL_INVALID_OPERATION);
1444          break;
1445       case MESA_FORMAT_LAYOUT_BPTC:
1446          target_can_be_compresed = ctx->Extensions.ARB_texture_compression_bptc;
1447          break;
1448       case MESA_FORMAT_LAYOUT_ASTC:
1449          target_can_be_compresed =
1450             ctx->Extensions.KHR_texture_compression_astc_hdr ||
1451             ctx->Extensions.KHR_texture_compression_astc_sliced_3d;
1452 
1453          /* Throw an INVALID_OPERATION error if the target is TEXTURE_3D and
1454           * neither of the above extensions are supported. See comment in
1455           * switch case GL_TEXTURE_CUBE_MAP_ARRAY for more info.
1456           */
1457          if (!target_can_be_compresed)
1458             return write_error(error, GL_INVALID_OPERATION);
1459          break;
1460       default:
1461          break;
1462       }
1463    default:
1464       break;
1465    }
1466    return write_error(error,
1467                       target_can_be_compresed ? GL_NO_ERROR : GL_INVALID_ENUM);
1468 }
1469 
1470 
1471 /**
1472  * Check if the given texture target value is legal for a
1473  * glTexImage1/2/3D call.
1474  */
1475 static GLboolean
legal_teximage_target(struct gl_context * ctx,GLuint dims,GLenum target)1476 legal_teximage_target(struct gl_context *ctx, GLuint dims, GLenum target)
1477 {
1478    switch (dims) {
1479    case 1:
1480       switch (target) {
1481       case GL_TEXTURE_1D:
1482       case GL_PROXY_TEXTURE_1D:
1483          return _mesa_is_desktop_gl(ctx);
1484       default:
1485          return GL_FALSE;
1486       }
1487    case 2:
1488       switch (target) {
1489       case GL_TEXTURE_2D:
1490          return GL_TRUE;
1491       case GL_PROXY_TEXTURE_2D:
1492          return _mesa_is_desktop_gl(ctx);
1493       case GL_PROXY_TEXTURE_CUBE_MAP:
1494          return _mesa_is_desktop_gl(ctx)
1495             && ctx->Extensions.ARB_texture_cube_map;
1496       case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1497       case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1498       case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1499       case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1500       case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1501       case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1502          return ctx->Extensions.ARB_texture_cube_map;
1503       case GL_TEXTURE_RECTANGLE_NV:
1504       case GL_PROXY_TEXTURE_RECTANGLE_NV:
1505          return _mesa_is_desktop_gl(ctx)
1506             && ctx->Extensions.NV_texture_rectangle;
1507       case GL_TEXTURE_1D_ARRAY_EXT:
1508       case GL_PROXY_TEXTURE_1D_ARRAY_EXT:
1509          return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array;
1510       default:
1511          return GL_FALSE;
1512       }
1513    case 3:
1514       switch (target) {
1515       case GL_TEXTURE_3D:
1516          return GL_TRUE;
1517       case GL_PROXY_TEXTURE_3D:
1518          return _mesa_is_desktop_gl(ctx);
1519       case GL_TEXTURE_2D_ARRAY_EXT:
1520          return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array)
1521             || _mesa_is_gles3(ctx);
1522       case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
1523          return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array;
1524       case GL_TEXTURE_CUBE_MAP_ARRAY:
1525       case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
1526          return _mesa_has_texture_cube_map_array(ctx);
1527       default:
1528          return GL_FALSE;
1529       }
1530    default:
1531       _mesa_problem(ctx, "invalid dims=%u in legal_teximage_target()", dims);
1532       return GL_FALSE;
1533    }
1534 }
1535 
1536 
1537 /**
1538  * Check if the given texture target value is legal for a
1539  * glTexSubImage, glCopyTexSubImage or glCopyTexImage call.
1540  * The difference compared to legal_teximage_target() above is that
1541  * proxy targets are not supported.
1542  */
1543 static GLboolean
legal_texsubimage_target(struct gl_context * ctx,GLuint dims,GLenum target,bool dsa)1544 legal_texsubimage_target(struct gl_context *ctx, GLuint dims, GLenum target,
1545                          bool dsa)
1546 {
1547    switch (dims) {
1548    case 1:
1549       return _mesa_is_desktop_gl(ctx) && target == GL_TEXTURE_1D;
1550    case 2:
1551       switch (target) {
1552       case GL_TEXTURE_2D:
1553          return GL_TRUE;
1554       case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
1555       case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
1556       case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
1557       case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
1558       case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
1559       case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
1560          return ctx->Extensions.ARB_texture_cube_map;
1561       case GL_TEXTURE_RECTANGLE_NV:
1562          return _mesa_is_desktop_gl(ctx)
1563             && ctx->Extensions.NV_texture_rectangle;
1564       case GL_TEXTURE_1D_ARRAY_EXT:
1565          return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array;
1566       default:
1567          return GL_FALSE;
1568       }
1569    case 3:
1570       switch (target) {
1571       case GL_TEXTURE_3D:
1572          return GL_TRUE;
1573       case GL_TEXTURE_2D_ARRAY_EXT:
1574          return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array)
1575             || _mesa_is_gles3(ctx);
1576       case GL_TEXTURE_CUBE_MAP_ARRAY:
1577       case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
1578          return _mesa_has_texture_cube_map_array(ctx);
1579 
1580       /* Table 8.15 of the OpenGL 4.5 core profile spec
1581        * (20141030) says that TEXTURE_CUBE_MAP is valid for TextureSubImage3D
1582        * and CopyTextureSubImage3D.
1583        */
1584       case GL_TEXTURE_CUBE_MAP:
1585          return dsa;
1586       default:
1587          return GL_FALSE;
1588       }
1589    default:
1590       _mesa_problem(ctx, "invalid dims=%u in legal_texsubimage_target()",
1591                     dims);
1592       return GL_FALSE;
1593    }
1594 }
1595 
1596 
1597 /**
1598  * Helper function to determine if a texture object is mutable (in terms
1599  * of GL_ARB_texture_storage).
1600  */
1601 static GLboolean
mutable_tex_object(struct gl_context * ctx,GLenum target)1602 mutable_tex_object(struct gl_context *ctx, GLenum target)
1603 {
1604    struct gl_texture_object *texObj = _mesa_get_current_tex_object(ctx, target);
1605    if (!texObj)
1606       return GL_FALSE;
1607 
1608    return !texObj->Immutable;
1609 }
1610 
1611 
1612 /**
1613  * Return expected size of a compressed texture.
1614  */
1615 static GLuint
compressed_tex_size(GLsizei width,GLsizei height,GLsizei depth,GLenum glformat)1616 compressed_tex_size(GLsizei width, GLsizei height, GLsizei depth,
1617                     GLenum glformat)
1618 {
1619    mesa_format mesaFormat = _mesa_glenum_to_compressed_format(glformat);
1620    return _mesa_format_image_size(mesaFormat, width, height, depth);
1621 }
1622 
1623 /**
1624  * Verify that a texture format is valid with a particular target
1625  *
1626  * In particular, textures with base format of \c GL_DEPTH_COMPONENT or
1627  * \c GL_DEPTH_STENCIL are only valid with certain, context dependent texture
1628  * targets.
1629  *
1630  * \param ctx             GL context
1631  * \param target          Texture target
1632  * \param internalFormat  Internal format of the texture image
1633  *
1634  * \returns true if the combination is legal, false otherwise.
1635  */
1636 bool
_mesa_legal_texture_base_format_for_target(struct gl_context * ctx,GLenum target,GLenum internalFormat)1637 _mesa_legal_texture_base_format_for_target(struct gl_context *ctx,
1638                                            GLenum target, GLenum internalFormat)
1639 {
1640    if (_mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_COMPONENT
1641        || _mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_STENCIL
1642        || _mesa_base_tex_format(ctx, internalFormat) == GL_STENCIL_INDEX) {
1643       /* Section 3.8.3 (Texture Image Specification) of the OpenGL 3.3 Core
1644        * Profile spec says:
1645        *
1646        *     "Textures with a base internal format of DEPTH_COMPONENT or
1647        *     DEPTH_STENCIL are supported by texture image specification
1648        *     commands only if target is TEXTURE_1D, TEXTURE_2D,
1649        *     TEXTURE_1D_ARRAY, TEXTURE_2D_ARRAY, TEXTURE_RECTANGLE,
1650        *     TEXTURE_CUBE_MAP, PROXY_TEXTURE_1D, PROXY_TEXTURE_2D,
1651        *     PROXY_TEXTURE_1D_ARRAY, PROXY_TEXTURE_2D_ARRAY,
1652        *     PROXY_TEXTURE_RECTANGLE, or PROXY_TEXTURE_CUBE_MAP. Using these
1653        *     formats in conjunction with any other target will result in an
1654        *     INVALID_OPERATION error."
1655        *
1656        * Cubemaps are only supported with desktop OpenGL version >= 3.0,
1657        * EXT_gpu_shader4, or, on OpenGL ES 2.0+, OES_depth_texture_cube_map.
1658        */
1659       if (target != GL_TEXTURE_1D &&
1660           target != GL_PROXY_TEXTURE_1D &&
1661           target != GL_TEXTURE_2D &&
1662           target != GL_PROXY_TEXTURE_2D &&
1663           target != GL_TEXTURE_1D_ARRAY &&
1664           target != GL_PROXY_TEXTURE_1D_ARRAY &&
1665           target != GL_TEXTURE_2D_ARRAY &&
1666           target != GL_PROXY_TEXTURE_2D_ARRAY &&
1667           target != GL_TEXTURE_RECTANGLE_ARB &&
1668           target != GL_PROXY_TEXTURE_RECTANGLE_ARB &&
1669          !((_mesa_is_cube_face(target) ||
1670             target == GL_TEXTURE_CUBE_MAP ||
1671             target == GL_PROXY_TEXTURE_CUBE_MAP) &&
1672            (ctx->Version >= 30 || ctx->Extensions.EXT_gpu_shader4
1673             || (ctx->API == API_OPENGLES2 && ctx->Extensions.OES_depth_texture_cube_map))) &&
1674           !((target == GL_TEXTURE_CUBE_MAP_ARRAY ||
1675              target == GL_PROXY_TEXTURE_CUBE_MAP_ARRAY) &&
1676             _mesa_has_texture_cube_map_array(ctx))) {
1677          return false;
1678       }
1679    }
1680 
1681    return true;
1682 }
1683 
1684 static bool
texture_formats_agree(GLenum internalFormat,GLenum format)1685 texture_formats_agree(GLenum internalFormat,
1686                       GLenum format)
1687 {
1688    GLboolean colorFormat;
1689    GLboolean is_format_depth_or_depthstencil;
1690    GLboolean is_internalFormat_depth_or_depthstencil;
1691 
1692    /* Even though there are no color-index textures, we still have to support
1693     * uploading color-index data and remapping it to RGB via the
1694     * GL_PIXEL_MAP_I_TO_[RGBA] tables.
1695     */
1696    const GLboolean indexFormat = (format == GL_COLOR_INDEX);
1697 
1698    is_internalFormat_depth_or_depthstencil =
1699       _mesa_is_depth_format(internalFormat) ||
1700       _mesa_is_depthstencil_format(internalFormat);
1701 
1702    is_format_depth_or_depthstencil =
1703       _mesa_is_depth_format(format) ||
1704       _mesa_is_depthstencil_format(format);
1705 
1706    colorFormat = _mesa_is_color_format(format);
1707 
1708    if (_mesa_is_color_format(internalFormat) && !colorFormat && !indexFormat)
1709       return false;
1710 
1711    if (is_internalFormat_depth_or_depthstencil !=
1712        is_format_depth_or_depthstencil)
1713       return false;
1714 
1715    if (_mesa_is_ycbcr_format(internalFormat) != _mesa_is_ycbcr_format(format))
1716       return false;
1717 
1718    return true;
1719 }
1720 
1721 /**
1722  * Test the combination of format, type and internal format arguments of
1723  * different texture operations on GLES.
1724  *
1725  * \param ctx GL context.
1726  * \param format pixel data format given by the user.
1727  * \param type pixel data type given by the user.
1728  * \param internalFormat internal format given by the user.
1729  * \param dimensions texture image dimensions (must be 1, 2 or 3).
1730  * \param callerName name of the caller function to print in the error message
1731  *
1732  * \return true if a error is found, false otherwise
1733  *
1734  * Currently, it is used by texture_error_check() and texsubimage_error_check().
1735  */
1736 static bool
texture_format_error_check_gles(struct gl_context * ctx,GLenum format,GLenum type,GLenum internalFormat,GLuint dimensions,const char * callerName)1737 texture_format_error_check_gles(struct gl_context *ctx, GLenum format,
1738                                 GLenum type, GLenum internalFormat,
1739                                 GLuint dimensions, const char *callerName)
1740 {
1741    GLenum err;
1742 
1743    if (_mesa_is_gles3(ctx)) {
1744       err = _mesa_es3_error_check_format_and_type(ctx, format, type,
1745                                                   internalFormat);
1746       if (err != GL_NO_ERROR) {
1747          _mesa_error(ctx, err,
1748                      "%s(format = %s, type = %s, internalformat = %s)",
1749                      callerName, _mesa_enum_to_string(format),
1750                      _mesa_enum_to_string(type),
1751                      _mesa_enum_to_string(internalFormat));
1752          return true;
1753       }
1754    }
1755    else {
1756       err = _mesa_es_error_check_format_and_type(ctx, format, type, dimensions);
1757       if (err != GL_NO_ERROR) {
1758          _mesa_error(ctx, err, "%s(format = %s, type = %s)",
1759                      callerName, _mesa_enum_to_string(format),
1760                      _mesa_enum_to_string(type));
1761          return true;
1762       }
1763    }
1764 
1765    return false;
1766 }
1767 
1768 /**
1769  * Test the glTexImage[123]D() parameters for errors.
1770  *
1771  * \param ctx GL context.
1772  * \param dimensions texture image dimensions (must be 1, 2 or 3).
1773  * \param target texture target given by the user (already validated).
1774  * \param level image level given by the user.
1775  * \param internalFormat internal format given by the user.
1776  * \param format pixel data format given by the user.
1777  * \param type pixel data type given by the user.
1778  * \param width image width given by the user.
1779  * \param height image height given by the user.
1780  * \param depth image depth given by the user.
1781  * \param border image border given by the user.
1782  *
1783  * \return GL_TRUE if a error is found, GL_FALSE otherwise
1784  *
1785  * Verifies each of the parameters against the constants specified in
1786  * __struct gl_contextRec::Const and the supported extensions, and according
1787  * to the OpenGL specification.
1788  * Note that we don't fully error-check the width, height, depth values
1789  * here.  That's done in _mesa_legal_texture_dimensions() which is used
1790  * by several other GL entrypoints.  Plus, texture dims have a special
1791  * interaction with proxy textures.
1792  */
1793 static GLboolean
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,const GLvoid * pixels)1794 texture_error_check( struct gl_context *ctx,
1795                      GLuint dimensions, GLenum target,
1796                      GLint level, GLint internalFormat,
1797                      GLenum format, GLenum type,
1798                      GLint width, GLint height,
1799                      GLint depth, GLint border,
1800                      const GLvoid *pixels )
1801 {
1802    GLenum err;
1803 
1804    /* Note: for proxy textures, some error conditions immediately generate
1805     * a GL error in the usual way.  But others do not generate a GL error.
1806     * Instead, they cause the width, height, depth, format fields of the
1807     * texture image to be zeroed-out.  The GL spec seems to indicate that the
1808     * zero-out behaviour is only used in cases related to memory allocation.
1809     */
1810 
1811    /* level check */
1812    if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) {
1813       _mesa_error(ctx, GL_INVALID_VALUE,
1814                   "glTexImage%dD(level=%d)", dimensions, level);
1815       return GL_TRUE;
1816    }
1817 
1818    /* Check border */
1819    if (border < 0 || border > 1 ||
1820        ((ctx->API != API_OPENGL_COMPAT ||
1821          target == GL_TEXTURE_RECTANGLE_NV ||
1822          target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) {
1823       _mesa_error(ctx, GL_INVALID_VALUE,
1824                   "glTexImage%dD(border=%d)", dimensions, border);
1825       return GL_TRUE;
1826    }
1827 
1828    if (width < 0 || height < 0 || depth < 0) {
1829       _mesa_error(ctx, GL_INVALID_VALUE,
1830                   "glTexImage%dD(width, height or depth < 0)", dimensions);
1831       return GL_TRUE;
1832    }
1833 
1834    /* Check incoming image format and type */
1835    err = _mesa_error_check_format_and_type(ctx, format, type);
1836    if (err != GL_NO_ERROR) {
1837       /* Prior to OpenGL-ES 2.0, an INVALID_VALUE is expected instead of
1838        * INVALID_ENUM. From page 73 OpenGL ES 1.1 spec:
1839        *
1840        *     "Specifying a value for internalformat that is not one of the
1841        *      above (acceptable) values generates the error INVALID VALUE."
1842        */
1843       if (err == GL_INVALID_ENUM && _mesa_is_gles(ctx) && ctx->Version < 20)
1844          err = GL_INVALID_VALUE;
1845 
1846       _mesa_error(ctx, err,
1847                   "glTexImage%dD(incompatible format = %s, type = %s)",
1848                   dimensions, _mesa_enum_to_string(format),
1849                   _mesa_enum_to_string(type));
1850       return GL_TRUE;
1851    }
1852 
1853    /* Check internalFormat */
1854    if (_mesa_base_tex_format(ctx, internalFormat) < 0) {
1855       _mesa_error(ctx, GL_INVALID_VALUE,
1856                   "glTexImage%dD(internalFormat=%s)",
1857                   dimensions, _mesa_enum_to_string(internalFormat));
1858       return GL_TRUE;
1859    }
1860 
1861    /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the
1862     * combinations of format, internalFormat, and type that can be used.
1863     * Formats and types that require additional extensions (e.g., GL_FLOAT
1864     * requires GL_OES_texture_float) are filtered elsewhere.
1865     */
1866    if (_mesa_is_gles(ctx) &&
1867        texture_format_error_check_gles(ctx, format, type, internalFormat,
1868                                        dimensions, "glTexImage%dD")) {
1869       return GL_TRUE;
1870    }
1871 
1872    /* validate the bound PBO, if any */
1873    if (!_mesa_validate_pbo_source(ctx, dimensions, &ctx->Unpack,
1874                                   width, height, depth, format, type,
1875                                   INT_MAX, pixels, "glTexImage")) {
1876       return GL_TRUE;
1877    }
1878 
1879    /* make sure internal format and format basically agree */
1880    if (!texture_formats_agree(internalFormat, format)) {
1881       _mesa_error(ctx, GL_INVALID_OPERATION,
1882                   "glTexImage%dD(incompatible internalFormat = %s, format = %s)",
1883                   dimensions, _mesa_enum_to_string(internalFormat),
1884                   _mesa_enum_to_string(format));
1885       return GL_TRUE;
1886    }
1887 
1888    /* additional checks for ycbcr textures */
1889    if (internalFormat == GL_YCBCR_MESA) {
1890       assert(ctx->Extensions.MESA_ycbcr_texture);
1891       if (type != GL_UNSIGNED_SHORT_8_8_MESA &&
1892           type != GL_UNSIGNED_SHORT_8_8_REV_MESA) {
1893          char message[100];
1894          _mesa_snprintf(message, sizeof(message),
1895                         "glTexImage%dD(format/type YCBCR mismatch)",
1896                         dimensions);
1897          _mesa_error(ctx, GL_INVALID_ENUM, "%s", message);
1898          return GL_TRUE; /* error */
1899       }
1900       if (target != GL_TEXTURE_2D &&
1901           target != GL_PROXY_TEXTURE_2D &&
1902           target != GL_TEXTURE_RECTANGLE_NV &&
1903           target != GL_PROXY_TEXTURE_RECTANGLE_NV) {
1904          _mesa_error(ctx, GL_INVALID_ENUM,
1905                      "glTexImage%dD(bad target for YCbCr texture)",
1906                      dimensions);
1907          return GL_TRUE;
1908       }
1909       if (border != 0) {
1910          char message[100];
1911          _mesa_snprintf(message, sizeof(message),
1912                         "glTexImage%dD(format=GL_YCBCR_MESA and border=%d)",
1913                         dimensions, border);
1914          _mesa_error(ctx, GL_INVALID_VALUE, "%s", message);
1915          return GL_TRUE;
1916       }
1917    }
1918 
1919    /* additional checks for depth textures */
1920    if (!_mesa_legal_texture_base_format_for_target(ctx, target, internalFormat)) {
1921       _mesa_error(ctx, GL_INVALID_OPERATION,
1922                   "glTexImage%dD(bad target for texture)", dimensions);
1923       return GL_TRUE;
1924    }
1925 
1926    /* additional checks for compressed textures */
1927    if (_mesa_is_compressed_format(ctx, internalFormat)) {
1928       GLenum err;
1929       if (!_mesa_target_can_be_compressed(ctx, target, internalFormat, &err)) {
1930          _mesa_error(ctx, err,
1931                      "glTexImage%dD(target can't be compressed)", dimensions);
1932          return GL_TRUE;
1933       }
1934       if (_mesa_format_no_online_compression(ctx, internalFormat)) {
1935          _mesa_error(ctx, GL_INVALID_OPERATION,
1936                      "glTexImage%dD(no compression for format)", dimensions);
1937          return GL_TRUE;
1938       }
1939       if (border != 0) {
1940          _mesa_error(ctx, GL_INVALID_OPERATION,
1941                      "glTexImage%dD(border!=0)", dimensions);
1942          return GL_TRUE;
1943       }
1944    }
1945 
1946    /* additional checks for integer textures */
1947    if ((ctx->Version >= 30 || ctx->Extensions.EXT_texture_integer) &&
1948        (_mesa_is_enum_format_integer(format) !=
1949         _mesa_is_enum_format_integer(internalFormat))) {
1950       _mesa_error(ctx, GL_INVALID_OPERATION,
1951                   "glTexImage%dD(integer/non-integer format mismatch)",
1952                   dimensions);
1953       return GL_TRUE;
1954    }
1955 
1956    if (!mutable_tex_object(ctx, target)) {
1957       _mesa_error(ctx, GL_INVALID_OPERATION,
1958                   "glTexImage%dD(immutable texture)", dimensions);
1959       return GL_TRUE;
1960    }
1961 
1962    /* if we get here, the parameters are OK */
1963    return GL_FALSE;
1964 }
1965 
1966 
1967 /**
1968  * Error checking for glCompressedTexImage[123]D().
1969  * Note that the width, height and depth values are not fully error checked
1970  * here.
1971  * \return GL_TRUE if a error is found, GL_FALSE otherwise
1972  */
1973 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,const GLvoid * data)1974 compressed_texture_error_check(struct gl_context *ctx, GLint dimensions,
1975                                GLenum target, GLint level,
1976                                GLenum internalFormat, GLsizei width,
1977                                GLsizei height, GLsizei depth, GLint border,
1978                                GLsizei imageSize, const GLvoid *data)
1979 {
1980    const GLint maxLevels = _mesa_max_texture_levels(ctx, target);
1981    GLint expectedSize;
1982    GLenum error = GL_NO_ERROR;
1983    char *reason = ""; /* no error */
1984 
1985    if (!_mesa_target_can_be_compressed(ctx, target, internalFormat, &error)) {
1986       reason = "target";
1987       goto error;
1988    }
1989 
1990    /* This will detect any invalid internalFormat value */
1991    if (!_mesa_is_compressed_format(ctx, internalFormat)) {
1992       _mesa_error(ctx, GL_INVALID_ENUM,
1993                   "glCompressedTexImage%dD(internalFormat=%s)",
1994                   dimensions, _mesa_enum_to_string(internalFormat));
1995       return GL_TRUE;
1996    }
1997 
1998    /* validate the bound PBO, if any */
1999    if (!_mesa_validate_pbo_source_compressed(ctx, dimensions, &ctx->Unpack,
2000                                              imageSize, data,
2001                                              "glCompressedTexImage")) {
2002       return GL_TRUE;
2003    }
2004 
2005    switch (internalFormat) {
2006    case GL_PALETTE4_RGB8_OES:
2007    case GL_PALETTE4_RGBA8_OES:
2008    case GL_PALETTE4_R5_G6_B5_OES:
2009    case GL_PALETTE4_RGBA4_OES:
2010    case GL_PALETTE4_RGB5_A1_OES:
2011    case GL_PALETTE8_RGB8_OES:
2012    case GL_PALETTE8_RGBA8_OES:
2013    case GL_PALETTE8_R5_G6_B5_OES:
2014    case GL_PALETTE8_RGBA4_OES:
2015    case GL_PALETTE8_RGB5_A1_OES:
2016       /* check level (note that level should be zero or less!) */
2017       if (level > 0 || level < -maxLevels) {
2018          reason = "level";
2019          error = GL_INVALID_VALUE;
2020          goto error;
2021       }
2022 
2023       if (dimensions != 2) {
2024          reason = "compressed paletted textures must be 2D";
2025          error = GL_INVALID_OPERATION;
2026          goto error;
2027       }
2028 
2029       /* Figure out the expected texture size (in bytes).  This will be
2030        * checked against the actual size later.
2031        */
2032       expectedSize = _mesa_cpal_compressed_size(level, internalFormat,
2033                                                 width, height);
2034 
2035       /* This is for the benefit of the TestProxyTexImage below.  It expects
2036        * level to be non-negative.  OES_compressed_paletted_texture uses a
2037        * weird mechanism where the level specified to glCompressedTexImage2D
2038        * is -(n-1) number of levels in the texture, and the data specifies the
2039        * complete mipmap stack.  This is done to ensure the palette is the
2040        * same for all levels.
2041        */
2042       level = -level;
2043       break;
2044 
2045    default:
2046       /* check level */
2047       if (level < 0 || level >= maxLevels) {
2048          reason = "level";
2049          error = GL_INVALID_VALUE;
2050          goto error;
2051       }
2052 
2053       /* Figure out the expected texture size (in bytes).  This will be
2054        * checked against the actual size later.
2055        */
2056       expectedSize = compressed_tex_size(width, height, depth, internalFormat);
2057       break;
2058    }
2059 
2060    /* This should really never fail */
2061    if (_mesa_base_tex_format(ctx, internalFormat) < 0) {
2062       reason = "internalFormat";
2063       error = GL_INVALID_ENUM;
2064       goto error;
2065    }
2066 
2067    /* No compressed formats support borders at this time */
2068    if (border != 0) {
2069       reason = "border != 0";
2070       error = GL_INVALID_VALUE;
2071       goto error;
2072    }
2073 
2074    /* Check for invalid pixel storage modes */
2075    if (!_mesa_compressed_pixel_storage_error_check(ctx, dimensions,
2076                                                    &ctx->Unpack,
2077                                                    "glCompressedTexImage")) {
2078       return GL_FALSE;
2079    }
2080 
2081    /* check image size in bytes */
2082    if (expectedSize != imageSize) {
2083       /* Per GL_ARB_texture_compression:  GL_INVALID_VALUE is generated [...]
2084        * if <imageSize> is not consistent with the format, dimensions, and
2085        * contents of the specified image.
2086        */
2087       reason = "imageSize inconsistent with width/height/format";
2088       error = GL_INVALID_VALUE;
2089       goto error;
2090    }
2091 
2092    if (!mutable_tex_object(ctx, target)) {
2093       reason = "immutable texture";
2094       error = GL_INVALID_OPERATION;
2095       goto error;
2096    }
2097 
2098    return GL_FALSE;
2099 
2100 error:
2101    /* Note: not all error paths exit through here. */
2102    _mesa_error(ctx, error, "glCompressedTexImage%dD(%s)",
2103                dimensions, reason);
2104    return GL_TRUE;
2105 }
2106 
2107 
2108 
2109 /**
2110  * Test glTexSubImage[123]D() parameters for errors.
2111  *
2112  * \param ctx GL context.
2113  * \param dimensions texture image dimensions (must be 1, 2 or 3).
2114  * \param target texture target given by the user (already validated)
2115  * \param level image level given by the user.
2116  * \param xoffset sub-image x offset given by the user.
2117  * \param yoffset sub-image y offset given by the user.
2118  * \param zoffset sub-image z offset given by the user.
2119  * \param format pixel data format given by the user.
2120  * \param type pixel data type given by the user.
2121  * \param width image width given by the user.
2122  * \param height image height given by the user.
2123  * \param depth image depth given by the user.
2124  *
2125  * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
2126  *
2127  * Verifies each of the parameters against the constants specified in
2128  * __struct gl_contextRec::Const and the supported extensions, and according
2129  * to the OpenGL specification.
2130  */
2131 static GLboolean
texsubimage_error_check(struct gl_context * ctx,GLuint dimensions,struct gl_texture_object * texObj,GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLint width,GLint height,GLint depth,GLenum format,GLenum type,const GLvoid * pixels,bool dsa,const char * callerName)2132 texsubimage_error_check(struct gl_context *ctx, GLuint dimensions,
2133                         struct gl_texture_object *texObj,
2134                         GLenum target, GLint level,
2135                         GLint xoffset, GLint yoffset, GLint zoffset,
2136                         GLint width, GLint height, GLint depth,
2137                         GLenum format, GLenum type, const GLvoid *pixels,
2138                         bool dsa, const char *callerName)
2139 {
2140    struct gl_texture_image *texImage;
2141    GLenum err;
2142 
2143    if (!texObj) {
2144       /* must be out of memory */
2145       _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s()", callerName);
2146       return GL_TRUE;
2147    }
2148 
2149    /* level check */
2150    if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) {
2151       _mesa_error(ctx, GL_INVALID_VALUE, "%s(level=%d)", callerName, level);
2152       return GL_TRUE;
2153    }
2154 
2155    if (error_check_subtexture_negative_dimensions(ctx, dimensions,
2156                                                   width, height, depth,
2157                                                   callerName)) {
2158       return GL_TRUE;
2159    }
2160 
2161    texImage = _mesa_select_tex_image(texObj, target, level);
2162    if (!texImage) {
2163       /* non-existant texture level */
2164       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid texture image)",
2165                   callerName);
2166       return GL_TRUE;
2167    }
2168 
2169    err = _mesa_error_check_format_and_type(ctx, format, type);
2170    if (err != GL_NO_ERROR) {
2171       _mesa_error(ctx, err,
2172                   "%s(incompatible format = %s, type = %s)",
2173                   callerName, _mesa_enum_to_string(format),
2174                   _mesa_enum_to_string(type));
2175       return GL_TRUE;
2176    }
2177 
2178    /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the
2179     * combinations of format, internalFormat, and type that can be used.
2180     * Formats and types that require additional extensions (e.g., GL_FLOAT
2181     * requires GL_OES_texture_float) are filtered elsewhere.
2182     */
2183    if (_mesa_is_gles(ctx) &&
2184        texture_format_error_check_gles(ctx, format, type,
2185                                        texImage->InternalFormat,
2186                                        dimensions, callerName)) {
2187       return GL_TRUE;
2188    }
2189 
2190    /* validate the bound PBO, if any */
2191    if (!_mesa_validate_pbo_source(ctx, dimensions, &ctx->Unpack,
2192                                   width, height, depth, format, type,
2193                                   INT_MAX, pixels, callerName)) {
2194       return GL_TRUE;
2195    }
2196 
2197    if (error_check_subtexture_dimensions(ctx, dimensions,
2198                                          texImage, xoffset, yoffset, zoffset,
2199                                          width, height, depth, callerName)) {
2200       return GL_TRUE;
2201    }
2202 
2203    if (_mesa_is_format_compressed(texImage->TexFormat)) {
2204       if (_mesa_format_no_online_compression(ctx, texImage->InternalFormat)) {
2205          _mesa_error(ctx, GL_INVALID_OPERATION,
2206                "%s(no compression for format)", callerName);
2207          return GL_TRUE;
2208       }
2209    }
2210 
2211    if (ctx->Version >= 30 || ctx->Extensions.EXT_texture_integer) {
2212       /* both source and dest must be integer-valued, or neither */
2213       if (_mesa_is_format_integer_color(texImage->TexFormat) !=
2214           _mesa_is_enum_format_integer(format)) {
2215          _mesa_error(ctx, GL_INVALID_OPERATION,
2216                      "%s(integer/non-integer format mismatch)", callerName);
2217          return GL_TRUE;
2218       }
2219    }
2220 
2221    return GL_FALSE;
2222 }
2223 
2224 
2225 /**
2226  * Test glCopyTexImage[12]D() parameters for errors.
2227  *
2228  * \param ctx GL context.
2229  * \param dimensions texture image dimensions (must be 1, 2 or 3).
2230  * \param target texture target given by the user.
2231  * \param level image level given by the user.
2232  * \param internalFormat internal format given by the user.
2233  * \param width image width given by the user.
2234  * \param height image height given by the user.
2235  * \param border texture border.
2236  *
2237  * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
2238  *
2239  * Verifies each of the parameters against the constants specified in
2240  * __struct gl_contextRec::Const and the supported extensions, and according
2241  * to the OpenGL specification.
2242  */
2243 static GLboolean
copytexture_error_check(struct gl_context * ctx,GLuint dimensions,GLenum target,GLint level,GLint internalFormat,GLint width,GLint height,GLint border)2244 copytexture_error_check( struct gl_context *ctx, GLuint dimensions,
2245                          GLenum target, GLint level, GLint internalFormat,
2246                          GLint width, GLint height, GLint border )
2247 {
2248    GLint baseFormat;
2249    GLint rb_base_format;
2250    struct gl_renderbuffer *rb;
2251    GLenum rb_internal_format;
2252 
2253    /* check target */
2254    if (!legal_texsubimage_target(ctx, dimensions, target, false)) {
2255       _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexImage%uD(target=%s)",
2256                   dimensions, _mesa_enum_to_string(target));
2257       return GL_TRUE;
2258    }
2259 
2260    /* level check */
2261    if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) {
2262       _mesa_error(ctx, GL_INVALID_VALUE,
2263                   "glCopyTexImage%dD(level=%d)", dimensions, level);
2264       return GL_TRUE;
2265    }
2266 
2267    /* Check that the source buffer is complete */
2268    if (_mesa_is_user_fbo(ctx->ReadBuffer)) {
2269       if (ctx->ReadBuffer->_Status == 0) {
2270          _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer);
2271       }
2272       if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
2273          _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
2274                      "glCopyTexImage%dD(invalid readbuffer)", dimensions);
2275          return GL_TRUE;
2276       }
2277 
2278       if (ctx->ReadBuffer->Visual.samples > 0) {
2279          _mesa_error(ctx, GL_INVALID_OPERATION,
2280                      "glCopyTexImage%dD(multisample FBO)", dimensions);
2281          return GL_TRUE;
2282       }
2283    }
2284 
2285    /* Check border */
2286    if (border < 0 || border > 1 ||
2287        ((ctx->API != API_OPENGL_COMPAT ||
2288          target == GL_TEXTURE_RECTANGLE_NV ||
2289          target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) {
2290       _mesa_error(ctx, GL_INVALID_VALUE,
2291                   "glCopyTexImage%dD(border=%d)", dimensions, border);
2292       return GL_TRUE;
2293    }
2294 
2295    /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the
2296     * internalFormat.
2297     */
2298    if (_mesa_is_gles(ctx) && !_mesa_is_gles3(ctx)) {
2299       switch (internalFormat) {
2300       case GL_ALPHA:
2301       case GL_RGB:
2302       case GL_RGBA:
2303       case GL_LUMINANCE:
2304       case GL_LUMINANCE_ALPHA:
2305          break;
2306       default:
2307          _mesa_error(ctx, GL_INVALID_ENUM,
2308                      "glCopyTexImage%dD(internalFormat=%s)", dimensions,
2309                      _mesa_enum_to_string(internalFormat));
2310          return GL_TRUE;
2311       }
2312    } else {
2313       /*
2314        * Section 8.6 (Alternate Texture Image Specification Commands) of the
2315        * OpenGL 4.5 (Compatibility Profile) spec says:
2316        *
2317        *     "Parameters level, internalformat, and border are specified using
2318        *     the same values, with the same meanings, as the corresponding
2319        *     arguments of TexImage2D, except that internalformat may not be
2320        *     specified as 1, 2, 3, or 4."
2321        */
2322       if (internalFormat >= 1 && internalFormat <= 4) {
2323          _mesa_error(ctx, GL_INVALID_ENUM,
2324                      "glCopyTexImage%dD(internalFormat=%d)", dimensions,
2325                      internalFormat);
2326          return GL_TRUE;
2327       }
2328    }
2329 
2330    baseFormat = _mesa_base_tex_format(ctx, internalFormat);
2331    if (baseFormat < 0) {
2332       _mesa_error(ctx, GL_INVALID_ENUM,
2333                   "glCopyTexImage%dD(internalFormat=%s)", dimensions,
2334                   _mesa_enum_to_string(internalFormat));
2335       return GL_TRUE;
2336    }
2337 
2338    rb = _mesa_get_read_renderbuffer_for_format(ctx, internalFormat);
2339    if (rb == NULL) {
2340       _mesa_error(ctx, GL_INVALID_OPERATION,
2341                   "glCopyTexImage%dD(read buffer)", dimensions);
2342       return GL_TRUE;
2343    }
2344 
2345    rb_internal_format = rb->InternalFormat;
2346    rb_base_format = _mesa_base_tex_format(ctx, rb->InternalFormat);
2347    if (_mesa_is_color_format(internalFormat)) {
2348       if (rb_base_format < 0) {
2349          _mesa_error(ctx, GL_INVALID_VALUE,
2350                      "glCopyTexImage%dD(internalFormat=%s)", dimensions,
2351                      _mesa_enum_to_string(internalFormat));
2352          return GL_TRUE;
2353       }
2354    }
2355 
2356    if (_mesa_is_gles(ctx)) {
2357       bool valid = true;
2358       if (_mesa_base_format_component_count(baseFormat) >
2359           _mesa_base_format_component_count(rb_base_format)) {
2360          valid = false;
2361       }
2362       if (baseFormat == GL_DEPTH_COMPONENT ||
2363           baseFormat == GL_DEPTH_STENCIL ||
2364           baseFormat == GL_STENCIL_INDEX ||
2365           rb_base_format == GL_DEPTH_COMPONENT ||
2366           rb_base_format == GL_DEPTH_STENCIL ||
2367           rb_base_format == GL_STENCIL_INDEX ||
2368           ((baseFormat == GL_LUMINANCE_ALPHA ||
2369             baseFormat == GL_ALPHA) &&
2370            rb_base_format != GL_RGBA) ||
2371           internalFormat == GL_RGB9_E5) {
2372          valid = false;
2373       }
2374       if (internalFormat == GL_RGB9_E5) {
2375          valid = false;
2376       }
2377       if (!valid) {
2378          _mesa_error(ctx, GL_INVALID_OPERATION,
2379                      "glCopyTexImage%dD(internalFormat=%s)", dimensions,
2380                      _mesa_enum_to_string(internalFormat));
2381          return GL_TRUE;
2382       }
2383    }
2384 
2385    if (_mesa_is_gles3(ctx)) {
2386       bool rb_is_srgb = false;
2387       bool dst_is_srgb = false;
2388 
2389       if (ctx->Extensions.EXT_framebuffer_sRGB &&
2390           _mesa_get_format_color_encoding(rb->Format) == GL_SRGB) {
2391          rb_is_srgb = true;
2392       }
2393 
2394       if (_mesa_get_linear_internalformat(internalFormat) != internalFormat) {
2395          dst_is_srgb = true;
2396       }
2397 
2398       if (rb_is_srgb != dst_is_srgb) {
2399          /* Page 137 (page 149 of the PDF) in section 3.8.5 of the
2400           * OpenGLES 3.0.0 spec says:
2401           *
2402           *     "The error INVALID_OPERATION is also generated if the
2403           *     value of FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING for the
2404           *     framebuffer attachment corresponding to the read buffer
2405           *     is LINEAR (see section 6.1.13) and internalformat is
2406           *     one of the sRGB formats described in section 3.8.16, or
2407           *     if the value of FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING is
2408           *     SRGB and internalformat is not one of the sRGB formats."
2409           */
2410          _mesa_error(ctx, GL_INVALID_OPERATION,
2411                      "glCopyTexImage%dD(srgb usage mismatch)", dimensions);
2412          return GL_TRUE;
2413       }
2414 
2415       /* Page 139, Table 3.15 of OpenGL ES 3.0 spec does not define ReadPixels
2416        * types for SNORM formats. Also, conversion to SNORM formats is not
2417        * allowed by Table 3.2 on Page 110.
2418        */
2419       if (_mesa_is_enum_format_snorm(internalFormat)) {
2420          _mesa_error(ctx, GL_INVALID_OPERATION,
2421                      "glCopyTexImage%dD(internalFormat=%s)", dimensions,
2422                      _mesa_enum_to_string(internalFormat));
2423          return GL_TRUE;
2424       }
2425    }
2426 
2427    if (!_mesa_source_buffer_exists(ctx, baseFormat)) {
2428       _mesa_error(ctx, GL_INVALID_OPERATION,
2429                   "glCopyTexImage%dD(missing readbuffer)", dimensions);
2430       return GL_TRUE;
2431    }
2432 
2433    /* From the EXT_texture_integer spec:
2434     *
2435     *     "INVALID_OPERATION is generated by CopyTexImage* and CopyTexSubImage*
2436     *      if the texture internalformat is an integer format and the read color
2437     *      buffer is not an integer format, or if the internalformat is not an
2438     *      integer format and the read color buffer is an integer format."
2439     */
2440    if (_mesa_is_color_format(internalFormat)) {
2441       bool is_int = _mesa_is_enum_format_integer(internalFormat);
2442       bool is_rbint = _mesa_is_enum_format_integer(rb_internal_format);
2443       bool is_unorm = _mesa_is_enum_format_unorm(internalFormat);
2444       bool is_rbunorm = _mesa_is_enum_format_unorm(rb_internal_format);
2445       if (is_int || is_rbint) {
2446          if (is_int != is_rbint) {
2447             _mesa_error(ctx, GL_INVALID_OPERATION,
2448                         "glCopyTexImage%dD(integer vs non-integer)", dimensions);
2449             return GL_TRUE;
2450          } else if (_mesa_is_gles(ctx) &&
2451                     _mesa_is_enum_format_unsigned_int(internalFormat) !=
2452                       _mesa_is_enum_format_unsigned_int(rb_internal_format)) {
2453             _mesa_error(ctx, GL_INVALID_OPERATION,
2454                         "glCopyTexImage%dD(signed vs unsigned integer)", dimensions);
2455             return GL_TRUE;
2456          }
2457       }
2458 
2459       /* From page 138 of OpenGL ES 3.0 spec:
2460        *    "The error INVALID_OPERATION is generated if floating-point RGBA
2461        *    data is required; if signed integer RGBA data is required and the
2462        *    format of the current color buffer is not signed integer; if
2463        *    unsigned integer RGBA data is required and the format of the
2464        *    current color buffer is not unsigned integer; or if fixed-point
2465        *    RGBA data is required and the format of the current color buffer
2466        *    is not fixed-point.
2467        */
2468       if (_mesa_is_gles(ctx) && is_unorm != is_rbunorm)
2469             _mesa_error(ctx, GL_INVALID_OPERATION,
2470                         "glCopyTexImage%dD(unorm vs non-unorm)", dimensions);
2471    }
2472 
2473    if (_mesa_is_compressed_format(ctx, internalFormat)) {
2474       GLenum err;
2475       if (!_mesa_target_can_be_compressed(ctx, target, internalFormat, &err)) {
2476          _mesa_error(ctx, err,
2477                      "glCopyTexImage%dD(target can't be compressed)", dimensions);
2478          return GL_TRUE;
2479       }
2480       if (_mesa_format_no_online_compression(ctx, internalFormat)) {
2481          _mesa_error(ctx, GL_INVALID_OPERATION,
2482                "glCopyTexImage%dD(no compression for format)", dimensions);
2483          return GL_TRUE;
2484       }
2485       if (border != 0) {
2486          _mesa_error(ctx, GL_INVALID_OPERATION,
2487                      "glCopyTexImage%dD(border!=0)", dimensions);
2488          return GL_TRUE;
2489       }
2490    }
2491 
2492    if (!mutable_tex_object(ctx, target)) {
2493       _mesa_error(ctx, GL_INVALID_OPERATION,
2494                   "glCopyTexImage%dD(immutable texture)", dimensions);
2495       return GL_TRUE;
2496    }
2497 
2498    /* if we get here, the parameters are OK */
2499    return GL_FALSE;
2500 }
2501 
2502 
2503 /**
2504  * Test glCopyTexSubImage[12]D() parameters for errors.
2505  * \return GL_TRUE if an error was detected, or GL_FALSE if no errors.
2506  */
2507 static GLboolean
copytexsubimage_error_check(struct gl_context * ctx,GLuint dimensions,const struct gl_texture_object * texObj,GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLint width,GLint height,const char * caller)2508 copytexsubimage_error_check(struct gl_context *ctx, GLuint dimensions,
2509                             const struct gl_texture_object *texObj,
2510                             GLenum target, GLint level,
2511                             GLint xoffset, GLint yoffset, GLint zoffset,
2512                             GLint width, GLint height, const char *caller)
2513 {
2514    struct gl_texture_image *texImage;
2515 
2516    /* Check that the source buffer is complete */
2517    if (_mesa_is_user_fbo(ctx->ReadBuffer)) {
2518       if (ctx->ReadBuffer->_Status == 0) {
2519          _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer);
2520       }
2521       if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) {
2522          _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT,
2523                      "%s(invalid readbuffer)", caller);
2524          return GL_TRUE;
2525       }
2526 
2527       if (ctx->ReadBuffer->Visual.samples > 0) {
2528          _mesa_error(ctx, GL_INVALID_OPERATION,
2529                 "%s(multisample FBO)", caller);
2530          return GL_TRUE;
2531       }
2532    }
2533 
2534    /* Check level */
2535    if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) {
2536       _mesa_error(ctx, GL_INVALID_VALUE, "%s(level=%d)", caller, level);
2537       return GL_TRUE;
2538    }
2539 
2540    /* Get dest image pointers */
2541    if (!texObj) {
2542       _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s()", caller);
2543       return GL_TRUE;
2544    }
2545 
2546    texImage = _mesa_select_tex_image(texObj, target, level);
2547    if (!texImage) {
2548       /* destination image does not exist */
2549       _mesa_error(ctx, GL_INVALID_OPERATION,
2550                   "%s(invalid texture image)", caller);
2551       return GL_TRUE;
2552    }
2553 
2554    if (error_check_subtexture_negative_dimensions(ctx, dimensions,
2555                                                   width, height, 1, caller)) {
2556       return GL_TRUE;
2557    }
2558 
2559    if (error_check_subtexture_dimensions(ctx, dimensions, texImage,
2560                                          xoffset, yoffset, zoffset,
2561                                          width, height, 1, caller)) {
2562       return GL_TRUE;
2563    }
2564 
2565    if (_mesa_is_format_compressed(texImage->TexFormat)) {
2566       if (_mesa_format_no_online_compression(ctx, texImage->InternalFormat)) {
2567          _mesa_error(ctx, GL_INVALID_OPERATION,
2568                "%s(no compression for format)", caller);
2569          return GL_TRUE;
2570       }
2571    }
2572 
2573    if (texImage->InternalFormat == GL_YCBCR_MESA) {
2574       _mesa_error(ctx, GL_INVALID_OPERATION, "%s()", caller);
2575       return GL_TRUE;
2576    }
2577 
2578    if (!_mesa_source_buffer_exists(ctx, texImage->_BaseFormat)) {
2579       _mesa_error(ctx, GL_INVALID_OPERATION,
2580                   "%s(missing readbuffer, format=%s)", caller,
2581                   _mesa_enum_to_string(texImage->_BaseFormat));
2582       return GL_TRUE;
2583    }
2584 
2585    /* From the EXT_texture_integer spec:
2586     *
2587     *     "INVALID_OPERATION is generated by CopyTexImage* and
2588     *     CopyTexSubImage* if the texture internalformat is an integer format
2589     *     and the read color buffer is not an integer format, or if the
2590     *     internalformat is not an integer format and the read color buffer
2591     *     is an integer format."
2592     */
2593    if (_mesa_is_color_format(texImage->InternalFormat)) {
2594       struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer;
2595 
2596       if (_mesa_is_format_integer_color(rb->Format) !=
2597           _mesa_is_format_integer_color(texImage->TexFormat)) {
2598          _mesa_error(ctx, GL_INVALID_OPERATION,
2599                      "%s(integer vs non-integer)", caller);
2600          return GL_TRUE;
2601       }
2602    }
2603 
2604    /* In the ES 3.2 specification's Table 8.13 (Valid CopyTexImage source
2605     * framebuffer/destination texture base internal format combinations),
2606     * all the entries for stencil are left blank (unsupported).
2607     */
2608    if (_mesa_is_gles(ctx) && _mesa_is_stencil_format(texImage->_BaseFormat)) {
2609       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(stencil disallowed)", caller);
2610       return GL_TRUE;
2611    }
2612 
2613    /* if we get here, the parameters are OK */
2614    return GL_FALSE;
2615 }
2616 
2617 
2618 /** Callback info for walking over FBO hash table */
2619 struct cb_info
2620 {
2621    struct gl_context *ctx;
2622    struct gl_texture_object *texObj;
2623    GLuint level, face;
2624 };
2625 
2626 
2627 /**
2628  * Check render to texture callback.  Called from _mesa_HashWalk().
2629  */
2630 static void
check_rtt_cb(GLuint key,void * data,void * userData)2631 check_rtt_cb(GLuint key, void *data, void *userData)
2632 {
2633    struct gl_framebuffer *fb = (struct gl_framebuffer *) data;
2634    const struct cb_info *info = (struct cb_info *) userData;
2635    struct gl_context *ctx = info->ctx;
2636    const struct gl_texture_object *texObj = info->texObj;
2637    const GLuint level = info->level, face = info->face;
2638 
2639    /* If this is a user-created FBO */
2640    if (_mesa_is_user_fbo(fb)) {
2641       GLuint i;
2642       /* check if any of the FBO's attachments point to 'texObj' */
2643       for (i = 0; i < BUFFER_COUNT; i++) {
2644          struct gl_renderbuffer_attachment *att = fb->Attachment + i;
2645          if (att->Type == GL_TEXTURE &&
2646              att->Texture == texObj &&
2647              att->TextureLevel == level &&
2648              att->CubeMapFace == face) {
2649             _mesa_update_texture_renderbuffer(ctx, fb, att);
2650             assert(att->Renderbuffer->TexImage);
2651             /* Mark fb status as indeterminate to force re-validation */
2652             fb->_Status = 0;
2653 
2654             /* Make sure that the revalidation actually happens if this is
2655              * being done to currently-bound buffers.
2656              */
2657             if (fb == ctx->DrawBuffer || fb == ctx->ReadBuffer)
2658                ctx->NewState |= _NEW_BUFFERS;
2659          }
2660       }
2661    }
2662 }
2663 
2664 
2665 /**
2666  * When a texture image is specified we have to check if it's bound to
2667  * any framebuffer objects (render to texture) in order to detect changes
2668  * in size or format since that effects FBO completeness.
2669  * Any FBOs rendering into the texture must be re-validated.
2670  */
2671 void
_mesa_update_fbo_texture(struct gl_context * ctx,struct gl_texture_object * texObj,GLuint face,GLuint level)2672 _mesa_update_fbo_texture(struct gl_context *ctx,
2673                          struct gl_texture_object *texObj,
2674                          GLuint face, GLuint level)
2675 {
2676    /* Only check this texture if it's been marked as RenderToTexture */
2677    if (texObj->_RenderToTexture) {
2678       struct cb_info info;
2679       info.ctx = ctx;
2680       info.texObj = texObj;
2681       info.level = level;
2682       info.face = face;
2683       _mesa_HashWalk(ctx->Shared->FrameBuffers, check_rtt_cb, &info);
2684    }
2685 }
2686 
2687 
2688 /**
2689  * If the texture object's GenerateMipmap flag is set and we've
2690  * changed the texture base level image, regenerate the rest of the
2691  * mipmap levels now.
2692  */
2693 static inline void
check_gen_mipmap(struct gl_context * ctx,GLenum target,struct gl_texture_object * texObj,GLint level)2694 check_gen_mipmap(struct gl_context *ctx, GLenum target,
2695                  struct gl_texture_object *texObj, GLint level)
2696 {
2697    if (texObj->GenerateMipmap &&
2698        level == texObj->BaseLevel &&
2699        level < texObj->MaxLevel) {
2700       assert(ctx->Driver.GenerateMipmap);
2701       ctx->Driver.GenerateMipmap(ctx, target, texObj);
2702    }
2703 }
2704 
2705 
2706 /** Debug helper: override the user-requested internal format */
2707 static GLenum
override_internal_format(GLenum internalFormat,GLint width,GLint height)2708 override_internal_format(GLenum internalFormat, GLint width, GLint height)
2709 {
2710 #if 0
2711    if (internalFormat == GL_RGBA16F_ARB ||
2712        internalFormat == GL_RGBA32F_ARB) {
2713       printf("Convert rgba float tex to int %d x %d\n", width, height);
2714       return GL_RGBA;
2715    }
2716    else if (internalFormat == GL_RGB16F_ARB ||
2717             internalFormat == GL_RGB32F_ARB) {
2718       printf("Convert rgb float tex to int %d x %d\n", width, height);
2719       return GL_RGB;
2720    }
2721    else if (internalFormat == GL_LUMINANCE_ALPHA16F_ARB ||
2722             internalFormat == GL_LUMINANCE_ALPHA32F_ARB) {
2723       printf("Convert luminance float tex to int %d x %d\n", width, height);
2724       return GL_LUMINANCE_ALPHA;
2725    }
2726    else if (internalFormat == GL_LUMINANCE16F_ARB ||
2727             internalFormat == GL_LUMINANCE32F_ARB) {
2728       printf("Convert luminance float tex to int %d x %d\n", width, height);
2729       return GL_LUMINANCE;
2730    }
2731    else if (internalFormat == GL_ALPHA16F_ARB ||
2732             internalFormat == GL_ALPHA32F_ARB) {
2733       printf("Convert luminance float tex to int %d x %d\n", width, height);
2734       return GL_ALPHA;
2735    }
2736    /*
2737    else if (internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) {
2738       internalFormat = GL_RGBA;
2739    }
2740    */
2741    else {
2742       return internalFormat;
2743    }
2744 #else
2745    return internalFormat;
2746 #endif
2747 }
2748 
2749 
2750 /**
2751  * Choose the actual hardware format for a texture image.
2752  * Try to use the same format as the previous image level when possible.
2753  * Otherwise, ask the driver for the best format.
2754  * It's important to try to choose a consistant format for all levels
2755  * for efficient texture memory layout/allocation.  In particular, this
2756  * comes up during automatic mipmap generation.
2757  */
2758 mesa_format
_mesa_choose_texture_format(struct gl_context * ctx,struct gl_texture_object * texObj,GLenum target,GLint level,GLenum internalFormat,GLenum format,GLenum type)2759 _mesa_choose_texture_format(struct gl_context *ctx,
2760                             struct gl_texture_object *texObj,
2761                             GLenum target, GLint level,
2762                             GLenum internalFormat, GLenum format, GLenum type)
2763 {
2764    mesa_format f;
2765 
2766    /* see if we've already chosen a format for the previous level */
2767    if (level > 0) {
2768       struct gl_texture_image *prevImage =
2769 	 _mesa_select_tex_image(texObj, target, level - 1);
2770       /* See if the prev level is defined and has an internal format which
2771        * matches the new internal format.
2772        */
2773       if (prevImage &&
2774           prevImage->Width > 0 &&
2775           prevImage->InternalFormat == internalFormat) {
2776          /* use the same format */
2777          assert(prevImage->TexFormat != MESA_FORMAT_NONE);
2778          return prevImage->TexFormat;
2779       }
2780    }
2781 
2782    /* If the application requested compression to an S3TC format but we don't
2783     * have the DXTn library, force a generic compressed format instead.
2784     */
2785    if (internalFormat != format && format != GL_NONE) {
2786       const GLenum before = internalFormat;
2787 
2788       switch (internalFormat) {
2789       case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
2790          if (!ctx->Mesa_DXTn)
2791             internalFormat = GL_COMPRESSED_RGB;
2792          break;
2793       case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
2794       case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
2795       case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
2796          if (!ctx->Mesa_DXTn)
2797             internalFormat = GL_COMPRESSED_RGBA;
2798          break;
2799       default:
2800          break;
2801       }
2802 
2803       if (before != internalFormat) {
2804          _mesa_warning(ctx,
2805                        "DXT compression requested (%s), "
2806                        "but libtxc_dxtn library not installed.  Using %s "
2807                        "instead.",
2808                        _mesa_enum_to_string(before),
2809                        _mesa_enum_to_string(internalFormat));
2810       }
2811    }
2812 
2813    /* choose format from scratch */
2814    f = ctx->Driver.ChooseTextureFormat(ctx, target, internalFormat,
2815                                        format, type);
2816    assert(f != MESA_FORMAT_NONE);
2817    return f;
2818 }
2819 
2820 
2821 /**
2822  * Adjust pixel unpack params and image dimensions to strip off the
2823  * one-pixel texture border.
2824  *
2825  * Gallium and intel don't support texture borders.  They've seldem been used
2826  * and seldom been implemented correctly anyway.
2827  *
2828  * \param unpackNew returns the new pixel unpack parameters
2829  */
2830 static void
strip_texture_border(GLenum target,GLint * width,GLint * height,GLint * depth,const struct gl_pixelstore_attrib * unpack,struct gl_pixelstore_attrib * unpackNew)2831 strip_texture_border(GLenum target,
2832                      GLint *width, GLint *height, GLint *depth,
2833                      const struct gl_pixelstore_attrib *unpack,
2834                      struct gl_pixelstore_attrib *unpackNew)
2835 {
2836    assert(width);
2837    assert(height);
2838    assert(depth);
2839 
2840    *unpackNew = *unpack;
2841 
2842    if (unpackNew->RowLength == 0)
2843       unpackNew->RowLength = *width;
2844 
2845    if (unpackNew->ImageHeight == 0)
2846       unpackNew->ImageHeight = *height;
2847 
2848    assert(*width >= 3);
2849    unpackNew->SkipPixels++;  /* skip the border */
2850    *width = *width - 2;      /* reduce the width by two border pixels */
2851 
2852    /* The min height of a texture with a border is 3 */
2853    if (*height >= 3 && target != GL_TEXTURE_1D_ARRAY) {
2854       unpackNew->SkipRows++;  /* skip the border */
2855       *height = *height - 2;  /* reduce the height by two border pixels */
2856    }
2857 
2858    if (*depth >= 3 &&
2859        target != GL_TEXTURE_2D_ARRAY &&
2860        target != GL_TEXTURE_CUBE_MAP_ARRAY) {
2861       unpackNew->SkipImages++;  /* skip the border */
2862       *depth = *depth - 2;      /* reduce the depth by two border pixels */
2863    }
2864 }
2865 
2866 
2867 /**
2868  * Common code to implement all the glTexImage1D/2D/3D functions
2869  * as well as glCompressedTexImage1D/2D/3D.
2870  * \param compressed  only GL_TRUE for glCompressedTexImage1D/2D/3D calls.
2871  * \param format  the user's image format (only used if !compressed)
2872  * \param type  the user's image type (only used if !compressed)
2873  * \param imageSize  only used for glCompressedTexImage1D/2D/3D calls.
2874  */
2875 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)2876 teximage(struct gl_context *ctx, GLboolean compressed, GLuint dims,
2877          GLenum target, GLint level, GLint internalFormat,
2878          GLsizei width, GLsizei height, GLsizei depth,
2879          GLint border, GLenum format, GLenum type,
2880          GLsizei imageSize, const GLvoid *pixels)
2881 {
2882    const char *func = compressed ? "glCompressedTexImage" : "glTexImage";
2883    struct gl_pixelstore_attrib unpack_no_border;
2884    const struct gl_pixelstore_attrib *unpack = &ctx->Unpack;
2885    struct gl_texture_object *texObj;
2886    mesa_format texFormat;
2887    GLboolean dimensionsOK, sizeOK;
2888 
2889    FLUSH_VERTICES(ctx, 0);
2890 
2891    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) {
2892       if (compressed)
2893          _mesa_debug(ctx,
2894                      "glCompressedTexImage%uD %s %d %s %d %d %d %d %p\n",
2895                      dims,
2896                      _mesa_enum_to_string(target), level,
2897                      _mesa_enum_to_string(internalFormat),
2898                      width, height, depth, border, pixels);
2899       else
2900          _mesa_debug(ctx,
2901                      "glTexImage%uD %s %d %s %d %d %d %d %s %s %p\n",
2902                      dims,
2903                      _mesa_enum_to_string(target), level,
2904                      _mesa_enum_to_string(internalFormat),
2905                      width, height, depth, border,
2906                      _mesa_enum_to_string(format),
2907                      _mesa_enum_to_string(type), pixels);
2908    }
2909 
2910    internalFormat = override_internal_format(internalFormat, width, height);
2911 
2912    /* target error checking */
2913    if (!legal_teximage_target(ctx, dims, target)) {
2914       _mesa_error(ctx, GL_INVALID_ENUM, "%s%uD(target=%s)",
2915                   func, dims, _mesa_enum_to_string(target));
2916       return;
2917    }
2918 
2919    /* general error checking */
2920    if (compressed) {
2921       if (compressed_texture_error_check(ctx, dims, target, level,
2922                                          internalFormat,
2923                                          width, height, depth,
2924                                          border, imageSize, pixels))
2925          return;
2926    }
2927    else {
2928       if (texture_error_check(ctx, dims, target, level, internalFormat,
2929                               format, type, width, height, depth, border,
2930                               pixels))
2931          return;
2932    }
2933 
2934    /* Here we convert a cpal compressed image into a regular glTexImage2D
2935     * call by decompressing the texture.  If we really want to support cpal
2936     * textures in any driver this would have to be changed.
2937     */
2938    if (ctx->API == API_OPENGLES && compressed && dims == 2) {
2939       switch (internalFormat) {
2940       case GL_PALETTE4_RGB8_OES:
2941       case GL_PALETTE4_RGBA8_OES:
2942       case GL_PALETTE4_R5_G6_B5_OES:
2943       case GL_PALETTE4_RGBA4_OES:
2944       case GL_PALETTE4_RGB5_A1_OES:
2945       case GL_PALETTE8_RGB8_OES:
2946       case GL_PALETTE8_RGBA8_OES:
2947       case GL_PALETTE8_R5_G6_B5_OES:
2948       case GL_PALETTE8_RGBA4_OES:
2949       case GL_PALETTE8_RGB5_A1_OES:
2950          _mesa_cpal_compressed_teximage2d(target, level, internalFormat,
2951                                           width, height, imageSize, pixels);
2952          return;
2953       }
2954    }
2955 
2956    texObj = _mesa_get_current_tex_object(ctx, target);
2957    assert(texObj);
2958 
2959    if (compressed) {
2960       /* For glCompressedTexImage() the driver has no choice about the
2961        * texture format since we'll never transcode the user's compressed
2962        * image data.  The internalFormat was error checked earlier.
2963        */
2964       texFormat = _mesa_glenum_to_compressed_format(internalFormat);
2965    }
2966    else {
2967       /* In case of HALF_FLOAT_OES or FLOAT_OES, find corresponding sized
2968        * internal floating point format for the given base format.
2969        */
2970       if (_mesa_is_gles(ctx) && format == internalFormat) {
2971          if (type == GL_FLOAT) {
2972             texObj->_IsFloat = GL_TRUE;
2973          } else if (type == GL_HALF_FLOAT_OES || type == GL_HALF_FLOAT) {
2974             texObj->_IsHalfFloat = GL_TRUE;
2975          }
2976 
2977          internalFormat = adjust_for_oes_float_texture(ctx, format, type);
2978       }
2979 
2980       texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
2981                                               internalFormat, format, type);
2982    }
2983 
2984    assert(texFormat != MESA_FORMAT_NONE);
2985 
2986    /* check that width, height, depth are legal for the mipmap level */
2987    dimensionsOK = _mesa_legal_texture_dimensions(ctx, target, level, width,
2988                                                  height, depth, border);
2989 
2990    /* check that the texture won't take too much memory, etc */
2991    sizeOK = ctx->Driver.TestProxyTexImage(ctx, proxy_target(target),
2992                                           0, level, texFormat, 1,
2993                                           width, height, depth);
2994 
2995    if (_mesa_is_proxy_texture(target)) {
2996       /* Proxy texture: just clear or set state depending on error checking */
2997       struct gl_texture_image *texImage =
2998          get_proxy_tex_image(ctx, target, level);
2999 
3000       if (!texImage)
3001          return;  /* GL_OUT_OF_MEMORY already recorded */
3002 
3003       if (dimensionsOK && sizeOK) {
3004          _mesa_init_teximage_fields(ctx, texImage, width, height, depth,
3005                                     border, internalFormat, texFormat);
3006       }
3007       else {
3008          clear_teximage_fields(texImage);
3009       }
3010    }
3011    else {
3012       /* non-proxy target */
3013       const GLuint face = _mesa_tex_target_to_face(target);
3014       struct gl_texture_image *texImage;
3015 
3016       if (!dimensionsOK) {
3017          _mesa_error(ctx, GL_INVALID_VALUE,
3018                      "%s%uD(invalid width or height or depth)",
3019                      func, dims);
3020          return;
3021       }
3022 
3023       if (!sizeOK) {
3024          _mesa_error(ctx, GL_OUT_OF_MEMORY,
3025                      "%s%uD(image too large: %d x %d x %d, %s format)",
3026                      func, dims, width, height, depth,
3027                      _mesa_enum_to_string(internalFormat));
3028          return;
3029       }
3030 
3031       /* Allow a hardware driver to just strip out the border, to provide
3032        * reliable but slightly incorrect hardware rendering instead of
3033        * rarely-tested software fallback rendering.
3034        */
3035       if (border && ctx->Const.StripTextureBorder) {
3036 	 strip_texture_border(target, &width, &height, &depth, unpack,
3037 			      &unpack_no_border);
3038          border = 0;
3039 	 unpack = &unpack_no_border;
3040       }
3041 
3042       if (ctx->NewState & _NEW_PIXEL)
3043 	 _mesa_update_state(ctx);
3044 
3045       _mesa_lock_texture(ctx, texObj);
3046       {
3047 	 texImage = _mesa_get_tex_image(ctx, texObj, target, level);
3048 
3049 	 if (!texImage) {
3050 	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s%uD", func, dims);
3051 	 }
3052          else {
3053             ctx->Driver.FreeTextureImageBuffer(ctx, texImage);
3054 
3055             _mesa_init_teximage_fields(ctx, texImage,
3056                                        width, height, depth,
3057                                        border, internalFormat, texFormat);
3058 
3059             /* Give the texture to the driver.  <pixels> may be null. */
3060             if (width > 0 && height > 0 && depth > 0) {
3061                if (compressed) {
3062                   ctx->Driver.CompressedTexImage(ctx, dims, texImage,
3063                                                  imageSize, pixels);
3064                }
3065                else {
3066                   ctx->Driver.TexImage(ctx, dims, texImage, format,
3067                                        type, pixels, unpack);
3068                }
3069             }
3070 
3071             check_gen_mipmap(ctx, target, texObj, level);
3072 
3073             _mesa_update_fbo_texture(ctx, texObj, face, level);
3074 
3075             _mesa_dirty_texobj(ctx, texObj);
3076          }
3077       }
3078       _mesa_unlock_texture(ctx, texObj);
3079    }
3080 }
3081 
3082 
3083 
3084 /*
3085  * Called from the API.  Note that width includes the border.
3086  */
3087 void GLAPIENTRY
_mesa_TexImage1D(GLenum target,GLint level,GLint internalFormat,GLsizei width,GLint border,GLenum format,GLenum type,const GLvoid * pixels)3088 _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat,
3089                   GLsizei width, GLint border, GLenum format,
3090                   GLenum type, const GLvoid *pixels )
3091 {
3092    GET_CURRENT_CONTEXT(ctx);
3093    teximage(ctx, GL_FALSE, 1, target, level, internalFormat, width, 1, 1,
3094             border, format, type, 0, pixels);
3095 }
3096 
3097 
3098 void GLAPIENTRY
_mesa_TexImage2D(GLenum target,GLint level,GLint internalFormat,GLsizei width,GLsizei height,GLint border,GLenum format,GLenum type,const GLvoid * pixels)3099 _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat,
3100                   GLsizei width, GLsizei height, GLint border,
3101                   GLenum format, GLenum type,
3102                   const GLvoid *pixels )
3103 {
3104    GET_CURRENT_CONTEXT(ctx);
3105    teximage(ctx, GL_FALSE, 2, target, level, internalFormat, width, height, 1,
3106             border, format, type, 0, pixels);
3107 }
3108 
3109 
3110 /*
3111  * Called by the API or display list executor.
3112  * Note that width and height include the border.
3113  */
3114 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)3115 _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat,
3116                   GLsizei width, GLsizei height, GLsizei depth,
3117                   GLint border, GLenum format, GLenum type,
3118                   const GLvoid *pixels )
3119 {
3120    GET_CURRENT_CONTEXT(ctx);
3121    teximage(ctx, GL_FALSE, 3, target, level, internalFormat,
3122             width, height, depth,
3123             border, format, type, 0, pixels);
3124 }
3125 
3126 
3127 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)3128 _mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat,
3129                      GLsizei width, GLsizei height, GLsizei depth,
3130                      GLint border, GLenum format, GLenum type,
3131                      const GLvoid *pixels )
3132 {
3133    _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height,
3134                     depth, border, format, type, pixels);
3135 }
3136 
3137 
3138 void GLAPIENTRY
_mesa_EGLImageTargetTexture2DOES(GLenum target,GLeglImageOES image)3139 _mesa_EGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image)
3140 {
3141    struct gl_texture_object *texObj;
3142    struct gl_texture_image *texImage;
3143    bool valid_target;
3144    GET_CURRENT_CONTEXT(ctx);
3145    FLUSH_VERTICES(ctx, 0);
3146 
3147    switch (target) {
3148    case GL_TEXTURE_2D:
3149       valid_target = ctx->Extensions.OES_EGL_image;
3150       break;
3151    case GL_TEXTURE_EXTERNAL_OES:
3152       valid_target =
3153          _mesa_is_gles(ctx) ? ctx->Extensions.OES_EGL_image_external : false;
3154       break;
3155    default:
3156       valid_target = false;
3157       break;
3158    }
3159 
3160    if (!valid_target) {
3161       _mesa_error(ctx, GL_INVALID_ENUM,
3162                   "glEGLImageTargetTexture2D(target=%d)", target);
3163       return;
3164    }
3165 
3166    if (!image) {
3167       _mesa_error(ctx, GL_INVALID_OPERATION,
3168                   "glEGLImageTargetTexture2D(image=%p)", image);
3169       return;
3170    }
3171 
3172    if (ctx->NewState & _NEW_PIXEL)
3173       _mesa_update_state(ctx);
3174 
3175    texObj = _mesa_get_current_tex_object(ctx, target);
3176    if (!texObj)
3177       return;
3178 
3179    _mesa_lock_texture(ctx, texObj);
3180 
3181    if (texObj->Immutable) {
3182       _mesa_error(ctx, GL_INVALID_OPERATION,
3183                   "glEGLImageTargetTexture2D(texture is immutable)");
3184       _mesa_unlock_texture(ctx, texObj);
3185       return;
3186    }
3187 
3188    texImage = _mesa_get_tex_image(ctx, texObj, target, 0);
3189    if (!texImage) {
3190       _mesa_error(ctx, GL_OUT_OF_MEMORY, "glEGLImageTargetTexture2D");
3191    } else {
3192       ctx->Driver.FreeTextureImageBuffer(ctx, texImage);
3193 
3194       ctx->Driver.EGLImageTargetTexture2D(ctx, target,
3195 					  texObj, texImage, image);
3196 
3197       _mesa_dirty_texobj(ctx, texObj);
3198    }
3199    _mesa_unlock_texture(ctx, texObj);
3200 }
3201 
3202 
3203 /**
3204  * Helper that implements the glTexSubImage1/2/3D()
3205  * and glTextureSubImage1/2/3D() functions.
3206  */
3207 void
_mesa_texture_sub_image(struct gl_context * ctx,GLuint dims,struct gl_texture_object * texObj,struct gl_texture_image * texImage,GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,const GLvoid * pixels,bool dsa)3208 _mesa_texture_sub_image(struct gl_context *ctx, GLuint dims,
3209                         struct gl_texture_object *texObj,
3210                         struct gl_texture_image *texImage,
3211                         GLenum target, GLint level,
3212                         GLint xoffset, GLint yoffset, GLint zoffset,
3213                         GLsizei width, GLsizei height, GLsizei depth,
3214                         GLenum format, GLenum type, const GLvoid *pixels,
3215                         bool dsa)
3216 {
3217    FLUSH_VERTICES(ctx, 0);
3218 
3219    if (ctx->NewState & _NEW_PIXEL)
3220       _mesa_update_state(ctx);
3221 
3222    _mesa_lock_texture(ctx, texObj);
3223    {
3224       if (width > 0 && height > 0 && depth > 0) {
3225          /* If we have a border, offset=-1 is legal.  Bias by border width. */
3226          switch (dims) {
3227          case 3:
3228             if (target != GL_TEXTURE_2D_ARRAY)
3229                zoffset += texImage->Border;
3230             /* fall-through */
3231          case 2:
3232             if (target != GL_TEXTURE_1D_ARRAY)
3233                yoffset += texImage->Border;
3234             /* fall-through */
3235          case 1:
3236             xoffset += texImage->Border;
3237          }
3238 
3239          ctx->Driver.TexSubImage(ctx, dims, texImage,
3240                                  xoffset, yoffset, zoffset,
3241                                  width, height, depth,
3242                                  format, type, pixels, &ctx->Unpack);
3243 
3244          check_gen_mipmap(ctx, target, texObj, level);
3245 
3246          /* NOTE: Don't signal _NEW_TEXTURE since we've only changed
3247           * the texel data, not the texture format, size, etc.
3248           */
3249       }
3250    }
3251    _mesa_unlock_texture(ctx, texObj);
3252 }
3253 
3254 /**
3255  * Implement all the glTexSubImage1/2/3D() functions.
3256  * Must split this out this way because of GL_TEXTURE_CUBE_MAP.
3257  */
3258 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,const char * callerName)3259 texsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level,
3260             GLint xoffset, GLint yoffset, GLint zoffset,
3261             GLsizei width, GLsizei height, GLsizei depth,
3262             GLenum format, GLenum type, const GLvoid *pixels,
3263             const char *callerName)
3264 {
3265    struct gl_texture_object *texObj;
3266    struct gl_texture_image *texImage;
3267 
3268    /* check target (proxies not allowed) */
3269    if (!legal_texsubimage_target(ctx, dims, target, false)) {
3270       _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage%uD(target=%s)",
3271                   dims, _mesa_enum_to_string(target));
3272       return;
3273    }
3274 
3275    texObj = _mesa_get_current_tex_object(ctx, target);
3276    if (!texObj)
3277       return;
3278 
3279    if (texsubimage_error_check(ctx, dims, texObj, target, level,
3280                                xoffset, yoffset, zoffset,
3281                                width, height, depth, format, type,
3282                                pixels, false, callerName)) {
3283       return;   /* error was detected */
3284    }
3285 
3286    texImage = _mesa_select_tex_image(texObj, target, level);
3287    /* texsubimage_error_check ensures that texImage is not NULL */
3288 
3289    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
3290       _mesa_debug(ctx, "glTexSubImage%uD %s %d %d %d %d %d %d %d %s %s %p\n",
3291                   dims,
3292                   _mesa_enum_to_string(target), level,
3293                   xoffset, yoffset, zoffset, width, height, depth,
3294                   _mesa_enum_to_string(format),
3295                   _mesa_enum_to_string(type), pixels);
3296 
3297    _mesa_texture_sub_image(ctx, dims, texObj, texImage, target, level,
3298                            xoffset, yoffset, zoffset, width, height, depth,
3299                            format, type, pixels, false);
3300 }
3301 
3302 
3303 /**
3304  * Implement all the glTextureSubImage1/2/3D() functions.
3305  * Must split this out this way because of GL_TEXTURE_CUBE_MAP.
3306  */
3307 static void
texturesubimage(struct gl_context * ctx,GLuint dims,GLuint texture,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,const GLvoid * pixels,const char * callerName)3308 texturesubimage(struct gl_context *ctx, GLuint dims,
3309                 GLuint texture, GLint level,
3310                 GLint xoffset, GLint yoffset, GLint zoffset,
3311                 GLsizei width, GLsizei height, GLsizei depth,
3312                 GLenum format, GLenum type, const GLvoid *pixels,
3313                 const char *callerName)
3314 {
3315    struct gl_texture_object *texObj;
3316    struct gl_texture_image *texImage;
3317    int i;
3318 
3319    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
3320       _mesa_debug(ctx,
3321                   "glTextureSubImage%uD %d %d %d %d %d %d %d %d %s %s %p\n",
3322                   dims, texture, level,
3323                   xoffset, yoffset, zoffset, width, height, depth,
3324                   _mesa_enum_to_string(format),
3325                   _mesa_enum_to_string(type), pixels);
3326 
3327    /* Get the texture object by Name. */
3328    texObj = _mesa_lookup_texture(ctx, texture);
3329    if (!texObj) {
3330       _mesa_error(ctx, GL_INVALID_OPERATION, "glTextureSubImage%uD(texture)",
3331                   dims);
3332       return;
3333    }
3334 
3335    /* check target (proxies not allowed) */
3336    if (!legal_texsubimage_target(ctx, dims, texObj->Target, true)) {
3337       _mesa_error(ctx, GL_INVALID_ENUM, "%s(target=%s)",
3338                   callerName, _mesa_enum_to_string(texObj->Target));
3339       return;
3340    }
3341 
3342    if (texsubimage_error_check(ctx, dims, texObj, texObj->Target, level,
3343                                xoffset, yoffset, zoffset,
3344                                width, height, depth, format, type,
3345                                pixels, true, callerName)) {
3346       return;   /* error was detected */
3347    }
3348 
3349 
3350    /* Must handle special case GL_TEXTURE_CUBE_MAP. */
3351    if (texObj->Target == GL_TEXTURE_CUBE_MAP) {
3352       GLint imageStride;
3353 
3354       /*
3355        * What do we do if the user created a texture with the following code
3356        * and then called this function with its handle?
3357        *
3358        *    GLuint tex;
3359        *    glCreateTextures(GL_TEXTURE_CUBE_MAP, 1, &tex);
3360        *    glBindTexture(GL_TEXTURE_CUBE_MAP, tex);
3361        *    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, ...);
3362        *    glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, ...);
3363        *    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, ...);
3364        *    // Note: GL_TEXTURE_CUBE_MAP_NEGATIVE_Y not set, or given the
3365        *    // wrong format, or given the wrong size, etc.
3366        *    glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, ...);
3367        *    glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, ...);
3368        *
3369        * A bug has been filed against the spec for this case.  In the
3370        * meantime, we will check for cube completeness.
3371        *
3372        * According to Section 8.17 Texture Completeness in the OpenGL 4.5
3373        * Core Profile spec (30.10.2014):
3374        *    "[A] cube map texture is cube complete if the
3375        *    following conditions all hold true: The [base level] texture
3376        *    images of each of the six cube map faces have identical, positive,
3377        *    and square dimensions. The [base level] images were each specified
3378        *    with the same internal format."
3379        *
3380        * It seems reasonable to check for cube completeness of an arbitrary
3381        * level here so that the image data has a consistent format and size.
3382        */
3383       if (!_mesa_cube_level_complete(texObj, level)) {
3384          _mesa_error(ctx, GL_INVALID_OPERATION,
3385                      "glTextureSubImage%uD(cube map incomplete)",
3386                      dims);
3387          return;
3388       }
3389 
3390       imageStride = _mesa_image_image_stride(&ctx->Unpack, width, height,
3391                                              format, type);
3392       /* Copy in each face. */
3393       for (i = zoffset; i < zoffset + depth; ++i) {
3394          texImage = texObj->Image[i][level];
3395          assert(texImage);
3396 
3397          _mesa_texture_sub_image(ctx, 3, texObj, texImage, texObj->Target,
3398                                  level, xoffset, yoffset, 0,
3399                                  width, height, 1, format,
3400                                  type, pixels, true);
3401          pixels = (GLubyte *) pixels + imageStride;
3402       }
3403    }
3404    else {
3405       texImage = _mesa_select_tex_image(texObj, texObj->Target, level);
3406       assert(texImage);
3407 
3408       _mesa_texture_sub_image(ctx, dims, texObj, texImage, texObj->Target,
3409                               level, xoffset, yoffset, zoffset,
3410                               width, height, depth, format,
3411                               type, pixels, true);
3412    }
3413 }
3414 
3415 
3416 void GLAPIENTRY
_mesa_TexSubImage1D(GLenum target,GLint level,GLint xoffset,GLsizei width,GLenum format,GLenum type,const GLvoid * pixels)3417 _mesa_TexSubImage1D( GLenum target, GLint level,
3418                      GLint xoffset, GLsizei width,
3419                      GLenum format, GLenum type,
3420                      const GLvoid *pixels )
3421 {
3422    GET_CURRENT_CONTEXT(ctx);
3423    texsubimage(ctx, 1, target, level,
3424                xoffset, 0, 0,
3425                width, 1, 1,
3426                format, type, pixels, "glTexSubImage1D");
3427 }
3428 
3429 
3430 void GLAPIENTRY
_mesa_TexSubImage2D(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLenum type,const GLvoid * pixels)3431 _mesa_TexSubImage2D( GLenum target, GLint level,
3432                      GLint xoffset, GLint yoffset,
3433                      GLsizei width, GLsizei height,
3434                      GLenum format, GLenum type,
3435                      const GLvoid *pixels )
3436 {
3437    GET_CURRENT_CONTEXT(ctx);
3438    texsubimage(ctx, 2, target, level,
3439                xoffset, yoffset, 0,
3440                width, height, 1,
3441                format, type, pixels, "glTexSubImage2D");
3442 }
3443 
3444 
3445 
3446 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)3447 _mesa_TexSubImage3D( GLenum target, GLint level,
3448                      GLint xoffset, GLint yoffset, GLint zoffset,
3449                      GLsizei width, GLsizei height, GLsizei depth,
3450                      GLenum format, GLenum type,
3451                      const GLvoid *pixels )
3452 {
3453    GET_CURRENT_CONTEXT(ctx);
3454    texsubimage(ctx, 3, target, level,
3455                xoffset, yoffset, zoffset,
3456                width, height, depth,
3457                format, type, pixels, "glTexSubImage3D");
3458 }
3459 
3460 void GLAPIENTRY
_mesa_TextureSubImage1D(GLuint texture,GLint level,GLint xoffset,GLsizei width,GLenum format,GLenum type,const GLvoid * pixels)3461 _mesa_TextureSubImage1D(GLuint texture, GLint level,
3462                         GLint xoffset, GLsizei width,
3463                         GLenum format, GLenum type,
3464                         const GLvoid *pixels)
3465 {
3466    GET_CURRENT_CONTEXT(ctx);
3467    texturesubimage(ctx, 1, texture, level,
3468                    xoffset, 0, 0,
3469                    width, 1, 1,
3470                    format, type, pixels, "glTextureSubImage1D");
3471 }
3472 
3473 
3474 void GLAPIENTRY
_mesa_TextureSubImage2D(GLuint texture,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLenum type,const GLvoid * pixels)3475 _mesa_TextureSubImage2D(GLuint texture, GLint level,
3476                         GLint xoffset, GLint yoffset,
3477                         GLsizei width, GLsizei height,
3478                         GLenum format, GLenum type,
3479                         const GLvoid *pixels)
3480 {
3481    GET_CURRENT_CONTEXT(ctx);
3482    texturesubimage(ctx, 2, texture, level,
3483                    xoffset, yoffset, 0,
3484                    width, height, 1,
3485                    format, type, pixels, "glTextureSubImage2D");
3486 }
3487 
3488 
3489 void GLAPIENTRY
_mesa_TextureSubImage3D(GLuint texture,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,const GLvoid * pixels)3490 _mesa_TextureSubImage3D(GLuint texture, GLint level,
3491                         GLint xoffset, GLint yoffset, GLint zoffset,
3492                         GLsizei width, GLsizei height, GLsizei depth,
3493                         GLenum format, GLenum type,
3494                         const GLvoid *pixels)
3495 {
3496    GET_CURRENT_CONTEXT(ctx);
3497    texturesubimage(ctx, 3, texture, level,
3498                    xoffset, yoffset, zoffset,
3499                    width, height, depth,
3500                    format, type, pixels, "glTextureSubImage3D");
3501 }
3502 
3503 
3504 /**
3505  * For glCopyTexSubImage, return the source renderbuffer to copy texel data
3506  * from.  This depends on whether the texture contains color or depth values.
3507  */
3508 static struct gl_renderbuffer *
get_copy_tex_image_source(struct gl_context * ctx,mesa_format texFormat)3509 get_copy_tex_image_source(struct gl_context *ctx, mesa_format texFormat)
3510 {
3511    if (_mesa_get_format_bits(texFormat, GL_DEPTH_BITS) > 0) {
3512       /* reading from depth/stencil buffer */
3513       return ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
3514    } else if (_mesa_get_format_bits(texFormat, GL_STENCIL_BITS) > 0) {
3515       return ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
3516    } else {
3517       /* copying from color buffer */
3518       return ctx->ReadBuffer->_ColorReadBuffer;
3519    }
3520 }
3521 
3522 static void
copytexsubimage_by_slice(struct gl_context * ctx,struct gl_texture_image * texImage,GLuint dims,GLint xoffset,GLint yoffset,GLint zoffset,struct gl_renderbuffer * rb,GLint x,GLint y,GLsizei width,GLsizei height)3523 copytexsubimage_by_slice(struct gl_context *ctx,
3524                          struct gl_texture_image *texImage,
3525                          GLuint dims,
3526                          GLint xoffset, GLint yoffset, GLint zoffset,
3527                          struct gl_renderbuffer *rb,
3528                          GLint x, GLint y,
3529                          GLsizei width, GLsizei height)
3530 {
3531    if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) {
3532       int slice;
3533 
3534       /* For 1D arrays, we copy each scanline of the source rectangle into the
3535        * next array slice.
3536        */
3537       assert(zoffset == 0);
3538 
3539       for (slice = 0; slice < height; slice++) {
3540          assert(yoffset + slice < texImage->Height);
3541          ctx->Driver.CopyTexSubImage(ctx, 2, texImage,
3542                                      xoffset, 0, yoffset + slice,
3543                                      rb, x, y + slice, width, 1);
3544       }
3545    } else {
3546       ctx->Driver.CopyTexSubImage(ctx, dims, texImage,
3547                                   xoffset, yoffset, zoffset,
3548                                   rb, x, y, width, height);
3549    }
3550 }
3551 
3552 static GLboolean
formats_differ_in_component_sizes(mesa_format f1,mesa_format f2)3553 formats_differ_in_component_sizes(mesa_format f1, mesa_format f2)
3554 {
3555    GLint f1_r_bits = _mesa_get_format_bits(f1, GL_RED_BITS);
3556    GLint f1_g_bits = _mesa_get_format_bits(f1, GL_GREEN_BITS);
3557    GLint f1_b_bits = _mesa_get_format_bits(f1, GL_BLUE_BITS);
3558    GLint f1_a_bits = _mesa_get_format_bits(f1, GL_ALPHA_BITS);
3559 
3560    GLint f2_r_bits = _mesa_get_format_bits(f2, GL_RED_BITS);
3561    GLint f2_g_bits = _mesa_get_format_bits(f2, GL_GREEN_BITS);
3562    GLint f2_b_bits = _mesa_get_format_bits(f2, GL_BLUE_BITS);
3563    GLint f2_a_bits = _mesa_get_format_bits(f2, GL_ALPHA_BITS);
3564 
3565    if ((f1_r_bits && f2_r_bits && f1_r_bits != f2_r_bits)
3566        || (f1_g_bits && f2_g_bits && f1_g_bits != f2_g_bits)
3567        || (f1_b_bits && f2_b_bits && f1_b_bits != f2_b_bits)
3568        || (f1_a_bits && f2_a_bits && f1_a_bits != f2_a_bits))
3569       return GL_TRUE;
3570 
3571    return GL_FALSE;
3572 }
3573 
3574 
3575 /**
3576  * Check if the given texture format and size arguments match those
3577  * of the texture image.
3578  * \param return true if arguments match, false otherwise.
3579  */
3580 static bool
can_avoid_reallocation(const struct gl_texture_image * texImage,GLenum internalFormat,mesa_format texFormat,GLint x,GLint y,GLsizei width,GLsizei height,GLint border)3581 can_avoid_reallocation(const struct gl_texture_image *texImage,
3582                        GLenum internalFormat,
3583                        mesa_format texFormat, GLint x, GLint y, GLsizei width,
3584                        GLsizei height, GLint border)
3585 {
3586    if (texImage->InternalFormat != internalFormat)
3587       return false;
3588    if (texImage->TexFormat != texFormat)
3589       return false;
3590    if (texImage->Border != border)
3591       return false;
3592    if (texImage->Width2 != width)
3593       return false;
3594    if (texImage->Height2 != height)
3595       return false;
3596    return true;
3597 }
3598 
3599 /**
3600  * Implement the glCopyTexImage1/2D() functions.
3601  */
3602 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)3603 copyteximage(struct gl_context *ctx, GLuint dims,
3604              GLenum target, GLint level, GLenum internalFormat,
3605              GLint x, GLint y, GLsizei width, GLsizei height, GLint border )
3606 {
3607    struct gl_texture_object *texObj;
3608    struct gl_texture_image *texImage;
3609    const GLuint face = _mesa_tex_target_to_face(target);
3610    mesa_format texFormat;
3611    struct gl_renderbuffer *rb;
3612 
3613    FLUSH_VERTICES(ctx, 0);
3614 
3615    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
3616       _mesa_debug(ctx, "glCopyTexImage%uD %s %d %s %d %d %d %d %d\n",
3617                   dims,
3618                   _mesa_enum_to_string(target), level,
3619                   _mesa_enum_to_string(internalFormat),
3620                   x, y, width, height, border);
3621 
3622    if (ctx->NewState & NEW_COPY_TEX_STATE)
3623       _mesa_update_state(ctx);
3624 
3625    if (copytexture_error_check(ctx, dims, target, level, internalFormat,
3626                                width, height, border))
3627       return;
3628 
3629    if (!_mesa_legal_texture_dimensions(ctx, target, level, width, height,
3630                                        1, border)) {
3631       _mesa_error(ctx, GL_INVALID_VALUE,
3632                   "glCopyTexImage%uD(invalid width or height)", dims);
3633       return;
3634    }
3635 
3636    texObj = _mesa_get_current_tex_object(ctx, target);
3637    assert(texObj);
3638 
3639    texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
3640                                            internalFormat, GL_NONE, GL_NONE);
3641 
3642    /* First check if reallocating the texture buffer can be avoided.
3643     * Without the realloc the copy can be 20x faster.
3644     */
3645    _mesa_lock_texture(ctx, texObj);
3646    {
3647       texImage = _mesa_select_tex_image(texObj, target, level);
3648       if (texImage && can_avoid_reallocation(texImage, internalFormat, texFormat,
3649                                              x, y, width, height, border)) {
3650          _mesa_unlock_texture(ctx, texObj);
3651          return _mesa_copy_texture_sub_image(ctx, dims, texObj, target, level,
3652                                              0, 0, 0, x, y, width, height,
3653                                              "CopyTexImage");
3654       }
3655    }
3656    _mesa_unlock_texture(ctx, texObj);
3657    _mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_LOW, "glCopyTexImage "
3658                     "can't avoid reallocating texture storage\n");
3659 
3660    rb = _mesa_get_read_renderbuffer_for_format(ctx, internalFormat);
3661 
3662    if (_mesa_is_gles3(ctx)) {
3663       if (_mesa_is_enum_format_unsized(internalFormat)) {
3664       /* Conversion from GL_RGB10_A2 source buffer format is not allowed in
3665        * OpenGL ES 3.0. Khronos bug# 9807.
3666        */
3667          if (rb->InternalFormat == GL_RGB10_A2) {
3668                _mesa_error(ctx, GL_INVALID_OPERATION,
3669                            "glCopyTexImage%uD(Reading from GL_RGB10_A2 buffer"
3670                            " and writing to unsized internal format)", dims);
3671                return;
3672          }
3673       }
3674       /* From Page 139 of OpenGL ES 3.0 spec:
3675        *    "If internalformat is sized, the internal format of the new texel
3676        *    array is internalformat, and this is also the new texel array’s
3677        *    effective internal format. If the component sizes of internalformat
3678        *    do not exactly match the corresponding component sizes of the source
3679        *    buffer’s effective internal format, described below, an
3680        *    INVALID_OPERATION error is generated. If internalformat is unsized,
3681        *    the internal format of the new texel array is the effective internal
3682        *    format of the source buffer, and this is also the new texel array’s
3683        *    effective internal format.
3684        */
3685       else if (formats_differ_in_component_sizes (texFormat, rb->Format)) {
3686             _mesa_error(ctx, GL_INVALID_OPERATION,
3687                         "glCopyTexImage%uD(componenet size changed in"
3688                         " internal format)", dims);
3689             return;
3690       }
3691    }
3692 
3693    assert(texFormat != MESA_FORMAT_NONE);
3694 
3695    if (!ctx->Driver.TestProxyTexImage(ctx, proxy_target(target),
3696                                       0, level, texFormat, 1,
3697                                       width, height, 1)) {
3698       _mesa_error(ctx, GL_OUT_OF_MEMORY,
3699                   "glCopyTexImage%uD(image too large)", dims);
3700       return;
3701    }
3702 
3703    if (border && ctx->Const.StripTextureBorder) {
3704       x += border;
3705       width -= border * 2;
3706       if (dims == 2) {
3707 	 y += border;
3708 	 height -= border * 2;
3709       }
3710       border = 0;
3711    }
3712 
3713    _mesa_lock_texture(ctx, texObj);
3714    {
3715       texImage = _mesa_get_tex_image(ctx, texObj, target, level);
3716 
3717       if (!texImage) {
3718 	 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage%uD", dims);
3719       }
3720       else {
3721          GLint srcX = x, srcY = y, dstX = 0, dstY = 0, dstZ = 0;
3722 
3723          /* Free old texture image */
3724          ctx->Driver.FreeTextureImageBuffer(ctx, texImage);
3725 
3726          _mesa_init_teximage_fields(ctx, texImage, width, height, 1,
3727                                     border, internalFormat, texFormat);
3728 
3729          if (width && height) {
3730             /* Allocate texture memory (no pixel data yet) */
3731             ctx->Driver.AllocTextureImageBuffer(ctx, texImage);
3732 
3733             if (_mesa_clip_copytexsubimage(ctx, &dstX, &dstY, &srcX, &srcY,
3734                                            &width, &height)) {
3735                struct gl_renderbuffer *srcRb =
3736                   get_copy_tex_image_source(ctx, texImage->TexFormat);
3737 
3738                copytexsubimage_by_slice(ctx, texImage, dims,
3739                                         dstX, dstY, dstZ,
3740                                         srcRb, srcX, srcY, width, height);
3741             }
3742 
3743             check_gen_mipmap(ctx, target, texObj, level);
3744          }
3745 
3746          _mesa_update_fbo_texture(ctx, texObj, face, level);
3747 
3748          _mesa_dirty_texobj(ctx, texObj);
3749       }
3750    }
3751    _mesa_unlock_texture(ctx, texObj);
3752 }
3753 
3754 
3755 
3756 void GLAPIENTRY
_mesa_CopyTexImage1D(GLenum target,GLint level,GLenum internalFormat,GLint x,GLint y,GLsizei width,GLint border)3757 _mesa_CopyTexImage1D( GLenum target, GLint level,
3758                       GLenum internalFormat,
3759                       GLint x, GLint y,
3760                       GLsizei width, GLint border )
3761 {
3762    GET_CURRENT_CONTEXT(ctx);
3763    copyteximage(ctx, 1, target, level, internalFormat, x, y, width, 1, border);
3764 }
3765 
3766 
3767 
3768 void GLAPIENTRY
_mesa_CopyTexImage2D(GLenum target,GLint level,GLenum internalFormat,GLint x,GLint y,GLsizei width,GLsizei height,GLint border)3769 _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat,
3770                       GLint x, GLint y, GLsizei width, GLsizei height,
3771                       GLint border )
3772 {
3773    GET_CURRENT_CONTEXT(ctx);
3774    copyteximage(ctx, 2, target, level, internalFormat,
3775                 x, y, width, height, border);
3776 }
3777 
3778 /**
3779  * Implementation for glCopyTex(ture)SubImage1/2/3D() functions.
3780  */
3781 void
_mesa_copy_texture_sub_image(struct gl_context * ctx,GLuint dims,struct gl_texture_object * texObj,GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLsizei width,GLsizei height,const char * caller)3782 _mesa_copy_texture_sub_image(struct gl_context *ctx, GLuint dims,
3783                              struct gl_texture_object *texObj,
3784                              GLenum target, GLint level,
3785                              GLint xoffset, GLint yoffset, GLint zoffset,
3786                              GLint x, GLint y,
3787                              GLsizei width, GLsizei height,
3788                              const char *caller)
3789 {
3790    struct gl_texture_image *texImage;
3791 
3792    FLUSH_VERTICES(ctx, 0);
3793 
3794    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
3795       _mesa_debug(ctx, "%s %s %d %d %d %d %d %d %d %d\n", caller,
3796                   _mesa_enum_to_string(target),
3797                   level, xoffset, yoffset, zoffset, x, y, width, height);
3798 
3799    if (ctx->NewState & NEW_COPY_TEX_STATE)
3800       _mesa_update_state(ctx);
3801 
3802    if (copytexsubimage_error_check(ctx, dims, texObj, target, level,
3803                                    xoffset, yoffset, zoffset,
3804                                    width, height, caller)) {
3805       return;
3806    }
3807 
3808    _mesa_lock_texture(ctx, texObj);
3809    {
3810       texImage = _mesa_select_tex_image(texObj, target, level);
3811 
3812       /* If we have a border, offset=-1 is legal.  Bias by border width. */
3813       switch (dims) {
3814       case 3:
3815          if (target != GL_TEXTURE_2D_ARRAY)
3816             zoffset += texImage->Border;
3817          /* fall-through */
3818       case 2:
3819          if (target != GL_TEXTURE_1D_ARRAY)
3820             yoffset += texImage->Border;
3821          /* fall-through */
3822       case 1:
3823          xoffset += texImage->Border;
3824       }
3825 
3826       if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y,
3827                                      &width, &height)) {
3828          struct gl_renderbuffer *srcRb =
3829             get_copy_tex_image_source(ctx, texImage->TexFormat);
3830 
3831          copytexsubimage_by_slice(ctx, texImage, dims,
3832                                   xoffset, yoffset, zoffset,
3833                                   srcRb, x, y, width, height);
3834 
3835          check_gen_mipmap(ctx, target, texObj, level);
3836 
3837          /* NOTE: Don't signal _NEW_TEXTURE since we've only changed
3838           * the texel data, not the texture format, size, etc.
3839           */
3840       }
3841    }
3842    _mesa_unlock_texture(ctx, texObj);
3843 }
3844 
3845 void GLAPIENTRY
_mesa_CopyTexSubImage1D(GLenum target,GLint level,GLint xoffset,GLint x,GLint y,GLsizei width)3846 _mesa_CopyTexSubImage1D( GLenum target, GLint level,
3847                          GLint xoffset, GLint x, GLint y, GLsizei width )
3848 {
3849    struct gl_texture_object* texObj;
3850    const char *self = "glCopyTexSubImage1D";
3851    GET_CURRENT_CONTEXT(ctx);
3852 
3853    /* Check target (proxies not allowed). Target must be checked prior to
3854     * calling _mesa_get_current_tex_object.
3855     */
3856    if (!legal_texsubimage_target(ctx, 1, target, false)) {
3857       _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", self,
3858                   _mesa_enum_to_string(target));
3859       return;
3860    }
3861 
3862    texObj = _mesa_get_current_tex_object(ctx, target);
3863    if (!texObj)
3864       return;
3865 
3866    _mesa_copy_texture_sub_image(ctx, 1, texObj, target, level, xoffset, 0, 0,
3867                                 x, y, width, 1, self);
3868 }
3869 
3870 
3871 
3872 void GLAPIENTRY
_mesa_CopyTexSubImage2D(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint x,GLint y,GLsizei width,GLsizei height)3873 _mesa_CopyTexSubImage2D( GLenum target, GLint level,
3874                          GLint xoffset, GLint yoffset,
3875                          GLint x, GLint y, GLsizei width, GLsizei height )
3876 {
3877    struct gl_texture_object* texObj;
3878    const char *self = "glCopyTexSubImage2D";
3879    GET_CURRENT_CONTEXT(ctx);
3880 
3881    /* Check target (proxies not allowed). Target must be checked prior to
3882     * calling _mesa_get_current_tex_object.
3883     */
3884    if (!legal_texsubimage_target(ctx, 2, target, false)) {
3885       _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", self,
3886                   _mesa_enum_to_string(target));
3887       return;
3888    }
3889 
3890    texObj = _mesa_get_current_tex_object(ctx, target);
3891    if (!texObj)
3892       return;
3893 
3894    _mesa_copy_texture_sub_image(ctx, 2, texObj, target, level,
3895                                 xoffset, yoffset, 0,
3896                                 x, y, width, height, self);
3897 }
3898 
3899 
3900 
3901 void GLAPIENTRY
_mesa_CopyTexSubImage3D(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLsizei width,GLsizei height)3902 _mesa_CopyTexSubImage3D( GLenum target, GLint level,
3903                          GLint xoffset, GLint yoffset, GLint zoffset,
3904                          GLint x, GLint y, GLsizei width, GLsizei height )
3905 {
3906    struct gl_texture_object* texObj;
3907    const char *self = "glCopyTexSubImage3D";
3908    GET_CURRENT_CONTEXT(ctx);
3909 
3910    /* Check target (proxies not allowed). Target must be checked prior to
3911     * calling _mesa_get_current_tex_object.
3912     */
3913    if (!legal_texsubimage_target(ctx, 3, target, false)) {
3914       _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", self,
3915                   _mesa_enum_to_string(target));
3916       return;
3917    }
3918 
3919    texObj = _mesa_get_current_tex_object(ctx, target);
3920    if (!texObj)
3921       return;
3922 
3923    _mesa_copy_texture_sub_image(ctx, 3, texObj, target, level,
3924                                 xoffset, yoffset, zoffset,
3925                                 x, y, width, height, self);
3926 }
3927 
3928 void GLAPIENTRY
_mesa_CopyTextureSubImage1D(GLuint texture,GLint level,GLint xoffset,GLint x,GLint y,GLsizei width)3929 _mesa_CopyTextureSubImage1D(GLuint texture, GLint level,
3930                             GLint xoffset, GLint x, GLint y, GLsizei width)
3931 {
3932    struct gl_texture_object* texObj;
3933    const char *self = "glCopyTextureSubImage1D";
3934    GET_CURRENT_CONTEXT(ctx);
3935 
3936    texObj = _mesa_lookup_texture_err(ctx, texture, self);
3937    if (!texObj)
3938       return;
3939 
3940    /* Check target (proxies not allowed). */
3941    if (!legal_texsubimage_target(ctx, 1, texObj->Target, true)) {
3942       _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", self,
3943                   _mesa_enum_to_string(texObj->Target));
3944       return;
3945    }
3946 
3947    _mesa_copy_texture_sub_image(ctx, 1, texObj, texObj->Target, level,
3948                                 xoffset, 0, 0, x, y, width, 1, self);
3949 }
3950 
3951 void GLAPIENTRY
_mesa_CopyTextureSubImage2D(GLuint texture,GLint level,GLint xoffset,GLint yoffset,GLint x,GLint y,GLsizei width,GLsizei height)3952 _mesa_CopyTextureSubImage2D(GLuint texture, GLint level,
3953                             GLint xoffset, GLint yoffset,
3954                             GLint x, GLint y, GLsizei width, GLsizei height)
3955 {
3956    struct gl_texture_object* texObj;
3957    const char *self = "glCopyTextureSubImage2D";
3958    GET_CURRENT_CONTEXT(ctx);
3959 
3960    texObj = _mesa_lookup_texture_err(ctx, texture, self);
3961    if (!texObj)
3962       return;
3963 
3964    /* Check target (proxies not allowed). */
3965    if (!legal_texsubimage_target(ctx, 2, texObj->Target, true)) {
3966       _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", self,
3967                   _mesa_enum_to_string(texObj->Target));
3968       return;
3969    }
3970 
3971    _mesa_copy_texture_sub_image(ctx, 2, texObj, texObj->Target, level,
3972                                 xoffset, yoffset, 0,
3973                                 x, y, width, height, self);
3974 }
3975 
3976 
3977 
3978 void GLAPIENTRY
_mesa_CopyTextureSubImage3D(GLuint texture,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLint x,GLint y,GLsizei width,GLsizei height)3979 _mesa_CopyTextureSubImage3D(GLuint texture, GLint level,
3980                             GLint xoffset, GLint yoffset, GLint zoffset,
3981                             GLint x, GLint y, GLsizei width, GLsizei height)
3982 {
3983    struct gl_texture_object* texObj;
3984    const char *self = "glCopyTextureSubImage3D";
3985    GET_CURRENT_CONTEXT(ctx);
3986 
3987    texObj = _mesa_lookup_texture_err(ctx, texture, self);
3988    if (!texObj)
3989       return;
3990 
3991    /* Check target (proxies not allowed). */
3992    if (!legal_texsubimage_target(ctx, 3, texObj->Target, true)) {
3993       _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", self,
3994                   _mesa_enum_to_string(texObj->Target));
3995       return;
3996    }
3997 
3998    if (texObj->Target == GL_TEXTURE_CUBE_MAP) {
3999       /* Act like CopyTexSubImage2D */
4000       _mesa_copy_texture_sub_image(ctx, 2, texObj,
4001                                    GL_TEXTURE_CUBE_MAP_POSITIVE_X + zoffset,
4002                                    level, xoffset, yoffset, 0,
4003                                    x, y, width, height, self);
4004    }
4005    else
4006       _mesa_copy_texture_sub_image(ctx, 3, texObj, texObj->Target, level,
4007                                    xoffset, yoffset, zoffset,
4008                                    x, y, width, height, self);
4009 }
4010 
4011 static bool
check_clear_tex_image(struct gl_context * ctx,const char * function,struct gl_texture_image * texImage,GLenum format,GLenum type,const void * data,GLubyte * clearValue)4012 check_clear_tex_image(struct gl_context *ctx,
4013                       const char *function,
4014                       struct gl_texture_image *texImage,
4015                       GLenum format, GLenum type,
4016                       const void *data,
4017                       GLubyte *clearValue)
4018 {
4019    struct gl_texture_object *texObj = texImage->TexObject;
4020    static const GLubyte zeroData[MAX_PIXEL_BYTES];
4021    GLenum internalFormat = texImage->InternalFormat;
4022    GLenum err;
4023 
4024    if (texObj->Target == GL_TEXTURE_BUFFER) {
4025       _mesa_error(ctx, GL_INVALID_OPERATION,
4026                   "%s(buffer texture)", function);
4027       return false;
4028    }
4029 
4030    if (_mesa_is_compressed_format(ctx, internalFormat)) {
4031       _mesa_error(ctx, GL_INVALID_OPERATION,
4032                   "%s(compressed texture)", function);
4033       return false;
4034    }
4035 
4036    err = _mesa_error_check_format_and_type(ctx, format, type);
4037    if (err != GL_NO_ERROR) {
4038       _mesa_error(ctx, err,
4039                   "%s(incompatible format = %s, type = %s)",
4040                   function,
4041                   _mesa_enum_to_string(format),
4042                   _mesa_enum_to_string(type));
4043       return false;
4044    }
4045 
4046    /* make sure internal format and format basically agree */
4047    if (!texture_formats_agree(internalFormat, format)) {
4048       _mesa_error(ctx, GL_INVALID_OPERATION,
4049                   "%s(incompatible internalFormat = %s, format = %s)",
4050                   function,
4051                   _mesa_enum_to_string(internalFormat),
4052                   _mesa_enum_to_string(format));
4053       return false;
4054    }
4055 
4056    if (ctx->Version >= 30 || ctx->Extensions.EXT_texture_integer) {
4057       /* both source and dest must be integer-valued, or neither */
4058       if (_mesa_is_format_integer_color(texImage->TexFormat) !=
4059           _mesa_is_enum_format_integer(format)) {
4060          _mesa_error(ctx, GL_INVALID_OPERATION,
4061                      "%s(integer/non-integer format mismatch)",
4062                      function);
4063          return false;
4064       }
4065    }
4066 
4067    if (!_mesa_texstore(ctx,
4068                        1, /* dims */
4069                        texImage->_BaseFormat,
4070                        texImage->TexFormat,
4071                        0, /* dstRowStride */
4072                        &clearValue,
4073                        1, 1, 1, /* srcWidth/Height/Depth */
4074                        format, type,
4075                        data ? data : zeroData,
4076                        &ctx->DefaultPacking)) {
4077       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid format)", function);
4078       return false;
4079    }
4080 
4081    return true;
4082 }
4083 
4084 static struct gl_texture_object *
get_tex_obj_for_clear(struct gl_context * ctx,const char * function,GLuint texture)4085 get_tex_obj_for_clear(struct gl_context *ctx,
4086                       const char *function,
4087                       GLuint texture)
4088 {
4089    struct gl_texture_object *texObj;
4090 
4091    if (texture == 0) {
4092       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(zero texture)", function);
4093       return NULL;
4094    }
4095 
4096    texObj = _mesa_lookup_texture(ctx, texture);
4097 
4098    if (texObj == NULL) {
4099       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(non-gen name)", function);
4100       return NULL;
4101    }
4102 
4103    if (texObj->Target == 0) {
4104       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unbound tex)", function);
4105       return NULL;
4106    }
4107 
4108    return texObj;
4109 }
4110 
4111 static int
get_tex_images_for_clear(struct gl_context * ctx,const char * function,struct gl_texture_object * texObj,GLint level,struct gl_texture_image ** texImages)4112 get_tex_images_for_clear(struct gl_context *ctx,
4113                          const char *function,
4114                          struct gl_texture_object *texObj,
4115                          GLint level,
4116                          struct gl_texture_image **texImages)
4117 {
4118    GLenum target;
4119    int i;
4120 
4121    if (level < 0 || level >= MAX_TEXTURE_LEVELS) {
4122       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid level)", function);
4123       return 0;
4124    }
4125 
4126    if (texObj->Target == GL_TEXTURE_CUBE_MAP) {
4127       for (i = 0; i < MAX_FACES; i++) {
4128          target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + i;
4129 
4130          texImages[i] = _mesa_select_tex_image(texObj, target, level);
4131          if (texImages[i] == NULL) {
4132             _mesa_error(ctx, GL_INVALID_OPERATION,
4133                         "%s(invalid level)", function);
4134             return 0;
4135          }
4136       }
4137 
4138       return MAX_FACES;
4139    }
4140 
4141    texImages[0] = _mesa_select_tex_image(texObj, texObj->Target, level);
4142 
4143    if (texImages[0] == NULL) {
4144       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid level)", function);
4145       return 0;
4146    }
4147 
4148    return 1;
4149 }
4150 
4151 void GLAPIENTRY
_mesa_ClearTexSubImage(GLuint texture,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLenum type,const void * data)4152 _mesa_ClearTexSubImage( GLuint texture, GLint level,
4153                         GLint xoffset, GLint yoffset, GLint zoffset,
4154                         GLsizei width, GLsizei height, GLsizei depth,
4155                         GLenum format, GLenum type, const void *data )
4156 {
4157    GET_CURRENT_CONTEXT(ctx);
4158    struct gl_texture_object *texObj;
4159    struct gl_texture_image *texImages[MAX_FACES];
4160    GLubyte clearValue[MAX_FACES][MAX_PIXEL_BYTES];
4161    int i, numImages;
4162    int minDepth, maxDepth;
4163 
4164    texObj = get_tex_obj_for_clear(ctx, "glClearTexSubImage", texture);
4165 
4166    if (texObj == NULL)
4167       return;
4168 
4169    _mesa_lock_texture(ctx, texObj);
4170 
4171    numImages = get_tex_images_for_clear(ctx, "glClearTexSubImage",
4172                                         texObj, level, texImages);
4173    if (numImages == 0)
4174       goto out;
4175 
4176    if (numImages == 1) {
4177       minDepth = -(int) texImages[0]->Border;
4178       maxDepth = texImages[0]->Depth;
4179    } else {
4180       minDepth = 0;
4181       maxDepth = numImages;
4182    }
4183 
4184    if (xoffset < -(GLint) texImages[0]->Border ||
4185        yoffset < -(GLint) texImages[0]->Border ||
4186        zoffset < minDepth ||
4187        width < 0 ||
4188        height < 0 ||
4189        depth < 0 ||
4190        xoffset + width > texImages[0]->Width ||
4191        yoffset + height > texImages[0]->Height ||
4192        zoffset + depth > maxDepth) {
4193       _mesa_error(ctx, GL_INVALID_OPERATION,
4194                   "glClearSubTexImage(invalid dimensions)");
4195       goto out;
4196    }
4197 
4198    if (numImages == 1) {
4199       if (check_clear_tex_image(ctx, "glClearTexSubImage",
4200                                 texImages[0],
4201                                 format, type, data, clearValue[0])) {
4202          ctx->Driver.ClearTexSubImage(ctx,
4203                                       texImages[0],
4204                                       xoffset, yoffset, zoffset,
4205                                       width, height, depth,
4206                                       data ? clearValue[0] : NULL);
4207       }
4208    } else {
4209       for (i = zoffset; i < zoffset + depth; i++) {
4210          if (!check_clear_tex_image(ctx, "glClearTexSubImage",
4211                                     texImages[i],
4212                                     format, type, data, clearValue[i]))
4213             goto out;
4214       }
4215       for (i = zoffset; i < zoffset + depth; i++) {
4216          ctx->Driver.ClearTexSubImage(ctx,
4217                                       texImages[i],
4218                                       xoffset, yoffset, 0,
4219                                       width, height, 1,
4220                                       data ? clearValue[i] : NULL);
4221       }
4222    }
4223 
4224  out:
4225    _mesa_unlock_texture(ctx, texObj);
4226 }
4227 
4228 void GLAPIENTRY
_mesa_ClearTexImage(GLuint texture,GLint level,GLenum format,GLenum type,const void * data)4229 _mesa_ClearTexImage( GLuint texture, GLint level,
4230                      GLenum format, GLenum type, const void *data )
4231 {
4232    GET_CURRENT_CONTEXT(ctx);
4233    struct gl_texture_object *texObj;
4234    struct gl_texture_image *texImages[MAX_FACES];
4235    GLubyte clearValue[MAX_FACES][MAX_PIXEL_BYTES];
4236    int i, numImages;
4237 
4238    texObj = get_tex_obj_for_clear(ctx, "glClearTexImage", texture);
4239 
4240    if (texObj == NULL)
4241       return;
4242 
4243    _mesa_lock_texture(ctx, texObj);
4244 
4245    numImages = get_tex_images_for_clear(ctx, "glClearTexImage",
4246                                         texObj, level, texImages);
4247 
4248    for (i = 0; i < numImages; i++) {
4249       if (!check_clear_tex_image(ctx, "glClearTexImage",
4250                                  texImages[i],
4251                                  format, type, data,
4252                                  clearValue[i]))
4253          goto out;
4254    }
4255 
4256    for (i = 0; i < numImages; i++) {
4257       ctx->Driver.ClearTexSubImage(ctx, texImages[i],
4258                                    -(GLint) texImages[i]->Border, /* xoffset */
4259                                    -(GLint) texImages[i]->Border, /* yoffset */
4260                                    -(GLint) texImages[i]->Border, /* zoffset */
4261                                    texImages[i]->Width,
4262                                    texImages[i]->Height,
4263                                    texImages[i]->Depth,
4264                                    data ? clearValue[i] : NULL);
4265    }
4266 
4267 out:
4268    _mesa_unlock_texture(ctx, texObj);
4269 }
4270 
4271 
4272 
4273 
4274 /**********************************************************************/
4275 /******                   Compressed Textures                    ******/
4276 /**********************************************************************/
4277 
4278 
4279 /**
4280  * Target checking for glCompressedTexSubImage[123]D().
4281  * \return GL_TRUE if error, GL_FALSE if no error
4282  * Must come before other error checking so that the texture object can
4283  * be correctly retrieved using _mesa_get_current_tex_object.
4284  */
4285 static GLboolean
compressed_subtexture_target_check(struct gl_context * ctx,GLenum target,GLint dims,GLenum format,bool dsa,const char * caller)4286 compressed_subtexture_target_check(struct gl_context *ctx, GLenum target,
4287                                    GLint dims, GLenum format, bool dsa,
4288                                    const char *caller)
4289 {
4290    GLboolean targetOK;
4291 
4292    if (dsa && target == GL_TEXTURE_RECTANGLE) {
4293       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid target %s)", caller,
4294                   _mesa_enum_to_string(target));
4295       return GL_TRUE;
4296    }
4297 
4298    switch (dims) {
4299    case 2:
4300       switch (target) {
4301       case GL_TEXTURE_2D:
4302          targetOK = GL_TRUE;
4303          break;
4304       case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
4305       case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
4306       case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
4307       case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
4308       case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
4309       case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
4310          targetOK = ctx->Extensions.ARB_texture_cube_map;
4311          break;
4312       default:
4313          targetOK = GL_FALSE;
4314          break;
4315       }
4316       break;
4317    case 3:
4318       switch (target) {
4319       case GL_TEXTURE_CUBE_MAP:
4320          targetOK = dsa && ctx->Extensions.ARB_texture_cube_map;
4321          break;
4322       case GL_TEXTURE_2D_ARRAY:
4323          targetOK = _mesa_is_gles3(ctx) ||
4324             (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array);
4325          break;
4326       case GL_TEXTURE_CUBE_MAP_ARRAY:
4327          targetOK = _mesa_has_texture_cube_map_array(ctx);
4328          break;
4329       case GL_TEXTURE_3D:
4330          targetOK = GL_TRUE;
4331          /*
4332           * OpenGL 4.5 spec (30.10.2014) says in Section 8.7 Compressed Texture
4333           * Images:
4334           *    "An INVALID_OPERATION error is generated by
4335           *    CompressedTex*SubImage3D if the internal format of the texture
4336           *    is one of the EAC, ETC2, or RGTC formats and either border is
4337           *    non-zero, or the effective target for the texture is not
4338           *    TEXTURE_2D_ARRAY."
4339           *
4340           * NOTE: that's probably a spec error.  It should probably say
4341           *    "... or the effective target for the texture is not
4342           *    TEXTURE_2D_ARRAY, TEXTURE_CUBE_MAP, nor
4343           *    GL_TEXTURE_CUBE_MAP_ARRAY."
4344           * since those targets are 2D images and they support all compression
4345           * formats.
4346           *
4347           * Instead of listing all these, just list those which are allowed,
4348           * which is (at this time) only bptc. Otherwise we'd say s3tc (and
4349           * more) are valid here, which they are not, but of course not
4350           * mentioned by core spec.
4351           */
4352          switch (format) {
4353          /* These are the only 3D compression formats supported at this time */
4354          case GL_COMPRESSED_RGBA_BPTC_UNORM:
4355          case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
4356          case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT:
4357          case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
4358             /* valid format */
4359             break;
4360          default:
4361             /* invalid format */
4362             _mesa_error(ctx, GL_INVALID_OPERATION,
4363                         "%s(invalid target %s for format %s)", caller,
4364                         _mesa_enum_to_string(target),
4365                         _mesa_enum_to_string(format));
4366             return GL_TRUE;
4367          }
4368          break;
4369       default:
4370          targetOK = GL_FALSE;
4371       }
4372 
4373       break;
4374    default:
4375       assert(dims == 1);
4376       /* no 1D compressed textures at this time */
4377       targetOK = GL_FALSE;
4378       break;
4379    }
4380 
4381    if (!targetOK) {
4382       _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", caller,
4383                   _mesa_enum_to_string(target));
4384       return GL_TRUE;
4385    }
4386 
4387    return GL_FALSE;
4388 }
4389 
4390 /**
4391  * Error checking for glCompressedTexSubImage[123]D().
4392  * \return GL_TRUE if error, GL_FALSE if no error
4393  */
4394 static GLboolean
compressed_subtexture_error_check(struct gl_context * ctx,GLint dims,const struct gl_texture_object * texObj,GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLsizei imageSize,const GLvoid * data,const char * callerName)4395 compressed_subtexture_error_check(struct gl_context *ctx, GLint dims,
4396                                   const struct gl_texture_object *texObj,
4397                                   GLenum target, GLint level,
4398                                   GLint xoffset, GLint yoffset, GLint zoffset,
4399                                   GLsizei width, GLsizei height, GLsizei depth,
4400                                   GLenum format, GLsizei imageSize,
4401                                   const GLvoid *data, const char *callerName)
4402 {
4403    struct gl_texture_image *texImage;
4404    GLint expectedSize;
4405 
4406    /* this will catch any invalid compressed format token */
4407    if (!_mesa_is_compressed_format(ctx, format)) {
4408       _mesa_error(ctx, GL_INVALID_ENUM,
4409                   "%s(format)", callerName);
4410       return GL_TRUE;
4411    }
4412 
4413    if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) {
4414       _mesa_error(ctx, GL_INVALID_VALUE,
4415                   "%s(level=%d)",
4416                   callerName, level);
4417       return GL_TRUE;
4418    }
4419 
4420    /* validate the bound PBO, if any */
4421    if (!_mesa_validate_pbo_source_compressed(ctx, dims, &ctx->Unpack,
4422                                      imageSize, data, callerName)) {
4423       return GL_TRUE;
4424    }
4425 
4426    /* Check for invalid pixel storage modes */
4427    if (!_mesa_compressed_pixel_storage_error_check(ctx, dims,
4428                                                    &ctx->Unpack, callerName)) {
4429       return GL_TRUE;
4430    }
4431 
4432    expectedSize = compressed_tex_size(width, height, depth, format);
4433    if (expectedSize != imageSize) {
4434       _mesa_error(ctx, GL_INVALID_VALUE,
4435                   "%s(size=%d)",
4436                   callerName, imageSize);
4437       return GL_TRUE;
4438    }
4439 
4440    texImage = _mesa_select_tex_image(texObj, target, level);
4441    if (!texImage) {
4442       _mesa_error(ctx, GL_INVALID_OPERATION,
4443                   "%s(invalid texture image)",
4444                   callerName);
4445       return GL_TRUE;
4446    }
4447 
4448    if ((GLint) format != texImage->InternalFormat) {
4449       _mesa_error(ctx, GL_INVALID_OPERATION,
4450                   "%s(format=%s)",
4451                   callerName, _mesa_enum_to_string(format));
4452       return GL_TRUE;
4453    }
4454 
4455    if (compressedteximage_only_format(ctx, format)) {
4456       _mesa_error(ctx, GL_INVALID_OPERATION,
4457                   "%s(format=%s cannot be updated)",
4458                   callerName, _mesa_enum_to_string(format));
4459       return GL_TRUE;
4460    }
4461 
4462    if (error_check_subtexture_negative_dimensions(ctx, dims,
4463                                                   width, height, depth,
4464                                                   callerName)) {
4465       return GL_TRUE;
4466    }
4467 
4468    if (error_check_subtexture_dimensions(ctx, dims,
4469                                          texImage, xoffset, yoffset, zoffset,
4470                                          width, height, depth,
4471                                          callerName)) {
4472       return GL_TRUE;
4473    }
4474 
4475    return GL_FALSE;
4476 }
4477 
4478 
4479 void GLAPIENTRY
_mesa_CompressedTexImage1D(GLenum target,GLint level,GLenum internalFormat,GLsizei width,GLint border,GLsizei imageSize,const GLvoid * data)4480 _mesa_CompressedTexImage1D(GLenum target, GLint level,
4481                               GLenum internalFormat, GLsizei width,
4482                               GLint border, GLsizei imageSize,
4483                               const GLvoid *data)
4484 {
4485    GET_CURRENT_CONTEXT(ctx);
4486    teximage(ctx, GL_TRUE, 1, target, level, internalFormat,
4487             width, 1, 1, border, GL_NONE, GL_NONE, imageSize, data);
4488 }
4489 
4490 
4491 void GLAPIENTRY
_mesa_CompressedTexImage2D(GLenum target,GLint level,GLenum internalFormat,GLsizei width,GLsizei height,GLint border,GLsizei imageSize,const GLvoid * data)4492 _mesa_CompressedTexImage2D(GLenum target, GLint level,
4493                               GLenum internalFormat, GLsizei width,
4494                               GLsizei height, GLint border, GLsizei imageSize,
4495                               const GLvoid *data)
4496 {
4497    GET_CURRENT_CONTEXT(ctx);
4498    teximage(ctx, GL_TRUE, 2, target, level, internalFormat,
4499             width, height, 1, border, GL_NONE, GL_NONE, imageSize, data);
4500 }
4501 
4502 
4503 void GLAPIENTRY
_mesa_CompressedTexImage3D(GLenum target,GLint level,GLenum internalFormat,GLsizei width,GLsizei height,GLsizei depth,GLint border,GLsizei imageSize,const GLvoid * data)4504 _mesa_CompressedTexImage3D(GLenum target, GLint level,
4505                               GLenum internalFormat, GLsizei width,
4506                               GLsizei height, GLsizei depth, GLint border,
4507                               GLsizei imageSize, const GLvoid *data)
4508 {
4509    GET_CURRENT_CONTEXT(ctx);
4510    teximage(ctx, GL_TRUE, 3, target, level, internalFormat,
4511             width, height, depth, border, GL_NONE, GL_NONE, imageSize, data);
4512 }
4513 
4514 
4515 /**
4516  * Common helper for glCompressedTexSubImage1/2/3D() and
4517  * glCompressedTextureSubImage1/2/3D().
4518  */
4519 void
_mesa_compressed_texture_sub_image(struct gl_context * ctx,GLuint dims,struct gl_texture_object * texObj,struct gl_texture_image * texImage,GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLsizei imageSize,const GLvoid * data)4520 _mesa_compressed_texture_sub_image(struct gl_context *ctx, GLuint dims,
4521                                    struct gl_texture_object *texObj,
4522                                    struct gl_texture_image *texImage,
4523                                    GLenum target, GLint level,
4524                                    GLint xoffset, GLint yoffset,
4525                                    GLint zoffset,
4526                                    GLsizei width, GLsizei height,
4527                                    GLsizei depth,
4528                                    GLenum format, GLsizei imageSize,
4529                                    const GLvoid *data)
4530 {
4531    FLUSH_VERTICES(ctx, 0);
4532 
4533    _mesa_lock_texture(ctx, texObj);
4534    {
4535       if (width > 0 && height > 0 && depth > 0) {
4536          ctx->Driver.CompressedTexSubImage(ctx, dims, texImage,
4537                                            xoffset, yoffset, zoffset,
4538                                            width, height, depth,
4539                                            format, imageSize, data);
4540 
4541          check_gen_mipmap(ctx, target, texObj, level);
4542 
4543          /* NOTE: Don't signal _NEW_TEXTURE since we've only changed
4544           * the texel data, not the texture format, size, etc.
4545           */
4546       }
4547    }
4548    _mesa_unlock_texture(ctx, texObj);
4549 }
4550 
4551 
4552 void GLAPIENTRY
_mesa_CompressedTexSubImage1D(GLenum target,GLint level,GLint xoffset,GLsizei width,GLenum format,GLsizei imageSize,const GLvoid * data)4553 _mesa_CompressedTexSubImage1D(GLenum target, GLint level, GLint xoffset,
4554                               GLsizei width, GLenum format,
4555                               GLsizei imageSize, const GLvoid *data)
4556 {
4557    struct gl_texture_object *texObj;
4558    struct gl_texture_image *texImage;
4559 
4560    GET_CURRENT_CONTEXT(ctx);
4561 
4562    if (compressed_subtexture_target_check(ctx, target, 1, format, false,
4563                                           "glCompressedTexSubImage1D")) {
4564       return;
4565    }
4566 
4567    texObj = _mesa_get_current_tex_object(ctx, target);
4568    if (!texObj)
4569       return;
4570 
4571    if (compressed_subtexture_error_check(ctx, 1, texObj, target,
4572                                          level, xoffset, 0, 0,
4573                                          width, 1, 1,
4574                                          format, imageSize, data,
4575                                          "glCompressedTexSubImage1D")) {
4576       return;
4577    }
4578 
4579    texImage = _mesa_select_tex_image(texObj, target, level);
4580    assert(texImage);
4581 
4582    _mesa_compressed_texture_sub_image(ctx, 1, texObj, texImage, target, level,
4583                                       xoffset, 0, 0, width, 1, 1,
4584                                       format, imageSize, data);
4585 }
4586 
4587 void GLAPIENTRY
_mesa_CompressedTextureSubImage1D(GLuint texture,GLint level,GLint xoffset,GLsizei width,GLenum format,GLsizei imageSize,const GLvoid * data)4588 _mesa_CompressedTextureSubImage1D(GLuint texture, GLint level, GLint xoffset,
4589                                   GLsizei width, GLenum format,
4590                                   GLsizei imageSize, const GLvoid *data)
4591 {
4592    struct gl_texture_object *texObj;
4593    struct gl_texture_image *texImage;
4594 
4595    GET_CURRENT_CONTEXT(ctx);
4596 
4597    texObj = _mesa_lookup_texture_err(ctx, texture,
4598                                      "glCompressedTextureSubImage1D");
4599    if (!texObj)
4600       return;
4601 
4602    if (compressed_subtexture_target_check(ctx, texObj->Target, 1, format, true,
4603                                           "glCompressedTextureSubImage1D")) {
4604       return;
4605    }
4606 
4607    if (compressed_subtexture_error_check(ctx, 1, texObj, texObj->Target,
4608                                          level, xoffset, 0, 0,
4609                                          width, 1, 1,
4610                                          format, imageSize, data,
4611                                          "glCompressedTextureSubImage1D")) {
4612       return;
4613    }
4614 
4615    texImage = _mesa_select_tex_image(texObj, texObj->Target, level);
4616    assert(texImage);
4617 
4618    _mesa_compressed_texture_sub_image(ctx, 1, texObj, texImage,
4619                                       texObj->Target, level,
4620                                       xoffset, 0, 0, width, 1, 1,
4621                                       format, imageSize, data);
4622 }
4623 
4624 
4625 void GLAPIENTRY
_mesa_CompressedTexSubImage2D(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLsizei imageSize,const GLvoid * data)4626 _mesa_CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset,
4627                               GLint yoffset, GLsizei width, GLsizei height,
4628                               GLenum format, GLsizei imageSize,
4629                               const GLvoid *data)
4630 {
4631    struct gl_texture_object *texObj;
4632    struct gl_texture_image *texImage;
4633 
4634    GET_CURRENT_CONTEXT(ctx);
4635 
4636    if (compressed_subtexture_target_check(ctx, target, 2, format, false,
4637                                           "glCompressedTexSubImage2D")) {
4638       return;
4639    }
4640 
4641    texObj = _mesa_get_current_tex_object(ctx, target);
4642    if (!texObj)
4643       return;
4644 
4645    if (compressed_subtexture_error_check(ctx, 2, texObj, target,
4646                                          level, xoffset, yoffset, 0,
4647                                          width, height, 1,
4648                                          format, imageSize, data,
4649                                          "glCompressedTexSubImage2D")) {
4650       return;
4651    }
4652 
4653 
4654    texImage = _mesa_select_tex_image(texObj, target, level);
4655    assert(texImage);
4656 
4657    _mesa_compressed_texture_sub_image(ctx, 2, texObj, texImage, target, level,
4658                                       xoffset, yoffset, 0, width, height, 1,
4659                                       format, imageSize, data);
4660 }
4661 
4662 void GLAPIENTRY
_mesa_CompressedTextureSubImage2D(GLuint texture,GLint level,GLint xoffset,GLint yoffset,GLsizei width,GLsizei height,GLenum format,GLsizei imageSize,const GLvoid * data)4663 _mesa_CompressedTextureSubImage2D(GLuint texture, GLint level, GLint xoffset,
4664                                   GLint yoffset,
4665                                   GLsizei width, GLsizei height,
4666                                   GLenum format, GLsizei imageSize,
4667                                   const GLvoid *data)
4668 {
4669    struct gl_texture_object *texObj;
4670    struct gl_texture_image *texImage;
4671 
4672    GET_CURRENT_CONTEXT(ctx);
4673 
4674    texObj = _mesa_lookup_texture_err(ctx, texture,
4675                                  "glCompressedTextureSubImage2D");
4676    if (!texObj)
4677       return;
4678 
4679    if (compressed_subtexture_target_check(ctx, texObj->Target, 2, format, true,
4680                                           "glCompressedTextureSubImage2D")) {
4681       return;
4682    }
4683 
4684    if (compressed_subtexture_error_check(ctx, 2, texObj, texObj->Target,
4685                                          level, xoffset, yoffset, 0,
4686                                          width, height, 1,
4687                                          format, imageSize, data,
4688                                          "glCompressedTextureSubImage2D")) {
4689       return;
4690    }
4691 
4692    texImage = _mesa_select_tex_image(texObj, texObj->Target, level);
4693    assert(texImage);
4694 
4695    _mesa_compressed_texture_sub_image(ctx, 2, texObj, texImage,
4696                                       texObj->Target, level,
4697                                       xoffset, yoffset, 0, width, height, 1,
4698                                       format, imageSize, data);
4699 }
4700 
4701 void GLAPIENTRY
_mesa_CompressedTexSubImage3D(GLenum target,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLsizei imageSize,const GLvoid * data)4702 _mesa_CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset,
4703                               GLint yoffset, GLint zoffset, GLsizei width,
4704                               GLsizei height, GLsizei depth, GLenum format,
4705                               GLsizei imageSize, const GLvoid *data)
4706 {
4707    struct gl_texture_object *texObj;
4708    struct gl_texture_image *texImage;
4709 
4710    GET_CURRENT_CONTEXT(ctx);
4711 
4712    if (compressed_subtexture_target_check(ctx, target, 3, format, false,
4713                                           "glCompressedTexSubImage3D")) {
4714       return;
4715    }
4716 
4717    texObj = _mesa_get_current_tex_object(ctx, target);
4718    if (!texObj)
4719       return;
4720 
4721    if (compressed_subtexture_error_check(ctx, 3, texObj, target,
4722                                          level, xoffset, yoffset, zoffset,
4723                                          width, height, depth,
4724                                          format, imageSize, data,
4725                                          "glCompressedTexSubImage3D")) {
4726       return;
4727    }
4728 
4729 
4730    texImage = _mesa_select_tex_image(texObj, target, level);
4731    assert(texImage);
4732 
4733    _mesa_compressed_texture_sub_image(ctx, 3, texObj, texImage, target, level,
4734                                       xoffset, yoffset, zoffset,
4735                                       width, height, depth,
4736                                       format, imageSize, data);
4737 }
4738 
4739 void GLAPIENTRY
_mesa_CompressedTextureSubImage3D(GLuint texture,GLint level,GLint xoffset,GLint yoffset,GLint zoffset,GLsizei width,GLsizei height,GLsizei depth,GLenum format,GLsizei imageSize,const GLvoid * data)4740 _mesa_CompressedTextureSubImage3D(GLuint texture, GLint level, GLint xoffset,
4741                                   GLint yoffset, GLint zoffset, GLsizei width,
4742                                   GLsizei height, GLsizei depth,
4743                                   GLenum format, GLsizei imageSize,
4744                                   const GLvoid *data)
4745 {
4746    struct gl_texture_object *texObj;
4747    struct gl_texture_image *texImage;
4748 
4749    GET_CURRENT_CONTEXT(ctx);
4750 
4751    texObj = _mesa_lookup_texture_err(ctx, texture,
4752                                      "glCompressedTextureSubImage3D");
4753    if (!texObj)
4754       return;
4755 
4756    if (compressed_subtexture_target_check(ctx, texObj->Target, 3, format, true,
4757                                           "glCompressedTextureSubImage3D")) {
4758       return;
4759    }
4760 
4761    if (compressed_subtexture_error_check(ctx, 3, texObj, texObj->Target,
4762                                          level, xoffset, yoffset, zoffset,
4763                                          width, height, depth,
4764                                          format, imageSize, data,
4765                                          "glCompressedTextureSubImage3D")) {
4766       return;
4767    }
4768 
4769    /* Must handle special case GL_TEXTURE_CUBE_MAP. */
4770    if (texObj->Target == GL_TEXTURE_CUBE_MAP) {
4771       const char *pixels = data;
4772       int i;
4773       GLint image_stride;
4774 
4775       /* Make sure the texture object is a proper cube.
4776        * (See texturesubimage in teximage.c for details on why this check is
4777        * performed.)
4778        */
4779       if (!_mesa_cube_level_complete(texObj, level)) {
4780          _mesa_error(ctx, GL_INVALID_OPERATION,
4781                      "glCompressedTextureSubImage3D(cube map incomplete)");
4782          return;
4783       }
4784 
4785       /* Copy in each face. */
4786       for (i = 0; i < 6; ++i) {
4787          texImage = texObj->Image[i][level];
4788          assert(texImage);
4789 
4790          _mesa_compressed_texture_sub_image(ctx, 3, texObj, texImage,
4791                                             texObj->Target, level,
4792                                             xoffset, yoffset, zoffset,
4793                                             width, height, 1,
4794                                             format, imageSize, pixels);
4795 
4796          /* Compressed images don't have a client format */
4797          image_stride = _mesa_format_image_size(texImage->TexFormat,
4798                                                 texImage->Width,
4799                                                 texImage->Height, 1);
4800 
4801          pixels += image_stride;
4802          imageSize -= image_stride;
4803       }
4804    }
4805    else {
4806       texImage = _mesa_select_tex_image(texObj, texObj->Target, level);
4807       assert(texImage);
4808 
4809       _mesa_compressed_texture_sub_image(ctx, 3, texObj, texImage,
4810                                          texObj->Target, level,
4811                                          xoffset, yoffset, zoffset,
4812                                          width, height, depth,
4813                                          format, imageSize, data);
4814    }
4815 }
4816 
4817 static mesa_format
get_texbuffer_format(const struct gl_context * ctx,GLenum internalFormat)4818 get_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat)
4819 {
4820    if (ctx->API == API_OPENGL_COMPAT) {
4821       switch (internalFormat) {
4822       case GL_ALPHA8:
4823          return MESA_FORMAT_A_UNORM8;
4824       case GL_ALPHA16:
4825          return MESA_FORMAT_A_UNORM16;
4826       case GL_ALPHA16F_ARB:
4827          return MESA_FORMAT_A_FLOAT16;
4828       case GL_ALPHA32F_ARB:
4829          return MESA_FORMAT_A_FLOAT32;
4830       case GL_ALPHA8I_EXT:
4831          return MESA_FORMAT_A_SINT8;
4832       case GL_ALPHA16I_EXT:
4833          return MESA_FORMAT_A_SINT16;
4834       case GL_ALPHA32I_EXT:
4835          return MESA_FORMAT_A_SINT32;
4836       case GL_ALPHA8UI_EXT:
4837          return MESA_FORMAT_A_UINT8;
4838       case GL_ALPHA16UI_EXT:
4839          return MESA_FORMAT_A_UINT16;
4840       case GL_ALPHA32UI_EXT:
4841          return MESA_FORMAT_A_UINT32;
4842       case GL_LUMINANCE8:
4843          return MESA_FORMAT_L_UNORM8;
4844       case GL_LUMINANCE16:
4845          return MESA_FORMAT_L_UNORM16;
4846       case GL_LUMINANCE16F_ARB:
4847          return MESA_FORMAT_L_FLOAT16;
4848       case GL_LUMINANCE32F_ARB:
4849          return MESA_FORMAT_L_FLOAT32;
4850       case GL_LUMINANCE8I_EXT:
4851          return MESA_FORMAT_L_SINT8;
4852       case GL_LUMINANCE16I_EXT:
4853          return MESA_FORMAT_L_SINT16;
4854       case GL_LUMINANCE32I_EXT:
4855          return MESA_FORMAT_L_SINT32;
4856       case GL_LUMINANCE8UI_EXT:
4857          return MESA_FORMAT_L_UINT8;
4858       case GL_LUMINANCE16UI_EXT:
4859          return MESA_FORMAT_L_UINT16;
4860       case GL_LUMINANCE32UI_EXT:
4861          return MESA_FORMAT_L_UINT32;
4862       case GL_LUMINANCE8_ALPHA8:
4863          return MESA_FORMAT_L8A8_UNORM;
4864       case GL_LUMINANCE16_ALPHA16:
4865          return MESA_FORMAT_L16A16_UNORM;
4866       case GL_LUMINANCE_ALPHA16F_ARB:
4867          return MESA_FORMAT_LA_FLOAT16;
4868       case GL_LUMINANCE_ALPHA32F_ARB:
4869          return MESA_FORMAT_LA_FLOAT32;
4870       case GL_LUMINANCE_ALPHA8I_EXT:
4871          return MESA_FORMAT_LA_SINT8;
4872       case GL_LUMINANCE_ALPHA16I_EXT:
4873          return MESA_FORMAT_LA_SINT16;
4874       case GL_LUMINANCE_ALPHA32I_EXT:
4875          return MESA_FORMAT_LA_SINT32;
4876       case GL_LUMINANCE_ALPHA8UI_EXT:
4877          return MESA_FORMAT_LA_UINT8;
4878       case GL_LUMINANCE_ALPHA16UI_EXT:
4879          return MESA_FORMAT_LA_UINT16;
4880       case GL_LUMINANCE_ALPHA32UI_EXT:
4881          return MESA_FORMAT_LA_UINT32;
4882       case GL_INTENSITY8:
4883          return MESA_FORMAT_I_UNORM8;
4884       case GL_INTENSITY16:
4885          return MESA_FORMAT_I_UNORM16;
4886       case GL_INTENSITY16F_ARB:
4887          return MESA_FORMAT_I_FLOAT16;
4888       case GL_INTENSITY32F_ARB:
4889          return MESA_FORMAT_I_FLOAT32;
4890       case GL_INTENSITY8I_EXT:
4891          return MESA_FORMAT_I_SINT8;
4892       case GL_INTENSITY16I_EXT:
4893          return MESA_FORMAT_I_SINT16;
4894       case GL_INTENSITY32I_EXT:
4895          return MESA_FORMAT_I_SINT32;
4896       case GL_INTENSITY8UI_EXT:
4897          return MESA_FORMAT_I_UINT8;
4898       case GL_INTENSITY16UI_EXT:
4899          return MESA_FORMAT_I_UINT16;
4900       case GL_INTENSITY32UI_EXT:
4901          return MESA_FORMAT_I_UINT32;
4902       default:
4903          break;
4904       }
4905    }
4906 
4907    if (_mesa_has_ARB_texture_buffer_object_rgb32(ctx) ||
4908        _mesa_has_OES_texture_buffer(ctx)) {
4909       switch (internalFormat) {
4910       case GL_RGB32F:
4911          return MESA_FORMAT_RGB_FLOAT32;
4912       case GL_RGB32UI:
4913          return MESA_FORMAT_RGB_UINT32;
4914       case GL_RGB32I:
4915          return MESA_FORMAT_RGB_SINT32;
4916       default:
4917          break;
4918       }
4919    }
4920 
4921    switch (internalFormat) {
4922    case GL_RGBA8:
4923       return MESA_FORMAT_R8G8B8A8_UNORM;
4924    case GL_RGBA16:
4925       if (_mesa_is_gles(ctx))
4926          return MESA_FORMAT_NONE;
4927       return MESA_FORMAT_RGBA_UNORM16;
4928    case GL_RGBA16F_ARB:
4929       return MESA_FORMAT_RGBA_FLOAT16;
4930    case GL_RGBA32F_ARB:
4931       return MESA_FORMAT_RGBA_FLOAT32;
4932    case GL_RGBA8I_EXT:
4933       return MESA_FORMAT_RGBA_SINT8;
4934    case GL_RGBA16I_EXT:
4935       return MESA_FORMAT_RGBA_SINT16;
4936    case GL_RGBA32I_EXT:
4937       return MESA_FORMAT_RGBA_SINT32;
4938    case GL_RGBA8UI_EXT:
4939       return MESA_FORMAT_RGBA_UINT8;
4940    case GL_RGBA16UI_EXT:
4941       return MESA_FORMAT_RGBA_UINT16;
4942    case GL_RGBA32UI_EXT:
4943       return MESA_FORMAT_RGBA_UINT32;
4944 
4945    case GL_RG8:
4946       return MESA_FORMAT_R8G8_UNORM;
4947    case GL_RG16:
4948       if (_mesa_is_gles(ctx))
4949          return MESA_FORMAT_NONE;
4950       return MESA_FORMAT_R16G16_UNORM;
4951    case GL_RG16F:
4952       return MESA_FORMAT_RG_FLOAT16;
4953    case GL_RG32F:
4954       return MESA_FORMAT_RG_FLOAT32;
4955    case GL_RG8I:
4956       return MESA_FORMAT_RG_SINT8;
4957    case GL_RG16I:
4958       return MESA_FORMAT_RG_SINT16;
4959    case GL_RG32I:
4960       return MESA_FORMAT_RG_SINT32;
4961    case GL_RG8UI:
4962       return MESA_FORMAT_RG_UINT8;
4963    case GL_RG16UI:
4964       return MESA_FORMAT_RG_UINT16;
4965    case GL_RG32UI:
4966       return MESA_FORMAT_RG_UINT32;
4967 
4968    case GL_R8:
4969       return MESA_FORMAT_R_UNORM8;
4970    case GL_R16:
4971       if (_mesa_is_gles(ctx))
4972          return MESA_FORMAT_NONE;
4973       return MESA_FORMAT_R_UNORM16;
4974    case GL_R16F:
4975       return MESA_FORMAT_R_FLOAT16;
4976    case GL_R32F:
4977       return MESA_FORMAT_R_FLOAT32;
4978    case GL_R8I:
4979       return MESA_FORMAT_R_SINT8;
4980    case GL_R16I:
4981       return MESA_FORMAT_R_SINT16;
4982    case GL_R32I:
4983       return MESA_FORMAT_R_SINT32;
4984    case GL_R8UI:
4985       return MESA_FORMAT_R_UINT8;
4986    case GL_R16UI:
4987       return MESA_FORMAT_R_UINT16;
4988    case GL_R32UI:
4989       return MESA_FORMAT_R_UINT32;
4990 
4991    default:
4992       return MESA_FORMAT_NONE;
4993    }
4994 }
4995 
4996 
4997 mesa_format
_mesa_validate_texbuffer_format(const struct gl_context * ctx,GLenum internalFormat)4998 _mesa_validate_texbuffer_format(const struct gl_context *ctx,
4999                                 GLenum internalFormat)
5000 {
5001    mesa_format format = get_texbuffer_format(ctx, internalFormat);
5002    GLenum datatype;
5003 
5004    if (format == MESA_FORMAT_NONE)
5005       return MESA_FORMAT_NONE;
5006 
5007    datatype = _mesa_get_format_datatype(format);
5008 
5009    /* The GL_ARB_texture_buffer_object spec says:
5010     *
5011     *     "If ARB_texture_float is not supported, references to the
5012     *     floating-point internal formats provided by that extension should be
5013     *     removed, and such formats may not be passed to TexBufferARB."
5014     *
5015     * As a result, GL_HALF_FLOAT internal format depends on both
5016     * GL_ARB_texture_float and GL_ARB_half_float_pixel.
5017     */
5018    if ((datatype == GL_FLOAT || datatype == GL_HALF_FLOAT) &&
5019        !ctx->Extensions.ARB_texture_float)
5020       return MESA_FORMAT_NONE;
5021 
5022    if (!ctx->Extensions.ARB_texture_rg) {
5023       GLenum base_format = _mesa_get_format_base_format(format);
5024       if (base_format == GL_R || base_format == GL_RG)
5025          return MESA_FORMAT_NONE;
5026    }
5027 
5028    if (!ctx->Extensions.ARB_texture_buffer_object_rgb32) {
5029       GLenum base_format = _mesa_get_format_base_format(format);
5030       if (base_format == GL_RGB)
5031          return MESA_FORMAT_NONE;
5032    }
5033    return format;
5034 }
5035 
5036 
5037 /**
5038  * Do work common to glTexBuffer, glTexBufferRange, glTextureBuffer
5039  * and glTextureBufferRange, including some error checking.
5040  */
5041 static void
texture_buffer_range(struct gl_context * ctx,struct gl_texture_object * texObj,GLenum internalFormat,struct gl_buffer_object * bufObj,GLintptr offset,GLsizeiptr size,const char * caller)5042 texture_buffer_range(struct gl_context *ctx,
5043                      struct gl_texture_object *texObj,
5044                      GLenum internalFormat,
5045                      struct gl_buffer_object *bufObj,
5046                      GLintptr offset, GLsizeiptr size,
5047                      const char *caller)
5048 {
5049    GLintptr oldOffset = texObj->BufferOffset;
5050    GLsizeiptr oldSize = texObj->BufferSize;
5051    mesa_format format;
5052 
5053    /* NOTE: ARB_texture_buffer_object has interactions with
5054     * the compatibility profile that are not implemented.
5055     */
5056    if (!_mesa_has_ARB_texture_buffer_object(ctx) &&
5057        !_mesa_has_OES_texture_buffer(ctx)) {
5058       _mesa_error(ctx, GL_INVALID_OPERATION,
5059                   "%s(ARB_texture_buffer_object is not"
5060                   " implemented for the compatibility profile)", caller);
5061       return;
5062    }
5063 
5064    format = _mesa_validate_texbuffer_format(ctx, internalFormat);
5065    if (format == MESA_FORMAT_NONE) {
5066       _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalFormat %s)",
5067                   caller, _mesa_enum_to_string(internalFormat));
5068       return;
5069    }
5070 
5071    FLUSH_VERTICES(ctx, 0);
5072 
5073    _mesa_lock_texture(ctx, texObj);
5074    {
5075       _mesa_reference_buffer_object(ctx, &texObj->BufferObject, bufObj);
5076       texObj->BufferObjectFormat = internalFormat;
5077       texObj->_BufferObjectFormat = format;
5078       texObj->BufferOffset = offset;
5079       texObj->BufferSize = size;
5080    }
5081    _mesa_unlock_texture(ctx, texObj);
5082 
5083    if (ctx->Driver.TexParameter) {
5084       if (offset != oldOffset) {
5085          ctx->Driver.TexParameter(ctx, texObj, GL_TEXTURE_BUFFER_OFFSET);
5086       }
5087       if (size != oldSize) {
5088          ctx->Driver.TexParameter(ctx, texObj, GL_TEXTURE_BUFFER_SIZE);
5089       }
5090    }
5091 
5092    ctx->NewDriverState |= ctx->DriverFlags.NewTextureBuffer;
5093 
5094    if (bufObj) {
5095       bufObj->UsageHistory |= USAGE_TEXTURE_BUFFER;
5096    }
5097 }
5098 
5099 
5100 /**
5101  * Make sure the texture buffer target is GL_TEXTURE_BUFFER.
5102  * Return true if it is, and return false if it is not
5103  * (and throw INVALID ENUM as dictated in the OpenGL 4.5
5104  * core spec, 02.02.2015, PDF page 245).
5105  */
5106 static bool
check_texture_buffer_target(struct gl_context * ctx,GLenum target,const char * caller)5107 check_texture_buffer_target(struct gl_context *ctx, GLenum target,
5108                             const char *caller)
5109 {
5110    if (target != GL_TEXTURE_BUFFER_ARB) {
5111       _mesa_error(ctx, GL_INVALID_ENUM,
5112                   "%s(texture target is not GL_TEXTURE_BUFFER)", caller);
5113       return false;
5114    }
5115    else
5116       return true;
5117 }
5118 
5119 /**
5120  * Check for errors related to the texture buffer range.
5121  * Return false if errors are found, true if none are found.
5122  */
5123 static bool
check_texture_buffer_range(struct gl_context * ctx,struct gl_buffer_object * bufObj,GLintptr offset,GLsizeiptr size,const char * caller)5124 check_texture_buffer_range(struct gl_context *ctx,
5125                            struct gl_buffer_object *bufObj,
5126                            GLintptr offset, GLsizeiptr size,
5127                            const char *caller)
5128 {
5129    /* OpenGL 4.5 core spec (02.02.2015) says in Section 8.9 Buffer
5130     * Textures (PDF page 245):
5131     *    "An INVALID_VALUE error is generated if offset is negative, if
5132     *    size is less than or equal to zero, or if offset + size is greater
5133     *    than the value of BUFFER_SIZE for the buffer bound to target."
5134     */
5135    if (offset < 0) {
5136       _mesa_error(ctx, GL_INVALID_VALUE, "%s(offset=%d < 0)", caller,
5137                   (int) offset);
5138       return false;
5139    }
5140 
5141    if (size <= 0) {
5142       _mesa_error(ctx, GL_INVALID_VALUE, "%s(size=%d <= 0)", caller,
5143                   (int) size);
5144       return false;
5145    }
5146 
5147    if (offset + size > bufObj->Size) {
5148       _mesa_error(ctx, GL_INVALID_VALUE,
5149                   "%s(offset=%d + size=%d > buffer_size=%d)", caller,
5150                   (int) offset, (int) size, (int) bufObj->Size);
5151       return false;
5152    }
5153 
5154    /* OpenGL 4.5 core spec (02.02.2015) says in Section 8.9 Buffer
5155     * Textures (PDF page 245):
5156     *    "An INVALID_VALUE error is generated if offset is not an integer
5157     *    multiple of the value of TEXTURE_BUFFER_OFFSET_ALIGNMENT."
5158     */
5159    if (offset % ctx->Const.TextureBufferOffsetAlignment) {
5160       _mesa_error(ctx, GL_INVALID_VALUE,
5161                   "%s(invalid offset alignment)", caller);
5162       return false;
5163    }
5164 
5165    return true;
5166 }
5167 
5168 
5169 /** GL_ARB_texture_buffer_object */
5170 void GLAPIENTRY
_mesa_TexBuffer(GLenum target,GLenum internalFormat,GLuint buffer)5171 _mesa_TexBuffer(GLenum target, GLenum internalFormat, GLuint buffer)
5172 {
5173    struct gl_texture_object *texObj;
5174    struct gl_buffer_object *bufObj;
5175 
5176    GET_CURRENT_CONTEXT(ctx);
5177 
5178    /* Need to catch a bad target before it gets to
5179     * _mesa_get_current_tex_object.
5180     */
5181    if (!check_texture_buffer_target(ctx, target, "glTexBuffer"))
5182       return;
5183 
5184    if (buffer) {
5185       bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glTexBuffer");
5186       if (!bufObj)
5187          return;
5188    } else
5189       bufObj = NULL;
5190 
5191    texObj = _mesa_get_current_tex_object(ctx, target);
5192    if (!texObj)
5193       return;
5194 
5195    texture_buffer_range(ctx, texObj, internalFormat, bufObj, 0,
5196                         buffer ? -1 : 0, "glTexBuffer");
5197 }
5198 
5199 
5200 /** GL_ARB_texture_buffer_range */
5201 void GLAPIENTRY
_mesa_TexBufferRange(GLenum target,GLenum internalFormat,GLuint buffer,GLintptr offset,GLsizeiptr size)5202 _mesa_TexBufferRange(GLenum target, GLenum internalFormat, GLuint buffer,
5203                      GLintptr offset, GLsizeiptr size)
5204 {
5205    struct gl_texture_object *texObj;
5206    struct gl_buffer_object *bufObj;
5207 
5208    GET_CURRENT_CONTEXT(ctx);
5209 
5210    /* Need to catch a bad target before it gets to
5211     * _mesa_get_current_tex_object.
5212     */
5213    if (!check_texture_buffer_target(ctx, target, "glTexBufferRange"))
5214       return;
5215 
5216    if (buffer) {
5217       bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glTexBufferRange");
5218       if (!bufObj)
5219          return;
5220 
5221       if (!check_texture_buffer_range(ctx, bufObj, offset, size,
5222           "glTexBufferRange"))
5223          return;
5224 
5225    } else {
5226       /* OpenGL 4.5 core spec (02.02.2015) says in Section 8.9 Buffer
5227        * Textures (PDF page 254):
5228        *    "If buffer is zero, then any buffer object attached to the buffer
5229        *    texture is detached, the values offset and size are ignored and
5230        *    the state for offset and size for the buffer texture are reset to
5231        *    zero."
5232        */
5233       offset = 0;
5234       size = 0;
5235       bufObj = NULL;
5236    }
5237 
5238    texObj = _mesa_get_current_tex_object(ctx, target);
5239    if (!texObj)
5240       return;
5241 
5242    texture_buffer_range(ctx, texObj, internalFormat, bufObj,
5243                         offset, size, "glTexBufferRange");
5244 }
5245 
5246 void GLAPIENTRY
_mesa_TextureBuffer(GLuint texture,GLenum internalFormat,GLuint buffer)5247 _mesa_TextureBuffer(GLuint texture, GLenum internalFormat, GLuint buffer)
5248 {
5249    struct gl_texture_object *texObj;
5250    struct gl_buffer_object *bufObj;
5251 
5252    GET_CURRENT_CONTEXT(ctx);
5253 
5254    if (buffer) {
5255       bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glTextureBuffer");
5256       if (!bufObj)
5257          return;
5258    } else
5259       bufObj = NULL;
5260 
5261    /* Get the texture object by Name. */
5262    texObj = _mesa_lookup_texture_err(ctx, texture, "glTextureBuffer");
5263    if (!texObj)
5264       return;
5265 
5266    if (!check_texture_buffer_target(ctx, texObj->Target, "glTextureBuffer"))
5267       return;
5268 
5269    texture_buffer_range(ctx, texObj, internalFormat,
5270                         bufObj, 0, buffer ? -1 : 0, "glTextureBuffer");
5271 }
5272 
5273 void GLAPIENTRY
_mesa_TextureBufferRange(GLuint texture,GLenum internalFormat,GLuint buffer,GLintptr offset,GLsizeiptr size)5274 _mesa_TextureBufferRange(GLuint texture, GLenum internalFormat, GLuint buffer,
5275                          GLintptr offset, GLsizeiptr size)
5276 {
5277    struct gl_texture_object *texObj;
5278    struct gl_buffer_object *bufObj;
5279 
5280    GET_CURRENT_CONTEXT(ctx);
5281 
5282    if (buffer) {
5283       bufObj = _mesa_lookup_bufferobj_err(ctx, buffer,
5284                                           "glTextureBufferRange");
5285       if (!bufObj)
5286          return;
5287 
5288       if (!check_texture_buffer_range(ctx, bufObj, offset, size,
5289           "glTextureBufferRange"))
5290          return;
5291 
5292    } else {
5293       /* OpenGL 4.5 core spec (02.02.2015) says in Section 8.9 Buffer
5294        * Textures (PDF page 254):
5295        *    "If buffer is zero, then any buffer object attached to the buffer
5296        *    texture is detached, the values offset and size are ignored and
5297        *    the state for offset and size for the buffer texture are reset to
5298        *    zero."
5299        */
5300       offset = 0;
5301       size = 0;
5302       bufObj = NULL;
5303    }
5304 
5305    /* Get the texture object by Name. */
5306    texObj = _mesa_lookup_texture_err(ctx, texture, "glTextureBufferRange");
5307    if (!texObj)
5308       return;
5309 
5310    if (!check_texture_buffer_target(ctx, texObj->Target,
5311        "glTextureBufferRange"))
5312       return;
5313 
5314    texture_buffer_range(ctx, texObj, internalFormat,
5315                         bufObj, offset, size, "glTextureBufferRange");
5316 }
5317 
5318 GLboolean
_mesa_is_renderable_texture_format(struct gl_context * ctx,GLenum internalformat)5319 _mesa_is_renderable_texture_format(struct gl_context *ctx, GLenum internalformat)
5320 {
5321    /* Everything that is allowed for renderbuffers,
5322     * except for a base format of GL_STENCIL_INDEX, unless supported.
5323     */
5324    GLenum baseFormat = _mesa_base_fbo_format(ctx, internalformat);
5325    if (ctx->Extensions.ARB_texture_stencil8)
5326       return baseFormat != 0;
5327    else
5328       return baseFormat != 0 && baseFormat != GL_STENCIL_INDEX;
5329 }
5330 
5331 
5332 /** GL_ARB_texture_multisample */
5333 static GLboolean
check_multisample_target(GLuint dims,GLenum target,bool dsa)5334 check_multisample_target(GLuint dims, GLenum target, bool dsa)
5335 {
5336    switch(target) {
5337    case GL_TEXTURE_2D_MULTISAMPLE:
5338       return dims == 2;
5339    case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
5340       return dims == 2 && !dsa;
5341    case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
5342       return dims == 3;
5343    case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
5344       return dims == 3 && !dsa;
5345    default:
5346       return GL_FALSE;
5347    }
5348 }
5349 
5350 
5351 static void
texture_image_multisample(struct gl_context * ctx,GLuint dims,struct gl_texture_object * texObj,GLenum target,GLsizei samples,GLint internalformat,GLsizei width,GLsizei height,GLsizei depth,GLboolean fixedsamplelocations,GLboolean immutable,const char * func)5352 texture_image_multisample(struct gl_context *ctx, GLuint dims,
5353                           struct gl_texture_object *texObj,
5354                           GLenum target, GLsizei samples,
5355                           GLint internalformat, GLsizei width,
5356                           GLsizei height, GLsizei depth,
5357                           GLboolean fixedsamplelocations,
5358                           GLboolean immutable, const char *func)
5359 {
5360    struct gl_texture_image *texImage;
5361    GLboolean sizeOK, dimensionsOK, samplesOK;
5362    mesa_format texFormat;
5363    GLenum sample_count_error;
5364    bool dsa = strstr(func, "ture") ? true : false;
5365 
5366    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) {
5367       _mesa_debug(ctx, "%s(target=%s, samples=%d)\n", func,
5368                   _mesa_enum_to_string(target), samples);
5369    }
5370 
5371    if (!((ctx->Extensions.ARB_texture_multisample
5372          && _mesa_is_desktop_gl(ctx))) && !_mesa_is_gles31(ctx)) {
5373       _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func);
5374       return;
5375    }
5376 
5377    if (samples < 1) {
5378       _mesa_error(ctx, GL_INVALID_VALUE, "%s(samples < 1)", func);
5379       return;
5380    }
5381 
5382    if (!check_multisample_target(dims, target, dsa)) {
5383       if (dsa) {
5384          _mesa_error(ctx, GL_INVALID_OPERATION, "%s(target)", func);
5385          return;
5386       }
5387       else {
5388          _mesa_error(ctx, GL_INVALID_ENUM, "%s(target)", func);
5389          return;
5390       }
5391    }
5392 
5393    /* check that the specified internalformat is color/depth/stencil-renderable;
5394     * refer GL3.1 spec 4.4.4
5395     */
5396 
5397    if (immutable && !_mesa_is_legal_tex_storage_format(ctx, internalformat)) {
5398       _mesa_error(ctx, GL_INVALID_ENUM,
5399             "%s(internalformat=%s not legal for immutable-format)",
5400             func, _mesa_enum_to_string(internalformat));
5401       return;
5402    }
5403 
5404    if (!_mesa_is_renderable_texture_format(ctx, internalformat)) {
5405       /* Page 172 of OpenGL ES 3.1 spec says:
5406        *   "An INVALID_ENUM error is generated if sizedinternalformat is not
5407        *   color-renderable, depth-renderable, or stencil-renderable (as
5408        *   defined in section 9.4).
5409        *
5410        *  (Same error is also defined for desktop OpenGL for multisample
5411        *  teximage/texstorage functions.)
5412        */
5413       _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalformat=%s)", func,
5414                   _mesa_enum_to_string(internalformat));
5415       return;
5416    }
5417 
5418    sample_count_error = _mesa_check_sample_count(ctx, target,
5419          internalformat, samples);
5420    samplesOK = sample_count_error == GL_NO_ERROR;
5421 
5422    /* Page 254 of OpenGL 4.4 spec says:
5423     *   "Proxy arrays for two-dimensional multisample and two-dimensional
5424     *    multisample array textures are operated on in the same way when
5425     *    TexImage2DMultisample is called with target specified as
5426     *    PROXY_TEXTURE_2D_MULTISAMPLE, or TexImage3DMultisample is called
5427     *    with target specified as PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY.
5428     *    However, if samples is not supported, then no error is generated.
5429     */
5430    if (!samplesOK && !_mesa_is_proxy_texture(target)) {
5431       _mesa_error(ctx, sample_count_error, "%s(samples)", func);
5432       return;
5433    }
5434 
5435    if (immutable && (!texObj || (texObj->Name == 0))) {
5436       _mesa_error(ctx, GL_INVALID_OPERATION,
5437             "%s(texture object 0)",
5438             func);
5439       return;
5440    }
5441 
5442    texImage = _mesa_get_tex_image(ctx, texObj, 0, 0);
5443 
5444    if (texImage == NULL) {
5445       _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s()", func);
5446       return;
5447    }
5448 
5449    texFormat = _mesa_choose_texture_format(ctx, texObj, target, 0,
5450          internalformat, GL_NONE, GL_NONE);
5451    assert(texFormat != MESA_FORMAT_NONE);
5452 
5453    dimensionsOK = _mesa_legal_texture_dimensions(ctx, target, 0,
5454          width, height, depth, 0);
5455 
5456    sizeOK = ctx->Driver.TestProxyTexImage(ctx, target, 0, 0, texFormat,
5457                                           samples, width, height, depth);
5458 
5459    if (_mesa_is_proxy_texture(target)) {
5460       if (samplesOK && dimensionsOK && sizeOK) {
5461          init_teximage_fields_ms(ctx, texImage, width, height, depth, 0,
5462                                  internalformat, texFormat,
5463                                  samples, fixedsamplelocations);
5464       }
5465       else {
5466          /* clear all image fields */
5467          clear_teximage_fields(texImage);
5468       }
5469    }
5470    else {
5471       if (!dimensionsOK) {
5472          _mesa_error(ctx, GL_INVALID_VALUE,
5473                      "%s(invalid width or height)", func);
5474          return;
5475       }
5476 
5477       if (!sizeOK) {
5478          _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(texture too large)", func);
5479          return;
5480       }
5481 
5482       /* Check if texObj->Immutable is set */
5483       if (texObj->Immutable) {
5484          _mesa_error(ctx, GL_INVALID_OPERATION, "%s(immutable)", func);
5485          return;
5486       }
5487 
5488       ctx->Driver.FreeTextureImageBuffer(ctx, texImage);
5489 
5490       init_teximage_fields_ms(ctx, texImage, width, height, depth, 0,
5491                               internalformat, texFormat,
5492                               samples, fixedsamplelocations);
5493 
5494       if (width > 0 && height > 0 && depth > 0) {
5495          if (!ctx->Driver.AllocTextureStorage(ctx, texObj, 1,
5496                                               width, height, depth)) {
5497             /* tidy up the texture image state. strictly speaking,
5498              * we're allowed to just leave this in whatever state we
5499              * like, but being tidy is good.
5500              */
5501             _mesa_init_teximage_fields(ctx, texImage,
5502                   0, 0, 0, 0, GL_NONE, MESA_FORMAT_NONE);
5503          }
5504       }
5505 
5506       texObj->Immutable |= immutable;
5507 
5508       if (immutable) {
5509          _mesa_set_texture_view_state(ctx, texObj, target, 1);
5510       }
5511 
5512       _mesa_update_fbo_texture(ctx, texObj, 0, 0);
5513    }
5514 }
5515 
5516 
5517 void GLAPIENTRY
_mesa_TexImage2DMultisample(GLenum target,GLsizei samples,GLenum internalformat,GLsizei width,GLsizei height,GLboolean fixedsamplelocations)5518 _mesa_TexImage2DMultisample(GLenum target, GLsizei samples,
5519                             GLenum internalformat, GLsizei width,
5520                             GLsizei height, GLboolean fixedsamplelocations)
5521 {
5522    struct gl_texture_object *texObj;
5523    GET_CURRENT_CONTEXT(ctx);
5524 
5525    texObj = _mesa_get_current_tex_object(ctx, target);
5526    if (!texObj)
5527       return;
5528 
5529    texture_image_multisample(ctx, 2, texObj, target, samples,
5530                              internalformat, width, height, 1,
5531                              fixedsamplelocations, GL_FALSE,
5532                              "glTexImage2DMultisample");
5533 }
5534 
5535 
5536 void GLAPIENTRY
_mesa_TexImage3DMultisample(GLenum target,GLsizei samples,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,GLboolean fixedsamplelocations)5537 _mesa_TexImage3DMultisample(GLenum target, GLsizei samples,
5538                             GLenum internalformat, GLsizei width,
5539                             GLsizei height, GLsizei depth,
5540                             GLboolean fixedsamplelocations)
5541 {
5542    struct gl_texture_object *texObj;
5543    GET_CURRENT_CONTEXT(ctx);
5544 
5545    texObj = _mesa_get_current_tex_object(ctx, target);
5546    if (!texObj)
5547       return;
5548 
5549    texture_image_multisample(ctx, 3, texObj, target, samples,
5550                              internalformat, width, height, depth,
5551                              fixedsamplelocations, GL_FALSE,
5552                              "glTexImage3DMultisample");
5553 }
5554 
5555 static bool
valid_texstorage_ms_parameters(GLsizei width,GLsizei height,GLsizei depth,GLsizei samples,unsigned dims)5556 valid_texstorage_ms_parameters(GLsizei width, GLsizei height, GLsizei depth,
5557                                GLsizei samples, unsigned dims)
5558 {
5559    GET_CURRENT_CONTEXT(ctx);
5560 
5561    if (!_mesa_valid_tex_storage_dim(width, height, depth)) {
5562       _mesa_error(ctx, GL_INVALID_VALUE,
5563                   "glTexStorage%uDMultisample(width=%d,height=%d,depth=%d)",
5564                   dims, width, height, depth);
5565       return false;
5566    }
5567    return true;
5568 }
5569 
5570 void GLAPIENTRY
_mesa_TexStorage2DMultisample(GLenum target,GLsizei samples,GLenum internalformat,GLsizei width,GLsizei height,GLboolean fixedsamplelocations)5571 _mesa_TexStorage2DMultisample(GLenum target, GLsizei samples,
5572                               GLenum internalformat, GLsizei width,
5573                               GLsizei height, GLboolean fixedsamplelocations)
5574 {
5575    struct gl_texture_object *texObj;
5576    GET_CURRENT_CONTEXT(ctx);
5577 
5578    texObj = _mesa_get_current_tex_object(ctx, target);
5579    if (!texObj)
5580       return;
5581 
5582    if (!valid_texstorage_ms_parameters(width, height, 1, samples, 2))
5583       return;
5584 
5585    texture_image_multisample(ctx, 2, texObj, target, samples,
5586                              internalformat, width, height, 1,
5587                              fixedsamplelocations, GL_TRUE,
5588                              "glTexStorage2DMultisample");
5589 }
5590 
5591 void GLAPIENTRY
_mesa_TexStorage3DMultisample(GLenum target,GLsizei samples,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,GLboolean fixedsamplelocations)5592 _mesa_TexStorage3DMultisample(GLenum target, GLsizei samples,
5593                               GLenum internalformat, GLsizei width,
5594                               GLsizei height, GLsizei depth,
5595                               GLboolean fixedsamplelocations)
5596 {
5597    struct gl_texture_object *texObj;
5598    GET_CURRENT_CONTEXT(ctx);
5599 
5600    texObj = _mesa_get_current_tex_object(ctx, target);
5601    if (!texObj)
5602       return;
5603 
5604    if (!valid_texstorage_ms_parameters(width, height, depth, samples, 3))
5605       return;
5606 
5607    texture_image_multisample(ctx, 3, texObj, target, samples,
5608                              internalformat, width, height, depth,
5609                              fixedsamplelocations, GL_TRUE,
5610                              "glTexStorage3DMultisample");
5611 }
5612 
5613 void GLAPIENTRY
_mesa_TextureStorage2DMultisample(GLuint texture,GLsizei samples,GLenum internalformat,GLsizei width,GLsizei height,GLboolean fixedsamplelocations)5614 _mesa_TextureStorage2DMultisample(GLuint texture, GLsizei samples,
5615                                   GLenum internalformat, GLsizei width,
5616                                   GLsizei height,
5617                                   GLboolean fixedsamplelocations)
5618 {
5619    struct gl_texture_object *texObj;
5620    GET_CURRENT_CONTEXT(ctx);
5621 
5622    texObj = _mesa_lookup_texture_err(ctx, texture,
5623                                      "glTextureStorage2DMultisample");
5624    if (!texObj)
5625       return;
5626 
5627    if (!valid_texstorage_ms_parameters(width, height, 1, samples, 2))
5628       return;
5629 
5630    texture_image_multisample(ctx, 2, texObj, texObj->Target, samples,
5631                              internalformat, width, height, 1,
5632                              fixedsamplelocations, GL_TRUE,
5633                              "glTextureStorage2DMultisample");
5634 }
5635 
5636 void GLAPIENTRY
_mesa_TextureStorage3DMultisample(GLuint texture,GLsizei samples,GLenum internalformat,GLsizei width,GLsizei height,GLsizei depth,GLboolean fixedsamplelocations)5637 _mesa_TextureStorage3DMultisample(GLuint texture, GLsizei samples,
5638                                   GLenum internalformat, GLsizei width,
5639                                   GLsizei height, GLsizei depth,
5640                                   GLboolean fixedsamplelocations)
5641 {
5642    struct gl_texture_object *texObj;
5643    GET_CURRENT_CONTEXT(ctx);
5644 
5645    /* Get the texture object by Name. */
5646    texObj = _mesa_lookup_texture_err(ctx, texture,
5647                                      "glTextureStorage3DMultisample");
5648    if (!texObj)
5649       return;
5650 
5651    if (!valid_texstorage_ms_parameters(width, height, depth, samples, 3))
5652       return;
5653 
5654    texture_image_multisample(ctx, 3, texObj, texObj->Target, samples,
5655                              internalformat, width, height, depth,
5656                              fixedsamplelocations, GL_TRUE,
5657                              "glTextureStorage3DMultisample");
5658 }
5659