teximage.c revision b9abf16e
17117f1b4Smrg/* 2af69d88dSmrg * Mesa 3-D graphics library 37117f1b4Smrg * 47117f1b4Smrg * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 54a49301eSmrg * Copyright (C) 2009 VMware, Inc. All Rights Reserved. 67117f1b4Smrg * 77117f1b4Smrg * Permission is hereby granted, free of charge, to any person obtaining a 87117f1b4Smrg * copy of this software and associated documentation files (the "Software"), 97117f1b4Smrg * to deal in the Software without restriction, including without limitation 107117f1b4Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 117117f1b4Smrg * and/or sell copies of the Software, and to permit persons to whom the 127117f1b4Smrg * Software is furnished to do so, subject to the following conditions: 137117f1b4Smrg * 147117f1b4Smrg * The above copyright notice and this permission notice shall be included 157117f1b4Smrg * in all copies or substantial portions of the Software. 167117f1b4Smrg * 177117f1b4Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 187117f1b4Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 197117f1b4Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20af69d88dSmrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 21af69d88dSmrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 22af69d88dSmrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 23af69d88dSmrg * OTHER DEALINGS IN THE SOFTWARE. 247117f1b4Smrg */ 257117f1b4Smrg 267117f1b4Smrg 277117f1b4Smrg/** 287117f1b4Smrg * \file teximage.c 297117f1b4Smrg * Texture image-related functions. 307117f1b4Smrg */ 317117f1b4Smrg 32af69d88dSmrg#include <stdbool.h> 337117f1b4Smrg#include "glheader.h" 347117f1b4Smrg#include "bufferobj.h" 357117f1b4Smrg#include "context.h" 364a49301eSmrg#include "enums.h" 377117f1b4Smrg#include "fbobject.h" 387117f1b4Smrg#include "framebuffer.h" 394a49301eSmrg#include "hash.h" 407117f1b4Smrg#include "image.h" 417117f1b4Smrg#include "imports.h" 427117f1b4Smrg#include "macros.h" 4301e04c3fSmrg#include "mipmap.h" 44af69d88dSmrg#include "multisample.h" 45af69d88dSmrg#include "pixelstore.h" 467117f1b4Smrg#include "state.h" 477117f1b4Smrg#include "texcompress.h" 48af69d88dSmrg#include "texcompress_cpal.h" 497117f1b4Smrg#include "teximage.h" 50af69d88dSmrg#include "texobj.h" 517117f1b4Smrg#include "texstate.h" 52af69d88dSmrg#include "texstorage.h" 53af69d88dSmrg#include "textureview.h" 547117f1b4Smrg#include "mtypes.h" 55af69d88dSmrg#include "glformats.h" 56af69d88dSmrg#include "texstore.h" 5701e04c3fSmrg#include "pbo.h" 587117f1b4Smrg 597117f1b4Smrg 60c1f859d4Smrg/** 61c1f859d4Smrg * State changes which we care about for glCopyTex[Sub]Image() calls. 62c1f859d4Smrg * In particular, we care about pixel transfer state and buffer state 63c1f859d4Smrg * (such as glReadBuffer to make sure we read from the right renderbuffer). 64c1f859d4Smrg */ 653464ebd5Sriastradh#define NEW_COPY_TEX_STATE (_NEW_BUFFERS | _NEW_PIXEL) 66c1f859d4Smrg 677117f1b4Smrg/** 6801e04c3fSmrg * Returns a corresponding internal floating point format for a given base 6901e04c3fSmrg * format as specifed by OES_texture_float. In case of GL_FLOAT, the internal 7001e04c3fSmrg * format needs to be a 32 bit component and in case of GL_HALF_FLOAT_OES it 7101e04c3fSmrg * needs to be a 16 bit component. 727117f1b4Smrg * 7301e04c3fSmrg * For example, given base format GL_RGBA, type GL_FLOAT return GL_RGBA32F_ARB. 747117f1b4Smrg */ 7501e04c3fSmrgstatic GLenum 7601e04c3fSmrgadjust_for_oes_float_texture(const struct gl_context *ctx, 7701e04c3fSmrg GLenum format, GLenum type) 787117f1b4Smrg{ 7901e04c3fSmrg switch (type) { 8001e04c3fSmrg case GL_FLOAT: 8101e04c3fSmrg if (ctx->Extensions.OES_texture_float) { 8201e04c3fSmrg switch (format) { 8301e04c3fSmrg case GL_RGBA: 8401e04c3fSmrg return GL_RGBA32F; 8501e04c3fSmrg case GL_RGB: 8601e04c3fSmrg return GL_RGB32F; 8701e04c3fSmrg case GL_ALPHA: 8801e04c3fSmrg return GL_ALPHA32F_ARB; 8901e04c3fSmrg case GL_LUMINANCE: 9001e04c3fSmrg return GL_LUMINANCE32F_ARB; 9101e04c3fSmrg case GL_LUMINANCE_ALPHA: 9201e04c3fSmrg return GL_LUMINANCE_ALPHA32F_ARB; 933464ebd5Sriastradh default: 9401e04c3fSmrg break; 9501e04c3fSmrg } 967117f1b4Smrg } 9701e04c3fSmrg break; 987117f1b4Smrg 9901e04c3fSmrg case GL_HALF_FLOAT_OES: 10001e04c3fSmrg if (ctx->Extensions.OES_texture_half_float) { 10101e04c3fSmrg switch (format) { 10201e04c3fSmrg case GL_RGBA: 10301e04c3fSmrg return GL_RGBA16F; 10401e04c3fSmrg case GL_RGB: 10501e04c3fSmrg return GL_RGB16F; 10601e04c3fSmrg case GL_ALPHA: 10701e04c3fSmrg return GL_ALPHA16F_ARB; 10801e04c3fSmrg case GL_LUMINANCE: 10901e04c3fSmrg return GL_LUMINANCE16F_ARB; 11001e04c3fSmrg case GL_LUMINANCE_ALPHA: 11101e04c3fSmrg return GL_LUMINANCE_ALPHA16F_ARB; 1127117f1b4Smrg default: 11301e04c3fSmrg break; 11401e04c3fSmrg } 1157117f1b4Smrg } 11601e04c3fSmrg break; 1177117f1b4Smrg 1184a49301eSmrg default: 11901e04c3fSmrg break; 1207117f1b4Smrg } 121af69d88dSmrg 12201e04c3fSmrg return format; 12301e04c3fSmrg} 1247117f1b4Smrg 12501e04c3fSmrg/** 12601e04c3fSmrg * Returns a corresponding base format for a given internal floating point 12701e04c3fSmrg * format as specifed by OES_texture_float. 12801e04c3fSmrg */ 12901e04c3fSmrgstatic GLenum 13001e04c3fSmrgoes_float_internal_format(const struct gl_context *ctx, 13101e04c3fSmrg GLenum format, GLenum type) 13201e04c3fSmrg{ 13301e04c3fSmrg switch (type) { 13401e04c3fSmrg case GL_FLOAT: 13501e04c3fSmrg if (ctx->Extensions.OES_texture_float) { 13601e04c3fSmrg switch (format) { 13701e04c3fSmrg case GL_RGBA32F: 1387117f1b4Smrg return GL_RGBA; 13901e04c3fSmrg case GL_RGB32F: 1407117f1b4Smrg return GL_RGB; 1417117f1b4Smrg case GL_ALPHA32F_ARB: 1427117f1b4Smrg return GL_ALPHA; 1437117f1b4Smrg case GL_LUMINANCE32F_ARB: 1447117f1b4Smrg return GL_LUMINANCE; 1457117f1b4Smrg case GL_LUMINANCE_ALPHA32F_ARB: 1467117f1b4Smrg return GL_LUMINANCE_ALPHA; 1477117f1b4Smrg default: 14801e04c3fSmrg break; 14901e04c3fSmrg } 1507117f1b4Smrg } 15101e04c3fSmrg break; 1527117f1b4Smrg 15301e04c3fSmrg case GL_HALF_FLOAT_OES: 15401e04c3fSmrg if (ctx->Extensions.OES_texture_half_float) { 15501e04c3fSmrg switch (format) { 15601e04c3fSmrg case GL_RGBA16F: 1574a49301eSmrg return GL_RGBA; 15801e04c3fSmrg case GL_RGB16F: 15901e04c3fSmrg return GL_RGB; 16001e04c3fSmrg case GL_ALPHA16F_ARB: 1613464ebd5Sriastradh return GL_ALPHA; 16201e04c3fSmrg case GL_LUMINANCE16F_ARB: 1633464ebd5Sriastradh return GL_LUMINANCE; 16401e04c3fSmrg case GL_LUMINANCE_ALPHA16F_ARB: 1653464ebd5Sriastradh return GL_LUMINANCE_ALPHA; 1664a49301eSmrg default: 16701e04c3fSmrg break; 16801e04c3fSmrg } 1693464ebd5Sriastradh } 17001e04c3fSmrg break; 1713464ebd5Sriastradh } 17201e04c3fSmrg return format; 1737117f1b4Smrg} 1747117f1b4Smrg 1757117f1b4Smrg 1767117f1b4Smrg/** 177af69d88dSmrg * Install gl_texture_image in a gl_texture_object according to the target 178af69d88dSmrg * and level parameters. 179b9abf16eSmaya * 1807117f1b4Smrg * \param tObj texture object. 1817117f1b4Smrg * \param target texture target. 1827117f1b4Smrg * \param level image level. 1837117f1b4Smrg * \param texImage texture image. 1847117f1b4Smrg */ 185af69d88dSmrgstatic void 186af69d88dSmrgset_tex_image(struct gl_texture_object *tObj, 187af69d88dSmrg GLenum target, GLint level, 188af69d88dSmrg struct gl_texture_image *texImage) 1897117f1b4Smrg{ 1904a49301eSmrg const GLuint face = _mesa_tex_target_to_face(target); 1914a49301eSmrg 19201e04c3fSmrg assert(tObj); 19301e04c3fSmrg assert(texImage); 194af69d88dSmrg if (target == GL_TEXTURE_RECTANGLE_NV || target == GL_TEXTURE_EXTERNAL_OES) 195af69d88dSmrg assert(level == 0); 1964a49301eSmrg 1974a49301eSmrg tObj->Image[face][level] = texImage; 1984a49301eSmrg 1997117f1b4Smrg /* Set the 'back' pointer */ 2007117f1b4Smrg texImage->TexObject = tObj; 201af69d88dSmrg texImage->Level = level; 202af69d88dSmrg texImage->Face = face; 2037117f1b4Smrg} 2047117f1b4Smrg 2057117f1b4Smrg 2067117f1b4Smrg/** 207af69d88dSmrg * Free a gl_texture_image and associated data. 208af69d88dSmrg * This function is a fallback called via ctx->Driver.DeleteTextureImage(). 2097117f1b4Smrg * 2104a49301eSmrg * \param texImage texture image. 2117117f1b4Smrg * 2127117f1b4Smrg * Free the texture image structure and the associated image data. 2137117f1b4Smrg */ 2147117f1b4Smrgvoid 2153464ebd5Sriastradh_mesa_delete_texture_image(struct gl_context *ctx, 2163464ebd5Sriastradh struct gl_texture_image *texImage) 2177117f1b4Smrg{ 2187117f1b4Smrg /* Free texImage->Data and/or any other driver-specific texture 2197117f1b4Smrg * image storage. 2207117f1b4Smrg */ 22101e04c3fSmrg assert(ctx->Driver.FreeTextureImageBuffer); 222af69d88dSmrg ctx->Driver.FreeTextureImageBuffer( ctx, texImage ); 223cdc920a0Smrg free(texImage); 2247117f1b4Smrg} 2257117f1b4Smrg 2267117f1b4Smrg 2277117f1b4Smrg/** 2287117f1b4Smrg * Test if a target is a proxy target. 2297117f1b4Smrg * 2307117f1b4Smrg * \param target texture target. 2317117f1b4Smrg * 2327117f1b4Smrg * \return GL_TRUE if the target is a proxy target, GL_FALSE otherwise. 2337117f1b4Smrg */ 2347117f1b4SmrgGLboolean 2357117f1b4Smrg_mesa_is_proxy_texture(GLenum target) 2367117f1b4Smrg{ 237af69d88dSmrg unsigned i; 238af69d88dSmrg static const GLenum targets[] = { 239af69d88dSmrg GL_PROXY_TEXTURE_1D, 240af69d88dSmrg GL_PROXY_TEXTURE_2D, 241af69d88dSmrg GL_PROXY_TEXTURE_3D, 242af69d88dSmrg GL_PROXY_TEXTURE_CUBE_MAP, 243af69d88dSmrg GL_PROXY_TEXTURE_RECTANGLE, 244af69d88dSmrg GL_PROXY_TEXTURE_1D_ARRAY, 245af69d88dSmrg GL_PROXY_TEXTURE_2D_ARRAY, 246af69d88dSmrg GL_PROXY_TEXTURE_CUBE_MAP_ARRAY, 247af69d88dSmrg GL_PROXY_TEXTURE_2D_MULTISAMPLE, 248af69d88dSmrg GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 249af69d88dSmrg }; 250af69d88dSmrg /* 251af69d88dSmrg * NUM_TEXTURE_TARGETS should match number of terms above, except there's no 252af69d88dSmrg * proxy for GL_TEXTURE_BUFFER and GL_TEXTURE_EXTERNAL_OES. 2533464ebd5Sriastradh */ 25401e04c3fSmrg STATIC_ASSERT(NUM_TEXTURE_TARGETS == ARRAY_SIZE(targets) + 2); 2554a49301eSmrg 25601e04c3fSmrg for (i = 0; i < ARRAY_SIZE(targets); ++i) 257af69d88dSmrg if (target == targets[i]) 258af69d88dSmrg return GL_TRUE; 259af69d88dSmrg return GL_FALSE; 2607117f1b4Smrg} 2617117f1b4Smrg 2627117f1b4Smrg 26301e04c3fSmrg/** 26401e04c3fSmrg * Test if a target is an array target. 26501e04c3fSmrg * 26601e04c3fSmrg * \param target texture target. 26701e04c3fSmrg * 26801e04c3fSmrg * \return true if the target is an array target, false otherwise. 26901e04c3fSmrg */ 27001e04c3fSmrgbool 27101e04c3fSmrg_mesa_is_array_texture(GLenum target) 27201e04c3fSmrg{ 27301e04c3fSmrg switch (target) { 27401e04c3fSmrg case GL_TEXTURE_1D_ARRAY: 27501e04c3fSmrg case GL_TEXTURE_2D_ARRAY: 27601e04c3fSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: 27701e04c3fSmrg case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 27801e04c3fSmrg return true; 27901e04c3fSmrg default: 28001e04c3fSmrg return false; 28101e04c3fSmrg }; 28201e04c3fSmrg} 28301e04c3fSmrg 28401e04c3fSmrg/** 28501e04c3fSmrg * Test if a target is a cube map. 28601e04c3fSmrg * 28701e04c3fSmrg * \param target texture target. 28801e04c3fSmrg * 28901e04c3fSmrg * \return true if the target is a cube map, false otherwise. 29001e04c3fSmrg */ 29101e04c3fSmrgbool 29201e04c3fSmrg_mesa_is_cube_map_texture(GLenum target) 29301e04c3fSmrg{ 29401e04c3fSmrg switch(target) { 29501e04c3fSmrg case GL_TEXTURE_CUBE_MAP: 29601e04c3fSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: 29701e04c3fSmrg return true; 29801e04c3fSmrg default: 29901e04c3fSmrg return false; 30001e04c3fSmrg } 30101e04c3fSmrg} 30201e04c3fSmrg 3037117f1b4Smrg/** 3043464ebd5Sriastradh * Return the proxy target which corresponds to the given texture target 3053464ebd5Sriastradh */ 3063464ebd5Sriastradhstatic GLenum 307af69d88dSmrgproxy_target(GLenum target) 3083464ebd5Sriastradh{ 3093464ebd5Sriastradh switch (target) { 3103464ebd5Sriastradh case GL_TEXTURE_1D: 3113464ebd5Sriastradh case GL_PROXY_TEXTURE_1D: 3123464ebd5Sriastradh return GL_PROXY_TEXTURE_1D; 3133464ebd5Sriastradh case GL_TEXTURE_2D: 3143464ebd5Sriastradh case GL_PROXY_TEXTURE_2D: 3153464ebd5Sriastradh return GL_PROXY_TEXTURE_2D; 3163464ebd5Sriastradh case GL_TEXTURE_3D: 3173464ebd5Sriastradh case GL_PROXY_TEXTURE_3D: 3183464ebd5Sriastradh return GL_PROXY_TEXTURE_3D; 31901e04c3fSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 32001e04c3fSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 32101e04c3fSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 32201e04c3fSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 32301e04c3fSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 32401e04c3fSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 32501e04c3fSmrg case GL_TEXTURE_CUBE_MAP: 32601e04c3fSmrg case GL_PROXY_TEXTURE_CUBE_MAP: 32701e04c3fSmrg return GL_PROXY_TEXTURE_CUBE_MAP; 3283464ebd5Sriastradh case GL_TEXTURE_RECTANGLE_NV: 3293464ebd5Sriastradh case GL_PROXY_TEXTURE_RECTANGLE_NV: 3303464ebd5Sriastradh return GL_PROXY_TEXTURE_RECTANGLE_NV; 3313464ebd5Sriastradh case GL_TEXTURE_1D_ARRAY_EXT: 3323464ebd5Sriastradh case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 3333464ebd5Sriastradh return GL_PROXY_TEXTURE_1D_ARRAY_EXT; 3343464ebd5Sriastradh case GL_TEXTURE_2D_ARRAY_EXT: 3353464ebd5Sriastradh case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 3363464ebd5Sriastradh return GL_PROXY_TEXTURE_2D_ARRAY_EXT; 337af69d88dSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: 338af69d88dSmrg case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY: 339af69d88dSmrg return GL_PROXY_TEXTURE_CUBE_MAP_ARRAY; 340af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE: 341af69d88dSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE: 342af69d88dSmrg return GL_PROXY_TEXTURE_2D_MULTISAMPLE; 343af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 344af69d88dSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY: 345af69d88dSmrg return GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY; 3463464ebd5Sriastradh default: 347af69d88dSmrg _mesa_problem(NULL, "unexpected target in proxy_target()"); 3483464ebd5Sriastradh return 0; 3493464ebd5Sriastradh } 3503464ebd5Sriastradh} 3513464ebd5Sriastradh 3523464ebd5Sriastradh 3537117f1b4Smrg 3544a49301eSmrg 3554a49301eSmrg/** 3564a49301eSmrg * Get a texture image pointer from a texture object, given a texture 3574a49301eSmrg * target and mipmap level. The target and level parameters should 3584a49301eSmrg * have already been error-checked. 3597117f1b4Smrg * 3604a49301eSmrg * \param texObj texture unit. 3617117f1b4Smrg * \param target texture target. 3627117f1b4Smrg * \param level image level. 3637117f1b4Smrg * 3644a49301eSmrg * \return pointer to the texture image structure, or NULL on failure. 3657117f1b4Smrg */ 3667117f1b4Smrgstruct gl_texture_image * 36701e04c3fSmrg_mesa_select_tex_image(const struct gl_texture_object *texObj, 36801e04c3fSmrg GLenum target, GLint level) 3697117f1b4Smrg{ 3704a49301eSmrg const GLuint face = _mesa_tex_target_to_face(target); 3717117f1b4Smrg 37201e04c3fSmrg assert(texObj); 37301e04c3fSmrg assert(level >= 0); 37401e04c3fSmrg assert(level < MAX_TEXTURE_LEVELS); 375c1f859d4Smrg 3764a49301eSmrg return texObj->Image[face][level]; 3777117f1b4Smrg} 3787117f1b4Smrg 3797117f1b4Smrg 3807117f1b4Smrg/** 3817117f1b4Smrg * Like _mesa_select_tex_image() but if the image doesn't exist, allocate 3827117f1b4Smrg * it and install it. Only return NULL if passed a bad parameter or run 3837117f1b4Smrg * out of memory. 3847117f1b4Smrg */ 3857117f1b4Smrgstruct gl_texture_image * 3863464ebd5Sriastradh_mesa_get_tex_image(struct gl_context *ctx, struct gl_texture_object *texObj, 3877117f1b4Smrg GLenum target, GLint level) 3887117f1b4Smrg{ 3897117f1b4Smrg struct gl_texture_image *texImage; 3907117f1b4Smrg 3917117f1b4Smrg if (!texObj) 3927117f1b4Smrg return NULL; 393af69d88dSmrg 39401e04c3fSmrg texImage = _mesa_select_tex_image(texObj, target, level); 3957117f1b4Smrg if (!texImage) { 3967117f1b4Smrg texImage = ctx->Driver.NewTextureImage(ctx); 3977117f1b4Smrg if (!texImage) { 3987117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture image allocation"); 3997117f1b4Smrg return NULL; 4007117f1b4Smrg } 4017117f1b4Smrg 402af69d88dSmrg set_tex_image(texObj, target, level, texImage); 4037117f1b4Smrg } 4047117f1b4Smrg 4057117f1b4Smrg return texImage; 4067117f1b4Smrg} 4077117f1b4Smrg 4087117f1b4Smrg 4097117f1b4Smrg/** 4107117f1b4Smrg * Return pointer to the specified proxy texture image. 4117117f1b4Smrg * Note that proxy textures are per-context, not per-texture unit. 4127117f1b4Smrg * \return pointer to texture image or NULL if invalid target, invalid 4137117f1b4Smrg * level, or out of memory. 4147117f1b4Smrg */ 415af69d88dSmrgstatic struct gl_texture_image * 416af69d88dSmrgget_proxy_tex_image(struct gl_context *ctx, GLenum target, GLint level) 4177117f1b4Smrg{ 4187117f1b4Smrg struct gl_texture_image *texImage; 4194a49301eSmrg GLuint texIndex; 4207117f1b4Smrg 421af69d88dSmrg if (level < 0) 4227117f1b4Smrg return NULL; 4237117f1b4Smrg 4247117f1b4Smrg switch (target) { 4257117f1b4Smrg case GL_PROXY_TEXTURE_1D: 4267117f1b4Smrg if (level >= ctx->Const.MaxTextureLevels) 4277117f1b4Smrg return NULL; 4284a49301eSmrg texIndex = TEXTURE_1D_INDEX; 4294a49301eSmrg break; 4307117f1b4Smrg case GL_PROXY_TEXTURE_2D: 4317117f1b4Smrg if (level >= ctx->Const.MaxTextureLevels) 4327117f1b4Smrg return NULL; 4334a49301eSmrg texIndex = TEXTURE_2D_INDEX; 4344a49301eSmrg break; 4357117f1b4Smrg case GL_PROXY_TEXTURE_3D: 4367117f1b4Smrg if (level >= ctx->Const.Max3DTextureLevels) 4377117f1b4Smrg return NULL; 4384a49301eSmrg texIndex = TEXTURE_3D_INDEX; 4394a49301eSmrg break; 4407117f1b4Smrg case GL_PROXY_TEXTURE_CUBE_MAP: 4417117f1b4Smrg if (level >= ctx->Const.MaxCubeTextureLevels) 4427117f1b4Smrg return NULL; 4434a49301eSmrg texIndex = TEXTURE_CUBE_INDEX; 4444a49301eSmrg break; 4457117f1b4Smrg case GL_PROXY_TEXTURE_RECTANGLE_NV: 4467117f1b4Smrg if (level > 0) 4477117f1b4Smrg return NULL; 4484a49301eSmrg texIndex = TEXTURE_RECT_INDEX; 4494a49301eSmrg break; 450c1f859d4Smrg case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 451c1f859d4Smrg if (level >= ctx->Const.MaxTextureLevels) 452c1f859d4Smrg return NULL; 4534a49301eSmrg texIndex = TEXTURE_1D_ARRAY_INDEX; 4544a49301eSmrg break; 455c1f859d4Smrg case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 456c1f859d4Smrg if (level >= ctx->Const.MaxTextureLevels) 457c1f859d4Smrg return NULL; 4584a49301eSmrg texIndex = TEXTURE_2D_ARRAY_INDEX; 4594a49301eSmrg break; 460af69d88dSmrg case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY: 461af69d88dSmrg if (level >= ctx->Const.MaxCubeTextureLevels) 462af69d88dSmrg return NULL; 463af69d88dSmrg texIndex = TEXTURE_CUBE_ARRAY_INDEX; 464af69d88dSmrg break; 465af69d88dSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE: 466af69d88dSmrg if (level > 0) 467af69d88dSmrg return 0; 468af69d88dSmrg texIndex = TEXTURE_2D_MULTISAMPLE_INDEX; 469af69d88dSmrg break; 470af69d88dSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY: 471af69d88dSmrg if (level > 0) 472af69d88dSmrg return 0; 473af69d88dSmrg texIndex = TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX; 474af69d88dSmrg break; 4757117f1b4Smrg default: 4767117f1b4Smrg return NULL; 4777117f1b4Smrg } 4784a49301eSmrg 4794a49301eSmrg texImage = ctx->Texture.ProxyTex[texIndex]->Image[0][level]; 4804a49301eSmrg if (!texImage) { 4814a49301eSmrg texImage = ctx->Driver.NewTextureImage(ctx); 4824a49301eSmrg if (!texImage) { 4834a49301eSmrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation"); 4844a49301eSmrg return NULL; 4854a49301eSmrg } 4864a49301eSmrg ctx->Texture.ProxyTex[texIndex]->Image[0][level] = texImage; 4874a49301eSmrg /* Set the 'back' pointer */ 4884a49301eSmrg texImage->TexObject = ctx->Texture.ProxyTex[texIndex]; 4894a49301eSmrg } 4904a49301eSmrg return texImage; 4917117f1b4Smrg} 4927117f1b4Smrg 4937117f1b4Smrg 4947117f1b4Smrg/** 4957117f1b4Smrg * Get the maximum number of allowed mipmap levels. 4967117f1b4Smrg * 4977117f1b4Smrg * \param ctx GL context. 4987117f1b4Smrg * \param target texture target. 499af69d88dSmrg * 5007117f1b4Smrg * \return the maximum number of allowed mipmap levels for the given 5017117f1b4Smrg * texture target, or zero if passed a bad target. 5027117f1b4Smrg * 5037117f1b4Smrg * \sa gl_constants. 5047117f1b4Smrg */ 5057117f1b4SmrgGLint 5063464ebd5Sriastradh_mesa_max_texture_levels(struct gl_context *ctx, GLenum target) 5077117f1b4Smrg{ 5087117f1b4Smrg switch (target) { 5097117f1b4Smrg case GL_TEXTURE_1D: 5107117f1b4Smrg case GL_PROXY_TEXTURE_1D: 5117117f1b4Smrg case GL_TEXTURE_2D: 5127117f1b4Smrg case GL_PROXY_TEXTURE_2D: 5137117f1b4Smrg return ctx->Const.MaxTextureLevels; 5147117f1b4Smrg case GL_TEXTURE_3D: 5157117f1b4Smrg case GL_PROXY_TEXTURE_3D: 5167117f1b4Smrg return ctx->Const.Max3DTextureLevels; 517af69d88dSmrg case GL_TEXTURE_CUBE_MAP: 51801e04c3fSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 51901e04c3fSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 52001e04c3fSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 52101e04c3fSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 52201e04c3fSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 52301e04c3fSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 52401e04c3fSmrg case GL_PROXY_TEXTURE_CUBE_MAP: 5254a49301eSmrg return ctx->Extensions.ARB_texture_cube_map 5264a49301eSmrg ? ctx->Const.MaxCubeTextureLevels : 0; 5277117f1b4Smrg case GL_TEXTURE_RECTANGLE_NV: 5287117f1b4Smrg case GL_PROXY_TEXTURE_RECTANGLE_NV: 5294a49301eSmrg return ctx->Extensions.NV_texture_rectangle ? 1 : 0; 5304a49301eSmrg case GL_TEXTURE_1D_ARRAY_EXT: 5314a49301eSmrg case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 5324a49301eSmrg case GL_TEXTURE_2D_ARRAY_EXT: 5334a49301eSmrg case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 534af69d88dSmrg return ctx->Extensions.EXT_texture_array 5354a49301eSmrg ? ctx->Const.MaxTextureLevels : 0; 536af69d88dSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: 537af69d88dSmrg case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY: 53801e04c3fSmrg return _mesa_has_texture_cube_map_array(ctx) 539af69d88dSmrg ? ctx->Const.MaxCubeTextureLevels : 0; 5403464ebd5Sriastradh case GL_TEXTURE_BUFFER: 54101e04c3fSmrg return (_mesa_has_ARB_texture_buffer_object(ctx) || 54201e04c3fSmrg _mesa_has_OES_texture_buffer(ctx)) ? 1 : 0; 543af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE: 544af69d88dSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE: 545af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 546af69d88dSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY: 54701e04c3fSmrg return (_mesa_is_desktop_gl(ctx) || _mesa_is_gles31(ctx)) 548af69d88dSmrg && ctx->Extensions.ARB_texture_multisample 549af69d88dSmrg ? 1 : 0; 550af69d88dSmrg case GL_TEXTURE_EXTERNAL_OES: 5513464ebd5Sriastradh /* fall-through */ 5527117f1b4Smrg default: 5537117f1b4Smrg return 0; /* bad target */ 5547117f1b4Smrg } 5557117f1b4Smrg} 5567117f1b4Smrg 5577117f1b4Smrg 5583464ebd5Sriastradh/** 5593464ebd5Sriastradh * Return number of dimensions per mipmap level for the given texture target. 5603464ebd5Sriastradh */ 5613464ebd5SriastradhGLint 5623464ebd5Sriastradh_mesa_get_texture_dimensions(GLenum target) 5633464ebd5Sriastradh{ 5643464ebd5Sriastradh switch (target) { 5653464ebd5Sriastradh case GL_TEXTURE_1D: 5663464ebd5Sriastradh case GL_PROXY_TEXTURE_1D: 5673464ebd5Sriastradh return 1; 5683464ebd5Sriastradh case GL_TEXTURE_2D: 5693464ebd5Sriastradh case GL_TEXTURE_RECTANGLE: 5703464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP: 5713464ebd5Sriastradh case GL_PROXY_TEXTURE_2D: 5723464ebd5Sriastradh case GL_PROXY_TEXTURE_RECTANGLE: 5733464ebd5Sriastradh case GL_PROXY_TEXTURE_CUBE_MAP: 5743464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 5753464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 5763464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 5773464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 5783464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 5793464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 5803464ebd5Sriastradh case GL_TEXTURE_1D_ARRAY: 5813464ebd5Sriastradh case GL_PROXY_TEXTURE_1D_ARRAY: 582af69d88dSmrg case GL_TEXTURE_EXTERNAL_OES: 583af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE: 584af69d88dSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE: 5853464ebd5Sriastradh return 2; 5863464ebd5Sriastradh case GL_TEXTURE_3D: 5873464ebd5Sriastradh case GL_PROXY_TEXTURE_3D: 5883464ebd5Sriastradh case GL_TEXTURE_2D_ARRAY: 5893464ebd5Sriastradh case GL_PROXY_TEXTURE_2D_ARRAY: 590af69d88dSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: 591af69d88dSmrg case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY: 592af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 593af69d88dSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY: 5943464ebd5Sriastradh return 3; 5953464ebd5Sriastradh case GL_TEXTURE_BUFFER: 5963464ebd5Sriastradh /* fall-through */ 5973464ebd5Sriastradh default: 5983464ebd5Sriastradh _mesa_problem(NULL, "invalid target 0x%x in get_texture_dimensions()", 5993464ebd5Sriastradh target); 6003464ebd5Sriastradh return 2; 6013464ebd5Sriastradh } 6023464ebd5Sriastradh} 6033464ebd5Sriastradh 6043464ebd5Sriastradh 605af69d88dSmrg/** 606af69d88dSmrg * Check if a texture target can have more than one layer. 607af69d88dSmrg */ 608af69d88dSmrgGLboolean 609af69d88dSmrg_mesa_tex_target_is_layered(GLenum target) 610af69d88dSmrg{ 611af69d88dSmrg switch (target) { 612af69d88dSmrg case GL_TEXTURE_1D: 613af69d88dSmrg case GL_PROXY_TEXTURE_1D: 614af69d88dSmrg case GL_TEXTURE_2D: 615af69d88dSmrg case GL_PROXY_TEXTURE_2D: 616af69d88dSmrg case GL_TEXTURE_RECTANGLE: 617af69d88dSmrg case GL_PROXY_TEXTURE_RECTANGLE: 618af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE: 619af69d88dSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE: 620af69d88dSmrg case GL_TEXTURE_BUFFER: 621af69d88dSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 622af69d88dSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 623af69d88dSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 624af69d88dSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 625af69d88dSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 626af69d88dSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 627af69d88dSmrg case GL_TEXTURE_EXTERNAL_OES: 628af69d88dSmrg return GL_FALSE; 629af69d88dSmrg 630af69d88dSmrg case GL_TEXTURE_3D: 631af69d88dSmrg case GL_PROXY_TEXTURE_3D: 632af69d88dSmrg case GL_TEXTURE_CUBE_MAP: 633af69d88dSmrg case GL_PROXY_TEXTURE_CUBE_MAP: 634af69d88dSmrg case GL_TEXTURE_1D_ARRAY: 635af69d88dSmrg case GL_PROXY_TEXTURE_1D_ARRAY: 636af69d88dSmrg case GL_TEXTURE_2D_ARRAY: 637af69d88dSmrg case GL_PROXY_TEXTURE_2D_ARRAY: 638af69d88dSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: 639af69d88dSmrg case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY: 640af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 641af69d88dSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY: 642af69d88dSmrg return GL_TRUE; 643af69d88dSmrg 644af69d88dSmrg default: 645af69d88dSmrg assert(!"Invalid texture target."); 646af69d88dSmrg return GL_FALSE; 647af69d88dSmrg } 648af69d88dSmrg} 649af69d88dSmrg 650af69d88dSmrg 651af69d88dSmrg/** 652af69d88dSmrg * Return the number of layers present in the given level of an array, 653af69d88dSmrg * cubemap or 3D texture. If the texture is not layered return zero. 654af69d88dSmrg */ 655af69d88dSmrgGLuint 656af69d88dSmrg_mesa_get_texture_layers(const struct gl_texture_object *texObj, GLint level) 657af69d88dSmrg{ 658af69d88dSmrg assert(level >= 0 && level < MAX_TEXTURE_LEVELS); 659af69d88dSmrg 660af69d88dSmrg switch (texObj->Target) { 661af69d88dSmrg case GL_TEXTURE_1D: 662af69d88dSmrg case GL_TEXTURE_2D: 663af69d88dSmrg case GL_TEXTURE_RECTANGLE: 664af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE: 665af69d88dSmrg case GL_TEXTURE_BUFFER: 666af69d88dSmrg case GL_TEXTURE_EXTERNAL_OES: 667af69d88dSmrg return 0; 668af69d88dSmrg 669af69d88dSmrg case GL_TEXTURE_CUBE_MAP: 670af69d88dSmrg return 6; 671af69d88dSmrg 672af69d88dSmrg case GL_TEXTURE_1D_ARRAY: { 673af69d88dSmrg struct gl_texture_image *img = texObj->Image[0][level]; 674af69d88dSmrg return img ? img->Height : 0; 675af69d88dSmrg } 676af69d88dSmrg 677af69d88dSmrg case GL_TEXTURE_3D: 678af69d88dSmrg case GL_TEXTURE_2D_ARRAY: 679af69d88dSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: 680af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: { 681af69d88dSmrg struct gl_texture_image *img = texObj->Image[0][level]; 682af69d88dSmrg return img ? img->Depth : 0; 683af69d88dSmrg } 684af69d88dSmrg 685af69d88dSmrg default: 686af69d88dSmrg assert(!"Invalid texture target."); 687af69d88dSmrg return 0; 688af69d88dSmrg } 689af69d88dSmrg} 690af69d88dSmrg 691af69d88dSmrg 692af69d88dSmrg/** 693af69d88dSmrg * Return the maximum number of mipmap levels for the given target 694af69d88dSmrg * and the dimensions. 695af69d88dSmrg * The dimensions are expected not to include the border. 696af69d88dSmrg */ 697af69d88dSmrgGLsizei 698af69d88dSmrg_mesa_get_tex_max_num_levels(GLenum target, GLsizei width, GLsizei height, 699af69d88dSmrg GLsizei depth) 700af69d88dSmrg{ 701af69d88dSmrg GLsizei size; 702af69d88dSmrg 703af69d88dSmrg switch (target) { 704af69d88dSmrg case GL_TEXTURE_1D: 705af69d88dSmrg case GL_TEXTURE_1D_ARRAY: 706af69d88dSmrg case GL_PROXY_TEXTURE_1D: 707af69d88dSmrg case GL_PROXY_TEXTURE_1D_ARRAY: 708af69d88dSmrg size = width; 709af69d88dSmrg break; 710af69d88dSmrg case GL_TEXTURE_CUBE_MAP: 711af69d88dSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: 712af69d88dSmrg case GL_PROXY_TEXTURE_CUBE_MAP: 713af69d88dSmrg case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY: 714af69d88dSmrg size = width; 715af69d88dSmrg break; 716af69d88dSmrg case GL_TEXTURE_2D: 717af69d88dSmrg case GL_TEXTURE_2D_ARRAY: 718af69d88dSmrg case GL_PROXY_TEXTURE_2D: 719af69d88dSmrg case GL_PROXY_TEXTURE_2D_ARRAY: 720af69d88dSmrg size = MAX2(width, height); 721af69d88dSmrg break; 722af69d88dSmrg case GL_TEXTURE_3D: 723af69d88dSmrg case GL_PROXY_TEXTURE_3D: 724af69d88dSmrg size = MAX3(width, height, depth); 725af69d88dSmrg break; 726af69d88dSmrg case GL_TEXTURE_RECTANGLE: 727af69d88dSmrg case GL_TEXTURE_EXTERNAL_OES: 728af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE: 729af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 730af69d88dSmrg case GL_PROXY_TEXTURE_RECTANGLE: 731af69d88dSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE: 732af69d88dSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY: 733af69d88dSmrg return 1; 734af69d88dSmrg default: 735af69d88dSmrg assert(0); 736af69d88dSmrg return 1; 737af69d88dSmrg } 738af69d88dSmrg 739af69d88dSmrg return _mesa_logbase2(size) + 1; 740af69d88dSmrg} 7413464ebd5Sriastradh 7427117f1b4Smrg 7437117f1b4Smrg#if 000 /* not used anymore */ 7447117f1b4Smrg/* 7457117f1b4Smrg * glTexImage[123]D can accept a NULL image pointer. In this case we 7467117f1b4Smrg * create a texture image with unspecified image contents per the OpenGL 7477117f1b4Smrg * spec. 7487117f1b4Smrg */ 7497117f1b4Smrgstatic GLubyte * 7507117f1b4Smrgmake_null_texture(GLint width, GLint height, GLint depth, GLenum format) 7517117f1b4Smrg{ 7527117f1b4Smrg const GLint components = _mesa_components_in_format(format); 7537117f1b4Smrg const GLint numPixels = width * height * depth; 754af69d88dSmrg GLubyte *data = (GLubyte *) malloc(numPixels * components * sizeof(GLubyte)); 7557117f1b4Smrg 7567117f1b4Smrg#ifdef DEBUG 7577117f1b4Smrg /* 7587117f1b4Smrg * Let's see if anyone finds this. If glTexImage2D() is called with 7597117f1b4Smrg * a NULL image pointer then load the texture image with something 7607117f1b4Smrg * interesting instead of leaving it indeterminate. 7617117f1b4Smrg */ 7627117f1b4Smrg if (data) { 7637117f1b4Smrg static const char message[8][32] = { 7647117f1b4Smrg " X X XXXXX XXX X ", 7657117f1b4Smrg " XX XX X X X X X ", 7667117f1b4Smrg " X X X X X X X ", 7677117f1b4Smrg " X X XXXX XXX XXXXX ", 7687117f1b4Smrg " X X X X X X ", 7697117f1b4Smrg " X X X X X X X ", 7707117f1b4Smrg " X X XXXXX XXX X X ", 7717117f1b4Smrg " " 7727117f1b4Smrg }; 7737117f1b4Smrg 7747117f1b4Smrg GLubyte *imgPtr = data; 7757117f1b4Smrg GLint h, i, j, k; 7767117f1b4Smrg for (h = 0; h < depth; h++) { 7777117f1b4Smrg for (i = 0; i < height; i++) { 7787117f1b4Smrg GLint srcRow = 7 - (i % 8); 7797117f1b4Smrg for (j = 0; j < width; j++) { 7807117f1b4Smrg GLint srcCol = j % 32; 7817117f1b4Smrg GLubyte texel = (message[srcRow][srcCol]=='X') ? 255 : 70; 7827117f1b4Smrg for (k = 0; k < components; k++) { 7837117f1b4Smrg *imgPtr++ = texel; 7847117f1b4Smrg } 7857117f1b4Smrg } 7867117f1b4Smrg } 7877117f1b4Smrg } 7887117f1b4Smrg } 7897117f1b4Smrg#endif 7907117f1b4Smrg 7917117f1b4Smrg return data; 7927117f1b4Smrg} 7937117f1b4Smrg#endif 7947117f1b4Smrg 7957117f1b4Smrg 7967117f1b4Smrg 7977117f1b4Smrg/** 798af69d88dSmrg * Set the size and format-related fields of a gl_texture_image struct 799af69d88dSmrg * to zero. This is used when a proxy texture test fails. 8007117f1b4Smrg */ 8017117f1b4Smrgstatic void 8027117f1b4Smrgclear_teximage_fields(struct gl_texture_image *img) 8037117f1b4Smrg{ 80401e04c3fSmrg assert(img); 8057117f1b4Smrg img->_BaseFormat = 0; 8067117f1b4Smrg img->InternalFormat = 0; 8077117f1b4Smrg img->Border = 0; 8087117f1b4Smrg img->Width = 0; 8097117f1b4Smrg img->Height = 0; 8107117f1b4Smrg img->Depth = 0; 8117117f1b4Smrg img->Width2 = 0; 8127117f1b4Smrg img->Height2 = 0; 8137117f1b4Smrg img->Depth2 = 0; 8147117f1b4Smrg img->WidthLog2 = 0; 8157117f1b4Smrg img->HeightLog2 = 0; 8167117f1b4Smrg img->DepthLog2 = 0; 8174a49301eSmrg img->TexFormat = MESA_FORMAT_NONE; 818af69d88dSmrg img->NumSamples = 0; 819af69d88dSmrg img->FixedSampleLocations = GL_TRUE; 8207117f1b4Smrg} 8217117f1b4Smrg 8227117f1b4Smrg 8237117f1b4Smrg/** 8247117f1b4Smrg * Initialize basic fields of the gl_texture_image struct. 8257117f1b4Smrg * 8267117f1b4Smrg * \param ctx GL context. 8277117f1b4Smrg * \param img texture image structure to be initialized. 8287117f1b4Smrg * \param width image width. 8297117f1b4Smrg * \param height image height. 8307117f1b4Smrg * \param depth image depth. 8317117f1b4Smrg * \param border image border. 8327117f1b4Smrg * \param internalFormat internal format. 8333464ebd5Sriastradh * \param format the actual hardware format (one of MESA_FORMAT_*) 834af69d88dSmrg * \param numSamples number of samples per texel, or zero for non-MS. 835af69d88dSmrg * \param fixedSampleLocations are sample locations fixed? 8367117f1b4Smrg * 8377117f1b4Smrg * Fills in the fields of \p img with the given information. 8387117f1b4Smrg * Note: width, height and depth include the border. 8397117f1b4Smrg */ 84001e04c3fSmrgvoid 84101e04c3fSmrg_mesa_init_teximage_fields_ms(struct gl_context *ctx, 842af69d88dSmrg struct gl_texture_image *img, 843af69d88dSmrg GLsizei width, GLsizei height, GLsizei depth, 844af69d88dSmrg GLint border, GLenum internalFormat, 845af69d88dSmrg mesa_format format, 846af69d88dSmrg GLuint numSamples, GLboolean fixedSampleLocations) 8477117f1b4Smrg{ 84801e04c3fSmrg const GLint base_format =_mesa_base_tex_format(ctx, internalFormat); 849af69d88dSmrg GLenum target; 85001e04c3fSmrg assert(img); 85101e04c3fSmrg assert(width >= 0); 85201e04c3fSmrg assert(height >= 0); 85301e04c3fSmrg assert(depth >= 0); 8547117f1b4Smrg 855af69d88dSmrg target = img->TexObject->Target; 85601e04c3fSmrg assert(base_format != -1); 85701e04c3fSmrg img->_BaseFormat = (GLenum16)base_format; 8587117f1b4Smrg img->InternalFormat = internalFormat; 8597117f1b4Smrg img->Border = border; 8607117f1b4Smrg img->Width = width; 8617117f1b4Smrg img->Height = height; 8627117f1b4Smrg img->Depth = depth; 8634a49301eSmrg 8647117f1b4Smrg img->Width2 = width - 2 * border; /* == 1 << img->WidthLog2; */ 8653464ebd5Sriastradh img->WidthLog2 = _mesa_logbase2(img->Width2); 8664a49301eSmrg 867af69d88dSmrg switch(target) { 868af69d88dSmrg case GL_TEXTURE_1D: 869af69d88dSmrg case GL_TEXTURE_BUFFER: 870af69d88dSmrg case GL_PROXY_TEXTURE_1D: 871af69d88dSmrg if (height == 0) 872af69d88dSmrg img->Height2 = 0; 873af69d88dSmrg else 874af69d88dSmrg img->Height2 = 1; 8757117f1b4Smrg img->HeightLog2 = 0; 876af69d88dSmrg if (depth == 0) 877af69d88dSmrg img->Depth2 = 0; 878af69d88dSmrg else 879af69d88dSmrg img->Depth2 = 1; 880af69d88dSmrg img->DepthLog2 = 0; 881af69d88dSmrg break; 882af69d88dSmrg case GL_TEXTURE_1D_ARRAY: 883af69d88dSmrg case GL_PROXY_TEXTURE_1D_ARRAY: 884af69d88dSmrg img->Height2 = height; /* no border */ 885af69d88dSmrg img->HeightLog2 = 0; /* not used */ 886af69d88dSmrg if (depth == 0) 887af69d88dSmrg img->Depth2 = 0; 888af69d88dSmrg else 889af69d88dSmrg img->Depth2 = 1; 890af69d88dSmrg img->DepthLog2 = 0; 891af69d88dSmrg break; 892af69d88dSmrg case GL_TEXTURE_2D: 893af69d88dSmrg case GL_TEXTURE_RECTANGLE: 894af69d88dSmrg case GL_TEXTURE_CUBE_MAP: 895af69d88dSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 896af69d88dSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 897af69d88dSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 898af69d88dSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 899af69d88dSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 900af69d88dSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 901af69d88dSmrg case GL_TEXTURE_EXTERNAL_OES: 902af69d88dSmrg case GL_PROXY_TEXTURE_2D: 903af69d88dSmrg case GL_PROXY_TEXTURE_RECTANGLE: 904af69d88dSmrg case GL_PROXY_TEXTURE_CUBE_MAP: 905af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE: 906af69d88dSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE: 9074a49301eSmrg img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */ 9083464ebd5Sriastradh img->HeightLog2 = _mesa_logbase2(img->Height2); 909af69d88dSmrg if (depth == 0) 910af69d88dSmrg img->Depth2 = 0; 911af69d88dSmrg else 912af69d88dSmrg img->Depth2 = 1; 9137117f1b4Smrg img->DepthLog2 = 0; 914af69d88dSmrg break; 915af69d88dSmrg case GL_TEXTURE_2D_ARRAY: 916af69d88dSmrg case GL_PROXY_TEXTURE_2D_ARRAY: 917af69d88dSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: 918af69d88dSmrg case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY: 919af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 920af69d88dSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY: 921af69d88dSmrg img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */ 922af69d88dSmrg img->HeightLog2 = _mesa_logbase2(img->Height2); 923af69d88dSmrg img->Depth2 = depth; /* no border */ 924af69d88dSmrg img->DepthLog2 = 0; /* not used */ 925af69d88dSmrg break; 926af69d88dSmrg case GL_TEXTURE_3D: 927af69d88dSmrg case GL_PROXY_TEXTURE_3D: 928af69d88dSmrg img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */ 929af69d88dSmrg img->HeightLog2 = _mesa_logbase2(img->Height2); 930af69d88dSmrg img->Depth2 = depth - 2 * border; /* == 1 << img->DepthLog2; */ 931af69d88dSmrg img->DepthLog2 = _mesa_logbase2(img->Depth2); 932af69d88dSmrg break; 933af69d88dSmrg default: 934af69d88dSmrg _mesa_problem(NULL, "invalid target 0x%x in _mesa_init_teximage_fields()", 935af69d88dSmrg target); 9367117f1b4Smrg } 9374a49301eSmrg 938af69d88dSmrg img->MaxNumLevels = 939af69d88dSmrg _mesa_get_tex_max_num_levels(target, 940af69d88dSmrg img->Width2, img->Height2, img->Depth2); 9413464ebd5Sriastradh img->TexFormat = format; 942af69d88dSmrg img->NumSamples = numSamples; 943af69d88dSmrg img->FixedSampleLocations = fixedSampleLocations; 944af69d88dSmrg} 9453464ebd5Sriastradh 9463464ebd5Sriastradh 947af69d88dSmrgvoid 948af69d88dSmrg_mesa_init_teximage_fields(struct gl_context *ctx, 949af69d88dSmrg struct gl_texture_image *img, 950af69d88dSmrg GLsizei width, GLsizei height, GLsizei depth, 951af69d88dSmrg GLint border, GLenum internalFormat, 952af69d88dSmrg mesa_format format) 953af69d88dSmrg{ 95401e04c3fSmrg _mesa_init_teximage_fields_ms(ctx, img, width, height, depth, border, 95501e04c3fSmrg internalFormat, format, 0, GL_TRUE); 9564a49301eSmrg} 9574a49301eSmrg 9584a49301eSmrg 9594a49301eSmrg/** 9604a49301eSmrg * Free and clear fields of the gl_texture_image struct. 9614a49301eSmrg * 9624a49301eSmrg * \param ctx GL context. 9634a49301eSmrg * \param texImage texture image structure to be cleared. 9644a49301eSmrg * 9654a49301eSmrg * After the call, \p texImage will have no data associated with it. Its 9664a49301eSmrg * fields are cleared so that its parent object will test incomplete. 9674a49301eSmrg */ 9684a49301eSmrgvoid 9693464ebd5Sriastradh_mesa_clear_texture_image(struct gl_context *ctx, 9703464ebd5Sriastradh struct gl_texture_image *texImage) 9714a49301eSmrg{ 972af69d88dSmrg ctx->Driver.FreeTextureImageBuffer(ctx, texImage); 9734a49301eSmrg clear_teximage_fields(texImage); 9747117f1b4Smrg} 9757117f1b4Smrg 9767117f1b4Smrg 9777117f1b4Smrg/** 978af69d88dSmrg * Check the width, height, depth and border of a texture image are legal. 979af69d88dSmrg * Used by all the glTexImage, glCompressedTexImage and glCopyTexImage 980af69d88dSmrg * functions. 981af69d88dSmrg * The target and level parameters will have already been validated. 982af69d88dSmrg * \return GL_TRUE if size is OK, GL_FALSE otherwise. 9837117f1b4Smrg */ 9847117f1b4SmrgGLboolean 985af69d88dSmrg_mesa_legal_texture_dimensions(struct gl_context *ctx, GLenum target, 986af69d88dSmrg GLint level, GLint width, GLint height, 987af69d88dSmrg GLint depth, GLint border) 9887117f1b4Smrg{ 9897117f1b4Smrg GLint maxSize; 9907117f1b4Smrg 9917117f1b4Smrg switch (target) { 992af69d88dSmrg case GL_TEXTURE_1D: 9937117f1b4Smrg case GL_PROXY_TEXTURE_1D: 994af69d88dSmrg maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); /* level zero size */ 995af69d88dSmrg maxSize >>= level; /* level size */ 996af69d88dSmrg if (width < 2 * border || width > 2 * border + maxSize) 9977117f1b4Smrg return GL_FALSE; 9983464ebd5Sriastradh if (!ctx->Extensions.ARB_texture_non_power_of_two) { 9993464ebd5Sriastradh if (width > 0 && !_mesa_is_pow_two(width - 2 * border)) 10003464ebd5Sriastradh return GL_FALSE; 10017117f1b4Smrg } 10027117f1b4Smrg return GL_TRUE; 10033464ebd5Sriastradh 1004af69d88dSmrg case GL_TEXTURE_2D: 10057117f1b4Smrg case GL_PROXY_TEXTURE_2D: 1006af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE: 1007af69d88dSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE: 10087117f1b4Smrg maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 1009af69d88dSmrg maxSize >>= level; 1010af69d88dSmrg if (width < 2 * border || width > 2 * border + maxSize) 10113464ebd5Sriastradh return GL_FALSE; 1012af69d88dSmrg if (height < 2 * border || height > 2 * border + maxSize) 10137117f1b4Smrg return GL_FALSE; 10143464ebd5Sriastradh if (!ctx->Extensions.ARB_texture_non_power_of_two) { 10153464ebd5Sriastradh if (width > 0 && !_mesa_is_pow_two(width - 2 * border)) 10163464ebd5Sriastradh return GL_FALSE; 10173464ebd5Sriastradh if (height > 0 && !_mesa_is_pow_two(height - 2 * border)) 10183464ebd5Sriastradh return GL_FALSE; 10197117f1b4Smrg } 10207117f1b4Smrg return GL_TRUE; 10213464ebd5Sriastradh 1022af69d88dSmrg case GL_TEXTURE_3D: 10237117f1b4Smrg case GL_PROXY_TEXTURE_3D: 10247117f1b4Smrg maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1); 1025af69d88dSmrg maxSize >>= level; 1026af69d88dSmrg if (width < 2 * border || width > 2 * border + maxSize) 10273464ebd5Sriastradh return GL_FALSE; 1028af69d88dSmrg if (height < 2 * border || height > 2 * border + maxSize) 10297117f1b4Smrg return GL_FALSE; 1030af69d88dSmrg if (depth < 2 * border || depth > 2 * border + maxSize) 10313464ebd5Sriastradh return GL_FALSE; 10323464ebd5Sriastradh if (!ctx->Extensions.ARB_texture_non_power_of_two) { 10333464ebd5Sriastradh if (width > 0 && !_mesa_is_pow_two(width - 2 * border)) 10343464ebd5Sriastradh return GL_FALSE; 10353464ebd5Sriastradh if (height > 0 && !_mesa_is_pow_two(height - 2 * border)) 10363464ebd5Sriastradh return GL_FALSE; 10373464ebd5Sriastradh if (depth > 0 && !_mesa_is_pow_two(depth - 2 * border)) 10383464ebd5Sriastradh return GL_FALSE; 10397117f1b4Smrg } 10407117f1b4Smrg return GL_TRUE; 10413464ebd5Sriastradh 1042af69d88dSmrg case GL_TEXTURE_RECTANGLE_NV: 10437117f1b4Smrg case GL_PROXY_TEXTURE_RECTANGLE_NV: 1044af69d88dSmrg if (level != 0) 1045af69d88dSmrg return GL_FALSE; 10463464ebd5Sriastradh maxSize = ctx->Const.MaxTextureRectSize; 10473464ebd5Sriastradh if (width < 0 || width > maxSize) 10483464ebd5Sriastradh return GL_FALSE; 10493464ebd5Sriastradh if (height < 0 || height > maxSize) 10503464ebd5Sriastradh return GL_FALSE; 10517117f1b4Smrg return GL_TRUE; 10523464ebd5Sriastradh 1053af69d88dSmrg case GL_TEXTURE_CUBE_MAP: 1054af69d88dSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 1055af69d88dSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 1056af69d88dSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 1057af69d88dSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 1058af69d88dSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 1059af69d88dSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 106001e04c3fSmrg case GL_PROXY_TEXTURE_CUBE_MAP: 10617117f1b4Smrg maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1); 1062af69d88dSmrg maxSize >>= level; 1063af69d88dSmrg if (width != height) 10643464ebd5Sriastradh return GL_FALSE; 1065af69d88dSmrg if (width < 2 * border || width > 2 * border + maxSize) 10667117f1b4Smrg return GL_FALSE; 1067af69d88dSmrg if (height < 2 * border || height > 2 * border + maxSize) 10683464ebd5Sriastradh return GL_FALSE; 10693464ebd5Sriastradh if (!ctx->Extensions.ARB_texture_non_power_of_two) { 10703464ebd5Sriastradh if (width > 0 && !_mesa_is_pow_two(width - 2 * border)) 10713464ebd5Sriastradh return GL_FALSE; 10723464ebd5Sriastradh if (height > 0 && !_mesa_is_pow_two(height - 2 * border)) 10733464ebd5Sriastradh return GL_FALSE; 10747117f1b4Smrg } 10757117f1b4Smrg return GL_TRUE; 10763464ebd5Sriastradh 1077af69d88dSmrg case GL_TEXTURE_1D_ARRAY_EXT: 1078c1f859d4Smrg case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 1079c1f859d4Smrg maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 1080af69d88dSmrg maxSize >>= level; 1081af69d88dSmrg if (width < 2 * border || width > 2 * border + maxSize) 10823464ebd5Sriastradh return GL_FALSE; 1083af69d88dSmrg if (height < 0 || height > ctx->Const.MaxArrayTextureLayers) 1084c1f859d4Smrg return GL_FALSE; 10853464ebd5Sriastradh if (!ctx->Extensions.ARB_texture_non_power_of_two) { 10863464ebd5Sriastradh if (width > 0 && !_mesa_is_pow_two(width - 2 * border)) 10873464ebd5Sriastradh return GL_FALSE; 1088c1f859d4Smrg } 1089c1f859d4Smrg return GL_TRUE; 10903464ebd5Sriastradh 1091af69d88dSmrg case GL_TEXTURE_2D_ARRAY_EXT: 1092c1f859d4Smrg case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 1093af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 1094af69d88dSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY: 1095c1f859d4Smrg maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 1096af69d88dSmrg maxSize >>= level; 1097af69d88dSmrg if (width < 2 * border || width > 2 * border + maxSize) 1098c1f859d4Smrg return GL_FALSE; 1099af69d88dSmrg if (height < 2 * border || height > 2 * border + maxSize) 11003464ebd5Sriastradh return GL_FALSE; 1101af69d88dSmrg if (depth < 0 || depth > ctx->Const.MaxArrayTextureLayers) 1102c1f859d4Smrg return GL_FALSE; 11033464ebd5Sriastradh if (!ctx->Extensions.ARB_texture_non_power_of_two) { 11043464ebd5Sriastradh if (width > 0 && !_mesa_is_pow_two(width - 2 * border)) 11053464ebd5Sriastradh return GL_FALSE; 11063464ebd5Sriastradh if (height > 0 && !_mesa_is_pow_two(height - 2 * border)) 11073464ebd5Sriastradh return GL_FALSE; 1108c1f859d4Smrg } 1109c1f859d4Smrg return GL_TRUE; 11103464ebd5Sriastradh 1111af69d88dSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: 1112af69d88dSmrg case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY: 1113af69d88dSmrg maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1); 1114af69d88dSmrg if (width < 2 * border || width > 2 * border + maxSize) 1115af69d88dSmrg return GL_FALSE; 1116af69d88dSmrg if (height < 2 * border || height > 2 * border + maxSize) 1117af69d88dSmrg return GL_FALSE; 1118af69d88dSmrg if (depth < 0 || depth > ctx->Const.MaxArrayTextureLayers || depth % 6) 1119af69d88dSmrg return GL_FALSE; 1120af69d88dSmrg if (width != height) 1121af69d88dSmrg return GL_FALSE; 1122af69d88dSmrg if (level >= ctx->Const.MaxCubeTextureLevels) 1123af69d88dSmrg return GL_FALSE; 1124af69d88dSmrg if (!ctx->Extensions.ARB_texture_non_power_of_two) { 1125af69d88dSmrg if (width > 0 && !_mesa_is_pow_two(width - 2 * border)) 1126af69d88dSmrg return GL_FALSE; 1127af69d88dSmrg if (height > 0 && !_mesa_is_pow_two(height - 2 * border)) 1128af69d88dSmrg return GL_FALSE; 1129af69d88dSmrg } 1130af69d88dSmrg return GL_TRUE; 11317117f1b4Smrg default: 1132af69d88dSmrg _mesa_problem(ctx, "Invalid target in _mesa_legal_texture_dimensions()"); 11337117f1b4Smrg return GL_FALSE; 11347117f1b4Smrg } 11357117f1b4Smrg} 11367117f1b4Smrg 113701e04c3fSmrgstatic bool 113801e04c3fSmrgerror_check_subtexture_negative_dimensions(struct gl_context *ctx, 113901e04c3fSmrg GLuint dims, 114001e04c3fSmrg GLsizei subWidth, 114101e04c3fSmrg GLsizei subHeight, 114201e04c3fSmrg GLsizei subDepth, 114301e04c3fSmrg const char *func) 114401e04c3fSmrg{ 114501e04c3fSmrg /* Check size */ 114601e04c3fSmrg if (subWidth < 0) { 114701e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(width=%d)", func, subWidth); 114801e04c3fSmrg return true; 114901e04c3fSmrg } 115001e04c3fSmrg 115101e04c3fSmrg if (dims > 1 && subHeight < 0) { 115201e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(height=%d)", func, subHeight); 115301e04c3fSmrg return true; 115401e04c3fSmrg } 115501e04c3fSmrg 115601e04c3fSmrg if (dims > 2 && subDepth < 0) { 115701e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(depth=%d)", func, subDepth); 115801e04c3fSmrg return true; 115901e04c3fSmrg } 116001e04c3fSmrg 116101e04c3fSmrg return false; 116201e04c3fSmrg} 11637117f1b4Smrg 11647117f1b4Smrg/** 1165af69d88dSmrg * Do error checking of xoffset, yoffset, zoffset, width, height and depth 1166af69d88dSmrg * for glTexSubImage, glCopyTexSubImage and glCompressedTexSubImage. 1167af69d88dSmrg * \param destImage the destination texture image. 1168af69d88dSmrg * \return GL_TRUE if error found, GL_FALSE otherwise. 11697117f1b4Smrg */ 11707117f1b4Smrgstatic GLboolean 117101e04c3fSmrgerror_check_subtexture_dimensions(struct gl_context *ctx, GLuint dims, 1172af69d88dSmrg const struct gl_texture_image *destImage, 1173af69d88dSmrg GLint xoffset, GLint yoffset, GLint zoffset, 1174af69d88dSmrg GLsizei subWidth, GLsizei subHeight, 117501e04c3fSmrg GLsizei subDepth, const char *func) 1176af69d88dSmrg{ 1177af69d88dSmrg const GLenum target = destImage->TexObject->Target; 117801e04c3fSmrg GLuint bw, bh, bd; 1179af69d88dSmrg 1180af69d88dSmrg /* check xoffset and width */ 1181af69d88dSmrg if (xoffset < - (GLint) destImage->Border) { 118201e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(xoffset)", func); 1183af69d88dSmrg return GL_TRUE; 1184af69d88dSmrg } 1185af69d88dSmrg 1186af69d88dSmrg if (xoffset + subWidth > (GLint) destImage->Width) { 118701e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(xoffset %d + width %d > %u)", func, 118801e04c3fSmrg xoffset, subWidth, destImage->Width); 1189af69d88dSmrg return GL_TRUE; 1190af69d88dSmrg } 1191af69d88dSmrg 1192af69d88dSmrg /* check yoffset and height */ 1193af69d88dSmrg if (dims > 1) { 1194af69d88dSmrg GLint yBorder = (target == GL_TEXTURE_1D_ARRAY) ? 0 : destImage->Border; 1195af69d88dSmrg if (yoffset < -yBorder) { 119601e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(yoffset)", func); 1197af69d88dSmrg return GL_TRUE; 1198af69d88dSmrg } 1199af69d88dSmrg if (yoffset + subHeight > (GLint) destImage->Height) { 120001e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(yoffset %d + height %d > %u)", 120101e04c3fSmrg func, yoffset, subHeight, destImage->Height); 1202af69d88dSmrg return GL_TRUE; 1203af69d88dSmrg } 1204af69d88dSmrg } 1205af69d88dSmrg 1206af69d88dSmrg /* check zoffset and depth */ 1207af69d88dSmrg if (dims > 2) { 120801e04c3fSmrg GLint depth; 1209af69d88dSmrg GLint zBorder = (target == GL_TEXTURE_2D_ARRAY || 1210af69d88dSmrg target == GL_TEXTURE_CUBE_MAP_ARRAY) ? 1211af69d88dSmrg 0 : destImage->Border; 1212af69d88dSmrg 1213af69d88dSmrg if (zoffset < -zBorder) { 121401e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(zoffset)", func); 1215af69d88dSmrg return GL_TRUE; 1216af69d88dSmrg } 121701e04c3fSmrg 121801e04c3fSmrg depth = (GLint) destImage->Depth; 121901e04c3fSmrg if (target == GL_TEXTURE_CUBE_MAP) 122001e04c3fSmrg depth = 6; 122101e04c3fSmrg if (zoffset + subDepth > depth) { 122201e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(zoffset %d + depth %d > %u)", 122301e04c3fSmrg func, zoffset, subDepth, depth); 1224af69d88dSmrg return GL_TRUE; 1225af69d88dSmrg } 1226af69d88dSmrg } 1227af69d88dSmrg 1228af69d88dSmrg /* 1229af69d88dSmrg * The OpenGL spec (and GL_ARB_texture_compression) says only whole 1230af69d88dSmrg * compressed texture images can be updated. But, that restriction may be 1231af69d88dSmrg * relaxed for particular compressed formats. At this time, all the 1232af69d88dSmrg * compressed formats supported by Mesa allow sub-textures to be updated 1233af69d88dSmrg * along compressed block boundaries. 1234af69d88dSmrg */ 123501e04c3fSmrg _mesa_get_format_block_size_3d(destImage->TexFormat, &bw, &bh, &bd); 1236af69d88dSmrg 123701e04c3fSmrg if (bw != 1 || bh != 1 || bd != 1) { 1238af69d88dSmrg /* offset must be multiple of block size */ 123901e04c3fSmrg if ((xoffset % bw != 0) || (yoffset % bh != 0) || (zoffset % bd != 0)) { 1240af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 124101e04c3fSmrg "%s(xoffset = %d, yoffset = %d, zoffset = %d)", 124201e04c3fSmrg func, xoffset, yoffset, zoffset); 1243af69d88dSmrg return GL_TRUE; 1244af69d88dSmrg } 1245af69d88dSmrg 1246af69d88dSmrg /* The size must be a multiple of bw x bh, or we must be using a 1247af69d88dSmrg * offset+size that exactly hits the edge of the image. This 1248af69d88dSmrg * is important for small mipmap levels (1x1, 2x1, etc) and for 1249af69d88dSmrg * NPOT textures. 1250af69d88dSmrg */ 1251af69d88dSmrg if ((subWidth % bw != 0) && 1252af69d88dSmrg (xoffset + subWidth != (GLint) destImage->Width)) { 1253af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 125401e04c3fSmrg "%s(width = %d)", func, subWidth); 1255af69d88dSmrg return GL_TRUE; 1256af69d88dSmrg } 1257af69d88dSmrg 1258af69d88dSmrg if ((subHeight % bh != 0) && 1259af69d88dSmrg (yoffset + subHeight != (GLint) destImage->Height)) { 1260af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 126101e04c3fSmrg "%s(height = %d)", func, subHeight); 126201e04c3fSmrg return GL_TRUE; 126301e04c3fSmrg } 126401e04c3fSmrg 126501e04c3fSmrg if ((subDepth % bd != 0) && 126601e04c3fSmrg (zoffset + subDepth != (GLint) destImage->Depth)) { 126701e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 126801e04c3fSmrg "%s(depth = %d)", func, subDepth); 1269af69d88dSmrg return GL_TRUE; 1270af69d88dSmrg } 1271af69d88dSmrg } 1272af69d88dSmrg 1273af69d88dSmrg return GL_FALSE; 1274af69d88dSmrg} 1275af69d88dSmrg 1276af69d88dSmrg 1277af69d88dSmrg 1278af69d88dSmrg 1279af69d88dSmrg/** 1280af69d88dSmrg * This is the fallback for Driver.TestProxyTexImage() for doing device- 1281af69d88dSmrg * specific texture image size checks. 1282af69d88dSmrg * 1283af69d88dSmrg * A hardware driver might override this function if, for example, the 1284af69d88dSmrg * max 3D texture size is 512x512x64 (i.e. not a cube). 1285af69d88dSmrg * 1286af69d88dSmrg * Note that width, height, depth == 0 is not an error. However, a 1287af69d88dSmrg * texture with zero width/height/depth will be considered "incomplete" 1288af69d88dSmrg * and texturing will effectively be disabled. 1289af69d88dSmrg * 1290af69d88dSmrg * \param target any texture target/type 129101e04c3fSmrg * \param numLevels number of mipmap levels in the texture or 0 if not known 1292af69d88dSmrg * \param level as passed to glTexImage 1293af69d88dSmrg * \param format the MESA_FORMAT_x for the tex image 129401e04c3fSmrg * \param numSamples number of samples per texel 1295af69d88dSmrg * \param width as passed to glTexImage 1296af69d88dSmrg * \param height as passed to glTexImage 1297af69d88dSmrg * \param depth as passed to glTexImage 1298af69d88dSmrg * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable. 1299af69d88dSmrg */ 1300af69d88dSmrgGLboolean 130101e04c3fSmrg_mesa_test_proxy_teximage(struct gl_context *ctx, GLenum target, 130201e04c3fSmrg GLuint numLevels, MAYBE_UNUSED GLint level, 130301e04c3fSmrg mesa_format format, GLuint numSamples, 130401e04c3fSmrg GLint width, GLint height, GLint depth) 13057117f1b4Smrg{ 130601e04c3fSmrg uint64_t bytes, mbytes; 130701e04c3fSmrg 130801e04c3fSmrg if (numLevels > 0) { 130901e04c3fSmrg /* Compute total memory for a whole mipmap. This is the path 131001e04c3fSmrg * taken for glTexStorage(GL_PROXY_TEXTURE_x). 131101e04c3fSmrg */ 131201e04c3fSmrg unsigned l; 131301e04c3fSmrg 131401e04c3fSmrg assert(level == 0); 131501e04c3fSmrg 131601e04c3fSmrg bytes = 0; 131701e04c3fSmrg 131801e04c3fSmrg for (l = 0; l < numLevels; l++) { 131901e04c3fSmrg GLint nextWidth, nextHeight, nextDepth; 132001e04c3fSmrg 132101e04c3fSmrg bytes += _mesa_format_image_size64(format, width, height, depth); 132201e04c3fSmrg 132301e04c3fSmrg if (_mesa_next_mipmap_level_size(target, 0, width, height, depth, 132401e04c3fSmrg &nextWidth, &nextHeight, 132501e04c3fSmrg &nextDepth)) { 132601e04c3fSmrg width = nextWidth; 132701e04c3fSmrg height = nextHeight; 132801e04c3fSmrg depth = nextDepth; 132901e04c3fSmrg } else { 133001e04c3fSmrg break; 133101e04c3fSmrg } 133201e04c3fSmrg } 133301e04c3fSmrg } else { 133401e04c3fSmrg /* We just compute the size of one mipmap level. This is the path 133501e04c3fSmrg * taken for glTexImage(GL_PROXY_TEXTURE_x). 133601e04c3fSmrg */ 133701e04c3fSmrg bytes = _mesa_format_image_size64(format, width, height, depth); 133801e04c3fSmrg } 133901e04c3fSmrg 134001e04c3fSmrg bytes *= _mesa_num_tex_faces(target); 134101e04c3fSmrg bytes *= MAX2(1, numSamples); 134201e04c3fSmrg 134301e04c3fSmrg mbytes = bytes / (1024 * 1024); /* convert to MB */ 134401e04c3fSmrg 1345af69d88dSmrg /* We just check if the image size is less than MaxTextureMbytes. 1346af69d88dSmrg * Some drivers may do more specific checks. 1347af69d88dSmrg */ 13483464ebd5Sriastradh return mbytes <= (uint64_t) ctx->Const.MaxTextureMbytes; 13497117f1b4Smrg} 13507117f1b4Smrg 13517117f1b4Smrg 1352af69d88dSmrg/** 1353af69d88dSmrg * Return true if the format is only valid for glCompressedTexImage. 1354af69d88dSmrg */ 135501e04c3fSmrgstatic bool 135601e04c3fSmrgcompressedteximage_only_format(GLenum format) 1357af69d88dSmrg{ 1358af69d88dSmrg switch (format) { 1359af69d88dSmrg case GL_PALETTE4_RGB8_OES: 1360af69d88dSmrg case GL_PALETTE4_RGBA8_OES: 1361af69d88dSmrg case GL_PALETTE4_R5_G6_B5_OES: 1362af69d88dSmrg case GL_PALETTE4_RGBA4_OES: 1363af69d88dSmrg case GL_PALETTE4_RGB5_A1_OES: 1364af69d88dSmrg case GL_PALETTE8_RGB8_OES: 1365af69d88dSmrg case GL_PALETTE8_RGBA8_OES: 1366af69d88dSmrg case GL_PALETTE8_R5_G6_B5_OES: 1367af69d88dSmrg case GL_PALETTE8_RGBA4_OES: 1368af69d88dSmrg case GL_PALETTE8_RGB5_A1_OES: 1369b9abf16eSmaya case GL_ATC_RGB_AMD: 1370b9abf16eSmaya case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD: 1371b9abf16eSmaya case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: 137201e04c3fSmrg return true; 1373af69d88dSmrg default: 137401e04c3fSmrg return false; 1375af69d88dSmrg } 1376af69d88dSmrg} 1377af69d88dSmrg 137801e04c3fSmrg/** 137901e04c3fSmrg * Return true if the format doesn't support online compression. 138001e04c3fSmrg */ 138101e04c3fSmrgbool 138201e04c3fSmrg_mesa_format_no_online_compression(GLenum format) 138301e04c3fSmrg{ 138401e04c3fSmrg return _mesa_is_astc_format(format) || 138501e04c3fSmrg _mesa_is_etc2_format(format) || 138601e04c3fSmrg compressedteximage_only_format(format); 138701e04c3fSmrg} 138801e04c3fSmrg 138901e04c3fSmrg/* Writes to an GL error pointer if non-null and returns whether or not the 139001e04c3fSmrg * error is GL_NO_ERROR */ 139101e04c3fSmrgstatic bool 139201e04c3fSmrgwrite_error(GLenum *err_ptr, GLenum error) 139301e04c3fSmrg{ 139401e04c3fSmrg if (err_ptr) 139501e04c3fSmrg *err_ptr = error; 139601e04c3fSmrg 139701e04c3fSmrg return error == GL_NO_ERROR; 139801e04c3fSmrg} 13993464ebd5Sriastradh 14007117f1b4Smrg/** 14013464ebd5Sriastradh * Helper function to determine whether a target and specific compression 140201e04c3fSmrg * format are supported. The error parameter returns GL_NO_ERROR if the 140301e04c3fSmrg * target can be compressed. Otherwise it returns either GL_INVALID_OPERATION 140401e04c3fSmrg * or GL_INVALID_ENUM, whichever is more appropriate. 14057117f1b4Smrg */ 1406af69d88dSmrgGLboolean 1407af69d88dSmrg_mesa_target_can_be_compressed(const struct gl_context *ctx, GLenum target, 140801e04c3fSmrg GLenum intFormat, GLenum *error) 14097117f1b4Smrg{ 141001e04c3fSmrg GLboolean target_can_be_compresed = GL_FALSE; 141101e04c3fSmrg mesa_format format = _mesa_glenum_to_compressed_format(intFormat); 141201e04c3fSmrg enum mesa_format_layout layout = _mesa_get_format_layout(format); 14137117f1b4Smrg 14143464ebd5Sriastradh switch (target) { 14153464ebd5Sriastradh case GL_TEXTURE_2D: 14163464ebd5Sriastradh case GL_PROXY_TEXTURE_2D: 141701e04c3fSmrg target_can_be_compresed = GL_TRUE; /* true for any compressed format so far */ 141801e04c3fSmrg break; 14193464ebd5Sriastradh case GL_PROXY_TEXTURE_CUBE_MAP: 1420af69d88dSmrg case GL_TEXTURE_CUBE_MAP: 14213464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 14223464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 14233464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 14243464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 14253464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 14263464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 142701e04c3fSmrg target_can_be_compresed = ctx->Extensions.ARB_texture_cube_map; 142801e04c3fSmrg break; 14293464ebd5Sriastradh case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 14303464ebd5Sriastradh case GL_TEXTURE_2D_ARRAY_EXT: 143101e04c3fSmrg target_can_be_compresed = ctx->Extensions.EXT_texture_array; 143201e04c3fSmrg break; 1433af69d88dSmrg case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY: 1434af69d88dSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: 143501e04c3fSmrg /* From the KHR_texture_compression_astc_hdr spec: 143601e04c3fSmrg * 143701e04c3fSmrg * Add a second new column "3D Tex." which is empty for all non-ASTC 143801e04c3fSmrg * formats. If only the LDR profile is supported by the 143901e04c3fSmrg * implementation, this column is also empty for all ASTC formats. If 144001e04c3fSmrg * both the LDR and HDR profiles are supported only, this column is 144101e04c3fSmrg * checked for all ASTC formats. 144201e04c3fSmrg * 144301e04c3fSmrg * Add a third new column "Cube Map Array Tex." which is empty for all 144401e04c3fSmrg * non-ASTC formats, and checked for all ASTC formats. 144501e04c3fSmrg * 144601e04c3fSmrg * and, 144701e04c3fSmrg * 144801e04c3fSmrg * 'An INVALID_OPERATION error is generated by CompressedTexImage3D 144901e04c3fSmrg * if <internalformat> is TEXTURE_CUBE_MAP_ARRAY and the 145001e04c3fSmrg * "Cube Map Array" column of table 8.19 is *not* checked, or if 145101e04c3fSmrg * <internalformat> is TEXTURE_3D and the "3D Tex." column of table 145201e04c3fSmrg * 8.19 is *not* checked' 145301e04c3fSmrg * 145401e04c3fSmrg * The instances of <internalformat> above should say <target>. 145501e04c3fSmrg * 145601e04c3fSmrg * ETC2/EAC formats are the only alternative in GLES and thus such errors 145701e04c3fSmrg * have already been handled by normal ETC2/EAC behavior. 145801e04c3fSmrg */ 145901e04c3fSmrg 146001e04c3fSmrg /* From section 3.8.6, page 146 of OpenGL ES 3.0 spec: 146101e04c3fSmrg * 146201e04c3fSmrg * "The ETC2/EAC texture compression algorithm supports only 146301e04c3fSmrg * two-dimensional images. If internalformat is an ETC2/EAC format, 146401e04c3fSmrg * glCompressedTexImage3D will generate an INVALID_OPERATION error if 146501e04c3fSmrg * target is not TEXTURE_2D_ARRAY." 146601e04c3fSmrg * 146701e04c3fSmrg * This should also be applicable for glTexStorage3D(). Other available 146801e04c3fSmrg * targets for these functions are: TEXTURE_3D and TEXTURE_CUBE_MAP_ARRAY. 146901e04c3fSmrg * 147001e04c3fSmrg * Section 8.7, page 179 of OpenGL ES 3.2 adds: 147101e04c3fSmrg * 147201e04c3fSmrg * An INVALID_OPERATION error is generated by CompressedTexImage3D 147301e04c3fSmrg * if internalformat is one of the the formats in table 8.17 and target is 147401e04c3fSmrg * not TEXTURE_2D_ARRAY, TEXTURE_CUBE_MAP_ARRAY or TEXTURE_3D. 147501e04c3fSmrg * 147601e04c3fSmrg * An INVALID_OPERATION error is generated by CompressedTexImage3D 147701e04c3fSmrg * if internalformat is TEXTURE_CUBE_MAP_ARRAY and the “Cube Map 147801e04c3fSmrg * Array” column of table 8.17 is not checked, or if internalformat 147901e04c3fSmrg * is TEXTURE_- 3D and the “3D Tex.” column of table 8.17 is not 148001e04c3fSmrg * checked. 148101e04c3fSmrg * 148201e04c3fSmrg * The instances of <internalformat> above should say <target>. 148301e04c3fSmrg * 148401e04c3fSmrg * Such table 8.17 has checked "Cube Map Array" column for all the 148501e04c3fSmrg * cases. So in practice, TEXTURE_CUBE_MAP_ARRAY is now valid for OpenGL ES 3.2 148601e04c3fSmrg */ 148701e04c3fSmrg if (layout == MESA_FORMAT_LAYOUT_ETC2 && _mesa_is_gles3(ctx) && 148801e04c3fSmrg !_mesa_is_gles32(ctx)) 148901e04c3fSmrg return write_error(error, GL_INVALID_OPERATION); 149001e04c3fSmrg target_can_be_compresed = _mesa_has_texture_cube_map_array(ctx); 149101e04c3fSmrg break; 149201e04c3fSmrg case GL_TEXTURE_3D: 149301e04c3fSmrg switch (layout) { 149401e04c3fSmrg case MESA_FORMAT_LAYOUT_ETC2: 149501e04c3fSmrg /* See ETC2/EAC comment in case GL_TEXTURE_CUBE_MAP_ARRAY. */ 149601e04c3fSmrg if (_mesa_is_gles3(ctx)) 149701e04c3fSmrg return write_error(error, GL_INVALID_OPERATION); 149801e04c3fSmrg break; 149901e04c3fSmrg case MESA_FORMAT_LAYOUT_BPTC: 150001e04c3fSmrg target_can_be_compresed = ctx->Extensions.ARB_texture_compression_bptc; 150101e04c3fSmrg break; 150201e04c3fSmrg case MESA_FORMAT_LAYOUT_ASTC: 150301e04c3fSmrg target_can_be_compresed = 150401e04c3fSmrg ctx->Extensions.KHR_texture_compression_astc_hdr || 150501e04c3fSmrg ctx->Extensions.KHR_texture_compression_astc_sliced_3d; 150601e04c3fSmrg 150701e04c3fSmrg /* Throw an INVALID_OPERATION error if the target is TEXTURE_3D and 150801e04c3fSmrg * neither of the above extensions are supported. See comment in 150901e04c3fSmrg * switch case GL_TEXTURE_CUBE_MAP_ARRAY for more info. 151001e04c3fSmrg */ 151101e04c3fSmrg if (!target_can_be_compresed) 151201e04c3fSmrg return write_error(error, GL_INVALID_OPERATION); 151301e04c3fSmrg break; 151401e04c3fSmrg default: 151501e04c3fSmrg break; 151601e04c3fSmrg } 15173464ebd5Sriastradh default: 151801e04c3fSmrg break; 1519af69d88dSmrg } 152001e04c3fSmrg return write_error(error, 152101e04c3fSmrg target_can_be_compresed ? GL_NO_ERROR : GL_INVALID_ENUM); 15223464ebd5Sriastradh} 15237117f1b4Smrg 15247117f1b4Smrg 15253464ebd5Sriastradh/** 15263464ebd5Sriastradh * Check if the given texture target value is legal for a 15273464ebd5Sriastradh * glTexImage1/2/3D call. 15283464ebd5Sriastradh */ 15293464ebd5Sriastradhstatic GLboolean 15303464ebd5Sriastradhlegal_teximage_target(struct gl_context *ctx, GLuint dims, GLenum target) 15313464ebd5Sriastradh{ 15323464ebd5Sriastradh switch (dims) { 15333464ebd5Sriastradh case 1: 15343464ebd5Sriastradh switch (target) { 15353464ebd5Sriastradh case GL_TEXTURE_1D: 15363464ebd5Sriastradh case GL_PROXY_TEXTURE_1D: 1537af69d88dSmrg return _mesa_is_desktop_gl(ctx); 15383464ebd5Sriastradh default: 15393464ebd5Sriastradh return GL_FALSE; 15407117f1b4Smrg } 15413464ebd5Sriastradh case 2: 15423464ebd5Sriastradh switch (target) { 15433464ebd5Sriastradh case GL_TEXTURE_2D: 15443464ebd5Sriastradh return GL_TRUE; 1545af69d88dSmrg case GL_PROXY_TEXTURE_2D: 1546af69d88dSmrg return _mesa_is_desktop_gl(ctx); 15473464ebd5Sriastradh case GL_PROXY_TEXTURE_CUBE_MAP: 1548af69d88dSmrg return _mesa_is_desktop_gl(ctx) 1549af69d88dSmrg && ctx->Extensions.ARB_texture_cube_map; 15503464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 15513464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 15523464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 15533464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 15543464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 15553464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 15563464ebd5Sriastradh return ctx->Extensions.ARB_texture_cube_map; 15573464ebd5Sriastradh case GL_TEXTURE_RECTANGLE_NV: 15583464ebd5Sriastradh case GL_PROXY_TEXTURE_RECTANGLE_NV: 1559af69d88dSmrg return _mesa_is_desktop_gl(ctx) 1560af69d88dSmrg && ctx->Extensions.NV_texture_rectangle; 15613464ebd5Sriastradh case GL_TEXTURE_1D_ARRAY_EXT: 15623464ebd5Sriastradh case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 1563af69d88dSmrg return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array; 15643464ebd5Sriastradh default: 15653464ebd5Sriastradh return GL_FALSE; 15667117f1b4Smrg } 15673464ebd5Sriastradh case 3: 15683464ebd5Sriastradh switch (target) { 15693464ebd5Sriastradh case GL_TEXTURE_3D: 15707117f1b4Smrg return GL_TRUE; 1571af69d88dSmrg case GL_PROXY_TEXTURE_3D: 1572af69d88dSmrg return _mesa_is_desktop_gl(ctx); 15733464ebd5Sriastradh case GL_TEXTURE_2D_ARRAY_EXT: 1574af69d88dSmrg return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array) 1575af69d88dSmrg || _mesa_is_gles3(ctx); 15763464ebd5Sriastradh case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 1577af69d88dSmrg return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array; 1578af69d88dSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: 1579af69d88dSmrg case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY: 158001e04c3fSmrg return _mesa_has_texture_cube_map_array(ctx); 15813464ebd5Sriastradh default: 15823464ebd5Sriastradh return GL_FALSE; 15837117f1b4Smrg } 15843464ebd5Sriastradh default: 15853464ebd5Sriastradh _mesa_problem(ctx, "invalid dims=%u in legal_teximage_target()", dims); 15863464ebd5Sriastradh return GL_FALSE; 15877117f1b4Smrg } 15883464ebd5Sriastradh} 15893464ebd5Sriastradh 15903464ebd5Sriastradh 15913464ebd5Sriastradh/** 15923464ebd5Sriastradh * Check if the given texture target value is legal for a 15933464ebd5Sriastradh * glTexSubImage, glCopyTexSubImage or glCopyTexImage call. 15943464ebd5Sriastradh * The difference compared to legal_teximage_target() above is that 15953464ebd5Sriastradh * proxy targets are not supported. 15963464ebd5Sriastradh */ 15973464ebd5Sriastradhstatic GLboolean 159801e04c3fSmrglegal_texsubimage_target(struct gl_context *ctx, GLuint dims, GLenum target, 159901e04c3fSmrg bool dsa) 16003464ebd5Sriastradh{ 16013464ebd5Sriastradh switch (dims) { 16023464ebd5Sriastradh case 1: 1603af69d88dSmrg return _mesa_is_desktop_gl(ctx) && target == GL_TEXTURE_1D; 16043464ebd5Sriastradh case 2: 16053464ebd5Sriastradh switch (target) { 16063464ebd5Sriastradh case GL_TEXTURE_2D: 16073464ebd5Sriastradh return GL_TRUE; 16083464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 16093464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 16103464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 16113464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 16123464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 16133464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 16143464ebd5Sriastradh return ctx->Extensions.ARB_texture_cube_map; 16153464ebd5Sriastradh case GL_TEXTURE_RECTANGLE_NV: 1616af69d88dSmrg return _mesa_is_desktop_gl(ctx) 1617af69d88dSmrg && ctx->Extensions.NV_texture_rectangle; 16183464ebd5Sriastradh case GL_TEXTURE_1D_ARRAY_EXT: 1619af69d88dSmrg return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array; 16203464ebd5Sriastradh default: 16213464ebd5Sriastradh return GL_FALSE; 1622c1f859d4Smrg } 16233464ebd5Sriastradh case 3: 16243464ebd5Sriastradh switch (target) { 16253464ebd5Sriastradh case GL_TEXTURE_3D: 16267117f1b4Smrg return GL_TRUE; 16273464ebd5Sriastradh case GL_TEXTURE_2D_ARRAY_EXT: 1628af69d88dSmrg return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array) 1629af69d88dSmrg || _mesa_is_gles3(ctx); 1630af69d88dSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: 1631af69d88dSmrg case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY: 163201e04c3fSmrg return _mesa_has_texture_cube_map_array(ctx); 163301e04c3fSmrg 163401e04c3fSmrg /* Table 8.15 of the OpenGL 4.5 core profile spec 163501e04c3fSmrg * (20141030) says that TEXTURE_CUBE_MAP is valid for TextureSubImage3D 163601e04c3fSmrg * and CopyTextureSubImage3D. 163701e04c3fSmrg */ 163801e04c3fSmrg case GL_TEXTURE_CUBE_MAP: 163901e04c3fSmrg return dsa; 16403464ebd5Sriastradh default: 16413464ebd5Sriastradh return GL_FALSE; 16427117f1b4Smrg } 16433464ebd5Sriastradh default: 16443464ebd5Sriastradh _mesa_problem(ctx, "invalid dims=%u in legal_texsubimage_target()", 16453464ebd5Sriastradh dims); 16463464ebd5Sriastradh return GL_FALSE; 16477117f1b4Smrg } 16483464ebd5Sriastradh} 16493464ebd5Sriastradh 16503464ebd5Sriastradh 16513464ebd5Sriastradh/** 1652af69d88dSmrg * Helper function to determine if a texture object is mutable (in terms 165301e04c3fSmrg * of GL_ARB_texture_storage/GL_ARB_bindless_texture). 16543464ebd5Sriastradh */ 16553464ebd5Sriastradhstatic GLboolean 1656af69d88dSmrgmutable_tex_object(struct gl_context *ctx, GLenum target) 16573464ebd5Sriastradh{ 1658af69d88dSmrg struct gl_texture_object *texObj = _mesa_get_current_tex_object(ctx, target); 165901e04c3fSmrg if (!texObj) 166001e04c3fSmrg return GL_FALSE; 166101e04c3fSmrg 166201e04c3fSmrg if (texObj->HandleAllocated) { 166301e04c3fSmrg /* The ARB_bindless_texture spec says: 166401e04c3fSmrg * 166501e04c3fSmrg * "The error INVALID_OPERATION is generated by TexImage*, CopyTexImage*, 166601e04c3fSmrg * CompressedTexImage*, TexBuffer*, TexParameter*, as well as other 166701e04c3fSmrg * functions defined in terms of these, if the texture object to be 166801e04c3fSmrg * modified is referenced by one or more texture or image handles." 166901e04c3fSmrg */ 167001e04c3fSmrg return GL_FALSE; 167101e04c3fSmrg } 167201e04c3fSmrg 1673af69d88dSmrg return !texObj->Immutable; 1674af69d88dSmrg} 16753464ebd5Sriastradh 16763464ebd5Sriastradh 1677af69d88dSmrg/** 1678af69d88dSmrg * Return expected size of a compressed texture. 1679af69d88dSmrg */ 1680af69d88dSmrgstatic GLuint 1681af69d88dSmrgcompressed_tex_size(GLsizei width, GLsizei height, GLsizei depth, 1682af69d88dSmrg GLenum glformat) 1683af69d88dSmrg{ 1684af69d88dSmrg mesa_format mesaFormat = _mesa_glenum_to_compressed_format(glformat); 1685af69d88dSmrg return _mesa_format_image_size(mesaFormat, width, height, depth); 1686af69d88dSmrg} 16877117f1b4Smrg 1688af69d88dSmrg/** 1689af69d88dSmrg * Verify that a texture format is valid with a particular target 1690af69d88dSmrg * 1691af69d88dSmrg * In particular, textures with base format of \c GL_DEPTH_COMPONENT or 1692af69d88dSmrg * \c GL_DEPTH_STENCIL are only valid with certain, context dependent texture 1693af69d88dSmrg * targets. 1694af69d88dSmrg * 1695af69d88dSmrg * \param ctx GL context 1696af69d88dSmrg * \param target Texture target 1697af69d88dSmrg * \param internalFormat Internal format of the texture image 1698af69d88dSmrg * 1699af69d88dSmrg * \returns true if the combination is legal, false otherwise. 1700af69d88dSmrg */ 1701af69d88dSmrgbool 1702af69d88dSmrg_mesa_legal_texture_base_format_for_target(struct gl_context *ctx, 170301e04c3fSmrg GLenum target, GLenum internalFormat) 1704af69d88dSmrg{ 1705af69d88dSmrg if (_mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_COMPONENT 170601e04c3fSmrg || _mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_STENCIL 170701e04c3fSmrg || _mesa_base_tex_format(ctx, internalFormat) == GL_STENCIL_INDEX) { 1708af69d88dSmrg /* Section 3.8.3 (Texture Image Specification) of the OpenGL 3.3 Core 1709af69d88dSmrg * Profile spec says: 1710af69d88dSmrg * 1711af69d88dSmrg * "Textures with a base internal format of DEPTH_COMPONENT or 1712af69d88dSmrg * DEPTH_STENCIL are supported by texture image specification 1713af69d88dSmrg * commands only if target is TEXTURE_1D, TEXTURE_2D, 1714af69d88dSmrg * TEXTURE_1D_ARRAY, TEXTURE_2D_ARRAY, TEXTURE_RECTANGLE, 1715af69d88dSmrg * TEXTURE_CUBE_MAP, PROXY_TEXTURE_1D, PROXY_TEXTURE_2D, 1716af69d88dSmrg * PROXY_TEXTURE_1D_ARRAY, PROXY_TEXTURE_2D_ARRAY, 1717af69d88dSmrg * PROXY_TEXTURE_RECTANGLE, or PROXY_TEXTURE_CUBE_MAP. Using these 1718af69d88dSmrg * formats in conjunction with any other target will result in an 1719af69d88dSmrg * INVALID_OPERATION error." 1720af69d88dSmrg * 1721af69d88dSmrg * Cubemaps are only supported with desktop OpenGL version >= 3.0, 1722af69d88dSmrg * EXT_gpu_shader4, or, on OpenGL ES 2.0+, OES_depth_texture_cube_map. 1723af69d88dSmrg */ 1724af69d88dSmrg if (target != GL_TEXTURE_1D && 1725af69d88dSmrg target != GL_PROXY_TEXTURE_1D && 1726af69d88dSmrg target != GL_TEXTURE_2D && 1727af69d88dSmrg target != GL_PROXY_TEXTURE_2D && 1728af69d88dSmrg target != GL_TEXTURE_1D_ARRAY && 1729af69d88dSmrg target != GL_PROXY_TEXTURE_1D_ARRAY && 1730af69d88dSmrg target != GL_TEXTURE_2D_ARRAY && 1731af69d88dSmrg target != GL_PROXY_TEXTURE_2D_ARRAY && 1732af69d88dSmrg target != GL_TEXTURE_RECTANGLE_ARB && 1733af69d88dSmrg target != GL_PROXY_TEXTURE_RECTANGLE_ARB && 1734af69d88dSmrg !((_mesa_is_cube_face(target) || 1735af69d88dSmrg target == GL_TEXTURE_CUBE_MAP || 1736af69d88dSmrg target == GL_PROXY_TEXTURE_CUBE_MAP) && 1737af69d88dSmrg (ctx->Version >= 30 || ctx->Extensions.EXT_gpu_shader4 1738af69d88dSmrg || (ctx->API == API_OPENGLES2 && ctx->Extensions.OES_depth_texture_cube_map))) && 1739af69d88dSmrg !((target == GL_TEXTURE_CUBE_MAP_ARRAY || 1740af69d88dSmrg target == GL_PROXY_TEXTURE_CUBE_MAP_ARRAY) && 174101e04c3fSmrg _mesa_has_texture_cube_map_array(ctx))) { 1742af69d88dSmrg return false; 1743af69d88dSmrg } 17443464ebd5Sriastradh } 17453464ebd5Sriastradh 1746af69d88dSmrg return true; 1747af69d88dSmrg} 1748af69d88dSmrg 1749af69d88dSmrgstatic bool 1750af69d88dSmrgtexture_formats_agree(GLenum internalFormat, 1751af69d88dSmrg GLenum format) 1752af69d88dSmrg{ 1753af69d88dSmrg GLboolean colorFormat; 1754af69d88dSmrg GLboolean is_format_depth_or_depthstencil; 1755af69d88dSmrg GLboolean is_internalFormat_depth_or_depthstencil; 1756af69d88dSmrg 1757af69d88dSmrg /* Even though there are no color-index textures, we still have to support 1758af69d88dSmrg * uploading color-index data and remapping it to RGB via the 1759af69d88dSmrg * GL_PIXEL_MAP_I_TO_[RGBA] tables. 17603464ebd5Sriastradh */ 1761af69d88dSmrg const GLboolean indexFormat = (format == GL_COLOR_INDEX); 1762af69d88dSmrg 1763af69d88dSmrg is_internalFormat_depth_or_depthstencil = 1764af69d88dSmrg _mesa_is_depth_format(internalFormat) || 1765af69d88dSmrg _mesa_is_depthstencil_format(internalFormat); 1766af69d88dSmrg 1767af69d88dSmrg is_format_depth_or_depthstencil = 1768af69d88dSmrg _mesa_is_depth_format(format) || 1769af69d88dSmrg _mesa_is_depthstencil_format(format); 1770af69d88dSmrg 1771af69d88dSmrg colorFormat = _mesa_is_color_format(format); 1772af69d88dSmrg 1773af69d88dSmrg if (_mesa_is_color_format(internalFormat) && !colorFormat && !indexFormat) 1774af69d88dSmrg return false; 1775af69d88dSmrg 1776af69d88dSmrg if (is_internalFormat_depth_or_depthstencil != 1777af69d88dSmrg is_format_depth_or_depthstencil) 1778af69d88dSmrg return false; 1779af69d88dSmrg 1780af69d88dSmrg if (_mesa_is_ycbcr_format(internalFormat) != _mesa_is_ycbcr_format(format)) 1781af69d88dSmrg return false; 1782af69d88dSmrg 1783af69d88dSmrg return true; 1784af69d88dSmrg} 1785af69d88dSmrg 178601e04c3fSmrg/** 178701e04c3fSmrg * Test the combination of format, type and internal format arguments of 178801e04c3fSmrg * different texture operations on GLES. 178901e04c3fSmrg * 179001e04c3fSmrg * \param ctx GL context. 179101e04c3fSmrg * \param format pixel data format given by the user. 179201e04c3fSmrg * \param type pixel data type given by the user. 179301e04c3fSmrg * \param internalFormat internal format given by the user. 179401e04c3fSmrg * \param callerName name of the caller function to print in the error message 179501e04c3fSmrg * 179601e04c3fSmrg * \return true if a error is found, false otherwise 179701e04c3fSmrg * 179801e04c3fSmrg * Currently, it is used by texture_error_check() and texsubimage_error_check(). 179901e04c3fSmrg */ 180001e04c3fSmrgstatic bool 180101e04c3fSmrgtexture_format_error_check_gles(struct gl_context *ctx, GLenum format, 180201e04c3fSmrg GLenum type, GLenum internalFormat, const char *callerName) 180301e04c3fSmrg{ 1804b9abf16eSmaya GLenum err = _mesa_gles_error_check_format_and_type(ctx, format, type, 1805b9abf16eSmaya internalFormat); 180601e04c3fSmrg if (err != GL_NO_ERROR) { 180701e04c3fSmrg _mesa_error(ctx, err, 180801e04c3fSmrg "%s(format = %s, type = %s, internalformat = %s)", 180901e04c3fSmrg callerName, _mesa_enum_to_string(format), 181001e04c3fSmrg _mesa_enum_to_string(type), 181101e04c3fSmrg _mesa_enum_to_string(internalFormat)); 181201e04c3fSmrg return true; 181301e04c3fSmrg } 181401e04c3fSmrg 181501e04c3fSmrg return false; 181601e04c3fSmrg} 181701e04c3fSmrg 1818af69d88dSmrg/** 1819af69d88dSmrg * Test the glTexImage[123]D() parameters for errors. 1820af69d88dSmrg * 1821af69d88dSmrg * \param ctx GL context. 1822af69d88dSmrg * \param dimensions texture image dimensions (must be 1, 2 or 3). 1823af69d88dSmrg * \param target texture target given by the user (already validated). 1824af69d88dSmrg * \param level image level given by the user. 1825af69d88dSmrg * \param internalFormat internal format given by the user. 1826af69d88dSmrg * \param format pixel data format given by the user. 1827af69d88dSmrg * \param type pixel data type given by the user. 1828af69d88dSmrg * \param width image width given by the user. 1829af69d88dSmrg * \param height image height given by the user. 1830af69d88dSmrg * \param depth image depth given by the user. 1831af69d88dSmrg * \param border image border given by the user. 1832af69d88dSmrg * 1833af69d88dSmrg * \return GL_TRUE if a error is found, GL_FALSE otherwise 1834af69d88dSmrg * 1835af69d88dSmrg * Verifies each of the parameters against the constants specified in 1836af69d88dSmrg * __struct gl_contextRec::Const and the supported extensions, and according 1837af69d88dSmrg * to the OpenGL specification. 1838af69d88dSmrg * Note that we don't fully error-check the width, height, depth values 1839af69d88dSmrg * here. That's done in _mesa_legal_texture_dimensions() which is used 1840af69d88dSmrg * by several other GL entrypoints. Plus, texture dims have a special 1841af69d88dSmrg * interaction with proxy textures. 1842af69d88dSmrg */ 1843af69d88dSmrgstatic GLboolean 1844af69d88dSmrgtexture_error_check( struct gl_context *ctx, 1845af69d88dSmrg GLuint dimensions, GLenum target, 1846af69d88dSmrg GLint level, GLint internalFormat, 1847af69d88dSmrg GLenum format, GLenum type, 1848af69d88dSmrg GLint width, GLint height, 184901e04c3fSmrg GLint depth, GLint border, 185001e04c3fSmrg const GLvoid *pixels ) 1851af69d88dSmrg{ 1852af69d88dSmrg GLenum err; 1853af69d88dSmrg 1854af69d88dSmrg /* Note: for proxy textures, some error conditions immediately generate 1855af69d88dSmrg * a GL error in the usual way. But others do not generate a GL error. 1856af69d88dSmrg * Instead, they cause the width, height, depth, format fields of the 1857af69d88dSmrg * texture image to be zeroed-out. The GL spec seems to indicate that the 1858af69d88dSmrg * zero-out behaviour is only used in cases related to memory allocation. 1859af69d88dSmrg */ 1860af69d88dSmrg 1861af69d88dSmrg /* level check */ 1862af69d88dSmrg if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) { 1863af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 1864af69d88dSmrg "glTexImage%dD(level=%d)", dimensions, level); 1865af69d88dSmrg return GL_TRUE; 1866af69d88dSmrg } 1867af69d88dSmrg 1868af69d88dSmrg /* Check border */ 1869af69d88dSmrg if (border < 0 || border > 1 || 1870af69d88dSmrg ((ctx->API != API_OPENGL_COMPAT || 1871af69d88dSmrg target == GL_TEXTURE_RECTANGLE_NV || 1872af69d88dSmrg target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) { 1873af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 1874af69d88dSmrg "glTexImage%dD(border=%d)", dimensions, border); 1875af69d88dSmrg return GL_TRUE; 1876af69d88dSmrg } 1877af69d88dSmrg 1878af69d88dSmrg if (width < 0 || height < 0 || depth < 0) { 1879af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 1880af69d88dSmrg "glTexImage%dD(width, height or depth < 0)", dimensions); 18817117f1b4Smrg return GL_TRUE; 18827117f1b4Smrg } 18837117f1b4Smrg 188401e04c3fSmrg /* Check incoming image format and type */ 188501e04c3fSmrg err = _mesa_error_check_format_and_type(ctx, format, type); 188601e04c3fSmrg if (err != GL_NO_ERROR) { 188701e04c3fSmrg /* Prior to OpenGL-ES 2.0, an INVALID_VALUE is expected instead of 188801e04c3fSmrg * INVALID_ENUM. From page 73 OpenGL ES 1.1 spec: 188901e04c3fSmrg * 189001e04c3fSmrg * "Specifying a value for internalformat that is not one of the 189101e04c3fSmrg * above (acceptable) values generates the error INVALID VALUE." 189201e04c3fSmrg */ 189301e04c3fSmrg if (err == GL_INVALID_ENUM && _mesa_is_gles(ctx) && ctx->Version < 20) 189401e04c3fSmrg err = GL_INVALID_VALUE; 1895af69d88dSmrg 189601e04c3fSmrg _mesa_error(ctx, err, 189701e04c3fSmrg "glTexImage%dD(incompatible format = %s, type = %s)", 189801e04c3fSmrg dimensions, _mesa_enum_to_string(format), 189901e04c3fSmrg _mesa_enum_to_string(type)); 190001e04c3fSmrg return GL_TRUE; 1901af69d88dSmrg } 1902af69d88dSmrg 19037117f1b4Smrg /* Check internalFormat */ 19047117f1b4Smrg if (_mesa_base_tex_format(ctx, internalFormat) < 0) { 1905af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 1906af69d88dSmrg "glTexImage%dD(internalFormat=%s)", 190701e04c3fSmrg dimensions, _mesa_enum_to_string(internalFormat)); 19087117f1b4Smrg return GL_TRUE; 19097117f1b4Smrg } 19107117f1b4Smrg 191101e04c3fSmrg /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the 191201e04c3fSmrg * combinations of format, internalFormat, and type that can be used. 191301e04c3fSmrg * Formats and types that require additional extensions (e.g., GL_FLOAT 191401e04c3fSmrg * requires GL_OES_texture_float) are filtered elsewhere. 191501e04c3fSmrg */ 191601e04c3fSmrg char bufCallerName[20]; 191701e04c3fSmrg _mesa_snprintf(bufCallerName, 20, "glTexImage%dD", dimensions); 191801e04c3fSmrg if (_mesa_is_gles(ctx) && 191901e04c3fSmrg texture_format_error_check_gles(ctx, format, type, 192001e04c3fSmrg internalFormat, bufCallerName)) { 192101e04c3fSmrg return GL_TRUE; 192201e04c3fSmrg } 192301e04c3fSmrg 192401e04c3fSmrg /* validate the bound PBO, if any */ 192501e04c3fSmrg if (!_mesa_validate_pbo_source(ctx, dimensions, &ctx->Unpack, 192601e04c3fSmrg width, height, depth, format, type, 192701e04c3fSmrg INT_MAX, pixels, "glTexImage")) { 19287117f1b4Smrg return GL_TRUE; 19297117f1b4Smrg } 19307117f1b4Smrg 19317117f1b4Smrg /* make sure internal format and format basically agree */ 1932af69d88dSmrg if (!texture_formats_agree(internalFormat, format)) { 1933af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 1934af69d88dSmrg "glTexImage%dD(incompatible internalFormat = %s, format = %s)", 193501e04c3fSmrg dimensions, _mesa_enum_to_string(internalFormat), 193601e04c3fSmrg _mesa_enum_to_string(format)); 19377117f1b4Smrg return GL_TRUE; 19387117f1b4Smrg } 19397117f1b4Smrg 19407117f1b4Smrg /* additional checks for ycbcr textures */ 19417117f1b4Smrg if (internalFormat == GL_YCBCR_MESA) { 194201e04c3fSmrg assert(ctx->Extensions.MESA_ycbcr_texture); 19437117f1b4Smrg if (type != GL_UNSIGNED_SHORT_8_8_MESA && 19447117f1b4Smrg type != GL_UNSIGNED_SHORT_8_8_REV_MESA) { 19457117f1b4Smrg char message[100]; 19463464ebd5Sriastradh _mesa_snprintf(message, sizeof(message), 1947af69d88dSmrg "glTexImage%dD(format/type YCBCR mismatch)", 1948af69d88dSmrg dimensions); 19493464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_ENUM, "%s", message); 19507117f1b4Smrg return GL_TRUE; /* error */ 19517117f1b4Smrg } 19527117f1b4Smrg if (target != GL_TEXTURE_2D && 19537117f1b4Smrg target != GL_PROXY_TEXTURE_2D && 19547117f1b4Smrg target != GL_TEXTURE_RECTANGLE_NV && 19557117f1b4Smrg target != GL_PROXY_TEXTURE_RECTANGLE_NV) { 1956af69d88dSmrg _mesa_error(ctx, GL_INVALID_ENUM, 1957af69d88dSmrg "glTexImage%dD(bad target for YCbCr texture)", 1958af69d88dSmrg dimensions); 19597117f1b4Smrg return GL_TRUE; 19607117f1b4Smrg } 19617117f1b4Smrg if (border != 0) { 1962af69d88dSmrg char message[100]; 1963af69d88dSmrg _mesa_snprintf(message, sizeof(message), 1964af69d88dSmrg "glTexImage%dD(format=GL_YCBCR_MESA and border=%d)", 1965af69d88dSmrg dimensions, border); 1966af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s", message); 19677117f1b4Smrg return GL_TRUE; 19687117f1b4Smrg } 19697117f1b4Smrg } 19707117f1b4Smrg 19717117f1b4Smrg /* additional checks for depth textures */ 197201e04c3fSmrg if (!_mesa_legal_texture_base_format_for_target(ctx, target, internalFormat)) { 197301e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 197401e04c3fSmrg "glTexImage%dD(bad target for texture)", dimensions); 1975af69d88dSmrg return GL_TRUE; 197601e04c3fSmrg } 19777117f1b4Smrg 19787117f1b4Smrg /* additional checks for compressed textures */ 19793464ebd5Sriastradh if (_mesa_is_compressed_format(ctx, internalFormat)) { 198001e04c3fSmrg GLenum err; 198101e04c3fSmrg if (!_mesa_target_can_be_compressed(ctx, target, internalFormat, &err)) { 198201e04c3fSmrg _mesa_error(ctx, err, 1983af69d88dSmrg "glTexImage%dD(target can't be compressed)", dimensions); 1984af69d88dSmrg return GL_TRUE; 1985af69d88dSmrg } 198601e04c3fSmrg if (_mesa_format_no_online_compression(internalFormat)) { 1987af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 1988af69d88dSmrg "glTexImage%dD(no compression for format)", dimensions); 19897117f1b4Smrg return GL_TRUE; 19907117f1b4Smrg } 19917117f1b4Smrg if (border != 0) { 1992af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 1993af69d88dSmrg "glTexImage%dD(border!=0)", dimensions); 19947117f1b4Smrg return GL_TRUE; 19957117f1b4Smrg } 19967117f1b4Smrg } 19977117f1b4Smrg 19983464ebd5Sriastradh /* additional checks for integer textures */ 1999af69d88dSmrg if ((ctx->Version >= 30 || ctx->Extensions.EXT_texture_integer) && 2000af69d88dSmrg (_mesa_is_enum_format_integer(format) != 2001af69d88dSmrg _mesa_is_enum_format_integer(internalFormat))) { 2002af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 2003af69d88dSmrg "glTexImage%dD(integer/non-integer format mismatch)", 2004af69d88dSmrg dimensions); 2005af69d88dSmrg return GL_TRUE; 2006af69d88dSmrg } 2007af69d88dSmrg 2008af69d88dSmrg if (!mutable_tex_object(ctx, target)) { 2009af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 2010af69d88dSmrg "glTexImage%dD(immutable texture)", dimensions); 20113464ebd5Sriastradh return GL_TRUE; 20123464ebd5Sriastradh } 20133464ebd5Sriastradh 20147117f1b4Smrg /* if we get here, the parameters are OK */ 20157117f1b4Smrg return GL_FALSE; 20167117f1b4Smrg} 20177117f1b4Smrg 20187117f1b4Smrg 2019af69d88dSmrg/** 2020af69d88dSmrg * Error checking for glCompressedTexImage[123]D(). 2021af69d88dSmrg * Note that the width, height and depth values are not fully error checked 2022af69d88dSmrg * here. 2023af69d88dSmrg * \return GL_TRUE if a error is found, GL_FALSE otherwise 2024af69d88dSmrg */ 2025af69d88dSmrgstatic GLenum 2026af69d88dSmrgcompressed_texture_error_check(struct gl_context *ctx, GLint dimensions, 2027af69d88dSmrg GLenum target, GLint level, 2028af69d88dSmrg GLenum internalFormat, GLsizei width, 2029af69d88dSmrg GLsizei height, GLsizei depth, GLint border, 203001e04c3fSmrg GLsizei imageSize, const GLvoid *data) 2031af69d88dSmrg{ 2032af69d88dSmrg const GLint maxLevels = _mesa_max_texture_levels(ctx, target); 2033af69d88dSmrg GLint expectedSize; 2034af69d88dSmrg GLenum error = GL_NO_ERROR; 2035af69d88dSmrg char *reason = ""; /* no error */ 2036af69d88dSmrg 203701e04c3fSmrg if (!_mesa_target_can_be_compressed(ctx, target, internalFormat, &error)) { 2038af69d88dSmrg reason = "target"; 2039af69d88dSmrg goto error; 2040af69d88dSmrg } 2041af69d88dSmrg 2042af69d88dSmrg /* This will detect any invalid internalFormat value */ 2043af69d88dSmrg if (!_mesa_is_compressed_format(ctx, internalFormat)) { 2044af69d88dSmrg _mesa_error(ctx, GL_INVALID_ENUM, 2045af69d88dSmrg "glCompressedTexImage%dD(internalFormat=%s)", 204601e04c3fSmrg dimensions, _mesa_enum_to_string(internalFormat)); 204701e04c3fSmrg return GL_TRUE; 204801e04c3fSmrg } 204901e04c3fSmrg 205001e04c3fSmrg /* validate the bound PBO, if any */ 205101e04c3fSmrg if (!_mesa_validate_pbo_source_compressed(ctx, dimensions, &ctx->Unpack, 205201e04c3fSmrg imageSize, data, 205301e04c3fSmrg "glCompressedTexImage")) { 2054af69d88dSmrg return GL_TRUE; 2055af69d88dSmrg } 2056af69d88dSmrg 2057af69d88dSmrg switch (internalFormat) { 2058af69d88dSmrg case GL_PALETTE4_RGB8_OES: 2059af69d88dSmrg case GL_PALETTE4_RGBA8_OES: 2060af69d88dSmrg case GL_PALETTE4_R5_G6_B5_OES: 2061af69d88dSmrg case GL_PALETTE4_RGBA4_OES: 2062af69d88dSmrg case GL_PALETTE4_RGB5_A1_OES: 2063af69d88dSmrg case GL_PALETTE8_RGB8_OES: 2064af69d88dSmrg case GL_PALETTE8_RGBA8_OES: 2065af69d88dSmrg case GL_PALETTE8_R5_G6_B5_OES: 2066af69d88dSmrg case GL_PALETTE8_RGBA4_OES: 2067af69d88dSmrg case GL_PALETTE8_RGB5_A1_OES: 2068af69d88dSmrg /* check level (note that level should be zero or less!) */ 2069af69d88dSmrg if (level > 0 || level < -maxLevels) { 207001e04c3fSmrg reason = "level"; 207101e04c3fSmrg error = GL_INVALID_VALUE; 2072af69d88dSmrg goto error; 2073af69d88dSmrg } 2074af69d88dSmrg 2075af69d88dSmrg if (dimensions != 2) { 207601e04c3fSmrg reason = "compressed paletted textures must be 2D"; 207701e04c3fSmrg error = GL_INVALID_OPERATION; 2078af69d88dSmrg goto error; 2079af69d88dSmrg } 2080af69d88dSmrg 2081af69d88dSmrg /* Figure out the expected texture size (in bytes). This will be 2082af69d88dSmrg * checked against the actual size later. 2083af69d88dSmrg */ 2084af69d88dSmrg expectedSize = _mesa_cpal_compressed_size(level, internalFormat, 208501e04c3fSmrg width, height); 2086af69d88dSmrg 2087af69d88dSmrg /* This is for the benefit of the TestProxyTexImage below. It expects 2088af69d88dSmrg * level to be non-negative. OES_compressed_paletted_texture uses a 2089af69d88dSmrg * weird mechanism where the level specified to glCompressedTexImage2D 2090af69d88dSmrg * is -(n-1) number of levels in the texture, and the data specifies the 2091af69d88dSmrg * complete mipmap stack. This is done to ensure the palette is the 2092af69d88dSmrg * same for all levels. 2093af69d88dSmrg */ 2094af69d88dSmrg level = -level; 2095af69d88dSmrg break; 2096af69d88dSmrg 2097af69d88dSmrg default: 2098af69d88dSmrg /* check level */ 2099af69d88dSmrg if (level < 0 || level >= maxLevels) { 210001e04c3fSmrg reason = "level"; 210101e04c3fSmrg error = GL_INVALID_VALUE; 2102af69d88dSmrg goto error; 2103af69d88dSmrg } 2104af69d88dSmrg 2105af69d88dSmrg /* Figure out the expected texture size (in bytes). This will be 2106af69d88dSmrg * checked against the actual size later. 2107af69d88dSmrg */ 2108af69d88dSmrg expectedSize = compressed_tex_size(width, height, depth, internalFormat); 2109af69d88dSmrg break; 2110af69d88dSmrg } 2111af69d88dSmrg 2112af69d88dSmrg /* This should really never fail */ 2113af69d88dSmrg if (_mesa_base_tex_format(ctx, internalFormat) < 0) { 2114af69d88dSmrg reason = "internalFormat"; 2115af69d88dSmrg error = GL_INVALID_ENUM; 2116af69d88dSmrg goto error; 2117af69d88dSmrg } 2118af69d88dSmrg 2119af69d88dSmrg /* No compressed formats support borders at this time */ 2120af69d88dSmrg if (border != 0) { 2121af69d88dSmrg reason = "border != 0"; 2122af69d88dSmrg error = GL_INVALID_VALUE; 2123af69d88dSmrg goto error; 2124af69d88dSmrg } 2125af69d88dSmrg 2126af69d88dSmrg /* Check for invalid pixel storage modes */ 2127af69d88dSmrg if (!_mesa_compressed_pixel_storage_error_check(ctx, dimensions, 2128af69d88dSmrg &ctx->Unpack, 2129af69d88dSmrg "glCompressedTexImage")) { 2130af69d88dSmrg return GL_FALSE; 2131af69d88dSmrg } 2132af69d88dSmrg 2133af69d88dSmrg /* check image size in bytes */ 2134af69d88dSmrg if (expectedSize != imageSize) { 2135af69d88dSmrg /* Per GL_ARB_texture_compression: GL_INVALID_VALUE is generated [...] 2136af69d88dSmrg * if <imageSize> is not consistent with the format, dimensions, and 2137af69d88dSmrg * contents of the specified image. 2138af69d88dSmrg */ 213901e04c3fSmrg reason = "imageSize inconsistent with width/height/format"; 2140af69d88dSmrg error = GL_INVALID_VALUE; 2141af69d88dSmrg goto error; 2142af69d88dSmrg } 2143af69d88dSmrg 2144af69d88dSmrg if (!mutable_tex_object(ctx, target)) { 2145af69d88dSmrg reason = "immutable texture"; 2146af69d88dSmrg error = GL_INVALID_OPERATION; 2147af69d88dSmrg goto error; 2148af69d88dSmrg } 2149af69d88dSmrg 2150af69d88dSmrg return GL_FALSE; 2151af69d88dSmrg 2152af69d88dSmrgerror: 2153af69d88dSmrg /* Note: not all error paths exit through here. */ 215401e04c3fSmrg _mesa_error(ctx, error, "glCompressedTexImage%dD(%s)", 215501e04c3fSmrg dimensions, reason); 2156af69d88dSmrg return GL_TRUE; 2157af69d88dSmrg} 2158af69d88dSmrg 2159af69d88dSmrg 2160af69d88dSmrg 21617117f1b4Smrg/** 21627117f1b4Smrg * Test glTexSubImage[123]D() parameters for errors. 2163af69d88dSmrg * 21647117f1b4Smrg * \param ctx GL context. 21657117f1b4Smrg * \param dimensions texture image dimensions (must be 1, 2 or 3). 2166af69d88dSmrg * \param target texture target given by the user (already validated) 21677117f1b4Smrg * \param level image level given by the user. 21687117f1b4Smrg * \param xoffset sub-image x offset given by the user. 21697117f1b4Smrg * \param yoffset sub-image y offset given by the user. 21707117f1b4Smrg * \param zoffset sub-image z offset given by the user. 21717117f1b4Smrg * \param format pixel data format given by the user. 21727117f1b4Smrg * \param type pixel data type given by the user. 21737117f1b4Smrg * \param width image width given by the user. 21747117f1b4Smrg * \param height image height given by the user. 21757117f1b4Smrg * \param depth image depth given by the user. 2176af69d88dSmrg * 21777117f1b4Smrg * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 21787117f1b4Smrg * 21797117f1b4Smrg * Verifies each of the parameters against the constants specified in 21803464ebd5Sriastradh * __struct gl_contextRec::Const and the supported extensions, and according 21813464ebd5Sriastradh * to the OpenGL specification. 21827117f1b4Smrg */ 21837117f1b4Smrgstatic GLboolean 2184af69d88dSmrgtexsubimage_error_check(struct gl_context *ctx, GLuint dimensions, 218501e04c3fSmrg struct gl_texture_object *texObj, 21867117f1b4Smrg GLenum target, GLint level, 21877117f1b4Smrg GLint xoffset, GLint yoffset, GLint zoffset, 21887117f1b4Smrg GLint width, GLint height, GLint depth, 218901e04c3fSmrg GLenum format, GLenum type, const GLvoid *pixels, 219001e04c3fSmrg const char *callerName) 21917117f1b4Smrg{ 2192af69d88dSmrg struct gl_texture_image *texImage; 2193af69d88dSmrg GLenum err; 2194af69d88dSmrg 219501e04c3fSmrg if (!texObj) { 219601e04c3fSmrg /* must be out of memory */ 219701e04c3fSmrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s()", callerName); 21987117f1b4Smrg return GL_TRUE; 21997117f1b4Smrg } 22007117f1b4Smrg 2201af69d88dSmrg /* level check */ 2202af69d88dSmrg if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) { 220301e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(level=%d)", callerName, level); 22047117f1b4Smrg return GL_TRUE; 22057117f1b4Smrg } 2206af69d88dSmrg 220701e04c3fSmrg if (error_check_subtexture_negative_dimensions(ctx, dimensions, 220801e04c3fSmrg width, height, depth, 220901e04c3fSmrg callerName)) { 221001e04c3fSmrg return GL_TRUE; 221101e04c3fSmrg } 221201e04c3fSmrg 221301e04c3fSmrg texImage = _mesa_select_tex_image(texObj, target, level); 221401e04c3fSmrg if (!texImage) { 221501e04c3fSmrg /* non-existant texture level */ 221601e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid texture level %d)", 221701e04c3fSmrg callerName, level); 221801e04c3fSmrg return GL_TRUE; 2219af69d88dSmrg } 2220af69d88dSmrg 2221af69d88dSmrg err = _mesa_error_check_format_and_type(ctx, format, type); 2222af69d88dSmrg if (err != GL_NO_ERROR) { 2223af69d88dSmrg _mesa_error(ctx, err, 222401e04c3fSmrg "%s(incompatible format = %s, type = %s)", 222501e04c3fSmrg callerName, _mesa_enum_to_string(format), 222601e04c3fSmrg _mesa_enum_to_string(type)); 22277117f1b4Smrg return GL_TRUE; 22287117f1b4Smrg } 2229af69d88dSmrg 223001e04c3fSmrg GLenum internalFormat = _mesa_is_gles(ctx) ? 223101e04c3fSmrg oes_float_internal_format(ctx, texImage->InternalFormat, type) : 223201e04c3fSmrg texImage->InternalFormat; 223301e04c3fSmrg 223401e04c3fSmrg /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the 223501e04c3fSmrg * combinations of format, internalFormat, and type that can be used. 223601e04c3fSmrg * Formats and types that require additional extensions (e.g., GL_FLOAT 223701e04c3fSmrg * requires GL_OES_texture_float) are filtered elsewhere. 223801e04c3fSmrg */ 223901e04c3fSmrg if (_mesa_is_gles(ctx) && 224001e04c3fSmrg texture_format_error_check_gles(ctx, format, type, 224101e04c3fSmrg internalFormat, callerName)) { 22427117f1b4Smrg return GL_TRUE; 22437117f1b4Smrg } 22447117f1b4Smrg 224501e04c3fSmrg /* validate the bound PBO, if any */ 224601e04c3fSmrg if (!_mesa_validate_pbo_source(ctx, dimensions, &ctx->Unpack, 224701e04c3fSmrg width, height, depth, format, type, 224801e04c3fSmrg INT_MAX, pixels, callerName)) { 22497117f1b4Smrg return GL_TRUE; 22507117f1b4Smrg } 22517117f1b4Smrg 225201e04c3fSmrg if (error_check_subtexture_dimensions(ctx, dimensions, 225301e04c3fSmrg texImage, xoffset, yoffset, zoffset, 225401e04c3fSmrg width, height, depth, callerName)) { 2255af69d88dSmrg return GL_TRUE; 2256af69d88dSmrg } 22577117f1b4Smrg 2258af69d88dSmrg if (_mesa_is_format_compressed(texImage->TexFormat)) { 225901e04c3fSmrg if (_mesa_format_no_online_compression(texImage->InternalFormat)) { 2260af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 226101e04c3fSmrg "%s(no compression for format)", callerName); 22627117f1b4Smrg return GL_TRUE; 22637117f1b4Smrg } 22647117f1b4Smrg } 22657117f1b4Smrg 2266af69d88dSmrg if (ctx->Version >= 30 || ctx->Extensions.EXT_texture_integer) { 2267af69d88dSmrg /* both source and dest must be integer-valued, or neither */ 2268af69d88dSmrg if (_mesa_is_format_integer_color(texImage->TexFormat) != 2269af69d88dSmrg _mesa_is_enum_format_integer(format)) { 22707117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 227101e04c3fSmrg "%s(integer/non-integer format mismatch)", callerName); 22727117f1b4Smrg return GL_TRUE; 22737117f1b4Smrg } 22747117f1b4Smrg } 22757117f1b4Smrg 22767117f1b4Smrg return GL_FALSE; 22777117f1b4Smrg} 22787117f1b4Smrg 22797117f1b4Smrg 22807117f1b4Smrg/** 22817117f1b4Smrg * Test glCopyTexImage[12]D() parameters for errors. 2282af69d88dSmrg * 22837117f1b4Smrg * \param ctx GL context. 22847117f1b4Smrg * \param dimensions texture image dimensions (must be 1, 2 or 3). 22857117f1b4Smrg * \param target texture target given by the user. 22867117f1b4Smrg * \param level image level given by the user. 22877117f1b4Smrg * \param internalFormat internal format given by the user. 22887117f1b4Smrg * \param width image width given by the user. 22897117f1b4Smrg * \param height image height given by the user. 22907117f1b4Smrg * \param border texture border. 2291af69d88dSmrg * 22927117f1b4Smrg * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 2293af69d88dSmrg * 22947117f1b4Smrg * Verifies each of the parameters against the constants specified in 22953464ebd5Sriastradh * __struct gl_contextRec::Const and the supported extensions, and according 22963464ebd5Sriastradh * to the OpenGL specification. 22977117f1b4Smrg */ 22987117f1b4Smrgstatic GLboolean 22993464ebd5Sriastradhcopytexture_error_check( struct gl_context *ctx, GLuint dimensions, 23007117f1b4Smrg GLenum target, GLint level, GLint internalFormat, 230101e04c3fSmrg GLint border ) 23027117f1b4Smrg{ 2303af69d88dSmrg GLint baseFormat; 2304af69d88dSmrg GLint rb_base_format; 2305af69d88dSmrg struct gl_renderbuffer *rb; 2306af69d88dSmrg GLenum rb_internal_format; 23077117f1b4Smrg 23083464ebd5Sriastradh /* check target */ 230901e04c3fSmrg if (!legal_texsubimage_target(ctx, dimensions, target, false)) { 23103464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexImage%uD(target=%s)", 231101e04c3fSmrg dimensions, _mesa_enum_to_string(target)); 23123464ebd5Sriastradh return GL_TRUE; 2313af69d88dSmrg } 23143464ebd5Sriastradh 2315af69d88dSmrg /* level check */ 2316af69d88dSmrg if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) { 23177117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 23187117f1b4Smrg "glCopyTexImage%dD(level=%d)", dimensions, level); 23197117f1b4Smrg return GL_TRUE; 23207117f1b4Smrg } 23217117f1b4Smrg 23227117f1b4Smrg /* Check that the source buffer is complete */ 2323af69d88dSmrg if (_mesa_is_user_fbo(ctx->ReadBuffer)) { 23243464ebd5Sriastradh if (ctx->ReadBuffer->_Status == 0) { 23253464ebd5Sriastradh _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer); 23263464ebd5Sriastradh } 23277117f1b4Smrg if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 23287117f1b4Smrg _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 23297117f1b4Smrg "glCopyTexImage%dD(invalid readbuffer)", dimensions); 23307117f1b4Smrg return GL_TRUE; 23317117f1b4Smrg } 2332af69d88dSmrg 2333af69d88dSmrg if (ctx->ReadBuffer->Visual.samples > 0) { 233401e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 233501e04c3fSmrg "glCopyTexImage%dD(multisample FBO)", dimensions); 233601e04c3fSmrg return GL_TRUE; 2337af69d88dSmrg } 23387117f1b4Smrg } 23397117f1b4Smrg 23407117f1b4Smrg /* Check border */ 23417117f1b4Smrg if (border < 0 || border > 1 || 2342af69d88dSmrg ((ctx->API != API_OPENGL_COMPAT || 2343af69d88dSmrg target == GL_TEXTURE_RECTANGLE_NV || 23447117f1b4Smrg target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) { 2345af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 2346af69d88dSmrg "glCopyTexImage%dD(border=%d)", dimensions, border); 23477117f1b4Smrg return GL_TRUE; 23487117f1b4Smrg } 23497117f1b4Smrg 2350af69d88dSmrg /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the 2351af69d88dSmrg * internalFormat. 2352af69d88dSmrg */ 2353af69d88dSmrg if (_mesa_is_gles(ctx) && !_mesa_is_gles3(ctx)) { 2354af69d88dSmrg switch (internalFormat) { 2355af69d88dSmrg case GL_ALPHA: 2356af69d88dSmrg case GL_RGB: 2357af69d88dSmrg case GL_RGBA: 2358af69d88dSmrg case GL_LUMINANCE: 2359af69d88dSmrg case GL_LUMINANCE_ALPHA: 2360af69d88dSmrg break; 2361af69d88dSmrg default: 236201e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, 2363af69d88dSmrg "glCopyTexImage%dD(internalFormat=%s)", dimensions, 236401e04c3fSmrg _mesa_enum_to_string(internalFormat)); 236501e04c3fSmrg return GL_TRUE; 236601e04c3fSmrg } 236701e04c3fSmrg } else { 236801e04c3fSmrg /* 236901e04c3fSmrg * Section 8.6 (Alternate Texture Image Specification Commands) of the 237001e04c3fSmrg * OpenGL 4.5 (Compatibility Profile) spec says: 237101e04c3fSmrg * 237201e04c3fSmrg * "Parameters level, internalformat, and border are specified using 237301e04c3fSmrg * the same values, with the same meanings, as the corresponding 237401e04c3fSmrg * arguments of TexImage2D, except that internalformat may not be 237501e04c3fSmrg * specified as 1, 2, 3, or 4." 237601e04c3fSmrg */ 237701e04c3fSmrg if (internalFormat >= 1 && internalFormat <= 4) { 237801e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, 237901e04c3fSmrg "glCopyTexImage%dD(internalFormat=%d)", dimensions, 238001e04c3fSmrg internalFormat); 2381af69d88dSmrg return GL_TRUE; 2382af69d88dSmrg } 2383af69d88dSmrg } 2384af69d88dSmrg 2385af69d88dSmrg baseFormat = _mesa_base_tex_format(ctx, internalFormat); 2386af69d88dSmrg if (baseFormat < 0) { 238701e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, 2388af69d88dSmrg "glCopyTexImage%dD(internalFormat=%s)", dimensions, 238901e04c3fSmrg _mesa_enum_to_string(internalFormat)); 239001e04c3fSmrg return GL_TRUE; 239101e04c3fSmrg } 239201e04c3fSmrg 239301e04c3fSmrg rb = _mesa_get_read_renderbuffer_for_format(ctx, internalFormat); 239401e04c3fSmrg if (rb == NULL) { 239501e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 239601e04c3fSmrg "glCopyTexImage%dD(read buffer)", dimensions); 23977117f1b4Smrg return GL_TRUE; 23987117f1b4Smrg } 23997117f1b4Smrg 2400af69d88dSmrg rb_internal_format = rb->InternalFormat; 2401af69d88dSmrg rb_base_format = _mesa_base_tex_format(ctx, rb->InternalFormat); 2402af69d88dSmrg if (_mesa_is_color_format(internalFormat)) { 2403af69d88dSmrg if (rb_base_format < 0) { 2404af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 2405af69d88dSmrg "glCopyTexImage%dD(internalFormat=%s)", dimensions, 240601e04c3fSmrg _mesa_enum_to_string(internalFormat)); 2407af69d88dSmrg return GL_TRUE; 2408af69d88dSmrg } 2409af69d88dSmrg } 2410af69d88dSmrg 2411af69d88dSmrg if (_mesa_is_gles(ctx)) { 2412af69d88dSmrg bool valid = true; 241301e04c3fSmrg if (_mesa_components_in_format(baseFormat) > 241401e04c3fSmrg _mesa_components_in_format(rb_base_format)) { 2415af69d88dSmrg valid = false; 2416af69d88dSmrg } 2417af69d88dSmrg if (baseFormat == GL_DEPTH_COMPONENT || 2418af69d88dSmrg baseFormat == GL_DEPTH_STENCIL || 241901e04c3fSmrg baseFormat == GL_STENCIL_INDEX || 2420af69d88dSmrg rb_base_format == GL_DEPTH_COMPONENT || 2421af69d88dSmrg rb_base_format == GL_DEPTH_STENCIL || 242201e04c3fSmrg rb_base_format == GL_STENCIL_INDEX || 2423af69d88dSmrg ((baseFormat == GL_LUMINANCE_ALPHA || 2424af69d88dSmrg baseFormat == GL_ALPHA) && 2425af69d88dSmrg rb_base_format != GL_RGBA) || 2426af69d88dSmrg internalFormat == GL_RGB9_E5) { 2427af69d88dSmrg valid = false; 2428af69d88dSmrg } 2429af69d88dSmrg if (internalFormat == GL_RGB9_E5) { 2430af69d88dSmrg valid = false; 2431af69d88dSmrg } 2432af69d88dSmrg if (!valid) { 2433af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 2434af69d88dSmrg "glCopyTexImage%dD(internalFormat=%s)", dimensions, 243501e04c3fSmrg _mesa_enum_to_string(internalFormat)); 2436af69d88dSmrg return GL_TRUE; 2437af69d88dSmrg } 2438af69d88dSmrg } 24397117f1b4Smrg 2440af69d88dSmrg if (_mesa_is_gles3(ctx)) { 2441af69d88dSmrg bool rb_is_srgb = false; 2442af69d88dSmrg bool dst_is_srgb = false; 24437117f1b4Smrg 2444b9abf16eSmaya if (ctx->Extensions.EXT_sRGB && 2445af69d88dSmrg _mesa_get_format_color_encoding(rb->Format) == GL_SRGB) { 2446af69d88dSmrg rb_is_srgb = true; 24477117f1b4Smrg } 2448af69d88dSmrg 2449af69d88dSmrg if (_mesa_get_linear_internalformat(internalFormat) != internalFormat) { 2450af69d88dSmrg dst_is_srgb = true; 2451af69d88dSmrg } 2452af69d88dSmrg 2453af69d88dSmrg if (rb_is_srgb != dst_is_srgb) { 2454af69d88dSmrg /* Page 137 (page 149 of the PDF) in section 3.8.5 of the 2455af69d88dSmrg * OpenGLES 3.0.0 spec says: 2456af69d88dSmrg * 2457af69d88dSmrg * "The error INVALID_OPERATION is also generated if the 2458af69d88dSmrg * value of FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING for the 2459af69d88dSmrg * framebuffer attachment corresponding to the read buffer 2460af69d88dSmrg * is LINEAR (see section 6.1.13) and internalformat is 2461af69d88dSmrg * one of the sRGB formats described in section 3.8.16, or 2462af69d88dSmrg * if the value of FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING is 2463af69d88dSmrg * SRGB and internalformat is not one of the sRGB formats." 2464af69d88dSmrg */ 2465af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 2466af69d88dSmrg "glCopyTexImage%dD(srgb usage mismatch)", dimensions); 2467af69d88dSmrg return GL_TRUE; 24687117f1b4Smrg } 2469af69d88dSmrg 2470af69d88dSmrg /* Page 139, Table 3.15 of OpenGL ES 3.0 spec does not define ReadPixels 2471af69d88dSmrg * types for SNORM formats. Also, conversion to SNORM formats is not 2472af69d88dSmrg * allowed by Table 3.2 on Page 110. 2473af69d88dSmrg */ 247401e04c3fSmrg if (!_mesa_has_EXT_render_snorm(ctx) && 247501e04c3fSmrg _mesa_is_enum_format_snorm(internalFormat)) { 2476af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 2477af69d88dSmrg "glCopyTexImage%dD(internalFormat=%s)", dimensions, 247801e04c3fSmrg _mesa_enum_to_string(internalFormat)); 2479af69d88dSmrg return GL_TRUE; 2480af69d88dSmrg } 2481af69d88dSmrg } 2482af69d88dSmrg 2483af69d88dSmrg if (!_mesa_source_buffer_exists(ctx, baseFormat)) { 2484af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 2485af69d88dSmrg "glCopyTexImage%dD(missing readbuffer)", dimensions); 24867117f1b4Smrg return GL_TRUE; 24877117f1b4Smrg } 24887117f1b4Smrg 2489af69d88dSmrg /* From the EXT_texture_integer spec: 2490af69d88dSmrg * 2491af69d88dSmrg * "INVALID_OPERATION is generated by CopyTexImage* and CopyTexSubImage* 2492af69d88dSmrg * if the texture internalformat is an integer format and the read color 2493af69d88dSmrg * buffer is not an integer format, or if the internalformat is not an 2494af69d88dSmrg * integer format and the read color buffer is an integer format." 2495af69d88dSmrg */ 2496af69d88dSmrg if (_mesa_is_color_format(internalFormat)) { 2497af69d88dSmrg bool is_int = _mesa_is_enum_format_integer(internalFormat); 2498af69d88dSmrg bool is_rbint = _mesa_is_enum_format_integer(rb_internal_format); 2499af69d88dSmrg bool is_unorm = _mesa_is_enum_format_unorm(internalFormat); 2500af69d88dSmrg bool is_rbunorm = _mesa_is_enum_format_unorm(rb_internal_format); 2501af69d88dSmrg if (is_int || is_rbint) { 2502af69d88dSmrg if (is_int != is_rbint) { 2503af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 2504af69d88dSmrg "glCopyTexImage%dD(integer vs non-integer)", dimensions); 2505af69d88dSmrg return GL_TRUE; 2506af69d88dSmrg } else if (_mesa_is_gles(ctx) && 2507af69d88dSmrg _mesa_is_enum_format_unsigned_int(internalFormat) != 2508af69d88dSmrg _mesa_is_enum_format_unsigned_int(rb_internal_format)) { 2509af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 251001e04c3fSmrg "glCopyTexImage%dD(signed vs unsigned integer)", 251101e04c3fSmrg dimensions); 2512af69d88dSmrg return GL_TRUE; 2513af69d88dSmrg } 2514af69d88dSmrg } 2515af69d88dSmrg 2516af69d88dSmrg /* From page 138 of OpenGL ES 3.0 spec: 2517af69d88dSmrg * "The error INVALID_OPERATION is generated if floating-point RGBA 2518af69d88dSmrg * data is required; if signed integer RGBA data is required and the 2519af69d88dSmrg * format of the current color buffer is not signed integer; if 2520af69d88dSmrg * unsigned integer RGBA data is required and the format of the 2521af69d88dSmrg * current color buffer is not unsigned integer; or if fixed-point 2522af69d88dSmrg * RGBA data is required and the format of the current color buffer 2523af69d88dSmrg * is not fixed-point. 2524af69d88dSmrg */ 2525af69d88dSmrg if (_mesa_is_gles(ctx) && is_unorm != is_rbunorm) 2526af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 2527af69d88dSmrg "glCopyTexImage%dD(unorm vs non-unorm)", dimensions); 2528af69d88dSmrg } 2529af69d88dSmrg 25303464ebd5Sriastradh if (_mesa_is_compressed_format(ctx, internalFormat)) { 253101e04c3fSmrg GLenum err; 253201e04c3fSmrg if (!_mesa_target_can_be_compressed(ctx, target, internalFormat, &err)) { 253301e04c3fSmrg _mesa_error(ctx, err, 253401e04c3fSmrg "glCopyTexImage%dD(target can't be compressed)", dimensions); 25357117f1b4Smrg return GL_TRUE; 25367117f1b4Smrg } 253701e04c3fSmrg if (_mesa_format_no_online_compression(internalFormat)) { 25387117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 2539af69d88dSmrg "glCopyTexImage%dD(no compression for format)", dimensions); 25407117f1b4Smrg return GL_TRUE; 25417117f1b4Smrg } 2542af69d88dSmrg if (border != 0) { 25437117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 2544af69d88dSmrg "glCopyTexImage%dD(border!=0)", dimensions); 25457117f1b4Smrg return GL_TRUE; 25467117f1b4Smrg } 25477117f1b4Smrg } 2548af69d88dSmrg 2549af69d88dSmrg if (!mutable_tex_object(ctx, target)) { 2550af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 2551af69d88dSmrg "glCopyTexImage%dD(immutable texture)", dimensions); 2552af69d88dSmrg return GL_TRUE; 25537117f1b4Smrg } 25547117f1b4Smrg 25557117f1b4Smrg /* if we get here, the parameters are OK */ 25567117f1b4Smrg return GL_FALSE; 25577117f1b4Smrg} 25587117f1b4Smrg 25597117f1b4Smrg 25607117f1b4Smrg/** 25617117f1b4Smrg * Test glCopyTexSubImage[12]D() parameters for errors. 25627117f1b4Smrg * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 25637117f1b4Smrg */ 25647117f1b4Smrgstatic GLboolean 2565af69d88dSmrgcopytexsubimage_error_check(struct gl_context *ctx, GLuint dimensions, 256601e04c3fSmrg const struct gl_texture_object *texObj, 2567af69d88dSmrg GLenum target, GLint level, 2568af69d88dSmrg GLint xoffset, GLint yoffset, GLint zoffset, 256901e04c3fSmrg GLint width, GLint height, const char *caller) 25707117f1b4Smrg{ 257101e04c3fSmrg assert(texObj); 257201e04c3fSmrg 2573af69d88dSmrg struct gl_texture_image *texImage; 2574af69d88dSmrg 25757117f1b4Smrg /* Check that the source buffer is complete */ 2576af69d88dSmrg if (_mesa_is_user_fbo(ctx->ReadBuffer)) { 25773464ebd5Sriastradh if (ctx->ReadBuffer->_Status == 0) { 25783464ebd5Sriastradh _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer); 25793464ebd5Sriastradh } 25807117f1b4Smrg if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 25817117f1b4Smrg _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 258201e04c3fSmrg "%s(invalid readbuffer)", caller); 25837117f1b4Smrg return GL_TRUE; 25847117f1b4Smrg } 2585af69d88dSmrg 2586af69d88dSmrg if (ctx->ReadBuffer->Visual.samples > 0) { 258701e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 258801e04c3fSmrg "%s(multisample FBO)", caller); 258901e04c3fSmrg return GL_TRUE; 2590af69d88dSmrg } 25917117f1b4Smrg } 25927117f1b4Smrg 25937117f1b4Smrg /* Check level */ 2594af69d88dSmrg if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) { 259501e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(level=%d)", caller, level); 25967117f1b4Smrg return GL_TRUE; 25977117f1b4Smrg } 25987117f1b4Smrg 259901e04c3fSmrg texImage = _mesa_select_tex_image(texObj, target, level); 2600af69d88dSmrg if (!texImage) { 2601af69d88dSmrg /* destination image does not exist */ 2602af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 260301e04c3fSmrg "%s(invalid texture level %d)", caller, level); 2604c1f859d4Smrg return GL_TRUE; 2605c1f859d4Smrg } 2606c1f859d4Smrg 260701e04c3fSmrg if (error_check_subtexture_negative_dimensions(ctx, dimensions, 260801e04c3fSmrg width, height, 1, caller)) { 260901e04c3fSmrg return GL_TRUE; 261001e04c3fSmrg } 261101e04c3fSmrg 261201e04c3fSmrg if (error_check_subtexture_dimensions(ctx, dimensions, texImage, 2613af69d88dSmrg xoffset, yoffset, zoffset, 261401e04c3fSmrg width, height, 1, caller)) { 26157117f1b4Smrg return GL_TRUE; 26167117f1b4Smrg } 26177117f1b4Smrg 2618af69d88dSmrg if (_mesa_is_format_compressed(texImage->TexFormat)) { 261901e04c3fSmrg if (_mesa_format_no_online_compression(texImage->InternalFormat)) { 2620af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 262101e04c3fSmrg "%s(no compression for format)", caller); 26227117f1b4Smrg return GL_TRUE; 26237117f1b4Smrg } 26247117f1b4Smrg } 26257117f1b4Smrg 2626af69d88dSmrg if (texImage->InternalFormat == GL_YCBCR_MESA) { 262701e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s()", caller); 262801e04c3fSmrg return GL_TRUE; 262901e04c3fSmrg } 263001e04c3fSmrg 263101e04c3fSmrg /* From OpenGL ES 3.2 spec, section 8.6: 263201e04c3fSmrg * 263301e04c3fSmrg * "An INVALID_OPERATION error is generated by CopyTexSubImage3D, 263401e04c3fSmrg * CopyTexImage2D, or CopyTexSubImage2D if the internalformat of the 263501e04c3fSmrg * texture image being (re)specified is RGB9_E5" 263601e04c3fSmrg */ 263701e04c3fSmrg if (texImage->InternalFormat == GL_RGB9_E5 && 263801e04c3fSmrg !_mesa_is_desktop_gl(ctx)) { 263901e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 264001e04c3fSmrg "%s(invalid internal format %s)", caller, 264101e04c3fSmrg _mesa_enum_to_string(texImage->InternalFormat)); 26427117f1b4Smrg return GL_TRUE; 26437117f1b4Smrg } 26447117f1b4Smrg 2645af69d88dSmrg if (!_mesa_source_buffer_exists(ctx, texImage->_BaseFormat)) { 26467117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 264701e04c3fSmrg "%s(missing readbuffer, format=%s)", caller, 264801e04c3fSmrg _mesa_enum_to_string(texImage->_BaseFormat)); 26497117f1b4Smrg return GL_TRUE; 26507117f1b4Smrg } 26517117f1b4Smrg 2652af69d88dSmrg /* From the EXT_texture_integer spec: 2653af69d88dSmrg * 265401e04c3fSmrg * "INVALID_OPERATION is generated by CopyTexImage* and 265501e04c3fSmrg * CopyTexSubImage* if the texture internalformat is an integer format 265601e04c3fSmrg * and the read color buffer is not an integer format, or if the 265701e04c3fSmrg * internalformat is not an integer format and the read color buffer 265801e04c3fSmrg * is an integer format." 26593464ebd5Sriastradh */ 2660af69d88dSmrg if (_mesa_is_color_format(texImage->InternalFormat)) { 26613464ebd5Sriastradh struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer; 2662af69d88dSmrg 2663af69d88dSmrg if (_mesa_is_format_integer_color(rb->Format) != 266401e04c3fSmrg _mesa_is_format_integer_color(texImage->TexFormat)) { 266501e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 266601e04c3fSmrg "%s(integer vs non-integer)", caller); 266701e04c3fSmrg return GL_TRUE; 26683464ebd5Sriastradh } 26693464ebd5Sriastradh } 26703464ebd5Sriastradh 267101e04c3fSmrg /* In the ES 3.2 specification's Table 8.13 (Valid CopyTexImage source 267201e04c3fSmrg * framebuffer/destination texture base internal format combinations), 267301e04c3fSmrg * all the entries for stencil are left blank (unsupported). 267401e04c3fSmrg */ 267501e04c3fSmrg if (_mesa_is_gles(ctx) && _mesa_is_stencil_format(texImage->_BaseFormat)) { 267601e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(stencil disallowed)", caller); 267701e04c3fSmrg return GL_TRUE; 267801e04c3fSmrg } 267901e04c3fSmrg 26807117f1b4Smrg /* if we get here, the parameters are OK */ 26817117f1b4Smrg return GL_FALSE; 26827117f1b4Smrg} 26837117f1b4Smrg 26847117f1b4Smrg 26854a49301eSmrg/** Callback info for walking over FBO hash table */ 26864a49301eSmrgstruct cb_info 26877117f1b4Smrg{ 26883464ebd5Sriastradh struct gl_context *ctx; 26897117f1b4Smrg struct gl_texture_object *texObj; 26904a49301eSmrg GLuint level, face; 26914a49301eSmrg}; 26927117f1b4Smrg 26937117f1b4Smrg 26947117f1b4Smrg/** 26954a49301eSmrg * Check render to texture callback. Called from _mesa_HashWalk(). 26967117f1b4Smrg */ 26977117f1b4Smrgstatic void 269801e04c3fSmrgcheck_rtt_cb(UNUSED GLuint key, void *data, void *userData) 26997117f1b4Smrg{ 27004a49301eSmrg struct gl_framebuffer *fb = (struct gl_framebuffer *) data; 27014a49301eSmrg const struct cb_info *info = (struct cb_info *) userData; 27023464ebd5Sriastradh struct gl_context *ctx = info->ctx; 27034a49301eSmrg const struct gl_texture_object *texObj = info->texObj; 27044a49301eSmrg const GLuint level = info->level, face = info->face; 27054a49301eSmrg 27064a49301eSmrg /* If this is a user-created FBO */ 2707af69d88dSmrg if (_mesa_is_user_fbo(fb)) { 27087117f1b4Smrg GLuint i; 27094a49301eSmrg /* check if any of the FBO's attachments point to 'texObj' */ 27107117f1b4Smrg for (i = 0; i < BUFFER_COUNT; i++) { 27114a49301eSmrg struct gl_renderbuffer_attachment *att = fb->Attachment + i; 27127117f1b4Smrg if (att->Type == GL_TEXTURE && 27137117f1b4Smrg att->Texture == texObj && 27147117f1b4Smrg att->TextureLevel == level && 27157117f1b4Smrg att->CubeMapFace == face) { 271601e04c3fSmrg _mesa_update_texture_renderbuffer(ctx, fb, att); 271701e04c3fSmrg assert(att->Renderbuffer->TexImage); 27184a49301eSmrg /* Mark fb status as indeterminate to force re-validation */ 27194a49301eSmrg fb->_Status = 0; 272001e04c3fSmrg 272101e04c3fSmrg /* Make sure that the revalidation actually happens if this is 272201e04c3fSmrg * being done to currently-bound buffers. 272301e04c3fSmrg */ 272401e04c3fSmrg if (fb == ctx->DrawBuffer || fb == ctx->ReadBuffer) 272501e04c3fSmrg ctx->NewState |= _NEW_BUFFERS; 27267117f1b4Smrg } 27277117f1b4Smrg } 27287117f1b4Smrg } 27297117f1b4Smrg} 27307117f1b4Smrg 27317117f1b4Smrg 27324a49301eSmrg/** 27334a49301eSmrg * When a texture image is specified we have to check if it's bound to 27344a49301eSmrg * any framebuffer objects (render to texture) in order to detect changes 27354a49301eSmrg * in size or format since that effects FBO completeness. 27364a49301eSmrg * Any FBOs rendering into the texture must be re-validated. 27374a49301eSmrg */ 2738af69d88dSmrgvoid 2739af69d88dSmrg_mesa_update_fbo_texture(struct gl_context *ctx, 2740af69d88dSmrg struct gl_texture_object *texObj, 2741af69d88dSmrg GLuint face, GLuint level) 27424a49301eSmrg{ 27434a49301eSmrg /* Only check this texture if it's been marked as RenderToTexture */ 27444a49301eSmrg if (texObj->_RenderToTexture) { 27454a49301eSmrg struct cb_info info; 27464a49301eSmrg info.ctx = ctx; 27474a49301eSmrg info.texObj = texObj; 27484a49301eSmrg info.level = level; 27494a49301eSmrg info.face = face; 27504a49301eSmrg _mesa_HashWalk(ctx->Shared->FrameBuffers, check_rtt_cb, &info); 27514a49301eSmrg } 27524a49301eSmrg} 27534a49301eSmrg 27544a49301eSmrg 27554a49301eSmrg/** 27564a49301eSmrg * If the texture object's GenerateMipmap flag is set and we've 27574a49301eSmrg * changed the texture base level image, regenerate the rest of the 27584a49301eSmrg * mipmap levels now. 27594a49301eSmrg */ 2760af69d88dSmrgstatic inline void 27613464ebd5Sriastradhcheck_gen_mipmap(struct gl_context *ctx, GLenum target, 27624a49301eSmrg struct gl_texture_object *texObj, GLint level) 27634a49301eSmrg{ 27644a49301eSmrg if (texObj->GenerateMipmap && 27654a49301eSmrg level == texObj->BaseLevel && 27664a49301eSmrg level < texObj->MaxLevel) { 276701e04c3fSmrg assert(ctx->Driver.GenerateMipmap); 27684a49301eSmrg ctx->Driver.GenerateMipmap(ctx, target, texObj); 27694a49301eSmrg } 27704a49301eSmrg} 27714a49301eSmrg 27724a49301eSmrg 27734a49301eSmrg/** Debug helper: override the user-requested internal format */ 27744a49301eSmrgstatic GLenum 277501e04c3fSmrgoverride_internal_format(GLenum internalFormat, UNUSED GLint width, 277601e04c3fSmrg UNUSED GLint height) 27774a49301eSmrg{ 27784a49301eSmrg#if 0 27794a49301eSmrg if (internalFormat == GL_RGBA16F_ARB || 27804a49301eSmrg internalFormat == GL_RGBA32F_ARB) { 27814a49301eSmrg printf("Convert rgba float tex to int %d x %d\n", width, height); 27824a49301eSmrg return GL_RGBA; 27834a49301eSmrg } 27844a49301eSmrg else if (internalFormat == GL_RGB16F_ARB || 27854a49301eSmrg internalFormat == GL_RGB32F_ARB) { 27864a49301eSmrg printf("Convert rgb float tex to int %d x %d\n", width, height); 27874a49301eSmrg return GL_RGB; 27884a49301eSmrg } 27894a49301eSmrg else if (internalFormat == GL_LUMINANCE_ALPHA16F_ARB || 27904a49301eSmrg internalFormat == GL_LUMINANCE_ALPHA32F_ARB) { 27914a49301eSmrg printf("Convert luminance float tex to int %d x %d\n", width, height); 27924a49301eSmrg return GL_LUMINANCE_ALPHA; 27934a49301eSmrg } 27944a49301eSmrg else if (internalFormat == GL_LUMINANCE16F_ARB || 27954a49301eSmrg internalFormat == GL_LUMINANCE32F_ARB) { 27964a49301eSmrg printf("Convert luminance float tex to int %d x %d\n", width, height); 27974a49301eSmrg return GL_LUMINANCE; 27984a49301eSmrg } 27994a49301eSmrg else if (internalFormat == GL_ALPHA16F_ARB || 28004a49301eSmrg internalFormat == GL_ALPHA32F_ARB) { 28014a49301eSmrg printf("Convert luminance float tex to int %d x %d\n", width, height); 28024a49301eSmrg return GL_ALPHA; 28034a49301eSmrg } 28044a49301eSmrg /* 28054a49301eSmrg else if (internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) { 28064a49301eSmrg internalFormat = GL_RGBA; 28074a49301eSmrg } 28084a49301eSmrg */ 28094a49301eSmrg else { 28104a49301eSmrg return internalFormat; 28114a49301eSmrg } 28124a49301eSmrg#else 28134a49301eSmrg return internalFormat; 28144a49301eSmrg#endif 28154a49301eSmrg} 28164a49301eSmrg 28177117f1b4Smrg 28183464ebd5Sriastradh/** 28193464ebd5Sriastradh * Choose the actual hardware format for a texture image. 28203464ebd5Sriastradh * Try to use the same format as the previous image level when possible. 28213464ebd5Sriastradh * Otherwise, ask the driver for the best format. 28223464ebd5Sriastradh * It's important to try to choose a consistant format for all levels 28233464ebd5Sriastradh * for efficient texture memory layout/allocation. In particular, this 28243464ebd5Sriastradh * comes up during automatic mipmap generation. 28257117f1b4Smrg */ 2826af69d88dSmrgmesa_format 28273464ebd5Sriastradh_mesa_choose_texture_format(struct gl_context *ctx, 28283464ebd5Sriastradh struct gl_texture_object *texObj, 28293464ebd5Sriastradh GLenum target, GLint level, 28303464ebd5Sriastradh GLenum internalFormat, GLenum format, GLenum type) 28317117f1b4Smrg{ 2832af69d88dSmrg mesa_format f; 28333464ebd5Sriastradh 28343464ebd5Sriastradh /* see if we've already chosen a format for the previous level */ 28353464ebd5Sriastradh if (level > 0) { 28363464ebd5Sriastradh struct gl_texture_image *prevImage = 283701e04c3fSmrg _mesa_select_tex_image(texObj, target, level - 1); 28383464ebd5Sriastradh /* See if the prev level is defined and has an internal format which 28393464ebd5Sriastradh * matches the new internal format. 28403464ebd5Sriastradh */ 28413464ebd5Sriastradh if (prevImage && 28423464ebd5Sriastradh prevImage->Width > 0 && 28433464ebd5Sriastradh prevImage->InternalFormat == internalFormat) { 28443464ebd5Sriastradh /* use the same format */ 284501e04c3fSmrg assert(prevImage->TexFormat != MESA_FORMAT_NONE); 28463464ebd5Sriastradh return prevImage->TexFormat; 28473464ebd5Sriastradh } 28483464ebd5Sriastradh } 28493464ebd5Sriastradh 2850af69d88dSmrg f = ctx->Driver.ChooseTextureFormat(ctx, target, internalFormat, 2851af69d88dSmrg format, type); 285201e04c3fSmrg assert(f != MESA_FORMAT_NONE); 28533464ebd5Sriastradh return f; 28543464ebd5Sriastradh} 28553464ebd5Sriastradh 28563464ebd5Sriastradh 28573464ebd5Sriastradh/** 2858af69d88dSmrg * Adjust pixel unpack params and image dimensions to strip off the 2859af69d88dSmrg * one-pixel texture border. 2860af69d88dSmrg * 2861af69d88dSmrg * Gallium and intel don't support texture borders. They've seldem been used 2862af69d88dSmrg * and seldom been implemented correctly anyway. 2863af69d88dSmrg * 2864af69d88dSmrg * \param unpackNew returns the new pixel unpack parameters 2865af69d88dSmrg */ 2866af69d88dSmrgstatic void 2867af69d88dSmrgstrip_texture_border(GLenum target, 2868af69d88dSmrg GLint *width, GLint *height, GLint *depth, 2869af69d88dSmrg const struct gl_pixelstore_attrib *unpack, 2870af69d88dSmrg struct gl_pixelstore_attrib *unpackNew) 2871af69d88dSmrg{ 2872af69d88dSmrg assert(width); 2873af69d88dSmrg assert(height); 2874af69d88dSmrg assert(depth); 2875af69d88dSmrg 2876af69d88dSmrg *unpackNew = *unpack; 2877af69d88dSmrg 2878af69d88dSmrg if (unpackNew->RowLength == 0) 2879af69d88dSmrg unpackNew->RowLength = *width; 2880af69d88dSmrg 2881af69d88dSmrg if (unpackNew->ImageHeight == 0) 2882af69d88dSmrg unpackNew->ImageHeight = *height; 2883af69d88dSmrg 2884af69d88dSmrg assert(*width >= 3); 2885af69d88dSmrg unpackNew->SkipPixels++; /* skip the border */ 2886af69d88dSmrg *width = *width - 2; /* reduce the width by two border pixels */ 2887af69d88dSmrg 2888af69d88dSmrg /* The min height of a texture with a border is 3 */ 2889af69d88dSmrg if (*height >= 3 && target != GL_TEXTURE_1D_ARRAY) { 2890af69d88dSmrg unpackNew->SkipRows++; /* skip the border */ 2891af69d88dSmrg *height = *height - 2; /* reduce the height by two border pixels */ 2892af69d88dSmrg } 2893af69d88dSmrg 2894af69d88dSmrg if (*depth >= 3 && 2895af69d88dSmrg target != GL_TEXTURE_2D_ARRAY && 2896af69d88dSmrg target != GL_TEXTURE_CUBE_MAP_ARRAY) { 2897af69d88dSmrg unpackNew->SkipImages++; /* skip the border */ 2898af69d88dSmrg *depth = *depth - 2; /* reduce the depth by two border pixels */ 2899af69d88dSmrg } 2900af69d88dSmrg} 2901af69d88dSmrg 2902af69d88dSmrg 2903af69d88dSmrg/** 2904af69d88dSmrg * Common code to implement all the glTexImage1D/2D/3D functions 2905af69d88dSmrg * as well as glCompressedTexImage1D/2D/3D. 2906af69d88dSmrg * \param compressed only GL_TRUE for glCompressedTexImage1D/2D/3D calls. 2907af69d88dSmrg * \param format the user's image format (only used if !compressed) 2908af69d88dSmrg * \param type the user's image type (only used if !compressed) 2909af69d88dSmrg * \param imageSize only used for glCompressedTexImage1D/2D/3D calls. 29103464ebd5Sriastradh */ 291101e04c3fSmrgstatic ALWAYS_INLINE void 2912af69d88dSmrgteximage(struct gl_context *ctx, GLboolean compressed, GLuint dims, 29133464ebd5Sriastradh GLenum target, GLint level, GLint internalFormat, 29143464ebd5Sriastradh GLsizei width, GLsizei height, GLsizei depth, 29153464ebd5Sriastradh GLint border, GLenum format, GLenum type, 291601e04c3fSmrg GLsizei imageSize, const GLvoid *pixels, bool no_error) 29173464ebd5Sriastradh{ 2918af69d88dSmrg const char *func = compressed ? "glCompressedTexImage" : "glTexImage"; 2919af69d88dSmrg struct gl_pixelstore_attrib unpack_no_border; 2920af69d88dSmrg const struct gl_pixelstore_attrib *unpack = &ctx->Unpack; 2921af69d88dSmrg struct gl_texture_object *texObj; 2922af69d88dSmrg mesa_format texFormat; 292301e04c3fSmrg bool dimensionsOK = true, sizeOK = true; 2924af69d88dSmrg 2925af69d88dSmrg FLUSH_VERTICES(ctx, 0); 2926af69d88dSmrg 2927af69d88dSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) { 2928af69d88dSmrg if (compressed) 2929af69d88dSmrg _mesa_debug(ctx, 2930af69d88dSmrg "glCompressedTexImage%uD %s %d %s %d %d %d %d %p\n", 2931af69d88dSmrg dims, 293201e04c3fSmrg _mesa_enum_to_string(target), level, 293301e04c3fSmrg _mesa_enum_to_string(internalFormat), 2934af69d88dSmrg width, height, depth, border, pixels); 2935af69d88dSmrg else 2936af69d88dSmrg _mesa_debug(ctx, 2937af69d88dSmrg "glTexImage%uD %s %d %s %d %d %d %d %s %s %p\n", 2938af69d88dSmrg dims, 293901e04c3fSmrg _mesa_enum_to_string(target), level, 294001e04c3fSmrg _mesa_enum_to_string(internalFormat), 2941af69d88dSmrg width, height, depth, border, 294201e04c3fSmrg _mesa_enum_to_string(format), 294301e04c3fSmrg _mesa_enum_to_string(type), pixels); 29443464ebd5Sriastradh } 294501e04c3fSmrg 294601e04c3fSmrg internalFormat = override_internal_format(internalFormat, width, height); 294701e04c3fSmrg 294801e04c3fSmrg if (!no_error) { 294901e04c3fSmrg /* target error checking */ 295001e04c3fSmrg if (!legal_teximage_target(ctx, dims, target)) { 295101e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, "%s%uD(target=%s)", 295201e04c3fSmrg func, dims, _mesa_enum_to_string(target)); 2953af69d88dSmrg return; 295401e04c3fSmrg } 295501e04c3fSmrg 295601e04c3fSmrg /* general error checking */ 295701e04c3fSmrg if (compressed) { 295801e04c3fSmrg if (compressed_texture_error_check(ctx, dims, target, level, 295901e04c3fSmrg internalFormat, 296001e04c3fSmrg width, height, depth, 296101e04c3fSmrg border, imageSize, pixels)) 296201e04c3fSmrg return; 296301e04c3fSmrg } else { 296401e04c3fSmrg if (texture_error_check(ctx, dims, target, level, internalFormat, 296501e04c3fSmrg format, type, width, height, depth, border, 296601e04c3fSmrg pixels)) 296701e04c3fSmrg return; 296801e04c3fSmrg } 2969af69d88dSmrg } 29707117f1b4Smrg 2971af69d88dSmrg /* Here we convert a cpal compressed image into a regular glTexImage2D 2972af69d88dSmrg * call by decompressing the texture. If we really want to support cpal 2973af69d88dSmrg * textures in any driver this would have to be changed. 2974af69d88dSmrg */ 2975af69d88dSmrg if (ctx->API == API_OPENGLES && compressed && dims == 2) { 2976af69d88dSmrg switch (internalFormat) { 2977af69d88dSmrg case GL_PALETTE4_RGB8_OES: 2978af69d88dSmrg case GL_PALETTE4_RGBA8_OES: 2979af69d88dSmrg case GL_PALETTE4_R5_G6_B5_OES: 2980af69d88dSmrg case GL_PALETTE4_RGBA4_OES: 2981af69d88dSmrg case GL_PALETTE4_RGB5_A1_OES: 2982af69d88dSmrg case GL_PALETTE8_RGB8_OES: 2983af69d88dSmrg case GL_PALETTE8_RGBA8_OES: 2984af69d88dSmrg case GL_PALETTE8_R5_G6_B5_OES: 2985af69d88dSmrg case GL_PALETTE8_RGBA4_OES: 2986af69d88dSmrg case GL_PALETTE8_RGB5_A1_OES: 2987af69d88dSmrg _mesa_cpal_compressed_teximage2d(target, level, internalFormat, 2988af69d88dSmrg width, height, imageSize, pixels); 2989af69d88dSmrg return; 2990af69d88dSmrg } 2991af69d88dSmrg } 2992af69d88dSmrg 2993af69d88dSmrg texObj = _mesa_get_current_tex_object(ctx, target); 2994af69d88dSmrg assert(texObj); 2995af69d88dSmrg 2996af69d88dSmrg if (compressed) { 2997af69d88dSmrg /* For glCompressedTexImage() the driver has no choice about the 2998af69d88dSmrg * texture format since we'll never transcode the user's compressed 2999af69d88dSmrg * image data. The internalFormat was error checked earlier. 3000af69d88dSmrg */ 3001af69d88dSmrg texFormat = _mesa_glenum_to_compressed_format(internalFormat); 3002af69d88dSmrg } 3003af69d88dSmrg else { 300401e04c3fSmrg /* In case of HALF_FLOAT_OES or FLOAT_OES, find corresponding sized 300501e04c3fSmrg * internal floating point format for the given base format. 300601e04c3fSmrg */ 300701e04c3fSmrg if (_mesa_is_gles(ctx) && format == internalFormat) { 300801e04c3fSmrg if (type == GL_FLOAT) { 300901e04c3fSmrg texObj->_IsFloat = GL_TRUE; 301001e04c3fSmrg } else if (type == GL_HALF_FLOAT_OES || type == GL_HALF_FLOAT) { 301101e04c3fSmrg texObj->_IsHalfFloat = GL_TRUE; 301201e04c3fSmrg } 301301e04c3fSmrg 301401e04c3fSmrg internalFormat = adjust_for_oes_float_texture(ctx, format, type); 301501e04c3fSmrg } 301601e04c3fSmrg 3017af69d88dSmrg texFormat = _mesa_choose_texture_format(ctx, texObj, target, level, 3018af69d88dSmrg internalFormat, format, type); 3019af69d88dSmrg } 3020af69d88dSmrg 3021af69d88dSmrg assert(texFormat != MESA_FORMAT_NONE); 3022af69d88dSmrg 302301e04c3fSmrg if (!no_error) { 302401e04c3fSmrg /* check that width, height, depth are legal for the mipmap level */ 302501e04c3fSmrg dimensionsOK = _mesa_legal_texture_dimensions(ctx, target, level, width, 302601e04c3fSmrg height, depth, border); 3027af69d88dSmrg 302801e04c3fSmrg /* check that the texture won't take too much memory, etc */ 302901e04c3fSmrg sizeOK = ctx->Driver.TestProxyTexImage(ctx, proxy_target(target), 303001e04c3fSmrg 0, level, texFormat, 1, 303101e04c3fSmrg width, height, depth); 303201e04c3fSmrg } 3033af69d88dSmrg 3034af69d88dSmrg if (_mesa_is_proxy_texture(target)) { 3035af69d88dSmrg /* Proxy texture: just clear or set state depending on error checking */ 3036af69d88dSmrg struct gl_texture_image *texImage = 3037af69d88dSmrg get_proxy_tex_image(ctx, target, level); 3038af69d88dSmrg 3039af69d88dSmrg if (!texImage) 3040af69d88dSmrg return; /* GL_OUT_OF_MEMORY already recorded */ 3041af69d88dSmrg 3042af69d88dSmrg if (dimensionsOK && sizeOK) { 3043af69d88dSmrg _mesa_init_teximage_fields(ctx, texImage, width, height, depth, 3044af69d88dSmrg border, internalFormat, texFormat); 3045af69d88dSmrg } 3046af69d88dSmrg else { 3047af69d88dSmrg clear_teximage_fields(texImage); 3048af69d88dSmrg } 3049af69d88dSmrg } 3050af69d88dSmrg else { 3051af69d88dSmrg /* non-proxy target */ 3052af69d88dSmrg const GLuint face = _mesa_tex_target_to_face(target); 3053af69d88dSmrg struct gl_texture_image *texImage; 3054af69d88dSmrg 3055af69d88dSmrg if (!dimensionsOK) { 3056af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 305701e04c3fSmrg "%s%uD(invalid width=%d or height=%d or depth=%d)", 305801e04c3fSmrg func, dims, width, height, depth); 3059af69d88dSmrg return; 3060af69d88dSmrg } 3061af69d88dSmrg 3062af69d88dSmrg if (!sizeOK) { 3063af69d88dSmrg _mesa_error(ctx, GL_OUT_OF_MEMORY, 306401e04c3fSmrg "%s%uD(image too large: %d x %d x %d, %s format)", 306501e04c3fSmrg func, dims, width, height, depth, 306601e04c3fSmrg _mesa_enum_to_string(internalFormat)); 3067af69d88dSmrg return; 3068af69d88dSmrg } 3069af69d88dSmrg 3070af69d88dSmrg /* Allow a hardware driver to just strip out the border, to provide 3071af69d88dSmrg * reliable but slightly incorrect hardware rendering instead of 3072af69d88dSmrg * rarely-tested software fallback rendering. 3073af69d88dSmrg */ 3074af69d88dSmrg if (border && ctx->Const.StripTextureBorder) { 307501e04c3fSmrg strip_texture_border(target, &width, &height, &depth, unpack, 307601e04c3fSmrg &unpack_no_border); 3077af69d88dSmrg border = 0; 307801e04c3fSmrg unpack = &unpack_no_border; 30797117f1b4Smrg } 30807117f1b4Smrg 30813464ebd5Sriastradh if (ctx->NewState & _NEW_PIXEL) 308201e04c3fSmrg _mesa_update_state(ctx); 30837117f1b4Smrg 30847117f1b4Smrg _mesa_lock_texture(ctx, texObj); 30857117f1b4Smrg { 308601e04c3fSmrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 30873464ebd5Sriastradh 308801e04c3fSmrg if (!texImage) { 308901e04c3fSmrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s%uD", func, dims); 309001e04c3fSmrg } 30914a49301eSmrg else { 3092af69d88dSmrg ctx->Driver.FreeTextureImageBuffer(ctx, texImage); 30933464ebd5Sriastradh 3094af69d88dSmrg _mesa_init_teximage_fields(ctx, texImage, 3095af69d88dSmrg width, height, depth, 3096af69d88dSmrg border, internalFormat, texFormat); 30974a49301eSmrg 3098af69d88dSmrg /* Give the texture to the driver. <pixels> may be null. */ 3099af69d88dSmrg if (width > 0 && height > 0 && depth > 0) { 3100af69d88dSmrg if (compressed) { 3101af69d88dSmrg ctx->Driver.CompressedTexImage(ctx, dims, texImage, 3102af69d88dSmrg imageSize, pixels); 3103af69d88dSmrg } 3104af69d88dSmrg else { 3105af69d88dSmrg ctx->Driver.TexImage(ctx, dims, texImage, format, 3106af69d88dSmrg type, pixels, unpack); 31073464ebd5Sriastradh } 3108af69d88dSmrg } 31094a49301eSmrg 3110af69d88dSmrg check_gen_mipmap(ctx, target, texObj, level); 31114a49301eSmrg 3112af69d88dSmrg _mesa_update_fbo_texture(ctx, texObj, face, level); 31134a49301eSmrg 3114af69d88dSmrg _mesa_dirty_texobj(ctx, texObj); 31153464ebd5Sriastradh } 31163464ebd5Sriastradh } 31173464ebd5Sriastradh _mesa_unlock_texture(ctx, texObj); 31183464ebd5Sriastradh } 31193464ebd5Sriastradh} 31207117f1b4Smrg 31214a49301eSmrg 312201e04c3fSmrg/* This is a wrapper around teximage() so that we can force the KHR_no_error 312301e04c3fSmrg * logic to be inlined without inlining the function into all the callers. 312401e04c3fSmrg */ 312501e04c3fSmrgstatic void 312601e04c3fSmrgteximage_err(struct gl_context *ctx, GLboolean compressed, GLuint dims, 312701e04c3fSmrg GLenum target, GLint level, GLint internalFormat, 312801e04c3fSmrg GLsizei width, GLsizei height, GLsizei depth, 312901e04c3fSmrg GLint border, GLenum format, GLenum type, 313001e04c3fSmrg GLsizei imageSize, const GLvoid *pixels) 313101e04c3fSmrg{ 313201e04c3fSmrg teximage(ctx, compressed, dims, target, level, internalFormat, width, height, 313301e04c3fSmrg depth, border, format, type, imageSize, pixels, false); 313401e04c3fSmrg} 313501e04c3fSmrg 313601e04c3fSmrg 313701e04c3fSmrgstatic void 313801e04c3fSmrgteximage_no_error(struct gl_context *ctx, GLboolean compressed, GLuint dims, 313901e04c3fSmrg GLenum target, GLint level, GLint internalFormat, 314001e04c3fSmrg GLsizei width, GLsizei height, GLsizei depth, 314101e04c3fSmrg GLint border, GLenum format, GLenum type, 314201e04c3fSmrg GLsizei imageSize, const GLvoid *pixels) 314301e04c3fSmrg{ 314401e04c3fSmrg teximage(ctx, compressed, dims, target, level, internalFormat, width, height, 314501e04c3fSmrg depth, border, format, type, imageSize, pixels, true); 314601e04c3fSmrg} 314701e04c3fSmrg 3148af69d88dSmrg 31493464ebd5Sriastradh/* 31503464ebd5Sriastradh * Called from the API. Note that width includes the border. 31513464ebd5Sriastradh */ 31523464ebd5Sriastradhvoid GLAPIENTRY 31533464ebd5Sriastradh_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat, 31543464ebd5Sriastradh GLsizei width, GLint border, GLenum format, 31553464ebd5Sriastradh GLenum type, const GLvoid *pixels ) 31563464ebd5Sriastradh{ 31573464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 315801e04c3fSmrg teximage_err(ctx, GL_FALSE, 1, target, level, internalFormat, width, 1, 1, 315901e04c3fSmrg border, format, type, 0, pixels); 31607117f1b4Smrg} 31617117f1b4Smrg 31627117f1b4Smrg 31637117f1b4Smrgvoid GLAPIENTRY 31647117f1b4Smrg_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat, 31657117f1b4Smrg GLsizei width, GLsizei height, GLint border, 31667117f1b4Smrg GLenum format, GLenum type, 31677117f1b4Smrg const GLvoid *pixels ) 31687117f1b4Smrg{ 31697117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 317001e04c3fSmrg teximage_err(ctx, GL_FALSE, 2, target, level, internalFormat, width, height, 1, 317101e04c3fSmrg border, format, type, 0, pixels); 31727117f1b4Smrg} 31737117f1b4Smrg 31747117f1b4Smrg 31757117f1b4Smrg/* 31767117f1b4Smrg * Called by the API or display list executor. 31777117f1b4Smrg * Note that width and height include the border. 31787117f1b4Smrg */ 31797117f1b4Smrgvoid GLAPIENTRY 31807117f1b4Smrg_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat, 31817117f1b4Smrg GLsizei width, GLsizei height, GLsizei depth, 31827117f1b4Smrg GLint border, GLenum format, GLenum type, 31837117f1b4Smrg const GLvoid *pixels ) 31847117f1b4Smrg{ 31857117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 318601e04c3fSmrg teximage_err(ctx, GL_FALSE, 3, target, level, internalFormat, 318701e04c3fSmrg width, height, depth, border, format, type, 0, pixels); 31887117f1b4Smrg} 31897117f1b4Smrg 31907117f1b4Smrg 31917117f1b4Smrgvoid GLAPIENTRY 31927117f1b4Smrg_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat, 31937117f1b4Smrg GLsizei width, GLsizei height, GLsizei depth, 31947117f1b4Smrg GLint border, GLenum format, GLenum type, 31957117f1b4Smrg const GLvoid *pixels ) 31967117f1b4Smrg{ 31977117f1b4Smrg _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height, 31987117f1b4Smrg depth, border, format, type, pixels); 31997117f1b4Smrg} 32007117f1b4Smrg 32017117f1b4Smrg 320201e04c3fSmrgvoid GLAPIENTRY 320301e04c3fSmrg_mesa_TexImage1D_no_error(GLenum target, GLint level, GLint internalFormat, 320401e04c3fSmrg GLsizei width, GLint border, GLenum format, 320501e04c3fSmrg GLenum type, const GLvoid *pixels) 320601e04c3fSmrg{ 320701e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 320801e04c3fSmrg teximage_no_error(ctx, GL_FALSE, 1, target, level, internalFormat, width, 1, 320901e04c3fSmrg 1, border, format, type, 0, pixels); 321001e04c3fSmrg} 321101e04c3fSmrg 321201e04c3fSmrg 321301e04c3fSmrgvoid GLAPIENTRY 321401e04c3fSmrg_mesa_TexImage2D_no_error(GLenum target, GLint level, GLint internalFormat, 321501e04c3fSmrg GLsizei width, GLsizei height, GLint border, 321601e04c3fSmrg GLenum format, GLenum type, const GLvoid *pixels) 321701e04c3fSmrg{ 321801e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 321901e04c3fSmrg teximage_no_error(ctx, GL_FALSE, 2, target, level, internalFormat, width, 322001e04c3fSmrg height, 1, border, format, type, 0, pixels); 322101e04c3fSmrg} 322201e04c3fSmrg 322301e04c3fSmrg 322401e04c3fSmrgvoid GLAPIENTRY 322501e04c3fSmrg_mesa_TexImage3D_no_error(GLenum target, GLint level, GLint internalFormat, 322601e04c3fSmrg GLsizei width, GLsizei height, GLsizei depth, 322701e04c3fSmrg GLint border, GLenum format, GLenum type, 322801e04c3fSmrg const GLvoid *pixels ) 322901e04c3fSmrg{ 323001e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 323101e04c3fSmrg teximage_no_error(ctx, GL_FALSE, 3, target, level, internalFormat, 323201e04c3fSmrg width, height, depth, border, format, type, 0, pixels); 323301e04c3fSmrg} 323401e04c3fSmrg 323501e04c3fSmrg 3236cdc920a0Smrgvoid GLAPIENTRY 3237cdc920a0Smrg_mesa_EGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image) 3238cdc920a0Smrg{ 3239cdc920a0Smrg struct gl_texture_object *texObj; 3240cdc920a0Smrg struct gl_texture_image *texImage; 3241af69d88dSmrg bool valid_target; 3242cdc920a0Smrg GET_CURRENT_CONTEXT(ctx); 3243af69d88dSmrg FLUSH_VERTICES(ctx, 0); 3244cdc920a0Smrg 3245af69d88dSmrg switch (target) { 3246af69d88dSmrg case GL_TEXTURE_2D: 3247af69d88dSmrg valid_target = ctx->Extensions.OES_EGL_image; 3248af69d88dSmrg break; 3249af69d88dSmrg case GL_TEXTURE_EXTERNAL_OES: 3250af69d88dSmrg valid_target = 3251af69d88dSmrg _mesa_is_gles(ctx) ? ctx->Extensions.OES_EGL_image_external : false; 3252af69d88dSmrg break; 3253af69d88dSmrg default: 3254af69d88dSmrg valid_target = false; 3255af69d88dSmrg break; 32563464ebd5Sriastradh } 32573464ebd5Sriastradh 3258af69d88dSmrg if (!valid_target) { 3259cdc920a0Smrg _mesa_error(ctx, GL_INVALID_ENUM, 326001e04c3fSmrg "glEGLImageTargetTexture2D(target=%d)", target); 3261cdc920a0Smrg return; 3262cdc920a0Smrg } 3263cdc920a0Smrg 3264af69d88dSmrg if (!image) { 3265af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 326601e04c3fSmrg "glEGLImageTargetTexture2D(image=%p)", image); 3267af69d88dSmrg return; 3268af69d88dSmrg } 3269af69d88dSmrg 32703464ebd5Sriastradh if (ctx->NewState & _NEW_PIXEL) 3271cdc920a0Smrg _mesa_update_state(ctx); 3272cdc920a0Smrg 3273cdc920a0Smrg texObj = _mesa_get_current_tex_object(ctx, target); 327401e04c3fSmrg if (!texObj) 327501e04c3fSmrg return; 327601e04c3fSmrg 3277cdc920a0Smrg _mesa_lock_texture(ctx, texObj); 3278cdc920a0Smrg 3279af69d88dSmrg if (texObj->Immutable) { 3280af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 328101e04c3fSmrg "glEGLImageTargetTexture2D(texture is immutable)"); 3282af69d88dSmrg _mesa_unlock_texture(ctx, texObj); 3283af69d88dSmrg return; 3284af69d88dSmrg } 3285af69d88dSmrg 3286cdc920a0Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, 0); 3287cdc920a0Smrg if (!texImage) { 3288cdc920a0Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glEGLImageTargetTexture2D"); 3289cdc920a0Smrg } else { 3290af69d88dSmrg ctx->Driver.FreeTextureImageBuffer(ctx, texImage); 3291cdc920a0Smrg 3292cdc920a0Smrg ctx->Driver.EGLImageTargetTexture2D(ctx, target, 329301e04c3fSmrg texObj, texImage, image); 3294cdc920a0Smrg 3295af69d88dSmrg _mesa_dirty_texobj(ctx, texObj); 3296cdc920a0Smrg } 3297cdc920a0Smrg _mesa_unlock_texture(ctx, texObj); 3298cdc920a0Smrg} 3299cdc920a0Smrg 33007117f1b4Smrg 33013464ebd5Sriastradh/** 330201e04c3fSmrg * Helper that implements the glTexSubImage1/2/3D() 330301e04c3fSmrg * and glTextureSubImage1/2/3D() functions. 33043464ebd5Sriastradh */ 33053464ebd5Sriastradhstatic void 330601e04c3fSmrgtexture_sub_image(struct gl_context *ctx, GLuint dims, 330701e04c3fSmrg struct gl_texture_object *texObj, 330801e04c3fSmrg struct gl_texture_image *texImage, 330901e04c3fSmrg GLenum target, GLint level, 331001e04c3fSmrg GLint xoffset, GLint yoffset, GLint zoffset, 331101e04c3fSmrg GLsizei width, GLsizei height, GLsizei depth, 331201e04c3fSmrg GLenum format, GLenum type, const GLvoid *pixels) 33137117f1b4Smrg{ 3314af69d88dSmrg FLUSH_VERTICES(ctx, 0); 33157117f1b4Smrg 33163464ebd5Sriastradh if (ctx->NewState & _NEW_PIXEL) 33173464ebd5Sriastradh _mesa_update_state(ctx); 33187117f1b4Smrg 33197117f1b4Smrg _mesa_lock_texture(ctx, texObj); 33207117f1b4Smrg { 3321af69d88dSmrg if (width > 0 && height > 0 && depth > 0) { 33223464ebd5Sriastradh /* If we have a border, offset=-1 is legal. Bias by border width. */ 33233464ebd5Sriastradh switch (dims) { 33243464ebd5Sriastradh case 3: 3325af69d88dSmrg if (target != GL_TEXTURE_2D_ARRAY) 3326af69d88dSmrg zoffset += texImage->Border; 33273464ebd5Sriastradh /* fall-through */ 33283464ebd5Sriastradh case 2: 3329af69d88dSmrg if (target != GL_TEXTURE_1D_ARRAY) 3330af69d88dSmrg yoffset += texImage->Border; 33313464ebd5Sriastradh /* fall-through */ 33323464ebd5Sriastradh case 1: 33333464ebd5Sriastradh xoffset += texImage->Border; 33343464ebd5Sriastradh } 33357117f1b4Smrg 3336af69d88dSmrg ctx->Driver.TexSubImage(ctx, dims, texImage, 3337af69d88dSmrg xoffset, yoffset, zoffset, 3338af69d88dSmrg width, height, depth, 3339af69d88dSmrg format, type, pixels, &ctx->Unpack); 33407117f1b4Smrg 33414a49301eSmrg check_gen_mipmap(ctx, target, texObj, level); 33427117f1b4Smrg 334301e04c3fSmrg /* NOTE: Don't signal _NEW_TEXTURE_OBJECT since we've only changed 3344af69d88dSmrg * the texel data, not the texture format, size, etc. 3345af69d88dSmrg */ 33464a49301eSmrg } 33477117f1b4Smrg } 33487117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 33497117f1b4Smrg} 33507117f1b4Smrg 335101e04c3fSmrg/** 335201e04c3fSmrg * Implement all the glTexSubImage1/2/3D() functions. 335301e04c3fSmrg * Must split this out this way because of GL_TEXTURE_CUBE_MAP. 335401e04c3fSmrg */ 335501e04c3fSmrgstatic void 335601e04c3fSmrgtexsubimage_err(struct gl_context *ctx, GLuint dims, GLenum target, GLint level, 335701e04c3fSmrg GLint xoffset, GLint yoffset, GLint zoffset, 335801e04c3fSmrg GLsizei width, GLsizei height, GLsizei depth, 335901e04c3fSmrg GLenum format, GLenum type, const GLvoid *pixels, 336001e04c3fSmrg const char *callerName) 336101e04c3fSmrg{ 336201e04c3fSmrg struct gl_texture_object *texObj; 336301e04c3fSmrg struct gl_texture_image *texImage; 336401e04c3fSmrg 336501e04c3fSmrg /* check target (proxies not allowed) */ 336601e04c3fSmrg if (!legal_texsubimage_target(ctx, dims, target, false)) { 336701e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage%uD(target=%s)", 336801e04c3fSmrg dims, _mesa_enum_to_string(target)); 336901e04c3fSmrg return; 337001e04c3fSmrg } 337101e04c3fSmrg 337201e04c3fSmrg texObj = _mesa_get_current_tex_object(ctx, target); 337301e04c3fSmrg if (!texObj) 337401e04c3fSmrg return; 337501e04c3fSmrg 337601e04c3fSmrg if (texsubimage_error_check(ctx, dims, texObj, target, level, 337701e04c3fSmrg xoffset, yoffset, zoffset, 337801e04c3fSmrg width, height, depth, format, type, 337901e04c3fSmrg pixels, callerName)) { 338001e04c3fSmrg return; /* error was detected */ 338101e04c3fSmrg } 338201e04c3fSmrg 338301e04c3fSmrg texImage = _mesa_select_tex_image(texObj, target, level); 338401e04c3fSmrg /* texsubimage_error_check ensures that texImage is not NULL */ 338501e04c3fSmrg 338601e04c3fSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 338701e04c3fSmrg _mesa_debug(ctx, "glTexSubImage%uD %s %d %d %d %d %d %d %d %s %s %p\n", 338801e04c3fSmrg dims, 338901e04c3fSmrg _mesa_enum_to_string(target), level, 339001e04c3fSmrg xoffset, yoffset, zoffset, width, height, depth, 339101e04c3fSmrg _mesa_enum_to_string(format), 339201e04c3fSmrg _mesa_enum_to_string(type), pixels); 339301e04c3fSmrg 339401e04c3fSmrg texture_sub_image(ctx, dims, texObj, texImage, target, level, 339501e04c3fSmrg xoffset, yoffset, zoffset, width, height, depth, 339601e04c3fSmrg format, type, pixels); 339701e04c3fSmrg} 339801e04c3fSmrg 339901e04c3fSmrg 340001e04c3fSmrgstatic void 340101e04c3fSmrgtexsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level, 340201e04c3fSmrg GLint xoffset, GLint yoffset, GLint zoffset, 340301e04c3fSmrg GLsizei width, GLsizei height, GLsizei depth, 340401e04c3fSmrg GLenum format, GLenum type, const GLvoid *pixels) 340501e04c3fSmrg{ 340601e04c3fSmrg struct gl_texture_object *texObj; 340701e04c3fSmrg struct gl_texture_image *texImage; 340801e04c3fSmrg 340901e04c3fSmrg texObj = _mesa_get_current_tex_object(ctx, target); 341001e04c3fSmrg texImage = _mesa_select_tex_image(texObj, target, level); 341101e04c3fSmrg 341201e04c3fSmrg texture_sub_image(ctx, dims, texObj, texImage, target, level, 341301e04c3fSmrg xoffset, yoffset, zoffset, width, height, depth, 341401e04c3fSmrg format, type, pixels); 341501e04c3fSmrg} 341601e04c3fSmrg 341701e04c3fSmrg 341801e04c3fSmrg/** 341901e04c3fSmrg * Implement all the glTextureSubImage1/2/3D() functions. 342001e04c3fSmrg * Must split this out this way because of GL_TEXTURE_CUBE_MAP. 342101e04c3fSmrg */ 342201e04c3fSmrgstatic ALWAYS_INLINE void 342301e04c3fSmrgtexturesubimage(struct gl_context *ctx, GLuint dims, 342401e04c3fSmrg GLuint texture, GLint level, 342501e04c3fSmrg GLint xoffset, GLint yoffset, GLint zoffset, 342601e04c3fSmrg GLsizei width, GLsizei height, GLsizei depth, 342701e04c3fSmrg GLenum format, GLenum type, const GLvoid *pixels, 342801e04c3fSmrg const char *callerName, bool no_error) 342901e04c3fSmrg{ 343001e04c3fSmrg struct gl_texture_object *texObj; 343101e04c3fSmrg struct gl_texture_image *texImage; 343201e04c3fSmrg int i; 343301e04c3fSmrg 343401e04c3fSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 343501e04c3fSmrg _mesa_debug(ctx, 343601e04c3fSmrg "glTextureSubImage%uD %d %d %d %d %d %d %d %d %s %s %p\n", 343701e04c3fSmrg dims, texture, level, 343801e04c3fSmrg xoffset, yoffset, zoffset, width, height, depth, 343901e04c3fSmrg _mesa_enum_to_string(format), 344001e04c3fSmrg _mesa_enum_to_string(type), pixels); 344101e04c3fSmrg 344201e04c3fSmrg /* Get the texture object by Name. */ 344301e04c3fSmrg if (!no_error) { 344401e04c3fSmrg texObj = _mesa_lookup_texture_err(ctx, texture, callerName); 344501e04c3fSmrg if (!texObj) 344601e04c3fSmrg return; 344701e04c3fSmrg } else { 344801e04c3fSmrg texObj = _mesa_lookup_texture(ctx, texture); 344901e04c3fSmrg } 345001e04c3fSmrg 345101e04c3fSmrg if (!no_error) { 345201e04c3fSmrg /* check target (proxies not allowed) */ 345301e04c3fSmrg if (!legal_texsubimage_target(ctx, dims, texObj->Target, true)) { 345401e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, "%s(target=%s)", 345501e04c3fSmrg callerName, _mesa_enum_to_string(texObj->Target)); 345601e04c3fSmrg return; 345701e04c3fSmrg } 345801e04c3fSmrg 345901e04c3fSmrg if (texsubimage_error_check(ctx, dims, texObj, texObj->Target, level, 346001e04c3fSmrg xoffset, yoffset, zoffset, 346101e04c3fSmrg width, height, depth, format, type, 346201e04c3fSmrg pixels, callerName)) { 346301e04c3fSmrg return; /* error was detected */ 346401e04c3fSmrg } 346501e04c3fSmrg } 346601e04c3fSmrg 346701e04c3fSmrg /* Must handle special case GL_TEXTURE_CUBE_MAP. */ 346801e04c3fSmrg if (texObj->Target == GL_TEXTURE_CUBE_MAP) { 346901e04c3fSmrg GLint imageStride; 347001e04c3fSmrg 347101e04c3fSmrg /* 347201e04c3fSmrg * What do we do if the user created a texture with the following code 347301e04c3fSmrg * and then called this function with its handle? 347401e04c3fSmrg * 347501e04c3fSmrg * GLuint tex; 347601e04c3fSmrg * glCreateTextures(GL_TEXTURE_CUBE_MAP, 1, &tex); 347701e04c3fSmrg * glBindTexture(GL_TEXTURE_CUBE_MAP, tex); 347801e04c3fSmrg * glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, ...); 347901e04c3fSmrg * glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, ...); 348001e04c3fSmrg * glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, ...); 348101e04c3fSmrg * // Note: GL_TEXTURE_CUBE_MAP_NEGATIVE_Y not set, or given the 348201e04c3fSmrg * // wrong format, or given the wrong size, etc. 348301e04c3fSmrg * glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, ...); 348401e04c3fSmrg * glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, ...); 348501e04c3fSmrg * 348601e04c3fSmrg * A bug has been filed against the spec for this case. In the 348701e04c3fSmrg * meantime, we will check for cube completeness. 348801e04c3fSmrg * 348901e04c3fSmrg * According to Section 8.17 Texture Completeness in the OpenGL 4.5 349001e04c3fSmrg * Core Profile spec (30.10.2014): 349101e04c3fSmrg * "[A] cube map texture is cube complete if the 349201e04c3fSmrg * following conditions all hold true: The [base level] texture 349301e04c3fSmrg * images of each of the six cube map faces have identical, positive, 349401e04c3fSmrg * and square dimensions. The [base level] images were each specified 349501e04c3fSmrg * with the same internal format." 349601e04c3fSmrg * 349701e04c3fSmrg * It seems reasonable to check for cube completeness of an arbitrary 349801e04c3fSmrg * level here so that the image data has a consistent format and size. 349901e04c3fSmrg */ 350001e04c3fSmrg if (!no_error && !_mesa_cube_level_complete(texObj, level)) { 350101e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 350201e04c3fSmrg "glTextureSubImage%uD(cube map incomplete)", 350301e04c3fSmrg dims); 350401e04c3fSmrg return; 350501e04c3fSmrg } 350601e04c3fSmrg 350701e04c3fSmrg imageStride = _mesa_image_image_stride(&ctx->Unpack, width, height, 350801e04c3fSmrg format, type); 350901e04c3fSmrg /* Copy in each face. */ 351001e04c3fSmrg for (i = zoffset; i < zoffset + depth; ++i) { 351101e04c3fSmrg texImage = texObj->Image[i][level]; 351201e04c3fSmrg assert(texImage); 351301e04c3fSmrg 351401e04c3fSmrg texture_sub_image(ctx, 3, texObj, texImage, texObj->Target, 351501e04c3fSmrg level, xoffset, yoffset, 0, 351601e04c3fSmrg width, height, 1, format, 351701e04c3fSmrg type, pixels); 351801e04c3fSmrg pixels = (GLubyte *) pixels + imageStride; 351901e04c3fSmrg } 352001e04c3fSmrg } 352101e04c3fSmrg else { 352201e04c3fSmrg texImage = _mesa_select_tex_image(texObj, texObj->Target, level); 352301e04c3fSmrg assert(texImage); 352401e04c3fSmrg 352501e04c3fSmrg texture_sub_image(ctx, dims, texObj, texImage, texObj->Target, 352601e04c3fSmrg level, xoffset, yoffset, zoffset, 352701e04c3fSmrg width, height, depth, format, 352801e04c3fSmrg type, pixels); 352901e04c3fSmrg } 353001e04c3fSmrg} 353101e04c3fSmrg 353201e04c3fSmrg 353301e04c3fSmrgstatic void 353401e04c3fSmrgtexturesubimage_error(struct gl_context *ctx, GLuint dims, 353501e04c3fSmrg GLuint texture, GLint level, 353601e04c3fSmrg GLint xoffset, GLint yoffset, GLint zoffset, 353701e04c3fSmrg GLsizei width, GLsizei height, GLsizei depth, 353801e04c3fSmrg GLenum format, GLenum type, const GLvoid *pixels, 353901e04c3fSmrg const char *callerName) 354001e04c3fSmrg{ 354101e04c3fSmrg texturesubimage(ctx, dims, texture, level, xoffset, yoffset, zoffset, 354201e04c3fSmrg width, height, depth, format, type, pixels, callerName, 354301e04c3fSmrg false); 354401e04c3fSmrg} 354501e04c3fSmrg 354601e04c3fSmrg 354701e04c3fSmrgstatic void 354801e04c3fSmrgtexturesubimage_no_error(struct gl_context *ctx, GLuint dims, 354901e04c3fSmrg GLuint texture, GLint level, 355001e04c3fSmrg GLint xoffset, GLint yoffset, GLint zoffset, 355101e04c3fSmrg GLsizei width, GLsizei height, GLsizei depth, 355201e04c3fSmrg GLenum format, GLenum type, const GLvoid *pixels, 355301e04c3fSmrg const char *callerName) 355401e04c3fSmrg{ 355501e04c3fSmrg texturesubimage(ctx, dims, texture, level, xoffset, yoffset, zoffset, 355601e04c3fSmrg width, height, depth, format, type, pixels, callerName, 355701e04c3fSmrg true); 355801e04c3fSmrg} 355901e04c3fSmrg 356001e04c3fSmrg 356101e04c3fSmrgvoid GLAPIENTRY 356201e04c3fSmrg_mesa_TexSubImage1D_no_error(GLenum target, GLint level, 356301e04c3fSmrg GLint xoffset, GLsizei width, 356401e04c3fSmrg GLenum format, GLenum type, 356501e04c3fSmrg const GLvoid *pixels) 356601e04c3fSmrg{ 356701e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 356801e04c3fSmrg texsubimage(ctx, 1, target, level, 356901e04c3fSmrg xoffset, 0, 0, 357001e04c3fSmrg width, 1, 1, 357101e04c3fSmrg format, type, pixels); 357201e04c3fSmrg} 357301e04c3fSmrg 357401e04c3fSmrg 357501e04c3fSmrgvoid GLAPIENTRY 357601e04c3fSmrg_mesa_TexSubImage1D( GLenum target, GLint level, 357701e04c3fSmrg GLint xoffset, GLsizei width, 357801e04c3fSmrg GLenum format, GLenum type, 357901e04c3fSmrg const GLvoid *pixels ) 358001e04c3fSmrg{ 358101e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 358201e04c3fSmrg texsubimage_err(ctx, 1, target, level, 358301e04c3fSmrg xoffset, 0, 0, 358401e04c3fSmrg width, 1, 1, 358501e04c3fSmrg format, type, pixels, "glTexSubImage1D"); 358601e04c3fSmrg} 358701e04c3fSmrg 358801e04c3fSmrg 358901e04c3fSmrgvoid GLAPIENTRY 359001e04c3fSmrg_mesa_TexSubImage2D_no_error(GLenum target, GLint level, 359101e04c3fSmrg GLint xoffset, GLint yoffset, 359201e04c3fSmrg GLsizei width, GLsizei height, 359301e04c3fSmrg GLenum format, GLenum type, 359401e04c3fSmrg const GLvoid *pixels) 359501e04c3fSmrg{ 359601e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 359701e04c3fSmrg texsubimage(ctx, 2, target, level, 359801e04c3fSmrg xoffset, yoffset, 0, 359901e04c3fSmrg width, height, 1, 360001e04c3fSmrg format, type, pixels); 360101e04c3fSmrg} 360201e04c3fSmrg 360301e04c3fSmrg 360401e04c3fSmrgvoid GLAPIENTRY 360501e04c3fSmrg_mesa_TexSubImage2D( GLenum target, GLint level, 360601e04c3fSmrg GLint xoffset, GLint yoffset, 360701e04c3fSmrg GLsizei width, GLsizei height, 360801e04c3fSmrg GLenum format, GLenum type, 360901e04c3fSmrg const GLvoid *pixels ) 361001e04c3fSmrg{ 361101e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 361201e04c3fSmrg texsubimage_err(ctx, 2, target, level, 361301e04c3fSmrg xoffset, yoffset, 0, 361401e04c3fSmrg width, height, 1, 361501e04c3fSmrg format, type, pixels, "glTexSubImage2D"); 361601e04c3fSmrg} 361701e04c3fSmrg 361801e04c3fSmrg 361901e04c3fSmrgvoid GLAPIENTRY 362001e04c3fSmrg_mesa_TexSubImage3D_no_error(GLenum target, GLint level, 362101e04c3fSmrg GLint xoffset, GLint yoffset, GLint zoffset, 362201e04c3fSmrg GLsizei width, GLsizei height, GLsizei depth, 362301e04c3fSmrg GLenum format, GLenum type, 362401e04c3fSmrg const GLvoid *pixels) 362501e04c3fSmrg{ 362601e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 362701e04c3fSmrg texsubimage(ctx, 3, target, level, 362801e04c3fSmrg xoffset, yoffset, zoffset, 362901e04c3fSmrg width, height, depth, 363001e04c3fSmrg format, type, pixels); 363101e04c3fSmrg} 363201e04c3fSmrg 363301e04c3fSmrg 363401e04c3fSmrgvoid GLAPIENTRY 363501e04c3fSmrg_mesa_TexSubImage3D( GLenum target, GLint level, 363601e04c3fSmrg GLint xoffset, GLint yoffset, GLint zoffset, 363701e04c3fSmrg GLsizei width, GLsizei height, GLsizei depth, 363801e04c3fSmrg GLenum format, GLenum type, 363901e04c3fSmrg const GLvoid *pixels ) 364001e04c3fSmrg{ 364101e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 364201e04c3fSmrg texsubimage_err(ctx, 3, target, level, 364301e04c3fSmrg xoffset, yoffset, zoffset, 364401e04c3fSmrg width, height, depth, 364501e04c3fSmrg format, type, pixels, "glTexSubImage3D"); 364601e04c3fSmrg} 364701e04c3fSmrg 364801e04c3fSmrg 364901e04c3fSmrgvoid GLAPIENTRY 365001e04c3fSmrg_mesa_TextureSubImage1D_no_error(GLuint texture, GLint level, GLint xoffset, 365101e04c3fSmrg GLsizei width, GLenum format, GLenum type, 365201e04c3fSmrg const GLvoid *pixels) 365301e04c3fSmrg{ 365401e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 365501e04c3fSmrg texturesubimage_no_error(ctx, 1, texture, level, xoffset, 0, 0, width, 1, 1, 365601e04c3fSmrg format, type, pixels, "glTextureSubImage1D"); 365701e04c3fSmrg} 365801e04c3fSmrg 365901e04c3fSmrg 366001e04c3fSmrgvoid GLAPIENTRY 366101e04c3fSmrg_mesa_TextureSubImage1D(GLuint texture, GLint level, 366201e04c3fSmrg GLint xoffset, GLsizei width, 366301e04c3fSmrg GLenum format, GLenum type, 366401e04c3fSmrg const GLvoid *pixels) 366501e04c3fSmrg{ 366601e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 366701e04c3fSmrg texturesubimage_error(ctx, 1, texture, level, xoffset, 0, 0, width, 1, 1, 366801e04c3fSmrg format, type, pixels, "glTextureSubImage1D"); 366901e04c3fSmrg} 367001e04c3fSmrg 367101e04c3fSmrg 367201e04c3fSmrgvoid GLAPIENTRY 367301e04c3fSmrg_mesa_TextureSubImage2D_no_error(GLuint texture, GLint level, GLint xoffset, 367401e04c3fSmrg GLint yoffset, GLsizei width, GLsizei height, 367501e04c3fSmrg GLenum format, GLenum type, 367601e04c3fSmrg const GLvoid *pixels) 367701e04c3fSmrg{ 367801e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 367901e04c3fSmrg texturesubimage_no_error(ctx, 2, texture, level, xoffset, yoffset, 0, width, 368001e04c3fSmrg height, 1, format, type, pixels, 368101e04c3fSmrg "glTextureSubImage2D"); 368201e04c3fSmrg} 368301e04c3fSmrg 36847117f1b4Smrg 36857117f1b4Smrgvoid GLAPIENTRY 368601e04c3fSmrg_mesa_TextureSubImage2D(GLuint texture, GLint level, 368701e04c3fSmrg GLint xoffset, GLint yoffset, 368801e04c3fSmrg GLsizei width, GLsizei height, 368901e04c3fSmrg GLenum format, GLenum type, 369001e04c3fSmrg const GLvoid *pixels) 36917117f1b4Smrg{ 36927117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 369301e04c3fSmrg texturesubimage_error(ctx, 2, texture, level, xoffset, yoffset, 0, width, 369401e04c3fSmrg height, 1, format, type, pixels, 369501e04c3fSmrg "glTextureSubImage2D"); 36967117f1b4Smrg} 36977117f1b4Smrg 36987117f1b4Smrg 36997117f1b4Smrgvoid GLAPIENTRY 370001e04c3fSmrg_mesa_TextureSubImage3D_no_error(GLuint texture, GLint level, GLint xoffset, 370101e04c3fSmrg GLint yoffset, GLint zoffset, GLsizei width, 370201e04c3fSmrg GLsizei height, GLsizei depth, GLenum format, 370301e04c3fSmrg GLenum type, const GLvoid *pixels) 37047117f1b4Smrg{ 37057117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 370601e04c3fSmrg texturesubimage_no_error(ctx, 3, texture, level, xoffset, yoffset, zoffset, 370701e04c3fSmrg width, height, depth, format, type, pixels, 370801e04c3fSmrg "glTextureSubImage3D"); 37097117f1b4Smrg} 37107117f1b4Smrg 37117117f1b4Smrg 37127117f1b4Smrgvoid GLAPIENTRY 371301e04c3fSmrg_mesa_TextureSubImage3D(GLuint texture, GLint level, 371401e04c3fSmrg GLint xoffset, GLint yoffset, GLint zoffset, 371501e04c3fSmrg GLsizei width, GLsizei height, GLsizei depth, 371601e04c3fSmrg GLenum format, GLenum type, 371701e04c3fSmrg const GLvoid *pixels) 37187117f1b4Smrg{ 37193464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 372001e04c3fSmrg texturesubimage_error(ctx, 3, texture, level, xoffset, yoffset, zoffset, 372101e04c3fSmrg width, height, depth, format, type, pixels, 372201e04c3fSmrg "glTextureSubImage3D"); 37237117f1b4Smrg} 37247117f1b4Smrg 37257117f1b4Smrg 3726af69d88dSmrg/** 3727af69d88dSmrg * For glCopyTexSubImage, return the source renderbuffer to copy texel data 3728af69d88dSmrg * from. This depends on whether the texture contains color or depth values. 3729af69d88dSmrg */ 3730af69d88dSmrgstatic struct gl_renderbuffer * 3731af69d88dSmrgget_copy_tex_image_source(struct gl_context *ctx, mesa_format texFormat) 3732af69d88dSmrg{ 3733af69d88dSmrg if (_mesa_get_format_bits(texFormat, GL_DEPTH_BITS) > 0) { 3734af69d88dSmrg /* reading from depth/stencil buffer */ 3735af69d88dSmrg return ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; 373601e04c3fSmrg } else if (_mesa_get_format_bits(texFormat, GL_STENCIL_BITS) > 0) { 373701e04c3fSmrg return ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer; 373801e04c3fSmrg } else { 3739af69d88dSmrg /* copying from color buffer */ 3740af69d88dSmrg return ctx->ReadBuffer->_ColorReadBuffer; 3741af69d88dSmrg } 3742af69d88dSmrg} 3743af69d88dSmrg 374401e04c3fSmrg 3745af69d88dSmrgstatic void 3746af69d88dSmrgcopytexsubimage_by_slice(struct gl_context *ctx, 3747af69d88dSmrg struct gl_texture_image *texImage, 3748af69d88dSmrg GLuint dims, 3749af69d88dSmrg GLint xoffset, GLint yoffset, GLint zoffset, 3750af69d88dSmrg struct gl_renderbuffer *rb, 3751af69d88dSmrg GLint x, GLint y, 3752af69d88dSmrg GLsizei width, GLsizei height) 3753af69d88dSmrg{ 3754af69d88dSmrg if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) { 3755af69d88dSmrg int slice; 3756af69d88dSmrg 3757af69d88dSmrg /* For 1D arrays, we copy each scanline of the source rectangle into the 3758af69d88dSmrg * next array slice. 3759af69d88dSmrg */ 3760af69d88dSmrg assert(zoffset == 0); 3761af69d88dSmrg 3762af69d88dSmrg for (slice = 0; slice < height; slice++) { 3763af69d88dSmrg assert(yoffset + slice < texImage->Height); 3764af69d88dSmrg ctx->Driver.CopyTexSubImage(ctx, 2, texImage, 3765af69d88dSmrg xoffset, 0, yoffset + slice, 3766af69d88dSmrg rb, x, y + slice, width, 1); 3767af69d88dSmrg } 3768af69d88dSmrg } else { 3769af69d88dSmrg ctx->Driver.CopyTexSubImage(ctx, dims, texImage, 3770af69d88dSmrg xoffset, yoffset, zoffset, 3771af69d88dSmrg rb, x, y, width, height); 3772af69d88dSmrg } 3773af69d88dSmrg} 3774af69d88dSmrg 377501e04c3fSmrg 3776af69d88dSmrgstatic GLboolean 377701e04c3fSmrgformats_differ_in_component_sizes(mesa_format f1, mesa_format f2) 3778af69d88dSmrg{ 3779af69d88dSmrg GLint f1_r_bits = _mesa_get_format_bits(f1, GL_RED_BITS); 3780af69d88dSmrg GLint f1_g_bits = _mesa_get_format_bits(f1, GL_GREEN_BITS); 3781af69d88dSmrg GLint f1_b_bits = _mesa_get_format_bits(f1, GL_BLUE_BITS); 3782af69d88dSmrg GLint f1_a_bits = _mesa_get_format_bits(f1, GL_ALPHA_BITS); 3783af69d88dSmrg 3784af69d88dSmrg GLint f2_r_bits = _mesa_get_format_bits(f2, GL_RED_BITS); 3785af69d88dSmrg GLint f2_g_bits = _mesa_get_format_bits(f2, GL_GREEN_BITS); 3786af69d88dSmrg GLint f2_b_bits = _mesa_get_format_bits(f2, GL_BLUE_BITS); 3787af69d88dSmrg GLint f2_a_bits = _mesa_get_format_bits(f2, GL_ALPHA_BITS); 3788af69d88dSmrg 3789af69d88dSmrg if ((f1_r_bits && f2_r_bits && f1_r_bits != f2_r_bits) 3790af69d88dSmrg || (f1_g_bits && f2_g_bits && f1_g_bits != f2_g_bits) 3791af69d88dSmrg || (f1_b_bits && f2_b_bits && f1_b_bits != f2_b_bits) 3792af69d88dSmrg || (f1_a_bits && f2_a_bits && f1_a_bits != f2_a_bits)) 3793af69d88dSmrg return GL_TRUE; 3794af69d88dSmrg 3795af69d88dSmrg return GL_FALSE; 3796af69d88dSmrg} 3797af69d88dSmrg 379801e04c3fSmrg 37993464ebd5Sriastradh/** 380001e04c3fSmrg * Check if the given texture format and size arguments match those 380101e04c3fSmrg * of the texture image. 380201e04c3fSmrg * \param return true if arguments match, false otherwise. 380301e04c3fSmrg */ 380401e04c3fSmrgstatic bool 380501e04c3fSmrgcan_avoid_reallocation(const struct gl_texture_image *texImage, 380601e04c3fSmrg GLenum internalFormat, 380701e04c3fSmrg mesa_format texFormat, GLsizei width, 380801e04c3fSmrg GLsizei height, GLint border) 380901e04c3fSmrg{ 381001e04c3fSmrg if (texImage->InternalFormat != internalFormat) 381101e04c3fSmrg return false; 381201e04c3fSmrg if (texImage->TexFormat != texFormat) 381301e04c3fSmrg return false; 381401e04c3fSmrg if (texImage->Border != border) 381501e04c3fSmrg return false; 381601e04c3fSmrg if (texImage->Width2 != width) 381701e04c3fSmrg return false; 381801e04c3fSmrg if (texImage->Height2 != height) 381901e04c3fSmrg return false; 382001e04c3fSmrg return true; 382101e04c3fSmrg} 382201e04c3fSmrg 382301e04c3fSmrg 382401e04c3fSmrg/** 382501e04c3fSmrg * Implementation for glCopyTex(ture)SubImage1/2/3D() functions. 38263464ebd5Sriastradh */ 38273464ebd5Sriastradhstatic void 382801e04c3fSmrgcopy_texture_sub_image(struct gl_context *ctx, GLuint dims, 382901e04c3fSmrg struct gl_texture_object *texObj, 383001e04c3fSmrg GLenum target, GLint level, 383101e04c3fSmrg GLint xoffset, GLint yoffset, GLint zoffset, 383201e04c3fSmrg GLint x, GLint y, GLsizei width, GLsizei height) 383301e04c3fSmrg{ 383401e04c3fSmrg struct gl_texture_image *texImage; 383501e04c3fSmrg 383601e04c3fSmrg _mesa_lock_texture(ctx, texObj); 383701e04c3fSmrg 383801e04c3fSmrg texImage = _mesa_select_tex_image(texObj, target, level); 383901e04c3fSmrg 384001e04c3fSmrg /* If we have a border, offset=-1 is legal. Bias by border width. */ 384101e04c3fSmrg switch (dims) { 384201e04c3fSmrg case 3: 384301e04c3fSmrg if (target != GL_TEXTURE_2D_ARRAY) 384401e04c3fSmrg zoffset += texImage->Border; 384501e04c3fSmrg /* fall-through */ 384601e04c3fSmrg case 2: 384701e04c3fSmrg if (target != GL_TEXTURE_1D_ARRAY) 384801e04c3fSmrg yoffset += texImage->Border; 384901e04c3fSmrg /* fall-through */ 385001e04c3fSmrg case 1: 385101e04c3fSmrg xoffset += texImage->Border; 385201e04c3fSmrg } 385301e04c3fSmrg 385401e04c3fSmrg if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, 385501e04c3fSmrg &width, &height)) { 385601e04c3fSmrg struct gl_renderbuffer *srcRb = 385701e04c3fSmrg get_copy_tex_image_source(ctx, texImage->TexFormat); 385801e04c3fSmrg 385901e04c3fSmrg copytexsubimage_by_slice(ctx, texImage, dims, xoffset, yoffset, zoffset, 386001e04c3fSmrg srcRb, x, y, width, height); 386101e04c3fSmrg 386201e04c3fSmrg check_gen_mipmap(ctx, target, texObj, level); 386301e04c3fSmrg 386401e04c3fSmrg /* NOTE: Don't signal _NEW_TEXTURE_OBJECT since we've only changed 386501e04c3fSmrg * the texel data, not the texture format, size, etc. 386601e04c3fSmrg */ 386701e04c3fSmrg } 386801e04c3fSmrg 386901e04c3fSmrg _mesa_unlock_texture(ctx, texObj); 387001e04c3fSmrg} 387101e04c3fSmrg 387201e04c3fSmrg 387301e04c3fSmrgstatic void 387401e04c3fSmrgcopy_texture_sub_image_err(struct gl_context *ctx, GLuint dims, 387501e04c3fSmrg struct gl_texture_object *texObj, 387601e04c3fSmrg GLenum target, GLint level, 387701e04c3fSmrg GLint xoffset, GLint yoffset, GLint zoffset, 387801e04c3fSmrg GLint x, GLint y, GLsizei width, GLsizei height, 387901e04c3fSmrg const char *caller) 388001e04c3fSmrg{ 388101e04c3fSmrg FLUSH_VERTICES(ctx, 0); 388201e04c3fSmrg 388301e04c3fSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 388401e04c3fSmrg _mesa_debug(ctx, "%s %s %d %d %d %d %d %d %d %d\n", caller, 388501e04c3fSmrg _mesa_enum_to_string(target), 388601e04c3fSmrg level, xoffset, yoffset, zoffset, x, y, width, height); 388701e04c3fSmrg 388801e04c3fSmrg if (ctx->NewState & NEW_COPY_TEX_STATE) 388901e04c3fSmrg _mesa_update_state(ctx); 389001e04c3fSmrg 389101e04c3fSmrg if (copytexsubimage_error_check(ctx, dims, texObj, target, level, 389201e04c3fSmrg xoffset, yoffset, zoffset, 389301e04c3fSmrg width, height, caller)) { 389401e04c3fSmrg return; 389501e04c3fSmrg } 389601e04c3fSmrg 389701e04c3fSmrg copy_texture_sub_image(ctx, dims, texObj, target, level, xoffset, yoffset, 389801e04c3fSmrg zoffset, x, y, width, height); 389901e04c3fSmrg} 390001e04c3fSmrg 390101e04c3fSmrg 390201e04c3fSmrgstatic void 390301e04c3fSmrgcopy_texture_sub_image_no_error(struct gl_context *ctx, GLuint dims, 390401e04c3fSmrg struct gl_texture_object *texObj, 390501e04c3fSmrg GLenum target, GLint level, 390601e04c3fSmrg GLint xoffset, GLint yoffset, GLint zoffset, 390701e04c3fSmrg GLint x, GLint y, GLsizei width, GLsizei height) 390801e04c3fSmrg{ 390901e04c3fSmrg FLUSH_VERTICES(ctx, 0); 391001e04c3fSmrg 391101e04c3fSmrg if (ctx->NewState & NEW_COPY_TEX_STATE) 391201e04c3fSmrg _mesa_update_state(ctx); 391301e04c3fSmrg 391401e04c3fSmrg copy_texture_sub_image(ctx, dims, texObj, target, level, xoffset, yoffset, 391501e04c3fSmrg zoffset, x, y, width, height); 391601e04c3fSmrg} 391701e04c3fSmrg 391801e04c3fSmrg 391901e04c3fSmrg/** 392001e04c3fSmrg * Implement the glCopyTexImage1/2D() functions. 392101e04c3fSmrg */ 392201e04c3fSmrgstatic ALWAYS_INLINE void 39233464ebd5Sriastradhcopyteximage(struct gl_context *ctx, GLuint dims, 39243464ebd5Sriastradh GLenum target, GLint level, GLenum internalFormat, 392501e04c3fSmrg GLint x, GLint y, GLsizei width, GLsizei height, GLint border, 392601e04c3fSmrg bool no_error) 39277117f1b4Smrg{ 39287117f1b4Smrg struct gl_texture_image *texImage; 392901e04c3fSmrg struct gl_texture_object *texObj; 3930af69d88dSmrg mesa_format texFormat; 39313464ebd5Sriastradh 3932af69d88dSmrg FLUSH_VERTICES(ctx, 0); 39337117f1b4Smrg 39344a49301eSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 39353464ebd5Sriastradh _mesa_debug(ctx, "glCopyTexImage%uD %s %d %s %d %d %d %d %d\n", 39363464ebd5Sriastradh dims, 393701e04c3fSmrg _mesa_enum_to_string(target), level, 393801e04c3fSmrg _mesa_enum_to_string(internalFormat), 39394a49301eSmrg x, y, width, height, border); 39404a49301eSmrg 3941c1f859d4Smrg if (ctx->NewState & NEW_COPY_TEX_STATE) 39427117f1b4Smrg _mesa_update_state(ctx); 39437117f1b4Smrg 394401e04c3fSmrg if (!no_error) { 394501e04c3fSmrg if (copytexture_error_check(ctx, dims, target, level, internalFormat, 394601e04c3fSmrg border)) 394701e04c3fSmrg return; 39487117f1b4Smrg 394901e04c3fSmrg if (!_mesa_legal_texture_dimensions(ctx, target, level, width, height, 395001e04c3fSmrg 1, border)) { 395101e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, 395201e04c3fSmrg "glCopyTexImage%uD(invalid width=%d or height=%d)", 395301e04c3fSmrg dims, width, height); 395401e04c3fSmrg return; 395501e04c3fSmrg } 3956af69d88dSmrg } 3957af69d88dSmrg 39584a49301eSmrg texObj = _mesa_get_current_tex_object(ctx, target); 3959af69d88dSmrg assert(texObj); 3960af69d88dSmrg 3961af69d88dSmrg texFormat = _mesa_choose_texture_format(ctx, texObj, target, level, 3962af69d88dSmrg internalFormat, GL_NONE, GL_NONE); 3963af69d88dSmrg 396401e04c3fSmrg /* First check if reallocating the texture buffer can be avoided. 396501e04c3fSmrg * Without the realloc the copy can be 20x faster. 396601e04c3fSmrg */ 396701e04c3fSmrg _mesa_lock_texture(ctx, texObj); 396801e04c3fSmrg { 396901e04c3fSmrg texImage = _mesa_select_tex_image(texObj, target, level); 397001e04c3fSmrg if (texImage && can_avoid_reallocation(texImage, internalFormat, texFormat, 397101e04c3fSmrg width, height, border)) { 397201e04c3fSmrg _mesa_unlock_texture(ctx, texObj); 397301e04c3fSmrg if (no_error) { 397401e04c3fSmrg copy_texture_sub_image_no_error(ctx, dims, texObj, target, level, 0, 397501e04c3fSmrg 0, 0, x, y, width, height); 397601e04c3fSmrg } else { 397701e04c3fSmrg copy_texture_sub_image_err(ctx, dims, texObj, target, level, 0, 0, 397801e04c3fSmrg 0, x, y, width, height,"CopyTexImage"); 397901e04c3fSmrg } 398001e04c3fSmrg return; 398101e04c3fSmrg } 398201e04c3fSmrg } 398301e04c3fSmrg _mesa_unlock_texture(ctx, texObj); 398401e04c3fSmrg _mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_LOW, "glCopyTexImage " 398501e04c3fSmrg "can't avoid reallocating texture storage\n"); 398601e04c3fSmrg 398701e04c3fSmrg if (!no_error && _mesa_is_gles3(ctx)) { 398801e04c3fSmrg struct gl_renderbuffer *rb = 398901e04c3fSmrg _mesa_get_read_renderbuffer_for_format(ctx, internalFormat); 3990af69d88dSmrg 3991af69d88dSmrg if (_mesa_is_enum_format_unsized(internalFormat)) { 3992af69d88dSmrg /* Conversion from GL_RGB10_A2 source buffer format is not allowed in 3993af69d88dSmrg * OpenGL ES 3.0. Khronos bug# 9807. 3994af69d88dSmrg */ 3995af69d88dSmrg if (rb->InternalFormat == GL_RGB10_A2) { 3996af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 399701e04c3fSmrg "glCopyTexImage%uD(Reading from GL_RGB10_A2 buffer" 399801e04c3fSmrg " and writing to unsized internal format)", dims); 3999af69d88dSmrg return; 4000af69d88dSmrg } 4001af69d88dSmrg } 4002af69d88dSmrg /* From Page 139 of OpenGL ES 3.0 spec: 4003af69d88dSmrg * "If internalformat is sized, the internal format of the new texel 4004af69d88dSmrg * array is internalformat, and this is also the new texel array’s 4005af69d88dSmrg * effective internal format. If the component sizes of internalformat 4006af69d88dSmrg * do not exactly match the corresponding component sizes of the source 4007af69d88dSmrg * buffer’s effective internal format, described below, an 4008af69d88dSmrg * INVALID_OPERATION error is generated. If internalformat is unsized, 4009af69d88dSmrg * the internal format of the new texel array is the effective internal 4010af69d88dSmrg * format of the source buffer, and this is also the new texel array’s 4011af69d88dSmrg * effective internal format. 4012af69d88dSmrg */ 4013af69d88dSmrg else if (formats_differ_in_component_sizes (texFormat, rb->Format)) { 4014af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 401501e04c3fSmrg "glCopyTexImage%uD(component size changed in" 4016af69d88dSmrg " internal format)", dims); 4017af69d88dSmrg return; 4018af69d88dSmrg } 4019af69d88dSmrg } 4020af69d88dSmrg 4021af69d88dSmrg assert(texFormat != MESA_FORMAT_NONE); 4022af69d88dSmrg 4023af69d88dSmrg if (!ctx->Driver.TestProxyTexImage(ctx, proxy_target(target), 402401e04c3fSmrg 0, level, texFormat, 1, 402501e04c3fSmrg width, height, 1)) { 4026af69d88dSmrg _mesa_error(ctx, GL_OUT_OF_MEMORY, 4027af69d88dSmrg "glCopyTexImage%uD(image too large)", dims); 4028af69d88dSmrg return; 4029af69d88dSmrg } 4030af69d88dSmrg 4031af69d88dSmrg if (border && ctx->Const.StripTextureBorder) { 4032af69d88dSmrg x += border; 4033af69d88dSmrg width -= border * 2; 4034af69d88dSmrg if (dims == 2) { 403501e04c3fSmrg y += border; 403601e04c3fSmrg height -= border * 2; 4037af69d88dSmrg } 4038af69d88dSmrg border = 0; 4039af69d88dSmrg } 40407117f1b4Smrg 40417117f1b4Smrg _mesa_lock_texture(ctx, texObj); 40427117f1b4Smrg { 40437117f1b4Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 40447117f1b4Smrg 40457117f1b4Smrg if (!texImage) { 404601e04c3fSmrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage%uD", dims); 40477117f1b4Smrg } 40484a49301eSmrg else { 4049af69d88dSmrg GLint srcX = x, srcY = y, dstX = 0, dstY = 0, dstZ = 0; 405001e04c3fSmrg const GLuint face = _mesa_tex_target_to_face(target); 40514a49301eSmrg 4052af69d88dSmrg /* Free old texture image */ 4053af69d88dSmrg ctx->Driver.FreeTextureImageBuffer(ctx, texImage); 40544a49301eSmrg 4055af69d88dSmrg _mesa_init_teximage_fields(ctx, texImage, width, height, 1, 4056af69d88dSmrg border, internalFormat, texFormat); 40577117f1b4Smrg 4058af69d88dSmrg if (width && height) { 40593464ebd5Sriastradh /* Allocate texture memory (no pixel data yet) */ 4060af69d88dSmrg ctx->Driver.AllocTextureImageBuffer(ctx, texImage); 40617117f1b4Smrg 40623464ebd5Sriastradh if (_mesa_clip_copytexsubimage(ctx, &dstX, &dstY, &srcX, &srcY, 40633464ebd5Sriastradh &width, &height)) { 4064af69d88dSmrg struct gl_renderbuffer *srcRb = 4065af69d88dSmrg get_copy_tex_image_source(ctx, texImage->TexFormat); 4066af69d88dSmrg 4067af69d88dSmrg copytexsubimage_by_slice(ctx, texImage, dims, 4068af69d88dSmrg dstX, dstY, dstZ, 4069af69d88dSmrg srcRb, srcX, srcY, width, height); 40703464ebd5Sriastradh } 40714a49301eSmrg 40723464ebd5Sriastradh check_gen_mipmap(ctx, target, texObj, level); 4073af69d88dSmrg } 40744a49301eSmrg 4075af69d88dSmrg _mesa_update_fbo_texture(ctx, texObj, face, level); 40764a49301eSmrg 4077af69d88dSmrg _mesa_dirty_texobj(ctx, texObj); 40784a49301eSmrg } 40797117f1b4Smrg } 40807117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 40817117f1b4Smrg} 40827117f1b4Smrg 40837117f1b4Smrg 408401e04c3fSmrgstatic void 408501e04c3fSmrgcopyteximage_err(struct gl_context *ctx, GLuint dims, GLenum target, 408601e04c3fSmrg GLint level, GLenum internalFormat, GLint x, GLint y, 408701e04c3fSmrg GLsizei width, GLsizei height, GLint border) 408801e04c3fSmrg{ 408901e04c3fSmrg copyteximage(ctx, dims, target, level, internalFormat, x, y, width, height, 409001e04c3fSmrg border, false); 409101e04c3fSmrg} 409201e04c3fSmrg 409301e04c3fSmrg 409401e04c3fSmrgstatic void 409501e04c3fSmrgcopyteximage_no_error(struct gl_context *ctx, GLuint dims, GLenum target, 409601e04c3fSmrg GLint level, GLenum internalFormat, GLint x, GLint y, 409701e04c3fSmrg GLsizei width, GLsizei height, GLint border) 409801e04c3fSmrg{ 409901e04c3fSmrg copyteximage(ctx, dims, target, level, internalFormat, x, y, width, height, 410001e04c3fSmrg border, true); 410101e04c3fSmrg} 410201e04c3fSmrg 410301e04c3fSmrg 410401e04c3fSmrgvoid GLAPIENTRY 410501e04c3fSmrg_mesa_CopyTexImage1D( GLenum target, GLint level, 410601e04c3fSmrg GLenum internalFormat, 410701e04c3fSmrg GLint x, GLint y, 410801e04c3fSmrg GLsizei width, GLint border ) 410901e04c3fSmrg{ 411001e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 411101e04c3fSmrg copyteximage_err(ctx, 1, target, level, internalFormat, x, y, width, 1, 411201e04c3fSmrg border); 411301e04c3fSmrg} 411401e04c3fSmrg 411501e04c3fSmrg 411601e04c3fSmrgvoid GLAPIENTRY 411701e04c3fSmrg_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat, 411801e04c3fSmrg GLint x, GLint y, GLsizei width, GLsizei height, 411901e04c3fSmrg GLint border ) 412001e04c3fSmrg{ 412101e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 412201e04c3fSmrg copyteximage_err(ctx, 2, target, level, internalFormat, 412301e04c3fSmrg x, y, width, height, border); 412401e04c3fSmrg} 412501e04c3fSmrg 412601e04c3fSmrg 412701e04c3fSmrgvoid GLAPIENTRY 412801e04c3fSmrg_mesa_CopyTexImage1D_no_error(GLenum target, GLint level, GLenum internalFormat, 412901e04c3fSmrg GLint x, GLint y, GLsizei width, GLint border) 413001e04c3fSmrg{ 413101e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 413201e04c3fSmrg copyteximage_no_error(ctx, 1, target, level, internalFormat, x, y, width, 1, 413301e04c3fSmrg border); 413401e04c3fSmrg} 413501e04c3fSmrg 413601e04c3fSmrg 413701e04c3fSmrgvoid GLAPIENTRY 413801e04c3fSmrg_mesa_CopyTexImage2D_no_error(GLenum target, GLint level, GLenum internalFormat, 413901e04c3fSmrg GLint x, GLint y, GLsizei width, GLsizei height, 414001e04c3fSmrg GLint border) 414101e04c3fSmrg{ 414201e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 414301e04c3fSmrg copyteximage_no_error(ctx, 2, target, level, internalFormat, 414401e04c3fSmrg x, y, width, height, border); 414501e04c3fSmrg} 414601e04c3fSmrg 414701e04c3fSmrg 414801e04c3fSmrgvoid GLAPIENTRY 414901e04c3fSmrg_mesa_CopyTexSubImage1D(GLenum target, GLint level, 415001e04c3fSmrg GLint xoffset, GLint x, GLint y, GLsizei width) 415101e04c3fSmrg{ 415201e04c3fSmrg struct gl_texture_object* texObj; 415301e04c3fSmrg const char *self = "glCopyTexSubImage1D"; 415401e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 415501e04c3fSmrg 415601e04c3fSmrg /* Check target (proxies not allowed). Target must be checked prior to 415701e04c3fSmrg * calling _mesa_get_current_tex_object. 415801e04c3fSmrg */ 415901e04c3fSmrg if (!legal_texsubimage_target(ctx, 1, target, false)) { 416001e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", self, 416101e04c3fSmrg _mesa_enum_to_string(target)); 416201e04c3fSmrg return; 416301e04c3fSmrg } 416401e04c3fSmrg 416501e04c3fSmrg texObj = _mesa_get_current_tex_object(ctx, target); 416601e04c3fSmrg if (!texObj) 416701e04c3fSmrg return; 416801e04c3fSmrg 416901e04c3fSmrg copy_texture_sub_image_err(ctx, 1, texObj, target, level, xoffset, 0, 0, 417001e04c3fSmrg x, y, width, 1, self); 417101e04c3fSmrg} 417201e04c3fSmrg 417301e04c3fSmrg 417401e04c3fSmrgvoid GLAPIENTRY 417501e04c3fSmrg_mesa_CopyTexSubImage2D(GLenum target, GLint level, 417601e04c3fSmrg GLint xoffset, GLint yoffset, 417701e04c3fSmrg GLint x, GLint y, GLsizei width, GLsizei height) 417801e04c3fSmrg{ 417901e04c3fSmrg struct gl_texture_object* texObj; 418001e04c3fSmrg const char *self = "glCopyTexSubImage2D"; 418101e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 418201e04c3fSmrg 418301e04c3fSmrg /* Check target (proxies not allowed). Target must be checked prior to 418401e04c3fSmrg * calling _mesa_get_current_tex_object. 418501e04c3fSmrg */ 418601e04c3fSmrg if (!legal_texsubimage_target(ctx, 2, target, false)) { 418701e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", self, 418801e04c3fSmrg _mesa_enum_to_string(target)); 418901e04c3fSmrg return; 419001e04c3fSmrg } 419101e04c3fSmrg 419201e04c3fSmrg texObj = _mesa_get_current_tex_object(ctx, target); 419301e04c3fSmrg if (!texObj) 419401e04c3fSmrg return; 419501e04c3fSmrg 419601e04c3fSmrg copy_texture_sub_image_err(ctx, 2, texObj, target, level, xoffset, yoffset, 419701e04c3fSmrg 0, x, y, width, height, self); 419801e04c3fSmrg} 419901e04c3fSmrg 420001e04c3fSmrg 420101e04c3fSmrgvoid GLAPIENTRY 420201e04c3fSmrg_mesa_CopyTexSubImage3D(GLenum target, GLint level, 420301e04c3fSmrg GLint xoffset, GLint yoffset, GLint zoffset, 420401e04c3fSmrg GLint x, GLint y, GLsizei width, GLsizei height) 420501e04c3fSmrg{ 420601e04c3fSmrg struct gl_texture_object* texObj; 420701e04c3fSmrg const char *self = "glCopyTexSubImage3D"; 420801e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 420901e04c3fSmrg 421001e04c3fSmrg /* Check target (proxies not allowed). Target must be checked prior to 421101e04c3fSmrg * calling _mesa_get_current_tex_object. 421201e04c3fSmrg */ 421301e04c3fSmrg if (!legal_texsubimage_target(ctx, 3, target, false)) { 421401e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", self, 421501e04c3fSmrg _mesa_enum_to_string(target)); 421601e04c3fSmrg return; 421701e04c3fSmrg } 421801e04c3fSmrg 421901e04c3fSmrg texObj = _mesa_get_current_tex_object(ctx, target); 422001e04c3fSmrg if (!texObj) 422101e04c3fSmrg return; 422201e04c3fSmrg 422301e04c3fSmrg copy_texture_sub_image_err(ctx, 3, texObj, target, level, xoffset, yoffset, 422401e04c3fSmrg zoffset, x, y, width, height, self); 422501e04c3fSmrg} 422601e04c3fSmrg 422701e04c3fSmrg 422801e04c3fSmrgvoid GLAPIENTRY 422901e04c3fSmrg_mesa_CopyTextureSubImage1D(GLuint texture, GLint level, 423001e04c3fSmrg GLint xoffset, GLint x, GLint y, GLsizei width) 423101e04c3fSmrg{ 423201e04c3fSmrg struct gl_texture_object* texObj; 423301e04c3fSmrg const char *self = "glCopyTextureSubImage1D"; 423401e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 423501e04c3fSmrg 423601e04c3fSmrg texObj = _mesa_lookup_texture_err(ctx, texture, self); 423701e04c3fSmrg if (!texObj) 423801e04c3fSmrg return; 423901e04c3fSmrg 424001e04c3fSmrg /* Check target (proxies not allowed). */ 424101e04c3fSmrg if (!legal_texsubimage_target(ctx, 1, texObj->Target, true)) { 424201e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid target %s)", self, 424301e04c3fSmrg _mesa_enum_to_string(texObj->Target)); 424401e04c3fSmrg return; 424501e04c3fSmrg } 424601e04c3fSmrg 424701e04c3fSmrg copy_texture_sub_image_err(ctx, 1, texObj, texObj->Target, level, xoffset, 0, 424801e04c3fSmrg 0, x, y, width, 1, self); 424901e04c3fSmrg} 425001e04c3fSmrg 425101e04c3fSmrg 425201e04c3fSmrgvoid GLAPIENTRY 425301e04c3fSmrg_mesa_CopyTextureSubImage2D(GLuint texture, GLint level, 425401e04c3fSmrg GLint xoffset, GLint yoffset, 425501e04c3fSmrg GLint x, GLint y, GLsizei width, GLsizei height) 425601e04c3fSmrg{ 425701e04c3fSmrg struct gl_texture_object* texObj; 425801e04c3fSmrg const char *self = "glCopyTextureSubImage2D"; 425901e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 426001e04c3fSmrg 426101e04c3fSmrg texObj = _mesa_lookup_texture_err(ctx, texture, self); 426201e04c3fSmrg if (!texObj) 426301e04c3fSmrg return; 426401e04c3fSmrg 426501e04c3fSmrg /* Check target (proxies not allowed). */ 426601e04c3fSmrg if (!legal_texsubimage_target(ctx, 2, texObj->Target, true)) { 426701e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid target %s)", self, 426801e04c3fSmrg _mesa_enum_to_string(texObj->Target)); 426901e04c3fSmrg return; 427001e04c3fSmrg } 427101e04c3fSmrg 427201e04c3fSmrg copy_texture_sub_image_err(ctx, 2, texObj, texObj->Target, level, xoffset, 427301e04c3fSmrg yoffset, 0, x, y, width, height, self); 427401e04c3fSmrg} 427501e04c3fSmrg 427601e04c3fSmrg 427701e04c3fSmrgvoid GLAPIENTRY 427801e04c3fSmrg_mesa_CopyTextureSubImage3D(GLuint texture, GLint level, 427901e04c3fSmrg GLint xoffset, GLint yoffset, GLint zoffset, 428001e04c3fSmrg GLint x, GLint y, GLsizei width, GLsizei height) 428101e04c3fSmrg{ 428201e04c3fSmrg struct gl_texture_object* texObj; 428301e04c3fSmrg const char *self = "glCopyTextureSubImage3D"; 428401e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 428501e04c3fSmrg 428601e04c3fSmrg texObj = _mesa_lookup_texture_err(ctx, texture, self); 428701e04c3fSmrg if (!texObj) 428801e04c3fSmrg return; 428901e04c3fSmrg 429001e04c3fSmrg /* Check target (proxies not allowed). */ 429101e04c3fSmrg if (!legal_texsubimage_target(ctx, 3, texObj->Target, true)) { 429201e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid target %s)", self, 429301e04c3fSmrg _mesa_enum_to_string(texObj->Target)); 429401e04c3fSmrg return; 429501e04c3fSmrg } 429601e04c3fSmrg 429701e04c3fSmrg if (texObj->Target == GL_TEXTURE_CUBE_MAP) { 429801e04c3fSmrg /* Act like CopyTexSubImage2D */ 429901e04c3fSmrg copy_texture_sub_image_err(ctx, 2, texObj, 430001e04c3fSmrg GL_TEXTURE_CUBE_MAP_POSITIVE_X + zoffset, 430101e04c3fSmrg level, xoffset, yoffset, 0, x, y, width, height, 430201e04c3fSmrg self); 430301e04c3fSmrg } 430401e04c3fSmrg else 430501e04c3fSmrg copy_texture_sub_image_err(ctx, 3, texObj, texObj->Target, level, xoffset, 430601e04c3fSmrg yoffset, zoffset, x, y, width, height, self); 430701e04c3fSmrg} 430801e04c3fSmrg 43093464ebd5Sriastradh 43107117f1b4Smrgvoid GLAPIENTRY 431101e04c3fSmrg_mesa_CopyTexSubImage1D_no_error(GLenum target, GLint level, GLint xoffset, 431201e04c3fSmrg GLint x, GLint y, GLsizei width) 43137117f1b4Smrg{ 43147117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 43157117f1b4Smrg 431601e04c3fSmrg struct gl_texture_object* texObj = _mesa_get_current_tex_object(ctx, target); 431701e04c3fSmrg copy_texture_sub_image_no_error(ctx, 1, texObj, target, level, xoffset, 0, 0, 431801e04c3fSmrg x, y, width, 1); 431901e04c3fSmrg} 43207117f1b4Smrg 4321c1f859d4Smrg 43223464ebd5Sriastradhvoid GLAPIENTRY 432301e04c3fSmrg_mesa_CopyTexSubImage2D_no_error(GLenum target, GLint level, GLint xoffset, 432401e04c3fSmrg GLint yoffset, GLint x, GLint y, GLsizei width, 432501e04c3fSmrg GLsizei height) 43263464ebd5Sriastradh{ 43273464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 43287117f1b4Smrg 432901e04c3fSmrg struct gl_texture_object* texObj = _mesa_get_current_tex_object(ctx, target); 433001e04c3fSmrg copy_texture_sub_image_no_error(ctx, 2, texObj, target, level, xoffset, 433101e04c3fSmrg yoffset, 0, x, y, width, height); 433201e04c3fSmrg} 43337117f1b4Smrg 43347117f1b4Smrg 433501e04c3fSmrgvoid GLAPIENTRY 433601e04c3fSmrg_mesa_CopyTexSubImage3D_no_error(GLenum target, GLint level, GLint xoffset, 433701e04c3fSmrg GLint yoffset, GLint zoffset, GLint x, GLint y, 433801e04c3fSmrg GLsizei width, GLsizei height) 43397117f1b4Smrg{ 434001e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 4341af69d88dSmrg 434201e04c3fSmrg struct gl_texture_object* texObj = _mesa_get_current_tex_object(ctx, target); 434301e04c3fSmrg copy_texture_sub_image_no_error(ctx, 3, texObj, target, level, xoffset, 434401e04c3fSmrg yoffset, zoffset, x, y, width, height); 43457117f1b4Smrg} 43467117f1b4Smrg 43477117f1b4Smrg 43487117f1b4Smrgvoid GLAPIENTRY 434901e04c3fSmrg_mesa_CopyTextureSubImage1D_no_error(GLuint texture, GLint level, GLint xoffset, 435001e04c3fSmrg GLint x, GLint y, GLsizei width) 43517117f1b4Smrg{ 43527117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 43537117f1b4Smrg 435401e04c3fSmrg struct gl_texture_object* texObj = _mesa_lookup_texture(ctx, texture); 435501e04c3fSmrg copy_texture_sub_image_no_error(ctx, 1, texObj, texObj->Target, level, 435601e04c3fSmrg xoffset, 0, 0, x, y, width, 1); 435701e04c3fSmrg} 43587117f1b4Smrg 4359c1f859d4Smrg 43603464ebd5Sriastradhvoid GLAPIENTRY 436101e04c3fSmrg_mesa_CopyTextureSubImage2D_no_error(GLuint texture, GLint level, GLint xoffset, 436201e04c3fSmrg GLint yoffset, GLint x, GLint y, 436301e04c3fSmrg GLsizei width, GLsizei height) 43643464ebd5Sriastradh{ 43653464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 43664a49301eSmrg 436701e04c3fSmrg struct gl_texture_object* texObj = _mesa_lookup_texture(ctx, texture); 436801e04c3fSmrg copy_texture_sub_image_no_error(ctx, 2, texObj, texObj->Target, level, 436901e04c3fSmrg xoffset, yoffset, 0, x, y, width, height); 437001e04c3fSmrg} 4371c1f859d4Smrg 43724a49301eSmrg 43733464ebd5Sriastradhvoid GLAPIENTRY 437401e04c3fSmrg_mesa_CopyTextureSubImage3D_no_error(GLuint texture, GLint level, GLint xoffset, 437501e04c3fSmrg GLint yoffset, GLint zoffset, GLint x, 437601e04c3fSmrg GLint y, GLsizei width, GLsizei height) 43773464ebd5Sriastradh{ 43783464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 437901e04c3fSmrg 438001e04c3fSmrg struct gl_texture_object* texObj = _mesa_lookup_texture(ctx, texture); 438101e04c3fSmrg if (texObj->Target == GL_TEXTURE_CUBE_MAP) { 438201e04c3fSmrg /* Act like CopyTexSubImage2D */ 438301e04c3fSmrg copy_texture_sub_image_no_error(ctx, 2, texObj, 438401e04c3fSmrg GL_TEXTURE_CUBE_MAP_POSITIVE_X + zoffset, 438501e04c3fSmrg level, xoffset, yoffset, 0, x, y, width, 438601e04c3fSmrg height); 438701e04c3fSmrg } 438801e04c3fSmrg else 438901e04c3fSmrg copy_texture_sub_image_no_error(ctx, 3, texObj, texObj->Target, level, 439001e04c3fSmrg xoffset, yoffset, zoffset, x, y, width, 439101e04c3fSmrg height); 43927117f1b4Smrg} 43937117f1b4Smrg 439401e04c3fSmrg 4395af69d88dSmrgstatic bool 4396af69d88dSmrgcheck_clear_tex_image(struct gl_context *ctx, 4397af69d88dSmrg const char *function, 4398af69d88dSmrg struct gl_texture_image *texImage, 4399af69d88dSmrg GLenum format, GLenum type, 4400af69d88dSmrg const void *data, 4401af69d88dSmrg GLubyte *clearValue) 4402af69d88dSmrg{ 4403af69d88dSmrg struct gl_texture_object *texObj = texImage->TexObject; 4404af69d88dSmrg static const GLubyte zeroData[MAX_PIXEL_BYTES]; 4405af69d88dSmrg GLenum internalFormat = texImage->InternalFormat; 4406af69d88dSmrg GLenum err; 44077117f1b4Smrg 4408af69d88dSmrg if (texObj->Target == GL_TEXTURE_BUFFER) { 4409af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 4410af69d88dSmrg "%s(buffer texture)", function); 4411af69d88dSmrg return false; 4412af69d88dSmrg } 44137117f1b4Smrg 4414af69d88dSmrg if (_mesa_is_compressed_format(ctx, internalFormat)) { 4415af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 4416af69d88dSmrg "%s(compressed texture)", function); 4417af69d88dSmrg return false; 4418af69d88dSmrg } 44197117f1b4Smrg 4420af69d88dSmrg err = _mesa_error_check_format_and_type(ctx, format, type); 4421af69d88dSmrg if (err != GL_NO_ERROR) { 4422af69d88dSmrg _mesa_error(ctx, err, 4423af69d88dSmrg "%s(incompatible format = %s, type = %s)", 4424af69d88dSmrg function, 442501e04c3fSmrg _mesa_enum_to_string(format), 442601e04c3fSmrg _mesa_enum_to_string(type)); 4427af69d88dSmrg return false; 4428af69d88dSmrg } 44297117f1b4Smrg 4430af69d88dSmrg /* make sure internal format and format basically agree */ 4431af69d88dSmrg if (!texture_formats_agree(internalFormat, format)) { 4432af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 4433af69d88dSmrg "%s(incompatible internalFormat = %s, format = %s)", 4434af69d88dSmrg function, 443501e04c3fSmrg _mesa_enum_to_string(internalFormat), 443601e04c3fSmrg _mesa_enum_to_string(format)); 4437af69d88dSmrg return false; 4438af69d88dSmrg } 44397117f1b4Smrg 4440af69d88dSmrg if (ctx->Version >= 30 || ctx->Extensions.EXT_texture_integer) { 4441af69d88dSmrg /* both source and dest must be integer-valued, or neither */ 4442af69d88dSmrg if (_mesa_is_format_integer_color(texImage->TexFormat) != 4443af69d88dSmrg _mesa_is_enum_format_integer(format)) { 4444af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 4445af69d88dSmrg "%s(integer/non-integer format mismatch)", 4446af69d88dSmrg function); 4447af69d88dSmrg return false; 4448af69d88dSmrg } 4449af69d88dSmrg } 44504a49301eSmrg 4451af69d88dSmrg if (!_mesa_texstore(ctx, 4452af69d88dSmrg 1, /* dims */ 4453af69d88dSmrg texImage->_BaseFormat, 4454af69d88dSmrg texImage->TexFormat, 4455af69d88dSmrg 0, /* dstRowStride */ 4456af69d88dSmrg &clearValue, 4457af69d88dSmrg 1, 1, 1, /* srcWidth/Height/Depth */ 4458af69d88dSmrg format, type, 4459af69d88dSmrg data ? data : zeroData, 4460af69d88dSmrg &ctx->DefaultPacking)) { 4461af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid format)", function); 4462af69d88dSmrg return false; 4463af69d88dSmrg } 44644a49301eSmrg 4465af69d88dSmrg return true; 44664a49301eSmrg} 44674a49301eSmrg 446801e04c3fSmrg 4469af69d88dSmrgstatic struct gl_texture_object * 4470af69d88dSmrgget_tex_obj_for_clear(struct gl_context *ctx, 4471af69d88dSmrg const char *function, 4472af69d88dSmrg GLuint texture) 44737117f1b4Smrg{ 4474af69d88dSmrg struct gl_texture_object *texObj; 4475af69d88dSmrg 447601e04c3fSmrg texObj = _mesa_lookup_texture_err(ctx, texture, function); 447701e04c3fSmrg if (!texObj) 4478af69d88dSmrg return NULL; 44797117f1b4Smrg 4480af69d88dSmrg if (texObj->Target == 0) { 4481af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unbound tex)", function); 4482af69d88dSmrg return NULL; 44833464ebd5Sriastradh } 44847117f1b4Smrg 4485af69d88dSmrg return texObj; 4486af69d88dSmrg} 44873464ebd5Sriastradh 448801e04c3fSmrg 448901e04c3fSmrg/** 449001e04c3fSmrg * For clearing cube textures, the zoffset and depth parameters indicate 449101e04c3fSmrg * which cube map faces are to be cleared. This is the one case where we 449201e04c3fSmrg * need to be concerned with multiple gl_texture_images. This function 449301e04c3fSmrg * returns the array of texture images to clear for cube maps, or one 449401e04c3fSmrg * texture image otherwise. 449501e04c3fSmrg * \return number of texture images, 0 for error, 6 for cube, 1 otherwise. 449601e04c3fSmrg */ 4497af69d88dSmrgstatic int 4498af69d88dSmrgget_tex_images_for_clear(struct gl_context *ctx, 4499af69d88dSmrg const char *function, 4500af69d88dSmrg struct gl_texture_object *texObj, 4501af69d88dSmrg GLint level, 4502af69d88dSmrg struct gl_texture_image **texImages) 4503af69d88dSmrg{ 4504af69d88dSmrg GLenum target; 450501e04c3fSmrg int numFaces, i; 45063464ebd5Sriastradh 4507af69d88dSmrg if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 4508af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid level)", function); 4509af69d88dSmrg return 0; 4510af69d88dSmrg } 45113464ebd5Sriastradh 4512af69d88dSmrg if (texObj->Target == GL_TEXTURE_CUBE_MAP) { 451301e04c3fSmrg target = GL_TEXTURE_CUBE_MAP_POSITIVE_X; 451401e04c3fSmrg numFaces = MAX_FACES; 451501e04c3fSmrg } 451601e04c3fSmrg else { 451701e04c3fSmrg target = texObj->Target; 451801e04c3fSmrg numFaces = 1; 4519af69d88dSmrg } 45207117f1b4Smrg 452101e04c3fSmrg for (i = 0; i < numFaces; i++) { 452201e04c3fSmrg texImages[i] = _mesa_select_tex_image(texObj, target + i, level); 452301e04c3fSmrg if (texImages[i] == NULL) { 452401e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid level)", function); 452501e04c3fSmrg return 0; 452601e04c3fSmrg } 45273464ebd5Sriastradh } 45283464ebd5Sriastradh 452901e04c3fSmrg return numFaces; 4530af69d88dSmrg} 45313464ebd5Sriastradh 453201e04c3fSmrg 4533af69d88dSmrgvoid GLAPIENTRY 453401e04c3fSmrg_mesa_ClearTexSubImage(GLuint texture, GLint level, 453501e04c3fSmrg GLint xoffset, GLint yoffset, GLint zoffset, 453601e04c3fSmrg GLsizei width, GLsizei height, GLsizei depth, 453701e04c3fSmrg GLenum format, GLenum type, const void *data) 4538af69d88dSmrg{ 4539af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 4540af69d88dSmrg struct gl_texture_object *texObj; 4541af69d88dSmrg struct gl_texture_image *texImages[MAX_FACES]; 4542af69d88dSmrg GLubyte clearValue[MAX_FACES][MAX_PIXEL_BYTES]; 4543af69d88dSmrg int i, numImages; 4544af69d88dSmrg int minDepth, maxDepth; 45453464ebd5Sriastradh 4546af69d88dSmrg texObj = get_tex_obj_for_clear(ctx, "glClearTexSubImage", texture); 45477117f1b4Smrg 4548af69d88dSmrg if (texObj == NULL) 4549af69d88dSmrg return; 45507117f1b4Smrg 4551af69d88dSmrg _mesa_lock_texture(ctx, texObj); 45527117f1b4Smrg 4553af69d88dSmrg numImages = get_tex_images_for_clear(ctx, "glClearTexSubImage", 4554af69d88dSmrg texObj, level, texImages); 4555af69d88dSmrg if (numImages == 0) 4556af69d88dSmrg goto out; 45577117f1b4Smrg 4558af69d88dSmrg if (numImages == 1) { 4559af69d88dSmrg minDepth = -(int) texImages[0]->Border; 4560af69d88dSmrg maxDepth = texImages[0]->Depth; 4561af69d88dSmrg } else { 456201e04c3fSmrg assert(numImages == MAX_FACES); 4563af69d88dSmrg minDepth = 0; 4564af69d88dSmrg maxDepth = numImages; 4565af69d88dSmrg } 4566af69d88dSmrg 4567af69d88dSmrg if (xoffset < -(GLint) texImages[0]->Border || 4568af69d88dSmrg yoffset < -(GLint) texImages[0]->Border || 4569af69d88dSmrg zoffset < minDepth || 4570af69d88dSmrg width < 0 || 4571af69d88dSmrg height < 0 || 4572af69d88dSmrg depth < 0 || 4573af69d88dSmrg xoffset + width > texImages[0]->Width || 4574af69d88dSmrg yoffset + height > texImages[0]->Height || 4575af69d88dSmrg zoffset + depth > maxDepth) { 4576af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 4577af69d88dSmrg "glClearSubTexImage(invalid dimensions)"); 4578af69d88dSmrg goto out; 45797117f1b4Smrg } 4580af69d88dSmrg 4581af69d88dSmrg if (numImages == 1) { 458201e04c3fSmrg if (check_clear_tex_image(ctx, "glClearTexSubImage", texImages[0], 4583af69d88dSmrg format, type, data, clearValue[0])) { 4584af69d88dSmrg ctx->Driver.ClearTexSubImage(ctx, 4585af69d88dSmrg texImages[0], 4586af69d88dSmrg xoffset, yoffset, zoffset, 4587af69d88dSmrg width, height, depth, 4588af69d88dSmrg data ? clearValue[0] : NULL); 45897117f1b4Smrg } 4590af69d88dSmrg } else { 459101e04c3fSmrg /* loop over cube face images */ 4592af69d88dSmrg for (i = zoffset; i < zoffset + depth; i++) { 459301e04c3fSmrg assert(i < MAX_FACES); 459401e04c3fSmrg if (!check_clear_tex_image(ctx, "glClearTexSubImage", texImages[i], 4595af69d88dSmrg format, type, data, clearValue[i])) 4596af69d88dSmrg goto out; 45977117f1b4Smrg } 4598af69d88dSmrg for (i = zoffset; i < zoffset + depth; i++) { 4599af69d88dSmrg ctx->Driver.ClearTexSubImage(ctx, 4600af69d88dSmrg texImages[i], 4601af69d88dSmrg xoffset, yoffset, 0, 4602af69d88dSmrg width, height, 1, 4603af69d88dSmrg data ? clearValue[i] : NULL); 46047117f1b4Smrg } 46057117f1b4Smrg } 46067117f1b4Smrg 4607af69d88dSmrg out: 4608af69d88dSmrg _mesa_unlock_texture(ctx, texObj); 4609af69d88dSmrg} 46107117f1b4Smrg 461101e04c3fSmrg 4612af69d88dSmrgvoid GLAPIENTRY 4613af69d88dSmrg_mesa_ClearTexImage( GLuint texture, GLint level, 4614af69d88dSmrg GLenum format, GLenum type, const void *data ) 4615af69d88dSmrg{ 4616af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 4617af69d88dSmrg struct gl_texture_object *texObj; 4618af69d88dSmrg struct gl_texture_image *texImages[MAX_FACES]; 4619af69d88dSmrg GLubyte clearValue[MAX_FACES][MAX_PIXEL_BYTES]; 4620af69d88dSmrg int i, numImages; 46217117f1b4Smrg 4622af69d88dSmrg texObj = get_tex_obj_for_clear(ctx, "glClearTexImage", texture); 46237117f1b4Smrg 4624af69d88dSmrg if (texObj == NULL) 4625af69d88dSmrg return; 46267117f1b4Smrg 4627af69d88dSmrg _mesa_lock_texture(ctx, texObj); 46287117f1b4Smrg 4629af69d88dSmrg numImages = get_tex_images_for_clear(ctx, "glClearTexImage", 4630af69d88dSmrg texObj, level, texImages); 46314a49301eSmrg 4632af69d88dSmrg for (i = 0; i < numImages; i++) { 463301e04c3fSmrg if (!check_clear_tex_image(ctx, "glClearTexImage", texImages[i], format, 463401e04c3fSmrg type, data, clearValue[i])) 4635af69d88dSmrg goto out; 4636af69d88dSmrg } 46377117f1b4Smrg 4638af69d88dSmrg for (i = 0; i < numImages; i++) { 4639af69d88dSmrg ctx->Driver.ClearTexSubImage(ctx, texImages[i], 4640af69d88dSmrg -(GLint) texImages[i]->Border, /* xoffset */ 4641af69d88dSmrg -(GLint) texImages[i]->Border, /* yoffset */ 4642af69d88dSmrg -(GLint) texImages[i]->Border, /* zoffset */ 4643af69d88dSmrg texImages[i]->Width, 4644af69d88dSmrg texImages[i]->Height, 4645af69d88dSmrg texImages[i]->Depth, 4646af69d88dSmrg data ? clearValue[i] : NULL); 4647af69d88dSmrg } 46487117f1b4Smrg 4649af69d88dSmrgout: 4650af69d88dSmrg _mesa_unlock_texture(ctx, texObj); 4651af69d88dSmrg} 46527117f1b4Smrg 46537117f1b4Smrg 4654af69d88dSmrg 4655af69d88dSmrg 4656af69d88dSmrg/**********************************************************************/ 4657af69d88dSmrg/****** Compressed Textures ******/ 4658af69d88dSmrg/**********************************************************************/ 46597117f1b4Smrg 46607117f1b4Smrg 46614a49301eSmrg/** 466201e04c3fSmrg * Target checking for glCompressedTexSubImage[123]D(). 4663af69d88dSmrg * \return GL_TRUE if error, GL_FALSE if no error 466401e04c3fSmrg * Must come before other error checking so that the texture object can 466501e04c3fSmrg * be correctly retrieved using _mesa_get_current_tex_object. 46664a49301eSmrg */ 46674a49301eSmrgstatic GLboolean 466801e04c3fSmrgcompressed_subtexture_target_check(struct gl_context *ctx, GLenum target, 466901e04c3fSmrg GLint dims, GLenum intFormat, bool dsa, 467001e04c3fSmrg const char *caller) 46714a49301eSmrg{ 4672af69d88dSmrg GLboolean targetOK; 467301e04c3fSmrg mesa_format format; 467401e04c3fSmrg enum mesa_format_layout layout; 467501e04c3fSmrg 467601e04c3fSmrg if (dsa && target == GL_TEXTURE_RECTANGLE) { 467701e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid target %s)", caller, 467801e04c3fSmrg _mesa_enum_to_string(target)); 467901e04c3fSmrg return GL_TRUE; 468001e04c3fSmrg } 46814a49301eSmrg 4682af69d88dSmrg switch (dims) { 4683af69d88dSmrg case 2: 4684af69d88dSmrg switch (target) { 4685af69d88dSmrg case GL_TEXTURE_2D: 468601e04c3fSmrg targetOK = GL_TRUE; 468701e04c3fSmrg break; 4688af69d88dSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 4689af69d88dSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 4690af69d88dSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 4691af69d88dSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 4692af69d88dSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 4693af69d88dSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 469401e04c3fSmrg targetOK = ctx->Extensions.ARB_texture_cube_map; 4695af69d88dSmrg break; 4696af69d88dSmrg default: 4697af69d88dSmrg targetOK = GL_FALSE; 4698af69d88dSmrg break; 4699af69d88dSmrg } 4700af69d88dSmrg break; 4701af69d88dSmrg case 3: 470201e04c3fSmrg switch (target) { 470301e04c3fSmrg case GL_TEXTURE_CUBE_MAP: 470401e04c3fSmrg targetOK = dsa && ctx->Extensions.ARB_texture_cube_map; 470501e04c3fSmrg break; 470601e04c3fSmrg case GL_TEXTURE_2D_ARRAY: 470701e04c3fSmrg targetOK = _mesa_is_gles3(ctx) || 470801e04c3fSmrg (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array); 470901e04c3fSmrg break; 471001e04c3fSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: 471101e04c3fSmrg targetOK = _mesa_has_texture_cube_map_array(ctx); 471201e04c3fSmrg break; 471301e04c3fSmrg case GL_TEXTURE_3D: 471401e04c3fSmrg targetOK = GL_TRUE; 471501e04c3fSmrg /* 471601e04c3fSmrg * OpenGL 4.5 spec (30.10.2014) says in Section 8.7 Compressed Texture 471701e04c3fSmrg * Images: 471801e04c3fSmrg * "An INVALID_OPERATION error is generated by 471901e04c3fSmrg * CompressedTex*SubImage3D if the internal format of the texture 472001e04c3fSmrg * is one of the EAC, ETC2, or RGTC formats and either border is 472101e04c3fSmrg * non-zero, or the effective target for the texture is not 472201e04c3fSmrg * TEXTURE_2D_ARRAY." 472301e04c3fSmrg * 472401e04c3fSmrg * NOTE: that's probably a spec error. It should probably say 472501e04c3fSmrg * "... or the effective target for the texture is not 472601e04c3fSmrg * TEXTURE_2D_ARRAY, TEXTURE_CUBE_MAP, nor 472701e04c3fSmrg * GL_TEXTURE_CUBE_MAP_ARRAY." 472801e04c3fSmrg * since those targets are 2D images and they support all compression 472901e04c3fSmrg * formats. 473001e04c3fSmrg * 473101e04c3fSmrg * Instead of listing all these, just list those which are allowed, 473201e04c3fSmrg * which is (at this time) only bptc. Otherwise we'd say s3tc (and 473301e04c3fSmrg * more) are valid here, which they are not, but of course not 473401e04c3fSmrg * mentioned by core spec. 473501e04c3fSmrg * 473601e04c3fSmrg * Also, from GL_KHR_texture_compression_astc_{hdr,ldr}: 473701e04c3fSmrg * 473801e04c3fSmrg * "Add a second new column "3D Tex." which is empty for all non-ASTC 473901e04c3fSmrg * formats. If only the LDR profile is supported by the implementation, 474001e04c3fSmrg * this column is also empty for all ASTC formats. If both the LDR and HDR 474101e04c3fSmrg * profiles are supported, this column is checked for all ASTC formats." 474201e04c3fSmrg * 474301e04c3fSmrg * "An INVALID_OPERATION error is generated by CompressedTexSubImage3D if 474401e04c3fSmrg * <format> is one of the formats in table 8.19 and <target> is not 474501e04c3fSmrg * TEXTURE_2D_ARRAY, TEXTURE_CUBE_MAP_ARRAY, or TEXTURE_3D. 474601e04c3fSmrg * 474701e04c3fSmrg * An INVALID_OPERATION error is generated by CompressedTexSubImage3D if 474801e04c3fSmrg * <format> is TEXTURE_CUBE_MAP_ARRAY and the "Cube Map Array" column of 474901e04c3fSmrg * table 8.19 is *not* checked, or if <format> is TEXTURE_3D and the "3D 475001e04c3fSmrg * Tex." column of table 8.19 is *not* checked" 475101e04c3fSmrg * 475201e04c3fSmrg * And from GL_KHR_texture_compression_astc_sliced_3d: 475301e04c3fSmrg * 475401e04c3fSmrg * "Modify the "3D Tex." column to be checked for all ASTC formats." 475501e04c3fSmrg */ 475601e04c3fSmrg format = _mesa_glenum_to_compressed_format(intFormat); 475701e04c3fSmrg layout = _mesa_get_format_layout(format); 475801e04c3fSmrg switch (layout) { 475901e04c3fSmrg case MESA_FORMAT_LAYOUT_BPTC: 476001e04c3fSmrg /* valid format */ 476101e04c3fSmrg break; 476201e04c3fSmrg case MESA_FORMAT_LAYOUT_ASTC: 476301e04c3fSmrg targetOK = 476401e04c3fSmrg ctx->Extensions.KHR_texture_compression_astc_hdr || 476501e04c3fSmrg ctx->Extensions.KHR_texture_compression_astc_sliced_3d; 476601e04c3fSmrg break; 476701e04c3fSmrg default: 476801e04c3fSmrg /* invalid format */ 476901e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 477001e04c3fSmrg "%s(invalid target %s for format %s)", caller, 477101e04c3fSmrg _mesa_enum_to_string(target), 477201e04c3fSmrg _mesa_enum_to_string(intFormat)); 477301e04c3fSmrg return GL_TRUE; 477401e04c3fSmrg } 477501e04c3fSmrg break; 477601e04c3fSmrg default: 477701e04c3fSmrg targetOK = GL_FALSE; 477801e04c3fSmrg } 477901e04c3fSmrg 4780af69d88dSmrg break; 4781af69d88dSmrg default: 4782af69d88dSmrg assert(dims == 1); 4783af69d88dSmrg /* no 1D compressed textures at this time */ 4784af69d88dSmrg targetOK = GL_FALSE; 4785af69d88dSmrg break; 47864a49301eSmrg } 47874a49301eSmrg 4788af69d88dSmrg if (!targetOK) { 478901e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", caller, 479001e04c3fSmrg _mesa_enum_to_string(target)); 47914a49301eSmrg return GL_TRUE; 47924a49301eSmrg } 47934a49301eSmrg 479401e04c3fSmrg return GL_FALSE; 479501e04c3fSmrg} 479601e04c3fSmrg 479701e04c3fSmrg/** 479801e04c3fSmrg * Error checking for glCompressedTexSubImage[123]D(). 479901e04c3fSmrg * \return GL_TRUE if error, GL_FALSE if no error 480001e04c3fSmrg */ 480101e04c3fSmrgstatic GLboolean 480201e04c3fSmrgcompressed_subtexture_error_check(struct gl_context *ctx, GLint dims, 480301e04c3fSmrg const struct gl_texture_object *texObj, 480401e04c3fSmrg GLenum target, GLint level, 480501e04c3fSmrg GLint xoffset, GLint yoffset, GLint zoffset, 480601e04c3fSmrg GLsizei width, GLsizei height, GLsizei depth, 480701e04c3fSmrg GLenum format, GLsizei imageSize, 480801e04c3fSmrg const GLvoid *data, const char *callerName) 480901e04c3fSmrg{ 481001e04c3fSmrg struct gl_texture_image *texImage; 481101e04c3fSmrg GLint expectedSize; 481201e04c3fSmrg 4813af69d88dSmrg /* this will catch any invalid compressed format token */ 4814af69d88dSmrg if (!_mesa_is_compressed_format(ctx, format)) { 481501e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, "%s(format)", callerName); 4816af69d88dSmrg return GL_TRUE; 48174a49301eSmrg } 48184a49301eSmrg 4819af69d88dSmrg if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) { 482001e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(level=%d)", callerName, level); 482101e04c3fSmrg return GL_TRUE; 482201e04c3fSmrg } 482301e04c3fSmrg 482401e04c3fSmrg /* validate the bound PBO, if any */ 482501e04c3fSmrg if (!_mesa_validate_pbo_source_compressed(ctx, dims, &ctx->Unpack, 482601e04c3fSmrg imageSize, data, callerName)) { 4827af69d88dSmrg return GL_TRUE; 48284a49301eSmrg } 48294a49301eSmrg 4830af69d88dSmrg /* Check for invalid pixel storage modes */ 4831af69d88dSmrg if (!_mesa_compressed_pixel_storage_error_check(ctx, dims, 483201e04c3fSmrg &ctx->Unpack, callerName)) { 4833af69d88dSmrg return GL_TRUE; 48347117f1b4Smrg } 48354a49301eSmrg 4836af69d88dSmrg expectedSize = compressed_tex_size(width, height, depth, format); 4837af69d88dSmrg if (expectedSize != imageSize) { 483801e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(size=%d)", callerName, imageSize); 4839af69d88dSmrg return GL_TRUE; 48407117f1b4Smrg } 48417117f1b4Smrg 484201e04c3fSmrg texImage = _mesa_select_tex_image(texObj, target, level); 484301e04c3fSmrg if (!texImage) { 484401e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid texture level %d)", 484501e04c3fSmrg callerName, level); 4846af69d88dSmrg return GL_TRUE; 48473464ebd5Sriastradh } 48487117f1b4Smrg 484901e04c3fSmrg if ((GLint) format != texImage->InternalFormat) { 485001e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(format=%s)", 485101e04c3fSmrg callerName, _mesa_enum_to_string(format)); 4852af69d88dSmrg return GL_TRUE; 48533464ebd5Sriastradh } 48543464ebd5Sriastradh 485501e04c3fSmrg if (compressedteximage_only_format(format)) { 485601e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(format=%s cannot be updated)", 485701e04c3fSmrg callerName, _mesa_enum_to_string(format)); 4858af69d88dSmrg return GL_TRUE; 4859af69d88dSmrg } 48604a49301eSmrg 486101e04c3fSmrg if (error_check_subtexture_negative_dimensions(ctx, dims, width, height, 486201e04c3fSmrg depth, callerName)) { 4863af69d88dSmrg return GL_TRUE; 4864af69d88dSmrg } 48654a49301eSmrg 486601e04c3fSmrg if (error_check_subtexture_dimensions(ctx, dims, texImage, xoffset, yoffset, 486701e04c3fSmrg zoffset, width, height, depth, 486801e04c3fSmrg callerName)) { 4869af69d88dSmrg return GL_TRUE; 48707117f1b4Smrg } 4871af69d88dSmrg 4872af69d88dSmrg return GL_FALSE; 48733464ebd5Sriastradh} 48744a49301eSmrg 48757117f1b4Smrg 48763464ebd5Sriastradhvoid GLAPIENTRY 4877af69d88dSmrg_mesa_CompressedTexImage1D(GLenum target, GLint level, 48783464ebd5Sriastradh GLenum internalFormat, GLsizei width, 48793464ebd5Sriastradh GLint border, GLsizei imageSize, 48803464ebd5Sriastradh const GLvoid *data) 48813464ebd5Sriastradh{ 48823464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 488301e04c3fSmrg teximage_err(ctx, GL_TRUE, 1, target, level, internalFormat, 488401e04c3fSmrg width, 1, 1, border, GL_NONE, GL_NONE, imageSize, data); 48853464ebd5Sriastradh} 48863464ebd5Sriastradh 48873464ebd5Sriastradh 48883464ebd5Sriastradhvoid GLAPIENTRY 4889af69d88dSmrg_mesa_CompressedTexImage2D(GLenum target, GLint level, 48903464ebd5Sriastradh GLenum internalFormat, GLsizei width, 48913464ebd5Sriastradh GLsizei height, GLint border, GLsizei imageSize, 48923464ebd5Sriastradh const GLvoid *data) 48933464ebd5Sriastradh{ 48943464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 489501e04c3fSmrg teximage_err(ctx, GL_TRUE, 2, target, level, internalFormat, 489601e04c3fSmrg width, height, 1, border, GL_NONE, GL_NONE, imageSize, data); 48977117f1b4Smrg} 48987117f1b4Smrg 48997117f1b4Smrg 49007117f1b4Smrgvoid GLAPIENTRY 4901af69d88dSmrg_mesa_CompressedTexImage3D(GLenum target, GLint level, 49027117f1b4Smrg GLenum internalFormat, GLsizei width, 49037117f1b4Smrg GLsizei height, GLsizei depth, GLint border, 49047117f1b4Smrg GLsizei imageSize, const GLvoid *data) 49057117f1b4Smrg{ 49067117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 490701e04c3fSmrg teximage_err(ctx, GL_TRUE, 3, target, level, internalFormat, width, height, 490801e04c3fSmrg depth, border, GL_NONE, GL_NONE, imageSize, data); 490901e04c3fSmrg} 491001e04c3fSmrg 491101e04c3fSmrg 491201e04c3fSmrgvoid GLAPIENTRY 491301e04c3fSmrg_mesa_CompressedTexImage1D_no_error(GLenum target, GLint level, 491401e04c3fSmrg GLenum internalFormat, GLsizei width, 491501e04c3fSmrg GLint border, GLsizei imageSize, 491601e04c3fSmrg const GLvoid *data) 491701e04c3fSmrg{ 491801e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 491901e04c3fSmrg teximage_no_error(ctx, GL_TRUE, 1, target, level, internalFormat, width, 1, 492001e04c3fSmrg 1, border, GL_NONE, GL_NONE, imageSize, data); 492101e04c3fSmrg} 492201e04c3fSmrg 492301e04c3fSmrg 492401e04c3fSmrgvoid GLAPIENTRY 492501e04c3fSmrg_mesa_CompressedTexImage2D_no_error(GLenum target, GLint level, 492601e04c3fSmrg GLenum internalFormat, GLsizei width, 492701e04c3fSmrg GLsizei height, GLint border, 492801e04c3fSmrg GLsizei imageSize, const GLvoid *data) 492901e04c3fSmrg{ 493001e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 493101e04c3fSmrg teximage_no_error(ctx, GL_TRUE, 2, target, level, internalFormat, width, 493201e04c3fSmrg height, 1, border, GL_NONE, GL_NONE, imageSize, data); 493301e04c3fSmrg} 493401e04c3fSmrg 493501e04c3fSmrg 493601e04c3fSmrgvoid GLAPIENTRY 493701e04c3fSmrg_mesa_CompressedTexImage3D_no_error(GLenum target, GLint level, 493801e04c3fSmrg GLenum internalFormat, GLsizei width, 493901e04c3fSmrg GLsizei height, GLsizei depth, GLint border, 494001e04c3fSmrg GLsizei imageSize, const GLvoid *data) 494101e04c3fSmrg{ 494201e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 494301e04c3fSmrg teximage_no_error(ctx, GL_TRUE, 3, target, level, internalFormat, width, 494401e04c3fSmrg height, depth, border, GL_NONE, GL_NONE, imageSize, data); 49457117f1b4Smrg} 49467117f1b4Smrg 49477117f1b4Smrg 49484a49301eSmrg/** 494901e04c3fSmrg * Common helper for glCompressedTexSubImage1/2/3D() and 495001e04c3fSmrg * glCompressedTextureSubImage1/2/3D(). 49514a49301eSmrg */ 49524a49301eSmrgstatic void 495301e04c3fSmrgcompressed_texture_sub_image(struct gl_context *ctx, GLuint dims, 495401e04c3fSmrg struct gl_texture_object *texObj, 495501e04c3fSmrg struct gl_texture_image *texImage, 495601e04c3fSmrg GLenum target, GLint level, GLint xoffset, 495701e04c3fSmrg GLint yoffset, GLint zoffset, GLsizei width, 495801e04c3fSmrg GLsizei height, GLsizei depth, GLenum format, 495901e04c3fSmrg GLsizei imageSize, const GLvoid *data) 49607117f1b4Smrg{ 496101e04c3fSmrg FLUSH_VERTICES(ctx, 0); 496201e04c3fSmrg 496301e04c3fSmrg _mesa_lock_texture(ctx, texObj); 496401e04c3fSmrg { 496501e04c3fSmrg if (width > 0 && height > 0 && depth > 0) { 496601e04c3fSmrg ctx->Driver.CompressedTexSubImage(ctx, dims, texImage, 496701e04c3fSmrg xoffset, yoffset, zoffset, 496801e04c3fSmrg width, height, depth, 496901e04c3fSmrg format, imageSize, data); 497001e04c3fSmrg 497101e04c3fSmrg check_gen_mipmap(ctx, target, texObj, level); 497201e04c3fSmrg 497301e04c3fSmrg /* NOTE: Don't signal _NEW_TEXTURE_OBJECT since we've only changed 497401e04c3fSmrg * the texel data, not the texture format, size, etc. 497501e04c3fSmrg */ 497601e04c3fSmrg } 497701e04c3fSmrg } 497801e04c3fSmrg _mesa_unlock_texture(ctx, texObj); 497901e04c3fSmrg} 498001e04c3fSmrg 498101e04c3fSmrg 498201e04c3fSmrgstatic ALWAYS_INLINE void 498301e04c3fSmrgcompressed_tex_sub_image(unsigned dim, GLenum target, GLuint texture, 498401e04c3fSmrg GLint level, GLint xoffset, GLint yoffset, 498501e04c3fSmrg GLint zoffset, GLsizei width, GLsizei height, 498601e04c3fSmrg GLsizei depth, GLenum format, GLsizei imageSize, 498701e04c3fSmrg const GLvoid *data, bool dsa, bool no_error, 498801e04c3fSmrg const char *caller) 498901e04c3fSmrg{ 499001e04c3fSmrg struct gl_texture_object *texObj = NULL; 49917117f1b4Smrg struct gl_texture_image *texImage; 499201e04c3fSmrg 49937117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 4994af69d88dSmrg 499501e04c3fSmrg if (dsa) { 499601e04c3fSmrg if (no_error) { 499701e04c3fSmrg texObj = _mesa_lookup_texture(ctx, texture); 499801e04c3fSmrg } else { 499901e04c3fSmrg texObj = _mesa_lookup_texture_err(ctx, texture, caller); 500001e04c3fSmrg if (!texObj) 500101e04c3fSmrg return; 500201e04c3fSmrg } 500301e04c3fSmrg 500401e04c3fSmrg target = texObj->Target; 500501e04c3fSmrg } 500601e04c3fSmrg 500701e04c3fSmrg if (!no_error && 500801e04c3fSmrg compressed_subtexture_target_check(ctx, target, dim, format, dsa, 500901e04c3fSmrg caller)) { 50107117f1b4Smrg return; 50117117f1b4Smrg } 50127117f1b4Smrg 501301e04c3fSmrg if (!dsa) { 501401e04c3fSmrg texObj = _mesa_get_current_tex_object(ctx, target); 501501e04c3fSmrg if (!no_error && !texObj) 501601e04c3fSmrg return; 501701e04c3fSmrg } 50184a49301eSmrg 501901e04c3fSmrg if (!no_error && 502001e04c3fSmrg compressed_subtexture_error_check(ctx, dim, texObj, target, level, 502101e04c3fSmrg xoffset, yoffset, zoffset, width, 502201e04c3fSmrg height, depth, format, 502301e04c3fSmrg imageSize, data, caller)) { 502401e04c3fSmrg return; 502501e04c3fSmrg } 502601e04c3fSmrg 502701e04c3fSmrg /* Must handle special case GL_TEXTURE_CUBE_MAP. */ 502801e04c3fSmrg if (dim == 3 && dsa && texObj->Target == GL_TEXTURE_CUBE_MAP) { 502901e04c3fSmrg const char *pixels = data; 503001e04c3fSmrg GLint image_stride; 503101e04c3fSmrg 503201e04c3fSmrg /* Make sure the texture object is a proper cube. 503301e04c3fSmrg * (See texturesubimage in teximage.c for details on why this check is 503401e04c3fSmrg * performed.) 503501e04c3fSmrg */ 503601e04c3fSmrg if (!no_error && !_mesa_cube_level_complete(texObj, level)) { 503701e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 503801e04c3fSmrg "glCompressedTextureSubImage3D(cube map incomplete)"); 503901e04c3fSmrg return; 504001e04c3fSmrg } 504101e04c3fSmrg 504201e04c3fSmrg /* Copy in each face. */ 504301e04c3fSmrg for (int i = zoffset; i < zoffset + depth; ++i) { 504401e04c3fSmrg texImage = texObj->Image[i][level]; 504501e04c3fSmrg assert(texImage); 504601e04c3fSmrg 504701e04c3fSmrg compressed_texture_sub_image(ctx, 3, texObj, texImage, 504801e04c3fSmrg texObj->Target, level, xoffset, yoffset, 504901e04c3fSmrg 0, width, height, 1, format, 505001e04c3fSmrg imageSize, pixels); 505101e04c3fSmrg 505201e04c3fSmrg /* Compressed images don't have a client format */ 505301e04c3fSmrg image_stride = _mesa_format_image_size(texImage->TexFormat, 505401e04c3fSmrg texImage->Width, 505501e04c3fSmrg texImage->Height, 1); 505601e04c3fSmrg 505701e04c3fSmrg pixels += image_stride; 505801e04c3fSmrg imageSize -= image_stride; 505901e04c3fSmrg } 506001e04c3fSmrg } else { 506101e04c3fSmrg texImage = _mesa_select_tex_image(texObj, target, level); 50627117f1b4Smrg assert(texImage); 50637117f1b4Smrg 506401e04c3fSmrg compressed_texture_sub_image(ctx, dim, texObj, texImage, target, level, 506501e04c3fSmrg xoffset, yoffset, zoffset, width, height, 506601e04c3fSmrg depth, format, imageSize, data); 506701e04c3fSmrg } 506801e04c3fSmrg} 506901e04c3fSmrg 507001e04c3fSmrgstatic void 507101e04c3fSmrgcompressed_tex_sub_image_error(unsigned dim, GLenum target, GLuint texture, 507201e04c3fSmrg GLint level, GLint xoffset, GLint yoffset, 507301e04c3fSmrg GLint zoffset, GLsizei width, GLsizei height, 507401e04c3fSmrg GLsizei depth, GLenum format, GLsizei imageSize, 507501e04c3fSmrg const GLvoid *data, bool dsa, 507601e04c3fSmrg const char *caller) 507701e04c3fSmrg{ 507801e04c3fSmrg compressed_tex_sub_image(dim, target, texture, level, xoffset, yoffset, 507901e04c3fSmrg zoffset, width, height, depth, format, imageSize, 508001e04c3fSmrg data, dsa, false, caller); 508101e04c3fSmrg} 508201e04c3fSmrg 508301e04c3fSmrgstatic void 508401e04c3fSmrgcompressed_tex_sub_image_no_error(unsigned dim, GLenum target, GLuint texture, 508501e04c3fSmrg GLint level, GLint xoffset, GLint yoffset, 508601e04c3fSmrg GLint zoffset, GLsizei width, GLsizei height, 508701e04c3fSmrg GLsizei depth, GLenum format, GLsizei imageSize, 508801e04c3fSmrg const GLvoid *data, bool dsa, 508901e04c3fSmrg const char *caller) 509001e04c3fSmrg{ 509101e04c3fSmrg compressed_tex_sub_image(dim, target, texture, level, xoffset, yoffset, 509201e04c3fSmrg zoffset, width, height, depth, format, imageSize, 509301e04c3fSmrg data, dsa, true, caller); 509401e04c3fSmrg} 509501e04c3fSmrg 509601e04c3fSmrgvoid GLAPIENTRY 509701e04c3fSmrg_mesa_CompressedTexSubImage1D_no_error(GLenum target, GLint level, 509801e04c3fSmrg GLint xoffset, GLsizei width, 509901e04c3fSmrg GLenum format, GLsizei imageSize, 510001e04c3fSmrg const GLvoid *data) 510101e04c3fSmrg{ 510201e04c3fSmrg compressed_tex_sub_image_no_error(1, target, 0, level, xoffset, 0, 0, width, 510301e04c3fSmrg 1, 1, format, imageSize, data, false, 510401e04c3fSmrg "glCompressedTexSubImage1D"); 510501e04c3fSmrg} 510601e04c3fSmrg 510701e04c3fSmrg 510801e04c3fSmrgvoid GLAPIENTRY 510901e04c3fSmrg_mesa_CompressedTexSubImage1D(GLenum target, GLint level, GLint xoffset, 511001e04c3fSmrg GLsizei width, GLenum format, 511101e04c3fSmrg GLsizei imageSize, const GLvoid *data) 511201e04c3fSmrg{ 511301e04c3fSmrg compressed_tex_sub_image_error(1, target, 0, level, xoffset, 0, 0, width, 1, 511401e04c3fSmrg 1, format, imageSize, data, false, 511501e04c3fSmrg "glCompressedTexSubImage1D"); 511601e04c3fSmrg} 511701e04c3fSmrg 511801e04c3fSmrg 511901e04c3fSmrgvoid GLAPIENTRY 512001e04c3fSmrg_mesa_CompressedTextureSubImage1D_no_error(GLuint texture, GLint level, 512101e04c3fSmrg GLint xoffset, GLsizei width, 512201e04c3fSmrg GLenum format, GLsizei imageSize, 512301e04c3fSmrg const GLvoid *data) 512401e04c3fSmrg{ 512501e04c3fSmrg compressed_tex_sub_image_no_error(1, 0, texture, level, xoffset, 0, 0, width, 512601e04c3fSmrg 1, 1, format, imageSize, data, true, 512701e04c3fSmrg "glCompressedTextureSubImage1D"); 512801e04c3fSmrg} 512901e04c3fSmrg 513001e04c3fSmrg 513101e04c3fSmrgvoid GLAPIENTRY 513201e04c3fSmrg_mesa_CompressedTextureSubImage1D(GLuint texture, GLint level, GLint xoffset, 513301e04c3fSmrg GLsizei width, GLenum format, 513401e04c3fSmrg GLsizei imageSize, const GLvoid *data) 513501e04c3fSmrg{ 513601e04c3fSmrg compressed_tex_sub_image_error(1, 0, texture, level, xoffset, 0, 0, width, 513701e04c3fSmrg 1, 1, format, imageSize, data, true, 513801e04c3fSmrg "glCompressedTextureSubImage1D"); 513901e04c3fSmrg} 514001e04c3fSmrg 514101e04c3fSmrgvoid GLAPIENTRY 514201e04c3fSmrg_mesa_CompressedTexSubImage2D_no_error(GLenum target, GLint level, 514301e04c3fSmrg GLint xoffset, GLint yoffset, 514401e04c3fSmrg GLsizei width, GLsizei height, 514501e04c3fSmrg GLenum format, GLsizei imageSize, 514601e04c3fSmrg const GLvoid *data) 514701e04c3fSmrg{ 514801e04c3fSmrg compressed_tex_sub_image_no_error(2, target, 0, level, xoffset, yoffset, 0, 514901e04c3fSmrg width, height, 1, format, imageSize, data, 515001e04c3fSmrg false, "glCompressedTexSubImage2D"); 515101e04c3fSmrg} 51527117f1b4Smrg 51537117f1b4Smrg 515401e04c3fSmrgvoid GLAPIENTRY 515501e04c3fSmrg_mesa_CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, 515601e04c3fSmrg GLint yoffset, GLsizei width, GLsizei height, 515701e04c3fSmrg GLenum format, GLsizei imageSize, 515801e04c3fSmrg const GLvoid *data) 515901e04c3fSmrg{ 516001e04c3fSmrg compressed_tex_sub_image_error(2, target, 0, level, xoffset, yoffset, 0, 516101e04c3fSmrg width, height, 1, format, imageSize, data, 516201e04c3fSmrg false, "glCompressedTexSubImage2D"); 51637117f1b4Smrg} 51647117f1b4Smrg 51657117f1b4Smrg 51664a49301eSmrgvoid GLAPIENTRY 516701e04c3fSmrg_mesa_CompressedTextureSubImage2D_no_error(GLuint texture, GLint level, 516801e04c3fSmrg GLint xoffset, GLint yoffset, 516901e04c3fSmrg GLsizei width, GLsizei height, 517001e04c3fSmrg GLenum format, GLsizei imageSize, 517101e04c3fSmrg const GLvoid *data) 51724a49301eSmrg{ 517301e04c3fSmrg compressed_tex_sub_image_no_error(2, 0, texture, level, xoffset, yoffset, 0, 517401e04c3fSmrg width, height, 1, format, imageSize, data, 517501e04c3fSmrg true, "glCompressedTextureSubImage2D"); 51764a49301eSmrg} 51774a49301eSmrg 51784a49301eSmrg 51797117f1b4Smrgvoid GLAPIENTRY 518001e04c3fSmrg_mesa_CompressedTextureSubImage2D(GLuint texture, GLint level, GLint xoffset, 518101e04c3fSmrg GLint yoffset, 518201e04c3fSmrg GLsizei width, GLsizei height, 518301e04c3fSmrg GLenum format, GLsizei imageSize, 518401e04c3fSmrg const GLvoid *data) 51857117f1b4Smrg{ 518601e04c3fSmrg compressed_tex_sub_image_error(2, 0, texture, level, xoffset, yoffset, 0, 518701e04c3fSmrg width, height, 1, format, imageSize, data, 518801e04c3fSmrg true, "glCompressedTextureSubImage2D"); 51897117f1b4Smrg} 51907117f1b4Smrg 519101e04c3fSmrgvoid GLAPIENTRY 519201e04c3fSmrg_mesa_CompressedTexSubImage3D_no_error(GLenum target, GLint level, 519301e04c3fSmrg GLint xoffset, GLint yoffset, 519401e04c3fSmrg GLint zoffset, GLsizei width, 519501e04c3fSmrg GLsizei height, GLsizei depth, 519601e04c3fSmrg GLenum format, GLsizei imageSize, 519701e04c3fSmrg const GLvoid *data) 519801e04c3fSmrg{ 519901e04c3fSmrg compressed_tex_sub_image_no_error(3, target, 0, level, xoffset, yoffset, 520001e04c3fSmrg zoffset, width, height, depth, format, 520101e04c3fSmrg imageSize, data, false, 520201e04c3fSmrg "glCompressedTexSubImage3D"); 520301e04c3fSmrg} 52047117f1b4Smrg 52057117f1b4Smrgvoid GLAPIENTRY 5206af69d88dSmrg_mesa_CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, 520701e04c3fSmrg GLint yoffset, GLint zoffset, GLsizei width, 520801e04c3fSmrg GLsizei height, GLsizei depth, GLenum format, 520901e04c3fSmrg GLsizei imageSize, const GLvoid *data) 521001e04c3fSmrg{ 521101e04c3fSmrg compressed_tex_sub_image_error(3, target, 0, level, xoffset, yoffset, 521201e04c3fSmrg zoffset, width, height, depth, format, 521301e04c3fSmrg imageSize, data, false, 521401e04c3fSmrg "glCompressedTexSubImage3D"); 521501e04c3fSmrg} 521601e04c3fSmrg 521701e04c3fSmrgvoid GLAPIENTRY 521801e04c3fSmrg_mesa_CompressedTextureSubImage3D_no_error(GLuint texture, GLint level, 521901e04c3fSmrg GLint xoffset, GLint yoffset, 522001e04c3fSmrg GLint zoffset, GLsizei width, 522101e04c3fSmrg GLsizei height, GLsizei depth, 522201e04c3fSmrg GLenum format, GLsizei imageSize, 522301e04c3fSmrg const GLvoid *data) 522401e04c3fSmrg{ 522501e04c3fSmrg compressed_tex_sub_image_no_error(3, 0, texture, level, xoffset, yoffset, 522601e04c3fSmrg zoffset, width, height, depth, format, 522701e04c3fSmrg imageSize, data, true, 522801e04c3fSmrg "glCompressedTextureSubImage3D"); 522901e04c3fSmrg} 523001e04c3fSmrg 523101e04c3fSmrgvoid GLAPIENTRY 523201e04c3fSmrg_mesa_CompressedTextureSubImage3D(GLuint texture, GLint level, GLint xoffset, 523301e04c3fSmrg GLint yoffset, GLint zoffset, GLsizei width, 523401e04c3fSmrg GLsizei height, GLsizei depth, 523501e04c3fSmrg GLenum format, GLsizei imageSize, 523601e04c3fSmrg const GLvoid *data) 52377117f1b4Smrg{ 523801e04c3fSmrg compressed_tex_sub_image_error(3, 0, texture, level, xoffset, yoffset, 523901e04c3fSmrg zoffset, width, height, depth, format, 524001e04c3fSmrg imageSize, data, true, 524101e04c3fSmrg "glCompressedTextureSubImage3D"); 52427117f1b4Smrg} 52437117f1b4Smrg 524401e04c3fSmrgmesa_format 524501e04c3fSmrg_mesa_get_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat) 52463464ebd5Sriastradh{ 524701e04c3fSmrg if (ctx->API == API_OPENGL_COMPAT) { 5248af69d88dSmrg switch (internalFormat) { 5249af69d88dSmrg case GL_ALPHA8: 5250af69d88dSmrg return MESA_FORMAT_A_UNORM8; 5251af69d88dSmrg case GL_ALPHA16: 5252af69d88dSmrg return MESA_FORMAT_A_UNORM16; 5253af69d88dSmrg case GL_ALPHA16F_ARB: 5254af69d88dSmrg return MESA_FORMAT_A_FLOAT16; 5255af69d88dSmrg case GL_ALPHA32F_ARB: 5256af69d88dSmrg return MESA_FORMAT_A_FLOAT32; 5257af69d88dSmrg case GL_ALPHA8I_EXT: 5258af69d88dSmrg return MESA_FORMAT_A_SINT8; 5259af69d88dSmrg case GL_ALPHA16I_EXT: 5260af69d88dSmrg return MESA_FORMAT_A_SINT16; 5261af69d88dSmrg case GL_ALPHA32I_EXT: 5262af69d88dSmrg return MESA_FORMAT_A_SINT32; 5263af69d88dSmrg case GL_ALPHA8UI_EXT: 5264af69d88dSmrg return MESA_FORMAT_A_UINT8; 5265af69d88dSmrg case GL_ALPHA16UI_EXT: 5266af69d88dSmrg return MESA_FORMAT_A_UINT16; 5267af69d88dSmrg case GL_ALPHA32UI_EXT: 5268af69d88dSmrg return MESA_FORMAT_A_UINT32; 5269af69d88dSmrg case GL_LUMINANCE8: 5270af69d88dSmrg return MESA_FORMAT_L_UNORM8; 5271af69d88dSmrg case GL_LUMINANCE16: 5272af69d88dSmrg return MESA_FORMAT_L_UNORM16; 5273af69d88dSmrg case GL_LUMINANCE16F_ARB: 5274af69d88dSmrg return MESA_FORMAT_L_FLOAT16; 5275af69d88dSmrg case GL_LUMINANCE32F_ARB: 5276af69d88dSmrg return MESA_FORMAT_L_FLOAT32; 5277af69d88dSmrg case GL_LUMINANCE8I_EXT: 5278af69d88dSmrg return MESA_FORMAT_L_SINT8; 5279af69d88dSmrg case GL_LUMINANCE16I_EXT: 5280af69d88dSmrg return MESA_FORMAT_L_SINT16; 5281af69d88dSmrg case GL_LUMINANCE32I_EXT: 5282af69d88dSmrg return MESA_FORMAT_L_SINT32; 5283af69d88dSmrg case GL_LUMINANCE8UI_EXT: 5284af69d88dSmrg return MESA_FORMAT_L_UINT8; 5285af69d88dSmrg case GL_LUMINANCE16UI_EXT: 5286af69d88dSmrg return MESA_FORMAT_L_UINT16; 5287af69d88dSmrg case GL_LUMINANCE32UI_EXT: 5288af69d88dSmrg return MESA_FORMAT_L_UINT32; 5289af69d88dSmrg case GL_LUMINANCE8_ALPHA8: 5290af69d88dSmrg return MESA_FORMAT_L8A8_UNORM; 5291af69d88dSmrg case GL_LUMINANCE16_ALPHA16: 5292af69d88dSmrg return MESA_FORMAT_L16A16_UNORM; 5293af69d88dSmrg case GL_LUMINANCE_ALPHA16F_ARB: 5294af69d88dSmrg return MESA_FORMAT_LA_FLOAT16; 5295af69d88dSmrg case GL_LUMINANCE_ALPHA32F_ARB: 5296af69d88dSmrg return MESA_FORMAT_LA_FLOAT32; 5297af69d88dSmrg case GL_LUMINANCE_ALPHA8I_EXT: 5298af69d88dSmrg return MESA_FORMAT_LA_SINT8; 5299af69d88dSmrg case GL_LUMINANCE_ALPHA16I_EXT: 5300af69d88dSmrg return MESA_FORMAT_LA_SINT16; 530101e04c3fSmrg case GL_LUMINANCE_ALPHA32I_EXT: 530201e04c3fSmrg return MESA_FORMAT_LA_SINT32; 5303af69d88dSmrg case GL_LUMINANCE_ALPHA8UI_EXT: 5304af69d88dSmrg return MESA_FORMAT_LA_UINT8; 5305af69d88dSmrg case GL_LUMINANCE_ALPHA16UI_EXT: 5306af69d88dSmrg return MESA_FORMAT_LA_UINT16; 5307af69d88dSmrg case GL_LUMINANCE_ALPHA32UI_EXT: 5308af69d88dSmrg return MESA_FORMAT_LA_UINT32; 5309af69d88dSmrg case GL_INTENSITY8: 5310af69d88dSmrg return MESA_FORMAT_I_UNORM8; 5311af69d88dSmrg case GL_INTENSITY16: 5312af69d88dSmrg return MESA_FORMAT_I_UNORM16; 5313af69d88dSmrg case GL_INTENSITY16F_ARB: 5314af69d88dSmrg return MESA_FORMAT_I_FLOAT16; 5315af69d88dSmrg case GL_INTENSITY32F_ARB: 5316af69d88dSmrg return MESA_FORMAT_I_FLOAT32; 5317af69d88dSmrg case GL_INTENSITY8I_EXT: 5318af69d88dSmrg return MESA_FORMAT_I_SINT8; 5319af69d88dSmrg case GL_INTENSITY16I_EXT: 5320af69d88dSmrg return MESA_FORMAT_I_SINT16; 5321af69d88dSmrg case GL_INTENSITY32I_EXT: 5322af69d88dSmrg return MESA_FORMAT_I_SINT32; 5323af69d88dSmrg case GL_INTENSITY8UI_EXT: 5324af69d88dSmrg return MESA_FORMAT_I_UINT8; 5325af69d88dSmrg case GL_INTENSITY16UI_EXT: 5326af69d88dSmrg return MESA_FORMAT_I_UINT16; 5327af69d88dSmrg case GL_INTENSITY32UI_EXT: 5328af69d88dSmrg return MESA_FORMAT_I_UINT32; 5329af69d88dSmrg default: 5330af69d88dSmrg break; 5331af69d88dSmrg } 5332af69d88dSmrg } 5333af69d88dSmrg 533401e04c3fSmrg if (_mesa_has_ARB_texture_buffer_object_rgb32(ctx) || 533501e04c3fSmrg _mesa_has_OES_texture_buffer(ctx)) { 5336af69d88dSmrg switch (internalFormat) { 5337af69d88dSmrg case GL_RGB32F: 5338af69d88dSmrg return MESA_FORMAT_RGB_FLOAT32; 5339af69d88dSmrg case GL_RGB32UI: 5340af69d88dSmrg return MESA_FORMAT_RGB_UINT32; 5341af69d88dSmrg case GL_RGB32I: 5342af69d88dSmrg return MESA_FORMAT_RGB_SINT32; 5343af69d88dSmrg default: 5344af69d88dSmrg break; 5345af69d88dSmrg } 5346af69d88dSmrg } 5347af69d88dSmrg 53483464ebd5Sriastradh switch (internalFormat) { 53493464ebd5Sriastradh case GL_RGBA8: 5350af69d88dSmrg return MESA_FORMAT_R8G8B8A8_UNORM; 53513464ebd5Sriastradh case GL_RGBA16: 535201e04c3fSmrg if (_mesa_is_gles(ctx) && !_mesa_has_EXT_texture_norm16(ctx)) 535301e04c3fSmrg return MESA_FORMAT_NONE; 5354af69d88dSmrg return MESA_FORMAT_RGBA_UNORM16; 53553464ebd5Sriastradh case GL_RGBA16F_ARB: 5356af69d88dSmrg return MESA_FORMAT_RGBA_FLOAT16; 53573464ebd5Sriastradh case GL_RGBA32F_ARB: 5358af69d88dSmrg return MESA_FORMAT_RGBA_FLOAT32; 53593464ebd5Sriastradh case GL_RGBA8I_EXT: 5360af69d88dSmrg return MESA_FORMAT_RGBA_SINT8; 53613464ebd5Sriastradh case GL_RGBA16I_EXT: 5362af69d88dSmrg return MESA_FORMAT_RGBA_SINT16; 53633464ebd5Sriastradh case GL_RGBA32I_EXT: 5364af69d88dSmrg return MESA_FORMAT_RGBA_SINT32; 53653464ebd5Sriastradh case GL_RGBA8UI_EXT: 5366af69d88dSmrg return MESA_FORMAT_RGBA_UINT8; 53673464ebd5Sriastradh case GL_RGBA16UI_EXT: 5368af69d88dSmrg return MESA_FORMAT_RGBA_UINT16; 53693464ebd5Sriastradh case GL_RGBA32UI_EXT: 5370af69d88dSmrg return MESA_FORMAT_RGBA_UINT32; 5371af69d88dSmrg 5372af69d88dSmrg case GL_RG8: 5373af69d88dSmrg return MESA_FORMAT_R8G8_UNORM; 5374af69d88dSmrg case GL_RG16: 537501e04c3fSmrg if (_mesa_is_gles(ctx) && !_mesa_has_EXT_texture_norm16(ctx)) 537601e04c3fSmrg return MESA_FORMAT_NONE; 5377af69d88dSmrg return MESA_FORMAT_R16G16_UNORM; 5378af69d88dSmrg case GL_RG16F: 5379af69d88dSmrg return MESA_FORMAT_RG_FLOAT16; 5380af69d88dSmrg case GL_RG32F: 5381af69d88dSmrg return MESA_FORMAT_RG_FLOAT32; 5382af69d88dSmrg case GL_RG8I: 5383af69d88dSmrg return MESA_FORMAT_RG_SINT8; 5384af69d88dSmrg case GL_RG16I: 5385af69d88dSmrg return MESA_FORMAT_RG_SINT16; 5386af69d88dSmrg case GL_RG32I: 5387af69d88dSmrg return MESA_FORMAT_RG_SINT32; 5388af69d88dSmrg case GL_RG8UI: 5389af69d88dSmrg return MESA_FORMAT_RG_UINT8; 5390af69d88dSmrg case GL_RG16UI: 5391af69d88dSmrg return MESA_FORMAT_RG_UINT16; 5392af69d88dSmrg case GL_RG32UI: 5393af69d88dSmrg return MESA_FORMAT_RG_UINT32; 5394af69d88dSmrg 5395af69d88dSmrg case GL_R8: 5396af69d88dSmrg return MESA_FORMAT_R_UNORM8; 5397af69d88dSmrg case GL_R16: 539801e04c3fSmrg if (_mesa_is_gles(ctx) && !_mesa_has_EXT_texture_norm16(ctx)) 539901e04c3fSmrg return MESA_FORMAT_NONE; 5400af69d88dSmrg return MESA_FORMAT_R_UNORM16; 5401af69d88dSmrg case GL_R16F: 5402af69d88dSmrg return MESA_FORMAT_R_FLOAT16; 5403af69d88dSmrg case GL_R32F: 5404af69d88dSmrg return MESA_FORMAT_R_FLOAT32; 5405af69d88dSmrg case GL_R8I: 5406af69d88dSmrg return MESA_FORMAT_R_SINT8; 5407af69d88dSmrg case GL_R16I: 5408af69d88dSmrg return MESA_FORMAT_R_SINT16; 5409af69d88dSmrg case GL_R32I: 5410af69d88dSmrg return MESA_FORMAT_R_SINT32; 5411af69d88dSmrg case GL_R8UI: 5412af69d88dSmrg return MESA_FORMAT_R_UINT8; 5413af69d88dSmrg case GL_R16UI: 5414af69d88dSmrg return MESA_FORMAT_R_UINT16; 5415af69d88dSmrg case GL_R32UI: 5416af69d88dSmrg return MESA_FORMAT_R_UINT32; 5417af69d88dSmrg 54183464ebd5Sriastradh default: 5419af69d88dSmrg return MESA_FORMAT_NONE; 54203464ebd5Sriastradh } 5421af69d88dSmrg} 54223464ebd5Sriastradh 54233464ebd5Sriastradh 5424af69d88dSmrgmesa_format 5425af69d88dSmrg_mesa_validate_texbuffer_format(const struct gl_context *ctx, 5426af69d88dSmrg GLenum internalFormat) 5427af69d88dSmrg{ 542801e04c3fSmrg mesa_format format = _mesa_get_texbuffer_format(ctx, internalFormat); 5429af69d88dSmrg GLenum datatype; 5430af69d88dSmrg 5431af69d88dSmrg if (format == MESA_FORMAT_NONE) 5432af69d88dSmrg return MESA_FORMAT_NONE; 5433af69d88dSmrg 5434af69d88dSmrg datatype = _mesa_get_format_datatype(format); 5435af69d88dSmrg 5436af69d88dSmrg /* The GL_ARB_texture_buffer_object spec says: 5437af69d88dSmrg * 5438af69d88dSmrg * "If ARB_texture_float is not supported, references to the 5439af69d88dSmrg * floating-point internal formats provided by that extension should be 5440af69d88dSmrg * removed, and such formats may not be passed to TexBufferARB." 5441af69d88dSmrg * 5442af69d88dSmrg * As a result, GL_HALF_FLOAT internal format depends on both 5443af69d88dSmrg * GL_ARB_texture_float and GL_ARB_half_float_pixel. 5444af69d88dSmrg */ 5445af69d88dSmrg if ((datatype == GL_FLOAT || datatype == GL_HALF_FLOAT) && 5446af69d88dSmrg !ctx->Extensions.ARB_texture_float) 5447af69d88dSmrg return MESA_FORMAT_NONE; 54483464ebd5Sriastradh 5449af69d88dSmrg if (!ctx->Extensions.ARB_texture_rg) { 5450af69d88dSmrg GLenum base_format = _mesa_get_format_base_format(format); 5451af69d88dSmrg if (base_format == GL_R || base_format == GL_RG) 5452af69d88dSmrg return MESA_FORMAT_NONE; 5453af69d88dSmrg } 5454af69d88dSmrg 5455af69d88dSmrg if (!ctx->Extensions.ARB_texture_buffer_object_rgb32) { 5456af69d88dSmrg GLenum base_format = _mesa_get_format_base_format(format); 5457af69d88dSmrg if (base_format == GL_RGB) 5458af69d88dSmrg return MESA_FORMAT_NONE; 5459af69d88dSmrg } 5460af69d88dSmrg return format; 5461af69d88dSmrg} 5462af69d88dSmrg 5463af69d88dSmrg 546401e04c3fSmrg/** 546501e04c3fSmrg * Do work common to glTexBuffer, glTexBufferRange, glTextureBuffer 546601e04c3fSmrg * and glTextureBufferRange, including some error checking. 546701e04c3fSmrg */ 5468af69d88dSmrgstatic void 546901e04c3fSmrgtexture_buffer_range(struct gl_context *ctx, 547001e04c3fSmrg struct gl_texture_object *texObj, 547101e04c3fSmrg GLenum internalFormat, 547201e04c3fSmrg struct gl_buffer_object *bufObj, 547301e04c3fSmrg GLintptr offset, GLsizeiptr size, 547401e04c3fSmrg const char *caller) 5475af69d88dSmrg{ 547601e04c3fSmrg GLintptr oldOffset = texObj->BufferOffset; 547701e04c3fSmrg GLsizeiptr oldSize = texObj->BufferSize; 5478af69d88dSmrg mesa_format format; 5479af69d88dSmrg 548001e04c3fSmrg /* NOTE: ARB_texture_buffer_object might not be supported in 548101e04c3fSmrg * the compatibility profile. 548201e04c3fSmrg */ 548301e04c3fSmrg if (!_mesa_has_ARB_texture_buffer_object(ctx) && 548401e04c3fSmrg !_mesa_has_OES_texture_buffer(ctx)) { 548501e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 548601e04c3fSmrg "%s(ARB_texture_buffer_object is not" 548701e04c3fSmrg " implemented for the compatibility profile)", caller); 548801e04c3fSmrg return; 548901e04c3fSmrg } 5490af69d88dSmrg 549101e04c3fSmrg if (texObj->HandleAllocated) { 549201e04c3fSmrg /* The ARB_bindless_texture spec says: 549301e04c3fSmrg * 549401e04c3fSmrg * "The error INVALID_OPERATION is generated by TexImage*, CopyTexImage*, 549501e04c3fSmrg * CompressedTexImage*, TexBuffer*, TexParameter*, as well as other 549601e04c3fSmrg * functions defined in terms of these, if the texture object to be 549701e04c3fSmrg * modified is referenced by one or more texture or image handles." 549801e04c3fSmrg */ 549901e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(immutable texture)", caller); 5500af69d88dSmrg return; 5501af69d88dSmrg } 5502af69d88dSmrg 5503af69d88dSmrg format = _mesa_validate_texbuffer_format(ctx, internalFormat); 5504af69d88dSmrg if (format == MESA_FORMAT_NONE) { 550501e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalFormat %s)", 550601e04c3fSmrg caller, _mesa_enum_to_string(internalFormat)); 5507af69d88dSmrg return; 5508af69d88dSmrg } 5509af69d88dSmrg 551001e04c3fSmrg FLUSH_VERTICES(ctx, 0); 5511af69d88dSmrg 5512af69d88dSmrg _mesa_lock_texture(ctx, texObj); 5513af69d88dSmrg { 5514af69d88dSmrg _mesa_reference_buffer_object(ctx, &texObj->BufferObject, bufObj); 5515af69d88dSmrg texObj->BufferObjectFormat = internalFormat; 5516af69d88dSmrg texObj->_BufferObjectFormat = format; 5517af69d88dSmrg texObj->BufferOffset = offset; 5518af69d88dSmrg texObj->BufferSize = size; 5519af69d88dSmrg } 5520af69d88dSmrg _mesa_unlock_texture(ctx, texObj); 552101e04c3fSmrg 552201e04c3fSmrg if (ctx->Driver.TexParameter) { 552301e04c3fSmrg if (offset != oldOffset) { 552401e04c3fSmrg ctx->Driver.TexParameter(ctx, texObj, GL_TEXTURE_BUFFER_OFFSET); 552501e04c3fSmrg } 552601e04c3fSmrg if (size != oldSize) { 552701e04c3fSmrg ctx->Driver.TexParameter(ctx, texObj, GL_TEXTURE_BUFFER_SIZE); 552801e04c3fSmrg } 552901e04c3fSmrg } 553001e04c3fSmrg 553101e04c3fSmrg ctx->NewDriverState |= ctx->DriverFlags.NewTextureBuffer; 553201e04c3fSmrg 553301e04c3fSmrg if (bufObj) { 553401e04c3fSmrg bufObj->UsageHistory |= USAGE_TEXTURE_BUFFER; 553501e04c3fSmrg } 553601e04c3fSmrg} 553701e04c3fSmrg 553801e04c3fSmrg 553901e04c3fSmrg/** 554001e04c3fSmrg * Make sure the texture buffer target is GL_TEXTURE_BUFFER. 554101e04c3fSmrg * Return true if it is, and return false if it is not 554201e04c3fSmrg * (and throw INVALID ENUM as dictated in the OpenGL 4.5 554301e04c3fSmrg * core spec, 02.02.2015, PDF page 245). 554401e04c3fSmrg */ 554501e04c3fSmrgstatic bool 554601e04c3fSmrgcheck_texture_buffer_target(struct gl_context *ctx, GLenum target, 554701e04c3fSmrg const char *caller) 554801e04c3fSmrg{ 554901e04c3fSmrg if (target != GL_TEXTURE_BUFFER_ARB) { 555001e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, 555101e04c3fSmrg "%s(texture target is not GL_TEXTURE_BUFFER)", caller); 555201e04c3fSmrg return false; 555301e04c3fSmrg } 555401e04c3fSmrg else 555501e04c3fSmrg return true; 555601e04c3fSmrg} 555701e04c3fSmrg 555801e04c3fSmrg/** 555901e04c3fSmrg * Check for errors related to the texture buffer range. 556001e04c3fSmrg * Return false if errors are found, true if none are found. 556101e04c3fSmrg */ 556201e04c3fSmrgstatic bool 556301e04c3fSmrgcheck_texture_buffer_range(struct gl_context *ctx, 556401e04c3fSmrg struct gl_buffer_object *bufObj, 556501e04c3fSmrg GLintptr offset, GLsizeiptr size, 556601e04c3fSmrg const char *caller) 556701e04c3fSmrg{ 556801e04c3fSmrg /* OpenGL 4.5 core spec (02.02.2015) says in Section 8.9 Buffer 556901e04c3fSmrg * Textures (PDF page 245): 557001e04c3fSmrg * "An INVALID_VALUE error is generated if offset is negative, if 557101e04c3fSmrg * size is less than or equal to zero, or if offset + size is greater 557201e04c3fSmrg * than the value of BUFFER_SIZE for the buffer bound to target." 557301e04c3fSmrg */ 557401e04c3fSmrg if (offset < 0) { 557501e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(offset=%d < 0)", caller, 557601e04c3fSmrg (int) offset); 557701e04c3fSmrg return false; 557801e04c3fSmrg } 557901e04c3fSmrg 558001e04c3fSmrg if (size <= 0) { 558101e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(size=%d <= 0)", caller, 558201e04c3fSmrg (int) size); 558301e04c3fSmrg return false; 558401e04c3fSmrg } 558501e04c3fSmrg 558601e04c3fSmrg if (offset + size > bufObj->Size) { 558701e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, 558801e04c3fSmrg "%s(offset=%d + size=%d > buffer_size=%d)", caller, 558901e04c3fSmrg (int) offset, (int) size, (int) bufObj->Size); 559001e04c3fSmrg return false; 559101e04c3fSmrg } 559201e04c3fSmrg 559301e04c3fSmrg /* OpenGL 4.5 core spec (02.02.2015) says in Section 8.9 Buffer 559401e04c3fSmrg * Textures (PDF page 245): 559501e04c3fSmrg * "An INVALID_VALUE error is generated if offset is not an integer 559601e04c3fSmrg * multiple of the value of TEXTURE_BUFFER_OFFSET_ALIGNMENT." 559701e04c3fSmrg */ 559801e04c3fSmrg if (offset % ctx->Const.TextureBufferOffsetAlignment) { 559901e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, 560001e04c3fSmrg "%s(invalid offset alignment)", caller); 560101e04c3fSmrg return false; 560201e04c3fSmrg } 560301e04c3fSmrg 560401e04c3fSmrg return true; 56053464ebd5Sriastradh} 56063464ebd5Sriastradh 56073464ebd5Sriastradh 56083464ebd5Sriastradh/** GL_ARB_texture_buffer_object */ 56093464ebd5Sriastradhvoid GLAPIENTRY 56103464ebd5Sriastradh_mesa_TexBuffer(GLenum target, GLenum internalFormat, GLuint buffer) 56113464ebd5Sriastradh{ 561201e04c3fSmrg struct gl_texture_object *texObj; 56133464ebd5Sriastradh struct gl_buffer_object *bufObj; 56143464ebd5Sriastradh 56153464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 56163464ebd5Sriastradh 561701e04c3fSmrg /* Need to catch a bad target before it gets to 561801e04c3fSmrg * _mesa_get_current_tex_object. 5619af69d88dSmrg */ 562001e04c3fSmrg if (!check_texture_buffer_target(ctx, target, "glTexBuffer")) 56213464ebd5Sriastradh return; 56223464ebd5Sriastradh 562301e04c3fSmrg if (buffer) { 562401e04c3fSmrg bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glTexBuffer"); 562501e04c3fSmrg if (!bufObj) 562601e04c3fSmrg return; 562701e04c3fSmrg } else 562801e04c3fSmrg bufObj = NULL; 562901e04c3fSmrg 563001e04c3fSmrg texObj = _mesa_get_current_tex_object(ctx, target); 563101e04c3fSmrg if (!texObj) 56323464ebd5Sriastradh return; 56333464ebd5Sriastradh 563401e04c3fSmrg texture_buffer_range(ctx, texObj, internalFormat, bufObj, 0, 563501e04c3fSmrg buffer ? -1 : 0, "glTexBuffer"); 5636af69d88dSmrg} 5637af69d88dSmrg 5638af69d88dSmrg 5639af69d88dSmrg/** GL_ARB_texture_buffer_range */ 5640af69d88dSmrgvoid GLAPIENTRY 5641af69d88dSmrg_mesa_TexBufferRange(GLenum target, GLenum internalFormat, GLuint buffer, 5642af69d88dSmrg GLintptr offset, GLsizeiptr size) 5643af69d88dSmrg{ 564401e04c3fSmrg struct gl_texture_object *texObj; 5645af69d88dSmrg struct gl_buffer_object *bufObj; 5646af69d88dSmrg 5647af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 5648af69d88dSmrg 564901e04c3fSmrg /* Need to catch a bad target before it gets to 565001e04c3fSmrg * _mesa_get_current_tex_object. 565101e04c3fSmrg */ 565201e04c3fSmrg if (!check_texture_buffer_target(ctx, target, "glTexBufferRange")) 56533464ebd5Sriastradh return; 56543464ebd5Sriastradh 565501e04c3fSmrg if (buffer) { 565601e04c3fSmrg bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glTexBufferRange"); 565701e04c3fSmrg if (!bufObj) 5658af69d88dSmrg return; 565901e04c3fSmrg 566001e04c3fSmrg if (!check_texture_buffer_range(ctx, bufObj, offset, size, 566101e04c3fSmrg "glTexBufferRange")) 5662af69d88dSmrg return; 566301e04c3fSmrg 5664af69d88dSmrg } else { 566501e04c3fSmrg /* OpenGL 4.5 core spec (02.02.2015) says in Section 8.9 Buffer 566601e04c3fSmrg * Textures (PDF page 254): 566701e04c3fSmrg * "If buffer is zero, then any buffer object attached to the buffer 566801e04c3fSmrg * texture is detached, the values offset and size are ignored and 566901e04c3fSmrg * the state for offset and size for the buffer texture are reset to 567001e04c3fSmrg * zero." 567101e04c3fSmrg */ 5672af69d88dSmrg offset = 0; 5673af69d88dSmrg size = 0; 567401e04c3fSmrg bufObj = NULL; 5675af69d88dSmrg } 5676af69d88dSmrg 567701e04c3fSmrg texObj = _mesa_get_current_tex_object(ctx, target); 567801e04c3fSmrg if (!texObj) 567901e04c3fSmrg return; 568001e04c3fSmrg 568101e04c3fSmrg texture_buffer_range(ctx, texObj, internalFormat, bufObj, 568201e04c3fSmrg offset, size, "glTexBufferRange"); 5683af69d88dSmrg} 5684af69d88dSmrg 568501e04c3fSmrgvoid GLAPIENTRY 568601e04c3fSmrg_mesa_TextureBuffer(GLuint texture, GLenum internalFormat, GLuint buffer) 568701e04c3fSmrg{ 568801e04c3fSmrg struct gl_texture_object *texObj; 568901e04c3fSmrg struct gl_buffer_object *bufObj; 5690af69d88dSmrg 569101e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 569201e04c3fSmrg 569301e04c3fSmrg if (buffer) { 569401e04c3fSmrg bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glTextureBuffer"); 569501e04c3fSmrg if (!bufObj) 569601e04c3fSmrg return; 569701e04c3fSmrg } else 569801e04c3fSmrg bufObj = NULL; 569901e04c3fSmrg 570001e04c3fSmrg /* Get the texture object by Name. */ 570101e04c3fSmrg texObj = _mesa_lookup_texture_err(ctx, texture, "glTextureBuffer"); 570201e04c3fSmrg if (!texObj) 570301e04c3fSmrg return; 570401e04c3fSmrg 570501e04c3fSmrg if (!check_texture_buffer_target(ctx, texObj->Target, "glTextureBuffer")) 570601e04c3fSmrg return; 570701e04c3fSmrg 570801e04c3fSmrg texture_buffer_range(ctx, texObj, internalFormat, 570901e04c3fSmrg bufObj, 0, buffer ? -1 : 0, "glTextureBuffer"); 571001e04c3fSmrg} 571101e04c3fSmrg 571201e04c3fSmrgvoid GLAPIENTRY 571301e04c3fSmrg_mesa_TextureBufferRange(GLuint texture, GLenum internalFormat, GLuint buffer, 571401e04c3fSmrg GLintptr offset, GLsizeiptr size) 571501e04c3fSmrg{ 571601e04c3fSmrg struct gl_texture_object *texObj; 571701e04c3fSmrg struct gl_buffer_object *bufObj; 571801e04c3fSmrg 571901e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 572001e04c3fSmrg 572101e04c3fSmrg if (buffer) { 572201e04c3fSmrg bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, 572301e04c3fSmrg "glTextureBufferRange"); 572401e04c3fSmrg if (!bufObj) 572501e04c3fSmrg return; 572601e04c3fSmrg 572701e04c3fSmrg if (!check_texture_buffer_range(ctx, bufObj, offset, size, 572801e04c3fSmrg "glTextureBufferRange")) 572901e04c3fSmrg return; 573001e04c3fSmrg 573101e04c3fSmrg } else { 573201e04c3fSmrg /* OpenGL 4.5 core spec (02.02.2015) says in Section 8.9 Buffer 573301e04c3fSmrg * Textures (PDF page 254): 573401e04c3fSmrg * "If buffer is zero, then any buffer object attached to the buffer 573501e04c3fSmrg * texture is detached, the values offset and size are ignored and 573601e04c3fSmrg * the state for offset and size for the buffer texture are reset to 573701e04c3fSmrg * zero." 573801e04c3fSmrg */ 573901e04c3fSmrg offset = 0; 574001e04c3fSmrg size = 0; 574101e04c3fSmrg bufObj = NULL; 574201e04c3fSmrg } 574301e04c3fSmrg 574401e04c3fSmrg /* Get the texture object by Name. */ 574501e04c3fSmrg texObj = _mesa_lookup_texture_err(ctx, texture, "glTextureBufferRange"); 574601e04c3fSmrg if (!texObj) 574701e04c3fSmrg return; 574801e04c3fSmrg 574901e04c3fSmrg if (!check_texture_buffer_target(ctx, texObj->Target, 575001e04c3fSmrg "glTextureBufferRange")) 575101e04c3fSmrg return; 575201e04c3fSmrg 575301e04c3fSmrg texture_buffer_range(ctx, texObj, internalFormat, 575401e04c3fSmrg bufObj, offset, size, "glTextureBufferRange"); 575501e04c3fSmrg} 575601e04c3fSmrg 575701e04c3fSmrgGLboolean 575801e04c3fSmrg_mesa_is_renderable_texture_format(const struct gl_context *ctx, 575901e04c3fSmrg GLenum internalformat) 5760af69d88dSmrg{ 5761af69d88dSmrg /* Everything that is allowed for renderbuffers, 576201e04c3fSmrg * except for a base format of GL_STENCIL_INDEX, unless supported. 5763af69d88dSmrg */ 5764af69d88dSmrg GLenum baseFormat = _mesa_base_fbo_format(ctx, internalformat); 576501e04c3fSmrg if (ctx->Extensions.ARB_texture_stencil8) 576601e04c3fSmrg return baseFormat != 0; 576701e04c3fSmrg else 576801e04c3fSmrg return baseFormat != 0 && baseFormat != GL_STENCIL_INDEX; 5769af69d88dSmrg} 5770af69d88dSmrg 5771af69d88dSmrg 5772af69d88dSmrg/** GL_ARB_texture_multisample */ 5773af69d88dSmrgstatic GLboolean 577401e04c3fSmrgcheck_multisample_target(GLuint dims, GLenum target, bool dsa) 5775af69d88dSmrg{ 5776af69d88dSmrg switch(target) { 5777af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE: 5778af69d88dSmrg return dims == 2; 577901e04c3fSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE: 578001e04c3fSmrg return dims == 2 && !dsa; 5781af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 5782af69d88dSmrg return dims == 3; 578301e04c3fSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY: 578401e04c3fSmrg return dims == 3 && !dsa; 5785af69d88dSmrg default: 5786af69d88dSmrg return GL_FALSE; 5787af69d88dSmrg } 5788af69d88dSmrg} 5789af69d88dSmrg 5790af69d88dSmrg 5791af69d88dSmrgstatic void 579201e04c3fSmrgtexture_image_multisample(struct gl_context *ctx, GLuint dims, 579301e04c3fSmrg struct gl_texture_object *texObj, 579401e04c3fSmrg struct gl_memory_object *memObj, 579501e04c3fSmrg GLenum target, GLsizei samples, 579601e04c3fSmrg GLint internalformat, GLsizei width, 579701e04c3fSmrg GLsizei height, GLsizei depth, 579801e04c3fSmrg GLboolean fixedsamplelocations, 579901e04c3fSmrg GLboolean immutable, GLuint64 offset, 580001e04c3fSmrg const char *func) 5801af69d88dSmrg{ 5802af69d88dSmrg struct gl_texture_image *texImage; 5803af69d88dSmrg GLboolean sizeOK, dimensionsOK, samplesOK; 5804af69d88dSmrg mesa_format texFormat; 5805af69d88dSmrg GLenum sample_count_error; 580601e04c3fSmrg bool dsa = strstr(func, "ture") ? true : false; 5807af69d88dSmrg 580801e04c3fSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) { 580901e04c3fSmrg _mesa_debug(ctx, "%s(target=%s, samples=%d)\n", func, 581001e04c3fSmrg _mesa_enum_to_string(target), samples); 581101e04c3fSmrg } 5812af69d88dSmrg 581301e04c3fSmrg if (!((ctx->Extensions.ARB_texture_multisample 581401e04c3fSmrg && _mesa_is_desktop_gl(ctx))) && !_mesa_is_gles31(ctx)) { 5815af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); 5816af69d88dSmrg return; 5817af69d88dSmrg } 5818af69d88dSmrg 581901e04c3fSmrg if (samples < 1) { 582001e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(samples < 1)", func); 582101e04c3fSmrg return; 582201e04c3fSmrg } 582301e04c3fSmrg 582401e04c3fSmrg if (!check_multisample_target(dims, target, dsa)) { 582501e04c3fSmrg GLenum err = dsa ? GL_INVALID_OPERATION : GL_INVALID_ENUM; 582601e04c3fSmrg _mesa_error(ctx, err, "%s(target=%s)", func, 582701e04c3fSmrg _mesa_enum_to_string(target)); 5828af69d88dSmrg return; 5829af69d88dSmrg } 5830af69d88dSmrg 5831af69d88dSmrg /* check that the specified internalformat is color/depth/stencil-renderable; 5832af69d88dSmrg * refer GL3.1 spec 4.4.4 5833af69d88dSmrg */ 5834af69d88dSmrg 5835af69d88dSmrg if (immutable && !_mesa_is_legal_tex_storage_format(ctx, internalformat)) { 5836af69d88dSmrg _mesa_error(ctx, GL_INVALID_ENUM, 5837af69d88dSmrg "%s(internalformat=%s not legal for immutable-format)", 583801e04c3fSmrg func, _mesa_enum_to_string(internalformat)); 5839af69d88dSmrg return; 5840af69d88dSmrg } 5841af69d88dSmrg 584201e04c3fSmrg if (!_mesa_is_renderable_texture_format(ctx, internalformat)) { 584301e04c3fSmrg /* Page 172 of OpenGL ES 3.1 spec says: 584401e04c3fSmrg * "An INVALID_ENUM error is generated if sizedinternalformat is not 584501e04c3fSmrg * color-renderable, depth-renderable, or stencil-renderable (as 584601e04c3fSmrg * defined in section 9.4). 584701e04c3fSmrg * 584801e04c3fSmrg * (Same error is also defined for desktop OpenGL for multisample 584901e04c3fSmrg * teximage/texstorage functions.) 585001e04c3fSmrg */ 585101e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalformat=%s)", func, 585201e04c3fSmrg _mesa_enum_to_string(internalformat)); 5853af69d88dSmrg return; 5854af69d88dSmrg } 5855af69d88dSmrg 5856af69d88dSmrg sample_count_error = _mesa_check_sample_count(ctx, target, 585701e04c3fSmrg internalformat, samples, samples); 5858af69d88dSmrg samplesOK = sample_count_error == GL_NO_ERROR; 5859af69d88dSmrg 5860af69d88dSmrg /* Page 254 of OpenGL 4.4 spec says: 5861af69d88dSmrg * "Proxy arrays for two-dimensional multisample and two-dimensional 5862af69d88dSmrg * multisample array textures are operated on in the same way when 5863af69d88dSmrg * TexImage2DMultisample is called with target specified as 5864af69d88dSmrg * PROXY_TEXTURE_2D_MULTISAMPLE, or TexImage3DMultisample is called 5865af69d88dSmrg * with target specified as PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY. 5866af69d88dSmrg * However, if samples is not supported, then no error is generated. 5867af69d88dSmrg */ 5868af69d88dSmrg if (!samplesOK && !_mesa_is_proxy_texture(target)) { 586901e04c3fSmrg _mesa_error(ctx, sample_count_error, "%s(samples=%d)", func, samples); 58703464ebd5Sriastradh return; 58713464ebd5Sriastradh } 58723464ebd5Sriastradh 5873af69d88dSmrg if (immutable && (!texObj || (texObj->Name == 0))) { 5874af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 5875af69d88dSmrg "%s(texture object 0)", 5876af69d88dSmrg func); 5877af69d88dSmrg return; 58783464ebd5Sriastradh } 5879af69d88dSmrg 5880af69d88dSmrg texImage = _mesa_get_tex_image(ctx, texObj, 0, 0); 5881af69d88dSmrg 5882af69d88dSmrg if (texImage == NULL) { 5883af69d88dSmrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s()", func); 5884af69d88dSmrg return; 5885af69d88dSmrg } 5886af69d88dSmrg 5887af69d88dSmrg texFormat = _mesa_choose_texture_format(ctx, texObj, target, 0, 5888af69d88dSmrg internalformat, GL_NONE, GL_NONE); 5889af69d88dSmrg assert(texFormat != MESA_FORMAT_NONE); 5890af69d88dSmrg 5891af69d88dSmrg dimensionsOK = _mesa_legal_texture_dimensions(ctx, target, 0, 5892af69d88dSmrg width, height, depth, 0); 5893af69d88dSmrg 589401e04c3fSmrg sizeOK = ctx->Driver.TestProxyTexImage(ctx, target, 0, 0, texFormat, 589501e04c3fSmrg samples, width, height, depth); 5896af69d88dSmrg 5897af69d88dSmrg if (_mesa_is_proxy_texture(target)) { 5898af69d88dSmrg if (samplesOK && dimensionsOK && sizeOK) { 589901e04c3fSmrg _mesa_init_teximage_fields_ms(ctx, texImage, width, height, depth, 0, 590001e04c3fSmrg internalformat, texFormat, 590101e04c3fSmrg samples, fixedsamplelocations); 5902af69d88dSmrg } 5903af69d88dSmrg else { 5904af69d88dSmrg /* clear all image fields */ 5905af69d88dSmrg clear_teximage_fields(texImage); 5906af69d88dSmrg } 5907af69d88dSmrg } 5908af69d88dSmrg else { 5909af69d88dSmrg if (!dimensionsOK) { 5910af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 591101e04c3fSmrg "%s(invalid width=%d or height=%d)", func, width, height); 5912af69d88dSmrg return; 5913af69d88dSmrg } 5914af69d88dSmrg 5915af69d88dSmrg if (!sizeOK) { 591601e04c3fSmrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(texture too large)", func); 5917af69d88dSmrg return; 5918af69d88dSmrg } 5919af69d88dSmrg 5920af69d88dSmrg /* Check if texObj->Immutable is set */ 5921af69d88dSmrg if (texObj->Immutable) { 5922af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(immutable)", func); 5923af69d88dSmrg return; 5924af69d88dSmrg } 5925af69d88dSmrg 5926af69d88dSmrg ctx->Driver.FreeTextureImageBuffer(ctx, texImage); 5927af69d88dSmrg 592801e04c3fSmrg _mesa_init_teximage_fields_ms(ctx, texImage, width, height, depth, 0, 592901e04c3fSmrg internalformat, texFormat, 593001e04c3fSmrg samples, fixedsamplelocations); 5931af69d88dSmrg 5932af69d88dSmrg if (width > 0 && height > 0 && depth > 0) { 593301e04c3fSmrg if (memObj) { 593401e04c3fSmrg if (!ctx->Driver.SetTextureStorageForMemoryObject(ctx, texObj, 593501e04c3fSmrg memObj, 1, width, 593601e04c3fSmrg height, depth, 593701e04c3fSmrg offset)) { 593801e04c3fSmrg 593901e04c3fSmrg _mesa_init_teximage_fields(ctx, texImage, 0, 0, 0, 0, 594001e04c3fSmrg internalformat, texFormat); 594101e04c3fSmrg } 594201e04c3fSmrg } else { 594301e04c3fSmrg if (!ctx->Driver.AllocTextureStorage(ctx, texObj, 1, 594401e04c3fSmrg width, height, depth)) { 594501e04c3fSmrg /* tidy up the texture image state. strictly speaking, 594601e04c3fSmrg * we're allowed to just leave this in whatever state we 594701e04c3fSmrg * like, but being tidy is good. 594801e04c3fSmrg */ 594901e04c3fSmrg _mesa_init_teximage_fields(ctx, texImage, 0, 0, 0, 0, 595001e04c3fSmrg internalformat, texFormat); 595101e04c3fSmrg } 5952af69d88dSmrg } 5953af69d88dSmrg } 5954af69d88dSmrg 595501e04c3fSmrg texObj->Immutable |= immutable; 5956af69d88dSmrg 5957af69d88dSmrg if (immutable) { 5958af69d88dSmrg _mesa_set_texture_view_state(ctx, texObj, target, 1); 5959af69d88dSmrg } 5960af69d88dSmrg 5961af69d88dSmrg _mesa_update_fbo_texture(ctx, texObj, 0, 0); 5962af69d88dSmrg } 5963af69d88dSmrg} 5964af69d88dSmrg 5965af69d88dSmrg 5966af69d88dSmrgvoid GLAPIENTRY 5967af69d88dSmrg_mesa_TexImage2DMultisample(GLenum target, GLsizei samples, 5968af69d88dSmrg GLenum internalformat, GLsizei width, 5969af69d88dSmrg GLsizei height, GLboolean fixedsamplelocations) 5970af69d88dSmrg{ 597101e04c3fSmrg struct gl_texture_object *texObj; 597201e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 597301e04c3fSmrg 597401e04c3fSmrg texObj = _mesa_get_current_tex_object(ctx, target); 597501e04c3fSmrg if (!texObj) 597601e04c3fSmrg return; 597701e04c3fSmrg 597801e04c3fSmrg texture_image_multisample(ctx, 2, texObj, NULL, target, samples, 597901e04c3fSmrg internalformat, width, height, 1, 598001e04c3fSmrg fixedsamplelocations, GL_FALSE, 0, 598101e04c3fSmrg "glTexImage2DMultisample"); 5982af69d88dSmrg} 5983af69d88dSmrg 5984af69d88dSmrg 5985af69d88dSmrgvoid GLAPIENTRY 5986af69d88dSmrg_mesa_TexImage3DMultisample(GLenum target, GLsizei samples, 5987af69d88dSmrg GLenum internalformat, GLsizei width, 5988af69d88dSmrg GLsizei height, GLsizei depth, 5989af69d88dSmrg GLboolean fixedsamplelocations) 5990af69d88dSmrg{ 599101e04c3fSmrg struct gl_texture_object *texObj; 599201e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 599301e04c3fSmrg 599401e04c3fSmrg texObj = _mesa_get_current_tex_object(ctx, target); 599501e04c3fSmrg if (!texObj) 599601e04c3fSmrg return; 599701e04c3fSmrg 599801e04c3fSmrg texture_image_multisample(ctx, 3, texObj, NULL, target, samples, 599901e04c3fSmrg internalformat, width, height, depth, 600001e04c3fSmrg fixedsamplelocations, GL_FALSE, 0, 600101e04c3fSmrg "glTexImage3DMultisample"); 6002af69d88dSmrg} 6003af69d88dSmrg 600401e04c3fSmrgstatic bool 600501e04c3fSmrgvalid_texstorage_ms_parameters(GLsizei width, GLsizei height, GLsizei depth, 600601e04c3fSmrg unsigned dims) 600701e04c3fSmrg{ 600801e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 600901e04c3fSmrg 601001e04c3fSmrg if (!_mesa_valid_tex_storage_dim(width, height, depth)) { 601101e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, 601201e04c3fSmrg "glTexStorage%uDMultisample(width=%d,height=%d,depth=%d)", 601301e04c3fSmrg dims, width, height, depth); 601401e04c3fSmrg return false; 601501e04c3fSmrg } 601601e04c3fSmrg return true; 601701e04c3fSmrg} 6018af69d88dSmrg 6019af69d88dSmrgvoid GLAPIENTRY 6020af69d88dSmrg_mesa_TexStorage2DMultisample(GLenum target, GLsizei samples, 6021af69d88dSmrg GLenum internalformat, GLsizei width, 6022af69d88dSmrg GLsizei height, GLboolean fixedsamplelocations) 6023af69d88dSmrg{ 602401e04c3fSmrg struct gl_texture_object *texObj; 602501e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 602601e04c3fSmrg 602701e04c3fSmrg texObj = _mesa_get_current_tex_object(ctx, target); 602801e04c3fSmrg if (!texObj) 602901e04c3fSmrg return; 603001e04c3fSmrg 603101e04c3fSmrg if (!valid_texstorage_ms_parameters(width, height, 1, 2)) 603201e04c3fSmrg return; 603301e04c3fSmrg 603401e04c3fSmrg texture_image_multisample(ctx, 2, texObj, NULL, target, samples, 603501e04c3fSmrg internalformat, width, height, 1, 603601e04c3fSmrg fixedsamplelocations, GL_TRUE, 0, 603701e04c3fSmrg "glTexStorage2DMultisample"); 6038af69d88dSmrg} 6039af69d88dSmrg 6040af69d88dSmrgvoid GLAPIENTRY 6041af69d88dSmrg_mesa_TexStorage3DMultisample(GLenum target, GLsizei samples, 6042af69d88dSmrg GLenum internalformat, GLsizei width, 6043af69d88dSmrg GLsizei height, GLsizei depth, 6044af69d88dSmrg GLboolean fixedsamplelocations) 6045af69d88dSmrg{ 604601e04c3fSmrg struct gl_texture_object *texObj; 604701e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 604801e04c3fSmrg 604901e04c3fSmrg texObj = _mesa_get_current_tex_object(ctx, target); 605001e04c3fSmrg if (!texObj) 605101e04c3fSmrg return; 605201e04c3fSmrg 605301e04c3fSmrg if (!valid_texstorage_ms_parameters(width, height, depth, 3)) 605401e04c3fSmrg return; 605501e04c3fSmrg 605601e04c3fSmrg texture_image_multisample(ctx, 3, texObj, NULL, target, samples, 605701e04c3fSmrg internalformat, width, height, depth, 605801e04c3fSmrg fixedsamplelocations, GL_TRUE, 0, 605901e04c3fSmrg "glTexStorage3DMultisample"); 606001e04c3fSmrg} 606101e04c3fSmrg 606201e04c3fSmrgvoid GLAPIENTRY 606301e04c3fSmrg_mesa_TextureStorage2DMultisample(GLuint texture, GLsizei samples, 606401e04c3fSmrg GLenum internalformat, GLsizei width, 606501e04c3fSmrg GLsizei height, 606601e04c3fSmrg GLboolean fixedsamplelocations) 606701e04c3fSmrg{ 606801e04c3fSmrg struct gl_texture_object *texObj; 606901e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 607001e04c3fSmrg 607101e04c3fSmrg texObj = _mesa_lookup_texture_err(ctx, texture, 607201e04c3fSmrg "glTextureStorage2DMultisample"); 607301e04c3fSmrg if (!texObj) 607401e04c3fSmrg return; 607501e04c3fSmrg 607601e04c3fSmrg if (!valid_texstorage_ms_parameters(width, height, 1, 2)) 607701e04c3fSmrg return; 607801e04c3fSmrg 607901e04c3fSmrg texture_image_multisample(ctx, 2, texObj, NULL, texObj->Target, 608001e04c3fSmrg samples, internalformat, width, height, 1, 608101e04c3fSmrg fixedsamplelocations, GL_TRUE, 0, 608201e04c3fSmrg "glTextureStorage2DMultisample"); 608301e04c3fSmrg} 608401e04c3fSmrg 608501e04c3fSmrgvoid GLAPIENTRY 608601e04c3fSmrg_mesa_TextureStorage3DMultisample(GLuint texture, GLsizei samples, 608701e04c3fSmrg GLenum internalformat, GLsizei width, 608801e04c3fSmrg GLsizei height, GLsizei depth, 608901e04c3fSmrg GLboolean fixedsamplelocations) 609001e04c3fSmrg{ 609101e04c3fSmrg struct gl_texture_object *texObj; 609201e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 609301e04c3fSmrg 609401e04c3fSmrg /* Get the texture object by Name. */ 609501e04c3fSmrg texObj = _mesa_lookup_texture_err(ctx, texture, 609601e04c3fSmrg "glTextureStorage3DMultisample"); 609701e04c3fSmrg if (!texObj) 609801e04c3fSmrg return; 609901e04c3fSmrg 610001e04c3fSmrg if (!valid_texstorage_ms_parameters(width, height, depth, 3)) 610101e04c3fSmrg return; 610201e04c3fSmrg 610301e04c3fSmrg texture_image_multisample(ctx, 3, texObj, NULL, texObj->Target, samples, 610401e04c3fSmrg internalformat, width, height, depth, 610501e04c3fSmrg fixedsamplelocations, GL_TRUE, 0, 610601e04c3fSmrg "glTextureStorage3DMultisample"); 610701e04c3fSmrg} 610801e04c3fSmrg 610901e04c3fSmrgvoid 611001e04c3fSmrg_mesa_texture_storage_ms_memory(struct gl_context *ctx, GLuint dims, 611101e04c3fSmrg struct gl_texture_object *texObj, 611201e04c3fSmrg struct gl_memory_object *memObj, 611301e04c3fSmrg GLenum target, GLsizei samples, 611401e04c3fSmrg GLenum internalFormat, GLsizei width, 611501e04c3fSmrg GLsizei height, GLsizei depth, 611601e04c3fSmrg GLboolean fixedSampleLocations, 611701e04c3fSmrg GLuint64 offset, const char* func) 611801e04c3fSmrg{ 611901e04c3fSmrg assert(memObj); 612001e04c3fSmrg 612101e04c3fSmrg texture_image_multisample(ctx, dims, texObj, memObj, target, samples, 612201e04c3fSmrg internalFormat, width, height, depth, 612301e04c3fSmrg fixedSampleLocations, GL_TRUE, offset, 612401e04c3fSmrg func); 61253464ebd5Sriastradh} 6126