1af69d88dSmrg/* 2af69d88dSmrg * Mesa 3-D graphics library 3af69d88dSmrg * 4af69d88dSmrg * Copyright (C) 2011 VMware, Inc. All Rights Reserved. 5af69d88dSmrg * 6af69d88dSmrg * Permission is hereby granted, free of charge, to any person obtaining a 7af69d88dSmrg * copy of this software and associated documentation files (the "Software"), 8af69d88dSmrg * to deal in the Software without restriction, including without limitation 9af69d88dSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10af69d88dSmrg * and/or sell copies of the Software, and to permit persons to whom the 11af69d88dSmrg * Software is furnished to do so, subject to the following conditions: 12af69d88dSmrg * 13af69d88dSmrg * The above copyright notice and this permission notice shall be included 14af69d88dSmrg * in all copies or substantial portions of the Software. 15af69d88dSmrg * 16af69d88dSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17af69d88dSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18af69d88dSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE. 23af69d88dSmrg */ 24af69d88dSmrg 25af69d88dSmrg/** 26af69d88dSmrg * \file texstorage.c 27af69d88dSmrg * GL_ARB_texture_storage functions 28af69d88dSmrg */ 29af69d88dSmrg 30af69d88dSmrg#include "glheader.h" 31af69d88dSmrg#include "context.h" 32af69d88dSmrg#include "enums.h" 337ec681f3Smrg 34af69d88dSmrg#include "macros.h" 35af69d88dSmrg#include "teximage.h" 36af69d88dSmrg#include "texobj.h" 37af69d88dSmrg#include "mipmap.h" 38af69d88dSmrg#include "texstorage.h" 39af69d88dSmrg#include "textureview.h" 40af69d88dSmrg#include "mtypes.h" 41af69d88dSmrg#include "glformats.h" 4201e04c3fSmrg#include "hash.h" 43af69d88dSmrg 44af69d88dSmrg 45af69d88dSmrg/** 46af69d88dSmrg * Check if the given texture target is a legal texture object target 47af69d88dSmrg * for a glTexStorage() command. 48af69d88dSmrg * This is a bit different than legal_teximage_target() when it comes 49af69d88dSmrg * to cube maps. 50af69d88dSmrg */ 5101e04c3fSmrgstatic bool 5201e04c3fSmrglegal_texobj_target(const struct gl_context *ctx, GLuint dims, GLenum target) 53af69d88dSmrg{ 5401e04c3fSmrg if (dims < 1 || dims > 3) { 5501e04c3fSmrg _mesa_problem(ctx, "invalid dims=%u in legal_texobj_target()", dims); 5601e04c3fSmrg return false; 5701e04c3fSmrg } 5801e04c3fSmrg 5901e04c3fSmrg switch (dims) { 6001e04c3fSmrg case 2: 6101e04c3fSmrg switch (target) { 6201e04c3fSmrg case GL_TEXTURE_2D: 6301e04c3fSmrg return true; 6401e04c3fSmrg case GL_TEXTURE_CUBE_MAP: 6501e04c3fSmrg return ctx->Extensions.ARB_texture_cube_map; 6601e04c3fSmrg } 6701e04c3fSmrg break; 6801e04c3fSmrg case 3: 6901e04c3fSmrg switch (target) { 7001e04c3fSmrg case GL_TEXTURE_3D: 7101e04c3fSmrg return true; 7201e04c3fSmrg case GL_TEXTURE_2D_ARRAY: 7301e04c3fSmrg return ctx->Extensions.EXT_texture_array; 7401e04c3fSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: 7501e04c3fSmrg return _mesa_has_texture_cube_map_array(ctx); 7601e04c3fSmrg } 7701e04c3fSmrg break; 7801e04c3fSmrg } 7901e04c3fSmrg 8001e04c3fSmrg if (!_mesa_is_desktop_gl(ctx)) 8101e04c3fSmrg return false; 82af69d88dSmrg 83af69d88dSmrg switch (dims) { 84af69d88dSmrg case 1: 85af69d88dSmrg switch (target) { 86af69d88dSmrg case GL_TEXTURE_1D: 87af69d88dSmrg case GL_PROXY_TEXTURE_1D: 8801e04c3fSmrg return true; 89af69d88dSmrg default: 9001e04c3fSmrg return false; 91af69d88dSmrg } 92af69d88dSmrg case 2: 93af69d88dSmrg switch (target) { 94af69d88dSmrg case GL_PROXY_TEXTURE_2D: 9501e04c3fSmrg return true; 96af69d88dSmrg case GL_PROXY_TEXTURE_CUBE_MAP: 97af69d88dSmrg return ctx->Extensions.ARB_texture_cube_map; 98af69d88dSmrg case GL_TEXTURE_RECTANGLE: 99af69d88dSmrg case GL_PROXY_TEXTURE_RECTANGLE: 100af69d88dSmrg return ctx->Extensions.NV_texture_rectangle; 101af69d88dSmrg case GL_TEXTURE_1D_ARRAY: 102af69d88dSmrg case GL_PROXY_TEXTURE_1D_ARRAY: 103af69d88dSmrg return ctx->Extensions.EXT_texture_array; 104af69d88dSmrg default: 10501e04c3fSmrg return false; 106af69d88dSmrg } 107af69d88dSmrg case 3: 108af69d88dSmrg switch (target) { 109af69d88dSmrg case GL_PROXY_TEXTURE_3D: 11001e04c3fSmrg return true; 111af69d88dSmrg case GL_PROXY_TEXTURE_2D_ARRAY: 112af69d88dSmrg return ctx->Extensions.EXT_texture_array; 113af69d88dSmrg case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY: 114af69d88dSmrg return ctx->Extensions.ARB_texture_cube_map_array; 115af69d88dSmrg default: 11601e04c3fSmrg return false; 117af69d88dSmrg } 118af69d88dSmrg default: 11901e04c3fSmrg unreachable("impossible dimensions"); 120af69d88dSmrg } 121af69d88dSmrg} 122af69d88dSmrg 123af69d88dSmrg 124af69d88dSmrg/** Helper to get a particular texture image in a texture object */ 125af69d88dSmrgstatic struct gl_texture_image * 12601e04c3fSmrgget_tex_image(struct gl_context *ctx, 127af69d88dSmrg struct gl_texture_object *texObj, 128af69d88dSmrg GLuint face, GLuint level) 129af69d88dSmrg{ 130af69d88dSmrg const GLenum faceTarget = 131af69d88dSmrg (texObj->Target == GL_TEXTURE_CUBE_MAP || 132af69d88dSmrg texObj->Target == GL_PROXY_TEXTURE_CUBE_MAP) 133af69d88dSmrg ? GL_TEXTURE_CUBE_MAP_POSITIVE_X + face : texObj->Target; 134af69d88dSmrg return _mesa_get_tex_image(ctx, texObj, faceTarget, level); 135af69d88dSmrg} 136af69d88dSmrg 137af69d88dSmrg 138af69d88dSmrg 139af69d88dSmrgstatic GLboolean 140af69d88dSmrginitialize_texture_fields(struct gl_context *ctx, 141af69d88dSmrg struct gl_texture_object *texObj, 142af69d88dSmrg GLint levels, 143af69d88dSmrg GLsizei width, GLsizei height, GLsizei depth, 144af69d88dSmrg GLenum internalFormat, mesa_format texFormat) 145af69d88dSmrg{ 146af69d88dSmrg const GLenum target = texObj->Target; 147af69d88dSmrg const GLuint numFaces = _mesa_num_tex_faces(target); 148af69d88dSmrg GLint level, levelWidth = width, levelHeight = height, levelDepth = depth; 149af69d88dSmrg GLuint face; 150af69d88dSmrg 151af69d88dSmrg /* Set up all the texture object's gl_texture_images */ 152af69d88dSmrg for (level = 0; level < levels; level++) { 153af69d88dSmrg for (face = 0; face < numFaces; face++) { 154af69d88dSmrg struct gl_texture_image *texImage = 155af69d88dSmrg get_tex_image(ctx, texObj, face, level); 156af69d88dSmrg 157af69d88dSmrg if (!texImage) { 158af69d88dSmrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage"); 159af69d88dSmrg return GL_FALSE; 160af69d88dSmrg } 161af69d88dSmrg 162af69d88dSmrg _mesa_init_teximage_fields(ctx, texImage, 163af69d88dSmrg levelWidth, levelHeight, levelDepth, 164af69d88dSmrg 0, internalFormat, texFormat); 165af69d88dSmrg } 166af69d88dSmrg 16701e04c3fSmrg _mesa_next_mipmap_level_size(target, 0, 16801e04c3fSmrg levelWidth, levelHeight, levelDepth, 169af69d88dSmrg &levelWidth, &levelHeight, &levelDepth); 170af69d88dSmrg } 171af69d88dSmrg return GL_TRUE; 172af69d88dSmrg} 173af69d88dSmrg 174af69d88dSmrg 175af69d88dSmrg/** 176af69d88dSmrg * Clear all fields of texture object to zeros. Used for proxy texture tests 177af69d88dSmrg * and to clean up when a texture memory allocation fails. 178af69d88dSmrg */ 179af69d88dSmrgstatic void 180af69d88dSmrgclear_texture_fields(struct gl_context *ctx, 181af69d88dSmrg struct gl_texture_object *texObj) 182af69d88dSmrg{ 183af69d88dSmrg const GLenum target = texObj->Target; 184af69d88dSmrg const GLuint numFaces = _mesa_num_tex_faces(target); 185af69d88dSmrg GLint level; 186af69d88dSmrg GLuint face; 187af69d88dSmrg 18801e04c3fSmrg for (level = 0; level < ARRAY_SIZE(texObj->Image[0]); level++) { 189af69d88dSmrg for (face = 0; face < numFaces; face++) { 190af69d88dSmrg struct gl_texture_image *texImage = 191af69d88dSmrg get_tex_image(ctx, texObj, face, level); 192af69d88dSmrg 193af69d88dSmrg if (!texImage) { 194af69d88dSmrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexStorage"); 195af69d88dSmrg return; 196af69d88dSmrg } 197af69d88dSmrg 19801e04c3fSmrg _mesa_clear_texture_image(ctx, texImage); 199af69d88dSmrg } 200af69d88dSmrg } 201af69d88dSmrg} 202af69d88dSmrg 203af69d88dSmrg 20401e04c3fSmrg/** 20501e04c3fSmrg * Update/re-validate framebuffer object. 20601e04c3fSmrg */ 20701e04c3fSmrgstatic void 20801e04c3fSmrgupdate_fbo_texture(struct gl_context *ctx, struct gl_texture_object *texObj) 20901e04c3fSmrg{ 21001e04c3fSmrg const unsigned numFaces = _mesa_num_tex_faces(texObj->Target); 21101e04c3fSmrg for (int level = 0; level < ARRAY_SIZE(texObj->Image[0]); level++) { 21201e04c3fSmrg for (unsigned face = 0; face < numFaces; face++) 21301e04c3fSmrg _mesa_update_fbo_texture(ctx, texObj, face, level); 21401e04c3fSmrg } 21501e04c3fSmrg} 21601e04c3fSmrg 21701e04c3fSmrg 218af69d88dSmrgGLboolean 21901e04c3fSmrg_mesa_is_legal_tex_storage_format(const struct gl_context *ctx, 22001e04c3fSmrg GLenum internalformat) 221af69d88dSmrg{ 222af69d88dSmrg /* check internal format - note that only sized formats are allowed */ 223af69d88dSmrg switch (internalformat) { 224af69d88dSmrg case GL_ALPHA: 225af69d88dSmrg case GL_LUMINANCE: 226af69d88dSmrg case GL_LUMINANCE_ALPHA: 227af69d88dSmrg case GL_INTENSITY: 228af69d88dSmrg case GL_RED: 229af69d88dSmrg case GL_RG: 230af69d88dSmrg case GL_RGB: 231af69d88dSmrg case GL_RGBA: 232af69d88dSmrg case GL_BGRA: 233af69d88dSmrg case GL_DEPTH_COMPONENT: 234af69d88dSmrg case GL_DEPTH_STENCIL: 235af69d88dSmrg case GL_COMPRESSED_ALPHA: 236af69d88dSmrg case GL_COMPRESSED_LUMINANCE_ALPHA: 237af69d88dSmrg case GL_COMPRESSED_LUMINANCE: 238af69d88dSmrg case GL_COMPRESSED_INTENSITY: 239af69d88dSmrg case GL_COMPRESSED_RGB: 240af69d88dSmrg case GL_COMPRESSED_RGBA: 241af69d88dSmrg case GL_COMPRESSED_SRGB: 242af69d88dSmrg case GL_COMPRESSED_SRGB_ALPHA: 243af69d88dSmrg case GL_COMPRESSED_SLUMINANCE: 244af69d88dSmrg case GL_COMPRESSED_SLUMINANCE_ALPHA: 245af69d88dSmrg case GL_RED_INTEGER: 246af69d88dSmrg case GL_GREEN_INTEGER: 247af69d88dSmrg case GL_BLUE_INTEGER: 248af69d88dSmrg case GL_ALPHA_INTEGER: 249af69d88dSmrg case GL_RGB_INTEGER: 250af69d88dSmrg case GL_RGBA_INTEGER: 251af69d88dSmrg case GL_BGR_INTEGER: 252af69d88dSmrg case GL_BGRA_INTEGER: 253af69d88dSmrg case GL_LUMINANCE_INTEGER_EXT: 254af69d88dSmrg case GL_LUMINANCE_ALPHA_INTEGER_EXT: 255af69d88dSmrg /* these unsized formats are illegal */ 256af69d88dSmrg return GL_FALSE; 257af69d88dSmrg default: 258af69d88dSmrg return _mesa_base_tex_format(ctx, internalformat) > 0; 259af69d88dSmrg } 260af69d88dSmrg} 261af69d88dSmrg 26201e04c3fSmrg 263af69d88dSmrg/** 264af69d88dSmrg * Default ctx->Driver.AllocTextureStorage() handler. 265af69d88dSmrg * 266af69d88dSmrg * The driver can override this with a more specific implementation if it 267af69d88dSmrg * desires, but this can be used to get the texture images allocated using the 268af69d88dSmrg * usual texture image handling code. The immutability of 269af69d88dSmrg * GL_ARB_texture_storage texture layouts is handled by texObj->Immutable 270af69d88dSmrg * checks at glTexImage* time. 271af69d88dSmrg */ 272af69d88dSmrgGLboolean 27301e04c3fSmrg_mesa_AllocTextureStorage_sw(struct gl_context *ctx, 27401e04c3fSmrg struct gl_texture_object *texObj, 27501e04c3fSmrg GLsizei levels, GLsizei width, 27601e04c3fSmrg GLsizei height, GLsizei depth) 277af69d88dSmrg{ 278af69d88dSmrg const int numFaces = _mesa_num_tex_faces(texObj->Target); 279af69d88dSmrg int face; 280af69d88dSmrg int level; 281af69d88dSmrg 282af69d88dSmrg (void) width; 283af69d88dSmrg (void) height; 284af69d88dSmrg (void) depth; 285af69d88dSmrg 286af69d88dSmrg for (face = 0; face < numFaces; face++) { 287af69d88dSmrg for (level = 0; level < levels; level++) { 288af69d88dSmrg struct gl_texture_image *const texImage = texObj->Image[face][level]; 289af69d88dSmrg if (!ctx->Driver.AllocTextureImageBuffer(ctx, texImage)) 290af69d88dSmrg return GL_FALSE; 291af69d88dSmrg } 292af69d88dSmrg } 293af69d88dSmrg 294af69d88dSmrg return GL_TRUE; 295af69d88dSmrg} 296af69d88dSmrg 297af69d88dSmrg 298af69d88dSmrg/** 299af69d88dSmrg * Do error checking for calls to glTexStorage1/2/3D(). 300af69d88dSmrg * If an error is found, record it with _mesa_error(), unless the target 301af69d88dSmrg * is a proxy texture. 302af69d88dSmrg * \return GL_TRUE if any error, GL_FALSE otherwise. 303af69d88dSmrg */ 304af69d88dSmrgstatic GLboolean 30501e04c3fSmrgtex_storage_error_check(struct gl_context *ctx, 30601e04c3fSmrg struct gl_texture_object *texObj, 30701e04c3fSmrg struct gl_memory_object *memObj, 30801e04c3fSmrg GLuint dims, GLenum target, 309af69d88dSmrg GLsizei levels, GLenum internalformat, 31001e04c3fSmrg GLsizei width, GLsizei height, GLsizei depth, 31101e04c3fSmrg bool dsa) 312af69d88dSmrg{ 31301e04c3fSmrg const char* suffix = dsa ? (memObj ? "tureMem" : "ture") : 31401e04c3fSmrg (memObj ? "Mem" : ""); 315af69d88dSmrg 31601e04c3fSmrg /* Legal format checking has been moved to texstorage and texturestorage in 31701e04c3fSmrg * order to allow meta functions to use legacy formats. */ 318af69d88dSmrg 319af69d88dSmrg /* size check */ 32001e04c3fSmrg if (!_mesa_valid_tex_storage_dim(width, height, depth)) { 321af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 32201e04c3fSmrg "glTex%sStorage%uD(width, height or depth < 1)", 32301e04c3fSmrg suffix, dims); 324af69d88dSmrg return GL_TRUE; 325af69d88dSmrg } 326af69d88dSmrg 32701e04c3fSmrg if (_mesa_is_compressed_format(ctx, internalformat)) { 32801e04c3fSmrg GLenum err; 32901e04c3fSmrg if (!_mesa_target_can_be_compressed(ctx, target, internalformat, &err)) { 33001e04c3fSmrg _mesa_error(ctx, err, 33101e04c3fSmrg "glTex%sStorage%dD(internalformat = %s)", suffix, dims, 33201e04c3fSmrg _mesa_enum_to_string(internalformat)); 33301e04c3fSmrg return GL_TRUE; 33401e04c3fSmrg } 335af69d88dSmrg } 336af69d88dSmrg 337af69d88dSmrg /* levels check */ 338af69d88dSmrg if (levels < 1) { 33901e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "glTex%sStorage%uD(levels < 1)", 34001e04c3fSmrg suffix, dims); 341af69d88dSmrg return GL_TRUE; 34201e04c3fSmrg } 343af69d88dSmrg 344af69d88dSmrg /* check levels against maximum (note different error than above) */ 345af69d88dSmrg if (levels > (GLint) _mesa_max_texture_levels(ctx, target)) { 346af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 34701e04c3fSmrg "glTex%sStorage%uD(levels too large)", 34801e04c3fSmrg suffix, dims); 349af69d88dSmrg return GL_TRUE; 350af69d88dSmrg } 351af69d88dSmrg 352af69d88dSmrg /* check levels against width/height/depth */ 353af69d88dSmrg if (levels > _mesa_get_tex_max_num_levels(target, width, height, depth)) { 354af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 35501e04c3fSmrg "glTex%sStorage%uD(too many levels" 35601e04c3fSmrg " for max texture dimension)", 35701e04c3fSmrg suffix, dims); 358af69d88dSmrg return GL_TRUE; 359af69d88dSmrg } 360af69d88dSmrg 361af69d88dSmrg /* non-default texture object check */ 362af69d88dSmrg if (!_mesa_is_proxy_texture(target) && (!texObj || (texObj->Name == 0))) { 363af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 36401e04c3fSmrg "glTex%sStorage%uD(texture object 0)", 36501e04c3fSmrg suffix, dims); 366af69d88dSmrg return GL_TRUE; 367af69d88dSmrg } 368af69d88dSmrg 369af69d88dSmrg /* Check if texObj->Immutable is set */ 370af69d88dSmrg if (!_mesa_is_proxy_texture(target) && texObj->Immutable) { 37101e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "glTex%sStorage%uD(immutable)", 37201e04c3fSmrg suffix, dims); 373af69d88dSmrg return GL_TRUE; 374af69d88dSmrg } 375af69d88dSmrg 376af69d88dSmrg /* additional checks for depth textures */ 37701e04c3fSmrg if (!_mesa_legal_texture_base_format_for_target(ctx, target, internalformat)) { 37801e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "glTex%sStorage%uD(bad target for texture)", 37901e04c3fSmrg suffix, dims); 380af69d88dSmrg return GL_TRUE; 38101e04c3fSmrg } 382af69d88dSmrg 383af69d88dSmrg return GL_FALSE; 384af69d88dSmrg} 385af69d88dSmrg 386af69d88dSmrg 387af69d88dSmrg/** 38801e04c3fSmrg * Helper that does the storage allocation for _mesa_TexStorage1/2/3D() 38901e04c3fSmrg * and _mesa_TextureStorage1/2/3D(). 390af69d88dSmrg */ 39101e04c3fSmrgstatic ALWAYS_INLINE void 39201e04c3fSmrgtexture_storage(struct gl_context *ctx, GLuint dims, 39301e04c3fSmrg struct gl_texture_object *texObj, 39401e04c3fSmrg struct gl_memory_object *memObj, GLenum target, 39501e04c3fSmrg GLsizei levels, GLenum internalformat, GLsizei width, 39601e04c3fSmrg GLsizei height, GLsizei depth, GLuint64 offset, bool dsa, 39701e04c3fSmrg bool no_error) 398af69d88dSmrg{ 39901e04c3fSmrg GLboolean sizeOK = GL_TRUE, dimensionsOK = GL_TRUE; 400af69d88dSmrg mesa_format texFormat; 40101e04c3fSmrg const char* suffix = dsa ? (memObj ? "tureMem" : "ture") : 40201e04c3fSmrg (memObj ? "Mem" : ""); 403af69d88dSmrg 40401e04c3fSmrg assert(texObj); 405af69d88dSmrg 40601e04c3fSmrg if (!no_error) { 40701e04c3fSmrg if (tex_storage_error_check(ctx, texObj, memObj, dims, target, levels, 40801e04c3fSmrg internalformat, width, height, depth, dsa)) { 40901e04c3fSmrg return; /* error was recorded */ 41001e04c3fSmrg } 411af69d88dSmrg } 412af69d88dSmrg 413af69d88dSmrg texFormat = _mesa_choose_texture_format(ctx, texObj, target, 0, 414af69d88dSmrg internalformat, GL_NONE, GL_NONE); 415af69d88dSmrg 41601e04c3fSmrg if (!no_error) { 41701e04c3fSmrg /* check that width, height, depth are legal for the mipmap level */ 41801e04c3fSmrg dimensionsOK = _mesa_legal_texture_dimensions(ctx, target, 0, 41901e04c3fSmrg width, height, depth, 0); 420af69d88dSmrg 42101e04c3fSmrg sizeOK = ctx->Driver.TestProxyTexImage(ctx, target, levels, 0, texFormat, 42201e04c3fSmrg 1, width, height, depth); 42301e04c3fSmrg } 424af69d88dSmrg 42501e04c3fSmrg if (_mesa_is_proxy_texture(target)) { 426af69d88dSmrg if (dimensionsOK && sizeOK) { 427af69d88dSmrg initialize_texture_fields(ctx, texObj, levels, width, height, depth, 428af69d88dSmrg internalformat, texFormat); 429af69d88dSmrg } 430af69d88dSmrg else { 431af69d88dSmrg /* clear all image fields for [levels] */ 432af69d88dSmrg clear_texture_fields(ctx, texObj); 433af69d88dSmrg } 434af69d88dSmrg } 435af69d88dSmrg else { 43601e04c3fSmrg if (!no_error) { 43701e04c3fSmrg if (!dimensionsOK) { 43801e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, 43901e04c3fSmrg "glTex%sStorage%uD(invalid width, height or depth)", 44001e04c3fSmrg suffix, dims); 44101e04c3fSmrg return; 44201e04c3fSmrg } 443af69d88dSmrg 44401e04c3fSmrg if (!sizeOK) { 44501e04c3fSmrg _mesa_error(ctx, GL_OUT_OF_MEMORY, 44601e04c3fSmrg "glTex%sStorage%uD(texture too large)", 44701e04c3fSmrg suffix, dims); 44801e04c3fSmrg return; 44901e04c3fSmrg } 450af69d88dSmrg } 451af69d88dSmrg 452af69d88dSmrg assert(levels > 0); 453af69d88dSmrg assert(width > 0); 454af69d88dSmrg assert(height > 0); 455af69d88dSmrg assert(depth > 0); 456af69d88dSmrg 457af69d88dSmrg if (!initialize_texture_fields(ctx, texObj, levels, width, height, depth, 458af69d88dSmrg internalformat, texFormat)) { 459af69d88dSmrg return; 460af69d88dSmrg } 461af69d88dSmrg 46201e04c3fSmrg /* Setup the backing memory */ 46301e04c3fSmrg if (memObj) { 46401e04c3fSmrg if (!ctx->Driver.SetTextureStorageForMemoryObject(ctx, texObj, memObj, 46501e04c3fSmrg levels, 46601e04c3fSmrg width, height, depth, 46701e04c3fSmrg offset)) { 46801e04c3fSmrg 46901e04c3fSmrg clear_texture_fields(ctx, texObj); 47001e04c3fSmrg return; 47101e04c3fSmrg } 47201e04c3fSmrg } 47301e04c3fSmrg else { 47401e04c3fSmrg if (!ctx->Driver.AllocTextureStorage(ctx, texObj, levels, 47501e04c3fSmrg width, height, depth)) { 47601e04c3fSmrg /* Reset the texture images' info to zeros. 47701e04c3fSmrg * Strictly speaking, we probably don't have to do this since 47801e04c3fSmrg * generating GL_OUT_OF_MEMORY can leave things in an undefined 47901e04c3fSmrg * state but this puts things in a consistent state. 48001e04c3fSmrg */ 48101e04c3fSmrg clear_texture_fields(ctx, texObj); 48201e04c3fSmrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTex%sStorage%uD", 48301e04c3fSmrg suffix, dims); 48401e04c3fSmrg return; 48501e04c3fSmrg } 486af69d88dSmrg } 487af69d88dSmrg 488af69d88dSmrg _mesa_set_texture_view_state(ctx, texObj, target, levels); 489af69d88dSmrg 49001e04c3fSmrg update_fbo_texture(ctx, texObj); 491af69d88dSmrg } 492af69d88dSmrg} 493af69d88dSmrg 494af69d88dSmrg 49501e04c3fSmrgstatic void 49601e04c3fSmrgtexture_storage_error(struct gl_context *ctx, GLuint dims, 49701e04c3fSmrg struct gl_texture_object *texObj, 49801e04c3fSmrg GLenum target, GLsizei levels, 49901e04c3fSmrg GLenum internalformat, GLsizei width, 50001e04c3fSmrg GLsizei height, GLsizei depth, bool dsa) 50101e04c3fSmrg{ 50201e04c3fSmrg texture_storage(ctx, dims, texObj, NULL, target, levels, internalformat, 50301e04c3fSmrg width, height, depth, dsa, 0, false); 50401e04c3fSmrg} 50501e04c3fSmrg 50601e04c3fSmrg 50701e04c3fSmrgstatic void 50801e04c3fSmrgtexture_storage_no_error(struct gl_context *ctx, GLuint dims, 50901e04c3fSmrg struct gl_texture_object *texObj, 51001e04c3fSmrg GLenum target, GLsizei levels, 51101e04c3fSmrg GLenum internalformat, GLsizei width, 51201e04c3fSmrg GLsizei height, GLsizei depth, bool dsa) 51301e04c3fSmrg{ 51401e04c3fSmrg texture_storage(ctx, dims, texObj, NULL, target, levels, internalformat, 51501e04c3fSmrg width, height, depth, dsa, 0, true); 51601e04c3fSmrg} 51701e04c3fSmrg 51801e04c3fSmrg 51901e04c3fSmrg/** 52001e04c3fSmrg * Helper used by _mesa_TexStorage1/2/3D(). 52101e04c3fSmrg */ 52201e04c3fSmrgstatic void 52301e04c3fSmrgtexstorage_error(GLuint dims, GLenum target, GLsizei levels, 52401e04c3fSmrg GLenum internalformat, GLsizei width, GLsizei height, 52501e04c3fSmrg GLsizei depth, const char *caller) 52601e04c3fSmrg{ 52701e04c3fSmrg struct gl_texture_object *texObj; 52801e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 52901e04c3fSmrg 53001e04c3fSmrg /* Check target. This is done here so that texture_storage 53101e04c3fSmrg * can receive unsized formats. 53201e04c3fSmrg */ 53301e04c3fSmrg if (!legal_texobj_target(ctx, dims, target)) { 53401e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, 53501e04c3fSmrg "%s(illegal target=%s)", 53601e04c3fSmrg caller, _mesa_enum_to_string(target)); 53701e04c3fSmrg return; 53801e04c3fSmrg } 53901e04c3fSmrg 54001e04c3fSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 54101e04c3fSmrg _mesa_debug(ctx, "%s %s %d %s %d %d %d\n", caller, 54201e04c3fSmrg _mesa_enum_to_string(target), levels, 54301e04c3fSmrg _mesa_enum_to_string(internalformat), 54401e04c3fSmrg width, height, depth); 54501e04c3fSmrg 54601e04c3fSmrg /* Check the format to make sure it is sized. */ 54701e04c3fSmrg if (!_mesa_is_legal_tex_storage_format(ctx, internalformat)) { 54801e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, 54901e04c3fSmrg "%s(internalformat = %s)", caller, 55001e04c3fSmrg _mesa_enum_to_string(internalformat)); 55101e04c3fSmrg return; 55201e04c3fSmrg } 55301e04c3fSmrg 55401e04c3fSmrg texObj = _mesa_get_current_tex_object(ctx, target); 55501e04c3fSmrg if (!texObj) 55601e04c3fSmrg return; 55701e04c3fSmrg 55801e04c3fSmrg texture_storage_error(ctx, dims, texObj, target, levels, 55901e04c3fSmrg internalformat, width, height, depth, false); 56001e04c3fSmrg} 56101e04c3fSmrg 56201e04c3fSmrg 56301e04c3fSmrgstatic void 56401e04c3fSmrgtexstorage_no_error(GLuint dims, GLenum target, GLsizei levels, 56501e04c3fSmrg GLenum internalformat, GLsizei width, GLsizei height, 56601e04c3fSmrg GLsizei depth) 56701e04c3fSmrg{ 56801e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 56901e04c3fSmrg 57001e04c3fSmrg struct gl_texture_object *texObj = _mesa_get_current_tex_object(ctx, target); 57101e04c3fSmrg texture_storage_no_error(ctx, dims, texObj, target, levels, 57201e04c3fSmrg internalformat, width, height, depth, false); 57301e04c3fSmrg} 57401e04c3fSmrg 57501e04c3fSmrg 57601e04c3fSmrg/** 57701e04c3fSmrg * Helper used by _mesa_TextureStorage1/2/3D(). 57801e04c3fSmrg */ 57901e04c3fSmrgstatic void 58001e04c3fSmrgtexturestorage_error(GLuint dims, GLuint texture, GLsizei levels, 58101e04c3fSmrg GLenum internalformat, GLsizei width, GLsizei height, 58201e04c3fSmrg GLsizei depth, const char *caller) 58301e04c3fSmrg{ 58401e04c3fSmrg struct gl_texture_object *texObj; 58501e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 58601e04c3fSmrg 58701e04c3fSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 58801e04c3fSmrg _mesa_debug(ctx, "%s %d %d %s %d %d %d\n", 58901e04c3fSmrg caller, texture, levels, 59001e04c3fSmrg _mesa_enum_to_string(internalformat), 59101e04c3fSmrg width, height, depth); 59201e04c3fSmrg 59301e04c3fSmrg /* Check the format to make sure it is sized. */ 59401e04c3fSmrg if (!_mesa_is_legal_tex_storage_format(ctx, internalformat)) { 59501e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, 59601e04c3fSmrg "%s(internalformat = %s)", caller, 59701e04c3fSmrg _mesa_enum_to_string(internalformat)); 59801e04c3fSmrg return; 59901e04c3fSmrg } 60001e04c3fSmrg 60101e04c3fSmrg texObj = _mesa_lookup_texture_err(ctx, texture, caller); 60201e04c3fSmrg if (!texObj) 60301e04c3fSmrg return; 60401e04c3fSmrg 60501e04c3fSmrg /* Check target. This is done here so that texture_storage 60601e04c3fSmrg * can receive unsized formats. 60701e04c3fSmrg */ 60801e04c3fSmrg if (!legal_texobj_target(ctx, dims, texObj->Target)) { 60901e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 61001e04c3fSmrg "%s(illegal target=%s)", caller, 61101e04c3fSmrg _mesa_enum_to_string(texObj->Target)); 61201e04c3fSmrg return; 61301e04c3fSmrg } 61401e04c3fSmrg 61501e04c3fSmrg texture_storage_error(ctx, dims, texObj, texObj->Target, 61601e04c3fSmrg levels, internalformat, width, height, depth, true); 61701e04c3fSmrg} 61801e04c3fSmrg 61901e04c3fSmrg 62001e04c3fSmrgstatic void 62101e04c3fSmrgtexturestorage_no_error(GLuint dims, GLuint texture, GLsizei levels, 62201e04c3fSmrg GLenum internalformat, GLsizei width, GLsizei height, 62301e04c3fSmrg GLsizei depth) 62401e04c3fSmrg{ 62501e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 62601e04c3fSmrg 62701e04c3fSmrg struct gl_texture_object *texObj = _mesa_lookup_texture(ctx, texture); 62801e04c3fSmrg texture_storage_no_error(ctx, dims, texObj, texObj->Target, 62901e04c3fSmrg levels, internalformat, width, height, depth, true); 63001e04c3fSmrg} 63101e04c3fSmrg 63201e04c3fSmrg 63301e04c3fSmrgvoid GLAPIENTRY 63401e04c3fSmrg_mesa_TexStorage1D_no_error(GLenum target, GLsizei levels, 63501e04c3fSmrg GLenum internalformat, GLsizei width) 63601e04c3fSmrg{ 63701e04c3fSmrg texstorage_no_error(1, target, levels, internalformat, width, 1, 1); 63801e04c3fSmrg} 63901e04c3fSmrg 64001e04c3fSmrg 641af69d88dSmrgvoid GLAPIENTRY 642af69d88dSmrg_mesa_TexStorage1D(GLenum target, GLsizei levels, GLenum internalformat, 643af69d88dSmrg GLsizei width) 644af69d88dSmrg{ 64501e04c3fSmrg texstorage_error(1, target, levels, internalformat, width, 1, 1, 64601e04c3fSmrg "glTexStorage1D"); 64701e04c3fSmrg} 64801e04c3fSmrg 64901e04c3fSmrg 65001e04c3fSmrgvoid GLAPIENTRY 65101e04c3fSmrg_mesa_TexStorage2D_no_error(GLenum target, GLsizei levels, 65201e04c3fSmrg GLenum internalformat, GLsizei width, 65301e04c3fSmrg GLsizei height) 65401e04c3fSmrg{ 65501e04c3fSmrg texstorage_no_error(2, target, levels, internalformat, width, height, 1); 656af69d88dSmrg} 657af69d88dSmrg 658af69d88dSmrg 659af69d88dSmrgvoid GLAPIENTRY 660af69d88dSmrg_mesa_TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, 661af69d88dSmrg GLsizei width, GLsizei height) 662af69d88dSmrg{ 66301e04c3fSmrg texstorage_error(2, target, levels, internalformat, width, height, 1, 66401e04c3fSmrg "glTexStorage2D"); 66501e04c3fSmrg} 66601e04c3fSmrg 66701e04c3fSmrg 66801e04c3fSmrgvoid GLAPIENTRY 66901e04c3fSmrg_mesa_TexStorage3D_no_error(GLenum target, GLsizei levels, 67001e04c3fSmrg GLenum internalformat, GLsizei width, 67101e04c3fSmrg GLsizei height, GLsizei depth) 67201e04c3fSmrg{ 67301e04c3fSmrg texstorage_no_error(3, target, levels, internalformat, width, height, depth); 674af69d88dSmrg} 675af69d88dSmrg 676af69d88dSmrg 677af69d88dSmrgvoid GLAPIENTRY 678af69d88dSmrg_mesa_TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, 679af69d88dSmrg GLsizei width, GLsizei height, GLsizei depth) 680af69d88dSmrg{ 68101e04c3fSmrg texstorage_error(3, target, levels, internalformat, width, height, depth, 68201e04c3fSmrg "glTexStorage3D"); 683af69d88dSmrg} 684af69d88dSmrg 685af69d88dSmrg 68601e04c3fSmrgvoid GLAPIENTRY 68701e04c3fSmrg_mesa_TextureStorage1D_no_error(GLuint texture, GLsizei levels, 68801e04c3fSmrg GLenum internalformat, GLsizei width) 68901e04c3fSmrg{ 69001e04c3fSmrg texturestorage_no_error(1, texture, levels, internalformat, width, 1, 1); 69101e04c3fSmrg} 69201e04c3fSmrg 69301e04c3fSmrg 69401e04c3fSmrgvoid GLAPIENTRY 69501e04c3fSmrg_mesa_TextureStorage1D(GLuint texture, GLsizei levels, GLenum internalformat, 69601e04c3fSmrg GLsizei width) 69701e04c3fSmrg{ 69801e04c3fSmrg texturestorage_error(1, texture, levels, internalformat, width, 1, 1, 69901e04c3fSmrg "glTextureStorage1D"); 70001e04c3fSmrg} 70101e04c3fSmrg 70201e04c3fSmrg 70301e04c3fSmrgvoid GLAPIENTRY 70401e04c3fSmrg_mesa_TextureStorage2D_no_error(GLuint texture, GLsizei levels, 70501e04c3fSmrg GLenum internalformat, 70601e04c3fSmrg GLsizei width, GLsizei height) 70701e04c3fSmrg{ 70801e04c3fSmrg texturestorage_no_error(2, texture, levels, internalformat, width, height, 1); 70901e04c3fSmrg} 71001e04c3fSmrg 71101e04c3fSmrg 71201e04c3fSmrgvoid GLAPIENTRY 71301e04c3fSmrg_mesa_TextureStorage2D(GLuint texture, GLsizei levels, 71401e04c3fSmrg GLenum internalformat, 71501e04c3fSmrg GLsizei width, GLsizei height) 71601e04c3fSmrg{ 71701e04c3fSmrg texturestorage_error(2, texture, levels, internalformat, width, height, 1, 71801e04c3fSmrg "glTextureStorage2D"); 71901e04c3fSmrg} 72001e04c3fSmrg 72101e04c3fSmrg 72201e04c3fSmrgvoid GLAPIENTRY 72301e04c3fSmrg_mesa_TextureStorage3D_no_error(GLuint texture, GLsizei levels, 72401e04c3fSmrg GLenum internalformat, GLsizei width, 72501e04c3fSmrg GLsizei height, GLsizei depth) 72601e04c3fSmrg{ 72701e04c3fSmrg texturestorage_no_error(3, texture, levels, internalformat, width, height, 72801e04c3fSmrg depth); 72901e04c3fSmrg} 73001e04c3fSmrg 73101e04c3fSmrg 73201e04c3fSmrgvoid GLAPIENTRY 73301e04c3fSmrg_mesa_TextureStorage3D(GLuint texture, GLsizei levels, GLenum internalformat, 73401e04c3fSmrg GLsizei width, GLsizei height, GLsizei depth) 73501e04c3fSmrg{ 73601e04c3fSmrg texturestorage_error(3, texture, levels, internalformat, width, height, depth, 73701e04c3fSmrg "glTextureStorage3D"); 73801e04c3fSmrg} 73901e04c3fSmrg 740af69d88dSmrg 741af69d88dSmrgvoid GLAPIENTRY 742af69d88dSmrg_mesa_TextureStorage1DEXT(GLuint texture, GLenum target, GLsizei levels, 743af69d88dSmrg GLenum internalformat, 744af69d88dSmrg GLsizei width) 745af69d88dSmrg{ 746af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 7477ec681f3Smrg /* 'texture' must always be initialized, even if the call to 7487ec681f3Smrg * glTextureStorage1DEXT will generate an error. 7497ec681f3Smrg */ 7507ec681f3Smrg if (!_mesa_lookup_or_create_texture(ctx, target, texture, false, true, 7517ec681f3Smrg "glTextureStorage1DEXT")) 7527ec681f3Smrg return; 7537ec681f3Smrg texturestorage_error(1, texture, levels, internalformat, width, 1, 1, 7547ec681f3Smrg "glTextureStorage1DEXT"); 755af69d88dSmrg} 756af69d88dSmrg 757af69d88dSmrg 758af69d88dSmrgvoid GLAPIENTRY 759af69d88dSmrg_mesa_TextureStorage2DEXT(GLuint texture, GLenum target, GLsizei levels, 760af69d88dSmrg GLenum internalformat, 761af69d88dSmrg GLsizei width, GLsizei height) 762af69d88dSmrg{ 763af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 7647ec681f3Smrg /* 'texture' must always be initialized, even if the call to 7657ec681f3Smrg * glTextureStorage2DEXT will generate an error. 7667ec681f3Smrg */ 7677ec681f3Smrg if (!_mesa_lookup_or_create_texture(ctx, target, texture, false, true, 7687ec681f3Smrg "glTextureStorage2DEXT")) 7697ec681f3Smrg return; 7707ec681f3Smrg texturestorage_error(2, texture, levels, internalformat, width, height, 1, 7717ec681f3Smrg "glTextureStorage2DEXT"); 772af69d88dSmrg} 773af69d88dSmrg 774af69d88dSmrg 775af69d88dSmrgvoid GLAPIENTRY 776af69d88dSmrg_mesa_TextureStorage3DEXT(GLuint texture, GLenum target, GLsizei levels, 777af69d88dSmrg GLenum internalformat, 778af69d88dSmrg GLsizei width, GLsizei height, GLsizei depth) 779af69d88dSmrg{ 780af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 7817ec681f3Smrg /* 'texture' must always be initialized, even if the call to 7827ec681f3Smrg * glTextureStorage3DEXT will generate an error. 7837ec681f3Smrg */ 7847ec681f3Smrg if (!_mesa_lookup_or_create_texture(ctx, target, texture, false, true, 7857ec681f3Smrg "glTextureStorage3DEXT")) 7867ec681f3Smrg return; 7877ec681f3Smrg texturestorage_error(3, texture, levels, internalformat, width, height, depth, 7887ec681f3Smrg "glTextureStorage3DEXT"); 789af69d88dSmrg} 79001e04c3fSmrg 79101e04c3fSmrg 79201e04c3fSmrgvoid 79301e04c3fSmrg_mesa_texture_storage_memory(struct gl_context *ctx, GLuint dims, 79401e04c3fSmrg struct gl_texture_object *texObj, 79501e04c3fSmrg struct gl_memory_object *memObj, 79601e04c3fSmrg GLenum target, GLsizei levels, 79701e04c3fSmrg GLenum internalformat, GLsizei width, 79801e04c3fSmrg GLsizei height, GLsizei depth, 79901e04c3fSmrg GLuint64 offset, bool dsa) 80001e04c3fSmrg{ 80101e04c3fSmrg assert(memObj); 80201e04c3fSmrg 80301e04c3fSmrg texture_storage(ctx, dims, texObj, memObj, target, levels, internalformat, 80401e04c3fSmrg width, height, depth, offset, dsa, false); 80501e04c3fSmrg} 806