Home | History | Annotate | Download | only in main
      1 /*
      2  * Mesa 3-D graphics library
      3  *
      4  * Copyright (C) 2011  VMware, Inc.  All Rights Reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included
     14  * in all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     22  * OTHER DEALINGS IN THE SOFTWARE.
     23  */
     24 
     25 /**
     26  * \file texstorage.c
     27  * GL_ARB_texture_storage functions
     28  */
     29 
     30 #include "glheader.h"
     31 #include "context.h"
     32 #include "enums.h"
     33 #include "imports.h"
     34 #include "macros.h"
     35 #include "teximage.h"
     36 #include "texobj.h"
     37 #include "mipmap.h"
     38 #include "texstorage.h"
     39 #include "textureview.h"
     40 #include "mtypes.h"
     41 #include "glformats.h"
     42 #include "hash.h"
     43 
     44 
     45 /**
     46  * Check if the given texture target is a legal texture object target
     47  * for a glTexStorage() command.
     48  * This is a bit different than legal_teximage_target() when it comes
     49  * to cube maps.
     50  */
     51 static bool
     52 legal_texobj_target(const struct gl_context *ctx, GLuint dims, GLenum target)
     53 {
     54    if (dims < 1 || dims > 3) {
     55       _mesa_problem(ctx, "invalid dims=%u in legal_texobj_target()", dims);
     56       return false;
     57    }
     58 
     59    switch (dims) {
     60    case 2:
     61       switch (target) {
     62       case GL_TEXTURE_2D:
     63          return true;
     64       case GL_TEXTURE_CUBE_MAP:
     65          return ctx->Extensions.ARB_texture_cube_map;
     66       }
     67       break;
     68    case 3:
     69       switch (target) {
     70       case GL_TEXTURE_3D:
     71          return true;
     72       case GL_TEXTURE_2D_ARRAY:
     73          return ctx->Extensions.EXT_texture_array;
     74       case GL_TEXTURE_CUBE_MAP_ARRAY:
     75          return _mesa_has_texture_cube_map_array(ctx);
     76       }
     77       break;
     78    }
     79 
     80    if (!_mesa_is_desktop_gl(ctx))
     81       return false;
     82 
     83    switch (dims) {
     84    case 1:
     85       switch (target) {
     86       case GL_TEXTURE_1D:
     87       case GL_PROXY_TEXTURE_1D:
     88          return true;
     89       default:
     90          return false;
     91       }
     92    case 2:
     93       switch (target) {
     94       case GL_PROXY_TEXTURE_2D:
     95          return true;
     96       case GL_PROXY_TEXTURE_CUBE_MAP:
     97          return ctx->Extensions.ARB_texture_cube_map;
     98       case GL_TEXTURE_RECTANGLE:
     99       case GL_PROXY_TEXTURE_RECTANGLE:
    100          return ctx->Extensions.NV_texture_rectangle;
    101       case GL_TEXTURE_1D_ARRAY:
    102       case GL_PROXY_TEXTURE_1D_ARRAY:
    103          return ctx->Extensions.EXT_texture_array;
    104       default:
    105          return false;
    106       }
    107    case 3:
    108       switch (target) {
    109       case GL_PROXY_TEXTURE_3D:
    110          return true;
    111       case GL_PROXY_TEXTURE_2D_ARRAY:
    112          return ctx->Extensions.EXT_texture_array;
    113       case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY:
    114          return ctx->Extensions.ARB_texture_cube_map_array;
    115       default:
    116          return false;
    117       }
    118    default:
    119       unreachable("impossible dimensions");
    120    }
    121 }
    122 
    123 
    124 /** Helper to get a particular texture image in a texture object */
    125 static struct gl_texture_image *
    126 get_tex_image(struct gl_context *ctx,
    127               struct gl_texture_object *texObj,
    128               GLuint face, GLuint level)
    129 {
    130    const GLenum faceTarget =
    131       (texObj->Target == GL_TEXTURE_CUBE_MAP ||
    132        texObj->Target == GL_PROXY_TEXTURE_CUBE_MAP)
    133       ? GL_TEXTURE_CUBE_MAP_POSITIVE_X + face : texObj->Target;
    134    return _mesa_get_tex_image(ctx, texObj, faceTarget, level);
    135 }
    136 
    137 
    138 
    139 static GLboolean
    140 initialize_texture_fields(struct gl_context *ctx,
    141                           struct gl_texture_object *texObj,
    142                           GLint levels,
    143                           GLsizei width, GLsizei height, GLsizei depth,
    144                           GLenum internalFormat, mesa_format texFormat)
    145 {
    146    const GLenum target = texObj->Target;
    147    const GLuint numFaces = _mesa_num_tex_faces(target);
    148    GLint level, levelWidth = width, levelHeight = height, levelDepth = depth;
    149    GLuint face;
    150 
    151    /* Set up all the texture object's gl_texture_images */
    152    for (level = 0; level < levels; level++) {
    153       for (face = 0; face < numFaces; face++) {
    154          struct gl_texture_image *texImage =
    155             get_tex_image(ctx, texObj, face, level);
    156 
    157 	 if (!texImage) {
    158 	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage");
    159             return GL_FALSE;
    160 	 }
    161 
    162          _mesa_init_teximage_fields(ctx, texImage,
    163                                     levelWidth, levelHeight, levelDepth,
    164                                     0, internalFormat, texFormat);
    165       }
    166 
    167       _mesa_next_mipmap_level_size(target, 0,
    168                                    levelWidth, levelHeight, levelDepth,
    169                                    &levelWidth, &levelHeight, &levelDepth);
    170    }
    171    return GL_TRUE;
    172 }
    173 
    174 
    175 /**
    176  * Clear all fields of texture object to zeros.  Used for proxy texture tests
    177  * and to clean up when a texture memory allocation fails.
    178  */
    179 static void
    180 clear_texture_fields(struct gl_context *ctx,
    181                      struct gl_texture_object *texObj)
    182 {
    183    const GLenum target = texObj->Target;
    184    const GLuint numFaces = _mesa_num_tex_faces(target);
    185    GLint level;
    186    GLuint face;
    187 
    188    for (level = 0; level < ARRAY_SIZE(texObj->Image[0]); level++) {
    189       for (face = 0; face < numFaces; face++) {
    190          struct gl_texture_image *texImage =
    191             get_tex_image(ctx, texObj, face, level);
    192 
    193 	 if (!texImage) {
    194 	    _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage");
    195             return;
    196 	 }
    197 
    198          _mesa_clear_texture_image(ctx, texImage);
    199       }
    200    }
    201 }
    202 
    203 
    204 /**
    205  * Update/re-validate framebuffer object.
    206  */
    207 static void
    208 update_fbo_texture(struct gl_context *ctx, struct gl_texture_object *texObj)
    209 {
    210    const unsigned numFaces = _mesa_num_tex_faces(texObj->Target);
    211    for (int level = 0; level < ARRAY_SIZE(texObj->Image[0]); level++) {
    212       for (unsigned face = 0; face < numFaces; face++)
    213          _mesa_update_fbo_texture(ctx, texObj, face, level);
    214    }
    215 }
    216 
    217 
    218 GLboolean
    219 _mesa_is_legal_tex_storage_format(const struct gl_context *ctx,
    220                                   GLenum internalformat)
    221 {
    222    /* check internal format - note that only sized formats are allowed */
    223    switch (internalformat) {
    224    case GL_ALPHA:
    225    case GL_LUMINANCE:
    226    case GL_LUMINANCE_ALPHA:
    227    case GL_INTENSITY:
    228    case GL_RED:
    229    case GL_RG:
    230    case GL_RGB:
    231    case GL_RGBA:
    232    case GL_BGRA:
    233    case GL_DEPTH_COMPONENT:
    234    case GL_DEPTH_STENCIL:
    235    case GL_COMPRESSED_ALPHA:
    236    case GL_COMPRESSED_LUMINANCE_ALPHA:
    237    case GL_COMPRESSED_LUMINANCE:
    238    case GL_COMPRESSED_INTENSITY:
    239    case GL_COMPRESSED_RGB:
    240    case GL_COMPRESSED_RGBA:
    241    case GL_COMPRESSED_SRGB:
    242    case GL_COMPRESSED_SRGB_ALPHA:
    243    case GL_COMPRESSED_SLUMINANCE:
    244    case GL_COMPRESSED_SLUMINANCE_ALPHA:
    245    case GL_RED_INTEGER:
    246    case GL_GREEN_INTEGER:
    247    case GL_BLUE_INTEGER:
    248    case GL_ALPHA_INTEGER:
    249    case GL_RGB_INTEGER:
    250    case GL_RGBA_INTEGER:
    251    case GL_BGR_INTEGER:
    252    case GL_BGRA_INTEGER:
    253    case GL_LUMINANCE_INTEGER_EXT:
    254    case GL_LUMINANCE_ALPHA_INTEGER_EXT:
    255       /* these unsized formats are illegal */
    256       return GL_FALSE;
    257    default:
    258       return _mesa_base_tex_format(ctx, internalformat) > 0;
    259    }
    260 }
    261 
    262 
    263 /**
    264  * Default ctx->Driver.AllocTextureStorage() handler.
    265  *
    266  * The driver can override this with a more specific implementation if it
    267  * desires, but this can be used to get the texture images allocated using the
    268  * usual texture image handling code.  The immutability of
    269  * GL_ARB_texture_storage texture layouts is handled by texObj->Immutable
    270  * checks at glTexImage* time.
    271  */
    272 GLboolean
    273 _mesa_AllocTextureStorage_sw(struct gl_context *ctx,
    274                              struct gl_texture_object *texObj,
    275                              GLsizei levels, GLsizei width,
    276                              GLsizei height, GLsizei depth)
    277 {
    278    const int numFaces = _mesa_num_tex_faces(texObj->Target);
    279    int face;
    280    int level;
    281 
    282    (void) width;
    283    (void) height;
    284    (void) depth;
    285 
    286    for (face = 0; face < numFaces; face++) {
    287       for (level = 0; level < levels; level++) {
    288          struct gl_texture_image *const texImage = texObj->Image[face][level];
    289          if (!ctx->Driver.AllocTextureImageBuffer(ctx, texImage))
    290             return GL_FALSE;
    291       }
    292    }
    293 
    294    return GL_TRUE;
    295 }
    296 
    297 
    298 /**
    299  * Do error checking for calls to glTexStorage1/2/3D().
    300  * If an error is found, record it with _mesa_error(), unless the target
    301  * is a proxy texture.
    302  * \return GL_TRUE if any error, GL_FALSE otherwise.
    303  */
    304 static GLboolean
    305 tex_storage_error_check(struct gl_context *ctx,
    306                         struct gl_texture_object *texObj,
    307                         GLuint dims, GLenum target,
    308                         GLsizei levels, GLenum internalformat,
    309                         GLsizei width, GLsizei height, GLsizei depth,
    310                         bool dsa)
    311 {
    312    const char* suffix = dsa ? "ture" : "";
    313 
    314    /* Legal format checking has been moved to texstorage and texturestorage in
    315     * order to allow meta functions to use legacy formats. */
    316 
    317    /* size check */
    318    if (!_mesa_valid_tex_storage_dim(width, height, depth)) {
    319       _mesa_error(ctx, GL_INVALID_VALUE,
    320                   "glTex%sStorage%uD(width, height or depth < 1)",
    321                   suffix, dims);
    322       return GL_TRUE;
    323    }
    324 
    325    if (_mesa_is_compressed_format(ctx, internalformat)) {
    326       GLenum err;
    327       if (!_mesa_target_can_be_compressed(ctx, target, internalformat, &err)) {
    328          _mesa_error(ctx, err,
    329                   "glTex%sStorage%dD(internalformat = %s)", suffix, dims,
    330                   _mesa_enum_to_string(internalformat));
    331          return GL_TRUE;
    332       }
    333    }
    334 
    335    /* levels check */
    336    if (levels < 1) {
    337       _mesa_error(ctx, GL_INVALID_VALUE, "glTex%sStorage%uD(levels < 1)",
    338                   suffix, dims);
    339       return GL_TRUE;
    340    }
    341 
    342    /* check levels against maximum (note different error than above) */
    343    if (levels > (GLint) _mesa_max_texture_levels(ctx, target)) {
    344       _mesa_error(ctx, GL_INVALID_OPERATION,
    345                   "glTex%sStorage%uD(levels too large)",
    346                   suffix, dims);
    347       return GL_TRUE;
    348    }
    349 
    350    /* check levels against width/height/depth */
    351    if (levels > _mesa_get_tex_max_num_levels(target, width, height, depth)) {
    352       _mesa_error(ctx, GL_INVALID_OPERATION,
    353                   "glTex%sStorage%uD(too many levels"
    354                   " for max texture dimension)",
    355                   suffix, dims);
    356       return GL_TRUE;
    357    }
    358 
    359    /* non-default texture object check */
    360    if (!_mesa_is_proxy_texture(target) && (!texObj || (texObj->Name == 0))) {
    361       _mesa_error(ctx, GL_INVALID_OPERATION,
    362                   "glTex%sStorage%uD(texture object 0)",
    363                   suffix, dims);
    364       return GL_TRUE;
    365    }
    366 
    367    /* Check if texObj->Immutable is set */
    368    if (!_mesa_is_proxy_texture(target) && texObj->Immutable) {
    369       _mesa_error(ctx, GL_INVALID_OPERATION, "glTex%sStorage%uD(immutable)",
    370                   suffix, dims);
    371       return GL_TRUE;
    372    }
    373 
    374    /* additional checks for depth textures */
    375    if (!_mesa_legal_texture_base_format_for_target(ctx, target, internalformat)) {
    376       _mesa_error(ctx, GL_INVALID_OPERATION, "glTex%sStorage%uD(bad target for texture)",
    377                   suffix, dims);
    378       return GL_TRUE;
    379    }
    380 
    381    return GL_FALSE;
    382 }
    383 
    384 
    385 /**
    386  * Helper that does the storage allocation for _mesa_TexStorage1/2/3D()
    387  * and _mesa_TextureStorage1/2/3D().
    388  */
    389 void
    390 _mesa_texture_storage(struct gl_context *ctx, GLuint dims,
    391                       struct gl_texture_object *texObj,
    392                       GLenum target, GLsizei levels,
    393                       GLenum internalformat, GLsizei width,
    394                       GLsizei height, GLsizei depth, bool dsa)
    395 {
    396    GLboolean sizeOK, dimensionsOK;
    397    mesa_format texFormat;
    398    const char* suffix = dsa ? "ture" : "";
    399 
    400    assert(texObj);
    401 
    402    if (tex_storage_error_check(ctx, texObj, dims, target, levels,
    403                                internalformat, width, height, depth, dsa)) {
    404       return; /* error was recorded */
    405    }
    406 
    407    texFormat = _mesa_choose_texture_format(ctx, texObj, target, 0,
    408                                            internalformat, GL_NONE, GL_NONE);
    409    assert(texFormat != MESA_FORMAT_NONE);
    410 
    411    /* check that width, height, depth are legal for the mipmap level */
    412    dimensionsOK = _mesa_legal_texture_dimensions(ctx, target, 0,
    413                                                   width, height, depth, 0);
    414 
    415    sizeOK = ctx->Driver.TestProxyTexImage(ctx, target, levels, 0, texFormat,
    416                                           1, width, height, depth);
    417 
    418    if (_mesa_is_proxy_texture(target)) {
    419       if (dimensionsOK && sizeOK) {
    420          initialize_texture_fields(ctx, texObj, levels, width, height, depth,
    421                                    internalformat, texFormat);
    422       }
    423       else {
    424          /* clear all image fields for [levels] */
    425          clear_texture_fields(ctx, texObj);
    426       }
    427    }
    428    else {
    429       if (!dimensionsOK) {
    430          _mesa_error(ctx, GL_INVALID_VALUE,
    431                      "glTex%sStorage%uD(invalid width, height or depth)",
    432                      suffix, dims);
    433          return;
    434       }
    435 
    436       if (!sizeOK) {
    437          _mesa_error(ctx, GL_OUT_OF_MEMORY,
    438                      "glTex%sStorage%uD(texture too large)",
    439                      suffix, dims);
    440       }
    441 
    442       assert(levels > 0);
    443       assert(width > 0);
    444       assert(height > 0);
    445       assert(depth > 0);
    446 
    447       if (!initialize_texture_fields(ctx, texObj, levels, width, height, depth,
    448                                      internalformat, texFormat)) {
    449          return;
    450       }
    451 
    452       /* Do actual texture memory allocation */
    453       if (!ctx->Driver.AllocTextureStorage(ctx, texObj, levels,
    454                                            width, height, depth)) {
    455          /* Reset the texture images' info to zeros.
    456           * Strictly speaking, we probably don't have to do this since
    457           * generating GL_OUT_OF_MEMORY can leave things in an undefined
    458           * state but this puts things in a consistent state.
    459           */
    460          clear_texture_fields(ctx, texObj);
    461          _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTex%sStorage%uD",
    462                      suffix, dims);
    463          return;
    464       }
    465 
    466       _mesa_set_texture_view_state(ctx, texObj, target, levels);
    467 
    468       update_fbo_texture(ctx, texObj);
    469    }
    470 }
    471 
    472 
    473 /**
    474  * Helper used by _mesa_TexStorage1/2/3D().
    475  */
    476 static void
    477 texstorage(GLuint dims, GLenum target, GLsizei levels, GLenum internalformat,
    478            GLsizei width, GLsizei height, GLsizei depth)
    479 {
    480    struct gl_texture_object *texObj;
    481    GET_CURRENT_CONTEXT(ctx);
    482 
    483    /* Check target.  This is done here so that _mesa_texture_storage
    484     * can receive unsized formats.
    485     */
    486    if (!legal_texobj_target(ctx, dims, target)) {
    487       _mesa_error(ctx, GL_INVALID_ENUM,
    488                   "glTexStorage%uD(illegal target=%s)",
    489                   dims, _mesa_enum_to_string(target));
    490       return;
    491    }
    492 
    493    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
    494       _mesa_debug(ctx, "glTexStorage%uD %s %d %s %d %d %d\n",
    495                   dims,
    496                   _mesa_enum_to_string(target), levels,
    497                   _mesa_enum_to_string(internalformat),
    498                   width, height, depth);
    499 
    500    /* Check the format to make sure it is sized. */
    501    if (!_mesa_is_legal_tex_storage_format(ctx, internalformat)) {
    502       _mesa_error(ctx, GL_INVALID_ENUM,
    503                   "glTexStorage%uD(internalformat = %s)", dims,
    504                   _mesa_enum_to_string(internalformat));
    505       return;
    506    }
    507 
    508    texObj = _mesa_get_current_tex_object(ctx, target);
    509    if (!texObj)
    510       return;
    511 
    512    _mesa_texture_storage(ctx, dims, texObj, target, levels,
    513                          internalformat, width, height, depth, false);
    514 }
    515 
    516 
    517 /**
    518  * Helper used by _mesa_TextureStorage1/2/3D().
    519  */
    520 static void
    521 texturestorage(GLuint dims, GLuint texture, GLsizei levels,
    522                GLenum internalformat, GLsizei width, GLsizei height,
    523                GLsizei depth)
    524 {
    525    struct gl_texture_object *texObj;
    526    GET_CURRENT_CONTEXT(ctx);
    527 
    528    if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE))
    529       _mesa_debug(ctx, "glTextureStorage%uD %d %d %s %d %d %d\n",
    530                   dims, texture, levels,
    531                   _mesa_enum_to_string(internalformat),
    532                   width, height, depth);
    533 
    534    /* Check the format to make sure it is sized. */
    535    if (!_mesa_is_legal_tex_storage_format(ctx, internalformat)) {
    536       _mesa_error(ctx, GL_INVALID_ENUM,
    537                   "glTextureStorage%uD(internalformat = %s)", dims,
    538                   _mesa_enum_to_string(internalformat));
    539       return;
    540    }
    541 
    542    /* Get the texture object by Name. */
    543    texObj = _mesa_lookup_texture(ctx, texture);
    544    if (!texObj) {
    545       _mesa_error(ctx, GL_INVALID_OPERATION,
    546                   "glTextureStorage%uD(texture = %d)", dims, texture);
    547       return;
    548    }
    549 
    550    /* Check target.  This is done here so that _mesa_texture_storage
    551     * can receive unsized formats.
    552     */
    553    if (!legal_texobj_target(ctx, dims, texObj->Target)) {
    554       _mesa_error(ctx, GL_INVALID_ENUM,
    555                   "glTextureStorage%uD(illegal target=%s)",
    556                   dims, _mesa_enum_to_string(texObj->Target));
    557       return;
    558    }
    559 
    560    _mesa_texture_storage(ctx, dims, texObj, texObj->Target,
    561                          levels, internalformat, width, height, depth, true);
    562 }
    563 
    564 
    565 void GLAPIENTRY
    566 _mesa_TexStorage1D(GLenum target, GLsizei levels, GLenum internalformat,
    567                    GLsizei width)
    568 {
    569    texstorage(1, target, levels, internalformat, width, 1, 1);
    570 }
    571 
    572 
    573 void GLAPIENTRY
    574 _mesa_TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat,
    575                    GLsizei width, GLsizei height)
    576 {
    577    texstorage(2, target, levels, internalformat, width, height, 1);
    578 }
    579 
    580 
    581 void GLAPIENTRY
    582 _mesa_TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat,
    583                    GLsizei width, GLsizei height, GLsizei depth)
    584 {
    585    texstorage(3, target, levels, internalformat, width, height, depth);
    586 }
    587 
    588 
    589 void GLAPIENTRY
    590 _mesa_TextureStorage1D(GLuint texture, GLsizei levels, GLenum internalformat,
    591                        GLsizei width)
    592 {
    593    texturestorage(1, texture, levels, internalformat, width, 1, 1);
    594 }
    595 
    596 
    597 void GLAPIENTRY
    598 _mesa_TextureStorage2D(GLuint texture, GLsizei levels,
    599                        GLenum internalformat,
    600                        GLsizei width, GLsizei height)
    601 {
    602    texturestorage(2, texture, levels, internalformat, width, height, 1);
    603 }
    604 
    605 
    606 void GLAPIENTRY
    607 _mesa_TextureStorage3D(GLuint texture, GLsizei levels, GLenum internalformat,
    608                        GLsizei width, GLsizei height, GLsizei depth)
    609 {
    610    texturestorage(3, texture, levels, internalformat, width, height, depth);
    611 }
    612 
    613 
    614 /*
    615  * Note: we don't support GL_EXT_direct_state_access and the spec says
    616  * we don't need the following functions.  However, glew checks for the
    617  * presence of all six functions and will say that GL_ARB_texture_storage
    618  * is not supported if these functions are missing.
    619  */
    620 
    621 
    622 void GLAPIENTRY
    623 _mesa_TextureStorage1DEXT(GLuint texture, GLenum target, GLsizei levels,
    624                           GLenum internalformat,
    625                           GLsizei width)
    626 {
    627    GET_CURRENT_CONTEXT(ctx);
    628 
    629    (void) texture;
    630    (void) target;
    631    (void) levels;
    632    (void) internalformat;
    633    (void) width;
    634 
    635    _mesa_error(ctx, GL_INVALID_OPERATION,
    636                "glTextureStorage1DEXT not supported");
    637 }
    638 
    639 
    640 void GLAPIENTRY
    641 _mesa_TextureStorage2DEXT(GLuint texture, GLenum target, GLsizei levels,
    642                           GLenum internalformat,
    643                           GLsizei width, GLsizei height)
    644 {
    645    GET_CURRENT_CONTEXT(ctx);
    646 
    647    (void) texture;
    648    (void) target;
    649    (void) levels;
    650    (void) internalformat;
    651    (void) width;
    652    (void) height;
    653 
    654    _mesa_error(ctx, GL_INVALID_OPERATION,
    655                "glTextureStorage2DEXT not supported");
    656 }
    657 
    658 
    659 void GLAPIENTRY
    660 _mesa_TextureStorage3DEXT(GLuint texture, GLenum target, GLsizei levels,
    661                           GLenum internalformat,
    662                           GLsizei width, GLsizei height, GLsizei depth)
    663 {
    664    GET_CURRENT_CONTEXT(ctx);
    665 
    666    (void) texture;
    667    (void) target;
    668    (void) levels;
    669    (void) internalformat;
    670    (void) width;
    671    (void) height;
    672    (void) depth;
    673 
    674    _mesa_error(ctx, GL_INVALID_OPERATION,
    675                "glTextureStorage3DEXT not supported");
    676 }
    677