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" 417ec681f3Smrg 427117f1b4Smrg#include "macros.h" 4301e04c3fSmrg#include "mipmap.h" 44af69d88dSmrg#include "multisample.h" 457ec681f3Smrg#include "pixel.h" 46af69d88dSmrg#include "pixelstore.h" 477117f1b4Smrg#include "state.h" 487117f1b4Smrg#include "texcompress.h" 49af69d88dSmrg#include "texcompress_cpal.h" 507117f1b4Smrg#include "teximage.h" 51af69d88dSmrg#include "texobj.h" 527117f1b4Smrg#include "texstate.h" 53af69d88dSmrg#include "texstorage.h" 54af69d88dSmrg#include "textureview.h" 557117f1b4Smrg#include "mtypes.h" 56af69d88dSmrg#include "glformats.h" 57af69d88dSmrg#include "texstore.h" 5801e04c3fSmrg#include "pbo.h" 597117f1b4Smrg 607117f1b4Smrg 61c1f859d4Smrg/** 62c1f859d4Smrg * State changes which we care about for glCopyTex[Sub]Image() calls. 63c1f859d4Smrg * In particular, we care about pixel transfer state and buffer state 64c1f859d4Smrg * (such as glReadBuffer to make sure we read from the right renderbuffer). 65c1f859d4Smrg */ 663464ebd5Sriastradh#define NEW_COPY_TEX_STATE (_NEW_BUFFERS | _NEW_PIXEL) 67c1f859d4Smrg 687117f1b4Smrg/** 6901e04c3fSmrg * Returns a corresponding internal floating point format for a given base 7001e04c3fSmrg * format as specifed by OES_texture_float. In case of GL_FLOAT, the internal 7101e04c3fSmrg * format needs to be a 32 bit component and in case of GL_HALF_FLOAT_OES it 7201e04c3fSmrg * needs to be a 16 bit component. 737117f1b4Smrg * 7401e04c3fSmrg * For example, given base format GL_RGBA, type GL_FLOAT return GL_RGBA32F_ARB. 757117f1b4Smrg */ 7601e04c3fSmrgstatic GLenum 7701e04c3fSmrgadjust_for_oes_float_texture(const struct gl_context *ctx, 7801e04c3fSmrg GLenum format, GLenum type) 797117f1b4Smrg{ 8001e04c3fSmrg switch (type) { 8101e04c3fSmrg case GL_FLOAT: 8201e04c3fSmrg if (ctx->Extensions.OES_texture_float) { 8301e04c3fSmrg switch (format) { 8401e04c3fSmrg case GL_RGBA: 8501e04c3fSmrg return GL_RGBA32F; 8601e04c3fSmrg case GL_RGB: 8701e04c3fSmrg return GL_RGB32F; 8801e04c3fSmrg case GL_ALPHA: 8901e04c3fSmrg return GL_ALPHA32F_ARB; 9001e04c3fSmrg case GL_LUMINANCE: 9101e04c3fSmrg return GL_LUMINANCE32F_ARB; 9201e04c3fSmrg case GL_LUMINANCE_ALPHA: 9301e04c3fSmrg return GL_LUMINANCE_ALPHA32F_ARB; 943464ebd5Sriastradh default: 9501e04c3fSmrg break; 9601e04c3fSmrg } 977117f1b4Smrg } 9801e04c3fSmrg break; 997117f1b4Smrg 10001e04c3fSmrg case GL_HALF_FLOAT_OES: 10101e04c3fSmrg if (ctx->Extensions.OES_texture_half_float) { 10201e04c3fSmrg switch (format) { 10301e04c3fSmrg case GL_RGBA: 10401e04c3fSmrg return GL_RGBA16F; 10501e04c3fSmrg case GL_RGB: 10601e04c3fSmrg return GL_RGB16F; 10701e04c3fSmrg case GL_ALPHA: 10801e04c3fSmrg return GL_ALPHA16F_ARB; 10901e04c3fSmrg case GL_LUMINANCE: 11001e04c3fSmrg return GL_LUMINANCE16F_ARB; 11101e04c3fSmrg case GL_LUMINANCE_ALPHA: 11201e04c3fSmrg return GL_LUMINANCE_ALPHA16F_ARB; 1137117f1b4Smrg default: 11401e04c3fSmrg break; 11501e04c3fSmrg } 1167117f1b4Smrg } 11701e04c3fSmrg break; 1187117f1b4Smrg 1194a49301eSmrg default: 12001e04c3fSmrg break; 1217117f1b4Smrg } 122af69d88dSmrg 12301e04c3fSmrg return format; 12401e04c3fSmrg} 1257117f1b4Smrg 12601e04c3fSmrg/** 12701e04c3fSmrg * Returns a corresponding base format for a given internal floating point 12801e04c3fSmrg * format as specifed by OES_texture_float. 12901e04c3fSmrg */ 13001e04c3fSmrgstatic GLenum 13101e04c3fSmrgoes_float_internal_format(const struct gl_context *ctx, 13201e04c3fSmrg GLenum format, GLenum type) 13301e04c3fSmrg{ 13401e04c3fSmrg switch (type) { 13501e04c3fSmrg case GL_FLOAT: 13601e04c3fSmrg if (ctx->Extensions.OES_texture_float) { 13701e04c3fSmrg switch (format) { 13801e04c3fSmrg case GL_RGBA32F: 1397117f1b4Smrg return GL_RGBA; 14001e04c3fSmrg case GL_RGB32F: 1417117f1b4Smrg return GL_RGB; 1427117f1b4Smrg case GL_ALPHA32F_ARB: 1437117f1b4Smrg return GL_ALPHA; 1447117f1b4Smrg case GL_LUMINANCE32F_ARB: 1457117f1b4Smrg return GL_LUMINANCE; 1467117f1b4Smrg case GL_LUMINANCE_ALPHA32F_ARB: 1477117f1b4Smrg return GL_LUMINANCE_ALPHA; 1487117f1b4Smrg default: 14901e04c3fSmrg break; 15001e04c3fSmrg } 1517117f1b4Smrg } 15201e04c3fSmrg break; 1537117f1b4Smrg 15401e04c3fSmrg case GL_HALF_FLOAT_OES: 15501e04c3fSmrg if (ctx->Extensions.OES_texture_half_float) { 15601e04c3fSmrg switch (format) { 15701e04c3fSmrg case GL_RGBA16F: 1584a49301eSmrg return GL_RGBA; 15901e04c3fSmrg case GL_RGB16F: 16001e04c3fSmrg return GL_RGB; 16101e04c3fSmrg case GL_ALPHA16F_ARB: 1623464ebd5Sriastradh return GL_ALPHA; 16301e04c3fSmrg case GL_LUMINANCE16F_ARB: 1643464ebd5Sriastradh return GL_LUMINANCE; 16501e04c3fSmrg case GL_LUMINANCE_ALPHA16F_ARB: 1663464ebd5Sriastradh return GL_LUMINANCE_ALPHA; 1674a49301eSmrg default: 16801e04c3fSmrg break; 16901e04c3fSmrg } 1703464ebd5Sriastradh } 17101e04c3fSmrg break; 1723464ebd5Sriastradh } 17301e04c3fSmrg return format; 1747117f1b4Smrg} 1757117f1b4Smrg 1767117f1b4Smrg 1777117f1b4Smrg/** 178af69d88dSmrg * Install gl_texture_image in a gl_texture_object according to the target 179af69d88dSmrg * and level parameters. 180b9abf16eSmaya * 1817117f1b4Smrg * \param tObj texture object. 1827117f1b4Smrg * \param target texture target. 1837117f1b4Smrg * \param level image level. 1847117f1b4Smrg * \param texImage texture image. 1857117f1b4Smrg */ 186af69d88dSmrgstatic void 187af69d88dSmrgset_tex_image(struct gl_texture_object *tObj, 188af69d88dSmrg GLenum target, GLint level, 189af69d88dSmrg struct gl_texture_image *texImage) 1907117f1b4Smrg{ 1914a49301eSmrg const GLuint face = _mesa_tex_target_to_face(target); 1924a49301eSmrg 19301e04c3fSmrg assert(tObj); 19401e04c3fSmrg assert(texImage); 195af69d88dSmrg if (target == GL_TEXTURE_RECTANGLE_NV || target == GL_TEXTURE_EXTERNAL_OES) 196af69d88dSmrg assert(level == 0); 1974a49301eSmrg 1984a49301eSmrg tObj->Image[face][level] = texImage; 1994a49301eSmrg 2007117f1b4Smrg /* Set the 'back' pointer */ 2017117f1b4Smrg texImage->TexObject = tObj; 202af69d88dSmrg texImage->Level = level; 203af69d88dSmrg texImage->Face = face; 2047117f1b4Smrg} 2057117f1b4Smrg 2067117f1b4Smrg 2077117f1b4Smrg/** 208af69d88dSmrg * Free a gl_texture_image and associated data. 209af69d88dSmrg * This function is a fallback called via ctx->Driver.DeleteTextureImage(). 2107117f1b4Smrg * 2114a49301eSmrg * \param texImage texture image. 2127117f1b4Smrg * 2137117f1b4Smrg * Free the texture image structure and the associated image data. 2147117f1b4Smrg */ 2157117f1b4Smrgvoid 2163464ebd5Sriastradh_mesa_delete_texture_image(struct gl_context *ctx, 2173464ebd5Sriastradh struct gl_texture_image *texImage) 2187117f1b4Smrg{ 2197117f1b4Smrg /* Free texImage->Data and/or any other driver-specific texture 2207117f1b4Smrg * image storage. 2217117f1b4Smrg */ 22201e04c3fSmrg assert(ctx->Driver.FreeTextureImageBuffer); 223af69d88dSmrg ctx->Driver.FreeTextureImageBuffer( ctx, texImage ); 224cdc920a0Smrg free(texImage); 2257117f1b4Smrg} 2267117f1b4Smrg 2277117f1b4Smrg 2287117f1b4Smrg/** 2297117f1b4Smrg * Test if a target is a proxy target. 2307117f1b4Smrg * 2317117f1b4Smrg * \param target texture target. 2327117f1b4Smrg * 2337117f1b4Smrg * \return GL_TRUE if the target is a proxy target, GL_FALSE otherwise. 2347117f1b4Smrg */ 2357117f1b4SmrgGLboolean 2367117f1b4Smrg_mesa_is_proxy_texture(GLenum target) 2377117f1b4Smrg{ 238af69d88dSmrg unsigned i; 239af69d88dSmrg static const GLenum targets[] = { 240af69d88dSmrg GL_PROXY_TEXTURE_1D, 241af69d88dSmrg GL_PROXY_TEXTURE_2D, 242af69d88dSmrg GL_PROXY_TEXTURE_3D, 243af69d88dSmrg GL_PROXY_TEXTURE_CUBE_MAP, 244af69d88dSmrg GL_PROXY_TEXTURE_RECTANGLE, 245af69d88dSmrg GL_PROXY_TEXTURE_1D_ARRAY, 246af69d88dSmrg GL_PROXY_TEXTURE_2D_ARRAY, 247af69d88dSmrg GL_PROXY_TEXTURE_CUBE_MAP_ARRAY, 248af69d88dSmrg GL_PROXY_TEXTURE_2D_MULTISAMPLE, 249af69d88dSmrg GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY 250af69d88dSmrg }; 251af69d88dSmrg /* 252af69d88dSmrg * NUM_TEXTURE_TARGETS should match number of terms above, except there's no 253af69d88dSmrg * proxy for GL_TEXTURE_BUFFER and GL_TEXTURE_EXTERNAL_OES. 2543464ebd5Sriastradh */ 25501e04c3fSmrg STATIC_ASSERT(NUM_TEXTURE_TARGETS == ARRAY_SIZE(targets) + 2); 2564a49301eSmrg 25701e04c3fSmrg for (i = 0; i < ARRAY_SIZE(targets); ++i) 258af69d88dSmrg if (target == targets[i]) 259af69d88dSmrg return GL_TRUE; 260af69d88dSmrg return GL_FALSE; 2617117f1b4Smrg} 2627117f1b4Smrg 2637117f1b4Smrg 26401e04c3fSmrg/** 26501e04c3fSmrg * Test if a target is an array target. 26601e04c3fSmrg * 26701e04c3fSmrg * \param target texture target. 26801e04c3fSmrg * 26901e04c3fSmrg * \return true if the target is an array target, false otherwise. 27001e04c3fSmrg */ 27101e04c3fSmrgbool 27201e04c3fSmrg_mesa_is_array_texture(GLenum target) 27301e04c3fSmrg{ 27401e04c3fSmrg switch (target) { 27501e04c3fSmrg case GL_TEXTURE_1D_ARRAY: 27601e04c3fSmrg case GL_TEXTURE_2D_ARRAY: 27701e04c3fSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: 27801e04c3fSmrg case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 27901e04c3fSmrg return true; 28001e04c3fSmrg default: 28101e04c3fSmrg return false; 28201e04c3fSmrg }; 28301e04c3fSmrg} 28401e04c3fSmrg 28501e04c3fSmrg/** 28601e04c3fSmrg * Test if a target is a cube map. 28701e04c3fSmrg * 28801e04c3fSmrg * \param target texture target. 28901e04c3fSmrg * 29001e04c3fSmrg * \return true if the target is a cube map, false otherwise. 29101e04c3fSmrg */ 29201e04c3fSmrgbool 29301e04c3fSmrg_mesa_is_cube_map_texture(GLenum target) 29401e04c3fSmrg{ 29501e04c3fSmrg switch(target) { 29601e04c3fSmrg case GL_TEXTURE_CUBE_MAP: 29701e04c3fSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: 29801e04c3fSmrg return true; 29901e04c3fSmrg default: 30001e04c3fSmrg return false; 30101e04c3fSmrg } 30201e04c3fSmrg} 30301e04c3fSmrg 3047117f1b4Smrg/** 3053464ebd5Sriastradh * Return the proxy target which corresponds to the given texture target 3063464ebd5Sriastradh */ 3073464ebd5Sriastradhstatic GLenum 308af69d88dSmrgproxy_target(GLenum target) 3093464ebd5Sriastradh{ 3103464ebd5Sriastradh switch (target) { 3113464ebd5Sriastradh case GL_TEXTURE_1D: 3123464ebd5Sriastradh case GL_PROXY_TEXTURE_1D: 3133464ebd5Sriastradh return GL_PROXY_TEXTURE_1D; 3143464ebd5Sriastradh case GL_TEXTURE_2D: 3153464ebd5Sriastradh case GL_PROXY_TEXTURE_2D: 3163464ebd5Sriastradh return GL_PROXY_TEXTURE_2D; 3173464ebd5Sriastradh case GL_TEXTURE_3D: 3183464ebd5Sriastradh case GL_PROXY_TEXTURE_3D: 3193464ebd5Sriastradh return GL_PROXY_TEXTURE_3D; 32001e04c3fSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 32101e04c3fSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 32201e04c3fSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 32301e04c3fSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 32401e04c3fSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 32501e04c3fSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 32601e04c3fSmrg case GL_TEXTURE_CUBE_MAP: 32701e04c3fSmrg case GL_PROXY_TEXTURE_CUBE_MAP: 32801e04c3fSmrg return GL_PROXY_TEXTURE_CUBE_MAP; 3293464ebd5Sriastradh case GL_TEXTURE_RECTANGLE_NV: 3303464ebd5Sriastradh case GL_PROXY_TEXTURE_RECTANGLE_NV: 3313464ebd5Sriastradh return GL_PROXY_TEXTURE_RECTANGLE_NV; 3323464ebd5Sriastradh case GL_TEXTURE_1D_ARRAY_EXT: 3333464ebd5Sriastradh case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 3343464ebd5Sriastradh return GL_PROXY_TEXTURE_1D_ARRAY_EXT; 3353464ebd5Sriastradh case GL_TEXTURE_2D_ARRAY_EXT: 3363464ebd5Sriastradh case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 3373464ebd5Sriastradh return GL_PROXY_TEXTURE_2D_ARRAY_EXT; 338af69d88dSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: 339af69d88dSmrg case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY: 340af69d88dSmrg return GL_PROXY_TEXTURE_CUBE_MAP_ARRAY; 341af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE: 342af69d88dSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE: 343af69d88dSmrg return GL_PROXY_TEXTURE_2D_MULTISAMPLE; 344af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 345af69d88dSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY: 346af69d88dSmrg return GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY; 3473464ebd5Sriastradh default: 348af69d88dSmrg _mesa_problem(NULL, "unexpected target in proxy_target()"); 3493464ebd5Sriastradh return 0; 3503464ebd5Sriastradh } 3513464ebd5Sriastradh} 3523464ebd5Sriastradh 3533464ebd5Sriastradh 3547117f1b4Smrg 3554a49301eSmrg 3564a49301eSmrg/** 3574a49301eSmrg * Get a texture image pointer from a texture object, given a texture 3584a49301eSmrg * target and mipmap level. The target and level parameters should 3594a49301eSmrg * have already been error-checked. 3607117f1b4Smrg * 3614a49301eSmrg * \param texObj texture unit. 3627117f1b4Smrg * \param target texture target. 3637117f1b4Smrg * \param level image level. 3647117f1b4Smrg * 3654a49301eSmrg * \return pointer to the texture image structure, or NULL on failure. 3667117f1b4Smrg */ 3677117f1b4Smrgstruct gl_texture_image * 36801e04c3fSmrg_mesa_select_tex_image(const struct gl_texture_object *texObj, 36901e04c3fSmrg GLenum target, GLint level) 3707117f1b4Smrg{ 3714a49301eSmrg const GLuint face = _mesa_tex_target_to_face(target); 3727117f1b4Smrg 37301e04c3fSmrg assert(texObj); 37401e04c3fSmrg assert(level >= 0); 37501e04c3fSmrg assert(level < MAX_TEXTURE_LEVELS); 376c1f859d4Smrg 3774a49301eSmrg return texObj->Image[face][level]; 3787117f1b4Smrg} 3797117f1b4Smrg 3807117f1b4Smrg 3817117f1b4Smrg/** 3827117f1b4Smrg * Like _mesa_select_tex_image() but if the image doesn't exist, allocate 3837117f1b4Smrg * it and install it. Only return NULL if passed a bad parameter or run 3847117f1b4Smrg * out of memory. 3857117f1b4Smrg */ 3867117f1b4Smrgstruct gl_texture_image * 3873464ebd5Sriastradh_mesa_get_tex_image(struct gl_context *ctx, struct gl_texture_object *texObj, 3887117f1b4Smrg GLenum target, GLint level) 3897117f1b4Smrg{ 3907117f1b4Smrg struct gl_texture_image *texImage; 3917117f1b4Smrg 3927117f1b4Smrg if (!texObj) 3937117f1b4Smrg return NULL; 394af69d88dSmrg 39501e04c3fSmrg texImage = _mesa_select_tex_image(texObj, target, level); 3967117f1b4Smrg if (!texImage) { 3977117f1b4Smrg texImage = ctx->Driver.NewTextureImage(ctx); 3987117f1b4Smrg if (!texImage) { 3997117f1b4Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture image allocation"); 4007117f1b4Smrg return NULL; 4017117f1b4Smrg } 4027117f1b4Smrg 403af69d88dSmrg set_tex_image(texObj, target, level, texImage); 4047117f1b4Smrg } 4057117f1b4Smrg 4067117f1b4Smrg return texImage; 4077117f1b4Smrg} 4087117f1b4Smrg 4097117f1b4Smrg 4107117f1b4Smrg/** 4117117f1b4Smrg * Return pointer to the specified proxy texture image. 4127117f1b4Smrg * Note that proxy textures are per-context, not per-texture unit. 4137117f1b4Smrg * \return pointer to texture image or NULL if invalid target, invalid 4147117f1b4Smrg * level, or out of memory. 4157117f1b4Smrg */ 416af69d88dSmrgstatic struct gl_texture_image * 417af69d88dSmrgget_proxy_tex_image(struct gl_context *ctx, GLenum target, GLint level) 4187117f1b4Smrg{ 4197117f1b4Smrg struct gl_texture_image *texImage; 4204a49301eSmrg GLuint texIndex; 4217117f1b4Smrg 422af69d88dSmrg if (level < 0) 4237117f1b4Smrg return NULL; 4247117f1b4Smrg 4257117f1b4Smrg switch (target) { 4267117f1b4Smrg case GL_PROXY_TEXTURE_1D: 4274a49301eSmrg texIndex = TEXTURE_1D_INDEX; 4284a49301eSmrg break; 4297117f1b4Smrg case GL_PROXY_TEXTURE_2D: 4304a49301eSmrg texIndex = TEXTURE_2D_INDEX; 4314a49301eSmrg break; 4327117f1b4Smrg case GL_PROXY_TEXTURE_3D: 4334a49301eSmrg texIndex = TEXTURE_3D_INDEX; 4344a49301eSmrg break; 4357117f1b4Smrg case GL_PROXY_TEXTURE_CUBE_MAP: 4364a49301eSmrg texIndex = TEXTURE_CUBE_INDEX; 4374a49301eSmrg break; 4387117f1b4Smrg case GL_PROXY_TEXTURE_RECTANGLE_NV: 4397117f1b4Smrg if (level > 0) 4407117f1b4Smrg return NULL; 4414a49301eSmrg texIndex = TEXTURE_RECT_INDEX; 4424a49301eSmrg break; 443c1f859d4Smrg case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 4444a49301eSmrg texIndex = TEXTURE_1D_ARRAY_INDEX; 4454a49301eSmrg break; 446c1f859d4Smrg case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 4474a49301eSmrg texIndex = TEXTURE_2D_ARRAY_INDEX; 4484a49301eSmrg break; 449af69d88dSmrg case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY: 450af69d88dSmrg texIndex = TEXTURE_CUBE_ARRAY_INDEX; 451af69d88dSmrg break; 452af69d88dSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE: 453af69d88dSmrg texIndex = TEXTURE_2D_MULTISAMPLE_INDEX; 454af69d88dSmrg break; 455af69d88dSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY: 456af69d88dSmrg texIndex = TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX; 457af69d88dSmrg break; 4587117f1b4Smrg default: 4597117f1b4Smrg return NULL; 4607117f1b4Smrg } 4614a49301eSmrg 4624a49301eSmrg texImage = ctx->Texture.ProxyTex[texIndex]->Image[0][level]; 4634a49301eSmrg if (!texImage) { 4644a49301eSmrg texImage = ctx->Driver.NewTextureImage(ctx); 4654a49301eSmrg if (!texImage) { 4664a49301eSmrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation"); 4674a49301eSmrg return NULL; 4684a49301eSmrg } 4694a49301eSmrg ctx->Texture.ProxyTex[texIndex]->Image[0][level] = texImage; 4704a49301eSmrg /* Set the 'back' pointer */ 4714a49301eSmrg texImage->TexObject = ctx->Texture.ProxyTex[texIndex]; 4724a49301eSmrg } 4734a49301eSmrg return texImage; 4747117f1b4Smrg} 4757117f1b4Smrg 4767117f1b4Smrg 4777117f1b4Smrg/** 4787117f1b4Smrg * Get the maximum number of allowed mipmap levels. 4797117f1b4Smrg * 4807117f1b4Smrg * \param ctx GL context. 4817117f1b4Smrg * \param target texture target. 482af69d88dSmrg * 4837117f1b4Smrg * \return the maximum number of allowed mipmap levels for the given 4847117f1b4Smrg * texture target, or zero if passed a bad target. 4857117f1b4Smrg * 4867117f1b4Smrg * \sa gl_constants. 4877117f1b4Smrg */ 4887117f1b4SmrgGLint 4897ec681f3Smrg_mesa_max_texture_levels(const struct gl_context *ctx, GLenum target) 4907117f1b4Smrg{ 4917117f1b4Smrg switch (target) { 4927117f1b4Smrg case GL_TEXTURE_1D: 4937117f1b4Smrg case GL_PROXY_TEXTURE_1D: 4947117f1b4Smrg case GL_TEXTURE_2D: 4957117f1b4Smrg case GL_PROXY_TEXTURE_2D: 4967ec681f3Smrg return ffs(util_next_power_of_two(ctx->Const.MaxTextureSize)); 4977117f1b4Smrg case GL_TEXTURE_3D: 4987117f1b4Smrg case GL_PROXY_TEXTURE_3D: 4997117f1b4Smrg return ctx->Const.Max3DTextureLevels; 500af69d88dSmrg case GL_TEXTURE_CUBE_MAP: 50101e04c3fSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 50201e04c3fSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 50301e04c3fSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 50401e04c3fSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 50501e04c3fSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 50601e04c3fSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 50701e04c3fSmrg case GL_PROXY_TEXTURE_CUBE_MAP: 5084a49301eSmrg return ctx->Extensions.ARB_texture_cube_map 5094a49301eSmrg ? ctx->Const.MaxCubeTextureLevels : 0; 5107117f1b4Smrg case GL_TEXTURE_RECTANGLE_NV: 5117117f1b4Smrg case GL_PROXY_TEXTURE_RECTANGLE_NV: 5124a49301eSmrg return ctx->Extensions.NV_texture_rectangle ? 1 : 0; 5134a49301eSmrg case GL_TEXTURE_1D_ARRAY_EXT: 5144a49301eSmrg case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 5154a49301eSmrg case GL_TEXTURE_2D_ARRAY_EXT: 5164a49301eSmrg case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 517af69d88dSmrg return ctx->Extensions.EXT_texture_array 5187ec681f3Smrg ? ffs(util_next_power_of_two(ctx->Const.MaxTextureSize)) : 0; 519af69d88dSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: 520af69d88dSmrg case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY: 52101e04c3fSmrg return _mesa_has_texture_cube_map_array(ctx) 522af69d88dSmrg ? ctx->Const.MaxCubeTextureLevels : 0; 5233464ebd5Sriastradh case GL_TEXTURE_BUFFER: 52401e04c3fSmrg return (_mesa_has_ARB_texture_buffer_object(ctx) || 52501e04c3fSmrg _mesa_has_OES_texture_buffer(ctx)) ? 1 : 0; 526af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE: 527af69d88dSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE: 528af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 529af69d88dSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY: 53001e04c3fSmrg return (_mesa_is_desktop_gl(ctx) || _mesa_is_gles31(ctx)) 531af69d88dSmrg && ctx->Extensions.ARB_texture_multisample 532af69d88dSmrg ? 1 : 0; 533af69d88dSmrg case GL_TEXTURE_EXTERNAL_OES: 5347ec681f3Smrg return _mesa_has_OES_EGL_image_external(ctx) ? 1 : 0; 5357117f1b4Smrg default: 5367117f1b4Smrg return 0; /* bad target */ 5377117f1b4Smrg } 5387117f1b4Smrg} 5397117f1b4Smrg 5407117f1b4Smrg 5413464ebd5Sriastradh/** 5423464ebd5Sriastradh * Return number of dimensions per mipmap level for the given texture target. 5433464ebd5Sriastradh */ 5443464ebd5SriastradhGLint 5453464ebd5Sriastradh_mesa_get_texture_dimensions(GLenum target) 5463464ebd5Sriastradh{ 5473464ebd5Sriastradh switch (target) { 5483464ebd5Sriastradh case GL_TEXTURE_1D: 5493464ebd5Sriastradh case GL_PROXY_TEXTURE_1D: 5503464ebd5Sriastradh return 1; 5513464ebd5Sriastradh case GL_TEXTURE_2D: 5523464ebd5Sriastradh case GL_TEXTURE_RECTANGLE: 5533464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP: 5543464ebd5Sriastradh case GL_PROXY_TEXTURE_2D: 5553464ebd5Sriastradh case GL_PROXY_TEXTURE_RECTANGLE: 5563464ebd5Sriastradh case GL_PROXY_TEXTURE_CUBE_MAP: 5573464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 5583464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 5593464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 5603464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 5613464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 5623464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 5633464ebd5Sriastradh case GL_TEXTURE_1D_ARRAY: 5643464ebd5Sriastradh case GL_PROXY_TEXTURE_1D_ARRAY: 565af69d88dSmrg case GL_TEXTURE_EXTERNAL_OES: 566af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE: 567af69d88dSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE: 5683464ebd5Sriastradh return 2; 5693464ebd5Sriastradh case GL_TEXTURE_3D: 5703464ebd5Sriastradh case GL_PROXY_TEXTURE_3D: 5713464ebd5Sriastradh case GL_TEXTURE_2D_ARRAY: 5723464ebd5Sriastradh case GL_PROXY_TEXTURE_2D_ARRAY: 573af69d88dSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: 574af69d88dSmrg case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY: 575af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 576af69d88dSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY: 5773464ebd5Sriastradh return 3; 5783464ebd5Sriastradh case GL_TEXTURE_BUFFER: 5797ec681f3Smrg FALLTHROUGH; 5803464ebd5Sriastradh default: 5813464ebd5Sriastradh _mesa_problem(NULL, "invalid target 0x%x in get_texture_dimensions()", 5823464ebd5Sriastradh target); 5833464ebd5Sriastradh return 2; 5843464ebd5Sriastradh } 5853464ebd5Sriastradh} 5863464ebd5Sriastradh 5873464ebd5Sriastradh 588af69d88dSmrg/** 589af69d88dSmrg * Check if a texture target can have more than one layer. 590af69d88dSmrg */ 591af69d88dSmrgGLboolean 592af69d88dSmrg_mesa_tex_target_is_layered(GLenum target) 593af69d88dSmrg{ 594af69d88dSmrg switch (target) { 595af69d88dSmrg case GL_TEXTURE_1D: 596af69d88dSmrg case GL_PROXY_TEXTURE_1D: 597af69d88dSmrg case GL_TEXTURE_2D: 598af69d88dSmrg case GL_PROXY_TEXTURE_2D: 599af69d88dSmrg case GL_TEXTURE_RECTANGLE: 600af69d88dSmrg case GL_PROXY_TEXTURE_RECTANGLE: 601af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE: 602af69d88dSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE: 603af69d88dSmrg case GL_TEXTURE_BUFFER: 604af69d88dSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 605af69d88dSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 606af69d88dSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 607af69d88dSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 608af69d88dSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 609af69d88dSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 610af69d88dSmrg case GL_TEXTURE_EXTERNAL_OES: 611af69d88dSmrg return GL_FALSE; 612af69d88dSmrg 613af69d88dSmrg case GL_TEXTURE_3D: 614af69d88dSmrg case GL_PROXY_TEXTURE_3D: 615af69d88dSmrg case GL_TEXTURE_CUBE_MAP: 616af69d88dSmrg case GL_PROXY_TEXTURE_CUBE_MAP: 617af69d88dSmrg case GL_TEXTURE_1D_ARRAY: 618af69d88dSmrg case GL_PROXY_TEXTURE_1D_ARRAY: 619af69d88dSmrg case GL_TEXTURE_2D_ARRAY: 620af69d88dSmrg case GL_PROXY_TEXTURE_2D_ARRAY: 621af69d88dSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: 622af69d88dSmrg case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY: 623af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 624af69d88dSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY: 625af69d88dSmrg return GL_TRUE; 626af69d88dSmrg 627af69d88dSmrg default: 628af69d88dSmrg assert(!"Invalid texture target."); 629af69d88dSmrg return GL_FALSE; 630af69d88dSmrg } 631af69d88dSmrg} 632af69d88dSmrg 633af69d88dSmrg 634af69d88dSmrg/** 635af69d88dSmrg * Return the number of layers present in the given level of an array, 636af69d88dSmrg * cubemap or 3D texture. If the texture is not layered return zero. 637af69d88dSmrg */ 638af69d88dSmrgGLuint 639af69d88dSmrg_mesa_get_texture_layers(const struct gl_texture_object *texObj, GLint level) 640af69d88dSmrg{ 641af69d88dSmrg assert(level >= 0 && level < MAX_TEXTURE_LEVELS); 642af69d88dSmrg 643af69d88dSmrg switch (texObj->Target) { 644af69d88dSmrg case GL_TEXTURE_1D: 645af69d88dSmrg case GL_TEXTURE_2D: 646af69d88dSmrg case GL_TEXTURE_RECTANGLE: 647af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE: 648af69d88dSmrg case GL_TEXTURE_BUFFER: 649af69d88dSmrg case GL_TEXTURE_EXTERNAL_OES: 650af69d88dSmrg return 0; 651af69d88dSmrg 652af69d88dSmrg case GL_TEXTURE_CUBE_MAP: 653af69d88dSmrg return 6; 654af69d88dSmrg 655af69d88dSmrg case GL_TEXTURE_1D_ARRAY: { 656af69d88dSmrg struct gl_texture_image *img = texObj->Image[0][level]; 657af69d88dSmrg return img ? img->Height : 0; 658af69d88dSmrg } 659af69d88dSmrg 660af69d88dSmrg case GL_TEXTURE_3D: 661af69d88dSmrg case GL_TEXTURE_2D_ARRAY: 662af69d88dSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: 663af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: { 664af69d88dSmrg struct gl_texture_image *img = texObj->Image[0][level]; 665af69d88dSmrg return img ? img->Depth : 0; 666af69d88dSmrg } 667af69d88dSmrg 668af69d88dSmrg default: 669af69d88dSmrg assert(!"Invalid texture target."); 670af69d88dSmrg return 0; 671af69d88dSmrg } 672af69d88dSmrg} 673af69d88dSmrg 674af69d88dSmrg 675af69d88dSmrg/** 676af69d88dSmrg * Return the maximum number of mipmap levels for the given target 677af69d88dSmrg * and the dimensions. 678af69d88dSmrg * The dimensions are expected not to include the border. 679af69d88dSmrg */ 680af69d88dSmrgGLsizei 681af69d88dSmrg_mesa_get_tex_max_num_levels(GLenum target, GLsizei width, GLsizei height, 682af69d88dSmrg GLsizei depth) 683af69d88dSmrg{ 684af69d88dSmrg GLsizei size; 685af69d88dSmrg 686af69d88dSmrg switch (target) { 687af69d88dSmrg case GL_TEXTURE_1D: 688af69d88dSmrg case GL_TEXTURE_1D_ARRAY: 689af69d88dSmrg case GL_PROXY_TEXTURE_1D: 690af69d88dSmrg case GL_PROXY_TEXTURE_1D_ARRAY: 691af69d88dSmrg size = width; 692af69d88dSmrg break; 693af69d88dSmrg case GL_TEXTURE_CUBE_MAP: 694af69d88dSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: 695af69d88dSmrg case GL_PROXY_TEXTURE_CUBE_MAP: 696af69d88dSmrg case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY: 697af69d88dSmrg size = width; 698af69d88dSmrg break; 699af69d88dSmrg case GL_TEXTURE_2D: 700af69d88dSmrg case GL_TEXTURE_2D_ARRAY: 701af69d88dSmrg case GL_PROXY_TEXTURE_2D: 702af69d88dSmrg case GL_PROXY_TEXTURE_2D_ARRAY: 703af69d88dSmrg size = MAX2(width, height); 704af69d88dSmrg break; 705af69d88dSmrg case GL_TEXTURE_3D: 706af69d88dSmrg case GL_PROXY_TEXTURE_3D: 707af69d88dSmrg size = MAX3(width, height, depth); 708af69d88dSmrg break; 709af69d88dSmrg case GL_TEXTURE_RECTANGLE: 710af69d88dSmrg case GL_TEXTURE_EXTERNAL_OES: 711af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE: 712af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 713af69d88dSmrg case GL_PROXY_TEXTURE_RECTANGLE: 714af69d88dSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE: 715af69d88dSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY: 716af69d88dSmrg return 1; 717af69d88dSmrg default: 718af69d88dSmrg assert(0); 719af69d88dSmrg return 1; 720af69d88dSmrg } 721af69d88dSmrg 7227ec681f3Smrg return util_logbase2(size) + 1; 723af69d88dSmrg} 7243464ebd5Sriastradh 7257117f1b4Smrg 7267117f1b4Smrg#if 000 /* not used anymore */ 7277117f1b4Smrg/* 7287117f1b4Smrg * glTexImage[123]D can accept a NULL image pointer. In this case we 7297117f1b4Smrg * create a texture image with unspecified image contents per the OpenGL 7307117f1b4Smrg * spec. 7317117f1b4Smrg */ 7327117f1b4Smrgstatic GLubyte * 7337117f1b4Smrgmake_null_texture(GLint width, GLint height, GLint depth, GLenum format) 7347117f1b4Smrg{ 7357117f1b4Smrg const GLint components = _mesa_components_in_format(format); 7367117f1b4Smrg const GLint numPixels = width * height * depth; 737af69d88dSmrg GLubyte *data = (GLubyte *) malloc(numPixels * components * sizeof(GLubyte)); 7387117f1b4Smrg 7397117f1b4Smrg#ifdef DEBUG 7407117f1b4Smrg /* 7417117f1b4Smrg * Let's see if anyone finds this. If glTexImage2D() is called with 7427117f1b4Smrg * a NULL image pointer then load the texture image with something 7437117f1b4Smrg * interesting instead of leaving it indeterminate. 7447117f1b4Smrg */ 7457117f1b4Smrg if (data) { 7467117f1b4Smrg static const char message[8][32] = { 7477117f1b4Smrg " X X XXXXX XXX X ", 7487117f1b4Smrg " XX XX X X X X X ", 7497117f1b4Smrg " X X X X X X X ", 7507117f1b4Smrg " X X XXXX XXX XXXXX ", 7517117f1b4Smrg " X X X X X X ", 7527117f1b4Smrg " X X X X X X X ", 7537117f1b4Smrg " X X XXXXX XXX X X ", 7547117f1b4Smrg " " 7557117f1b4Smrg }; 7567117f1b4Smrg 7577117f1b4Smrg GLubyte *imgPtr = data; 7587117f1b4Smrg GLint h, i, j, k; 7597117f1b4Smrg for (h = 0; h < depth; h++) { 7607117f1b4Smrg for (i = 0; i < height; i++) { 7617117f1b4Smrg GLint srcRow = 7 - (i % 8); 7627117f1b4Smrg for (j = 0; j < width; j++) { 7637117f1b4Smrg GLint srcCol = j % 32; 7647117f1b4Smrg GLubyte texel = (message[srcRow][srcCol]=='X') ? 255 : 70; 7657117f1b4Smrg for (k = 0; k < components; k++) { 7667117f1b4Smrg *imgPtr++ = texel; 7677117f1b4Smrg } 7687117f1b4Smrg } 7697117f1b4Smrg } 7707117f1b4Smrg } 7717117f1b4Smrg } 7727117f1b4Smrg#endif 7737117f1b4Smrg 7747117f1b4Smrg return data; 7757117f1b4Smrg} 7767117f1b4Smrg#endif 7777117f1b4Smrg 7787117f1b4Smrg 7797117f1b4Smrg 7807117f1b4Smrg/** 781af69d88dSmrg * Set the size and format-related fields of a gl_texture_image struct 782af69d88dSmrg * to zero. This is used when a proxy texture test fails. 7837117f1b4Smrg */ 7847117f1b4Smrgstatic void 7857117f1b4Smrgclear_teximage_fields(struct gl_texture_image *img) 7867117f1b4Smrg{ 78701e04c3fSmrg assert(img); 7887117f1b4Smrg img->_BaseFormat = 0; 7897117f1b4Smrg img->InternalFormat = 0; 7907117f1b4Smrg img->Border = 0; 7917117f1b4Smrg img->Width = 0; 7927117f1b4Smrg img->Height = 0; 7937117f1b4Smrg img->Depth = 0; 7947117f1b4Smrg img->Width2 = 0; 7957117f1b4Smrg img->Height2 = 0; 7967117f1b4Smrg img->Depth2 = 0; 7977117f1b4Smrg img->WidthLog2 = 0; 7987117f1b4Smrg img->HeightLog2 = 0; 7997117f1b4Smrg img->DepthLog2 = 0; 8004a49301eSmrg img->TexFormat = MESA_FORMAT_NONE; 801af69d88dSmrg img->NumSamples = 0; 802af69d88dSmrg img->FixedSampleLocations = GL_TRUE; 8037117f1b4Smrg} 8047117f1b4Smrg 8057117f1b4Smrg 8067117f1b4Smrg/** 8077117f1b4Smrg * Initialize basic fields of the gl_texture_image struct. 8087117f1b4Smrg * 8097117f1b4Smrg * \param ctx GL context. 8107117f1b4Smrg * \param img texture image structure to be initialized. 8117117f1b4Smrg * \param width image width. 8127117f1b4Smrg * \param height image height. 8137117f1b4Smrg * \param depth image depth. 8147117f1b4Smrg * \param border image border. 8157117f1b4Smrg * \param internalFormat internal format. 8163464ebd5Sriastradh * \param format the actual hardware format (one of MESA_FORMAT_*) 817af69d88dSmrg * \param numSamples number of samples per texel, or zero for non-MS. 818af69d88dSmrg * \param fixedSampleLocations are sample locations fixed? 8197117f1b4Smrg * 8207117f1b4Smrg * Fills in the fields of \p img with the given information. 8217117f1b4Smrg * Note: width, height and depth include the border. 8227117f1b4Smrg */ 82301e04c3fSmrgvoid 82401e04c3fSmrg_mesa_init_teximage_fields_ms(struct gl_context *ctx, 825af69d88dSmrg struct gl_texture_image *img, 826af69d88dSmrg GLsizei width, GLsizei height, GLsizei depth, 827af69d88dSmrg GLint border, GLenum internalFormat, 828af69d88dSmrg mesa_format format, 829af69d88dSmrg GLuint numSamples, GLboolean fixedSampleLocations) 8307117f1b4Smrg{ 83101e04c3fSmrg const GLint base_format =_mesa_base_tex_format(ctx, internalFormat); 832af69d88dSmrg GLenum target; 83301e04c3fSmrg assert(img); 83401e04c3fSmrg assert(width >= 0); 83501e04c3fSmrg assert(height >= 0); 83601e04c3fSmrg assert(depth >= 0); 8377117f1b4Smrg 838af69d88dSmrg target = img->TexObject->Target; 83901e04c3fSmrg assert(base_format != -1); 84001e04c3fSmrg img->_BaseFormat = (GLenum16)base_format; 8417117f1b4Smrg img->InternalFormat = internalFormat; 8427117f1b4Smrg img->Border = border; 8437117f1b4Smrg img->Width = width; 8447117f1b4Smrg img->Height = height; 8457117f1b4Smrg img->Depth = depth; 8464a49301eSmrg 8477117f1b4Smrg img->Width2 = width - 2 * border; /* == 1 << img->WidthLog2; */ 8487ec681f3Smrg img->WidthLog2 = util_logbase2(img->Width2); 8494a49301eSmrg 850af69d88dSmrg switch(target) { 851af69d88dSmrg case GL_TEXTURE_1D: 852af69d88dSmrg case GL_TEXTURE_BUFFER: 853af69d88dSmrg case GL_PROXY_TEXTURE_1D: 854af69d88dSmrg if (height == 0) 855af69d88dSmrg img->Height2 = 0; 856af69d88dSmrg else 857af69d88dSmrg img->Height2 = 1; 8587117f1b4Smrg img->HeightLog2 = 0; 859af69d88dSmrg if (depth == 0) 860af69d88dSmrg img->Depth2 = 0; 861af69d88dSmrg else 862af69d88dSmrg img->Depth2 = 1; 863af69d88dSmrg img->DepthLog2 = 0; 864af69d88dSmrg break; 865af69d88dSmrg case GL_TEXTURE_1D_ARRAY: 866af69d88dSmrg case GL_PROXY_TEXTURE_1D_ARRAY: 867af69d88dSmrg img->Height2 = height; /* no border */ 868af69d88dSmrg img->HeightLog2 = 0; /* not used */ 869af69d88dSmrg if (depth == 0) 870af69d88dSmrg img->Depth2 = 0; 871af69d88dSmrg else 872af69d88dSmrg img->Depth2 = 1; 873af69d88dSmrg img->DepthLog2 = 0; 874af69d88dSmrg break; 875af69d88dSmrg case GL_TEXTURE_2D: 876af69d88dSmrg case GL_TEXTURE_RECTANGLE: 877af69d88dSmrg case GL_TEXTURE_CUBE_MAP: 878af69d88dSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 879af69d88dSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 880af69d88dSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 881af69d88dSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 882af69d88dSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 883af69d88dSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 884af69d88dSmrg case GL_TEXTURE_EXTERNAL_OES: 885af69d88dSmrg case GL_PROXY_TEXTURE_2D: 886af69d88dSmrg case GL_PROXY_TEXTURE_RECTANGLE: 887af69d88dSmrg case GL_PROXY_TEXTURE_CUBE_MAP: 888af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE: 889af69d88dSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE: 8904a49301eSmrg img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */ 8917ec681f3Smrg img->HeightLog2 = util_logbase2(img->Height2); 892af69d88dSmrg if (depth == 0) 893af69d88dSmrg img->Depth2 = 0; 894af69d88dSmrg else 895af69d88dSmrg img->Depth2 = 1; 8967117f1b4Smrg img->DepthLog2 = 0; 897af69d88dSmrg break; 898af69d88dSmrg case GL_TEXTURE_2D_ARRAY: 899af69d88dSmrg case GL_PROXY_TEXTURE_2D_ARRAY: 900af69d88dSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: 901af69d88dSmrg case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY: 902af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 903af69d88dSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY: 904af69d88dSmrg img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */ 9057ec681f3Smrg img->HeightLog2 = util_logbase2(img->Height2); 906af69d88dSmrg img->Depth2 = depth; /* no border */ 907af69d88dSmrg img->DepthLog2 = 0; /* not used */ 908af69d88dSmrg break; 909af69d88dSmrg case GL_TEXTURE_3D: 910af69d88dSmrg case GL_PROXY_TEXTURE_3D: 911af69d88dSmrg img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */ 9127ec681f3Smrg img->HeightLog2 = util_logbase2(img->Height2); 913af69d88dSmrg img->Depth2 = depth - 2 * border; /* == 1 << img->DepthLog2; */ 9147ec681f3Smrg img->DepthLog2 = util_logbase2(img->Depth2); 915af69d88dSmrg break; 916af69d88dSmrg default: 917af69d88dSmrg _mesa_problem(NULL, "invalid target 0x%x in _mesa_init_teximage_fields()", 918af69d88dSmrg target); 9197117f1b4Smrg } 9204a49301eSmrg 921af69d88dSmrg img->MaxNumLevels = 922af69d88dSmrg _mesa_get_tex_max_num_levels(target, 923af69d88dSmrg img->Width2, img->Height2, img->Depth2); 9243464ebd5Sriastradh img->TexFormat = format; 925af69d88dSmrg img->NumSamples = numSamples; 926af69d88dSmrg img->FixedSampleLocations = fixedSampleLocations; 927af69d88dSmrg} 9283464ebd5Sriastradh 9293464ebd5Sriastradh 930af69d88dSmrgvoid 931af69d88dSmrg_mesa_init_teximage_fields(struct gl_context *ctx, 932af69d88dSmrg struct gl_texture_image *img, 933af69d88dSmrg GLsizei width, GLsizei height, GLsizei depth, 934af69d88dSmrg GLint border, GLenum internalFormat, 935af69d88dSmrg mesa_format format) 936af69d88dSmrg{ 93701e04c3fSmrg _mesa_init_teximage_fields_ms(ctx, img, width, height, depth, border, 93801e04c3fSmrg internalFormat, format, 0, GL_TRUE); 9394a49301eSmrg} 9404a49301eSmrg 9414a49301eSmrg 9424a49301eSmrg/** 9434a49301eSmrg * Free and clear fields of the gl_texture_image struct. 9444a49301eSmrg * 9454a49301eSmrg * \param ctx GL context. 9464a49301eSmrg * \param texImage texture image structure to be cleared. 9474a49301eSmrg * 9484a49301eSmrg * After the call, \p texImage will have no data associated with it. Its 9494a49301eSmrg * fields are cleared so that its parent object will test incomplete. 9504a49301eSmrg */ 9514a49301eSmrgvoid 9523464ebd5Sriastradh_mesa_clear_texture_image(struct gl_context *ctx, 9533464ebd5Sriastradh struct gl_texture_image *texImage) 9544a49301eSmrg{ 955af69d88dSmrg ctx->Driver.FreeTextureImageBuffer(ctx, texImage); 9564a49301eSmrg clear_teximage_fields(texImage); 9577117f1b4Smrg} 9587117f1b4Smrg 9597117f1b4Smrg 9607117f1b4Smrg/** 961af69d88dSmrg * Check the width, height, depth and border of a texture image are legal. 962af69d88dSmrg * Used by all the glTexImage, glCompressedTexImage and glCopyTexImage 963af69d88dSmrg * functions. 964af69d88dSmrg * The target and level parameters will have already been validated. 965af69d88dSmrg * \return GL_TRUE if size is OK, GL_FALSE otherwise. 9667117f1b4Smrg */ 9677117f1b4SmrgGLboolean 968af69d88dSmrg_mesa_legal_texture_dimensions(struct gl_context *ctx, GLenum target, 969af69d88dSmrg GLint level, GLint width, GLint height, 970af69d88dSmrg GLint depth, GLint border) 9717117f1b4Smrg{ 9727117f1b4Smrg GLint maxSize; 9737117f1b4Smrg 9747117f1b4Smrg switch (target) { 975af69d88dSmrg case GL_TEXTURE_1D: 9767117f1b4Smrg case GL_PROXY_TEXTURE_1D: 9777ec681f3Smrg maxSize = ctx->Const.MaxTextureSize >> level; 978af69d88dSmrg if (width < 2 * border || width > 2 * border + maxSize) 9797117f1b4Smrg return GL_FALSE; 9803464ebd5Sriastradh if (!ctx->Extensions.ARB_texture_non_power_of_two) { 9817ec681f3Smrg if (width > 0 && !util_is_power_of_two_nonzero(width - 2 * border)) 9823464ebd5Sriastradh return GL_FALSE; 9837117f1b4Smrg } 9847117f1b4Smrg return GL_TRUE; 9853464ebd5Sriastradh 986af69d88dSmrg case GL_TEXTURE_2D: 9877117f1b4Smrg case GL_PROXY_TEXTURE_2D: 988af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE: 989af69d88dSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE: 9907ec681f3Smrg maxSize = ctx->Const.MaxTextureSize >> level; 991af69d88dSmrg if (width < 2 * border || width > 2 * border + maxSize) 9923464ebd5Sriastradh return GL_FALSE; 993af69d88dSmrg if (height < 2 * border || height > 2 * border + maxSize) 9947117f1b4Smrg return GL_FALSE; 9953464ebd5Sriastradh if (!ctx->Extensions.ARB_texture_non_power_of_two) { 9967ec681f3Smrg if (width > 0 && !util_is_power_of_two_nonzero(width - 2 * border)) 9973464ebd5Sriastradh return GL_FALSE; 9987ec681f3Smrg if (height > 0 && !util_is_power_of_two_nonzero(height - 2 * border)) 9993464ebd5Sriastradh return GL_FALSE; 10007117f1b4Smrg } 10017117f1b4Smrg return GL_TRUE; 10023464ebd5Sriastradh 1003af69d88dSmrg case GL_TEXTURE_3D: 10047117f1b4Smrg case GL_PROXY_TEXTURE_3D: 10057117f1b4Smrg maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1); 1006af69d88dSmrg maxSize >>= level; 1007af69d88dSmrg if (width < 2 * border || width > 2 * border + maxSize) 10083464ebd5Sriastradh return GL_FALSE; 1009af69d88dSmrg if (height < 2 * border || height > 2 * border + maxSize) 10107117f1b4Smrg return GL_FALSE; 1011af69d88dSmrg if (depth < 2 * border || depth > 2 * border + maxSize) 10123464ebd5Sriastradh return GL_FALSE; 10133464ebd5Sriastradh if (!ctx->Extensions.ARB_texture_non_power_of_two) { 10147ec681f3Smrg if (width > 0 && !util_is_power_of_two_nonzero(width - 2 * border)) 10153464ebd5Sriastradh return GL_FALSE; 10167ec681f3Smrg if (height > 0 && !util_is_power_of_two_nonzero(height - 2 * border)) 10173464ebd5Sriastradh return GL_FALSE; 10187ec681f3Smrg if (depth > 0 && !util_is_power_of_two_nonzero(depth - 2 * border)) 10193464ebd5Sriastradh return GL_FALSE; 10207117f1b4Smrg } 10217117f1b4Smrg return GL_TRUE; 10223464ebd5Sriastradh 1023af69d88dSmrg case GL_TEXTURE_RECTANGLE_NV: 10247117f1b4Smrg case GL_PROXY_TEXTURE_RECTANGLE_NV: 1025af69d88dSmrg if (level != 0) 1026af69d88dSmrg return GL_FALSE; 10273464ebd5Sriastradh maxSize = ctx->Const.MaxTextureRectSize; 10283464ebd5Sriastradh if (width < 0 || width > maxSize) 10293464ebd5Sriastradh return GL_FALSE; 10303464ebd5Sriastradh if (height < 0 || height > maxSize) 10313464ebd5Sriastradh return GL_FALSE; 10327117f1b4Smrg return GL_TRUE; 10333464ebd5Sriastradh 1034af69d88dSmrg case GL_TEXTURE_CUBE_MAP: 1035af69d88dSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 1036af69d88dSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 1037af69d88dSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 1038af69d88dSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 1039af69d88dSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 1040af69d88dSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 104101e04c3fSmrg case GL_PROXY_TEXTURE_CUBE_MAP: 10427117f1b4Smrg maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1); 1043af69d88dSmrg maxSize >>= level; 1044af69d88dSmrg if (width != height) 10453464ebd5Sriastradh return GL_FALSE; 1046af69d88dSmrg if (width < 2 * border || width > 2 * border + maxSize) 10477117f1b4Smrg return GL_FALSE; 1048af69d88dSmrg if (height < 2 * border || height > 2 * border + maxSize) 10493464ebd5Sriastradh return GL_FALSE; 10503464ebd5Sriastradh if (!ctx->Extensions.ARB_texture_non_power_of_two) { 10517ec681f3Smrg if (width > 0 && !util_is_power_of_two_nonzero(width - 2 * border)) 10523464ebd5Sriastradh return GL_FALSE; 10537ec681f3Smrg if (height > 0 && !util_is_power_of_two_nonzero(height - 2 * border)) 10543464ebd5Sriastradh return GL_FALSE; 10557117f1b4Smrg } 10567117f1b4Smrg return GL_TRUE; 10573464ebd5Sriastradh 1058af69d88dSmrg case GL_TEXTURE_1D_ARRAY_EXT: 1059c1f859d4Smrg case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 10607ec681f3Smrg maxSize = ctx->Const.MaxTextureSize >> level; 1061af69d88dSmrg if (width < 2 * border || width > 2 * border + maxSize) 10623464ebd5Sriastradh return GL_FALSE; 1063af69d88dSmrg if (height < 0 || height > ctx->Const.MaxArrayTextureLayers) 1064c1f859d4Smrg return GL_FALSE; 10653464ebd5Sriastradh if (!ctx->Extensions.ARB_texture_non_power_of_two) { 10667ec681f3Smrg if (width > 0 && !util_is_power_of_two_nonzero(width - 2 * border)) 10673464ebd5Sriastradh return GL_FALSE; 1068c1f859d4Smrg } 1069c1f859d4Smrg return GL_TRUE; 10703464ebd5Sriastradh 1071af69d88dSmrg case GL_TEXTURE_2D_ARRAY_EXT: 1072c1f859d4Smrg case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 1073af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 1074af69d88dSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY: 10757ec681f3Smrg maxSize = ctx->Const.MaxTextureSize >> level; 1076af69d88dSmrg if (width < 2 * border || width > 2 * border + maxSize) 1077c1f859d4Smrg return GL_FALSE; 1078af69d88dSmrg if (height < 2 * border || height > 2 * border + maxSize) 10793464ebd5Sriastradh return GL_FALSE; 1080af69d88dSmrg if (depth < 0 || depth > ctx->Const.MaxArrayTextureLayers) 1081c1f859d4Smrg return GL_FALSE; 10823464ebd5Sriastradh if (!ctx->Extensions.ARB_texture_non_power_of_two) { 10837ec681f3Smrg if (width > 0 && !util_is_power_of_two_nonzero(width - 2 * border)) 10843464ebd5Sriastradh return GL_FALSE; 10857ec681f3Smrg if (height > 0 && !util_is_power_of_two_nonzero(height - 2 * border)) 10863464ebd5Sriastradh return GL_FALSE; 1087c1f859d4Smrg } 1088c1f859d4Smrg return GL_TRUE; 10893464ebd5Sriastradh 1090af69d88dSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: 1091af69d88dSmrg case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY: 1092af69d88dSmrg maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1); 1093af69d88dSmrg if (width < 2 * border || width > 2 * border + maxSize) 1094af69d88dSmrg return GL_FALSE; 1095af69d88dSmrg if (height < 2 * border || height > 2 * border + maxSize) 1096af69d88dSmrg return GL_FALSE; 1097af69d88dSmrg if (depth < 0 || depth > ctx->Const.MaxArrayTextureLayers || depth % 6) 1098af69d88dSmrg return GL_FALSE; 1099af69d88dSmrg if (width != height) 1100af69d88dSmrg return GL_FALSE; 1101af69d88dSmrg if (level >= ctx->Const.MaxCubeTextureLevels) 1102af69d88dSmrg return GL_FALSE; 1103af69d88dSmrg if (!ctx->Extensions.ARB_texture_non_power_of_two) { 11047ec681f3Smrg if (width > 0 && !util_is_power_of_two_nonzero(width - 2 * border)) 1105af69d88dSmrg return GL_FALSE; 11067ec681f3Smrg if (height > 0 && !util_is_power_of_two_nonzero(height - 2 * border)) 1107af69d88dSmrg return GL_FALSE; 1108af69d88dSmrg } 1109af69d88dSmrg return GL_TRUE; 11107117f1b4Smrg default: 1111af69d88dSmrg _mesa_problem(ctx, "Invalid target in _mesa_legal_texture_dimensions()"); 11127117f1b4Smrg return GL_FALSE; 11137117f1b4Smrg } 11147117f1b4Smrg} 11157117f1b4Smrg 111601e04c3fSmrgstatic bool 111701e04c3fSmrgerror_check_subtexture_negative_dimensions(struct gl_context *ctx, 111801e04c3fSmrg GLuint dims, 111901e04c3fSmrg GLsizei subWidth, 112001e04c3fSmrg GLsizei subHeight, 112101e04c3fSmrg GLsizei subDepth, 112201e04c3fSmrg const char *func) 112301e04c3fSmrg{ 112401e04c3fSmrg /* Check size */ 112501e04c3fSmrg if (subWidth < 0) { 112601e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(width=%d)", func, subWidth); 112701e04c3fSmrg return true; 112801e04c3fSmrg } 112901e04c3fSmrg 113001e04c3fSmrg if (dims > 1 && subHeight < 0) { 113101e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(height=%d)", func, subHeight); 113201e04c3fSmrg return true; 113301e04c3fSmrg } 113401e04c3fSmrg 113501e04c3fSmrg if (dims > 2 && subDepth < 0) { 113601e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(depth=%d)", func, subDepth); 113701e04c3fSmrg return true; 113801e04c3fSmrg } 113901e04c3fSmrg 114001e04c3fSmrg return false; 114101e04c3fSmrg} 11427117f1b4Smrg 11437117f1b4Smrg/** 1144af69d88dSmrg * Do error checking of xoffset, yoffset, zoffset, width, height and depth 1145af69d88dSmrg * for glTexSubImage, glCopyTexSubImage and glCompressedTexSubImage. 1146af69d88dSmrg * \param destImage the destination texture image. 1147af69d88dSmrg * \return GL_TRUE if error found, GL_FALSE otherwise. 11487117f1b4Smrg */ 11497117f1b4Smrgstatic GLboolean 115001e04c3fSmrgerror_check_subtexture_dimensions(struct gl_context *ctx, GLuint dims, 1151af69d88dSmrg const struct gl_texture_image *destImage, 1152af69d88dSmrg GLint xoffset, GLint yoffset, GLint zoffset, 1153af69d88dSmrg GLsizei subWidth, GLsizei subHeight, 115401e04c3fSmrg GLsizei subDepth, const char *func) 1155af69d88dSmrg{ 1156af69d88dSmrg const GLenum target = destImage->TexObject->Target; 115701e04c3fSmrg GLuint bw, bh, bd; 1158af69d88dSmrg 1159af69d88dSmrg /* check xoffset and width */ 1160af69d88dSmrg if (xoffset < - (GLint) destImage->Border) { 116101e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(xoffset)", func); 1162af69d88dSmrg return GL_TRUE; 1163af69d88dSmrg } 1164af69d88dSmrg 1165af69d88dSmrg if (xoffset + subWidth > (GLint) destImage->Width) { 116601e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(xoffset %d + width %d > %u)", func, 116701e04c3fSmrg xoffset, subWidth, destImage->Width); 1168af69d88dSmrg return GL_TRUE; 1169af69d88dSmrg } 1170af69d88dSmrg 1171af69d88dSmrg /* check yoffset and height */ 1172af69d88dSmrg if (dims > 1) { 1173af69d88dSmrg GLint yBorder = (target == GL_TEXTURE_1D_ARRAY) ? 0 : destImage->Border; 1174af69d88dSmrg if (yoffset < -yBorder) { 117501e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(yoffset)", func); 1176af69d88dSmrg return GL_TRUE; 1177af69d88dSmrg } 1178af69d88dSmrg if (yoffset + subHeight > (GLint) destImage->Height) { 117901e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(yoffset %d + height %d > %u)", 118001e04c3fSmrg func, yoffset, subHeight, destImage->Height); 1181af69d88dSmrg return GL_TRUE; 1182af69d88dSmrg } 1183af69d88dSmrg } 1184af69d88dSmrg 1185af69d88dSmrg /* check zoffset and depth */ 1186af69d88dSmrg if (dims > 2) { 118701e04c3fSmrg GLint depth; 1188af69d88dSmrg GLint zBorder = (target == GL_TEXTURE_2D_ARRAY || 1189af69d88dSmrg target == GL_TEXTURE_CUBE_MAP_ARRAY) ? 1190af69d88dSmrg 0 : destImage->Border; 1191af69d88dSmrg 1192af69d88dSmrg if (zoffset < -zBorder) { 119301e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(zoffset)", func); 1194af69d88dSmrg return GL_TRUE; 1195af69d88dSmrg } 119601e04c3fSmrg 119701e04c3fSmrg depth = (GLint) destImage->Depth; 119801e04c3fSmrg if (target == GL_TEXTURE_CUBE_MAP) 119901e04c3fSmrg depth = 6; 120001e04c3fSmrg if (zoffset + subDepth > depth) { 120101e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(zoffset %d + depth %d > %u)", 120201e04c3fSmrg func, zoffset, subDepth, depth); 1203af69d88dSmrg return GL_TRUE; 1204af69d88dSmrg } 1205af69d88dSmrg } 1206af69d88dSmrg 1207af69d88dSmrg /* 1208af69d88dSmrg * The OpenGL spec (and GL_ARB_texture_compression) says only whole 1209af69d88dSmrg * compressed texture images can be updated. But, that restriction may be 1210af69d88dSmrg * relaxed for particular compressed formats. At this time, all the 1211af69d88dSmrg * compressed formats supported by Mesa allow sub-textures to be updated 1212af69d88dSmrg * along compressed block boundaries. 1213af69d88dSmrg */ 121401e04c3fSmrg _mesa_get_format_block_size_3d(destImage->TexFormat, &bw, &bh, &bd); 1215af69d88dSmrg 121601e04c3fSmrg if (bw != 1 || bh != 1 || bd != 1) { 1217af69d88dSmrg /* offset must be multiple of block size */ 121801e04c3fSmrg if ((xoffset % bw != 0) || (yoffset % bh != 0) || (zoffset % bd != 0)) { 1219af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 122001e04c3fSmrg "%s(xoffset = %d, yoffset = %d, zoffset = %d)", 122101e04c3fSmrg func, xoffset, yoffset, zoffset); 1222af69d88dSmrg return GL_TRUE; 1223af69d88dSmrg } 1224af69d88dSmrg 1225af69d88dSmrg /* The size must be a multiple of bw x bh, or we must be using a 1226af69d88dSmrg * offset+size that exactly hits the edge of the image. This 1227af69d88dSmrg * is important for small mipmap levels (1x1, 2x1, etc) and for 1228af69d88dSmrg * NPOT textures. 1229af69d88dSmrg */ 1230af69d88dSmrg if ((subWidth % bw != 0) && 1231af69d88dSmrg (xoffset + subWidth != (GLint) destImage->Width)) { 1232af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 123301e04c3fSmrg "%s(width = %d)", func, subWidth); 1234af69d88dSmrg return GL_TRUE; 1235af69d88dSmrg } 1236af69d88dSmrg 1237af69d88dSmrg if ((subHeight % bh != 0) && 1238af69d88dSmrg (yoffset + subHeight != (GLint) destImage->Height)) { 1239af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 124001e04c3fSmrg "%s(height = %d)", func, subHeight); 124101e04c3fSmrg return GL_TRUE; 124201e04c3fSmrg } 124301e04c3fSmrg 124401e04c3fSmrg if ((subDepth % bd != 0) && 124501e04c3fSmrg (zoffset + subDepth != (GLint) destImage->Depth)) { 124601e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 124701e04c3fSmrg "%s(depth = %d)", func, subDepth); 1248af69d88dSmrg return GL_TRUE; 1249af69d88dSmrg } 1250af69d88dSmrg } 1251af69d88dSmrg 1252af69d88dSmrg return GL_FALSE; 1253af69d88dSmrg} 1254af69d88dSmrg 1255af69d88dSmrg 1256af69d88dSmrg 1257af69d88dSmrg 1258af69d88dSmrg/** 1259af69d88dSmrg * This is the fallback for Driver.TestProxyTexImage() for doing device- 1260af69d88dSmrg * specific texture image size checks. 1261af69d88dSmrg * 1262af69d88dSmrg * A hardware driver might override this function if, for example, the 1263af69d88dSmrg * max 3D texture size is 512x512x64 (i.e. not a cube). 1264af69d88dSmrg * 1265af69d88dSmrg * Note that width, height, depth == 0 is not an error. However, a 1266af69d88dSmrg * texture with zero width/height/depth will be considered "incomplete" 1267af69d88dSmrg * and texturing will effectively be disabled. 1268af69d88dSmrg * 1269af69d88dSmrg * \param target any texture target/type 127001e04c3fSmrg * \param numLevels number of mipmap levels in the texture or 0 if not known 1271af69d88dSmrg * \param level as passed to glTexImage 1272af69d88dSmrg * \param format the MESA_FORMAT_x for the tex image 127301e04c3fSmrg * \param numSamples number of samples per texel 1274af69d88dSmrg * \param width as passed to glTexImage 1275af69d88dSmrg * \param height as passed to glTexImage 1276af69d88dSmrg * \param depth as passed to glTexImage 1277af69d88dSmrg * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable. 1278af69d88dSmrg */ 1279af69d88dSmrgGLboolean 128001e04c3fSmrg_mesa_test_proxy_teximage(struct gl_context *ctx, GLenum target, 12817ec681f3Smrg GLuint numLevels, ASSERTED GLint level, 128201e04c3fSmrg mesa_format format, GLuint numSamples, 128301e04c3fSmrg GLint width, GLint height, GLint depth) 12847117f1b4Smrg{ 128501e04c3fSmrg uint64_t bytes, mbytes; 128601e04c3fSmrg 128701e04c3fSmrg if (numLevels > 0) { 128801e04c3fSmrg /* Compute total memory for a whole mipmap. This is the path 128901e04c3fSmrg * taken for glTexStorage(GL_PROXY_TEXTURE_x). 129001e04c3fSmrg */ 129101e04c3fSmrg unsigned l; 129201e04c3fSmrg 129301e04c3fSmrg assert(level == 0); 129401e04c3fSmrg 129501e04c3fSmrg bytes = 0; 129601e04c3fSmrg 129701e04c3fSmrg for (l = 0; l < numLevels; l++) { 129801e04c3fSmrg GLint nextWidth, nextHeight, nextDepth; 129901e04c3fSmrg 130001e04c3fSmrg bytes += _mesa_format_image_size64(format, width, height, depth); 130101e04c3fSmrg 130201e04c3fSmrg if (_mesa_next_mipmap_level_size(target, 0, width, height, depth, 130301e04c3fSmrg &nextWidth, &nextHeight, 130401e04c3fSmrg &nextDepth)) { 130501e04c3fSmrg width = nextWidth; 130601e04c3fSmrg height = nextHeight; 130701e04c3fSmrg depth = nextDepth; 130801e04c3fSmrg } else { 130901e04c3fSmrg break; 131001e04c3fSmrg } 131101e04c3fSmrg } 131201e04c3fSmrg } else { 131301e04c3fSmrg /* We just compute the size of one mipmap level. This is the path 131401e04c3fSmrg * taken for glTexImage(GL_PROXY_TEXTURE_x). 131501e04c3fSmrg */ 131601e04c3fSmrg bytes = _mesa_format_image_size64(format, width, height, depth); 131701e04c3fSmrg } 131801e04c3fSmrg 131901e04c3fSmrg bytes *= _mesa_num_tex_faces(target); 132001e04c3fSmrg bytes *= MAX2(1, numSamples); 132101e04c3fSmrg 132201e04c3fSmrg mbytes = bytes / (1024 * 1024); /* convert to MB */ 132301e04c3fSmrg 1324af69d88dSmrg /* We just check if the image size is less than MaxTextureMbytes. 1325af69d88dSmrg * Some drivers may do more specific checks. 1326af69d88dSmrg */ 13273464ebd5Sriastradh return mbytes <= (uint64_t) ctx->Const.MaxTextureMbytes; 13287117f1b4Smrg} 13297117f1b4Smrg 13307117f1b4Smrg 1331af69d88dSmrg/** 1332af69d88dSmrg * Return true if the format is only valid for glCompressedTexImage. 1333af69d88dSmrg */ 133401e04c3fSmrgstatic bool 133501e04c3fSmrgcompressedteximage_only_format(GLenum format) 1336af69d88dSmrg{ 1337af69d88dSmrg switch (format) { 1338af69d88dSmrg case GL_PALETTE4_RGB8_OES: 1339af69d88dSmrg case GL_PALETTE4_RGBA8_OES: 1340af69d88dSmrg case GL_PALETTE4_R5_G6_B5_OES: 1341af69d88dSmrg case GL_PALETTE4_RGBA4_OES: 1342af69d88dSmrg case GL_PALETTE4_RGB5_A1_OES: 1343af69d88dSmrg case GL_PALETTE8_RGB8_OES: 1344af69d88dSmrg case GL_PALETTE8_RGBA8_OES: 1345af69d88dSmrg case GL_PALETTE8_R5_G6_B5_OES: 1346af69d88dSmrg case GL_PALETTE8_RGBA4_OES: 1347af69d88dSmrg case GL_PALETTE8_RGB5_A1_OES: 1348b9abf16eSmaya case GL_ATC_RGB_AMD: 1349b9abf16eSmaya case GL_ATC_RGBA_EXPLICIT_ALPHA_AMD: 1350b9abf16eSmaya case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD: 135101e04c3fSmrg return true; 1352af69d88dSmrg default: 135301e04c3fSmrg return false; 1354af69d88dSmrg } 1355af69d88dSmrg} 1356af69d88dSmrg 135701e04c3fSmrg/** 135801e04c3fSmrg * Return true if the format doesn't support online compression. 135901e04c3fSmrg */ 136001e04c3fSmrgbool 136101e04c3fSmrg_mesa_format_no_online_compression(GLenum format) 136201e04c3fSmrg{ 136301e04c3fSmrg return _mesa_is_astc_format(format) || 136401e04c3fSmrg _mesa_is_etc2_format(format) || 136501e04c3fSmrg compressedteximage_only_format(format); 136601e04c3fSmrg} 136701e04c3fSmrg 136801e04c3fSmrg/* Writes to an GL error pointer if non-null and returns whether or not the 136901e04c3fSmrg * error is GL_NO_ERROR */ 137001e04c3fSmrgstatic bool 137101e04c3fSmrgwrite_error(GLenum *err_ptr, GLenum error) 137201e04c3fSmrg{ 137301e04c3fSmrg if (err_ptr) 137401e04c3fSmrg *err_ptr = error; 137501e04c3fSmrg 137601e04c3fSmrg return error == GL_NO_ERROR; 137701e04c3fSmrg} 13783464ebd5Sriastradh 13797117f1b4Smrg/** 13803464ebd5Sriastradh * Helper function to determine whether a target and specific compression 138101e04c3fSmrg * format are supported. The error parameter returns GL_NO_ERROR if the 138201e04c3fSmrg * target can be compressed. Otherwise it returns either GL_INVALID_OPERATION 138301e04c3fSmrg * or GL_INVALID_ENUM, whichever is more appropriate. 13847117f1b4Smrg */ 1385af69d88dSmrgGLboolean 1386af69d88dSmrg_mesa_target_can_be_compressed(const struct gl_context *ctx, GLenum target, 138701e04c3fSmrg GLenum intFormat, GLenum *error) 13887117f1b4Smrg{ 138901e04c3fSmrg GLboolean target_can_be_compresed = GL_FALSE; 139001e04c3fSmrg mesa_format format = _mesa_glenum_to_compressed_format(intFormat); 139101e04c3fSmrg enum mesa_format_layout layout = _mesa_get_format_layout(format); 13927117f1b4Smrg 13933464ebd5Sriastradh switch (target) { 13943464ebd5Sriastradh case GL_TEXTURE_2D: 13953464ebd5Sriastradh case GL_PROXY_TEXTURE_2D: 139601e04c3fSmrg target_can_be_compresed = GL_TRUE; /* true for any compressed format so far */ 139701e04c3fSmrg break; 13983464ebd5Sriastradh case GL_PROXY_TEXTURE_CUBE_MAP: 1399af69d88dSmrg case GL_TEXTURE_CUBE_MAP: 14003464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 14013464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 14023464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 14033464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 14043464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 14053464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 140601e04c3fSmrg target_can_be_compresed = ctx->Extensions.ARB_texture_cube_map; 140701e04c3fSmrg break; 14083464ebd5Sriastradh case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 14093464ebd5Sriastradh case GL_TEXTURE_2D_ARRAY_EXT: 141001e04c3fSmrg target_can_be_compresed = ctx->Extensions.EXT_texture_array; 141101e04c3fSmrg break; 1412af69d88dSmrg case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY: 1413af69d88dSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: 141401e04c3fSmrg /* From the KHR_texture_compression_astc_hdr spec: 141501e04c3fSmrg * 141601e04c3fSmrg * Add a second new column "3D Tex." which is empty for all non-ASTC 141701e04c3fSmrg * formats. If only the LDR profile is supported by the 141801e04c3fSmrg * implementation, this column is also empty for all ASTC formats. If 141901e04c3fSmrg * both the LDR and HDR profiles are supported only, this column is 142001e04c3fSmrg * checked for all ASTC formats. 142101e04c3fSmrg * 142201e04c3fSmrg * Add a third new column "Cube Map Array Tex." which is empty for all 142301e04c3fSmrg * non-ASTC formats, and checked for all ASTC formats. 142401e04c3fSmrg * 142501e04c3fSmrg * and, 142601e04c3fSmrg * 142701e04c3fSmrg * 'An INVALID_OPERATION error is generated by CompressedTexImage3D 142801e04c3fSmrg * if <internalformat> is TEXTURE_CUBE_MAP_ARRAY and the 142901e04c3fSmrg * "Cube Map Array" column of table 8.19 is *not* checked, or if 143001e04c3fSmrg * <internalformat> is TEXTURE_3D and the "3D Tex." column of table 143101e04c3fSmrg * 8.19 is *not* checked' 143201e04c3fSmrg * 143301e04c3fSmrg * The instances of <internalformat> above should say <target>. 143401e04c3fSmrg * 143501e04c3fSmrg * ETC2/EAC formats are the only alternative in GLES and thus such errors 143601e04c3fSmrg * have already been handled by normal ETC2/EAC behavior. 143701e04c3fSmrg */ 143801e04c3fSmrg 143901e04c3fSmrg /* From section 3.8.6, page 146 of OpenGL ES 3.0 spec: 144001e04c3fSmrg * 144101e04c3fSmrg * "The ETC2/EAC texture compression algorithm supports only 144201e04c3fSmrg * two-dimensional images. If internalformat is an ETC2/EAC format, 144301e04c3fSmrg * glCompressedTexImage3D will generate an INVALID_OPERATION error if 144401e04c3fSmrg * target is not TEXTURE_2D_ARRAY." 144501e04c3fSmrg * 144601e04c3fSmrg * This should also be applicable for glTexStorage3D(). Other available 144701e04c3fSmrg * targets for these functions are: TEXTURE_3D and TEXTURE_CUBE_MAP_ARRAY. 144801e04c3fSmrg * 144901e04c3fSmrg * Section 8.7, page 179 of OpenGL ES 3.2 adds: 145001e04c3fSmrg * 145101e04c3fSmrg * An INVALID_OPERATION error is generated by CompressedTexImage3D 145201e04c3fSmrg * if internalformat is one of the the formats in table 8.17 and target is 145301e04c3fSmrg * not TEXTURE_2D_ARRAY, TEXTURE_CUBE_MAP_ARRAY or TEXTURE_3D. 145401e04c3fSmrg * 145501e04c3fSmrg * An INVALID_OPERATION error is generated by CompressedTexImage3D 145601e04c3fSmrg * if internalformat is TEXTURE_CUBE_MAP_ARRAY and the “Cube Map 145701e04c3fSmrg * Array” column of table 8.17 is not checked, or if internalformat 145801e04c3fSmrg * is TEXTURE_- 3D and the “3D Tex.” column of table 8.17 is not 145901e04c3fSmrg * checked. 146001e04c3fSmrg * 146101e04c3fSmrg * The instances of <internalformat> above should say <target>. 146201e04c3fSmrg * 146301e04c3fSmrg * Such table 8.17 has checked "Cube Map Array" column for all the 146401e04c3fSmrg * cases. So in practice, TEXTURE_CUBE_MAP_ARRAY is now valid for OpenGL ES 3.2 146501e04c3fSmrg */ 146601e04c3fSmrg if (layout == MESA_FORMAT_LAYOUT_ETC2 && _mesa_is_gles3(ctx) && 146701e04c3fSmrg !_mesa_is_gles32(ctx)) 146801e04c3fSmrg return write_error(error, GL_INVALID_OPERATION); 146901e04c3fSmrg target_can_be_compresed = _mesa_has_texture_cube_map_array(ctx); 147001e04c3fSmrg break; 147101e04c3fSmrg case GL_TEXTURE_3D: 147201e04c3fSmrg switch (layout) { 147301e04c3fSmrg case MESA_FORMAT_LAYOUT_ETC2: 147401e04c3fSmrg /* See ETC2/EAC comment in case GL_TEXTURE_CUBE_MAP_ARRAY. */ 147501e04c3fSmrg if (_mesa_is_gles3(ctx)) 147601e04c3fSmrg return write_error(error, GL_INVALID_OPERATION); 147701e04c3fSmrg break; 147801e04c3fSmrg case MESA_FORMAT_LAYOUT_BPTC: 147901e04c3fSmrg target_can_be_compresed = ctx->Extensions.ARB_texture_compression_bptc; 148001e04c3fSmrg break; 148101e04c3fSmrg case MESA_FORMAT_LAYOUT_ASTC: 148201e04c3fSmrg target_can_be_compresed = 148301e04c3fSmrg ctx->Extensions.KHR_texture_compression_astc_hdr || 148401e04c3fSmrg ctx->Extensions.KHR_texture_compression_astc_sliced_3d; 148501e04c3fSmrg 148601e04c3fSmrg /* Throw an INVALID_OPERATION error if the target is TEXTURE_3D and 148701e04c3fSmrg * neither of the above extensions are supported. See comment in 148801e04c3fSmrg * switch case GL_TEXTURE_CUBE_MAP_ARRAY for more info. 148901e04c3fSmrg */ 149001e04c3fSmrg if (!target_can_be_compresed) 149101e04c3fSmrg return write_error(error, GL_INVALID_OPERATION); 149201e04c3fSmrg break; 149301e04c3fSmrg default: 149401e04c3fSmrg break; 149501e04c3fSmrg } 14967ec681f3Smrg FALLTHROUGH; 14973464ebd5Sriastradh default: 149801e04c3fSmrg break; 1499af69d88dSmrg } 150001e04c3fSmrg return write_error(error, 150101e04c3fSmrg target_can_be_compresed ? GL_NO_ERROR : GL_INVALID_ENUM); 15023464ebd5Sriastradh} 15037117f1b4Smrg 15047117f1b4Smrg 15053464ebd5Sriastradh/** 15063464ebd5Sriastradh * Check if the given texture target value is legal for a 15073464ebd5Sriastradh * glTexImage1/2/3D call. 15083464ebd5Sriastradh */ 15093464ebd5Sriastradhstatic GLboolean 15103464ebd5Sriastradhlegal_teximage_target(struct gl_context *ctx, GLuint dims, GLenum target) 15113464ebd5Sriastradh{ 15123464ebd5Sriastradh switch (dims) { 15133464ebd5Sriastradh case 1: 15143464ebd5Sriastradh switch (target) { 15153464ebd5Sriastradh case GL_TEXTURE_1D: 15163464ebd5Sriastradh case GL_PROXY_TEXTURE_1D: 1517af69d88dSmrg return _mesa_is_desktop_gl(ctx); 15183464ebd5Sriastradh default: 15193464ebd5Sriastradh return GL_FALSE; 15207117f1b4Smrg } 15213464ebd5Sriastradh case 2: 15223464ebd5Sriastradh switch (target) { 15233464ebd5Sriastradh case GL_TEXTURE_2D: 15243464ebd5Sriastradh return GL_TRUE; 1525af69d88dSmrg case GL_PROXY_TEXTURE_2D: 1526af69d88dSmrg return _mesa_is_desktop_gl(ctx); 15273464ebd5Sriastradh case GL_PROXY_TEXTURE_CUBE_MAP: 1528af69d88dSmrg return _mesa_is_desktop_gl(ctx) 1529af69d88dSmrg && ctx->Extensions.ARB_texture_cube_map; 15303464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 15313464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 15323464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 15333464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 15343464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 15353464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 15363464ebd5Sriastradh return ctx->Extensions.ARB_texture_cube_map; 15373464ebd5Sriastradh case GL_TEXTURE_RECTANGLE_NV: 15383464ebd5Sriastradh case GL_PROXY_TEXTURE_RECTANGLE_NV: 1539af69d88dSmrg return _mesa_is_desktop_gl(ctx) 1540af69d88dSmrg && ctx->Extensions.NV_texture_rectangle; 15413464ebd5Sriastradh case GL_TEXTURE_1D_ARRAY_EXT: 15423464ebd5Sriastradh case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 1543af69d88dSmrg return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array; 15443464ebd5Sriastradh default: 15453464ebd5Sriastradh return GL_FALSE; 15467117f1b4Smrg } 15473464ebd5Sriastradh case 3: 15483464ebd5Sriastradh switch (target) { 15493464ebd5Sriastradh case GL_TEXTURE_3D: 15507117f1b4Smrg return GL_TRUE; 1551af69d88dSmrg case GL_PROXY_TEXTURE_3D: 1552af69d88dSmrg return _mesa_is_desktop_gl(ctx); 15533464ebd5Sriastradh case GL_TEXTURE_2D_ARRAY_EXT: 1554af69d88dSmrg return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array) 1555af69d88dSmrg || _mesa_is_gles3(ctx); 15563464ebd5Sriastradh case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 1557af69d88dSmrg return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array; 1558af69d88dSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: 1559af69d88dSmrg case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY: 156001e04c3fSmrg return _mesa_has_texture_cube_map_array(ctx); 15613464ebd5Sriastradh default: 15623464ebd5Sriastradh return GL_FALSE; 15637117f1b4Smrg } 15643464ebd5Sriastradh default: 15653464ebd5Sriastradh _mesa_problem(ctx, "invalid dims=%u in legal_teximage_target()", dims); 15663464ebd5Sriastradh return GL_FALSE; 15677117f1b4Smrg } 15683464ebd5Sriastradh} 15693464ebd5Sriastradh 15703464ebd5Sriastradh 15713464ebd5Sriastradh/** 15723464ebd5Sriastradh * Check if the given texture target value is legal for a 15733464ebd5Sriastradh * glTexSubImage, glCopyTexSubImage or glCopyTexImage call. 15743464ebd5Sriastradh * The difference compared to legal_teximage_target() above is that 15753464ebd5Sriastradh * proxy targets are not supported. 15763464ebd5Sriastradh */ 15773464ebd5Sriastradhstatic GLboolean 157801e04c3fSmrglegal_texsubimage_target(struct gl_context *ctx, GLuint dims, GLenum target, 157901e04c3fSmrg bool dsa) 15803464ebd5Sriastradh{ 15813464ebd5Sriastradh switch (dims) { 15823464ebd5Sriastradh case 1: 1583af69d88dSmrg return _mesa_is_desktop_gl(ctx) && target == GL_TEXTURE_1D; 15843464ebd5Sriastradh case 2: 15853464ebd5Sriastradh switch (target) { 15863464ebd5Sriastradh case GL_TEXTURE_2D: 15873464ebd5Sriastradh return GL_TRUE; 15883464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 15893464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 15903464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 15913464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 15923464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 15933464ebd5Sriastradh case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 15943464ebd5Sriastradh return ctx->Extensions.ARB_texture_cube_map; 15953464ebd5Sriastradh case GL_TEXTURE_RECTANGLE_NV: 1596af69d88dSmrg return _mesa_is_desktop_gl(ctx) 1597af69d88dSmrg && ctx->Extensions.NV_texture_rectangle; 15983464ebd5Sriastradh case GL_TEXTURE_1D_ARRAY_EXT: 1599af69d88dSmrg return _mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array; 16003464ebd5Sriastradh default: 16013464ebd5Sriastradh return GL_FALSE; 1602c1f859d4Smrg } 16033464ebd5Sriastradh case 3: 16043464ebd5Sriastradh switch (target) { 16053464ebd5Sriastradh case GL_TEXTURE_3D: 16067117f1b4Smrg return GL_TRUE; 16073464ebd5Sriastradh case GL_TEXTURE_2D_ARRAY_EXT: 1608af69d88dSmrg return (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array) 1609af69d88dSmrg || _mesa_is_gles3(ctx); 1610af69d88dSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: 1611af69d88dSmrg case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY: 161201e04c3fSmrg return _mesa_has_texture_cube_map_array(ctx); 161301e04c3fSmrg 161401e04c3fSmrg /* Table 8.15 of the OpenGL 4.5 core profile spec 161501e04c3fSmrg * (20141030) says that TEXTURE_CUBE_MAP is valid for TextureSubImage3D 161601e04c3fSmrg * and CopyTextureSubImage3D. 161701e04c3fSmrg */ 161801e04c3fSmrg case GL_TEXTURE_CUBE_MAP: 161901e04c3fSmrg return dsa; 16203464ebd5Sriastradh default: 16213464ebd5Sriastradh return GL_FALSE; 16227117f1b4Smrg } 16233464ebd5Sriastradh default: 16243464ebd5Sriastradh _mesa_problem(ctx, "invalid dims=%u in legal_texsubimage_target()", 16253464ebd5Sriastradh dims); 16263464ebd5Sriastradh return GL_FALSE; 16277117f1b4Smrg } 16283464ebd5Sriastradh} 16293464ebd5Sriastradh 16303464ebd5Sriastradh 16313464ebd5Sriastradh/** 1632af69d88dSmrg * Helper function to determine if a texture object is mutable (in terms 163301e04c3fSmrg * of GL_ARB_texture_storage/GL_ARB_bindless_texture). 16343464ebd5Sriastradh */ 16353464ebd5Sriastradhstatic GLboolean 16367ec681f3Smrgmutable_tex_object(struct gl_texture_object *texObj) 16373464ebd5Sriastradh{ 163801e04c3fSmrg if (!texObj) 163901e04c3fSmrg return GL_FALSE; 164001e04c3fSmrg 164101e04c3fSmrg if (texObj->HandleAllocated) { 164201e04c3fSmrg /* The ARB_bindless_texture spec says: 164301e04c3fSmrg * 164401e04c3fSmrg * "The error INVALID_OPERATION is generated by TexImage*, CopyTexImage*, 164501e04c3fSmrg * CompressedTexImage*, TexBuffer*, TexParameter*, as well as other 164601e04c3fSmrg * functions defined in terms of these, if the texture object to be 164701e04c3fSmrg * modified is referenced by one or more texture or image handles." 164801e04c3fSmrg */ 164901e04c3fSmrg return GL_FALSE; 165001e04c3fSmrg } 165101e04c3fSmrg 1652af69d88dSmrg return !texObj->Immutable; 1653af69d88dSmrg} 16543464ebd5Sriastradh 16553464ebd5Sriastradh 1656af69d88dSmrg/** 1657af69d88dSmrg * Return expected size of a compressed texture. 1658af69d88dSmrg */ 1659af69d88dSmrgstatic GLuint 1660af69d88dSmrgcompressed_tex_size(GLsizei width, GLsizei height, GLsizei depth, 1661af69d88dSmrg GLenum glformat) 1662af69d88dSmrg{ 1663af69d88dSmrg mesa_format mesaFormat = _mesa_glenum_to_compressed_format(glformat); 1664af69d88dSmrg return _mesa_format_image_size(mesaFormat, width, height, depth); 1665af69d88dSmrg} 16667117f1b4Smrg 1667af69d88dSmrg/** 1668af69d88dSmrg * Verify that a texture format is valid with a particular target 1669af69d88dSmrg * 1670af69d88dSmrg * In particular, textures with base format of \c GL_DEPTH_COMPONENT or 1671af69d88dSmrg * \c GL_DEPTH_STENCIL are only valid with certain, context dependent texture 1672af69d88dSmrg * targets. 1673af69d88dSmrg * 1674af69d88dSmrg * \param ctx GL context 1675af69d88dSmrg * \param target Texture target 1676af69d88dSmrg * \param internalFormat Internal format of the texture image 1677af69d88dSmrg * 1678af69d88dSmrg * \returns true if the combination is legal, false otherwise. 1679af69d88dSmrg */ 1680af69d88dSmrgbool 1681af69d88dSmrg_mesa_legal_texture_base_format_for_target(struct gl_context *ctx, 168201e04c3fSmrg GLenum target, GLenum internalFormat) 1683af69d88dSmrg{ 1684af69d88dSmrg if (_mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_COMPONENT 168501e04c3fSmrg || _mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_STENCIL 168601e04c3fSmrg || _mesa_base_tex_format(ctx, internalFormat) == GL_STENCIL_INDEX) { 1687af69d88dSmrg /* Section 3.8.3 (Texture Image Specification) of the OpenGL 3.3 Core 1688af69d88dSmrg * Profile spec says: 1689af69d88dSmrg * 1690af69d88dSmrg * "Textures with a base internal format of DEPTH_COMPONENT or 1691af69d88dSmrg * DEPTH_STENCIL are supported by texture image specification 1692af69d88dSmrg * commands only if target is TEXTURE_1D, TEXTURE_2D, 1693af69d88dSmrg * TEXTURE_1D_ARRAY, TEXTURE_2D_ARRAY, TEXTURE_RECTANGLE, 1694af69d88dSmrg * TEXTURE_CUBE_MAP, PROXY_TEXTURE_1D, PROXY_TEXTURE_2D, 1695af69d88dSmrg * PROXY_TEXTURE_1D_ARRAY, PROXY_TEXTURE_2D_ARRAY, 1696af69d88dSmrg * PROXY_TEXTURE_RECTANGLE, or PROXY_TEXTURE_CUBE_MAP. Using these 1697af69d88dSmrg * formats in conjunction with any other target will result in an 1698af69d88dSmrg * INVALID_OPERATION error." 1699af69d88dSmrg * 1700af69d88dSmrg * Cubemaps are only supported with desktop OpenGL version >= 3.0, 1701af69d88dSmrg * EXT_gpu_shader4, or, on OpenGL ES 2.0+, OES_depth_texture_cube_map. 1702af69d88dSmrg */ 1703af69d88dSmrg if (target != GL_TEXTURE_1D && 1704af69d88dSmrg target != GL_PROXY_TEXTURE_1D && 1705af69d88dSmrg target != GL_TEXTURE_2D && 1706af69d88dSmrg target != GL_PROXY_TEXTURE_2D && 1707af69d88dSmrg target != GL_TEXTURE_1D_ARRAY && 1708af69d88dSmrg target != GL_PROXY_TEXTURE_1D_ARRAY && 1709af69d88dSmrg target != GL_TEXTURE_2D_ARRAY && 1710af69d88dSmrg target != GL_PROXY_TEXTURE_2D_ARRAY && 1711af69d88dSmrg target != GL_TEXTURE_RECTANGLE_ARB && 1712af69d88dSmrg target != GL_PROXY_TEXTURE_RECTANGLE_ARB && 1713af69d88dSmrg !((_mesa_is_cube_face(target) || 1714af69d88dSmrg target == GL_TEXTURE_CUBE_MAP || 1715af69d88dSmrg target == GL_PROXY_TEXTURE_CUBE_MAP) && 1716af69d88dSmrg (ctx->Version >= 30 || ctx->Extensions.EXT_gpu_shader4 1717af69d88dSmrg || (ctx->API == API_OPENGLES2 && ctx->Extensions.OES_depth_texture_cube_map))) && 1718af69d88dSmrg !((target == GL_TEXTURE_CUBE_MAP_ARRAY || 1719af69d88dSmrg target == GL_PROXY_TEXTURE_CUBE_MAP_ARRAY) && 172001e04c3fSmrg _mesa_has_texture_cube_map_array(ctx))) { 1721af69d88dSmrg return false; 1722af69d88dSmrg } 17233464ebd5Sriastradh } 17243464ebd5Sriastradh 1725af69d88dSmrg return true; 1726af69d88dSmrg} 1727af69d88dSmrg 1728af69d88dSmrgstatic bool 1729af69d88dSmrgtexture_formats_agree(GLenum internalFormat, 1730af69d88dSmrg GLenum format) 1731af69d88dSmrg{ 1732af69d88dSmrg GLboolean colorFormat; 1733af69d88dSmrg GLboolean is_format_depth_or_depthstencil; 1734af69d88dSmrg GLboolean is_internalFormat_depth_or_depthstencil; 1735af69d88dSmrg 1736af69d88dSmrg /* Even though there are no color-index textures, we still have to support 1737af69d88dSmrg * uploading color-index data and remapping it to RGB via the 1738af69d88dSmrg * GL_PIXEL_MAP_I_TO_[RGBA] tables. 17393464ebd5Sriastradh */ 1740af69d88dSmrg const GLboolean indexFormat = (format == GL_COLOR_INDEX); 1741af69d88dSmrg 1742af69d88dSmrg is_internalFormat_depth_or_depthstencil = 1743af69d88dSmrg _mesa_is_depth_format(internalFormat) || 1744af69d88dSmrg _mesa_is_depthstencil_format(internalFormat); 1745af69d88dSmrg 1746af69d88dSmrg is_format_depth_or_depthstencil = 1747af69d88dSmrg _mesa_is_depth_format(format) || 1748af69d88dSmrg _mesa_is_depthstencil_format(format); 1749af69d88dSmrg 1750af69d88dSmrg colorFormat = _mesa_is_color_format(format); 1751af69d88dSmrg 1752af69d88dSmrg if (_mesa_is_color_format(internalFormat) && !colorFormat && !indexFormat) 1753af69d88dSmrg return false; 1754af69d88dSmrg 1755af69d88dSmrg if (is_internalFormat_depth_or_depthstencil != 1756af69d88dSmrg is_format_depth_or_depthstencil) 1757af69d88dSmrg return false; 1758af69d88dSmrg 1759af69d88dSmrg if (_mesa_is_ycbcr_format(internalFormat) != _mesa_is_ycbcr_format(format)) 1760af69d88dSmrg return false; 1761af69d88dSmrg 1762af69d88dSmrg return true; 1763af69d88dSmrg} 1764af69d88dSmrg 176501e04c3fSmrg/** 176601e04c3fSmrg * Test the combination of format, type and internal format arguments of 176701e04c3fSmrg * different texture operations on GLES. 176801e04c3fSmrg * 176901e04c3fSmrg * \param ctx GL context. 177001e04c3fSmrg * \param format pixel data format given by the user. 177101e04c3fSmrg * \param type pixel data type given by the user. 177201e04c3fSmrg * \param internalFormat internal format given by the user. 177301e04c3fSmrg * \param callerName name of the caller function to print in the error message 177401e04c3fSmrg * 177501e04c3fSmrg * \return true if a error is found, false otherwise 177601e04c3fSmrg * 177701e04c3fSmrg * Currently, it is used by texture_error_check() and texsubimage_error_check(). 177801e04c3fSmrg */ 177901e04c3fSmrgstatic bool 178001e04c3fSmrgtexture_format_error_check_gles(struct gl_context *ctx, GLenum format, 178101e04c3fSmrg GLenum type, GLenum internalFormat, const char *callerName) 178201e04c3fSmrg{ 1783b9abf16eSmaya GLenum err = _mesa_gles_error_check_format_and_type(ctx, format, type, 1784b9abf16eSmaya internalFormat); 178501e04c3fSmrg if (err != GL_NO_ERROR) { 178601e04c3fSmrg _mesa_error(ctx, err, 178701e04c3fSmrg "%s(format = %s, type = %s, internalformat = %s)", 178801e04c3fSmrg callerName, _mesa_enum_to_string(format), 178901e04c3fSmrg _mesa_enum_to_string(type), 179001e04c3fSmrg _mesa_enum_to_string(internalFormat)); 179101e04c3fSmrg return true; 179201e04c3fSmrg } 179301e04c3fSmrg 179401e04c3fSmrg return false; 179501e04c3fSmrg} 179601e04c3fSmrg 1797af69d88dSmrg/** 1798af69d88dSmrg * Test the glTexImage[123]D() parameters for errors. 1799af69d88dSmrg * 1800af69d88dSmrg * \param ctx GL context. 1801af69d88dSmrg * \param dimensions texture image dimensions (must be 1, 2 or 3). 1802af69d88dSmrg * \param target texture target given by the user (already validated). 1803af69d88dSmrg * \param level image level given by the user. 1804af69d88dSmrg * \param internalFormat internal format given by the user. 1805af69d88dSmrg * \param format pixel data format given by the user. 1806af69d88dSmrg * \param type pixel data type given by the user. 1807af69d88dSmrg * \param width image width given by the user. 1808af69d88dSmrg * \param height image height given by the user. 1809af69d88dSmrg * \param depth image depth given by the user. 1810af69d88dSmrg * \param border image border given by the user. 1811af69d88dSmrg * 1812af69d88dSmrg * \return GL_TRUE if a error is found, GL_FALSE otherwise 1813af69d88dSmrg * 1814af69d88dSmrg * Verifies each of the parameters against the constants specified in 1815af69d88dSmrg * __struct gl_contextRec::Const and the supported extensions, and according 1816af69d88dSmrg * to the OpenGL specification. 1817af69d88dSmrg * Note that we don't fully error-check the width, height, depth values 1818af69d88dSmrg * here. That's done in _mesa_legal_texture_dimensions() which is used 1819af69d88dSmrg * by several other GL entrypoints. Plus, texture dims have a special 1820af69d88dSmrg * interaction with proxy textures. 1821af69d88dSmrg */ 1822af69d88dSmrgstatic GLboolean 1823af69d88dSmrgtexture_error_check( struct gl_context *ctx, 1824af69d88dSmrg GLuint dimensions, GLenum target, 18257ec681f3Smrg struct gl_texture_object* texObj, 1826af69d88dSmrg GLint level, GLint internalFormat, 1827af69d88dSmrg GLenum format, GLenum type, 1828af69d88dSmrg GLint width, GLint height, 182901e04c3fSmrg GLint depth, GLint border, 183001e04c3fSmrg const GLvoid *pixels ) 1831af69d88dSmrg{ 1832af69d88dSmrg GLenum err; 1833af69d88dSmrg 1834af69d88dSmrg /* Note: for proxy textures, some error conditions immediately generate 1835af69d88dSmrg * a GL error in the usual way. But others do not generate a GL error. 1836af69d88dSmrg * Instead, they cause the width, height, depth, format fields of the 1837af69d88dSmrg * texture image to be zeroed-out. The GL spec seems to indicate that the 1838af69d88dSmrg * zero-out behaviour is only used in cases related to memory allocation. 1839af69d88dSmrg */ 1840af69d88dSmrg 1841af69d88dSmrg /* level check */ 1842af69d88dSmrg if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) { 1843af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 1844af69d88dSmrg "glTexImage%dD(level=%d)", dimensions, level); 1845af69d88dSmrg return GL_TRUE; 1846af69d88dSmrg } 1847af69d88dSmrg 1848af69d88dSmrg /* Check border */ 1849af69d88dSmrg if (border < 0 || border > 1 || 1850af69d88dSmrg ((ctx->API != API_OPENGL_COMPAT || 1851af69d88dSmrg target == GL_TEXTURE_RECTANGLE_NV || 1852af69d88dSmrg target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) { 1853af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 1854af69d88dSmrg "glTexImage%dD(border=%d)", dimensions, border); 1855af69d88dSmrg return GL_TRUE; 1856af69d88dSmrg } 1857af69d88dSmrg 1858af69d88dSmrg if (width < 0 || height < 0 || depth < 0) { 1859af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 1860af69d88dSmrg "glTexImage%dD(width, height or depth < 0)", dimensions); 18617117f1b4Smrg return GL_TRUE; 18627117f1b4Smrg } 18637117f1b4Smrg 186401e04c3fSmrg /* Check incoming image format and type */ 186501e04c3fSmrg err = _mesa_error_check_format_and_type(ctx, format, type); 186601e04c3fSmrg if (err != GL_NO_ERROR) { 186701e04c3fSmrg /* Prior to OpenGL-ES 2.0, an INVALID_VALUE is expected instead of 186801e04c3fSmrg * INVALID_ENUM. From page 73 OpenGL ES 1.1 spec: 186901e04c3fSmrg * 187001e04c3fSmrg * "Specifying a value for internalformat that is not one of the 187101e04c3fSmrg * above (acceptable) values generates the error INVALID VALUE." 187201e04c3fSmrg */ 187301e04c3fSmrg if (err == GL_INVALID_ENUM && _mesa_is_gles(ctx) && ctx->Version < 20) 187401e04c3fSmrg err = GL_INVALID_VALUE; 1875af69d88dSmrg 187601e04c3fSmrg _mesa_error(ctx, err, 187701e04c3fSmrg "glTexImage%dD(incompatible format = %s, type = %s)", 187801e04c3fSmrg dimensions, _mesa_enum_to_string(format), 187901e04c3fSmrg _mesa_enum_to_string(type)); 188001e04c3fSmrg return GL_TRUE; 1881af69d88dSmrg } 1882af69d88dSmrg 18837117f1b4Smrg /* Check internalFormat */ 18847117f1b4Smrg if (_mesa_base_tex_format(ctx, internalFormat) < 0) { 1885af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 1886af69d88dSmrg "glTexImage%dD(internalFormat=%s)", 188701e04c3fSmrg dimensions, _mesa_enum_to_string(internalFormat)); 18887117f1b4Smrg return GL_TRUE; 18897117f1b4Smrg } 18907117f1b4Smrg 189101e04c3fSmrg /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the 189201e04c3fSmrg * combinations of format, internalFormat, and type that can be used. 189301e04c3fSmrg * Formats and types that require additional extensions (e.g., GL_FLOAT 189401e04c3fSmrg * requires GL_OES_texture_float) are filtered elsewhere. 189501e04c3fSmrg */ 189601e04c3fSmrg char bufCallerName[20]; 18977ec681f3Smrg snprintf(bufCallerName, 20, "glTexImage%dD", dimensions); 189801e04c3fSmrg if (_mesa_is_gles(ctx) && 189901e04c3fSmrg texture_format_error_check_gles(ctx, format, type, 190001e04c3fSmrg internalFormat, bufCallerName)) { 190101e04c3fSmrg return GL_TRUE; 190201e04c3fSmrg } 190301e04c3fSmrg 190401e04c3fSmrg /* validate the bound PBO, if any */ 190501e04c3fSmrg if (!_mesa_validate_pbo_source(ctx, dimensions, &ctx->Unpack, 190601e04c3fSmrg width, height, depth, format, type, 190701e04c3fSmrg INT_MAX, pixels, "glTexImage")) { 19087117f1b4Smrg return GL_TRUE; 19097117f1b4Smrg } 19107117f1b4Smrg 19117117f1b4Smrg /* make sure internal format and format basically agree */ 1912af69d88dSmrg if (!texture_formats_agree(internalFormat, format)) { 1913af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 1914af69d88dSmrg "glTexImage%dD(incompatible internalFormat = %s, format = %s)", 191501e04c3fSmrg dimensions, _mesa_enum_to_string(internalFormat), 191601e04c3fSmrg _mesa_enum_to_string(format)); 19177117f1b4Smrg return GL_TRUE; 19187117f1b4Smrg } 19197117f1b4Smrg 19207117f1b4Smrg /* additional checks for ycbcr textures */ 19217117f1b4Smrg if (internalFormat == GL_YCBCR_MESA) { 192201e04c3fSmrg assert(ctx->Extensions.MESA_ycbcr_texture); 19237117f1b4Smrg if (type != GL_UNSIGNED_SHORT_8_8_MESA && 19247117f1b4Smrg type != GL_UNSIGNED_SHORT_8_8_REV_MESA) { 19257117f1b4Smrg char message[100]; 19267ec681f3Smrg snprintf(message, sizeof(message), 1927af69d88dSmrg "glTexImage%dD(format/type YCBCR mismatch)", 1928af69d88dSmrg dimensions); 19293464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_ENUM, "%s", message); 19307117f1b4Smrg return GL_TRUE; /* error */ 19317117f1b4Smrg } 19327117f1b4Smrg if (target != GL_TEXTURE_2D && 19337117f1b4Smrg target != GL_PROXY_TEXTURE_2D && 19347117f1b4Smrg target != GL_TEXTURE_RECTANGLE_NV && 19357117f1b4Smrg target != GL_PROXY_TEXTURE_RECTANGLE_NV) { 1936af69d88dSmrg _mesa_error(ctx, GL_INVALID_ENUM, 1937af69d88dSmrg "glTexImage%dD(bad target for YCbCr texture)", 1938af69d88dSmrg dimensions); 19397117f1b4Smrg return GL_TRUE; 19407117f1b4Smrg } 19417117f1b4Smrg if (border != 0) { 1942af69d88dSmrg char message[100]; 19437ec681f3Smrg snprintf(message, sizeof(message), 1944af69d88dSmrg "glTexImage%dD(format=GL_YCBCR_MESA and border=%d)", 1945af69d88dSmrg dimensions, border); 1946af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s", message); 19477117f1b4Smrg return GL_TRUE; 19487117f1b4Smrg } 19497117f1b4Smrg } 19507117f1b4Smrg 19517117f1b4Smrg /* additional checks for depth textures */ 195201e04c3fSmrg if (!_mesa_legal_texture_base_format_for_target(ctx, target, internalFormat)) { 195301e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 195401e04c3fSmrg "glTexImage%dD(bad target for texture)", dimensions); 1955af69d88dSmrg return GL_TRUE; 195601e04c3fSmrg } 19577117f1b4Smrg 19587117f1b4Smrg /* additional checks for compressed textures */ 19593464ebd5Sriastradh if (_mesa_is_compressed_format(ctx, internalFormat)) { 196001e04c3fSmrg GLenum err; 196101e04c3fSmrg if (!_mesa_target_can_be_compressed(ctx, target, internalFormat, &err)) { 196201e04c3fSmrg _mesa_error(ctx, err, 1963af69d88dSmrg "glTexImage%dD(target can't be compressed)", dimensions); 1964af69d88dSmrg return GL_TRUE; 1965af69d88dSmrg } 196601e04c3fSmrg if (_mesa_format_no_online_compression(internalFormat)) { 1967af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 1968af69d88dSmrg "glTexImage%dD(no compression for format)", dimensions); 19697117f1b4Smrg return GL_TRUE; 19707117f1b4Smrg } 19717117f1b4Smrg if (border != 0) { 1972af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 1973af69d88dSmrg "glTexImage%dD(border!=0)", dimensions); 19747117f1b4Smrg return GL_TRUE; 19757117f1b4Smrg } 19767117f1b4Smrg } 19777117f1b4Smrg 19783464ebd5Sriastradh /* additional checks for integer textures */ 1979af69d88dSmrg if ((ctx->Version >= 30 || ctx->Extensions.EXT_texture_integer) && 1980af69d88dSmrg (_mesa_is_enum_format_integer(format) != 1981af69d88dSmrg _mesa_is_enum_format_integer(internalFormat))) { 1982af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 1983af69d88dSmrg "glTexImage%dD(integer/non-integer format mismatch)", 1984af69d88dSmrg dimensions); 1985af69d88dSmrg return GL_TRUE; 1986af69d88dSmrg } 1987af69d88dSmrg 19887ec681f3Smrg if (!mutable_tex_object(texObj)) { 1989af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 1990af69d88dSmrg "glTexImage%dD(immutable texture)", dimensions); 19913464ebd5Sriastradh return GL_TRUE; 19923464ebd5Sriastradh } 19933464ebd5Sriastradh 19947117f1b4Smrg /* if we get here, the parameters are OK */ 19957117f1b4Smrg return GL_FALSE; 19967117f1b4Smrg} 19977117f1b4Smrg 19987117f1b4Smrg 1999af69d88dSmrg/** 2000af69d88dSmrg * Error checking for glCompressedTexImage[123]D(). 2001af69d88dSmrg * Note that the width, height and depth values are not fully error checked 2002af69d88dSmrg * here. 2003af69d88dSmrg * \return GL_TRUE if a error is found, GL_FALSE otherwise 2004af69d88dSmrg */ 2005af69d88dSmrgstatic GLenum 2006af69d88dSmrgcompressed_texture_error_check(struct gl_context *ctx, GLint dimensions, 20077ec681f3Smrg GLenum target, struct gl_texture_object* texObj, 20087ec681f3Smrg GLint level, GLenum internalFormat, GLsizei width, 2009af69d88dSmrg GLsizei height, GLsizei depth, GLint border, 201001e04c3fSmrg GLsizei imageSize, const GLvoid *data) 2011af69d88dSmrg{ 2012af69d88dSmrg const GLint maxLevels = _mesa_max_texture_levels(ctx, target); 2013af69d88dSmrg GLint expectedSize; 2014af69d88dSmrg GLenum error = GL_NO_ERROR; 2015af69d88dSmrg char *reason = ""; /* no error */ 2016af69d88dSmrg 201701e04c3fSmrg if (!_mesa_target_can_be_compressed(ctx, target, internalFormat, &error)) { 2018af69d88dSmrg reason = "target"; 2019af69d88dSmrg goto error; 2020af69d88dSmrg } 2021af69d88dSmrg 2022af69d88dSmrg /* This will detect any invalid internalFormat value */ 2023af69d88dSmrg if (!_mesa_is_compressed_format(ctx, internalFormat)) { 2024af69d88dSmrg _mesa_error(ctx, GL_INVALID_ENUM, 2025af69d88dSmrg "glCompressedTexImage%dD(internalFormat=%s)", 202601e04c3fSmrg dimensions, _mesa_enum_to_string(internalFormat)); 202701e04c3fSmrg return GL_TRUE; 202801e04c3fSmrg } 202901e04c3fSmrg 203001e04c3fSmrg /* validate the bound PBO, if any */ 203101e04c3fSmrg if (!_mesa_validate_pbo_source_compressed(ctx, dimensions, &ctx->Unpack, 203201e04c3fSmrg imageSize, data, 203301e04c3fSmrg "glCompressedTexImage")) { 2034af69d88dSmrg return GL_TRUE; 2035af69d88dSmrg } 2036af69d88dSmrg 2037af69d88dSmrg switch (internalFormat) { 2038af69d88dSmrg case GL_PALETTE4_RGB8_OES: 2039af69d88dSmrg case GL_PALETTE4_RGBA8_OES: 2040af69d88dSmrg case GL_PALETTE4_R5_G6_B5_OES: 2041af69d88dSmrg case GL_PALETTE4_RGBA4_OES: 2042af69d88dSmrg case GL_PALETTE4_RGB5_A1_OES: 2043af69d88dSmrg case GL_PALETTE8_RGB8_OES: 2044af69d88dSmrg case GL_PALETTE8_RGBA8_OES: 2045af69d88dSmrg case GL_PALETTE8_R5_G6_B5_OES: 2046af69d88dSmrg case GL_PALETTE8_RGBA4_OES: 2047af69d88dSmrg case GL_PALETTE8_RGB5_A1_OES: 2048af69d88dSmrg /* check level (note that level should be zero or less!) */ 2049af69d88dSmrg if (level > 0 || level < -maxLevels) { 205001e04c3fSmrg reason = "level"; 205101e04c3fSmrg error = GL_INVALID_VALUE; 2052af69d88dSmrg goto error; 2053af69d88dSmrg } 2054af69d88dSmrg 2055af69d88dSmrg if (dimensions != 2) { 205601e04c3fSmrg reason = "compressed paletted textures must be 2D"; 205701e04c3fSmrg error = GL_INVALID_OPERATION; 2058af69d88dSmrg goto error; 2059af69d88dSmrg } 2060af69d88dSmrg 2061af69d88dSmrg /* Figure out the expected texture size (in bytes). This will be 2062af69d88dSmrg * checked against the actual size later. 2063af69d88dSmrg */ 2064af69d88dSmrg expectedSize = _mesa_cpal_compressed_size(level, internalFormat, 206501e04c3fSmrg width, height); 2066af69d88dSmrg 2067af69d88dSmrg /* This is for the benefit of the TestProxyTexImage below. It expects 2068af69d88dSmrg * level to be non-negative. OES_compressed_paletted_texture uses a 2069af69d88dSmrg * weird mechanism where the level specified to glCompressedTexImage2D 2070af69d88dSmrg * is -(n-1) number of levels in the texture, and the data specifies the 2071af69d88dSmrg * complete mipmap stack. This is done to ensure the palette is the 2072af69d88dSmrg * same for all levels. 2073af69d88dSmrg */ 2074af69d88dSmrg level = -level; 2075af69d88dSmrg break; 2076af69d88dSmrg 2077af69d88dSmrg default: 2078af69d88dSmrg /* check level */ 2079af69d88dSmrg if (level < 0 || level >= maxLevels) { 208001e04c3fSmrg reason = "level"; 208101e04c3fSmrg error = GL_INVALID_VALUE; 2082af69d88dSmrg goto error; 2083af69d88dSmrg } 2084af69d88dSmrg 2085af69d88dSmrg /* Figure out the expected texture size (in bytes). This will be 2086af69d88dSmrg * checked against the actual size later. 2087af69d88dSmrg */ 2088af69d88dSmrg expectedSize = compressed_tex_size(width, height, depth, internalFormat); 2089af69d88dSmrg break; 2090af69d88dSmrg } 2091af69d88dSmrg 2092af69d88dSmrg /* This should really never fail */ 2093af69d88dSmrg if (_mesa_base_tex_format(ctx, internalFormat) < 0) { 2094af69d88dSmrg reason = "internalFormat"; 2095af69d88dSmrg error = GL_INVALID_ENUM; 2096af69d88dSmrg goto error; 2097af69d88dSmrg } 2098af69d88dSmrg 2099af69d88dSmrg /* No compressed formats support borders at this time */ 2100af69d88dSmrg if (border != 0) { 2101af69d88dSmrg reason = "border != 0"; 21027ec681f3Smrg error = _mesa_is_desktop_gl(ctx) ? GL_INVALID_OPERATION : GL_INVALID_VALUE; 2103af69d88dSmrg goto error; 2104af69d88dSmrg } 2105af69d88dSmrg 2106af69d88dSmrg /* Check for invalid pixel storage modes */ 2107af69d88dSmrg if (!_mesa_compressed_pixel_storage_error_check(ctx, dimensions, 2108af69d88dSmrg &ctx->Unpack, 2109af69d88dSmrg "glCompressedTexImage")) { 2110af69d88dSmrg return GL_FALSE; 2111af69d88dSmrg } 2112af69d88dSmrg 2113af69d88dSmrg /* check image size in bytes */ 2114af69d88dSmrg if (expectedSize != imageSize) { 2115af69d88dSmrg /* Per GL_ARB_texture_compression: GL_INVALID_VALUE is generated [...] 2116af69d88dSmrg * if <imageSize> is not consistent with the format, dimensions, and 2117af69d88dSmrg * contents of the specified image. 2118af69d88dSmrg */ 211901e04c3fSmrg reason = "imageSize inconsistent with width/height/format"; 2120af69d88dSmrg error = GL_INVALID_VALUE; 2121af69d88dSmrg goto error; 2122af69d88dSmrg } 2123af69d88dSmrg 21247ec681f3Smrg if (!mutable_tex_object(texObj)) { 2125af69d88dSmrg reason = "immutable texture"; 2126af69d88dSmrg error = GL_INVALID_OPERATION; 2127af69d88dSmrg goto error; 2128af69d88dSmrg } 2129af69d88dSmrg 2130af69d88dSmrg return GL_FALSE; 2131af69d88dSmrg 2132af69d88dSmrgerror: 2133af69d88dSmrg /* Note: not all error paths exit through here. */ 213401e04c3fSmrg _mesa_error(ctx, error, "glCompressedTexImage%dD(%s)", 213501e04c3fSmrg dimensions, reason); 2136af69d88dSmrg return GL_TRUE; 2137af69d88dSmrg} 2138af69d88dSmrg 2139af69d88dSmrg 2140af69d88dSmrg 21417117f1b4Smrg/** 21427117f1b4Smrg * Test glTexSubImage[123]D() parameters for errors. 2143af69d88dSmrg * 21447117f1b4Smrg * \param ctx GL context. 21457117f1b4Smrg * \param dimensions texture image dimensions (must be 1, 2 or 3). 2146af69d88dSmrg * \param target texture target given by the user (already validated) 21477117f1b4Smrg * \param level image level given by the user. 21487117f1b4Smrg * \param xoffset sub-image x offset given by the user. 21497117f1b4Smrg * \param yoffset sub-image y offset given by the user. 21507117f1b4Smrg * \param zoffset sub-image z offset given by the user. 21517117f1b4Smrg * \param format pixel data format given by the user. 21527117f1b4Smrg * \param type pixel data type given by the user. 21537117f1b4Smrg * \param width image width given by the user. 21547117f1b4Smrg * \param height image height given by the user. 21557117f1b4Smrg * \param depth image depth given by the user. 2156af69d88dSmrg * 21577117f1b4Smrg * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 21587117f1b4Smrg * 21597117f1b4Smrg * Verifies each of the parameters against the constants specified in 21603464ebd5Sriastradh * __struct gl_contextRec::Const and the supported extensions, and according 21613464ebd5Sriastradh * to the OpenGL specification. 21627117f1b4Smrg */ 21637117f1b4Smrgstatic GLboolean 2164af69d88dSmrgtexsubimage_error_check(struct gl_context *ctx, GLuint dimensions, 216501e04c3fSmrg struct gl_texture_object *texObj, 21667117f1b4Smrg GLenum target, GLint level, 21677117f1b4Smrg GLint xoffset, GLint yoffset, GLint zoffset, 21687117f1b4Smrg GLint width, GLint height, GLint depth, 216901e04c3fSmrg GLenum format, GLenum type, const GLvoid *pixels, 217001e04c3fSmrg const char *callerName) 21717117f1b4Smrg{ 2172af69d88dSmrg struct gl_texture_image *texImage; 2173af69d88dSmrg GLenum err; 2174af69d88dSmrg 217501e04c3fSmrg if (!texObj) { 217601e04c3fSmrg /* must be out of memory */ 217701e04c3fSmrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s()", callerName); 21787117f1b4Smrg return GL_TRUE; 21797117f1b4Smrg } 21807117f1b4Smrg 2181af69d88dSmrg /* level check */ 2182af69d88dSmrg if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) { 218301e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(level=%d)", callerName, level); 21847117f1b4Smrg return GL_TRUE; 21857117f1b4Smrg } 2186af69d88dSmrg 218701e04c3fSmrg if (error_check_subtexture_negative_dimensions(ctx, dimensions, 218801e04c3fSmrg width, height, depth, 218901e04c3fSmrg callerName)) { 219001e04c3fSmrg return GL_TRUE; 219101e04c3fSmrg } 219201e04c3fSmrg 219301e04c3fSmrg texImage = _mesa_select_tex_image(texObj, target, level); 219401e04c3fSmrg if (!texImage) { 219501e04c3fSmrg /* non-existant texture level */ 219601e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid texture level %d)", 219701e04c3fSmrg callerName, level); 219801e04c3fSmrg return GL_TRUE; 2199af69d88dSmrg } 2200af69d88dSmrg 2201af69d88dSmrg err = _mesa_error_check_format_and_type(ctx, format, type); 2202af69d88dSmrg if (err != GL_NO_ERROR) { 2203af69d88dSmrg _mesa_error(ctx, err, 220401e04c3fSmrg "%s(incompatible format = %s, type = %s)", 220501e04c3fSmrg callerName, _mesa_enum_to_string(format), 220601e04c3fSmrg _mesa_enum_to_string(type)); 22077117f1b4Smrg return GL_TRUE; 22087117f1b4Smrg } 2209af69d88dSmrg 22107ec681f3Smrg if (!texture_formats_agree(texImage->InternalFormat, format)) { 22117ec681f3Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 22127ec681f3Smrg "%s(incompatible internalFormat = %s, format = %s)", 22137ec681f3Smrg callerName, 22147ec681f3Smrg _mesa_enum_to_string(texImage->InternalFormat), 22157ec681f3Smrg _mesa_enum_to_string(format)); 22167ec681f3Smrg return GL_TRUE; 22177ec681f3Smrg } 22187ec681f3Smrg 221901e04c3fSmrg GLenum internalFormat = _mesa_is_gles(ctx) ? 222001e04c3fSmrg oes_float_internal_format(ctx, texImage->InternalFormat, type) : 222101e04c3fSmrg texImage->InternalFormat; 222201e04c3fSmrg 222301e04c3fSmrg /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the 222401e04c3fSmrg * combinations of format, internalFormat, and type that can be used. 222501e04c3fSmrg * Formats and types that require additional extensions (e.g., GL_FLOAT 222601e04c3fSmrg * requires GL_OES_texture_float) are filtered elsewhere. 222701e04c3fSmrg */ 222801e04c3fSmrg if (_mesa_is_gles(ctx) && 222901e04c3fSmrg texture_format_error_check_gles(ctx, format, type, 223001e04c3fSmrg internalFormat, callerName)) { 22317117f1b4Smrg return GL_TRUE; 22327117f1b4Smrg } 22337117f1b4Smrg 223401e04c3fSmrg /* validate the bound PBO, if any */ 223501e04c3fSmrg if (!_mesa_validate_pbo_source(ctx, dimensions, &ctx->Unpack, 223601e04c3fSmrg width, height, depth, format, type, 223701e04c3fSmrg INT_MAX, pixels, callerName)) { 22387117f1b4Smrg return GL_TRUE; 22397117f1b4Smrg } 22407117f1b4Smrg 224101e04c3fSmrg if (error_check_subtexture_dimensions(ctx, dimensions, 224201e04c3fSmrg texImage, xoffset, yoffset, zoffset, 224301e04c3fSmrg width, height, depth, callerName)) { 2244af69d88dSmrg return GL_TRUE; 2245af69d88dSmrg } 22467117f1b4Smrg 2247af69d88dSmrg if (_mesa_is_format_compressed(texImage->TexFormat)) { 224801e04c3fSmrg if (_mesa_format_no_online_compression(texImage->InternalFormat)) { 2249af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 225001e04c3fSmrg "%s(no compression for format)", callerName); 22517117f1b4Smrg return GL_TRUE; 22527117f1b4Smrg } 22537117f1b4Smrg } 22547117f1b4Smrg 2255af69d88dSmrg if (ctx->Version >= 30 || ctx->Extensions.EXT_texture_integer) { 2256af69d88dSmrg /* both source and dest must be integer-valued, or neither */ 2257af69d88dSmrg if (_mesa_is_format_integer_color(texImage->TexFormat) != 2258af69d88dSmrg _mesa_is_enum_format_integer(format)) { 22597117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 226001e04c3fSmrg "%s(integer/non-integer format mismatch)", callerName); 22617117f1b4Smrg return GL_TRUE; 22627117f1b4Smrg } 22637117f1b4Smrg } 22647117f1b4Smrg 22657117f1b4Smrg return GL_FALSE; 22667117f1b4Smrg} 22677117f1b4Smrg 22687117f1b4Smrg 22697117f1b4Smrg/** 22707117f1b4Smrg * Test glCopyTexImage[12]D() parameters for errors. 2271af69d88dSmrg * 22727117f1b4Smrg * \param ctx GL context. 22737117f1b4Smrg * \param dimensions texture image dimensions (must be 1, 2 or 3). 22747117f1b4Smrg * \param target texture target given by the user. 22757117f1b4Smrg * \param level image level given by the user. 22767117f1b4Smrg * \param internalFormat internal format given by the user. 22777117f1b4Smrg * \param width image width given by the user. 22787117f1b4Smrg * \param height image height given by the user. 22797117f1b4Smrg * \param border texture border. 2280af69d88dSmrg * 22817117f1b4Smrg * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 2282af69d88dSmrg * 22837117f1b4Smrg * Verifies each of the parameters against the constants specified in 22843464ebd5Sriastradh * __struct gl_contextRec::Const and the supported extensions, and according 22853464ebd5Sriastradh * to the OpenGL specification. 22867117f1b4Smrg */ 22877117f1b4Smrgstatic GLboolean 22883464ebd5Sriastradhcopytexture_error_check( struct gl_context *ctx, GLuint dimensions, 22897ec681f3Smrg GLenum target, struct gl_texture_object* texObj, 22907ec681f3Smrg GLint level, GLint internalFormat, GLint border ) 22917117f1b4Smrg{ 2292af69d88dSmrg GLint baseFormat; 2293af69d88dSmrg GLint rb_base_format; 2294af69d88dSmrg struct gl_renderbuffer *rb; 2295af69d88dSmrg GLenum rb_internal_format; 22967117f1b4Smrg 22973464ebd5Sriastradh /* check target */ 229801e04c3fSmrg if (!legal_texsubimage_target(ctx, dimensions, target, false)) { 22993464ebd5Sriastradh _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexImage%uD(target=%s)", 230001e04c3fSmrg dimensions, _mesa_enum_to_string(target)); 23013464ebd5Sriastradh return GL_TRUE; 2302af69d88dSmrg } 23033464ebd5Sriastradh 2304af69d88dSmrg /* level check */ 2305af69d88dSmrg if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) { 23067117f1b4Smrg _mesa_error(ctx, GL_INVALID_VALUE, 23077117f1b4Smrg "glCopyTexImage%dD(level=%d)", dimensions, level); 23087117f1b4Smrg return GL_TRUE; 23097117f1b4Smrg } 23107117f1b4Smrg 23117117f1b4Smrg /* Check that the source buffer is complete */ 2312af69d88dSmrg if (_mesa_is_user_fbo(ctx->ReadBuffer)) { 23133464ebd5Sriastradh if (ctx->ReadBuffer->_Status == 0) { 23143464ebd5Sriastradh _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer); 23153464ebd5Sriastradh } 23167117f1b4Smrg if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 23177117f1b4Smrg _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 23187117f1b4Smrg "glCopyTexImage%dD(invalid readbuffer)", dimensions); 23197117f1b4Smrg return GL_TRUE; 23207117f1b4Smrg } 2321af69d88dSmrg 2322af69d88dSmrg if (ctx->ReadBuffer->Visual.samples > 0) { 232301e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 232401e04c3fSmrg "glCopyTexImage%dD(multisample FBO)", dimensions); 232501e04c3fSmrg return GL_TRUE; 2326af69d88dSmrg } 23277117f1b4Smrg } 23287117f1b4Smrg 23297117f1b4Smrg /* Check border */ 23307117f1b4Smrg if (border < 0 || border > 1 || 2331af69d88dSmrg ((ctx->API != API_OPENGL_COMPAT || 2332af69d88dSmrg target == GL_TEXTURE_RECTANGLE_NV || 23337117f1b4Smrg target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) { 2334af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 2335af69d88dSmrg "glCopyTexImage%dD(border=%d)", dimensions, border); 23367117f1b4Smrg return GL_TRUE; 23377117f1b4Smrg } 23387117f1b4Smrg 2339af69d88dSmrg /* OpenGL ES 1.x and OpenGL ES 2.0 impose additional restrictions on the 2340af69d88dSmrg * internalFormat. 2341af69d88dSmrg */ 2342af69d88dSmrg if (_mesa_is_gles(ctx) && !_mesa_is_gles3(ctx)) { 2343af69d88dSmrg switch (internalFormat) { 2344af69d88dSmrg case GL_ALPHA: 2345af69d88dSmrg case GL_RGB: 2346af69d88dSmrg case GL_RGBA: 2347af69d88dSmrg case GL_LUMINANCE: 2348af69d88dSmrg case GL_LUMINANCE_ALPHA: 23497ec681f3Smrg 23507ec681f3Smrg /* Added by GL_OES_required_internalformat (always enabled) in table 3.4.y.*/ 23517ec681f3Smrg case GL_ALPHA8: 23527ec681f3Smrg case GL_LUMINANCE8: 23537ec681f3Smrg case GL_LUMINANCE8_ALPHA8: 23547ec681f3Smrg case GL_LUMINANCE4_ALPHA4: 23557ec681f3Smrg case GL_RGB565: 23567ec681f3Smrg case GL_RGB8: 23577ec681f3Smrg case GL_RGBA4: 23587ec681f3Smrg case GL_RGB5_A1: 23597ec681f3Smrg case GL_RGBA8: 23607ec681f3Smrg case GL_DEPTH_COMPONENT16: 23617ec681f3Smrg case GL_DEPTH_COMPONENT24: 23627ec681f3Smrg case GL_DEPTH_COMPONENT32: 23637ec681f3Smrg case GL_DEPTH24_STENCIL8: 23647ec681f3Smrg case GL_RGB10: 23657ec681f3Smrg case GL_RGB10_A2: 2366af69d88dSmrg break; 23677ec681f3Smrg 2368af69d88dSmrg default: 236901e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, 2370af69d88dSmrg "glCopyTexImage%dD(internalFormat=%s)", dimensions, 237101e04c3fSmrg _mesa_enum_to_string(internalFormat)); 237201e04c3fSmrg return GL_TRUE; 237301e04c3fSmrg } 237401e04c3fSmrg } else { 237501e04c3fSmrg /* 237601e04c3fSmrg * Section 8.6 (Alternate Texture Image Specification Commands) of the 237701e04c3fSmrg * OpenGL 4.5 (Compatibility Profile) spec says: 237801e04c3fSmrg * 237901e04c3fSmrg * "Parameters level, internalformat, and border are specified using 238001e04c3fSmrg * the same values, with the same meanings, as the corresponding 238101e04c3fSmrg * arguments of TexImage2D, except that internalformat may not be 238201e04c3fSmrg * specified as 1, 2, 3, or 4." 238301e04c3fSmrg */ 238401e04c3fSmrg if (internalFormat >= 1 && internalFormat <= 4) { 238501e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, 238601e04c3fSmrg "glCopyTexImage%dD(internalFormat=%d)", dimensions, 238701e04c3fSmrg internalFormat); 2388af69d88dSmrg return GL_TRUE; 2389af69d88dSmrg } 2390af69d88dSmrg } 2391af69d88dSmrg 2392af69d88dSmrg baseFormat = _mesa_base_tex_format(ctx, internalFormat); 2393af69d88dSmrg if (baseFormat < 0) { 239401e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, 2395af69d88dSmrg "glCopyTexImage%dD(internalFormat=%s)", dimensions, 239601e04c3fSmrg _mesa_enum_to_string(internalFormat)); 239701e04c3fSmrg return GL_TRUE; 239801e04c3fSmrg } 239901e04c3fSmrg 240001e04c3fSmrg rb = _mesa_get_read_renderbuffer_for_format(ctx, internalFormat); 240101e04c3fSmrg if (rb == NULL) { 240201e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 240301e04c3fSmrg "glCopyTexImage%dD(read buffer)", dimensions); 24047117f1b4Smrg return GL_TRUE; 24057117f1b4Smrg } 24067117f1b4Smrg 2407af69d88dSmrg rb_internal_format = rb->InternalFormat; 2408af69d88dSmrg rb_base_format = _mesa_base_tex_format(ctx, rb->InternalFormat); 2409af69d88dSmrg if (_mesa_is_color_format(internalFormat)) { 2410af69d88dSmrg if (rb_base_format < 0) { 2411af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 2412af69d88dSmrg "glCopyTexImage%dD(internalFormat=%s)", dimensions, 241301e04c3fSmrg _mesa_enum_to_string(internalFormat)); 2414af69d88dSmrg return GL_TRUE; 2415af69d88dSmrg } 2416af69d88dSmrg } 2417af69d88dSmrg 2418af69d88dSmrg if (_mesa_is_gles(ctx)) { 2419af69d88dSmrg bool valid = true; 242001e04c3fSmrg if (_mesa_components_in_format(baseFormat) > 242101e04c3fSmrg _mesa_components_in_format(rb_base_format)) { 2422af69d88dSmrg valid = false; 2423af69d88dSmrg } 2424af69d88dSmrg if (baseFormat == GL_DEPTH_COMPONENT || 2425af69d88dSmrg baseFormat == GL_DEPTH_STENCIL || 242601e04c3fSmrg baseFormat == GL_STENCIL_INDEX || 2427af69d88dSmrg rb_base_format == GL_DEPTH_COMPONENT || 2428af69d88dSmrg rb_base_format == GL_DEPTH_STENCIL || 242901e04c3fSmrg rb_base_format == GL_STENCIL_INDEX || 2430af69d88dSmrg ((baseFormat == GL_LUMINANCE_ALPHA || 2431af69d88dSmrg baseFormat == GL_ALPHA) && 2432af69d88dSmrg rb_base_format != GL_RGBA) || 2433af69d88dSmrg internalFormat == GL_RGB9_E5) { 2434af69d88dSmrg valid = false; 2435af69d88dSmrg } 2436af69d88dSmrg if (internalFormat == GL_RGB9_E5) { 2437af69d88dSmrg valid = false; 2438af69d88dSmrg } 2439af69d88dSmrg if (!valid) { 2440af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 2441af69d88dSmrg "glCopyTexImage%dD(internalFormat=%s)", dimensions, 244201e04c3fSmrg _mesa_enum_to_string(internalFormat)); 2443af69d88dSmrg return GL_TRUE; 2444af69d88dSmrg } 2445af69d88dSmrg } 24467117f1b4Smrg 2447af69d88dSmrg if (_mesa_is_gles3(ctx)) { 24487ec681f3Smrg bool rb_is_srgb = (ctx->Extensions.EXT_sRGB && 24497ec681f3Smrg _mesa_is_format_srgb(rb->Format)); 2450af69d88dSmrg bool dst_is_srgb = false; 24517117f1b4Smrg 2452af69d88dSmrg if (_mesa_get_linear_internalformat(internalFormat) != internalFormat) { 2453af69d88dSmrg dst_is_srgb = true; 2454af69d88dSmrg } 2455af69d88dSmrg 2456af69d88dSmrg if (rb_is_srgb != dst_is_srgb) { 2457af69d88dSmrg /* Page 137 (page 149 of the PDF) in section 3.8.5 of the 2458af69d88dSmrg * OpenGLES 3.0.0 spec says: 2459af69d88dSmrg * 2460af69d88dSmrg * "The error INVALID_OPERATION is also generated if the 2461af69d88dSmrg * value of FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING for the 2462af69d88dSmrg * framebuffer attachment corresponding to the read buffer 2463af69d88dSmrg * is LINEAR (see section 6.1.13) and internalformat is 2464af69d88dSmrg * one of the sRGB formats described in section 3.8.16, or 2465af69d88dSmrg * if the value of FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING is 2466af69d88dSmrg * SRGB and internalformat is not one of the sRGB formats." 2467af69d88dSmrg */ 2468af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 2469af69d88dSmrg "glCopyTexImage%dD(srgb usage mismatch)", dimensions); 2470af69d88dSmrg return GL_TRUE; 24717117f1b4Smrg } 2472af69d88dSmrg 2473af69d88dSmrg /* Page 139, Table 3.15 of OpenGL ES 3.0 spec does not define ReadPixels 2474af69d88dSmrg * types for SNORM formats. Also, conversion to SNORM formats is not 2475af69d88dSmrg * allowed by Table 3.2 on Page 110. 2476af69d88dSmrg */ 247701e04c3fSmrg if (!_mesa_has_EXT_render_snorm(ctx) && 247801e04c3fSmrg _mesa_is_enum_format_snorm(internalFormat)) { 2479af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 2480af69d88dSmrg "glCopyTexImage%dD(internalFormat=%s)", dimensions, 248101e04c3fSmrg _mesa_enum_to_string(internalFormat)); 2482af69d88dSmrg return GL_TRUE; 2483af69d88dSmrg } 2484af69d88dSmrg } 2485af69d88dSmrg 2486af69d88dSmrg if (!_mesa_source_buffer_exists(ctx, baseFormat)) { 2487af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 2488af69d88dSmrg "glCopyTexImage%dD(missing readbuffer)", dimensions); 24897117f1b4Smrg return GL_TRUE; 24907117f1b4Smrg } 24917117f1b4Smrg 2492af69d88dSmrg /* From the EXT_texture_integer spec: 2493af69d88dSmrg * 2494af69d88dSmrg * "INVALID_OPERATION is generated by CopyTexImage* and CopyTexSubImage* 2495af69d88dSmrg * if the texture internalformat is an integer format and the read color 2496af69d88dSmrg * buffer is not an integer format, or if the internalformat is not an 2497af69d88dSmrg * integer format and the read color buffer is an integer format." 2498af69d88dSmrg */ 2499af69d88dSmrg if (_mesa_is_color_format(internalFormat)) { 2500af69d88dSmrg bool is_int = _mesa_is_enum_format_integer(internalFormat); 2501af69d88dSmrg bool is_rbint = _mesa_is_enum_format_integer(rb_internal_format); 2502af69d88dSmrg bool is_unorm = _mesa_is_enum_format_unorm(internalFormat); 2503af69d88dSmrg bool is_rbunorm = _mesa_is_enum_format_unorm(rb_internal_format); 2504af69d88dSmrg if (is_int || is_rbint) { 2505af69d88dSmrg if (is_int != is_rbint) { 2506af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 2507af69d88dSmrg "glCopyTexImage%dD(integer vs non-integer)", dimensions); 2508af69d88dSmrg return GL_TRUE; 2509af69d88dSmrg } else if (_mesa_is_gles(ctx) && 2510af69d88dSmrg _mesa_is_enum_format_unsigned_int(internalFormat) != 2511af69d88dSmrg _mesa_is_enum_format_unsigned_int(rb_internal_format)) { 2512af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 251301e04c3fSmrg "glCopyTexImage%dD(signed vs unsigned integer)", 251401e04c3fSmrg dimensions); 2515af69d88dSmrg return GL_TRUE; 2516af69d88dSmrg } 2517af69d88dSmrg } 2518af69d88dSmrg 2519af69d88dSmrg /* From page 138 of OpenGL ES 3.0 spec: 2520af69d88dSmrg * "The error INVALID_OPERATION is generated if floating-point RGBA 2521af69d88dSmrg * data is required; if signed integer RGBA data is required and the 2522af69d88dSmrg * format of the current color buffer is not signed integer; if 2523af69d88dSmrg * unsigned integer RGBA data is required and the format of the 2524af69d88dSmrg * current color buffer is not unsigned integer; or if fixed-point 2525af69d88dSmrg * RGBA data is required and the format of the current color buffer 2526af69d88dSmrg * is not fixed-point. 2527af69d88dSmrg */ 2528af69d88dSmrg if (_mesa_is_gles(ctx) && is_unorm != is_rbunorm) 2529af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 2530af69d88dSmrg "glCopyTexImage%dD(unorm vs non-unorm)", dimensions); 2531af69d88dSmrg } 2532af69d88dSmrg 25333464ebd5Sriastradh if (_mesa_is_compressed_format(ctx, internalFormat)) { 253401e04c3fSmrg GLenum err; 253501e04c3fSmrg if (!_mesa_target_can_be_compressed(ctx, target, internalFormat, &err)) { 253601e04c3fSmrg _mesa_error(ctx, err, 253701e04c3fSmrg "glCopyTexImage%dD(target can't be compressed)", dimensions); 25387117f1b4Smrg return GL_TRUE; 25397117f1b4Smrg } 254001e04c3fSmrg if (_mesa_format_no_online_compression(internalFormat)) { 25417117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 2542af69d88dSmrg "glCopyTexImage%dD(no compression for format)", dimensions); 25437117f1b4Smrg return GL_TRUE; 25447117f1b4Smrg } 2545af69d88dSmrg if (border != 0) { 25467117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 2547af69d88dSmrg "glCopyTexImage%dD(border!=0)", dimensions); 25487117f1b4Smrg return GL_TRUE; 25497117f1b4Smrg } 25507117f1b4Smrg } 2551af69d88dSmrg 25527ec681f3Smrg if (!mutable_tex_object(texObj)) { 2553af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 2554af69d88dSmrg "glCopyTexImage%dD(immutable texture)", dimensions); 2555af69d88dSmrg return GL_TRUE; 25567117f1b4Smrg } 25577117f1b4Smrg 25587117f1b4Smrg /* if we get here, the parameters are OK */ 25597117f1b4Smrg return GL_FALSE; 25607117f1b4Smrg} 25617117f1b4Smrg 25627117f1b4Smrg 25637117f1b4Smrg/** 25647117f1b4Smrg * Test glCopyTexSubImage[12]D() parameters for errors. 25657117f1b4Smrg * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 25667117f1b4Smrg */ 25677117f1b4Smrgstatic GLboolean 2568af69d88dSmrgcopytexsubimage_error_check(struct gl_context *ctx, GLuint dimensions, 256901e04c3fSmrg const struct gl_texture_object *texObj, 2570af69d88dSmrg GLenum target, GLint level, 2571af69d88dSmrg GLint xoffset, GLint yoffset, GLint zoffset, 257201e04c3fSmrg GLint width, GLint height, const char *caller) 25737117f1b4Smrg{ 257401e04c3fSmrg assert(texObj); 257501e04c3fSmrg 2576af69d88dSmrg struct gl_texture_image *texImage; 2577af69d88dSmrg 25787117f1b4Smrg /* Check that the source buffer is complete */ 2579af69d88dSmrg if (_mesa_is_user_fbo(ctx->ReadBuffer)) { 25803464ebd5Sriastradh if (ctx->ReadBuffer->_Status == 0) { 25813464ebd5Sriastradh _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer); 25823464ebd5Sriastradh } 25837117f1b4Smrg if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 25847117f1b4Smrg _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 258501e04c3fSmrg "%s(invalid readbuffer)", caller); 25867117f1b4Smrg return GL_TRUE; 25877117f1b4Smrg } 2588af69d88dSmrg 2589af69d88dSmrg if (ctx->ReadBuffer->Visual.samples > 0) { 259001e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 259101e04c3fSmrg "%s(multisample FBO)", caller); 259201e04c3fSmrg return GL_TRUE; 2593af69d88dSmrg } 25947117f1b4Smrg } 25957117f1b4Smrg 25967117f1b4Smrg /* Check level */ 2597af69d88dSmrg if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) { 259801e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(level=%d)", caller, level); 25997117f1b4Smrg return GL_TRUE; 26007117f1b4Smrg } 26017117f1b4Smrg 260201e04c3fSmrg texImage = _mesa_select_tex_image(texObj, target, level); 2603af69d88dSmrg if (!texImage) { 2604af69d88dSmrg /* destination image does not exist */ 2605af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 260601e04c3fSmrg "%s(invalid texture level %d)", caller, level); 2607c1f859d4Smrg return GL_TRUE; 2608c1f859d4Smrg } 2609c1f859d4Smrg 261001e04c3fSmrg if (error_check_subtexture_negative_dimensions(ctx, dimensions, 261101e04c3fSmrg width, height, 1, caller)) { 261201e04c3fSmrg return GL_TRUE; 261301e04c3fSmrg } 261401e04c3fSmrg 261501e04c3fSmrg if (error_check_subtexture_dimensions(ctx, dimensions, texImage, 2616af69d88dSmrg xoffset, yoffset, zoffset, 261701e04c3fSmrg width, height, 1, caller)) { 26187117f1b4Smrg return GL_TRUE; 26197117f1b4Smrg } 26207117f1b4Smrg 2621af69d88dSmrg if (_mesa_is_format_compressed(texImage->TexFormat)) { 262201e04c3fSmrg if (_mesa_format_no_online_compression(texImage->InternalFormat)) { 2623af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 262401e04c3fSmrg "%s(no compression for format)", caller); 26257117f1b4Smrg return GL_TRUE; 26267117f1b4Smrg } 26277117f1b4Smrg } 26287117f1b4Smrg 2629af69d88dSmrg if (texImage->InternalFormat == GL_YCBCR_MESA) { 263001e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s()", caller); 263101e04c3fSmrg return GL_TRUE; 263201e04c3fSmrg } 263301e04c3fSmrg 263401e04c3fSmrg /* From OpenGL ES 3.2 spec, section 8.6: 263501e04c3fSmrg * 263601e04c3fSmrg * "An INVALID_OPERATION error is generated by CopyTexSubImage3D, 263701e04c3fSmrg * CopyTexImage2D, or CopyTexSubImage2D if the internalformat of the 263801e04c3fSmrg * texture image being (re)specified is RGB9_E5" 263901e04c3fSmrg */ 264001e04c3fSmrg if (texImage->InternalFormat == GL_RGB9_E5 && 264101e04c3fSmrg !_mesa_is_desktop_gl(ctx)) { 264201e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 264301e04c3fSmrg "%s(invalid internal format %s)", caller, 264401e04c3fSmrg _mesa_enum_to_string(texImage->InternalFormat)); 26457117f1b4Smrg return GL_TRUE; 26467117f1b4Smrg } 26477117f1b4Smrg 2648af69d88dSmrg if (!_mesa_source_buffer_exists(ctx, texImage->_BaseFormat)) { 26497117f1b4Smrg _mesa_error(ctx, GL_INVALID_OPERATION, 265001e04c3fSmrg "%s(missing readbuffer, format=%s)", caller, 265101e04c3fSmrg _mesa_enum_to_string(texImage->_BaseFormat)); 26527117f1b4Smrg return GL_TRUE; 26537117f1b4Smrg } 26547117f1b4Smrg 2655af69d88dSmrg /* From the EXT_texture_integer spec: 2656af69d88dSmrg * 265701e04c3fSmrg * "INVALID_OPERATION is generated by CopyTexImage* and 265801e04c3fSmrg * CopyTexSubImage* if the texture internalformat is an integer format 265901e04c3fSmrg * and the read color buffer is not an integer format, or if the 266001e04c3fSmrg * internalformat is not an integer format and the read color buffer 266101e04c3fSmrg * is an integer format." 26623464ebd5Sriastradh */ 2663af69d88dSmrg if (_mesa_is_color_format(texImage->InternalFormat)) { 26643464ebd5Sriastradh struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer; 2665af69d88dSmrg 2666af69d88dSmrg if (_mesa_is_format_integer_color(rb->Format) != 266701e04c3fSmrg _mesa_is_format_integer_color(texImage->TexFormat)) { 266801e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 266901e04c3fSmrg "%s(integer vs non-integer)", caller); 267001e04c3fSmrg return GL_TRUE; 26713464ebd5Sriastradh } 26723464ebd5Sriastradh } 26733464ebd5Sriastradh 267401e04c3fSmrg /* In the ES 3.2 specification's Table 8.13 (Valid CopyTexImage source 267501e04c3fSmrg * framebuffer/destination texture base internal format combinations), 267601e04c3fSmrg * all the entries for stencil are left blank (unsupported). 267701e04c3fSmrg */ 267801e04c3fSmrg if (_mesa_is_gles(ctx) && _mesa_is_stencil_format(texImage->_BaseFormat)) { 267901e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(stencil disallowed)", caller); 268001e04c3fSmrg return GL_TRUE; 268101e04c3fSmrg } 268201e04c3fSmrg 26837117f1b4Smrg /* if we get here, the parameters are OK */ 26847117f1b4Smrg return GL_FALSE; 26857117f1b4Smrg} 26867117f1b4Smrg 26877117f1b4Smrg 26884a49301eSmrg/** Callback info for walking over FBO hash table */ 26894a49301eSmrgstruct cb_info 26907117f1b4Smrg{ 26913464ebd5Sriastradh struct gl_context *ctx; 26927117f1b4Smrg struct gl_texture_object *texObj; 26934a49301eSmrg GLuint level, face; 26944a49301eSmrg}; 26957117f1b4Smrg 26967117f1b4Smrg 26977117f1b4Smrg/** 26984a49301eSmrg * Check render to texture callback. Called from _mesa_HashWalk(). 26997117f1b4Smrg */ 27007117f1b4Smrgstatic void 27017ec681f3Smrgcheck_rtt_cb(void *data, void *userData) 27027117f1b4Smrg{ 27034a49301eSmrg struct gl_framebuffer *fb = (struct gl_framebuffer *) data; 27044a49301eSmrg const struct cb_info *info = (struct cb_info *) userData; 27053464ebd5Sriastradh struct gl_context *ctx = info->ctx; 27064a49301eSmrg const struct gl_texture_object *texObj = info->texObj; 27074a49301eSmrg const GLuint level = info->level, face = info->face; 27084a49301eSmrg 27094a49301eSmrg /* If this is a user-created FBO */ 2710af69d88dSmrg if (_mesa_is_user_fbo(fb)) { 27117117f1b4Smrg GLuint i; 27124a49301eSmrg /* check if any of the FBO's attachments point to 'texObj' */ 27137117f1b4Smrg for (i = 0; i < BUFFER_COUNT; i++) { 27144a49301eSmrg struct gl_renderbuffer_attachment *att = fb->Attachment + i; 27157117f1b4Smrg if (att->Type == GL_TEXTURE && 27167117f1b4Smrg att->Texture == texObj && 27177117f1b4Smrg att->TextureLevel == level && 27187117f1b4Smrg att->CubeMapFace == face) { 271901e04c3fSmrg _mesa_update_texture_renderbuffer(ctx, fb, att); 272001e04c3fSmrg assert(att->Renderbuffer->TexImage); 27214a49301eSmrg /* Mark fb status as indeterminate to force re-validation */ 27224a49301eSmrg fb->_Status = 0; 272301e04c3fSmrg 272401e04c3fSmrg /* Make sure that the revalidation actually happens if this is 272501e04c3fSmrg * being done to currently-bound buffers. 272601e04c3fSmrg */ 272701e04c3fSmrg if (fb == ctx->DrawBuffer || fb == ctx->ReadBuffer) 272801e04c3fSmrg ctx->NewState |= _NEW_BUFFERS; 27297117f1b4Smrg } 27307117f1b4Smrg } 27317117f1b4Smrg } 27327117f1b4Smrg} 27337117f1b4Smrg 27347117f1b4Smrg 27354a49301eSmrg/** 27364a49301eSmrg * When a texture image is specified we have to check if it's bound to 27374a49301eSmrg * any framebuffer objects (render to texture) in order to detect changes 27384a49301eSmrg * in size or format since that effects FBO completeness. 27394a49301eSmrg * Any FBOs rendering into the texture must be re-validated. 27404a49301eSmrg */ 2741af69d88dSmrgvoid 2742af69d88dSmrg_mesa_update_fbo_texture(struct gl_context *ctx, 2743af69d88dSmrg struct gl_texture_object *texObj, 2744af69d88dSmrg GLuint face, GLuint level) 27454a49301eSmrg{ 27464a49301eSmrg /* Only check this texture if it's been marked as RenderToTexture */ 27474a49301eSmrg if (texObj->_RenderToTexture) { 27484a49301eSmrg struct cb_info info; 27494a49301eSmrg info.ctx = ctx; 27504a49301eSmrg info.texObj = texObj; 27514a49301eSmrg info.level = level; 27524a49301eSmrg info.face = face; 27534a49301eSmrg _mesa_HashWalk(ctx->Shared->FrameBuffers, check_rtt_cb, &info); 27544a49301eSmrg } 27554a49301eSmrg} 27564a49301eSmrg 27574a49301eSmrg 27584a49301eSmrg/** 27594a49301eSmrg * If the texture object's GenerateMipmap flag is set and we've 27604a49301eSmrg * changed the texture base level image, regenerate the rest of the 27614a49301eSmrg * mipmap levels now. 27624a49301eSmrg */ 2763af69d88dSmrgstatic inline void 27643464ebd5Sriastradhcheck_gen_mipmap(struct gl_context *ctx, GLenum target, 27654a49301eSmrg struct gl_texture_object *texObj, GLint level) 27664a49301eSmrg{ 27677ec681f3Smrg if (texObj->Attrib.GenerateMipmap && 27687ec681f3Smrg level == texObj->Attrib.BaseLevel && 27697ec681f3Smrg level < texObj->Attrib.MaxLevel) { 277001e04c3fSmrg assert(ctx->Driver.GenerateMipmap); 27714a49301eSmrg ctx->Driver.GenerateMipmap(ctx, target, texObj); 27724a49301eSmrg } 27734a49301eSmrg} 27744a49301eSmrg 27754a49301eSmrg 27764a49301eSmrg/** Debug helper: override the user-requested internal format */ 27774a49301eSmrgstatic GLenum 277801e04c3fSmrgoverride_internal_format(GLenum internalFormat, UNUSED GLint width, 277901e04c3fSmrg UNUSED GLint height) 27804a49301eSmrg{ 27814a49301eSmrg#if 0 27824a49301eSmrg if (internalFormat == GL_RGBA16F_ARB || 27834a49301eSmrg internalFormat == GL_RGBA32F_ARB) { 27844a49301eSmrg printf("Convert rgba float tex to int %d x %d\n", width, height); 27854a49301eSmrg return GL_RGBA; 27864a49301eSmrg } 27874a49301eSmrg else if (internalFormat == GL_RGB16F_ARB || 27884a49301eSmrg internalFormat == GL_RGB32F_ARB) { 27894a49301eSmrg printf("Convert rgb float tex to int %d x %d\n", width, height); 27904a49301eSmrg return GL_RGB; 27914a49301eSmrg } 27924a49301eSmrg else if (internalFormat == GL_LUMINANCE_ALPHA16F_ARB || 27934a49301eSmrg internalFormat == GL_LUMINANCE_ALPHA32F_ARB) { 27944a49301eSmrg printf("Convert luminance float tex to int %d x %d\n", width, height); 27954a49301eSmrg return GL_LUMINANCE_ALPHA; 27964a49301eSmrg } 27974a49301eSmrg else if (internalFormat == GL_LUMINANCE16F_ARB || 27984a49301eSmrg internalFormat == GL_LUMINANCE32F_ARB) { 27994a49301eSmrg printf("Convert luminance float tex to int %d x %d\n", width, height); 28004a49301eSmrg return GL_LUMINANCE; 28014a49301eSmrg } 28024a49301eSmrg else if (internalFormat == GL_ALPHA16F_ARB || 28034a49301eSmrg internalFormat == GL_ALPHA32F_ARB) { 28044a49301eSmrg printf("Convert luminance float tex to int %d x %d\n", width, height); 28054a49301eSmrg return GL_ALPHA; 28064a49301eSmrg } 28074a49301eSmrg /* 28084a49301eSmrg else if (internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) { 28094a49301eSmrg internalFormat = GL_RGBA; 28104a49301eSmrg } 28114a49301eSmrg */ 28124a49301eSmrg else { 28134a49301eSmrg return internalFormat; 28144a49301eSmrg } 28154a49301eSmrg#else 28164a49301eSmrg return internalFormat; 28174a49301eSmrg#endif 28184a49301eSmrg} 28194a49301eSmrg 28207117f1b4Smrg 28213464ebd5Sriastradh/** 28223464ebd5Sriastradh * Choose the actual hardware format for a texture image. 28233464ebd5Sriastradh * Try to use the same format as the previous image level when possible. 28243464ebd5Sriastradh * Otherwise, ask the driver for the best format. 28253464ebd5Sriastradh * It's important to try to choose a consistant format for all levels 28263464ebd5Sriastradh * for efficient texture memory layout/allocation. In particular, this 28273464ebd5Sriastradh * comes up during automatic mipmap generation. 28287117f1b4Smrg */ 2829af69d88dSmrgmesa_format 28303464ebd5Sriastradh_mesa_choose_texture_format(struct gl_context *ctx, 28313464ebd5Sriastradh struct gl_texture_object *texObj, 28323464ebd5Sriastradh GLenum target, GLint level, 28333464ebd5Sriastradh GLenum internalFormat, GLenum format, GLenum type) 28347117f1b4Smrg{ 2835af69d88dSmrg mesa_format f; 28363464ebd5Sriastradh 28373464ebd5Sriastradh /* see if we've already chosen a format for the previous level */ 28383464ebd5Sriastradh if (level > 0) { 28393464ebd5Sriastradh struct gl_texture_image *prevImage = 284001e04c3fSmrg _mesa_select_tex_image(texObj, target, level - 1); 28413464ebd5Sriastradh /* See if the prev level is defined and has an internal format which 28423464ebd5Sriastradh * matches the new internal format. 28433464ebd5Sriastradh */ 28443464ebd5Sriastradh if (prevImage && 28453464ebd5Sriastradh prevImage->Width > 0 && 28463464ebd5Sriastradh prevImage->InternalFormat == internalFormat) { 28473464ebd5Sriastradh /* use the same format */ 284801e04c3fSmrg assert(prevImage->TexFormat != MESA_FORMAT_NONE); 28493464ebd5Sriastradh return prevImage->TexFormat; 28503464ebd5Sriastradh } 28513464ebd5Sriastradh } 28523464ebd5Sriastradh 2853af69d88dSmrg f = ctx->Driver.ChooseTextureFormat(ctx, target, internalFormat, 2854af69d88dSmrg format, type); 285501e04c3fSmrg assert(f != MESA_FORMAT_NONE); 28563464ebd5Sriastradh return f; 28573464ebd5Sriastradh} 28583464ebd5Sriastradh 28593464ebd5Sriastradh 28603464ebd5Sriastradh/** 2861af69d88dSmrg * Adjust pixel unpack params and image dimensions to strip off the 2862af69d88dSmrg * one-pixel texture border. 2863af69d88dSmrg * 2864af69d88dSmrg * Gallium and intel don't support texture borders. They've seldem been used 2865af69d88dSmrg * and seldom been implemented correctly anyway. 2866af69d88dSmrg * 2867af69d88dSmrg * \param unpackNew returns the new pixel unpack parameters 2868af69d88dSmrg */ 2869af69d88dSmrgstatic void 2870af69d88dSmrgstrip_texture_border(GLenum target, 2871af69d88dSmrg GLint *width, GLint *height, GLint *depth, 2872af69d88dSmrg const struct gl_pixelstore_attrib *unpack, 2873af69d88dSmrg struct gl_pixelstore_attrib *unpackNew) 2874af69d88dSmrg{ 2875af69d88dSmrg assert(width); 2876af69d88dSmrg assert(height); 2877af69d88dSmrg assert(depth); 2878af69d88dSmrg 2879af69d88dSmrg *unpackNew = *unpack; 2880af69d88dSmrg 2881af69d88dSmrg if (unpackNew->RowLength == 0) 2882af69d88dSmrg unpackNew->RowLength = *width; 2883af69d88dSmrg 2884af69d88dSmrg if (unpackNew->ImageHeight == 0) 2885af69d88dSmrg unpackNew->ImageHeight = *height; 2886af69d88dSmrg 2887af69d88dSmrg assert(*width >= 3); 2888af69d88dSmrg unpackNew->SkipPixels++; /* skip the border */ 2889af69d88dSmrg *width = *width - 2; /* reduce the width by two border pixels */ 2890af69d88dSmrg 2891af69d88dSmrg /* The min height of a texture with a border is 3 */ 2892af69d88dSmrg if (*height >= 3 && target != GL_TEXTURE_1D_ARRAY) { 2893af69d88dSmrg unpackNew->SkipRows++; /* skip the border */ 2894af69d88dSmrg *height = *height - 2; /* reduce the height by two border pixels */ 2895af69d88dSmrg } 2896af69d88dSmrg 2897af69d88dSmrg if (*depth >= 3 && 2898af69d88dSmrg target != GL_TEXTURE_2D_ARRAY && 2899af69d88dSmrg target != GL_TEXTURE_CUBE_MAP_ARRAY) { 2900af69d88dSmrg unpackNew->SkipImages++; /* skip the border */ 2901af69d88dSmrg *depth = *depth - 2; /* reduce the depth by two border pixels */ 2902af69d88dSmrg } 2903af69d88dSmrg} 2904af69d88dSmrg 29057ec681f3Smrgstatic struct gl_texture_object * 29067ec681f3Smrglookup_texture_ext_dsa(struct gl_context *ctx, GLenum target, GLuint texture, 29077ec681f3Smrg const char *caller) 29087ec681f3Smrg{ 29097ec681f3Smrg GLenum boundTarget; 29107ec681f3Smrg switch (target) { 29117ec681f3Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 29127ec681f3Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 29137ec681f3Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 29147ec681f3Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 29157ec681f3Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 29167ec681f3Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 29177ec681f3Smrg boundTarget = GL_TEXTURE_CUBE_MAP; 29187ec681f3Smrg break; 29197ec681f3Smrg default: 29207ec681f3Smrg boundTarget = target; 29217ec681f3Smrg break; 29227ec681f3Smrg } 29237ec681f3Smrg 29247ec681f3Smrg int targetIndex = _mesa_tex_target_to_index(ctx, boundTarget); 29257ec681f3Smrg if (targetIndex < 0) { 29267ec681f3Smrg _mesa_error(ctx, GL_INVALID_ENUM, "%s(target = %s)", caller, 29277ec681f3Smrg _mesa_enum_to_string(target)); 29287ec681f3Smrg return NULL; 29297ec681f3Smrg } 29307ec681f3Smrg assert(targetIndex < NUM_TEXTURE_TARGETS); 29317ec681f3Smrg 29327ec681f3Smrg struct gl_texture_object *texObj; 29337ec681f3Smrg if (texture == 0) { 29347ec681f3Smrg /* Use a default texture object */ 29357ec681f3Smrg texObj = ctx->Shared->DefaultTex[targetIndex]; 29367ec681f3Smrg assert(texObj); 29377ec681f3Smrg } else { 29387ec681f3Smrg bool isGenName; 29397ec681f3Smrg texObj = _mesa_lookup_texture(ctx, texture); 29407ec681f3Smrg isGenName = texObj != NULL; 29417ec681f3Smrg if (!texObj && ctx->API == API_OPENGL_CORE) { 29427ec681f3Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(non-gen name)", caller); 29437ec681f3Smrg return NULL; 29447ec681f3Smrg } 29457ec681f3Smrg 29467ec681f3Smrg if (!texObj) { 29477ec681f3Smrg texObj = ctx->Driver.NewTextureObject(ctx, texture, boundTarget); 29487ec681f3Smrg if (!texObj) { 29497ec681f3Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller); 29507ec681f3Smrg return NULL; 29517ec681f3Smrg } 29527ec681f3Smrg 29537ec681f3Smrg /* insert into hash table */ 29547ec681f3Smrg _mesa_HashInsert(ctx->Shared->TexObjects, texObj->Name, texObj, isGenName); 29557ec681f3Smrg } 29567ec681f3Smrg 29577ec681f3Smrg if (texObj->Target != boundTarget) { 29587ec681f3Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(%s != %s)", 29597ec681f3Smrg caller, _mesa_enum_to_string(texObj->Target), 29607ec681f3Smrg _mesa_enum_to_string(target)); 29617ec681f3Smrg return NULL; 29627ec681f3Smrg } 29637ec681f3Smrg } 29647ec681f3Smrg 29657ec681f3Smrg return texObj; 29667ec681f3Smrg} 2967af69d88dSmrg 2968af69d88dSmrg/** 29697ec681f3Smrg * Common code to implement all the glTexImage1D/2D/3D functions, 29707ec681f3Smrg * glCompressedTexImage1D/2D/3D and glTextureImage1D/2D/3DEXT 2971af69d88dSmrg * \param compressed only GL_TRUE for glCompressedTexImage1D/2D/3D calls. 2972af69d88dSmrg * \param format the user's image format (only used if !compressed) 2973af69d88dSmrg * \param type the user's image type (only used if !compressed) 2974af69d88dSmrg * \param imageSize only used for glCompressedTexImage1D/2D/3D calls. 29753464ebd5Sriastradh */ 297601e04c3fSmrgstatic ALWAYS_INLINE void 2977af69d88dSmrgteximage(struct gl_context *ctx, GLboolean compressed, GLuint dims, 29787ec681f3Smrg struct gl_texture_object *texObj, 29793464ebd5Sriastradh GLenum target, GLint level, GLint internalFormat, 29803464ebd5Sriastradh GLsizei width, GLsizei height, GLsizei depth, 29813464ebd5Sriastradh GLint border, GLenum format, GLenum type, 298201e04c3fSmrg GLsizei imageSize, const GLvoid *pixels, bool no_error) 29833464ebd5Sriastradh{ 2984af69d88dSmrg const char *func = compressed ? "glCompressedTexImage" : "glTexImage"; 2985af69d88dSmrg struct gl_pixelstore_attrib unpack_no_border; 2986af69d88dSmrg const struct gl_pixelstore_attrib *unpack = &ctx->Unpack; 2987af69d88dSmrg mesa_format texFormat; 298801e04c3fSmrg bool dimensionsOK = true, sizeOK = true; 2989af69d88dSmrg 29907ec681f3Smrg FLUSH_VERTICES(ctx, 0, 0); 2991af69d88dSmrg 2992af69d88dSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) { 2993af69d88dSmrg if (compressed) 2994af69d88dSmrg _mesa_debug(ctx, 2995af69d88dSmrg "glCompressedTexImage%uD %s %d %s %d %d %d %d %p\n", 2996af69d88dSmrg dims, 299701e04c3fSmrg _mesa_enum_to_string(target), level, 299801e04c3fSmrg _mesa_enum_to_string(internalFormat), 2999af69d88dSmrg width, height, depth, border, pixels); 3000af69d88dSmrg else 3001af69d88dSmrg _mesa_debug(ctx, 3002af69d88dSmrg "glTexImage%uD %s %d %s %d %d %d %d %s %s %p\n", 3003af69d88dSmrg dims, 300401e04c3fSmrg _mesa_enum_to_string(target), level, 300501e04c3fSmrg _mesa_enum_to_string(internalFormat), 3006af69d88dSmrg width, height, depth, border, 300701e04c3fSmrg _mesa_enum_to_string(format), 300801e04c3fSmrg _mesa_enum_to_string(type), pixels); 30093464ebd5Sriastradh } 301001e04c3fSmrg 301101e04c3fSmrg internalFormat = override_internal_format(internalFormat, width, height); 301201e04c3fSmrg 30137ec681f3Smrg if (!no_error && 30147ec681f3Smrg /* target error checking */ 30157ec681f3Smrg !legal_teximage_target(ctx, dims, target)) { 30167ec681f3Smrg _mesa_error(ctx, GL_INVALID_ENUM, "%s%uD(target=%s)", 30177ec681f3Smrg func, dims, _mesa_enum_to_string(target)); 30187ec681f3Smrg return; 30197ec681f3Smrg } 30207ec681f3Smrg 30217ec681f3Smrg if (!texObj) 30227ec681f3Smrg texObj = _mesa_get_current_tex_object(ctx, target); 302301e04c3fSmrg 30247ec681f3Smrg if (!no_error) { 302501e04c3fSmrg /* general error checking */ 302601e04c3fSmrg if (compressed) { 30277ec681f3Smrg if (compressed_texture_error_check(ctx, dims, target, texObj, 30287ec681f3Smrg level, internalFormat, 302901e04c3fSmrg width, height, depth, 303001e04c3fSmrg border, imageSize, pixels)) 303101e04c3fSmrg return; 303201e04c3fSmrg } else { 30337ec681f3Smrg if (texture_error_check(ctx, dims, target, texObj, level, internalFormat, 303401e04c3fSmrg format, type, width, height, depth, border, 303501e04c3fSmrg pixels)) 303601e04c3fSmrg return; 303701e04c3fSmrg } 3038af69d88dSmrg } 30397ec681f3Smrg assert(texObj); 30407117f1b4Smrg 3041af69d88dSmrg /* Here we convert a cpal compressed image into a regular glTexImage2D 3042af69d88dSmrg * call by decompressing the texture. If we really want to support cpal 3043af69d88dSmrg * textures in any driver this would have to be changed. 3044af69d88dSmrg */ 3045af69d88dSmrg if (ctx->API == API_OPENGLES && compressed && dims == 2) { 3046af69d88dSmrg switch (internalFormat) { 3047af69d88dSmrg case GL_PALETTE4_RGB8_OES: 3048af69d88dSmrg case GL_PALETTE4_RGBA8_OES: 3049af69d88dSmrg case GL_PALETTE4_R5_G6_B5_OES: 3050af69d88dSmrg case GL_PALETTE4_RGBA4_OES: 3051af69d88dSmrg case GL_PALETTE4_RGB5_A1_OES: 3052af69d88dSmrg case GL_PALETTE8_RGB8_OES: 3053af69d88dSmrg case GL_PALETTE8_RGBA8_OES: 3054af69d88dSmrg case GL_PALETTE8_R5_G6_B5_OES: 3055af69d88dSmrg case GL_PALETTE8_RGBA4_OES: 3056af69d88dSmrg case GL_PALETTE8_RGB5_A1_OES: 3057af69d88dSmrg _mesa_cpal_compressed_teximage2d(target, level, internalFormat, 3058af69d88dSmrg width, height, imageSize, pixels); 3059af69d88dSmrg return; 3060af69d88dSmrg } 3061af69d88dSmrg } 3062af69d88dSmrg 3063af69d88dSmrg if (compressed) { 3064af69d88dSmrg /* For glCompressedTexImage() the driver has no choice about the 3065af69d88dSmrg * texture format since we'll never transcode the user's compressed 3066af69d88dSmrg * image data. The internalFormat was error checked earlier. 3067af69d88dSmrg */ 3068af69d88dSmrg texFormat = _mesa_glenum_to_compressed_format(internalFormat); 3069af69d88dSmrg } 3070af69d88dSmrg else { 307101e04c3fSmrg /* In case of HALF_FLOAT_OES or FLOAT_OES, find corresponding sized 307201e04c3fSmrg * internal floating point format for the given base format. 307301e04c3fSmrg */ 307401e04c3fSmrg if (_mesa_is_gles(ctx) && format == internalFormat) { 307501e04c3fSmrg if (type == GL_FLOAT) { 307601e04c3fSmrg texObj->_IsFloat = GL_TRUE; 307701e04c3fSmrg } else if (type == GL_HALF_FLOAT_OES || type == GL_HALF_FLOAT) { 307801e04c3fSmrg texObj->_IsHalfFloat = GL_TRUE; 307901e04c3fSmrg } 308001e04c3fSmrg 308101e04c3fSmrg internalFormat = adjust_for_oes_float_texture(ctx, format, type); 308201e04c3fSmrg } 308301e04c3fSmrg 3084af69d88dSmrg texFormat = _mesa_choose_texture_format(ctx, texObj, target, level, 3085af69d88dSmrg internalFormat, format, type); 3086af69d88dSmrg } 3087af69d88dSmrg 3088af69d88dSmrg assert(texFormat != MESA_FORMAT_NONE); 3089af69d88dSmrg 309001e04c3fSmrg if (!no_error) { 309101e04c3fSmrg /* check that width, height, depth are legal for the mipmap level */ 309201e04c3fSmrg dimensionsOK = _mesa_legal_texture_dimensions(ctx, target, level, width, 309301e04c3fSmrg height, depth, border); 3094af69d88dSmrg 309501e04c3fSmrg /* check that the texture won't take too much memory, etc */ 309601e04c3fSmrg sizeOK = ctx->Driver.TestProxyTexImage(ctx, proxy_target(target), 309701e04c3fSmrg 0, level, texFormat, 1, 309801e04c3fSmrg width, height, depth); 309901e04c3fSmrg } 3100af69d88dSmrg 3101af69d88dSmrg if (_mesa_is_proxy_texture(target)) { 3102af69d88dSmrg /* Proxy texture: just clear or set state depending on error checking */ 3103af69d88dSmrg struct gl_texture_image *texImage = 3104af69d88dSmrg get_proxy_tex_image(ctx, target, level); 3105af69d88dSmrg 3106af69d88dSmrg if (!texImage) 3107af69d88dSmrg return; /* GL_OUT_OF_MEMORY already recorded */ 3108af69d88dSmrg 3109af69d88dSmrg if (dimensionsOK && sizeOK) { 3110af69d88dSmrg _mesa_init_teximage_fields(ctx, texImage, width, height, depth, 3111af69d88dSmrg border, internalFormat, texFormat); 3112af69d88dSmrg } 3113af69d88dSmrg else { 3114af69d88dSmrg clear_teximage_fields(texImage); 3115af69d88dSmrg } 3116af69d88dSmrg } 3117af69d88dSmrg else { 3118af69d88dSmrg /* non-proxy target */ 3119af69d88dSmrg const GLuint face = _mesa_tex_target_to_face(target); 3120af69d88dSmrg struct gl_texture_image *texImage; 3121af69d88dSmrg 3122af69d88dSmrg if (!dimensionsOK) { 3123af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 312401e04c3fSmrg "%s%uD(invalid width=%d or height=%d or depth=%d)", 312501e04c3fSmrg func, dims, width, height, depth); 3126af69d88dSmrg return; 3127af69d88dSmrg } 3128af69d88dSmrg 3129af69d88dSmrg if (!sizeOK) { 3130af69d88dSmrg _mesa_error(ctx, GL_OUT_OF_MEMORY, 313101e04c3fSmrg "%s%uD(image too large: %d x %d x %d, %s format)", 313201e04c3fSmrg func, dims, width, height, depth, 313301e04c3fSmrg _mesa_enum_to_string(internalFormat)); 3134af69d88dSmrg return; 3135af69d88dSmrg } 3136af69d88dSmrg 3137af69d88dSmrg /* Allow a hardware driver to just strip out the border, to provide 3138af69d88dSmrg * reliable but slightly incorrect hardware rendering instead of 3139af69d88dSmrg * rarely-tested software fallback rendering. 3140af69d88dSmrg */ 3141af69d88dSmrg if (border && ctx->Const.StripTextureBorder) { 314201e04c3fSmrg strip_texture_border(target, &width, &height, &depth, unpack, 314301e04c3fSmrg &unpack_no_border); 3144af69d88dSmrg border = 0; 314501e04c3fSmrg unpack = &unpack_no_border; 31467117f1b4Smrg } 31477117f1b4Smrg 31487ec681f3Smrg _mesa_update_pixel(ctx); 31497117f1b4Smrg 31507117f1b4Smrg _mesa_lock_texture(ctx, texObj); 31517117f1b4Smrg { 31527ec681f3Smrg texObj->External = GL_FALSE; 31537ec681f3Smrg 315401e04c3fSmrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 31553464ebd5Sriastradh 315601e04c3fSmrg if (!texImage) { 315701e04c3fSmrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s%uD", func, dims); 315801e04c3fSmrg } 31594a49301eSmrg else { 3160af69d88dSmrg ctx->Driver.FreeTextureImageBuffer(ctx, texImage); 31613464ebd5Sriastradh 3162af69d88dSmrg _mesa_init_teximage_fields(ctx, texImage, 3163af69d88dSmrg width, height, depth, 3164af69d88dSmrg border, internalFormat, texFormat); 31654a49301eSmrg 3166af69d88dSmrg /* Give the texture to the driver. <pixels> may be null. */ 3167af69d88dSmrg if (width > 0 && height > 0 && depth > 0) { 3168af69d88dSmrg if (compressed) { 3169af69d88dSmrg ctx->Driver.CompressedTexImage(ctx, dims, texImage, 3170af69d88dSmrg imageSize, pixels); 3171af69d88dSmrg } 3172af69d88dSmrg else { 3173af69d88dSmrg ctx->Driver.TexImage(ctx, dims, texImage, format, 3174af69d88dSmrg type, pixels, unpack); 31753464ebd5Sriastradh } 3176af69d88dSmrg } 31774a49301eSmrg 3178af69d88dSmrg check_gen_mipmap(ctx, target, texObj, level); 31794a49301eSmrg 3180af69d88dSmrg _mesa_update_fbo_texture(ctx, texObj, face, level); 31814a49301eSmrg 3182af69d88dSmrg _mesa_dirty_texobj(ctx, texObj); 31833464ebd5Sriastradh } 31843464ebd5Sriastradh } 31853464ebd5Sriastradh _mesa_unlock_texture(ctx, texObj); 31863464ebd5Sriastradh } 31873464ebd5Sriastradh} 31887117f1b4Smrg 31894a49301eSmrg 319001e04c3fSmrg/* This is a wrapper around teximage() so that we can force the KHR_no_error 319101e04c3fSmrg * logic to be inlined without inlining the function into all the callers. 319201e04c3fSmrg */ 319301e04c3fSmrgstatic void 319401e04c3fSmrgteximage_err(struct gl_context *ctx, GLboolean compressed, GLuint dims, 319501e04c3fSmrg GLenum target, GLint level, GLint internalFormat, 319601e04c3fSmrg GLsizei width, GLsizei height, GLsizei depth, 319701e04c3fSmrg GLint border, GLenum format, GLenum type, 319801e04c3fSmrg GLsizei imageSize, const GLvoid *pixels) 319901e04c3fSmrg{ 32007ec681f3Smrg teximage(ctx, compressed, dims, NULL, target, level, internalFormat, width, height, 320101e04c3fSmrg depth, border, format, type, imageSize, pixels, false); 320201e04c3fSmrg} 320301e04c3fSmrg 320401e04c3fSmrg 320501e04c3fSmrgstatic void 320601e04c3fSmrgteximage_no_error(struct gl_context *ctx, GLboolean compressed, GLuint dims, 320701e04c3fSmrg GLenum target, GLint level, GLint internalFormat, 320801e04c3fSmrg GLsizei width, GLsizei height, GLsizei depth, 320901e04c3fSmrg GLint border, GLenum format, GLenum type, 321001e04c3fSmrg GLsizei imageSize, const GLvoid *pixels) 321101e04c3fSmrg{ 32127ec681f3Smrg teximage(ctx, compressed, dims, NULL, target, level, internalFormat, width, height, 321301e04c3fSmrg depth, border, format, type, imageSize, pixels, true); 321401e04c3fSmrg} 321501e04c3fSmrg 3216af69d88dSmrg 32173464ebd5Sriastradh/* 32183464ebd5Sriastradh * Called from the API. Note that width includes the border. 32193464ebd5Sriastradh */ 32203464ebd5Sriastradhvoid GLAPIENTRY 32213464ebd5Sriastradh_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat, 32223464ebd5Sriastradh GLsizei width, GLint border, GLenum format, 32233464ebd5Sriastradh GLenum type, const GLvoid *pixels ) 32243464ebd5Sriastradh{ 32253464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 322601e04c3fSmrg teximage_err(ctx, GL_FALSE, 1, target, level, internalFormat, width, 1, 1, 322701e04c3fSmrg border, format, type, 0, pixels); 32287117f1b4Smrg} 32297117f1b4Smrg 32307ec681f3Smrgvoid GLAPIENTRY 32317ec681f3Smrg_mesa_TextureImage1DEXT(GLuint texture, GLenum target, GLint level, 32327ec681f3Smrg GLint internalFormat, GLsizei width, GLint border, 32337ec681f3Smrg GLenum format, GLenum type, const GLvoid *pixels ) 32347ec681f3Smrg{ 32357ec681f3Smrg struct gl_texture_object* texObj; 32367ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 32377ec681f3Smrg 32387ec681f3Smrg texObj = _mesa_lookup_or_create_texture(ctx, target, texture, false, true, 32397ec681f3Smrg "glTextureImage1DEXT"); 32407ec681f3Smrg if (!texObj) 32417ec681f3Smrg return; 32427ec681f3Smrg teximage(ctx, GL_FALSE, 1, texObj, target, level, internalFormat, 32437ec681f3Smrg width, 1, 1, border, format, type, 0, pixels, false); 32447ec681f3Smrg} 32457ec681f3Smrg 32467ec681f3Smrgvoid GLAPIENTRY 32477ec681f3Smrg_mesa_MultiTexImage1DEXT(GLenum texunit, GLenum target, GLint level, 32487ec681f3Smrg GLint internalFormat, GLsizei width, GLint border, 32497ec681f3Smrg GLenum format, GLenum type, const GLvoid *pixels ) 32507ec681f3Smrg{ 32517ec681f3Smrg struct gl_texture_object* texObj; 32527ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 32537ec681f3Smrg 32547ec681f3Smrg texObj = _mesa_get_texobj_by_target_and_texunit(ctx, target, 32557ec681f3Smrg texunit - GL_TEXTURE0, 32567ec681f3Smrg true, 32577ec681f3Smrg "glMultiTexImage1DEXT"); 32587ec681f3Smrg if (!texObj) 32597ec681f3Smrg return; 32607ec681f3Smrg teximage(ctx, GL_FALSE, 1, texObj, target, level, internalFormat, width, 1, 1, 32617ec681f3Smrg border, format, type, 0, pixels, false); 32627ec681f3Smrg} 32637117f1b4Smrg 32647117f1b4Smrgvoid GLAPIENTRY 32657117f1b4Smrg_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat, 32667117f1b4Smrg GLsizei width, GLsizei height, GLint border, 32677117f1b4Smrg GLenum format, GLenum type, 32687117f1b4Smrg const GLvoid *pixels ) 32697117f1b4Smrg{ 32707117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 327101e04c3fSmrg teximage_err(ctx, GL_FALSE, 2, target, level, internalFormat, width, height, 1, 327201e04c3fSmrg border, format, type, 0, pixels); 32737117f1b4Smrg} 32747117f1b4Smrg 32757ec681f3Smrgvoid GLAPIENTRY 32767ec681f3Smrg_mesa_TextureImage2DEXT(GLuint texture, GLenum target, GLint level, 32777ec681f3Smrg GLint internalFormat, GLsizei width, GLsizei height, 32787ec681f3Smrg GLint border, 32797ec681f3Smrg GLenum format, GLenum type, const GLvoid *pixels ) 32807ec681f3Smrg{ 32817ec681f3Smrg struct gl_texture_object* texObj; 32827ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 32837ec681f3Smrg 32847ec681f3Smrg texObj = _mesa_lookup_or_create_texture(ctx, target, texture, false, true, 32857ec681f3Smrg "glTextureImage2DEXT"); 32867ec681f3Smrg if (!texObj) 32877ec681f3Smrg return; 32887ec681f3Smrg teximage(ctx, GL_FALSE, 2, texObj, target, level, internalFormat, 32897ec681f3Smrg width, height, 1, border, format, type, 0, pixels, false); 32907ec681f3Smrg} 32917ec681f3Smrg 32927ec681f3Smrgvoid GLAPIENTRY 32937ec681f3Smrg_mesa_MultiTexImage2DEXT(GLenum texunit, GLenum target, GLint level, 32947ec681f3Smrg GLint internalFormat, GLsizei width, GLsizei height, 32957ec681f3Smrg GLint border, 32967ec681f3Smrg GLenum format, GLenum type, const GLvoid *pixels ) 32977ec681f3Smrg{ 32987ec681f3Smrg struct gl_texture_object* texObj; 32997ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 33007ec681f3Smrg 33017ec681f3Smrg texObj = _mesa_get_texobj_by_target_and_texunit(ctx, target, 33027ec681f3Smrg texunit - GL_TEXTURE0, 33037ec681f3Smrg true, 33047ec681f3Smrg "glMultiTexImage2DEXT"); 33057ec681f3Smrg if (!texObj) 33067ec681f3Smrg return; 33077ec681f3Smrg teximage(ctx, GL_FALSE, 2, texObj, target, level, internalFormat, width, height, 1, 33087ec681f3Smrg border, format, type, 0, pixels, false); 33097ec681f3Smrg} 33107117f1b4Smrg 33117117f1b4Smrg/* 33127117f1b4Smrg * Called by the API or display list executor. 33137117f1b4Smrg * Note that width and height include the border. 33147117f1b4Smrg */ 33157117f1b4Smrgvoid GLAPIENTRY 33167117f1b4Smrg_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat, 33177117f1b4Smrg GLsizei width, GLsizei height, GLsizei depth, 33187117f1b4Smrg GLint border, GLenum format, GLenum type, 33197117f1b4Smrg const GLvoid *pixels ) 33207117f1b4Smrg{ 33217117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 332201e04c3fSmrg teximage_err(ctx, GL_FALSE, 3, target, level, internalFormat, 332301e04c3fSmrg width, height, depth, border, format, type, 0, pixels); 33247117f1b4Smrg} 33257117f1b4Smrg 33267ec681f3Smrgvoid GLAPIENTRY 33277ec681f3Smrg_mesa_TextureImage3DEXT(GLuint texture, GLenum target, GLint level, 33287ec681f3Smrg GLint internalFormat, GLsizei width, GLsizei height, 33297ec681f3Smrg GLsizei depth, GLint border, 33307ec681f3Smrg GLenum format, GLenum type, const GLvoid *pixels ) 33317ec681f3Smrg{ 33327ec681f3Smrg struct gl_texture_object* texObj; 33337ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 33347ec681f3Smrg 33357ec681f3Smrg texObj = _mesa_lookup_or_create_texture(ctx, target, texture, false, true, 33367ec681f3Smrg "glTextureImage3DEXT"); 33377ec681f3Smrg if (!texObj) 33387ec681f3Smrg return; 33397ec681f3Smrg teximage(ctx, GL_FALSE, 3, texObj, target, level, internalFormat, 33407ec681f3Smrg width, height, depth, border, format, type, 0, pixels, false); 33417ec681f3Smrg} 33427ec681f3Smrg 33437ec681f3Smrg 33447ec681f3Smrgvoid GLAPIENTRY 33457ec681f3Smrg_mesa_MultiTexImage3DEXT(GLenum texunit, GLenum target, GLint level, 33467ec681f3Smrg GLint internalFormat, GLsizei width, GLsizei height, 33477ec681f3Smrg GLsizei depth, GLint border, GLenum format, GLenum type, 33487ec681f3Smrg const GLvoid *pixels ) 33497ec681f3Smrg{ 33507ec681f3Smrg struct gl_texture_object* texObj; 33517ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 33527ec681f3Smrg 33537ec681f3Smrg texObj = _mesa_get_texobj_by_target_and_texunit(ctx, target, 33547ec681f3Smrg texunit - GL_TEXTURE0, 33557ec681f3Smrg true, 33567ec681f3Smrg "glMultiTexImage3DEXT"); 33577ec681f3Smrg if (!texObj) 33587ec681f3Smrg return; 33597ec681f3Smrg teximage(ctx, GL_FALSE, 3, texObj, target, level, internalFormat, 33607ec681f3Smrg width, height, depth, border, format, type, 0, pixels, false); 33617ec681f3Smrg} 33627ec681f3Smrg 33637117f1b4Smrg 33647117f1b4Smrgvoid GLAPIENTRY 33657117f1b4Smrg_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat, 33667117f1b4Smrg GLsizei width, GLsizei height, GLsizei depth, 33677117f1b4Smrg GLint border, GLenum format, GLenum type, 33687117f1b4Smrg const GLvoid *pixels ) 33697117f1b4Smrg{ 33707117f1b4Smrg _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height, 33717117f1b4Smrg depth, border, format, type, pixels); 33727117f1b4Smrg} 33737117f1b4Smrg 33747117f1b4Smrg 337501e04c3fSmrgvoid GLAPIENTRY 337601e04c3fSmrg_mesa_TexImage1D_no_error(GLenum target, GLint level, GLint internalFormat, 337701e04c3fSmrg GLsizei width, GLint border, GLenum format, 337801e04c3fSmrg GLenum type, const GLvoid *pixels) 337901e04c3fSmrg{ 338001e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 338101e04c3fSmrg teximage_no_error(ctx, GL_FALSE, 1, target, level, internalFormat, width, 1, 338201e04c3fSmrg 1, border, format, type, 0, pixels); 338301e04c3fSmrg} 338401e04c3fSmrg 338501e04c3fSmrg 338601e04c3fSmrgvoid GLAPIENTRY 338701e04c3fSmrg_mesa_TexImage2D_no_error(GLenum target, GLint level, GLint internalFormat, 338801e04c3fSmrg GLsizei width, GLsizei height, GLint border, 338901e04c3fSmrg GLenum format, GLenum type, const GLvoid *pixels) 339001e04c3fSmrg{ 339101e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 339201e04c3fSmrg teximage_no_error(ctx, GL_FALSE, 2, target, level, internalFormat, width, 339301e04c3fSmrg height, 1, border, format, type, 0, pixels); 339401e04c3fSmrg} 339501e04c3fSmrg 339601e04c3fSmrg 339701e04c3fSmrgvoid GLAPIENTRY 339801e04c3fSmrg_mesa_TexImage3D_no_error(GLenum target, GLint level, GLint internalFormat, 339901e04c3fSmrg GLsizei width, GLsizei height, GLsizei depth, 340001e04c3fSmrg GLint border, GLenum format, GLenum type, 340101e04c3fSmrg const GLvoid *pixels ) 340201e04c3fSmrg{ 340301e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 340401e04c3fSmrg teximage_no_error(ctx, GL_FALSE, 3, target, level, internalFormat, 340501e04c3fSmrg width, height, depth, border, format, type, 0, pixels); 340601e04c3fSmrg} 340701e04c3fSmrg 34087ec681f3Smrg/* 34097ec681f3Smrg * Helper used by __mesa_EGLImageTargetTexture2DOES and 34107ec681f3Smrg * _mesa_EGLImageTargetTexStorageEXT. 34117ec681f3Smrg */ 34127ec681f3Smrgstatic void 34137ec681f3Smrgegl_image_target_texture(struct gl_context *ctx, 34147ec681f3Smrg struct gl_texture_object *texObj, GLenum target, 34157ec681f3Smrg GLeglImageOES image, bool tex_storage, 34167ec681f3Smrg const char *caller) 3417cdc920a0Smrg{ 3418cdc920a0Smrg struct gl_texture_image *texImage; 3419af69d88dSmrg bool valid_target; 34207ec681f3Smrg FLUSH_VERTICES(ctx, 0, 0); 3421cdc920a0Smrg 3422af69d88dSmrg switch (target) { 3423af69d88dSmrg case GL_TEXTURE_2D: 34247ec681f3Smrg valid_target = _mesa_has_OES_EGL_image(ctx) || 34257ec681f3Smrg (tex_storage && _mesa_has_EXT_EGL_image_storage(ctx)); 3426af69d88dSmrg break; 3427af69d88dSmrg case GL_TEXTURE_EXTERNAL_OES: 3428af69d88dSmrg valid_target = 34297ec681f3Smrg _mesa_is_gles(ctx) ? _mesa_has_OES_EGL_image_external(ctx) : false; 3430af69d88dSmrg break; 3431af69d88dSmrg default: 3432af69d88dSmrg valid_target = false; 3433af69d88dSmrg break; 34343464ebd5Sriastradh } 34353464ebd5Sriastradh 3436af69d88dSmrg if (!valid_target) { 34377ec681f3Smrg _mesa_error(ctx, GL_INVALID_ENUM, "%s(target=%d)", caller, target); 3438cdc920a0Smrg return; 3439cdc920a0Smrg } 3440cdc920a0Smrg 34417ec681f3Smrg if (!image || (ctx->Driver.ValidateEGLImage && 34427ec681f3Smrg !ctx->Driver.ValidateEGLImage(ctx, image))) { 34437ec681f3Smrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(image=%p)", caller, image); 3444af69d88dSmrg return; 3445af69d88dSmrg } 3446af69d88dSmrg 3447cdc920a0Smrg _mesa_lock_texture(ctx, texObj); 3448cdc920a0Smrg 3449af69d88dSmrg if (texObj->Immutable) { 34507ec681f3Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(texture is immutable)", caller); 3451af69d88dSmrg _mesa_unlock_texture(ctx, texObj); 3452af69d88dSmrg return; 3453af69d88dSmrg } 3454af69d88dSmrg 3455cdc920a0Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, 0); 3456cdc920a0Smrg if (!texImage) { 34577ec681f3Smrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller); 3458cdc920a0Smrg } else { 3459af69d88dSmrg ctx->Driver.FreeTextureImageBuffer(ctx, texImage); 3460cdc920a0Smrg 34617ec681f3Smrg texObj->External = GL_TRUE; 34627ec681f3Smrg 34637ec681f3Smrg if (tex_storage) { 34647ec681f3Smrg ctx->Driver.EGLImageTargetTexStorage(ctx, target, texObj, texImage, 34657ec681f3Smrg image); 34667ec681f3Smrg } else { 34677ec681f3Smrg ctx->Driver.EGLImageTargetTexture2D(ctx, target, texObj, texImage, 34687ec681f3Smrg image); 34697ec681f3Smrg } 3470cdc920a0Smrg 3471af69d88dSmrg _mesa_dirty_texobj(ctx, texObj); 3472cdc920a0Smrg } 34737ec681f3Smrg 34747ec681f3Smrg if (tex_storage) 34757ec681f3Smrg _mesa_set_texture_view_state(ctx, texObj, target, 1); 34767ec681f3Smrg 34777ec681f3Smrg _mesa_update_fbo_texture(ctx, texObj, 0, 0); 34787ec681f3Smrg 3479cdc920a0Smrg _mesa_unlock_texture(ctx, texObj); 3480cdc920a0Smrg} 3481cdc920a0Smrg 34827ec681f3Smrgvoid GLAPIENTRY 34837ec681f3Smrg_mesa_EGLImageTargetTexture2DOES(GLenum target, GLeglImageOES image) 34847ec681f3Smrg{ 34857ec681f3Smrg struct gl_texture_object *texObj; 34867ec681f3Smrg const char *func = "glEGLImageTargetTexture2D"; 34877ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 34887ec681f3Smrg 34897ec681f3Smrg texObj = _mesa_get_current_tex_object(ctx, target); 34907ec681f3Smrg if (!texObj) { 34917ec681f3Smrg _mesa_error(ctx, GL_INVALID_ENUM, "%s(target=%d)", func, target); 34927ec681f3Smrg return; 34937ec681f3Smrg } 34947ec681f3Smrg 34957ec681f3Smrg egl_image_target_texture(ctx, texObj, target, image, false, func); 34967ec681f3Smrg} 34977ec681f3Smrg 34987ec681f3Smrgstatic void 34997ec681f3Smrgegl_image_target_texture_storage(struct gl_context *ctx, 35007ec681f3Smrg struct gl_texture_object *texObj, GLenum target, 35017ec681f3Smrg GLeglImageOES image, const GLint *attrib_list, 35027ec681f3Smrg const char *caller) 35037ec681f3Smrg{ 35047ec681f3Smrg /* 35057ec681f3Smrg * EXT_EGL_image_storage: 35067ec681f3Smrg * 35077ec681f3Smrg * "<attrib_list> must be NULL or a pointer to the value GL_NONE." 35087ec681f3Smrg */ 35097ec681f3Smrg if (attrib_list && attrib_list[0] != GL_NONE) { 35107ec681f3Smrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(image=%p)", caller, image); 35117ec681f3Smrg return; 35127ec681f3Smrg } 35137ec681f3Smrg 35147ec681f3Smrg switch (target) { 35157ec681f3Smrg case GL_TEXTURE_2D: 35167ec681f3Smrg case GL_TEXTURE_EXTERNAL_OES: 35177ec681f3Smrg break; 35187ec681f3Smrg default: 35197ec681f3Smrg /* 35207ec681f3Smrg * The EXT_EGL_image_storage spec allows for many other targets besides 35217ec681f3Smrg * GL_TEXTURE_2D and GL_TEXTURE_EXTERNAL_OES, however these are complicated 35227ec681f3Smrg * to implement. 35237ec681f3Smrg */ 35247ec681f3Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported target=%d)", 35257ec681f3Smrg caller, target); 35267ec681f3Smrg return; 35277ec681f3Smrg } 35287ec681f3Smrg 35297ec681f3Smrg egl_image_target_texture(ctx, texObj, target, image, true, caller); 35307ec681f3Smrg} 35317ec681f3Smrg 35327ec681f3Smrg 35337ec681f3Smrgvoid GLAPIENTRY 35347ec681f3Smrg_mesa_EGLImageTargetTexStorageEXT(GLenum target, GLeglImageOES image, 35357ec681f3Smrg const GLint *attrib_list) 35367ec681f3Smrg{ 35377ec681f3Smrg struct gl_texture_object *texObj; 35387ec681f3Smrg const char *func = "glEGLImageTargetTexStorageEXT"; 35397ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 35407ec681f3Smrg 35417ec681f3Smrg texObj = _mesa_get_current_tex_object(ctx, target); 35427ec681f3Smrg if (!texObj) { 35437ec681f3Smrg _mesa_error(ctx, GL_INVALID_ENUM, "%s(target=%d)", func, target); 35447ec681f3Smrg return; 35457ec681f3Smrg } 35467ec681f3Smrg 35477ec681f3Smrg egl_image_target_texture_storage(ctx, texObj, target, image, attrib_list, 35487ec681f3Smrg func); 35497ec681f3Smrg} 35507ec681f3Smrg 35517ec681f3Smrgvoid GLAPIENTRY 35527ec681f3Smrg_mesa_EGLImageTargetTextureStorageEXT(GLuint texture, GLeglImageOES image, 35537ec681f3Smrg const GLint *attrib_list) 35547ec681f3Smrg{ 35557ec681f3Smrg struct gl_texture_object *texObj; 35567ec681f3Smrg const char *func = "glEGLImageTargetTextureStorageEXT"; 35577ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 35587ec681f3Smrg 35597ec681f3Smrg if (!(_mesa_is_desktop_gl(ctx) && ctx->Version >= 45) && 35607ec681f3Smrg !_mesa_has_ARB_direct_state_access(ctx) && 35617ec681f3Smrg !_mesa_has_EXT_direct_state_access(ctx)) { 35627ec681f3Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "direct access not supported"); 35637ec681f3Smrg return; 35647ec681f3Smrg } 35657ec681f3Smrg 35667ec681f3Smrg texObj = _mesa_lookup_texture_err(ctx, texture, func); 35677ec681f3Smrg if (!texObj) 35687ec681f3Smrg return; 35697ec681f3Smrg 35707ec681f3Smrg egl_image_target_texture_storage(ctx, texObj, texObj->Target, image, 35717ec681f3Smrg attrib_list, func); 35727ec681f3Smrg} 35737117f1b4Smrg 35743464ebd5Sriastradh/** 357501e04c3fSmrg * Helper that implements the glTexSubImage1/2/3D() 357601e04c3fSmrg * and glTextureSubImage1/2/3D() functions. 35773464ebd5Sriastradh */ 35783464ebd5Sriastradhstatic void 357901e04c3fSmrgtexture_sub_image(struct gl_context *ctx, GLuint dims, 358001e04c3fSmrg struct gl_texture_object *texObj, 358101e04c3fSmrg struct gl_texture_image *texImage, 358201e04c3fSmrg GLenum target, GLint level, 358301e04c3fSmrg GLint xoffset, GLint yoffset, GLint zoffset, 358401e04c3fSmrg GLsizei width, GLsizei height, GLsizei depth, 358501e04c3fSmrg GLenum format, GLenum type, const GLvoid *pixels) 35867117f1b4Smrg{ 35877ec681f3Smrg FLUSH_VERTICES(ctx, 0, 0); 35887117f1b4Smrg 35897ec681f3Smrg _mesa_update_pixel(ctx); 35907117f1b4Smrg 35917117f1b4Smrg _mesa_lock_texture(ctx, texObj); 35927117f1b4Smrg { 3593af69d88dSmrg if (width > 0 && height > 0 && depth > 0) { 35943464ebd5Sriastradh /* If we have a border, offset=-1 is legal. Bias by border width. */ 35953464ebd5Sriastradh switch (dims) { 35963464ebd5Sriastradh case 3: 3597af69d88dSmrg if (target != GL_TEXTURE_2D_ARRAY) 3598af69d88dSmrg zoffset += texImage->Border; 35997ec681f3Smrg FALLTHROUGH; 36003464ebd5Sriastradh case 2: 3601af69d88dSmrg if (target != GL_TEXTURE_1D_ARRAY) 3602af69d88dSmrg yoffset += texImage->Border; 36037ec681f3Smrg FALLTHROUGH; 36043464ebd5Sriastradh case 1: 36053464ebd5Sriastradh xoffset += texImage->Border; 36063464ebd5Sriastradh } 36077117f1b4Smrg 3608af69d88dSmrg ctx->Driver.TexSubImage(ctx, dims, texImage, 3609af69d88dSmrg xoffset, yoffset, zoffset, 3610af69d88dSmrg width, height, depth, 3611af69d88dSmrg format, type, pixels, &ctx->Unpack); 36127117f1b4Smrg 36134a49301eSmrg check_gen_mipmap(ctx, target, texObj, level); 36147117f1b4Smrg 361501e04c3fSmrg /* NOTE: Don't signal _NEW_TEXTURE_OBJECT since we've only changed 3616af69d88dSmrg * the texel data, not the texture format, size, etc. 3617af69d88dSmrg */ 36184a49301eSmrg } 36197117f1b4Smrg } 36207117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 36217117f1b4Smrg} 36227117f1b4Smrg 362301e04c3fSmrg/** 362401e04c3fSmrg * Implement all the glTexSubImage1/2/3D() functions. 362501e04c3fSmrg * Must split this out this way because of GL_TEXTURE_CUBE_MAP. 362601e04c3fSmrg */ 362701e04c3fSmrgstatic void 362801e04c3fSmrgtexsubimage_err(struct gl_context *ctx, GLuint dims, GLenum target, GLint level, 362901e04c3fSmrg GLint xoffset, GLint yoffset, GLint zoffset, 363001e04c3fSmrg GLsizei width, GLsizei height, GLsizei depth, 363101e04c3fSmrg GLenum format, GLenum type, const GLvoid *pixels, 363201e04c3fSmrg const char *callerName) 363301e04c3fSmrg{ 363401e04c3fSmrg struct gl_texture_object *texObj; 363501e04c3fSmrg struct gl_texture_image *texImage; 363601e04c3fSmrg 363701e04c3fSmrg /* check target (proxies not allowed) */ 363801e04c3fSmrg if (!legal_texsubimage_target(ctx, dims, target, false)) { 363901e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage%uD(target=%s)", 364001e04c3fSmrg dims, _mesa_enum_to_string(target)); 364101e04c3fSmrg return; 364201e04c3fSmrg } 364301e04c3fSmrg 364401e04c3fSmrg texObj = _mesa_get_current_tex_object(ctx, target); 364501e04c3fSmrg if (!texObj) 364601e04c3fSmrg return; 364701e04c3fSmrg 364801e04c3fSmrg if (texsubimage_error_check(ctx, dims, texObj, target, level, 364901e04c3fSmrg xoffset, yoffset, zoffset, 365001e04c3fSmrg width, height, depth, format, type, 365101e04c3fSmrg pixels, callerName)) { 365201e04c3fSmrg return; /* error was detected */ 365301e04c3fSmrg } 365401e04c3fSmrg 365501e04c3fSmrg texImage = _mesa_select_tex_image(texObj, target, level); 365601e04c3fSmrg /* texsubimage_error_check ensures that texImage is not NULL */ 365701e04c3fSmrg 365801e04c3fSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 365901e04c3fSmrg _mesa_debug(ctx, "glTexSubImage%uD %s %d %d %d %d %d %d %d %s %s %p\n", 366001e04c3fSmrg dims, 366101e04c3fSmrg _mesa_enum_to_string(target), level, 366201e04c3fSmrg xoffset, yoffset, zoffset, width, height, depth, 366301e04c3fSmrg _mesa_enum_to_string(format), 366401e04c3fSmrg _mesa_enum_to_string(type), pixels); 366501e04c3fSmrg 366601e04c3fSmrg texture_sub_image(ctx, dims, texObj, texImage, target, level, 366701e04c3fSmrg xoffset, yoffset, zoffset, width, height, depth, 366801e04c3fSmrg format, type, pixels); 366901e04c3fSmrg} 367001e04c3fSmrg 367101e04c3fSmrg 367201e04c3fSmrgstatic void 367301e04c3fSmrgtexsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level, 367401e04c3fSmrg GLint xoffset, GLint yoffset, GLint zoffset, 367501e04c3fSmrg GLsizei width, GLsizei height, GLsizei depth, 367601e04c3fSmrg GLenum format, GLenum type, const GLvoid *pixels) 367701e04c3fSmrg{ 367801e04c3fSmrg struct gl_texture_object *texObj; 367901e04c3fSmrg struct gl_texture_image *texImage; 368001e04c3fSmrg 368101e04c3fSmrg texObj = _mesa_get_current_tex_object(ctx, target); 368201e04c3fSmrg texImage = _mesa_select_tex_image(texObj, target, level); 368301e04c3fSmrg 368401e04c3fSmrg texture_sub_image(ctx, dims, texObj, texImage, target, level, 368501e04c3fSmrg xoffset, yoffset, zoffset, width, height, depth, 368601e04c3fSmrg format, type, pixels); 368701e04c3fSmrg} 368801e04c3fSmrg 368901e04c3fSmrg 369001e04c3fSmrg/** 369101e04c3fSmrg * Implement all the glTextureSubImage1/2/3D() functions. 369201e04c3fSmrg * Must split this out this way because of GL_TEXTURE_CUBE_MAP. 369301e04c3fSmrg */ 369401e04c3fSmrgstatic ALWAYS_INLINE void 369501e04c3fSmrgtexturesubimage(struct gl_context *ctx, GLuint dims, 36967ec681f3Smrg GLuint texture, GLenum target, GLint level, 369701e04c3fSmrg GLint xoffset, GLint yoffset, GLint zoffset, 369801e04c3fSmrg GLsizei width, GLsizei height, GLsizei depth, 369901e04c3fSmrg GLenum format, GLenum type, const GLvoid *pixels, 37007ec681f3Smrg const char *callerName, bool no_error, bool ext_dsa) 370101e04c3fSmrg{ 370201e04c3fSmrg struct gl_texture_object *texObj; 370301e04c3fSmrg struct gl_texture_image *texImage; 370401e04c3fSmrg int i; 370501e04c3fSmrg 370601e04c3fSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 370701e04c3fSmrg _mesa_debug(ctx, 370801e04c3fSmrg "glTextureSubImage%uD %d %d %d %d %d %d %d %d %s %s %p\n", 370901e04c3fSmrg dims, texture, level, 371001e04c3fSmrg xoffset, yoffset, zoffset, width, height, depth, 371101e04c3fSmrg _mesa_enum_to_string(format), 371201e04c3fSmrg _mesa_enum_to_string(type), pixels); 371301e04c3fSmrg 371401e04c3fSmrg /* Get the texture object by Name. */ 371501e04c3fSmrg if (!no_error) { 37167ec681f3Smrg if (!ext_dsa) { 37177ec681f3Smrg texObj = _mesa_lookup_texture_err(ctx, texture, callerName); 37187ec681f3Smrg } else { 37197ec681f3Smrg texObj = lookup_texture_ext_dsa(ctx, target, texture, callerName); 37207ec681f3Smrg } 372101e04c3fSmrg if (!texObj) 372201e04c3fSmrg return; 372301e04c3fSmrg } else { 372401e04c3fSmrg texObj = _mesa_lookup_texture(ctx, texture); 372501e04c3fSmrg } 372601e04c3fSmrg 372701e04c3fSmrg if (!no_error) { 372801e04c3fSmrg /* check target (proxies not allowed) */ 372901e04c3fSmrg if (!legal_texsubimage_target(ctx, dims, texObj->Target, true)) { 37307ec681f3Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(target=%s)", 373101e04c3fSmrg callerName, _mesa_enum_to_string(texObj->Target)); 373201e04c3fSmrg return; 373301e04c3fSmrg } 373401e04c3fSmrg 373501e04c3fSmrg if (texsubimage_error_check(ctx, dims, texObj, texObj->Target, level, 373601e04c3fSmrg xoffset, yoffset, zoffset, 373701e04c3fSmrg width, height, depth, format, type, 373801e04c3fSmrg pixels, callerName)) { 373901e04c3fSmrg return; /* error was detected */ 374001e04c3fSmrg } 374101e04c3fSmrg } 374201e04c3fSmrg 374301e04c3fSmrg /* Must handle special case GL_TEXTURE_CUBE_MAP. */ 374401e04c3fSmrg if (texObj->Target == GL_TEXTURE_CUBE_MAP) { 374501e04c3fSmrg GLint imageStride; 374601e04c3fSmrg 374701e04c3fSmrg /* 374801e04c3fSmrg * What do we do if the user created a texture with the following code 374901e04c3fSmrg * and then called this function with its handle? 375001e04c3fSmrg * 375101e04c3fSmrg * GLuint tex; 375201e04c3fSmrg * glCreateTextures(GL_TEXTURE_CUBE_MAP, 1, &tex); 375301e04c3fSmrg * glBindTexture(GL_TEXTURE_CUBE_MAP, tex); 375401e04c3fSmrg * glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, ...); 375501e04c3fSmrg * glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, ...); 375601e04c3fSmrg * glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, ...); 375701e04c3fSmrg * // Note: GL_TEXTURE_CUBE_MAP_NEGATIVE_Y not set, or given the 375801e04c3fSmrg * // wrong format, or given the wrong size, etc. 375901e04c3fSmrg * glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, ...); 376001e04c3fSmrg * glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, ...); 376101e04c3fSmrg * 376201e04c3fSmrg * A bug has been filed against the spec for this case. In the 376301e04c3fSmrg * meantime, we will check for cube completeness. 376401e04c3fSmrg * 376501e04c3fSmrg * According to Section 8.17 Texture Completeness in the OpenGL 4.5 376601e04c3fSmrg * Core Profile spec (30.10.2014): 376701e04c3fSmrg * "[A] cube map texture is cube complete if the 376801e04c3fSmrg * following conditions all hold true: The [base level] texture 376901e04c3fSmrg * images of each of the six cube map faces have identical, positive, 377001e04c3fSmrg * and square dimensions. The [base level] images were each specified 377101e04c3fSmrg * with the same internal format." 377201e04c3fSmrg * 377301e04c3fSmrg * It seems reasonable to check for cube completeness of an arbitrary 377401e04c3fSmrg * level here so that the image data has a consistent format and size. 377501e04c3fSmrg */ 377601e04c3fSmrg if (!no_error && !_mesa_cube_level_complete(texObj, level)) { 377701e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 377801e04c3fSmrg "glTextureSubImage%uD(cube map incomplete)", 377901e04c3fSmrg dims); 378001e04c3fSmrg return; 378101e04c3fSmrg } 378201e04c3fSmrg 378301e04c3fSmrg imageStride = _mesa_image_image_stride(&ctx->Unpack, width, height, 378401e04c3fSmrg format, type); 378501e04c3fSmrg /* Copy in each face. */ 378601e04c3fSmrg for (i = zoffset; i < zoffset + depth; ++i) { 378701e04c3fSmrg texImage = texObj->Image[i][level]; 378801e04c3fSmrg assert(texImage); 378901e04c3fSmrg 379001e04c3fSmrg texture_sub_image(ctx, 3, texObj, texImage, texObj->Target, 379101e04c3fSmrg level, xoffset, yoffset, 0, 379201e04c3fSmrg width, height, 1, format, 379301e04c3fSmrg type, pixels); 379401e04c3fSmrg pixels = (GLubyte *) pixels + imageStride; 379501e04c3fSmrg } 379601e04c3fSmrg } 379701e04c3fSmrg else { 379801e04c3fSmrg texImage = _mesa_select_tex_image(texObj, texObj->Target, level); 379901e04c3fSmrg assert(texImage); 380001e04c3fSmrg 380101e04c3fSmrg texture_sub_image(ctx, dims, texObj, texImage, texObj->Target, 380201e04c3fSmrg level, xoffset, yoffset, zoffset, 380301e04c3fSmrg width, height, depth, format, 380401e04c3fSmrg type, pixels); 380501e04c3fSmrg } 380601e04c3fSmrg} 380701e04c3fSmrg 380801e04c3fSmrg 380901e04c3fSmrgstatic void 381001e04c3fSmrgtexturesubimage_error(struct gl_context *ctx, GLuint dims, 38117ec681f3Smrg GLuint texture, GLenum target, GLint level, 381201e04c3fSmrg GLint xoffset, GLint yoffset, GLint zoffset, 381301e04c3fSmrg GLsizei width, GLsizei height, GLsizei depth, 381401e04c3fSmrg GLenum format, GLenum type, const GLvoid *pixels, 38157ec681f3Smrg const char *callerName, bool ext_dsa) 381601e04c3fSmrg{ 38177ec681f3Smrg texturesubimage(ctx, dims, texture, target, level, xoffset, yoffset, 38187ec681f3Smrg zoffset, width, height, depth, format, type, pixels, 38197ec681f3Smrg callerName, false, ext_dsa); 382001e04c3fSmrg} 382101e04c3fSmrg 382201e04c3fSmrg 382301e04c3fSmrgstatic void 382401e04c3fSmrgtexturesubimage_no_error(struct gl_context *ctx, GLuint dims, 38257ec681f3Smrg GLuint texture, GLenum target, GLint level, 382601e04c3fSmrg GLint xoffset, GLint yoffset, GLint zoffset, 382701e04c3fSmrg GLsizei width, GLsizei height, GLsizei depth, 382801e04c3fSmrg GLenum format, GLenum type, const GLvoid *pixels, 38297ec681f3Smrg const char *callerName, bool ext_dsa) 383001e04c3fSmrg{ 38317ec681f3Smrg texturesubimage(ctx, dims, texture, target, level, xoffset, yoffset, 38327ec681f3Smrg zoffset, width, height, depth, format, type, pixels, 38337ec681f3Smrg callerName, true, ext_dsa); 383401e04c3fSmrg} 383501e04c3fSmrg 383601e04c3fSmrg 383701e04c3fSmrgvoid GLAPIENTRY 383801e04c3fSmrg_mesa_TexSubImage1D_no_error(GLenum target, GLint level, 383901e04c3fSmrg GLint xoffset, GLsizei width, 384001e04c3fSmrg GLenum format, GLenum type, 384101e04c3fSmrg const GLvoid *pixels) 384201e04c3fSmrg{ 384301e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 384401e04c3fSmrg texsubimage(ctx, 1, target, level, 384501e04c3fSmrg xoffset, 0, 0, 384601e04c3fSmrg width, 1, 1, 384701e04c3fSmrg format, type, pixels); 384801e04c3fSmrg} 384901e04c3fSmrg 385001e04c3fSmrg 385101e04c3fSmrgvoid GLAPIENTRY 385201e04c3fSmrg_mesa_TexSubImage1D( GLenum target, GLint level, 385301e04c3fSmrg GLint xoffset, GLsizei width, 385401e04c3fSmrg GLenum format, GLenum type, 385501e04c3fSmrg const GLvoid *pixels ) 385601e04c3fSmrg{ 385701e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 385801e04c3fSmrg texsubimage_err(ctx, 1, target, level, 385901e04c3fSmrg xoffset, 0, 0, 386001e04c3fSmrg width, 1, 1, 386101e04c3fSmrg format, type, pixels, "glTexSubImage1D"); 386201e04c3fSmrg} 386301e04c3fSmrg 386401e04c3fSmrg 386501e04c3fSmrgvoid GLAPIENTRY 386601e04c3fSmrg_mesa_TexSubImage2D_no_error(GLenum target, GLint level, 386701e04c3fSmrg GLint xoffset, GLint yoffset, 386801e04c3fSmrg GLsizei width, GLsizei height, 386901e04c3fSmrg GLenum format, GLenum type, 387001e04c3fSmrg const GLvoid *pixels) 387101e04c3fSmrg{ 387201e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 387301e04c3fSmrg texsubimage(ctx, 2, target, level, 387401e04c3fSmrg xoffset, yoffset, 0, 387501e04c3fSmrg width, height, 1, 387601e04c3fSmrg format, type, pixels); 387701e04c3fSmrg} 387801e04c3fSmrg 387901e04c3fSmrg 388001e04c3fSmrgvoid GLAPIENTRY 388101e04c3fSmrg_mesa_TexSubImage2D( GLenum target, GLint level, 388201e04c3fSmrg GLint xoffset, GLint yoffset, 388301e04c3fSmrg GLsizei width, GLsizei height, 388401e04c3fSmrg GLenum format, GLenum type, 388501e04c3fSmrg const GLvoid *pixels ) 388601e04c3fSmrg{ 388701e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 388801e04c3fSmrg texsubimage_err(ctx, 2, target, level, 388901e04c3fSmrg xoffset, yoffset, 0, 389001e04c3fSmrg width, height, 1, 389101e04c3fSmrg format, type, pixels, "glTexSubImage2D"); 389201e04c3fSmrg} 389301e04c3fSmrg 389401e04c3fSmrg 389501e04c3fSmrgvoid GLAPIENTRY 389601e04c3fSmrg_mesa_TexSubImage3D_no_error(GLenum target, GLint level, 389701e04c3fSmrg GLint xoffset, GLint yoffset, GLint zoffset, 389801e04c3fSmrg GLsizei width, GLsizei height, GLsizei depth, 389901e04c3fSmrg GLenum format, GLenum type, 390001e04c3fSmrg const GLvoid *pixels) 390101e04c3fSmrg{ 390201e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 390301e04c3fSmrg texsubimage(ctx, 3, target, level, 390401e04c3fSmrg xoffset, yoffset, zoffset, 390501e04c3fSmrg width, height, depth, 390601e04c3fSmrg format, type, pixels); 390701e04c3fSmrg} 390801e04c3fSmrg 390901e04c3fSmrg 391001e04c3fSmrgvoid GLAPIENTRY 391101e04c3fSmrg_mesa_TexSubImage3D( GLenum target, GLint level, 391201e04c3fSmrg GLint xoffset, GLint yoffset, GLint zoffset, 391301e04c3fSmrg GLsizei width, GLsizei height, GLsizei depth, 391401e04c3fSmrg GLenum format, GLenum type, 391501e04c3fSmrg const GLvoid *pixels ) 391601e04c3fSmrg{ 391701e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 391801e04c3fSmrg texsubimage_err(ctx, 3, target, level, 391901e04c3fSmrg xoffset, yoffset, zoffset, 392001e04c3fSmrg width, height, depth, 392101e04c3fSmrg format, type, pixels, "glTexSubImage3D"); 392201e04c3fSmrg} 392301e04c3fSmrg 392401e04c3fSmrg 392501e04c3fSmrgvoid GLAPIENTRY 392601e04c3fSmrg_mesa_TextureSubImage1D_no_error(GLuint texture, GLint level, GLint xoffset, 392701e04c3fSmrg GLsizei width, GLenum format, GLenum type, 392801e04c3fSmrg const GLvoid *pixels) 392901e04c3fSmrg{ 393001e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 39317ec681f3Smrg texturesubimage_no_error(ctx, 1, texture, 0, level, xoffset, 0, 0, width, 39327ec681f3Smrg 1, 1, format, type, pixels, "glTextureSubImage1D", 39337ec681f3Smrg false); 39347ec681f3Smrg} 39357ec681f3Smrg 39367ec681f3Smrg 39377ec681f3Smrgvoid GLAPIENTRY 39387ec681f3Smrg_mesa_TextureSubImage1DEXT(GLuint texture, GLenum target, GLint level, 39397ec681f3Smrg GLint xoffset, GLsizei width, 39407ec681f3Smrg GLenum format, GLenum type, 39417ec681f3Smrg const GLvoid *pixels) 39427ec681f3Smrg{ 39437ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 39447ec681f3Smrg texturesubimage_error(ctx, 1, texture, target, level, xoffset, 0, 0, width, 1, 39457ec681f3Smrg 1, format, type, pixels, "glTextureSubImage1DEXT", 39467ec681f3Smrg false); 39477ec681f3Smrg} 39487ec681f3Smrg 39497ec681f3Smrg 39507ec681f3Smrgvoid GLAPIENTRY 39517ec681f3Smrg_mesa_MultiTexSubImage1DEXT(GLenum texunit, GLenum target, GLint level, 39527ec681f3Smrg GLint xoffset, GLsizei width, 39537ec681f3Smrg GLenum format, GLenum type, 39547ec681f3Smrg const GLvoid *pixels) 39557ec681f3Smrg{ 39567ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 39577ec681f3Smrg struct gl_texture_object *texObj; 39587ec681f3Smrg struct gl_texture_image *texImage; 39597ec681f3Smrg 39607ec681f3Smrg texObj = _mesa_get_texobj_by_target_and_texunit(ctx, target, 39617ec681f3Smrg texunit - GL_TEXTURE0, 39627ec681f3Smrg false, 39637ec681f3Smrg "glMultiTexImage1DEXT"); 39647ec681f3Smrg texImage = _mesa_select_tex_image(texObj, target, level); 39657ec681f3Smrg 39667ec681f3Smrg texture_sub_image(ctx, 1, texObj, texImage, target, level, 39677ec681f3Smrg xoffset, 0, 0, width, 1, 1, 39687ec681f3Smrg format, type, pixels); 396901e04c3fSmrg} 397001e04c3fSmrg 397101e04c3fSmrg 397201e04c3fSmrgvoid GLAPIENTRY 397301e04c3fSmrg_mesa_TextureSubImage1D(GLuint texture, GLint level, 397401e04c3fSmrg GLint xoffset, GLsizei width, 397501e04c3fSmrg GLenum format, GLenum type, 397601e04c3fSmrg const GLvoid *pixels) 397701e04c3fSmrg{ 397801e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 39797ec681f3Smrg texturesubimage_error(ctx, 1, texture, 0, level, xoffset, 0, 0, width, 1, 39807ec681f3Smrg 1, format, type, pixels, "glTextureSubImage1D", 39817ec681f3Smrg false); 398201e04c3fSmrg} 398301e04c3fSmrg 398401e04c3fSmrg 398501e04c3fSmrgvoid GLAPIENTRY 398601e04c3fSmrg_mesa_TextureSubImage2D_no_error(GLuint texture, GLint level, GLint xoffset, 398701e04c3fSmrg GLint yoffset, GLsizei width, GLsizei height, 398801e04c3fSmrg GLenum format, GLenum type, 398901e04c3fSmrg const GLvoid *pixels) 399001e04c3fSmrg{ 399101e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 39927ec681f3Smrg texturesubimage_no_error(ctx, 2, texture, 0, level, xoffset, yoffset, 0, 39937ec681f3Smrg width, height, 1, format, type, pixels, 39947ec681f3Smrg "glTextureSubImage2D", false); 39957ec681f3Smrg} 39967ec681f3Smrg 39977ec681f3Smrg 39987ec681f3Smrgvoid GLAPIENTRY 39997ec681f3Smrg_mesa_TextureSubImage2DEXT(GLuint texture, GLenum target, GLint level, 40007ec681f3Smrg GLint xoffset, GLint yoffset, GLsizei width, 40017ec681f3Smrg GLsizei height, GLenum format, GLenum type, 40027ec681f3Smrg const GLvoid *pixels) 40037ec681f3Smrg{ 40047ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 40057ec681f3Smrg texturesubimage_error(ctx, 2, texture, target, level, xoffset, yoffset, 0, 40067ec681f3Smrg width, height, 1, format, type, pixels, 40077ec681f3Smrg "glTextureSubImage2DEXT", true); 40087ec681f3Smrg} 40097ec681f3Smrg 40107ec681f3Smrg 40117ec681f3Smrgvoid GLAPIENTRY 40127ec681f3Smrg_mesa_MultiTexSubImage2DEXT(GLenum texunit, GLenum target, GLint level, 40137ec681f3Smrg GLint xoffset, GLint yoffset, GLsizei width, 40147ec681f3Smrg GLsizei height, GLenum format, GLenum type, 40157ec681f3Smrg const GLvoid *pixels) 40167ec681f3Smrg{ 40177ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 40187ec681f3Smrg struct gl_texture_object *texObj; 40197ec681f3Smrg struct gl_texture_image *texImage; 40207ec681f3Smrg 40217ec681f3Smrg texObj = _mesa_get_texobj_by_target_and_texunit(ctx, target, 40227ec681f3Smrg texunit - GL_TEXTURE0, 40237ec681f3Smrg false, 40247ec681f3Smrg "glMultiTexImage2DEXT"); 40257ec681f3Smrg texImage = _mesa_select_tex_image(texObj, target, level); 40267ec681f3Smrg 40277ec681f3Smrg texture_sub_image(ctx, 2, texObj, texImage, target, level, 40287ec681f3Smrg xoffset, yoffset, 0, width, height, 1, 40297ec681f3Smrg format, type, pixels); 403001e04c3fSmrg} 403101e04c3fSmrg 40327117f1b4Smrg 40337117f1b4Smrgvoid GLAPIENTRY 403401e04c3fSmrg_mesa_TextureSubImage2D(GLuint texture, GLint level, 403501e04c3fSmrg GLint xoffset, GLint yoffset, 403601e04c3fSmrg GLsizei width, GLsizei height, 403701e04c3fSmrg GLenum format, GLenum type, 403801e04c3fSmrg const GLvoid *pixels) 40397117f1b4Smrg{ 40407117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 40417ec681f3Smrg texturesubimage_error(ctx, 2, texture, 0, level, xoffset, yoffset, 0, 40427ec681f3Smrg width, height, 1, format, type, pixels, 40437ec681f3Smrg "glTextureSubImage2D", false); 40447117f1b4Smrg} 40457117f1b4Smrg 40467117f1b4Smrg 40477117f1b4Smrgvoid GLAPIENTRY 404801e04c3fSmrg_mesa_TextureSubImage3D_no_error(GLuint texture, GLint level, GLint xoffset, 404901e04c3fSmrg GLint yoffset, GLint zoffset, GLsizei width, 405001e04c3fSmrg GLsizei height, GLsizei depth, GLenum format, 405101e04c3fSmrg GLenum type, const GLvoid *pixels) 40527117f1b4Smrg{ 40537117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 40547ec681f3Smrg texturesubimage_no_error(ctx, 3, texture, 0, level, xoffset, yoffset, 40557ec681f3Smrg zoffset, width, height, depth, format, type, 40567ec681f3Smrg pixels, "glTextureSubImage3D", false); 40577117f1b4Smrg} 40587117f1b4Smrg 40597117f1b4Smrg 40607117f1b4Smrgvoid GLAPIENTRY 40617ec681f3Smrg_mesa_TextureSubImage3DEXT(GLuint texture, GLenum target, GLint level, 40627ec681f3Smrg GLint xoffset, GLint yoffset, GLint zoffset, 40637ec681f3Smrg GLsizei width, GLsizei height, GLsizei depth, 40647ec681f3Smrg GLenum format, GLenum type, const GLvoid *pixels) 40657117f1b4Smrg{ 40663464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 40677ec681f3Smrg texturesubimage_error(ctx, 3, texture, target, level, xoffset, yoffset, 40687ec681f3Smrg zoffset, width, height, depth, format, type, 40697ec681f3Smrg pixels, "glTextureSubImage3DEXT", true); 40707117f1b4Smrg} 40717117f1b4Smrg 40727117f1b4Smrg 40737ec681f3Smrgvoid GLAPIENTRY 40747ec681f3Smrg_mesa_MultiTexSubImage3DEXT(GLenum texunit, GLenum target, GLint level, 40757ec681f3Smrg GLint xoffset, GLint yoffset, GLint zoffset, 40767ec681f3Smrg GLsizei width, GLsizei height, GLsizei depth, 40777ec681f3Smrg GLenum format, GLenum type, const GLvoid *pixels) 40787ec681f3Smrg{ 40797ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 40807ec681f3Smrg struct gl_texture_object *texObj; 40817ec681f3Smrg struct gl_texture_image *texImage; 40827ec681f3Smrg 40837ec681f3Smrg texObj = _mesa_get_texobj_by_target_and_texunit(ctx, target, 40847ec681f3Smrg texunit - GL_TEXTURE0, 40857ec681f3Smrg false, 40867ec681f3Smrg "glMultiTexImage3DEXT"); 40877ec681f3Smrg texImage = _mesa_select_tex_image(texObj, target, level); 40887ec681f3Smrg 40897ec681f3Smrg texture_sub_image(ctx, 3, texObj, texImage, target, level, 40907ec681f3Smrg xoffset, yoffset, zoffset, width, height, depth, 40917ec681f3Smrg format, type, pixels); 40927ec681f3Smrg} 40937ec681f3Smrg 40947ec681f3Smrg 40957ec681f3Smrgvoid GLAPIENTRY 40967ec681f3Smrg_mesa_TextureSubImage3D(GLuint texture, GLint level, 40977ec681f3Smrg GLint xoffset, GLint yoffset, GLint zoffset, 40987ec681f3Smrg GLsizei width, GLsizei height, GLsizei depth, 40997ec681f3Smrg GLenum format, GLenum type, 41007ec681f3Smrg const GLvoid *pixels) 41017ec681f3Smrg{ 41027ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 41037ec681f3Smrg texturesubimage_error(ctx, 3, texture, 0, level, xoffset, yoffset, zoffset, 41047ec681f3Smrg width, height, depth, format, type, pixels, 41057ec681f3Smrg "glTextureSubImage3D", false); 41067ec681f3Smrg} 41077ec681f3Smrg 41087ec681f3Smrg 41097ec681f3Smrg/** 41107ec681f3Smrg * For glCopyTexSubImage, return the source renderbuffer to copy texel data 4111af69d88dSmrg * from. This depends on whether the texture contains color or depth values. 4112af69d88dSmrg */ 4113af69d88dSmrgstatic struct gl_renderbuffer * 4114af69d88dSmrgget_copy_tex_image_source(struct gl_context *ctx, mesa_format texFormat) 4115af69d88dSmrg{ 4116af69d88dSmrg if (_mesa_get_format_bits(texFormat, GL_DEPTH_BITS) > 0) { 4117af69d88dSmrg /* reading from depth/stencil buffer */ 4118af69d88dSmrg return ctx->ReadBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; 411901e04c3fSmrg } else if (_mesa_get_format_bits(texFormat, GL_STENCIL_BITS) > 0) { 412001e04c3fSmrg return ctx->ReadBuffer->Attachment[BUFFER_STENCIL].Renderbuffer; 412101e04c3fSmrg } else { 4122af69d88dSmrg /* copying from color buffer */ 4123af69d88dSmrg return ctx->ReadBuffer->_ColorReadBuffer; 4124af69d88dSmrg } 4125af69d88dSmrg} 4126af69d88dSmrg 412701e04c3fSmrg 4128af69d88dSmrgstatic void 4129af69d88dSmrgcopytexsubimage_by_slice(struct gl_context *ctx, 4130af69d88dSmrg struct gl_texture_image *texImage, 4131af69d88dSmrg GLuint dims, 4132af69d88dSmrg GLint xoffset, GLint yoffset, GLint zoffset, 4133af69d88dSmrg struct gl_renderbuffer *rb, 4134af69d88dSmrg GLint x, GLint y, 4135af69d88dSmrg GLsizei width, GLsizei height) 4136af69d88dSmrg{ 4137af69d88dSmrg if (texImage->TexObject->Target == GL_TEXTURE_1D_ARRAY) { 4138af69d88dSmrg int slice; 4139af69d88dSmrg 4140af69d88dSmrg /* For 1D arrays, we copy each scanline of the source rectangle into the 4141af69d88dSmrg * next array slice. 4142af69d88dSmrg */ 4143af69d88dSmrg assert(zoffset == 0); 4144af69d88dSmrg 4145af69d88dSmrg for (slice = 0; slice < height; slice++) { 4146af69d88dSmrg assert(yoffset + slice < texImage->Height); 4147af69d88dSmrg ctx->Driver.CopyTexSubImage(ctx, 2, texImage, 4148af69d88dSmrg xoffset, 0, yoffset + slice, 4149af69d88dSmrg rb, x, y + slice, width, 1); 4150af69d88dSmrg } 4151af69d88dSmrg } else { 4152af69d88dSmrg ctx->Driver.CopyTexSubImage(ctx, dims, texImage, 4153af69d88dSmrg xoffset, yoffset, zoffset, 4154af69d88dSmrg rb, x, y, width, height); 4155af69d88dSmrg } 4156af69d88dSmrg} 4157af69d88dSmrg 415801e04c3fSmrg 4159af69d88dSmrgstatic GLboolean 416001e04c3fSmrgformats_differ_in_component_sizes(mesa_format f1, mesa_format f2) 4161af69d88dSmrg{ 4162af69d88dSmrg GLint f1_r_bits = _mesa_get_format_bits(f1, GL_RED_BITS); 4163af69d88dSmrg GLint f1_g_bits = _mesa_get_format_bits(f1, GL_GREEN_BITS); 4164af69d88dSmrg GLint f1_b_bits = _mesa_get_format_bits(f1, GL_BLUE_BITS); 4165af69d88dSmrg GLint f1_a_bits = _mesa_get_format_bits(f1, GL_ALPHA_BITS); 4166af69d88dSmrg 4167af69d88dSmrg GLint f2_r_bits = _mesa_get_format_bits(f2, GL_RED_BITS); 4168af69d88dSmrg GLint f2_g_bits = _mesa_get_format_bits(f2, GL_GREEN_BITS); 4169af69d88dSmrg GLint f2_b_bits = _mesa_get_format_bits(f2, GL_BLUE_BITS); 4170af69d88dSmrg GLint f2_a_bits = _mesa_get_format_bits(f2, GL_ALPHA_BITS); 4171af69d88dSmrg 4172af69d88dSmrg if ((f1_r_bits && f2_r_bits && f1_r_bits != f2_r_bits) 4173af69d88dSmrg || (f1_g_bits && f2_g_bits && f1_g_bits != f2_g_bits) 4174af69d88dSmrg || (f1_b_bits && f2_b_bits && f1_b_bits != f2_b_bits) 4175af69d88dSmrg || (f1_a_bits && f2_a_bits && f1_a_bits != f2_a_bits)) 4176af69d88dSmrg return GL_TRUE; 4177af69d88dSmrg 4178af69d88dSmrg return GL_FALSE; 4179af69d88dSmrg} 4180af69d88dSmrg 418101e04c3fSmrg 41823464ebd5Sriastradh/** 418301e04c3fSmrg * Check if the given texture format and size arguments match those 418401e04c3fSmrg * of the texture image. 418501e04c3fSmrg * \param return true if arguments match, false otherwise. 418601e04c3fSmrg */ 418701e04c3fSmrgstatic bool 418801e04c3fSmrgcan_avoid_reallocation(const struct gl_texture_image *texImage, 418901e04c3fSmrg GLenum internalFormat, 419001e04c3fSmrg mesa_format texFormat, GLsizei width, 419101e04c3fSmrg GLsizei height, GLint border) 419201e04c3fSmrg{ 419301e04c3fSmrg if (texImage->InternalFormat != internalFormat) 419401e04c3fSmrg return false; 419501e04c3fSmrg if (texImage->TexFormat != texFormat) 419601e04c3fSmrg return false; 419701e04c3fSmrg if (texImage->Border != border) 419801e04c3fSmrg return false; 419901e04c3fSmrg if (texImage->Width2 != width) 420001e04c3fSmrg return false; 420101e04c3fSmrg if (texImage->Height2 != height) 420201e04c3fSmrg return false; 420301e04c3fSmrg return true; 420401e04c3fSmrg} 420501e04c3fSmrg 420601e04c3fSmrg 420701e04c3fSmrg/** 420801e04c3fSmrg * Implementation for glCopyTex(ture)SubImage1/2/3D() functions. 42093464ebd5Sriastradh */ 42103464ebd5Sriastradhstatic void 421101e04c3fSmrgcopy_texture_sub_image(struct gl_context *ctx, GLuint dims, 421201e04c3fSmrg struct gl_texture_object *texObj, 421301e04c3fSmrg GLenum target, GLint level, 421401e04c3fSmrg GLint xoffset, GLint yoffset, GLint zoffset, 421501e04c3fSmrg GLint x, GLint y, GLsizei width, GLsizei height) 421601e04c3fSmrg{ 421701e04c3fSmrg struct gl_texture_image *texImage; 421801e04c3fSmrg 421901e04c3fSmrg _mesa_lock_texture(ctx, texObj); 422001e04c3fSmrg 422101e04c3fSmrg texImage = _mesa_select_tex_image(texObj, target, level); 422201e04c3fSmrg 422301e04c3fSmrg /* If we have a border, offset=-1 is legal. Bias by border width. */ 422401e04c3fSmrg switch (dims) { 422501e04c3fSmrg case 3: 422601e04c3fSmrg if (target != GL_TEXTURE_2D_ARRAY) 422701e04c3fSmrg zoffset += texImage->Border; 42287ec681f3Smrg FALLTHROUGH; 422901e04c3fSmrg case 2: 423001e04c3fSmrg if (target != GL_TEXTURE_1D_ARRAY) 423101e04c3fSmrg yoffset += texImage->Border; 42327ec681f3Smrg FALLTHROUGH; 423301e04c3fSmrg case 1: 423401e04c3fSmrg xoffset += texImage->Border; 423501e04c3fSmrg } 423601e04c3fSmrg 42377ec681f3Smrg if (ctx->Const.NoClippingOnCopyTex || 42387ec681f3Smrg _mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, 423901e04c3fSmrg &width, &height)) { 424001e04c3fSmrg struct gl_renderbuffer *srcRb = 424101e04c3fSmrg get_copy_tex_image_source(ctx, texImage->TexFormat); 424201e04c3fSmrg 424301e04c3fSmrg copytexsubimage_by_slice(ctx, texImage, dims, xoffset, yoffset, zoffset, 424401e04c3fSmrg srcRb, x, y, width, height); 424501e04c3fSmrg 424601e04c3fSmrg check_gen_mipmap(ctx, target, texObj, level); 424701e04c3fSmrg 424801e04c3fSmrg /* NOTE: Don't signal _NEW_TEXTURE_OBJECT since we've only changed 424901e04c3fSmrg * the texel data, not the texture format, size, etc. 425001e04c3fSmrg */ 425101e04c3fSmrg } 425201e04c3fSmrg 425301e04c3fSmrg _mesa_unlock_texture(ctx, texObj); 425401e04c3fSmrg} 425501e04c3fSmrg 425601e04c3fSmrg 425701e04c3fSmrgstatic void 425801e04c3fSmrgcopy_texture_sub_image_err(struct gl_context *ctx, GLuint dims, 425901e04c3fSmrg struct gl_texture_object *texObj, 426001e04c3fSmrg GLenum target, GLint level, 426101e04c3fSmrg GLint xoffset, GLint yoffset, GLint zoffset, 426201e04c3fSmrg GLint x, GLint y, GLsizei width, GLsizei height, 426301e04c3fSmrg const char *caller) 426401e04c3fSmrg{ 42657ec681f3Smrg FLUSH_VERTICES(ctx, 0, 0); 426601e04c3fSmrg 426701e04c3fSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 426801e04c3fSmrg _mesa_debug(ctx, "%s %s %d %d %d %d %d %d %d %d\n", caller, 426901e04c3fSmrg _mesa_enum_to_string(target), 427001e04c3fSmrg level, xoffset, yoffset, zoffset, x, y, width, height); 427101e04c3fSmrg 42727ec681f3Smrg _mesa_update_pixel(ctx); 42737ec681f3Smrg 427401e04c3fSmrg if (ctx->NewState & NEW_COPY_TEX_STATE) 427501e04c3fSmrg _mesa_update_state(ctx); 427601e04c3fSmrg 427701e04c3fSmrg if (copytexsubimage_error_check(ctx, dims, texObj, target, level, 427801e04c3fSmrg xoffset, yoffset, zoffset, 427901e04c3fSmrg width, height, caller)) { 428001e04c3fSmrg return; 428101e04c3fSmrg } 428201e04c3fSmrg 428301e04c3fSmrg copy_texture_sub_image(ctx, dims, texObj, target, level, xoffset, yoffset, 428401e04c3fSmrg zoffset, x, y, width, height); 428501e04c3fSmrg} 428601e04c3fSmrg 428701e04c3fSmrg 428801e04c3fSmrgstatic void 428901e04c3fSmrgcopy_texture_sub_image_no_error(struct gl_context *ctx, GLuint dims, 429001e04c3fSmrg struct gl_texture_object *texObj, 429101e04c3fSmrg GLenum target, GLint level, 429201e04c3fSmrg GLint xoffset, GLint yoffset, GLint zoffset, 429301e04c3fSmrg GLint x, GLint y, GLsizei width, GLsizei height) 429401e04c3fSmrg{ 42957ec681f3Smrg FLUSH_VERTICES(ctx, 0, 0); 42967ec681f3Smrg 42977ec681f3Smrg _mesa_update_pixel(ctx); 429801e04c3fSmrg 429901e04c3fSmrg if (ctx->NewState & NEW_COPY_TEX_STATE) 430001e04c3fSmrg _mesa_update_state(ctx); 430101e04c3fSmrg 430201e04c3fSmrg copy_texture_sub_image(ctx, dims, texObj, target, level, xoffset, yoffset, 430301e04c3fSmrg zoffset, x, y, width, height); 430401e04c3fSmrg} 430501e04c3fSmrg 430601e04c3fSmrg 430701e04c3fSmrg/** 430801e04c3fSmrg * Implement the glCopyTexImage1/2D() functions. 430901e04c3fSmrg */ 431001e04c3fSmrgstatic ALWAYS_INLINE void 43117ec681f3Smrgcopyteximage(struct gl_context *ctx, GLuint dims, struct gl_texture_object *texObj, 43123464ebd5Sriastradh GLenum target, GLint level, GLenum internalFormat, 431301e04c3fSmrg GLint x, GLint y, GLsizei width, GLsizei height, GLint border, 431401e04c3fSmrg bool no_error) 43157117f1b4Smrg{ 43167117f1b4Smrg struct gl_texture_image *texImage; 4317af69d88dSmrg mesa_format texFormat; 43183464ebd5Sriastradh 43197ec681f3Smrg FLUSH_VERTICES(ctx, 0, 0); 43207117f1b4Smrg 43214a49301eSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 43223464ebd5Sriastradh _mesa_debug(ctx, "glCopyTexImage%uD %s %d %s %d %d %d %d %d\n", 43233464ebd5Sriastradh dims, 432401e04c3fSmrg _mesa_enum_to_string(target), level, 432501e04c3fSmrg _mesa_enum_to_string(internalFormat), 43264a49301eSmrg x, y, width, height, border); 43274a49301eSmrg 43287ec681f3Smrg _mesa_update_pixel(ctx); 43297ec681f3Smrg 4330c1f859d4Smrg if (ctx->NewState & NEW_COPY_TEX_STATE) 43317117f1b4Smrg _mesa_update_state(ctx); 43327117f1b4Smrg 433301e04c3fSmrg if (!no_error) { 43347ec681f3Smrg if (copytexture_error_check(ctx, dims, target, texObj, level, 43357ec681f3Smrg internalFormat, border)) 433601e04c3fSmrg return; 43377117f1b4Smrg 433801e04c3fSmrg if (!_mesa_legal_texture_dimensions(ctx, target, level, width, height, 433901e04c3fSmrg 1, border)) { 434001e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, 434101e04c3fSmrg "glCopyTexImage%uD(invalid width=%d or height=%d)", 434201e04c3fSmrg dims, width, height); 434301e04c3fSmrg return; 434401e04c3fSmrg } 4345af69d88dSmrg } 4346af69d88dSmrg 4347af69d88dSmrg assert(texObj); 4348af69d88dSmrg 4349af69d88dSmrg texFormat = _mesa_choose_texture_format(ctx, texObj, target, level, 4350af69d88dSmrg internalFormat, GL_NONE, GL_NONE); 4351af69d88dSmrg 435201e04c3fSmrg /* First check if reallocating the texture buffer can be avoided. 435301e04c3fSmrg * Without the realloc the copy can be 20x faster. 435401e04c3fSmrg */ 435501e04c3fSmrg _mesa_lock_texture(ctx, texObj); 435601e04c3fSmrg { 435701e04c3fSmrg texImage = _mesa_select_tex_image(texObj, target, level); 435801e04c3fSmrg if (texImage && can_avoid_reallocation(texImage, internalFormat, texFormat, 435901e04c3fSmrg width, height, border)) { 436001e04c3fSmrg _mesa_unlock_texture(ctx, texObj); 436101e04c3fSmrg if (no_error) { 436201e04c3fSmrg copy_texture_sub_image_no_error(ctx, dims, texObj, target, level, 0, 436301e04c3fSmrg 0, 0, x, y, width, height); 436401e04c3fSmrg } else { 436501e04c3fSmrg copy_texture_sub_image_err(ctx, dims, texObj, target, level, 0, 0, 436601e04c3fSmrg 0, x, y, width, height,"CopyTexImage"); 436701e04c3fSmrg } 436801e04c3fSmrg return; 436901e04c3fSmrg } 437001e04c3fSmrg } 437101e04c3fSmrg _mesa_unlock_texture(ctx, texObj); 437201e04c3fSmrg _mesa_perf_debug(ctx, MESA_DEBUG_SEVERITY_LOW, "glCopyTexImage " 437301e04c3fSmrg "can't avoid reallocating texture storage\n"); 437401e04c3fSmrg 437501e04c3fSmrg if (!no_error && _mesa_is_gles3(ctx)) { 437601e04c3fSmrg struct gl_renderbuffer *rb = 437701e04c3fSmrg _mesa_get_read_renderbuffer_for_format(ctx, internalFormat); 4378af69d88dSmrg 4379af69d88dSmrg if (_mesa_is_enum_format_unsized(internalFormat)) { 4380af69d88dSmrg /* Conversion from GL_RGB10_A2 source buffer format is not allowed in 4381af69d88dSmrg * OpenGL ES 3.0. Khronos bug# 9807. 4382af69d88dSmrg */ 4383af69d88dSmrg if (rb->InternalFormat == GL_RGB10_A2) { 4384af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 438501e04c3fSmrg "glCopyTexImage%uD(Reading from GL_RGB10_A2 buffer" 438601e04c3fSmrg " and writing to unsized internal format)", dims); 4387af69d88dSmrg return; 4388af69d88dSmrg } 4389af69d88dSmrg } 4390af69d88dSmrg /* From Page 139 of OpenGL ES 3.0 spec: 4391af69d88dSmrg * "If internalformat is sized, the internal format of the new texel 4392af69d88dSmrg * array is internalformat, and this is also the new texel array’s 4393af69d88dSmrg * effective internal format. If the component sizes of internalformat 4394af69d88dSmrg * do not exactly match the corresponding component sizes of the source 4395af69d88dSmrg * buffer’s effective internal format, described below, an 4396af69d88dSmrg * INVALID_OPERATION error is generated. If internalformat is unsized, 4397af69d88dSmrg * the internal format of the new texel array is the effective internal 4398af69d88dSmrg * format of the source buffer, and this is also the new texel array’s 4399af69d88dSmrg * effective internal format. 4400af69d88dSmrg */ 4401af69d88dSmrg else if (formats_differ_in_component_sizes (texFormat, rb->Format)) { 4402af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 440301e04c3fSmrg "glCopyTexImage%uD(component size changed in" 4404af69d88dSmrg " internal format)", dims); 4405af69d88dSmrg return; 4406af69d88dSmrg } 4407af69d88dSmrg } 4408af69d88dSmrg 4409af69d88dSmrg assert(texFormat != MESA_FORMAT_NONE); 4410af69d88dSmrg 4411af69d88dSmrg if (!ctx->Driver.TestProxyTexImage(ctx, proxy_target(target), 441201e04c3fSmrg 0, level, texFormat, 1, 441301e04c3fSmrg width, height, 1)) { 4414af69d88dSmrg _mesa_error(ctx, GL_OUT_OF_MEMORY, 4415af69d88dSmrg "glCopyTexImage%uD(image too large)", dims); 4416af69d88dSmrg return; 4417af69d88dSmrg } 4418af69d88dSmrg 4419af69d88dSmrg if (border && ctx->Const.StripTextureBorder) { 4420af69d88dSmrg x += border; 4421af69d88dSmrg width -= border * 2; 4422af69d88dSmrg if (dims == 2) { 442301e04c3fSmrg y += border; 442401e04c3fSmrg height -= border * 2; 4425af69d88dSmrg } 4426af69d88dSmrg border = 0; 4427af69d88dSmrg } 44287117f1b4Smrg 44297117f1b4Smrg _mesa_lock_texture(ctx, texObj); 44307117f1b4Smrg { 44317ec681f3Smrg texObj->External = GL_FALSE; 44327117f1b4Smrg texImage = _mesa_get_tex_image(ctx, texObj, target, level); 44337117f1b4Smrg 44347117f1b4Smrg if (!texImage) { 443501e04c3fSmrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage%uD", dims); 44367117f1b4Smrg } 44374a49301eSmrg else { 4438af69d88dSmrg GLint srcX = x, srcY = y, dstX = 0, dstY = 0, dstZ = 0; 443901e04c3fSmrg const GLuint face = _mesa_tex_target_to_face(target); 44404a49301eSmrg 4441af69d88dSmrg /* Free old texture image */ 4442af69d88dSmrg ctx->Driver.FreeTextureImageBuffer(ctx, texImage); 44434a49301eSmrg 4444af69d88dSmrg _mesa_init_teximage_fields(ctx, texImage, width, height, 1, 4445af69d88dSmrg border, internalFormat, texFormat); 44467117f1b4Smrg 4447af69d88dSmrg if (width && height) { 44483464ebd5Sriastradh /* Allocate texture memory (no pixel data yet) */ 4449af69d88dSmrg ctx->Driver.AllocTextureImageBuffer(ctx, texImage); 44507117f1b4Smrg 44517ec681f3Smrg if (ctx->Const.NoClippingOnCopyTex || 44527ec681f3Smrg _mesa_clip_copytexsubimage(ctx, &dstX, &dstY, &srcX, &srcY, 44533464ebd5Sriastradh &width, &height)) { 4454af69d88dSmrg struct gl_renderbuffer *srcRb = 4455af69d88dSmrg get_copy_tex_image_source(ctx, texImage->TexFormat); 4456af69d88dSmrg 4457af69d88dSmrg copytexsubimage_by_slice(ctx, texImage, dims, 4458af69d88dSmrg dstX, dstY, dstZ, 4459af69d88dSmrg srcRb, srcX, srcY, width, height); 44603464ebd5Sriastradh } 44614a49301eSmrg 44623464ebd5Sriastradh check_gen_mipmap(ctx, target, texObj, level); 4463af69d88dSmrg } 44644a49301eSmrg 4465af69d88dSmrg _mesa_update_fbo_texture(ctx, texObj, face, level); 44664a49301eSmrg 4467af69d88dSmrg _mesa_dirty_texobj(ctx, texObj); 44684a49301eSmrg } 44697117f1b4Smrg } 44707117f1b4Smrg _mesa_unlock_texture(ctx, texObj); 44717117f1b4Smrg} 44727117f1b4Smrg 44737117f1b4Smrg 447401e04c3fSmrgstatic void 44757ec681f3Smrgcopyteximage_err(struct gl_context *ctx, GLuint dims, 44767ec681f3Smrg GLenum target, 447701e04c3fSmrg GLint level, GLenum internalFormat, GLint x, GLint y, 447801e04c3fSmrg GLsizei width, GLsizei height, GLint border) 447901e04c3fSmrg{ 44807ec681f3Smrg struct gl_texture_object* texObj = _mesa_get_current_tex_object(ctx, target); 44817ec681f3Smrg copyteximage(ctx, dims, texObj, target, level, internalFormat, x, y, width, height, 448201e04c3fSmrg border, false); 448301e04c3fSmrg} 448401e04c3fSmrg 448501e04c3fSmrg 448601e04c3fSmrgstatic void 448701e04c3fSmrgcopyteximage_no_error(struct gl_context *ctx, GLuint dims, GLenum target, 448801e04c3fSmrg GLint level, GLenum internalFormat, GLint x, GLint y, 448901e04c3fSmrg GLsizei width, GLsizei height, GLint border) 449001e04c3fSmrg{ 44917ec681f3Smrg struct gl_texture_object* texObj = _mesa_get_current_tex_object(ctx, target); 44927ec681f3Smrg copyteximage(ctx, dims, texObj, target, level, internalFormat, x, y, width, height, 449301e04c3fSmrg border, true); 449401e04c3fSmrg} 449501e04c3fSmrg 449601e04c3fSmrg 449701e04c3fSmrgvoid GLAPIENTRY 449801e04c3fSmrg_mesa_CopyTexImage1D( GLenum target, GLint level, 449901e04c3fSmrg GLenum internalFormat, 450001e04c3fSmrg GLint x, GLint y, 450101e04c3fSmrg GLsizei width, GLint border ) 450201e04c3fSmrg{ 450301e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 450401e04c3fSmrg copyteximage_err(ctx, 1, target, level, internalFormat, x, y, width, 1, 450501e04c3fSmrg border); 450601e04c3fSmrg} 450701e04c3fSmrg 450801e04c3fSmrg 45097ec681f3Smrgvoid GLAPIENTRY 45107ec681f3Smrg_mesa_CopyTextureImage1DEXT( GLuint texture, GLenum target, GLint level, 45117ec681f3Smrg GLenum internalFormat, 45127ec681f3Smrg GLint x, GLint y, 45137ec681f3Smrg GLsizei width, GLint border ) 45147ec681f3Smrg{ 45157ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 45167ec681f3Smrg struct gl_texture_object* texObj = 45177ec681f3Smrg _mesa_lookup_or_create_texture(ctx, target, texture, false, true, 45187ec681f3Smrg "glCopyTextureImage1DEXT"); 45197ec681f3Smrg if (!texObj) 45207ec681f3Smrg return; 45217ec681f3Smrg copyteximage(ctx, 1, texObj, target, level, internalFormat, x, y, width, 1, 45227ec681f3Smrg border, false); 45237ec681f3Smrg} 45247ec681f3Smrg 45257ec681f3Smrg 45267ec681f3Smrgvoid GLAPIENTRY 45277ec681f3Smrg_mesa_CopyMultiTexImage1DEXT( GLenum texunit, GLenum target, GLint level, 45287ec681f3Smrg GLenum internalFormat, 45297ec681f3Smrg GLint x, GLint y, 45307ec681f3Smrg GLsizei width, GLint border ) 45317ec681f3Smrg{ 45327ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 45337ec681f3Smrg struct gl_texture_object* texObj = 45347ec681f3Smrg _mesa_get_texobj_by_target_and_texunit(ctx, target, 45357ec681f3Smrg texunit - GL_TEXTURE0, 45367ec681f3Smrg false, 45377ec681f3Smrg "glCopyMultiTexImage1DEXT"); 45387ec681f3Smrg if (!texObj) 45397ec681f3Smrg return; 45407ec681f3Smrg copyteximage(ctx, 1, texObj, target, level, internalFormat, x, y, width, 1, 45417ec681f3Smrg border, false); 45427ec681f3Smrg} 45437ec681f3Smrg 45447ec681f3Smrg 454501e04c3fSmrgvoid GLAPIENTRY 454601e04c3fSmrg_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat, 454701e04c3fSmrg GLint x, GLint y, GLsizei width, GLsizei height, 454801e04c3fSmrg GLint border ) 454901e04c3fSmrg{ 455001e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 455101e04c3fSmrg copyteximage_err(ctx, 2, target, level, internalFormat, 455201e04c3fSmrg x, y, width, height, border); 455301e04c3fSmrg} 455401e04c3fSmrg 455501e04c3fSmrg 45567ec681f3Smrgvoid GLAPIENTRY 45577ec681f3Smrg_mesa_CopyTextureImage2DEXT( GLuint texture, GLenum target, GLint level, 45587ec681f3Smrg GLenum internalFormat, 45597ec681f3Smrg GLint x, GLint y, 45607ec681f3Smrg GLsizei width, GLsizei height, 45617ec681f3Smrg GLint border ) 45627ec681f3Smrg{ 45637ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 45647ec681f3Smrg struct gl_texture_object* texObj = 45657ec681f3Smrg _mesa_lookup_or_create_texture(ctx, target, texture, false, true, 45667ec681f3Smrg "glCopyTextureImage2DEXT"); 45677ec681f3Smrg if (!texObj) 45687ec681f3Smrg return; 45697ec681f3Smrg copyteximage(ctx, 2, texObj, target, level, internalFormat, x, y, width, height, 45707ec681f3Smrg border, false); 45717ec681f3Smrg} 45727ec681f3Smrg 45737ec681f3Smrg 45747ec681f3Smrgvoid GLAPIENTRY 45757ec681f3Smrg_mesa_CopyMultiTexImage2DEXT( GLenum texunit, GLenum target, GLint level, 45767ec681f3Smrg GLenum internalFormat, 45777ec681f3Smrg GLint x, GLint y, 45787ec681f3Smrg GLsizei width, GLsizei height, GLint border ) 45797ec681f3Smrg{ 45807ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 45817ec681f3Smrg struct gl_texture_object* texObj = 45827ec681f3Smrg _mesa_get_texobj_by_target_and_texunit(ctx, target, 45837ec681f3Smrg texunit - GL_TEXTURE0, 45847ec681f3Smrg false, 45857ec681f3Smrg "glCopyMultiTexImage2DEXT"); 45867ec681f3Smrg if (!texObj) 45877ec681f3Smrg return; 45887ec681f3Smrg copyteximage(ctx, 2, texObj, target, level, internalFormat, x, y, width, height, 45897ec681f3Smrg border, false); 45907ec681f3Smrg} 45917ec681f3Smrg 45927ec681f3Smrg 459301e04c3fSmrgvoid GLAPIENTRY 459401e04c3fSmrg_mesa_CopyTexImage1D_no_error(GLenum target, GLint level, GLenum internalFormat, 459501e04c3fSmrg GLint x, GLint y, GLsizei width, GLint border) 459601e04c3fSmrg{ 459701e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 459801e04c3fSmrg copyteximage_no_error(ctx, 1, target, level, internalFormat, x, y, width, 1, 459901e04c3fSmrg border); 460001e04c3fSmrg} 460101e04c3fSmrg 460201e04c3fSmrg 460301e04c3fSmrgvoid GLAPIENTRY 460401e04c3fSmrg_mesa_CopyTexImage2D_no_error(GLenum target, GLint level, GLenum internalFormat, 460501e04c3fSmrg GLint x, GLint y, GLsizei width, GLsizei height, 460601e04c3fSmrg GLint border) 460701e04c3fSmrg{ 460801e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 460901e04c3fSmrg copyteximage_no_error(ctx, 2, target, level, internalFormat, 461001e04c3fSmrg x, y, width, height, border); 461101e04c3fSmrg} 461201e04c3fSmrg 461301e04c3fSmrg 461401e04c3fSmrgvoid GLAPIENTRY 461501e04c3fSmrg_mesa_CopyTexSubImage1D(GLenum target, GLint level, 461601e04c3fSmrg GLint xoffset, GLint x, GLint y, GLsizei width) 461701e04c3fSmrg{ 461801e04c3fSmrg struct gl_texture_object* texObj; 461901e04c3fSmrg const char *self = "glCopyTexSubImage1D"; 462001e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 462101e04c3fSmrg 462201e04c3fSmrg /* Check target (proxies not allowed). Target must be checked prior to 462301e04c3fSmrg * calling _mesa_get_current_tex_object. 462401e04c3fSmrg */ 462501e04c3fSmrg if (!legal_texsubimage_target(ctx, 1, target, false)) { 462601e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", self, 462701e04c3fSmrg _mesa_enum_to_string(target)); 462801e04c3fSmrg return; 462901e04c3fSmrg } 463001e04c3fSmrg 463101e04c3fSmrg texObj = _mesa_get_current_tex_object(ctx, target); 463201e04c3fSmrg if (!texObj) 463301e04c3fSmrg return; 463401e04c3fSmrg 463501e04c3fSmrg copy_texture_sub_image_err(ctx, 1, texObj, target, level, xoffset, 0, 0, 463601e04c3fSmrg x, y, width, 1, self); 463701e04c3fSmrg} 463801e04c3fSmrg 463901e04c3fSmrg 464001e04c3fSmrgvoid GLAPIENTRY 464101e04c3fSmrg_mesa_CopyTexSubImage2D(GLenum target, GLint level, 464201e04c3fSmrg GLint xoffset, GLint yoffset, 464301e04c3fSmrg GLint x, GLint y, GLsizei width, GLsizei height) 464401e04c3fSmrg{ 464501e04c3fSmrg struct gl_texture_object* texObj; 464601e04c3fSmrg const char *self = "glCopyTexSubImage2D"; 464701e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 464801e04c3fSmrg 464901e04c3fSmrg /* Check target (proxies not allowed). Target must be checked prior to 465001e04c3fSmrg * calling _mesa_get_current_tex_object. 465101e04c3fSmrg */ 465201e04c3fSmrg if (!legal_texsubimage_target(ctx, 2, target, false)) { 465301e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", self, 465401e04c3fSmrg _mesa_enum_to_string(target)); 465501e04c3fSmrg return; 465601e04c3fSmrg } 465701e04c3fSmrg 465801e04c3fSmrg texObj = _mesa_get_current_tex_object(ctx, target); 465901e04c3fSmrg if (!texObj) 466001e04c3fSmrg return; 466101e04c3fSmrg 466201e04c3fSmrg copy_texture_sub_image_err(ctx, 2, texObj, target, level, xoffset, yoffset, 466301e04c3fSmrg 0, x, y, width, height, self); 466401e04c3fSmrg} 466501e04c3fSmrg 466601e04c3fSmrg 466701e04c3fSmrgvoid GLAPIENTRY 466801e04c3fSmrg_mesa_CopyTexSubImage3D(GLenum target, GLint level, 466901e04c3fSmrg GLint xoffset, GLint yoffset, GLint zoffset, 467001e04c3fSmrg GLint x, GLint y, GLsizei width, GLsizei height) 467101e04c3fSmrg{ 467201e04c3fSmrg struct gl_texture_object* texObj; 467301e04c3fSmrg const char *self = "glCopyTexSubImage3D"; 467401e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 467501e04c3fSmrg 467601e04c3fSmrg /* Check target (proxies not allowed). Target must be checked prior to 467701e04c3fSmrg * calling _mesa_get_current_tex_object. 467801e04c3fSmrg */ 467901e04c3fSmrg if (!legal_texsubimage_target(ctx, 3, target, false)) { 468001e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", self, 468101e04c3fSmrg _mesa_enum_to_string(target)); 468201e04c3fSmrg return; 468301e04c3fSmrg } 468401e04c3fSmrg 468501e04c3fSmrg texObj = _mesa_get_current_tex_object(ctx, target); 468601e04c3fSmrg if (!texObj) 468701e04c3fSmrg return; 468801e04c3fSmrg 468901e04c3fSmrg copy_texture_sub_image_err(ctx, 3, texObj, target, level, xoffset, yoffset, 469001e04c3fSmrg zoffset, x, y, width, height, self); 469101e04c3fSmrg} 469201e04c3fSmrg 469301e04c3fSmrg 469401e04c3fSmrgvoid GLAPIENTRY 469501e04c3fSmrg_mesa_CopyTextureSubImage1D(GLuint texture, GLint level, 469601e04c3fSmrg GLint xoffset, GLint x, GLint y, GLsizei width) 469701e04c3fSmrg{ 469801e04c3fSmrg struct gl_texture_object* texObj; 469901e04c3fSmrg const char *self = "glCopyTextureSubImage1D"; 470001e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 470101e04c3fSmrg 470201e04c3fSmrg texObj = _mesa_lookup_texture_err(ctx, texture, self); 470301e04c3fSmrg if (!texObj) 470401e04c3fSmrg return; 470501e04c3fSmrg 470601e04c3fSmrg /* Check target (proxies not allowed). */ 470701e04c3fSmrg if (!legal_texsubimage_target(ctx, 1, texObj->Target, true)) { 470801e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid target %s)", self, 470901e04c3fSmrg _mesa_enum_to_string(texObj->Target)); 471001e04c3fSmrg return; 471101e04c3fSmrg } 471201e04c3fSmrg 471301e04c3fSmrg copy_texture_sub_image_err(ctx, 1, texObj, texObj->Target, level, xoffset, 0, 471401e04c3fSmrg 0, x, y, width, 1, self); 471501e04c3fSmrg} 471601e04c3fSmrg 471701e04c3fSmrg 47187ec681f3Smrgvoid GLAPIENTRY 47197ec681f3Smrg_mesa_CopyTextureSubImage1DEXT(GLuint texture, GLenum target, GLint level, 47207ec681f3Smrg GLint xoffset, GLint x, GLint y, GLsizei width) 47217ec681f3Smrg{ 47227ec681f3Smrg struct gl_texture_object* texObj; 47237ec681f3Smrg const char *self = "glCopyTextureSubImage1DEXT"; 47247ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 47257ec681f3Smrg 47267ec681f3Smrg texObj = _mesa_lookup_or_create_texture(ctx, target, texture, false, true, 47277ec681f3Smrg self); 47287ec681f3Smrg if (!texObj) 47297ec681f3Smrg return; 47307ec681f3Smrg 47317ec681f3Smrg /* Check target (proxies not allowed). */ 47327ec681f3Smrg if (!legal_texsubimage_target(ctx, 1, texObj->Target, true)) { 47337ec681f3Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid target %s)", self, 47347ec681f3Smrg _mesa_enum_to_string(texObj->Target)); 47357ec681f3Smrg return; 47367ec681f3Smrg } 47377ec681f3Smrg 47387ec681f3Smrg copy_texture_sub_image_err(ctx, 1, texObj, texObj->Target, level, xoffset, 0, 47397ec681f3Smrg 0, x, y, width, 1, self); 47407ec681f3Smrg} 47417ec681f3Smrg 47427ec681f3Smrg 47437ec681f3Smrgvoid GLAPIENTRY 47447ec681f3Smrg_mesa_CopyMultiTexSubImage1DEXT(GLenum texunit, GLenum target, GLint level, 47457ec681f3Smrg GLint xoffset, GLint x, GLint y, GLsizei width) 47467ec681f3Smrg{ 47477ec681f3Smrg struct gl_texture_object* texObj; 47487ec681f3Smrg const char *self = "glCopyMultiTexSubImage1DEXT"; 47497ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 47507ec681f3Smrg 47517ec681f3Smrg texObj = _mesa_get_texobj_by_target_and_texunit(ctx, target, 47527ec681f3Smrg texunit - GL_TEXTURE0, 47537ec681f3Smrg false, self); 47547ec681f3Smrg if (!texObj) 47557ec681f3Smrg return; 47567ec681f3Smrg 47577ec681f3Smrg copy_texture_sub_image_err(ctx, 1, texObj, texObj->Target, level, xoffset, 0, 47587ec681f3Smrg 0, x, y, width, 1, self); 47597ec681f3Smrg} 47607ec681f3Smrg 47617ec681f3Smrg 476201e04c3fSmrgvoid GLAPIENTRY 476301e04c3fSmrg_mesa_CopyTextureSubImage2D(GLuint texture, GLint level, 476401e04c3fSmrg GLint xoffset, GLint yoffset, 476501e04c3fSmrg GLint x, GLint y, GLsizei width, GLsizei height) 476601e04c3fSmrg{ 476701e04c3fSmrg struct gl_texture_object* texObj; 476801e04c3fSmrg const char *self = "glCopyTextureSubImage2D"; 476901e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 477001e04c3fSmrg 477101e04c3fSmrg texObj = _mesa_lookup_texture_err(ctx, texture, self); 477201e04c3fSmrg if (!texObj) 477301e04c3fSmrg return; 477401e04c3fSmrg 477501e04c3fSmrg /* Check target (proxies not allowed). */ 477601e04c3fSmrg if (!legal_texsubimage_target(ctx, 2, texObj->Target, true)) { 477701e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid target %s)", self, 477801e04c3fSmrg _mesa_enum_to_string(texObj->Target)); 477901e04c3fSmrg return; 478001e04c3fSmrg } 478101e04c3fSmrg 478201e04c3fSmrg copy_texture_sub_image_err(ctx, 2, texObj, texObj->Target, level, xoffset, 478301e04c3fSmrg yoffset, 0, x, y, width, height, self); 478401e04c3fSmrg} 478501e04c3fSmrg 478601e04c3fSmrg 47877ec681f3Smrgvoid GLAPIENTRY 47887ec681f3Smrg_mesa_CopyTextureSubImage2DEXT(GLuint texture, GLenum target, GLint level, 47897ec681f3Smrg GLint xoffset, GLint yoffset, 47907ec681f3Smrg GLint x, GLint y, GLsizei width, GLsizei height) 47917ec681f3Smrg{ 47927ec681f3Smrg struct gl_texture_object* texObj; 47937ec681f3Smrg const char *self = "glCopyTextureSubImage2DEXT"; 47947ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 47957ec681f3Smrg 47967ec681f3Smrg texObj = _mesa_lookup_or_create_texture(ctx, target, texture, false, true, self); 47977ec681f3Smrg if (!texObj) 47987ec681f3Smrg return; 47997ec681f3Smrg 48007ec681f3Smrg /* Check target (proxies not allowed). */ 48017ec681f3Smrg if (!legal_texsubimage_target(ctx, 2, texObj->Target, true)) { 48027ec681f3Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid target %s)", self, 48037ec681f3Smrg _mesa_enum_to_string(texObj->Target)); 48047ec681f3Smrg return; 48057ec681f3Smrg } 48067ec681f3Smrg 48077ec681f3Smrg copy_texture_sub_image_err(ctx, 2, texObj, texObj->Target, level, xoffset, 48087ec681f3Smrg yoffset, 0, x, y, width, height, self); 48097ec681f3Smrg} 48107ec681f3Smrg 48117ec681f3Smrg 48127ec681f3Smrgvoid GLAPIENTRY 48137ec681f3Smrg_mesa_CopyMultiTexSubImage2DEXT(GLenum texunit, GLenum target, GLint level, 48147ec681f3Smrg GLint xoffset, GLint yoffset, 48157ec681f3Smrg GLint x, GLint y, GLsizei width, GLsizei height) 48167ec681f3Smrg{ 48177ec681f3Smrg struct gl_texture_object* texObj; 48187ec681f3Smrg const char *self = "glCopyMultiTexSubImage2DEXT"; 48197ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 48207ec681f3Smrg 48217ec681f3Smrg texObj = _mesa_get_texobj_by_target_and_texunit(ctx, target, 48227ec681f3Smrg texunit - GL_TEXTURE0, 48237ec681f3Smrg false, self); 48247ec681f3Smrg if (!texObj) 48257ec681f3Smrg return; 48267ec681f3Smrg 48277ec681f3Smrg copy_texture_sub_image_err(ctx, 2, texObj, texObj->Target, level, xoffset, 48287ec681f3Smrg yoffset, 0, x, y, width, height, self); 48297ec681f3Smrg} 48307ec681f3Smrg 483101e04c3fSmrgvoid GLAPIENTRY 483201e04c3fSmrg_mesa_CopyTextureSubImage3D(GLuint texture, GLint level, 483301e04c3fSmrg GLint xoffset, GLint yoffset, GLint zoffset, 483401e04c3fSmrg GLint x, GLint y, GLsizei width, GLsizei height) 483501e04c3fSmrg{ 483601e04c3fSmrg struct gl_texture_object* texObj; 483701e04c3fSmrg const char *self = "glCopyTextureSubImage3D"; 483801e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 483901e04c3fSmrg 484001e04c3fSmrg texObj = _mesa_lookup_texture_err(ctx, texture, self); 484101e04c3fSmrg if (!texObj) 484201e04c3fSmrg return; 484301e04c3fSmrg 484401e04c3fSmrg /* Check target (proxies not allowed). */ 484501e04c3fSmrg if (!legal_texsubimage_target(ctx, 3, texObj->Target, true)) { 484601e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid target %s)", self, 484701e04c3fSmrg _mesa_enum_to_string(texObj->Target)); 484801e04c3fSmrg return; 484901e04c3fSmrg } 485001e04c3fSmrg 485101e04c3fSmrg if (texObj->Target == GL_TEXTURE_CUBE_MAP) { 485201e04c3fSmrg /* Act like CopyTexSubImage2D */ 485301e04c3fSmrg copy_texture_sub_image_err(ctx, 2, texObj, 485401e04c3fSmrg GL_TEXTURE_CUBE_MAP_POSITIVE_X + zoffset, 485501e04c3fSmrg level, xoffset, yoffset, 0, x, y, width, height, 485601e04c3fSmrg self); 485701e04c3fSmrg } 485801e04c3fSmrg else 485901e04c3fSmrg copy_texture_sub_image_err(ctx, 3, texObj, texObj->Target, level, xoffset, 486001e04c3fSmrg yoffset, zoffset, x, y, width, height, self); 486101e04c3fSmrg} 486201e04c3fSmrg 48633464ebd5Sriastradh 48647ec681f3Smrgvoid GLAPIENTRY 48657ec681f3Smrg_mesa_CopyTextureSubImage3DEXT(GLuint texture, GLenum target, GLint level, 48667ec681f3Smrg GLint xoffset, GLint yoffset, GLint zoffset, 48677ec681f3Smrg GLint x, GLint y, GLsizei width, GLsizei height) 48687ec681f3Smrg{ 48697ec681f3Smrg struct gl_texture_object* texObj; 48707ec681f3Smrg const char *self = "glCopyTextureSubImage3D"; 48717ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 48727ec681f3Smrg 48737ec681f3Smrg texObj = _mesa_lookup_or_create_texture(ctx, target, texture, false, true, self); 48747ec681f3Smrg if (!texObj) 48757ec681f3Smrg return; 48767ec681f3Smrg 48777ec681f3Smrg /* Check target (proxies not allowed). */ 48787ec681f3Smrg if (!legal_texsubimage_target(ctx, 3, texObj->Target, true)) { 48797ec681f3Smrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid target %s)", self, 48807ec681f3Smrg _mesa_enum_to_string(texObj->Target)); 48817ec681f3Smrg return; 48827ec681f3Smrg } 48837ec681f3Smrg 48847ec681f3Smrg if (texObj->Target == GL_TEXTURE_CUBE_MAP) { 48857ec681f3Smrg /* Act like CopyTexSubImage2D */ 48867ec681f3Smrg copy_texture_sub_image_err(ctx, 2, texObj, 48877ec681f3Smrg GL_TEXTURE_CUBE_MAP_POSITIVE_X + zoffset, 48887ec681f3Smrg level, xoffset, yoffset, 0, x, y, width, height, 48897ec681f3Smrg self); 48907ec681f3Smrg } 48917ec681f3Smrg else 48927ec681f3Smrg copy_texture_sub_image_err(ctx, 3, texObj, texObj->Target, level, xoffset, 48937ec681f3Smrg yoffset, zoffset, x, y, width, height, self); 48947ec681f3Smrg} 48957ec681f3Smrg 48967ec681f3Smrg 48977ec681f3Smrgvoid GLAPIENTRY 48987ec681f3Smrg_mesa_CopyMultiTexSubImage3DEXT(GLenum texunit, GLenum target, GLint level, 48997ec681f3Smrg GLint xoffset, GLint yoffset, GLint zoffset, 49007ec681f3Smrg GLint x, GLint y, GLsizei width, GLsizei height) 49017ec681f3Smrg{ 49027ec681f3Smrg struct gl_texture_object* texObj; 49037ec681f3Smrg const char *self = "glCopyMultiTexSubImage3D"; 49047ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 49057ec681f3Smrg 49067ec681f3Smrg texObj = _mesa_get_texobj_by_target_and_texunit(ctx, target, 49077ec681f3Smrg texunit - GL_TEXTURE0, 49087ec681f3Smrg false, self); 49097ec681f3Smrg if (!texObj) 49107ec681f3Smrg return; 49117ec681f3Smrg 49127ec681f3Smrg if (texObj->Target == GL_TEXTURE_CUBE_MAP) { 49137ec681f3Smrg /* Act like CopyTexSubImage2D */ 49147ec681f3Smrg copy_texture_sub_image_err(ctx, 2, texObj, 49157ec681f3Smrg GL_TEXTURE_CUBE_MAP_POSITIVE_X + zoffset, 49167ec681f3Smrg level, xoffset, yoffset, 0, x, y, width, height, 49177ec681f3Smrg self); 49187ec681f3Smrg } 49197ec681f3Smrg else 49207ec681f3Smrg copy_texture_sub_image_err(ctx, 3, texObj, texObj->Target, level, xoffset, 49217ec681f3Smrg yoffset, zoffset, x, y, width, height, self); 49227ec681f3Smrg} 49237ec681f3Smrg 49247ec681f3Smrg 49257117f1b4Smrgvoid GLAPIENTRY 492601e04c3fSmrg_mesa_CopyTexSubImage1D_no_error(GLenum target, GLint level, GLint xoffset, 492701e04c3fSmrg GLint x, GLint y, GLsizei width) 49287117f1b4Smrg{ 49297117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 49307117f1b4Smrg 493101e04c3fSmrg struct gl_texture_object* texObj = _mesa_get_current_tex_object(ctx, target); 493201e04c3fSmrg copy_texture_sub_image_no_error(ctx, 1, texObj, target, level, xoffset, 0, 0, 493301e04c3fSmrg x, y, width, 1); 493401e04c3fSmrg} 49357117f1b4Smrg 4936c1f859d4Smrg 49373464ebd5Sriastradhvoid GLAPIENTRY 493801e04c3fSmrg_mesa_CopyTexSubImage2D_no_error(GLenum target, GLint level, GLint xoffset, 493901e04c3fSmrg GLint yoffset, GLint x, GLint y, GLsizei width, 494001e04c3fSmrg GLsizei height) 49413464ebd5Sriastradh{ 49423464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 49437117f1b4Smrg 494401e04c3fSmrg struct gl_texture_object* texObj = _mesa_get_current_tex_object(ctx, target); 494501e04c3fSmrg copy_texture_sub_image_no_error(ctx, 2, texObj, target, level, xoffset, 494601e04c3fSmrg yoffset, 0, x, y, width, height); 494701e04c3fSmrg} 49487117f1b4Smrg 49497117f1b4Smrg 495001e04c3fSmrgvoid GLAPIENTRY 495101e04c3fSmrg_mesa_CopyTexSubImage3D_no_error(GLenum target, GLint level, GLint xoffset, 495201e04c3fSmrg GLint yoffset, GLint zoffset, GLint x, GLint y, 495301e04c3fSmrg GLsizei width, GLsizei height) 49547117f1b4Smrg{ 495501e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 4956af69d88dSmrg 495701e04c3fSmrg struct gl_texture_object* texObj = _mesa_get_current_tex_object(ctx, target); 495801e04c3fSmrg copy_texture_sub_image_no_error(ctx, 3, texObj, target, level, xoffset, 495901e04c3fSmrg yoffset, zoffset, x, y, width, height); 49607117f1b4Smrg} 49617117f1b4Smrg 49627117f1b4Smrg 49637117f1b4Smrgvoid GLAPIENTRY 496401e04c3fSmrg_mesa_CopyTextureSubImage1D_no_error(GLuint texture, GLint level, GLint xoffset, 496501e04c3fSmrg GLint x, GLint y, GLsizei width) 49667117f1b4Smrg{ 49677117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 49687117f1b4Smrg 496901e04c3fSmrg struct gl_texture_object* texObj = _mesa_lookup_texture(ctx, texture); 497001e04c3fSmrg copy_texture_sub_image_no_error(ctx, 1, texObj, texObj->Target, level, 497101e04c3fSmrg xoffset, 0, 0, x, y, width, 1); 497201e04c3fSmrg} 49737117f1b4Smrg 4974c1f859d4Smrg 49753464ebd5Sriastradhvoid GLAPIENTRY 497601e04c3fSmrg_mesa_CopyTextureSubImage2D_no_error(GLuint texture, GLint level, GLint xoffset, 497701e04c3fSmrg GLint yoffset, GLint x, GLint y, 497801e04c3fSmrg GLsizei width, GLsizei height) 49793464ebd5Sriastradh{ 49803464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 49814a49301eSmrg 498201e04c3fSmrg struct gl_texture_object* texObj = _mesa_lookup_texture(ctx, texture); 498301e04c3fSmrg copy_texture_sub_image_no_error(ctx, 2, texObj, texObj->Target, level, 498401e04c3fSmrg xoffset, yoffset, 0, x, y, width, height); 498501e04c3fSmrg} 4986c1f859d4Smrg 49874a49301eSmrg 49883464ebd5Sriastradhvoid GLAPIENTRY 498901e04c3fSmrg_mesa_CopyTextureSubImage3D_no_error(GLuint texture, GLint level, GLint xoffset, 499001e04c3fSmrg GLint yoffset, GLint zoffset, GLint x, 499101e04c3fSmrg GLint y, GLsizei width, GLsizei height) 49923464ebd5Sriastradh{ 49933464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 499401e04c3fSmrg 499501e04c3fSmrg struct gl_texture_object* texObj = _mesa_lookup_texture(ctx, texture); 499601e04c3fSmrg if (texObj->Target == GL_TEXTURE_CUBE_MAP) { 499701e04c3fSmrg /* Act like CopyTexSubImage2D */ 499801e04c3fSmrg copy_texture_sub_image_no_error(ctx, 2, texObj, 499901e04c3fSmrg GL_TEXTURE_CUBE_MAP_POSITIVE_X + zoffset, 500001e04c3fSmrg level, xoffset, yoffset, 0, x, y, width, 500101e04c3fSmrg height); 500201e04c3fSmrg } 500301e04c3fSmrg else 500401e04c3fSmrg copy_texture_sub_image_no_error(ctx, 3, texObj, texObj->Target, level, 500501e04c3fSmrg xoffset, yoffset, zoffset, x, y, width, 500601e04c3fSmrg height); 50077117f1b4Smrg} 50087117f1b4Smrg 500901e04c3fSmrg 5010af69d88dSmrgstatic bool 5011af69d88dSmrgcheck_clear_tex_image(struct gl_context *ctx, 5012af69d88dSmrg const char *function, 5013af69d88dSmrg struct gl_texture_image *texImage, 5014af69d88dSmrg GLenum format, GLenum type, 5015af69d88dSmrg const void *data, 5016af69d88dSmrg GLubyte *clearValue) 5017af69d88dSmrg{ 5018af69d88dSmrg struct gl_texture_object *texObj = texImage->TexObject; 5019af69d88dSmrg static const GLubyte zeroData[MAX_PIXEL_BYTES]; 5020af69d88dSmrg GLenum internalFormat = texImage->InternalFormat; 5021af69d88dSmrg GLenum err; 50227117f1b4Smrg 5023af69d88dSmrg if (texObj->Target == GL_TEXTURE_BUFFER) { 5024af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 5025af69d88dSmrg "%s(buffer texture)", function); 5026af69d88dSmrg return false; 5027af69d88dSmrg } 50287117f1b4Smrg 5029af69d88dSmrg if (_mesa_is_compressed_format(ctx, internalFormat)) { 5030af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 5031af69d88dSmrg "%s(compressed texture)", function); 5032af69d88dSmrg return false; 5033af69d88dSmrg } 50347117f1b4Smrg 5035af69d88dSmrg err = _mesa_error_check_format_and_type(ctx, format, type); 5036af69d88dSmrg if (err != GL_NO_ERROR) { 5037af69d88dSmrg _mesa_error(ctx, err, 5038af69d88dSmrg "%s(incompatible format = %s, type = %s)", 5039af69d88dSmrg function, 504001e04c3fSmrg _mesa_enum_to_string(format), 504101e04c3fSmrg _mesa_enum_to_string(type)); 5042af69d88dSmrg return false; 5043af69d88dSmrg } 50447117f1b4Smrg 5045af69d88dSmrg /* make sure internal format and format basically agree */ 5046af69d88dSmrg if (!texture_formats_agree(internalFormat, format)) { 5047af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 5048af69d88dSmrg "%s(incompatible internalFormat = %s, format = %s)", 5049af69d88dSmrg function, 505001e04c3fSmrg _mesa_enum_to_string(internalFormat), 505101e04c3fSmrg _mesa_enum_to_string(format)); 5052af69d88dSmrg return false; 5053af69d88dSmrg } 50547117f1b4Smrg 5055af69d88dSmrg if (ctx->Version >= 30 || ctx->Extensions.EXT_texture_integer) { 5056af69d88dSmrg /* both source and dest must be integer-valued, or neither */ 5057af69d88dSmrg if (_mesa_is_format_integer_color(texImage->TexFormat) != 5058af69d88dSmrg _mesa_is_enum_format_integer(format)) { 5059af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 5060af69d88dSmrg "%s(integer/non-integer format mismatch)", 5061af69d88dSmrg function); 5062af69d88dSmrg return false; 5063af69d88dSmrg } 5064af69d88dSmrg } 50654a49301eSmrg 5066af69d88dSmrg if (!_mesa_texstore(ctx, 5067af69d88dSmrg 1, /* dims */ 5068af69d88dSmrg texImage->_BaseFormat, 5069af69d88dSmrg texImage->TexFormat, 5070af69d88dSmrg 0, /* dstRowStride */ 5071af69d88dSmrg &clearValue, 5072af69d88dSmrg 1, 1, 1, /* srcWidth/Height/Depth */ 5073af69d88dSmrg format, type, 5074af69d88dSmrg data ? data : zeroData, 5075af69d88dSmrg &ctx->DefaultPacking)) { 5076af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid format)", function); 5077af69d88dSmrg return false; 5078af69d88dSmrg } 50794a49301eSmrg 5080af69d88dSmrg return true; 50814a49301eSmrg} 50824a49301eSmrg 508301e04c3fSmrg 5084af69d88dSmrgstatic struct gl_texture_object * 5085af69d88dSmrgget_tex_obj_for_clear(struct gl_context *ctx, 5086af69d88dSmrg const char *function, 5087af69d88dSmrg GLuint texture) 50887117f1b4Smrg{ 5089af69d88dSmrg struct gl_texture_object *texObj; 5090af69d88dSmrg 509101e04c3fSmrg texObj = _mesa_lookup_texture_err(ctx, texture, function); 509201e04c3fSmrg if (!texObj) 5093af69d88dSmrg return NULL; 50947117f1b4Smrg 5095af69d88dSmrg if (texObj->Target == 0) { 5096af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unbound tex)", function); 5097af69d88dSmrg return NULL; 50983464ebd5Sriastradh } 50997117f1b4Smrg 5100af69d88dSmrg return texObj; 5101af69d88dSmrg} 51023464ebd5Sriastradh 510301e04c3fSmrg 510401e04c3fSmrg/** 510501e04c3fSmrg * For clearing cube textures, the zoffset and depth parameters indicate 510601e04c3fSmrg * which cube map faces are to be cleared. This is the one case where we 510701e04c3fSmrg * need to be concerned with multiple gl_texture_images. This function 510801e04c3fSmrg * returns the array of texture images to clear for cube maps, or one 510901e04c3fSmrg * texture image otherwise. 511001e04c3fSmrg * \return number of texture images, 0 for error, 6 for cube, 1 otherwise. 511101e04c3fSmrg */ 5112af69d88dSmrgstatic int 5113af69d88dSmrgget_tex_images_for_clear(struct gl_context *ctx, 5114af69d88dSmrg const char *function, 5115af69d88dSmrg struct gl_texture_object *texObj, 5116af69d88dSmrg GLint level, 5117af69d88dSmrg struct gl_texture_image **texImages) 5118af69d88dSmrg{ 5119af69d88dSmrg GLenum target; 512001e04c3fSmrg int numFaces, i; 51213464ebd5Sriastradh 5122af69d88dSmrg if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 5123af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid level)", function); 5124af69d88dSmrg return 0; 5125af69d88dSmrg } 51263464ebd5Sriastradh 5127af69d88dSmrg if (texObj->Target == GL_TEXTURE_CUBE_MAP) { 512801e04c3fSmrg target = GL_TEXTURE_CUBE_MAP_POSITIVE_X; 512901e04c3fSmrg numFaces = MAX_FACES; 513001e04c3fSmrg } 513101e04c3fSmrg else { 513201e04c3fSmrg target = texObj->Target; 513301e04c3fSmrg numFaces = 1; 5134af69d88dSmrg } 51357117f1b4Smrg 513601e04c3fSmrg for (i = 0; i < numFaces; i++) { 513701e04c3fSmrg texImages[i] = _mesa_select_tex_image(texObj, target + i, level); 513801e04c3fSmrg if (texImages[i] == NULL) { 513901e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid level)", function); 514001e04c3fSmrg return 0; 514101e04c3fSmrg } 51423464ebd5Sriastradh } 51433464ebd5Sriastradh 514401e04c3fSmrg return numFaces; 5145af69d88dSmrg} 51463464ebd5Sriastradh 514701e04c3fSmrg 5148af69d88dSmrgvoid GLAPIENTRY 514901e04c3fSmrg_mesa_ClearTexSubImage(GLuint texture, GLint level, 515001e04c3fSmrg GLint xoffset, GLint yoffset, GLint zoffset, 515101e04c3fSmrg GLsizei width, GLsizei height, GLsizei depth, 515201e04c3fSmrg GLenum format, GLenum type, const void *data) 5153af69d88dSmrg{ 5154af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 5155af69d88dSmrg struct gl_texture_object *texObj; 5156af69d88dSmrg struct gl_texture_image *texImages[MAX_FACES]; 5157af69d88dSmrg GLubyte clearValue[MAX_FACES][MAX_PIXEL_BYTES]; 5158af69d88dSmrg int i, numImages; 5159af69d88dSmrg int minDepth, maxDepth; 51603464ebd5Sriastradh 5161af69d88dSmrg texObj = get_tex_obj_for_clear(ctx, "glClearTexSubImage", texture); 51627117f1b4Smrg 5163af69d88dSmrg if (texObj == NULL) 5164af69d88dSmrg return; 51657117f1b4Smrg 5166af69d88dSmrg _mesa_lock_texture(ctx, texObj); 51677117f1b4Smrg 5168af69d88dSmrg numImages = get_tex_images_for_clear(ctx, "glClearTexSubImage", 5169af69d88dSmrg texObj, level, texImages); 5170af69d88dSmrg if (numImages == 0) 5171af69d88dSmrg goto out; 51727117f1b4Smrg 5173af69d88dSmrg if (numImages == 1) { 5174af69d88dSmrg minDepth = -(int) texImages[0]->Border; 5175af69d88dSmrg maxDepth = texImages[0]->Depth; 5176af69d88dSmrg } else { 517701e04c3fSmrg assert(numImages == MAX_FACES); 5178af69d88dSmrg minDepth = 0; 5179af69d88dSmrg maxDepth = numImages; 5180af69d88dSmrg } 5181af69d88dSmrg 5182af69d88dSmrg if (xoffset < -(GLint) texImages[0]->Border || 5183af69d88dSmrg yoffset < -(GLint) texImages[0]->Border || 5184af69d88dSmrg zoffset < minDepth || 5185af69d88dSmrg width < 0 || 5186af69d88dSmrg height < 0 || 5187af69d88dSmrg depth < 0 || 5188af69d88dSmrg xoffset + width > texImages[0]->Width || 5189af69d88dSmrg yoffset + height > texImages[0]->Height || 5190af69d88dSmrg zoffset + depth > maxDepth) { 5191af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 5192af69d88dSmrg "glClearSubTexImage(invalid dimensions)"); 5193af69d88dSmrg goto out; 51947117f1b4Smrg } 5195af69d88dSmrg 5196af69d88dSmrg if (numImages == 1) { 519701e04c3fSmrg if (check_clear_tex_image(ctx, "glClearTexSubImage", texImages[0], 5198af69d88dSmrg format, type, data, clearValue[0])) { 5199af69d88dSmrg ctx->Driver.ClearTexSubImage(ctx, 5200af69d88dSmrg texImages[0], 5201af69d88dSmrg xoffset, yoffset, zoffset, 5202af69d88dSmrg width, height, depth, 5203af69d88dSmrg data ? clearValue[0] : NULL); 52047117f1b4Smrg } 5205af69d88dSmrg } else { 520601e04c3fSmrg /* loop over cube face images */ 5207af69d88dSmrg for (i = zoffset; i < zoffset + depth; i++) { 520801e04c3fSmrg assert(i < MAX_FACES); 520901e04c3fSmrg if (!check_clear_tex_image(ctx, "glClearTexSubImage", texImages[i], 5210af69d88dSmrg format, type, data, clearValue[i])) 5211af69d88dSmrg goto out; 52127117f1b4Smrg } 5213af69d88dSmrg for (i = zoffset; i < zoffset + depth; i++) { 5214af69d88dSmrg ctx->Driver.ClearTexSubImage(ctx, 5215af69d88dSmrg texImages[i], 5216af69d88dSmrg xoffset, yoffset, 0, 5217af69d88dSmrg width, height, 1, 5218af69d88dSmrg data ? clearValue[i] : NULL); 52197117f1b4Smrg } 52207117f1b4Smrg } 52217117f1b4Smrg 5222af69d88dSmrg out: 5223af69d88dSmrg _mesa_unlock_texture(ctx, texObj); 5224af69d88dSmrg} 52257117f1b4Smrg 522601e04c3fSmrg 5227af69d88dSmrgvoid GLAPIENTRY 5228af69d88dSmrg_mesa_ClearTexImage( GLuint texture, GLint level, 5229af69d88dSmrg GLenum format, GLenum type, const void *data ) 5230af69d88dSmrg{ 5231af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 5232af69d88dSmrg struct gl_texture_object *texObj; 5233af69d88dSmrg struct gl_texture_image *texImages[MAX_FACES]; 5234af69d88dSmrg GLubyte clearValue[MAX_FACES][MAX_PIXEL_BYTES]; 5235af69d88dSmrg int i, numImages; 52367117f1b4Smrg 5237af69d88dSmrg texObj = get_tex_obj_for_clear(ctx, "glClearTexImage", texture); 52387117f1b4Smrg 5239af69d88dSmrg if (texObj == NULL) 5240af69d88dSmrg return; 52417117f1b4Smrg 5242af69d88dSmrg _mesa_lock_texture(ctx, texObj); 52437117f1b4Smrg 5244af69d88dSmrg numImages = get_tex_images_for_clear(ctx, "glClearTexImage", 5245af69d88dSmrg texObj, level, texImages); 52464a49301eSmrg 5247af69d88dSmrg for (i = 0; i < numImages; i++) { 524801e04c3fSmrg if (!check_clear_tex_image(ctx, "glClearTexImage", texImages[i], format, 524901e04c3fSmrg type, data, clearValue[i])) 5250af69d88dSmrg goto out; 5251af69d88dSmrg } 52527117f1b4Smrg 5253af69d88dSmrg for (i = 0; i < numImages; i++) { 5254af69d88dSmrg ctx->Driver.ClearTexSubImage(ctx, texImages[i], 5255af69d88dSmrg -(GLint) texImages[i]->Border, /* xoffset */ 5256af69d88dSmrg -(GLint) texImages[i]->Border, /* yoffset */ 5257af69d88dSmrg -(GLint) texImages[i]->Border, /* zoffset */ 5258af69d88dSmrg texImages[i]->Width, 5259af69d88dSmrg texImages[i]->Height, 5260af69d88dSmrg texImages[i]->Depth, 5261af69d88dSmrg data ? clearValue[i] : NULL); 5262af69d88dSmrg } 52637117f1b4Smrg 5264af69d88dSmrgout: 5265af69d88dSmrg _mesa_unlock_texture(ctx, texObj); 5266af69d88dSmrg} 52677117f1b4Smrg 52687117f1b4Smrg 5269af69d88dSmrg 5270af69d88dSmrg 5271af69d88dSmrg/**********************************************************************/ 5272af69d88dSmrg/****** Compressed Textures ******/ 5273af69d88dSmrg/**********************************************************************/ 52747117f1b4Smrg 52757117f1b4Smrg 52764a49301eSmrg/** 527701e04c3fSmrg * Target checking for glCompressedTexSubImage[123]D(). 5278af69d88dSmrg * \return GL_TRUE if error, GL_FALSE if no error 527901e04c3fSmrg * Must come before other error checking so that the texture object can 528001e04c3fSmrg * be correctly retrieved using _mesa_get_current_tex_object. 52814a49301eSmrg */ 52824a49301eSmrgstatic GLboolean 528301e04c3fSmrgcompressed_subtexture_target_check(struct gl_context *ctx, GLenum target, 528401e04c3fSmrg GLint dims, GLenum intFormat, bool dsa, 528501e04c3fSmrg const char *caller) 52864a49301eSmrg{ 5287af69d88dSmrg GLboolean targetOK; 528801e04c3fSmrg mesa_format format; 528901e04c3fSmrg enum mesa_format_layout layout; 529001e04c3fSmrg 529101e04c3fSmrg if (dsa && target == GL_TEXTURE_RECTANGLE) { 529201e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid target %s)", caller, 529301e04c3fSmrg _mesa_enum_to_string(target)); 529401e04c3fSmrg return GL_TRUE; 529501e04c3fSmrg } 52964a49301eSmrg 5297af69d88dSmrg switch (dims) { 5298af69d88dSmrg case 2: 5299af69d88dSmrg switch (target) { 5300af69d88dSmrg case GL_TEXTURE_2D: 530101e04c3fSmrg targetOK = GL_TRUE; 530201e04c3fSmrg break; 5303af69d88dSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 5304af69d88dSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 5305af69d88dSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 5306af69d88dSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 5307af69d88dSmrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 5308af69d88dSmrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 530901e04c3fSmrg targetOK = ctx->Extensions.ARB_texture_cube_map; 5310af69d88dSmrg break; 5311af69d88dSmrg default: 5312af69d88dSmrg targetOK = GL_FALSE; 5313af69d88dSmrg break; 5314af69d88dSmrg } 5315af69d88dSmrg break; 5316af69d88dSmrg case 3: 531701e04c3fSmrg switch (target) { 531801e04c3fSmrg case GL_TEXTURE_CUBE_MAP: 531901e04c3fSmrg targetOK = dsa && ctx->Extensions.ARB_texture_cube_map; 532001e04c3fSmrg break; 532101e04c3fSmrg case GL_TEXTURE_2D_ARRAY: 532201e04c3fSmrg targetOK = _mesa_is_gles3(ctx) || 532301e04c3fSmrg (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_texture_array); 532401e04c3fSmrg break; 532501e04c3fSmrg case GL_TEXTURE_CUBE_MAP_ARRAY: 532601e04c3fSmrg targetOK = _mesa_has_texture_cube_map_array(ctx); 532701e04c3fSmrg break; 532801e04c3fSmrg case GL_TEXTURE_3D: 532901e04c3fSmrg targetOK = GL_TRUE; 533001e04c3fSmrg /* 533101e04c3fSmrg * OpenGL 4.5 spec (30.10.2014) says in Section 8.7 Compressed Texture 533201e04c3fSmrg * Images: 533301e04c3fSmrg * "An INVALID_OPERATION error is generated by 533401e04c3fSmrg * CompressedTex*SubImage3D if the internal format of the texture 533501e04c3fSmrg * is one of the EAC, ETC2, or RGTC formats and either border is 533601e04c3fSmrg * non-zero, or the effective target for the texture is not 533701e04c3fSmrg * TEXTURE_2D_ARRAY." 533801e04c3fSmrg * 533901e04c3fSmrg * NOTE: that's probably a spec error. It should probably say 534001e04c3fSmrg * "... or the effective target for the texture is not 534101e04c3fSmrg * TEXTURE_2D_ARRAY, TEXTURE_CUBE_MAP, nor 534201e04c3fSmrg * GL_TEXTURE_CUBE_MAP_ARRAY." 534301e04c3fSmrg * since those targets are 2D images and they support all compression 534401e04c3fSmrg * formats. 534501e04c3fSmrg * 534601e04c3fSmrg * Instead of listing all these, just list those which are allowed, 534701e04c3fSmrg * which is (at this time) only bptc. Otherwise we'd say s3tc (and 534801e04c3fSmrg * more) are valid here, which they are not, but of course not 534901e04c3fSmrg * mentioned by core spec. 535001e04c3fSmrg * 535101e04c3fSmrg * Also, from GL_KHR_texture_compression_astc_{hdr,ldr}: 535201e04c3fSmrg * 535301e04c3fSmrg * "Add a second new column "3D Tex." which is empty for all non-ASTC 535401e04c3fSmrg * formats. If only the LDR profile is supported by the implementation, 535501e04c3fSmrg * this column is also empty for all ASTC formats. If both the LDR and HDR 535601e04c3fSmrg * profiles are supported, this column is checked for all ASTC formats." 535701e04c3fSmrg * 535801e04c3fSmrg * "An INVALID_OPERATION error is generated by CompressedTexSubImage3D if 535901e04c3fSmrg * <format> is one of the formats in table 8.19 and <target> is not 536001e04c3fSmrg * TEXTURE_2D_ARRAY, TEXTURE_CUBE_MAP_ARRAY, or TEXTURE_3D. 536101e04c3fSmrg * 536201e04c3fSmrg * An INVALID_OPERATION error is generated by CompressedTexSubImage3D if 536301e04c3fSmrg * <format> is TEXTURE_CUBE_MAP_ARRAY and the "Cube Map Array" column of 536401e04c3fSmrg * table 8.19 is *not* checked, or if <format> is TEXTURE_3D and the "3D 536501e04c3fSmrg * Tex." column of table 8.19 is *not* checked" 536601e04c3fSmrg * 536701e04c3fSmrg * And from GL_KHR_texture_compression_astc_sliced_3d: 536801e04c3fSmrg * 536901e04c3fSmrg * "Modify the "3D Tex." column to be checked for all ASTC formats." 537001e04c3fSmrg */ 537101e04c3fSmrg format = _mesa_glenum_to_compressed_format(intFormat); 537201e04c3fSmrg layout = _mesa_get_format_layout(format); 537301e04c3fSmrg switch (layout) { 537401e04c3fSmrg case MESA_FORMAT_LAYOUT_BPTC: 537501e04c3fSmrg /* valid format */ 537601e04c3fSmrg break; 537701e04c3fSmrg case MESA_FORMAT_LAYOUT_ASTC: 537801e04c3fSmrg targetOK = 537901e04c3fSmrg ctx->Extensions.KHR_texture_compression_astc_hdr || 538001e04c3fSmrg ctx->Extensions.KHR_texture_compression_astc_sliced_3d; 538101e04c3fSmrg break; 538201e04c3fSmrg default: 538301e04c3fSmrg /* invalid format */ 538401e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 538501e04c3fSmrg "%s(invalid target %s for format %s)", caller, 538601e04c3fSmrg _mesa_enum_to_string(target), 538701e04c3fSmrg _mesa_enum_to_string(intFormat)); 538801e04c3fSmrg return GL_TRUE; 538901e04c3fSmrg } 539001e04c3fSmrg break; 539101e04c3fSmrg default: 539201e04c3fSmrg targetOK = GL_FALSE; 539301e04c3fSmrg } 539401e04c3fSmrg 5395af69d88dSmrg break; 5396af69d88dSmrg default: 5397af69d88dSmrg assert(dims == 1); 5398af69d88dSmrg /* no 1D compressed textures at this time */ 5399af69d88dSmrg targetOK = GL_FALSE; 5400af69d88dSmrg break; 54014a49301eSmrg } 54024a49301eSmrg 5403af69d88dSmrg if (!targetOK) { 540401e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, "%s(invalid target %s)", caller, 540501e04c3fSmrg _mesa_enum_to_string(target)); 54064a49301eSmrg return GL_TRUE; 54074a49301eSmrg } 54084a49301eSmrg 540901e04c3fSmrg return GL_FALSE; 541001e04c3fSmrg} 541101e04c3fSmrg 541201e04c3fSmrg/** 541301e04c3fSmrg * Error checking for glCompressedTexSubImage[123]D(). 541401e04c3fSmrg * \return GL_TRUE if error, GL_FALSE if no error 541501e04c3fSmrg */ 541601e04c3fSmrgstatic GLboolean 541701e04c3fSmrgcompressed_subtexture_error_check(struct gl_context *ctx, GLint dims, 541801e04c3fSmrg const struct gl_texture_object *texObj, 541901e04c3fSmrg GLenum target, GLint level, 542001e04c3fSmrg GLint xoffset, GLint yoffset, GLint zoffset, 542101e04c3fSmrg GLsizei width, GLsizei height, GLsizei depth, 542201e04c3fSmrg GLenum format, GLsizei imageSize, 542301e04c3fSmrg const GLvoid *data, const char *callerName) 542401e04c3fSmrg{ 542501e04c3fSmrg struct gl_texture_image *texImage; 542601e04c3fSmrg GLint expectedSize; 542701e04c3fSmrg 54287ec681f3Smrg GLenum is_generic_compressed_token = 54297ec681f3Smrg _mesa_generic_compressed_format_to_uncompressed_format(format) != 54307ec681f3Smrg format; 54317ec681f3Smrg 54327ec681f3Smrg /* OpenGL 4.6 and OpenGL ES 3.2 spec: 54337ec681f3Smrg * 54347ec681f3Smrg * "An INVALID_OPERATION error is generated if format does not match the 54357ec681f3Smrg * internal format of the texture image being modified, since these commands do 54367ec681f3Smrg * not provide for image format conversion." 54377ec681f3Smrg * 54387ec681f3Smrg * Desktop spec has an additional rule for GL_INVALID_ENUM: 54397ec681f3Smrg * 54407ec681f3Smrg * "An INVALID_ENUM error is generated if format is one of the generic 54417ec681f3Smrg * compressed internal formats." 54427ec681f3Smrg */ 5443af69d88dSmrg /* this will catch any invalid compressed format token */ 5444af69d88dSmrg if (!_mesa_is_compressed_format(ctx, format)) { 54457ec681f3Smrg GLenum error = _mesa_is_desktop_gl(ctx) && is_generic_compressed_token ? 54467ec681f3Smrg GL_INVALID_ENUM : GL_INVALID_OPERATION; 54477ec681f3Smrg _mesa_error(ctx, error, "%s(format)", callerName); 5448af69d88dSmrg return GL_TRUE; 54494a49301eSmrg } 54504a49301eSmrg 5451af69d88dSmrg if (level < 0 || level >= _mesa_max_texture_levels(ctx, target)) { 545201e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(level=%d)", callerName, level); 545301e04c3fSmrg return GL_TRUE; 545401e04c3fSmrg } 545501e04c3fSmrg 545601e04c3fSmrg /* validate the bound PBO, if any */ 545701e04c3fSmrg if (!_mesa_validate_pbo_source_compressed(ctx, dims, &ctx->Unpack, 545801e04c3fSmrg imageSize, data, callerName)) { 5459af69d88dSmrg return GL_TRUE; 54604a49301eSmrg } 54614a49301eSmrg 5462af69d88dSmrg /* Check for invalid pixel storage modes */ 5463af69d88dSmrg if (!_mesa_compressed_pixel_storage_error_check(ctx, dims, 546401e04c3fSmrg &ctx->Unpack, callerName)) { 5465af69d88dSmrg return GL_TRUE; 54667117f1b4Smrg } 54674a49301eSmrg 5468af69d88dSmrg expectedSize = compressed_tex_size(width, height, depth, format); 5469af69d88dSmrg if (expectedSize != imageSize) { 547001e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(size=%d)", callerName, imageSize); 5471af69d88dSmrg return GL_TRUE; 54727117f1b4Smrg } 54737117f1b4Smrg 547401e04c3fSmrg texImage = _mesa_select_tex_image(texObj, target, level); 547501e04c3fSmrg if (!texImage) { 547601e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(invalid texture level %d)", 547701e04c3fSmrg callerName, level); 5478af69d88dSmrg return GL_TRUE; 54793464ebd5Sriastradh } 54807117f1b4Smrg 548101e04c3fSmrg if ((GLint) format != texImage->InternalFormat) { 548201e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(format=%s)", 548301e04c3fSmrg callerName, _mesa_enum_to_string(format)); 5484af69d88dSmrg return GL_TRUE; 54853464ebd5Sriastradh } 54863464ebd5Sriastradh 548701e04c3fSmrg if (compressedteximage_only_format(format)) { 548801e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(format=%s cannot be updated)", 548901e04c3fSmrg callerName, _mesa_enum_to_string(format)); 5490af69d88dSmrg return GL_TRUE; 5491af69d88dSmrg } 54924a49301eSmrg 549301e04c3fSmrg if (error_check_subtexture_negative_dimensions(ctx, dims, width, height, 549401e04c3fSmrg depth, callerName)) { 5495af69d88dSmrg return GL_TRUE; 5496af69d88dSmrg } 54974a49301eSmrg 549801e04c3fSmrg if (error_check_subtexture_dimensions(ctx, dims, texImage, xoffset, yoffset, 549901e04c3fSmrg zoffset, width, height, depth, 550001e04c3fSmrg callerName)) { 5501af69d88dSmrg return GL_TRUE; 55027117f1b4Smrg } 5503af69d88dSmrg 5504af69d88dSmrg return GL_FALSE; 55053464ebd5Sriastradh} 55064a49301eSmrg 55077117f1b4Smrg 55083464ebd5Sriastradhvoid GLAPIENTRY 5509af69d88dSmrg_mesa_CompressedTexImage1D(GLenum target, GLint level, 55103464ebd5Sriastradh GLenum internalFormat, GLsizei width, 55113464ebd5Sriastradh GLint border, GLsizei imageSize, 55123464ebd5Sriastradh const GLvoid *data) 55133464ebd5Sriastradh{ 55143464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 551501e04c3fSmrg teximage_err(ctx, GL_TRUE, 1, target, level, internalFormat, 551601e04c3fSmrg width, 1, 1, border, GL_NONE, GL_NONE, imageSize, data); 55173464ebd5Sriastradh} 55183464ebd5Sriastradh 55193464ebd5Sriastradh 55207ec681f3Smrgvoid GLAPIENTRY 55217ec681f3Smrg_mesa_CompressedTextureImage1DEXT(GLuint texture, GLenum target, GLint level, 55227ec681f3Smrg GLenum internalFormat, GLsizei width, 55237ec681f3Smrg GLint border, GLsizei imageSize, 55247ec681f3Smrg const GLvoid *pixels) 55257ec681f3Smrg{ 55267ec681f3Smrg struct gl_texture_object* texObj; 55277ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 55287ec681f3Smrg 55297ec681f3Smrg texObj = _mesa_lookup_or_create_texture(ctx, target, texture, false, true, 55307ec681f3Smrg "glCompressedTextureImage1DEXT"); 55317ec681f3Smrg if (!texObj) 55327ec681f3Smrg return; 55337ec681f3Smrg teximage(ctx, GL_TRUE, 1, texObj, target, level, internalFormat, 55347ec681f3Smrg width, 1, 1, border, GL_NONE, GL_NONE, imageSize, pixels, false); 55357ec681f3Smrg} 55367ec681f3Smrg 55377ec681f3Smrg 55387ec681f3Smrgvoid GLAPIENTRY 55397ec681f3Smrg_mesa_CompressedMultiTexImage1DEXT(GLenum texunit, GLenum target, GLint level, 55407ec681f3Smrg GLenum internalFormat, GLsizei width, 55417ec681f3Smrg GLint border, GLsizei imageSize, 55427ec681f3Smrg const GLvoid *pixels) 55437ec681f3Smrg{ 55447ec681f3Smrg struct gl_texture_object* texObj; 55457ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 55467ec681f3Smrg 55477ec681f3Smrg texObj = _mesa_get_texobj_by_target_and_texunit(ctx, target, 55487ec681f3Smrg texunit - GL_TEXTURE0, 55497ec681f3Smrg true, 55507ec681f3Smrg "glCompressedMultiTexImage1DEXT"); 55517ec681f3Smrg if (!texObj) 55527ec681f3Smrg return; 55537ec681f3Smrg teximage(ctx, GL_TRUE, 1, texObj, target, level, internalFormat, 55547ec681f3Smrg width, 1, 1, border, GL_NONE, GL_NONE, imageSize, pixels, false); 55557ec681f3Smrg} 55567ec681f3Smrg 55577ec681f3Smrg 55583464ebd5Sriastradhvoid GLAPIENTRY 5559af69d88dSmrg_mesa_CompressedTexImage2D(GLenum target, GLint level, 55603464ebd5Sriastradh GLenum internalFormat, GLsizei width, 55613464ebd5Sriastradh GLsizei height, GLint border, GLsizei imageSize, 55623464ebd5Sriastradh const GLvoid *data) 55633464ebd5Sriastradh{ 55643464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 556501e04c3fSmrg teximage_err(ctx, GL_TRUE, 2, target, level, internalFormat, 556601e04c3fSmrg width, height, 1, border, GL_NONE, GL_NONE, imageSize, data); 55677117f1b4Smrg} 55687117f1b4Smrg 55697117f1b4Smrg 55707ec681f3Smrgvoid GLAPIENTRY 55717ec681f3Smrg_mesa_CompressedTextureImage2DEXT(GLuint texture, GLenum target, GLint level, 55727ec681f3Smrg GLenum internalFormat, GLsizei width, 55737ec681f3Smrg GLsizei height, GLint border, GLsizei imageSize, 55747ec681f3Smrg const GLvoid *pixels) 55757ec681f3Smrg{ 55767ec681f3Smrg struct gl_texture_object* texObj; 55777ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 55787ec681f3Smrg 55797ec681f3Smrg texObj = _mesa_lookup_or_create_texture(ctx, target, texture, false, true, 55807ec681f3Smrg "glCompressedTextureImage2DEXT"); 55817ec681f3Smrg if (!texObj) 55827ec681f3Smrg return; 55837ec681f3Smrg teximage(ctx, GL_TRUE, 2, texObj, target, level, internalFormat, 55847ec681f3Smrg width, height, 1, border, GL_NONE, GL_NONE, imageSize, pixels, false); 55857ec681f3Smrg} 55867ec681f3Smrg 55877ec681f3Smrg 55887ec681f3Smrgvoid GLAPIENTRY 55897ec681f3Smrg_mesa_CompressedMultiTexImage2DEXT(GLenum texunit, GLenum target, GLint level, 55907ec681f3Smrg GLenum internalFormat, GLsizei width, 55917ec681f3Smrg GLsizei height, GLint border, GLsizei imageSize, 55927ec681f3Smrg const GLvoid *pixels) 55937ec681f3Smrg{ 55947ec681f3Smrg struct gl_texture_object* texObj; 55957ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 55967ec681f3Smrg 55977ec681f3Smrg texObj = _mesa_get_texobj_by_target_and_texunit(ctx, target, 55987ec681f3Smrg texunit - GL_TEXTURE0, 55997ec681f3Smrg true, 56007ec681f3Smrg "glCompressedMultiTexImage2DEXT"); 56017ec681f3Smrg if (!texObj) 56027ec681f3Smrg return; 56037ec681f3Smrg teximage(ctx, GL_TRUE, 2, texObj, target, level, internalFormat, 56047ec681f3Smrg width, height, 1, border, GL_NONE, GL_NONE, imageSize, pixels, false); 56057ec681f3Smrg} 56067ec681f3Smrg 56077ec681f3Smrg 56087117f1b4Smrgvoid GLAPIENTRY 5609af69d88dSmrg_mesa_CompressedTexImage3D(GLenum target, GLint level, 56107117f1b4Smrg GLenum internalFormat, GLsizei width, 56117117f1b4Smrg GLsizei height, GLsizei depth, GLint border, 56127117f1b4Smrg GLsizei imageSize, const GLvoid *data) 56137117f1b4Smrg{ 56147117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 561501e04c3fSmrg teximage_err(ctx, GL_TRUE, 3, target, level, internalFormat, width, height, 561601e04c3fSmrg depth, border, GL_NONE, GL_NONE, imageSize, data); 561701e04c3fSmrg} 561801e04c3fSmrg 561901e04c3fSmrg 56207ec681f3Smrgvoid GLAPIENTRY 56217ec681f3Smrg_mesa_CompressedTextureImage3DEXT(GLuint texture, GLenum target, GLint level, 56227ec681f3Smrg GLenum internalFormat, GLsizei width, 56237ec681f3Smrg GLsizei height, GLsizei depth, GLint border, 56247ec681f3Smrg GLsizei imageSize, const GLvoid *pixels) 56257ec681f3Smrg{ 56267ec681f3Smrg struct gl_texture_object* texObj; 56277ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 56287ec681f3Smrg 56297ec681f3Smrg texObj = _mesa_lookup_or_create_texture(ctx, target, texture, false, true, 56307ec681f3Smrg "glCompressedTextureImage3DEXT"); 56317ec681f3Smrg if (!texObj) 56327ec681f3Smrg return; 56337ec681f3Smrg teximage(ctx, GL_TRUE, 3, texObj, target, level, internalFormat, 56347ec681f3Smrg width, height, depth, border, GL_NONE, GL_NONE, imageSize, pixels, false); 56357ec681f3Smrg} 56367ec681f3Smrg 56377ec681f3Smrg 56387ec681f3Smrgvoid GLAPIENTRY 56397ec681f3Smrg_mesa_CompressedMultiTexImage3DEXT(GLenum texunit, GLenum target, GLint level, 56407ec681f3Smrg GLenum internalFormat, GLsizei width, 56417ec681f3Smrg GLsizei height, GLsizei depth, GLint border, 56427ec681f3Smrg GLsizei imageSize, const GLvoid *pixels) 56437ec681f3Smrg{ 56447ec681f3Smrg struct gl_texture_object* texObj; 56457ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 56467ec681f3Smrg 56477ec681f3Smrg texObj = _mesa_get_texobj_by_target_and_texunit(ctx, target, 56487ec681f3Smrg texunit - GL_TEXTURE0, 56497ec681f3Smrg true, 56507ec681f3Smrg "glCompressedMultiTexImage3DEXT"); 56517ec681f3Smrg if (!texObj) 56527ec681f3Smrg return; 56537ec681f3Smrg teximage(ctx, GL_TRUE, 3, texObj, target, level, internalFormat, 56547ec681f3Smrg width, height, depth, border, GL_NONE, GL_NONE, imageSize, pixels, false); 56557ec681f3Smrg} 56567ec681f3Smrg 56577ec681f3Smrg 565801e04c3fSmrgvoid GLAPIENTRY 565901e04c3fSmrg_mesa_CompressedTexImage1D_no_error(GLenum target, GLint level, 566001e04c3fSmrg GLenum internalFormat, GLsizei width, 566101e04c3fSmrg GLint border, GLsizei imageSize, 566201e04c3fSmrg const GLvoid *data) 566301e04c3fSmrg{ 566401e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 566501e04c3fSmrg teximage_no_error(ctx, GL_TRUE, 1, target, level, internalFormat, width, 1, 566601e04c3fSmrg 1, border, GL_NONE, GL_NONE, imageSize, data); 566701e04c3fSmrg} 566801e04c3fSmrg 566901e04c3fSmrg 567001e04c3fSmrgvoid GLAPIENTRY 567101e04c3fSmrg_mesa_CompressedTexImage2D_no_error(GLenum target, GLint level, 567201e04c3fSmrg GLenum internalFormat, GLsizei width, 567301e04c3fSmrg GLsizei height, GLint border, 567401e04c3fSmrg GLsizei imageSize, const GLvoid *data) 567501e04c3fSmrg{ 567601e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 567701e04c3fSmrg teximage_no_error(ctx, GL_TRUE, 2, target, level, internalFormat, width, 567801e04c3fSmrg height, 1, border, GL_NONE, GL_NONE, imageSize, data); 567901e04c3fSmrg} 568001e04c3fSmrg 568101e04c3fSmrg 568201e04c3fSmrgvoid GLAPIENTRY 568301e04c3fSmrg_mesa_CompressedTexImage3D_no_error(GLenum target, GLint level, 568401e04c3fSmrg GLenum internalFormat, GLsizei width, 568501e04c3fSmrg GLsizei height, GLsizei depth, GLint border, 568601e04c3fSmrg GLsizei imageSize, const GLvoid *data) 568701e04c3fSmrg{ 568801e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 568901e04c3fSmrg teximage_no_error(ctx, GL_TRUE, 3, target, level, internalFormat, width, 569001e04c3fSmrg height, depth, border, GL_NONE, GL_NONE, imageSize, data); 56917117f1b4Smrg} 56927117f1b4Smrg 56937117f1b4Smrg 56944a49301eSmrg/** 569501e04c3fSmrg * Common helper for glCompressedTexSubImage1/2/3D() and 569601e04c3fSmrg * glCompressedTextureSubImage1/2/3D(). 56974a49301eSmrg */ 56984a49301eSmrgstatic void 569901e04c3fSmrgcompressed_texture_sub_image(struct gl_context *ctx, GLuint dims, 570001e04c3fSmrg struct gl_texture_object *texObj, 570101e04c3fSmrg struct gl_texture_image *texImage, 570201e04c3fSmrg GLenum target, GLint level, GLint xoffset, 570301e04c3fSmrg GLint yoffset, GLint zoffset, GLsizei width, 570401e04c3fSmrg GLsizei height, GLsizei depth, GLenum format, 570501e04c3fSmrg GLsizei imageSize, const GLvoid *data) 57067117f1b4Smrg{ 57077ec681f3Smrg FLUSH_VERTICES(ctx, 0, 0); 570801e04c3fSmrg 570901e04c3fSmrg _mesa_lock_texture(ctx, texObj); 571001e04c3fSmrg { 571101e04c3fSmrg if (width > 0 && height > 0 && depth > 0) { 571201e04c3fSmrg ctx->Driver.CompressedTexSubImage(ctx, dims, texImage, 571301e04c3fSmrg xoffset, yoffset, zoffset, 571401e04c3fSmrg width, height, depth, 571501e04c3fSmrg format, imageSize, data); 571601e04c3fSmrg 571701e04c3fSmrg check_gen_mipmap(ctx, target, texObj, level); 571801e04c3fSmrg 571901e04c3fSmrg /* NOTE: Don't signal _NEW_TEXTURE_OBJECT since we've only changed 572001e04c3fSmrg * the texel data, not the texture format, size, etc. 572101e04c3fSmrg */ 572201e04c3fSmrg } 572301e04c3fSmrg } 572401e04c3fSmrg _mesa_unlock_texture(ctx, texObj); 572501e04c3fSmrg} 572601e04c3fSmrg 572701e04c3fSmrg 57287ec681f3Smrgenum tex_mode { 57297ec681f3Smrg /* Use bound texture to current unit */ 57307ec681f3Smrg TEX_MODE_CURRENT_NO_ERROR = 0, 57317ec681f3Smrg TEX_MODE_CURRENT_ERROR, 57327ec681f3Smrg /* Use the specified texture name */ 57337ec681f3Smrg TEX_MODE_DSA_NO_ERROR, 57347ec681f3Smrg TEX_MODE_DSA_ERROR, 57357ec681f3Smrg /* Use the specified texture name + target */ 57367ec681f3Smrg TEX_MODE_EXT_DSA_TEXTURE, 57377ec681f3Smrg /* Use the specified texture unit + target */ 57387ec681f3Smrg TEX_MODE_EXT_DSA_TEXUNIT, 57397ec681f3Smrg}; 57407ec681f3Smrg 57417ec681f3Smrg 57427ec681f3Smrgstatic void 57437ec681f3Smrgcompressed_tex_sub_image(unsigned dim, GLenum target, GLuint textureOrIndex, 574401e04c3fSmrg GLint level, GLint xoffset, GLint yoffset, 574501e04c3fSmrg GLint zoffset, GLsizei width, GLsizei height, 574601e04c3fSmrg GLsizei depth, GLenum format, GLsizei imageSize, 57477ec681f3Smrg const GLvoid *data, enum tex_mode mode, 574801e04c3fSmrg const char *caller) 574901e04c3fSmrg{ 575001e04c3fSmrg struct gl_texture_object *texObj = NULL; 57517117f1b4Smrg struct gl_texture_image *texImage; 57527ec681f3Smrg bool no_error = false; 57537117f1b4Smrg GET_CURRENT_CONTEXT(ctx); 5754af69d88dSmrg 57557ec681f3Smrg switch (mode) { 57567ec681f3Smrg case TEX_MODE_DSA_ERROR: 57577ec681f3Smrg assert(target == 0); 57587ec681f3Smrg texObj = _mesa_lookup_texture_err(ctx, textureOrIndex, caller); 57597ec681f3Smrg if (texObj) 57607ec681f3Smrg target = texObj->Target; 57617ec681f3Smrg break; 57627ec681f3Smrg case TEX_MODE_DSA_NO_ERROR: 57637ec681f3Smrg assert(target == 0); 57647ec681f3Smrg texObj = _mesa_lookup_texture(ctx, textureOrIndex); 57657ec681f3Smrg if (texObj) 57667ec681f3Smrg target = texObj->Target; 57677ec681f3Smrg no_error = true; 57687ec681f3Smrg break; 57697ec681f3Smrg case TEX_MODE_EXT_DSA_TEXTURE: 57707ec681f3Smrg texObj = _mesa_lookup_or_create_texture(ctx, target, textureOrIndex, 57717ec681f3Smrg false, true, caller); 57727ec681f3Smrg break; 57737ec681f3Smrg case TEX_MODE_EXT_DSA_TEXUNIT: 57747ec681f3Smrg texObj = _mesa_get_texobj_by_target_and_texunit(ctx, target, 57757ec681f3Smrg textureOrIndex, 57767ec681f3Smrg false, 57777ec681f3Smrg caller); 57787ec681f3Smrg break; 57797ec681f3Smrg case TEX_MODE_CURRENT_NO_ERROR: 57807ec681f3Smrg no_error = true; 57817ec681f3Smrg FALLTHROUGH; 57827ec681f3Smrg case TEX_MODE_CURRENT_ERROR: 57837ec681f3Smrg default: 57847ec681f3Smrg assert(textureOrIndex == 0); 57857ec681f3Smrg break; 578601e04c3fSmrg } 578701e04c3fSmrg 578801e04c3fSmrg if (!no_error && 57897ec681f3Smrg compressed_subtexture_target_check(ctx, target, dim, format, 57907ec681f3Smrg mode == TEX_MODE_DSA_ERROR, 579101e04c3fSmrg caller)) { 57927117f1b4Smrg return; 57937117f1b4Smrg } 57947117f1b4Smrg 57957ec681f3Smrg if (mode == TEX_MODE_CURRENT_NO_ERROR || 57967ec681f3Smrg mode == TEX_MODE_CURRENT_ERROR) { 579701e04c3fSmrg texObj = _mesa_get_current_tex_object(ctx, target); 579801e04c3fSmrg } 57994a49301eSmrg 58007ec681f3Smrg if (!texObj) 58017ec681f3Smrg return; 58027ec681f3Smrg 580301e04c3fSmrg if (!no_error && 580401e04c3fSmrg compressed_subtexture_error_check(ctx, dim, texObj, target, level, 580501e04c3fSmrg xoffset, yoffset, zoffset, width, 580601e04c3fSmrg height, depth, format, 580701e04c3fSmrg imageSize, data, caller)) { 580801e04c3fSmrg return; 580901e04c3fSmrg } 581001e04c3fSmrg 581101e04c3fSmrg /* Must handle special case GL_TEXTURE_CUBE_MAP. */ 58127ec681f3Smrg if (dim == 3 && 58137ec681f3Smrg (mode == TEX_MODE_DSA_ERROR || mode == TEX_MODE_DSA_NO_ERROR) && 58147ec681f3Smrg texObj->Target == GL_TEXTURE_CUBE_MAP) { 581501e04c3fSmrg const char *pixels = data; 581601e04c3fSmrg GLint image_stride; 581701e04c3fSmrg 581801e04c3fSmrg /* Make sure the texture object is a proper cube. 581901e04c3fSmrg * (See texturesubimage in teximage.c for details on why this check is 582001e04c3fSmrg * performed.) 582101e04c3fSmrg */ 582201e04c3fSmrg if (!no_error && !_mesa_cube_level_complete(texObj, level)) { 582301e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 582401e04c3fSmrg "glCompressedTextureSubImage3D(cube map incomplete)"); 582501e04c3fSmrg return; 582601e04c3fSmrg } 582701e04c3fSmrg 582801e04c3fSmrg /* Copy in each face. */ 582901e04c3fSmrg for (int i = zoffset; i < zoffset + depth; ++i) { 583001e04c3fSmrg texImage = texObj->Image[i][level]; 583101e04c3fSmrg assert(texImage); 583201e04c3fSmrg 583301e04c3fSmrg compressed_texture_sub_image(ctx, 3, texObj, texImage, 583401e04c3fSmrg texObj->Target, level, xoffset, yoffset, 583501e04c3fSmrg 0, width, height, 1, format, 583601e04c3fSmrg imageSize, pixels); 583701e04c3fSmrg 583801e04c3fSmrg /* Compressed images don't have a client format */ 583901e04c3fSmrg image_stride = _mesa_format_image_size(texImage->TexFormat, 584001e04c3fSmrg texImage->Width, 584101e04c3fSmrg texImage->Height, 1); 584201e04c3fSmrg 584301e04c3fSmrg pixels += image_stride; 584401e04c3fSmrg imageSize -= image_stride; 584501e04c3fSmrg } 584601e04c3fSmrg } else { 584701e04c3fSmrg texImage = _mesa_select_tex_image(texObj, target, level); 58487117f1b4Smrg assert(texImage); 58497117f1b4Smrg 585001e04c3fSmrg compressed_texture_sub_image(ctx, dim, texObj, texImage, target, level, 585101e04c3fSmrg xoffset, yoffset, zoffset, width, height, 585201e04c3fSmrg depth, format, imageSize, data); 585301e04c3fSmrg } 585401e04c3fSmrg} 585501e04c3fSmrg 585601e04c3fSmrg 585701e04c3fSmrgvoid GLAPIENTRY 585801e04c3fSmrg_mesa_CompressedTexSubImage1D_no_error(GLenum target, GLint level, 585901e04c3fSmrg GLint xoffset, GLsizei width, 586001e04c3fSmrg GLenum format, GLsizei imageSize, 586101e04c3fSmrg const GLvoid *data) 586201e04c3fSmrg{ 58637ec681f3Smrg compressed_tex_sub_image(1, target, 0, 58647ec681f3Smrg level, xoffset, 0, 0, width, 58657ec681f3Smrg 1, 1, format, imageSize, data, 58667ec681f3Smrg TEX_MODE_CURRENT_NO_ERROR, 58677ec681f3Smrg "glCompressedTexSubImage1D"); 586801e04c3fSmrg} 586901e04c3fSmrg 587001e04c3fSmrg 587101e04c3fSmrgvoid GLAPIENTRY 587201e04c3fSmrg_mesa_CompressedTexSubImage1D(GLenum target, GLint level, GLint xoffset, 587301e04c3fSmrg GLsizei width, GLenum format, 587401e04c3fSmrg GLsizei imageSize, const GLvoid *data) 587501e04c3fSmrg{ 58767ec681f3Smrg compressed_tex_sub_image(1, target, 0, 58777ec681f3Smrg level, xoffset, 0, 0, width, 58787ec681f3Smrg 1, 1, format, imageSize, data, 58797ec681f3Smrg TEX_MODE_CURRENT_ERROR, 58807ec681f3Smrg "glCompressedTexSubImage1D"); 588101e04c3fSmrg} 588201e04c3fSmrg 588301e04c3fSmrg 588401e04c3fSmrgvoid GLAPIENTRY 588501e04c3fSmrg_mesa_CompressedTextureSubImage1D_no_error(GLuint texture, GLint level, 588601e04c3fSmrg GLint xoffset, GLsizei width, 588701e04c3fSmrg GLenum format, GLsizei imageSize, 588801e04c3fSmrg const GLvoid *data) 588901e04c3fSmrg{ 58907ec681f3Smrg compressed_tex_sub_image(1, 0, texture, 58917ec681f3Smrg level, xoffset, 0, 0, 58927ec681f3Smrg width, 1, 1, format, imageSize, data, 58937ec681f3Smrg TEX_MODE_DSA_NO_ERROR, 58947ec681f3Smrg "glCompressedTextureSubImage1D"); 589501e04c3fSmrg} 589601e04c3fSmrg 589701e04c3fSmrg 589801e04c3fSmrgvoid GLAPIENTRY 589901e04c3fSmrg_mesa_CompressedTextureSubImage1D(GLuint texture, GLint level, GLint xoffset, 590001e04c3fSmrg GLsizei width, GLenum format, 590101e04c3fSmrg GLsizei imageSize, const GLvoid *data) 590201e04c3fSmrg{ 59037ec681f3Smrg compressed_tex_sub_image(1, 0, texture, 59047ec681f3Smrg level, xoffset, 0, 0, 59057ec681f3Smrg width, 1, 1, format, imageSize, data, 59067ec681f3Smrg TEX_MODE_DSA_ERROR, 59077ec681f3Smrg "glCompressedTextureSubImage1D"); 590801e04c3fSmrg} 590901e04c3fSmrg 59107ec681f3Smrg 59117ec681f3Smrgvoid GLAPIENTRY 59127ec681f3Smrg_mesa_CompressedTextureSubImage1DEXT(GLuint texture, GLenum target, 59137ec681f3Smrg GLint level, GLint xoffset, 59147ec681f3Smrg GLsizei width, GLenum format, 59157ec681f3Smrg GLsizei imageSize, const GLvoid *data) 59167ec681f3Smrg{ 59177ec681f3Smrg compressed_tex_sub_image(1, target, texture, level, xoffset, 0, 59187ec681f3Smrg 0, width, 1, 1, format, imageSize, 59197ec681f3Smrg data, 59207ec681f3Smrg TEX_MODE_EXT_DSA_TEXTURE, 59217ec681f3Smrg "glCompressedTextureSubImage1DEXT"); 59227ec681f3Smrg} 59237ec681f3Smrg 59247ec681f3Smrg 59257ec681f3Smrgvoid GLAPIENTRY 59267ec681f3Smrg_mesa_CompressedMultiTexSubImage1DEXT(GLenum texunit, GLenum target, 59277ec681f3Smrg GLint level, GLint xoffset, 59287ec681f3Smrg GLsizei width, GLenum format, 59297ec681f3Smrg GLsizei imageSize, const GLvoid *data) 59307ec681f3Smrg{ 59317ec681f3Smrg compressed_tex_sub_image(1, target, texunit - GL_TEXTURE0, level, 59327ec681f3Smrg xoffset, 0, 0, width, 1, 1, format, imageSize, 59337ec681f3Smrg data, 59347ec681f3Smrg TEX_MODE_EXT_DSA_TEXUNIT, 59357ec681f3Smrg "glCompressedMultiTexSubImage1DEXT"); 59367ec681f3Smrg} 59377ec681f3Smrg 59387ec681f3Smrg 593901e04c3fSmrgvoid GLAPIENTRY 594001e04c3fSmrg_mesa_CompressedTexSubImage2D_no_error(GLenum target, GLint level, 594101e04c3fSmrg GLint xoffset, GLint yoffset, 594201e04c3fSmrg GLsizei width, GLsizei height, 594301e04c3fSmrg GLenum format, GLsizei imageSize, 594401e04c3fSmrg const GLvoid *data) 594501e04c3fSmrg{ 59467ec681f3Smrg compressed_tex_sub_image(2, target, 0, level, 59477ec681f3Smrg xoffset, yoffset, 0, 59487ec681f3Smrg width, height, 1, format, imageSize, data, 59497ec681f3Smrg TEX_MODE_CURRENT_NO_ERROR, 59507ec681f3Smrg "glCompressedTexSubImage2D"); 595101e04c3fSmrg} 59527117f1b4Smrg 59537117f1b4Smrg 595401e04c3fSmrgvoid GLAPIENTRY 595501e04c3fSmrg_mesa_CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, 595601e04c3fSmrg GLint yoffset, GLsizei width, GLsizei height, 595701e04c3fSmrg GLenum format, GLsizei imageSize, 595801e04c3fSmrg const GLvoid *data) 595901e04c3fSmrg{ 59607ec681f3Smrg compressed_tex_sub_image(2, target, 0, level, 59617ec681f3Smrg xoffset, yoffset, 0, 59627ec681f3Smrg width, height, 1, format, imageSize, data, 59637ec681f3Smrg TEX_MODE_CURRENT_ERROR, 59647ec681f3Smrg "glCompressedTexSubImage2D"); 59657ec681f3Smrg} 59667ec681f3Smrg 59677ec681f3Smrg 59687ec681f3Smrgvoid GLAPIENTRY 59697ec681f3Smrg_mesa_CompressedTextureSubImage2DEXT(GLuint texture, GLenum target, 59707ec681f3Smrg GLint level, GLint xoffset, 59717ec681f3Smrg GLint yoffset, GLsizei width, 59727ec681f3Smrg GLsizei height, GLenum format, 59737ec681f3Smrg GLsizei imageSize, const GLvoid *data) 59747ec681f3Smrg{ 59757ec681f3Smrg compressed_tex_sub_image(2, target, texture, level, xoffset, 59767ec681f3Smrg yoffset, 0, width, height, 1, format, 59777ec681f3Smrg imageSize, data, 59787ec681f3Smrg TEX_MODE_EXT_DSA_TEXTURE, 59797ec681f3Smrg "glCompressedTextureSubImage2DEXT"); 59807ec681f3Smrg} 59817ec681f3Smrg 59827ec681f3Smrg 59837ec681f3Smrgvoid GLAPIENTRY 59847ec681f3Smrg_mesa_CompressedMultiTexSubImage2DEXT(GLenum texunit, GLenum target, 59857ec681f3Smrg GLint level, GLint xoffset, GLint yoffset, 59867ec681f3Smrg GLsizei width, GLsizei height, GLenum format, 59877ec681f3Smrg GLsizei imageSize, const GLvoid *data) 59887ec681f3Smrg{ 59897ec681f3Smrg compressed_tex_sub_image(2, target, texunit - GL_TEXTURE0, level, 59907ec681f3Smrg xoffset, yoffset, 0, width, height, 1, format, 59917ec681f3Smrg imageSize, data, 59927ec681f3Smrg TEX_MODE_EXT_DSA_TEXUNIT, 59937ec681f3Smrg "glCompressedMultiTexSubImage2DEXT"); 59947117f1b4Smrg} 59957117f1b4Smrg 59967117f1b4Smrg 59974a49301eSmrgvoid GLAPIENTRY 599801e04c3fSmrg_mesa_CompressedTextureSubImage2D_no_error(GLuint texture, GLint level, 599901e04c3fSmrg GLint xoffset, GLint yoffset, 600001e04c3fSmrg GLsizei width, GLsizei height, 600101e04c3fSmrg GLenum format, GLsizei imageSize, 600201e04c3fSmrg const GLvoid *data) 60034a49301eSmrg{ 60047ec681f3Smrg compressed_tex_sub_image(2, 0, texture, level, xoffset, yoffset, 0, 60057ec681f3Smrg width, height, 1, format, imageSize, data, 60067ec681f3Smrg TEX_MODE_DSA_NO_ERROR, 60077ec681f3Smrg "glCompressedTextureSubImage2D"); 60084a49301eSmrg} 60094a49301eSmrg 60104a49301eSmrg 60117117f1b4Smrgvoid GLAPIENTRY 601201e04c3fSmrg_mesa_CompressedTextureSubImage2D(GLuint texture, GLint level, GLint xoffset, 601301e04c3fSmrg GLint yoffset, 601401e04c3fSmrg GLsizei width, GLsizei height, 601501e04c3fSmrg GLenum format, GLsizei imageSize, 601601e04c3fSmrg const GLvoid *data) 60177117f1b4Smrg{ 60187ec681f3Smrg compressed_tex_sub_image(2, 0, texture, level, xoffset, yoffset, 0, 60197ec681f3Smrg width, height, 1, format, imageSize, data, 60207ec681f3Smrg TEX_MODE_DSA_ERROR, 60217ec681f3Smrg "glCompressedTextureSubImage2D"); 60227117f1b4Smrg} 60237117f1b4Smrg 602401e04c3fSmrgvoid GLAPIENTRY 602501e04c3fSmrg_mesa_CompressedTexSubImage3D_no_error(GLenum target, GLint level, 602601e04c3fSmrg GLint xoffset, GLint yoffset, 602701e04c3fSmrg GLint zoffset, GLsizei width, 602801e04c3fSmrg GLsizei height, GLsizei depth, 602901e04c3fSmrg GLenum format, GLsizei imageSize, 603001e04c3fSmrg const GLvoid *data) 603101e04c3fSmrg{ 60327ec681f3Smrg compressed_tex_sub_image(3, target, 0, level, xoffset, yoffset, 60337ec681f3Smrg zoffset, width, height, depth, format, 60347ec681f3Smrg imageSize, data, 60357ec681f3Smrg TEX_MODE_CURRENT_NO_ERROR, 60367ec681f3Smrg "glCompressedTexSubImage3D"); 603701e04c3fSmrg} 60387117f1b4Smrg 60397117f1b4Smrgvoid GLAPIENTRY 6040af69d88dSmrg_mesa_CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, 604101e04c3fSmrg GLint yoffset, GLint zoffset, GLsizei width, 604201e04c3fSmrg GLsizei height, GLsizei depth, GLenum format, 604301e04c3fSmrg GLsizei imageSize, const GLvoid *data) 604401e04c3fSmrg{ 60457ec681f3Smrg compressed_tex_sub_image(3, target, 0, level, xoffset, yoffset, 60467ec681f3Smrg zoffset, width, height, depth, format, 60477ec681f3Smrg imageSize, data, 60487ec681f3Smrg TEX_MODE_CURRENT_ERROR, 60497ec681f3Smrg "glCompressedTexSubImage3D"); 605001e04c3fSmrg} 605101e04c3fSmrg 605201e04c3fSmrgvoid GLAPIENTRY 605301e04c3fSmrg_mesa_CompressedTextureSubImage3D_no_error(GLuint texture, GLint level, 605401e04c3fSmrg GLint xoffset, GLint yoffset, 605501e04c3fSmrg GLint zoffset, GLsizei width, 605601e04c3fSmrg GLsizei height, GLsizei depth, 605701e04c3fSmrg GLenum format, GLsizei imageSize, 605801e04c3fSmrg const GLvoid *data) 605901e04c3fSmrg{ 60607ec681f3Smrg compressed_tex_sub_image(3, 0, texture, level, xoffset, yoffset, 60617ec681f3Smrg zoffset, width, height, depth, format, 60627ec681f3Smrg imageSize, data, 60637ec681f3Smrg TEX_MODE_DSA_NO_ERROR, 60647ec681f3Smrg "glCompressedTextureSubImage3D"); 606501e04c3fSmrg} 606601e04c3fSmrg 606701e04c3fSmrgvoid GLAPIENTRY 606801e04c3fSmrg_mesa_CompressedTextureSubImage3D(GLuint texture, GLint level, GLint xoffset, 606901e04c3fSmrg GLint yoffset, GLint zoffset, GLsizei width, 607001e04c3fSmrg GLsizei height, GLsizei depth, 607101e04c3fSmrg GLenum format, GLsizei imageSize, 607201e04c3fSmrg const GLvoid *data) 60737117f1b4Smrg{ 60747ec681f3Smrg compressed_tex_sub_image(3, 0, texture, level, xoffset, yoffset, 60757ec681f3Smrg zoffset, width, height, depth, format, 60767ec681f3Smrg imageSize, data, 60777ec681f3Smrg TEX_MODE_DSA_ERROR, 60787ec681f3Smrg "glCompressedTextureSubImage3D"); 60797ec681f3Smrg} 60807ec681f3Smrg 60817ec681f3Smrg 60827ec681f3Smrgvoid GLAPIENTRY 60837ec681f3Smrg_mesa_CompressedTextureSubImage3DEXT(GLuint texture, GLenum target, 60847ec681f3Smrg GLint level, GLint xoffset, 60857ec681f3Smrg GLint yoffset, GLint zoffset, 60867ec681f3Smrg GLsizei width, GLsizei height, 60877ec681f3Smrg GLsizei depth, GLenum format, 60887ec681f3Smrg GLsizei imageSize, const GLvoid *data) 60897ec681f3Smrg{ 60907ec681f3Smrg compressed_tex_sub_image(3, target, texture, level, xoffset, yoffset, 60917ec681f3Smrg zoffset, width, height, depth, format, 60927ec681f3Smrg imageSize, data, 60937ec681f3Smrg TEX_MODE_EXT_DSA_TEXTURE, 60947ec681f3Smrg "glCompressedTextureSubImage3DEXT"); 60957117f1b4Smrg} 60967117f1b4Smrg 60977ec681f3Smrg 60987ec681f3Smrgvoid GLAPIENTRY 60997ec681f3Smrg_mesa_CompressedMultiTexSubImage3DEXT(GLenum texunit, GLenum target, 61007ec681f3Smrg GLint level, GLint xoffset, GLint yoffset, 61017ec681f3Smrg GLint zoffset, GLsizei width, GLsizei height, 61027ec681f3Smrg GLsizei depth, GLenum format, 61037ec681f3Smrg GLsizei imageSize, const GLvoid *data) 61047ec681f3Smrg{ 61057ec681f3Smrg compressed_tex_sub_image(3, target, texunit - GL_TEXTURE0, level, 61067ec681f3Smrg xoffset, yoffset, zoffset, width, height, depth, 61077ec681f3Smrg format, imageSize, data, 61087ec681f3Smrg TEX_MODE_EXT_DSA_TEXUNIT, 61097ec681f3Smrg "glCompressedMultiTexSubImage3DEXT"); 61107ec681f3Smrg} 61117ec681f3Smrg 61127ec681f3Smrg 611301e04c3fSmrgmesa_format 611401e04c3fSmrg_mesa_get_texbuffer_format(const struct gl_context *ctx, GLenum internalFormat) 61153464ebd5Sriastradh{ 611601e04c3fSmrg if (ctx->API == API_OPENGL_COMPAT) { 6117af69d88dSmrg switch (internalFormat) { 6118af69d88dSmrg case GL_ALPHA8: 6119af69d88dSmrg return MESA_FORMAT_A_UNORM8; 6120af69d88dSmrg case GL_ALPHA16: 6121af69d88dSmrg return MESA_FORMAT_A_UNORM16; 6122af69d88dSmrg case GL_ALPHA16F_ARB: 6123af69d88dSmrg return MESA_FORMAT_A_FLOAT16; 6124af69d88dSmrg case GL_ALPHA32F_ARB: 6125af69d88dSmrg return MESA_FORMAT_A_FLOAT32; 6126af69d88dSmrg case GL_ALPHA8I_EXT: 6127af69d88dSmrg return MESA_FORMAT_A_SINT8; 6128af69d88dSmrg case GL_ALPHA16I_EXT: 6129af69d88dSmrg return MESA_FORMAT_A_SINT16; 6130af69d88dSmrg case GL_ALPHA32I_EXT: 6131af69d88dSmrg return MESA_FORMAT_A_SINT32; 6132af69d88dSmrg case GL_ALPHA8UI_EXT: 6133af69d88dSmrg return MESA_FORMAT_A_UINT8; 6134af69d88dSmrg case GL_ALPHA16UI_EXT: 6135af69d88dSmrg return MESA_FORMAT_A_UINT16; 6136af69d88dSmrg case GL_ALPHA32UI_EXT: 6137af69d88dSmrg return MESA_FORMAT_A_UINT32; 6138af69d88dSmrg case GL_LUMINANCE8: 6139af69d88dSmrg return MESA_FORMAT_L_UNORM8; 6140af69d88dSmrg case GL_LUMINANCE16: 6141af69d88dSmrg return MESA_FORMAT_L_UNORM16; 6142af69d88dSmrg case GL_LUMINANCE16F_ARB: 6143af69d88dSmrg return MESA_FORMAT_L_FLOAT16; 6144af69d88dSmrg case GL_LUMINANCE32F_ARB: 6145af69d88dSmrg return MESA_FORMAT_L_FLOAT32; 6146af69d88dSmrg case GL_LUMINANCE8I_EXT: 6147af69d88dSmrg return MESA_FORMAT_L_SINT8; 6148af69d88dSmrg case GL_LUMINANCE16I_EXT: 6149af69d88dSmrg return MESA_FORMAT_L_SINT16; 6150af69d88dSmrg case GL_LUMINANCE32I_EXT: 6151af69d88dSmrg return MESA_FORMAT_L_SINT32; 6152af69d88dSmrg case GL_LUMINANCE8UI_EXT: 6153af69d88dSmrg return MESA_FORMAT_L_UINT8; 6154af69d88dSmrg case GL_LUMINANCE16UI_EXT: 6155af69d88dSmrg return MESA_FORMAT_L_UINT16; 6156af69d88dSmrg case GL_LUMINANCE32UI_EXT: 6157af69d88dSmrg return MESA_FORMAT_L_UINT32; 6158af69d88dSmrg case GL_LUMINANCE8_ALPHA8: 61597ec681f3Smrg return MESA_FORMAT_LA_UNORM8; 6160af69d88dSmrg case GL_LUMINANCE16_ALPHA16: 61617ec681f3Smrg return MESA_FORMAT_LA_UNORM16; 6162af69d88dSmrg case GL_LUMINANCE_ALPHA16F_ARB: 6163af69d88dSmrg return MESA_FORMAT_LA_FLOAT16; 6164af69d88dSmrg case GL_LUMINANCE_ALPHA32F_ARB: 6165af69d88dSmrg return MESA_FORMAT_LA_FLOAT32; 6166af69d88dSmrg case GL_LUMINANCE_ALPHA8I_EXT: 6167af69d88dSmrg return MESA_FORMAT_LA_SINT8; 6168af69d88dSmrg case GL_LUMINANCE_ALPHA16I_EXT: 6169af69d88dSmrg return MESA_FORMAT_LA_SINT16; 617001e04c3fSmrg case GL_LUMINANCE_ALPHA32I_EXT: 617101e04c3fSmrg return MESA_FORMAT_LA_SINT32; 6172af69d88dSmrg case GL_LUMINANCE_ALPHA8UI_EXT: 6173af69d88dSmrg return MESA_FORMAT_LA_UINT8; 6174af69d88dSmrg case GL_LUMINANCE_ALPHA16UI_EXT: 6175af69d88dSmrg return MESA_FORMAT_LA_UINT16; 6176af69d88dSmrg case GL_LUMINANCE_ALPHA32UI_EXT: 6177af69d88dSmrg return MESA_FORMAT_LA_UINT32; 6178af69d88dSmrg case GL_INTENSITY8: 6179af69d88dSmrg return MESA_FORMAT_I_UNORM8; 6180af69d88dSmrg case GL_INTENSITY16: 6181af69d88dSmrg return MESA_FORMAT_I_UNORM16; 6182af69d88dSmrg case GL_INTENSITY16F_ARB: 6183af69d88dSmrg return MESA_FORMAT_I_FLOAT16; 6184af69d88dSmrg case GL_INTENSITY32F_ARB: 6185af69d88dSmrg return MESA_FORMAT_I_FLOAT32; 6186af69d88dSmrg case GL_INTENSITY8I_EXT: 6187af69d88dSmrg return MESA_FORMAT_I_SINT8; 6188af69d88dSmrg case GL_INTENSITY16I_EXT: 6189af69d88dSmrg return MESA_FORMAT_I_SINT16; 6190af69d88dSmrg case GL_INTENSITY32I_EXT: 6191af69d88dSmrg return MESA_FORMAT_I_SINT32; 6192af69d88dSmrg case GL_INTENSITY8UI_EXT: 6193af69d88dSmrg return MESA_FORMAT_I_UINT8; 6194af69d88dSmrg case GL_INTENSITY16UI_EXT: 6195af69d88dSmrg return MESA_FORMAT_I_UINT16; 6196af69d88dSmrg case GL_INTENSITY32UI_EXT: 6197af69d88dSmrg return MESA_FORMAT_I_UINT32; 6198af69d88dSmrg default: 6199af69d88dSmrg break; 6200af69d88dSmrg } 6201af69d88dSmrg } 6202af69d88dSmrg 620301e04c3fSmrg if (_mesa_has_ARB_texture_buffer_object_rgb32(ctx) || 620401e04c3fSmrg _mesa_has_OES_texture_buffer(ctx)) { 6205af69d88dSmrg switch (internalFormat) { 6206af69d88dSmrg case GL_RGB32F: 6207af69d88dSmrg return MESA_FORMAT_RGB_FLOAT32; 6208af69d88dSmrg case GL_RGB32UI: 6209af69d88dSmrg return MESA_FORMAT_RGB_UINT32; 6210af69d88dSmrg case GL_RGB32I: 6211af69d88dSmrg return MESA_FORMAT_RGB_SINT32; 6212af69d88dSmrg default: 6213af69d88dSmrg break; 6214af69d88dSmrg } 6215af69d88dSmrg } 6216af69d88dSmrg 62173464ebd5Sriastradh switch (internalFormat) { 62183464ebd5Sriastradh case GL_RGBA8: 6219af69d88dSmrg return MESA_FORMAT_R8G8B8A8_UNORM; 62203464ebd5Sriastradh case GL_RGBA16: 622101e04c3fSmrg if (_mesa_is_gles(ctx) && !_mesa_has_EXT_texture_norm16(ctx)) 622201e04c3fSmrg return MESA_FORMAT_NONE; 6223af69d88dSmrg return MESA_FORMAT_RGBA_UNORM16; 62243464ebd5Sriastradh case GL_RGBA16F_ARB: 6225af69d88dSmrg return MESA_FORMAT_RGBA_FLOAT16; 62263464ebd5Sriastradh case GL_RGBA32F_ARB: 6227af69d88dSmrg return MESA_FORMAT_RGBA_FLOAT32; 62283464ebd5Sriastradh case GL_RGBA8I_EXT: 6229af69d88dSmrg return MESA_FORMAT_RGBA_SINT8; 62303464ebd5Sriastradh case GL_RGBA16I_EXT: 6231af69d88dSmrg return MESA_FORMAT_RGBA_SINT16; 62323464ebd5Sriastradh case GL_RGBA32I_EXT: 6233af69d88dSmrg return MESA_FORMAT_RGBA_SINT32; 62343464ebd5Sriastradh case GL_RGBA8UI_EXT: 6235af69d88dSmrg return MESA_FORMAT_RGBA_UINT8; 62363464ebd5Sriastradh case GL_RGBA16UI_EXT: 6237af69d88dSmrg return MESA_FORMAT_RGBA_UINT16; 62383464ebd5Sriastradh case GL_RGBA32UI_EXT: 6239af69d88dSmrg return MESA_FORMAT_RGBA_UINT32; 6240af69d88dSmrg 6241af69d88dSmrg case GL_RG8: 62427ec681f3Smrg return MESA_FORMAT_RG_UNORM8; 6243af69d88dSmrg case GL_RG16: 624401e04c3fSmrg if (_mesa_is_gles(ctx) && !_mesa_has_EXT_texture_norm16(ctx)) 624501e04c3fSmrg return MESA_FORMAT_NONE; 62467ec681f3Smrg return MESA_FORMAT_RG_UNORM16; 6247af69d88dSmrg case GL_RG16F: 6248af69d88dSmrg return MESA_FORMAT_RG_FLOAT16; 6249af69d88dSmrg case GL_RG32F: 6250af69d88dSmrg return MESA_FORMAT_RG_FLOAT32; 6251af69d88dSmrg case GL_RG8I: 6252af69d88dSmrg return MESA_FORMAT_RG_SINT8; 6253af69d88dSmrg case GL_RG16I: 6254af69d88dSmrg return MESA_FORMAT_RG_SINT16; 6255af69d88dSmrg case GL_RG32I: 6256af69d88dSmrg return MESA_FORMAT_RG_SINT32; 6257af69d88dSmrg case GL_RG8UI: 6258af69d88dSmrg return MESA_FORMAT_RG_UINT8; 6259af69d88dSmrg case GL_RG16UI: 6260af69d88dSmrg return MESA_FORMAT_RG_UINT16; 6261af69d88dSmrg case GL_RG32UI: 6262af69d88dSmrg return MESA_FORMAT_RG_UINT32; 6263af69d88dSmrg 6264af69d88dSmrg case GL_R8: 6265af69d88dSmrg return MESA_FORMAT_R_UNORM8; 6266af69d88dSmrg case GL_R16: 626701e04c3fSmrg if (_mesa_is_gles(ctx) && !_mesa_has_EXT_texture_norm16(ctx)) 626801e04c3fSmrg return MESA_FORMAT_NONE; 6269af69d88dSmrg return MESA_FORMAT_R_UNORM16; 6270af69d88dSmrg case GL_R16F: 6271af69d88dSmrg return MESA_FORMAT_R_FLOAT16; 6272af69d88dSmrg case GL_R32F: 6273af69d88dSmrg return MESA_FORMAT_R_FLOAT32; 6274af69d88dSmrg case GL_R8I: 6275af69d88dSmrg return MESA_FORMAT_R_SINT8; 6276af69d88dSmrg case GL_R16I: 6277af69d88dSmrg return MESA_FORMAT_R_SINT16; 6278af69d88dSmrg case GL_R32I: 6279af69d88dSmrg return MESA_FORMAT_R_SINT32; 6280af69d88dSmrg case GL_R8UI: 6281af69d88dSmrg return MESA_FORMAT_R_UINT8; 6282af69d88dSmrg case GL_R16UI: 6283af69d88dSmrg return MESA_FORMAT_R_UINT16; 6284af69d88dSmrg case GL_R32UI: 6285af69d88dSmrg return MESA_FORMAT_R_UINT32; 6286af69d88dSmrg 62873464ebd5Sriastradh default: 6288af69d88dSmrg return MESA_FORMAT_NONE; 62893464ebd5Sriastradh } 6290af69d88dSmrg} 62913464ebd5Sriastradh 62923464ebd5Sriastradh 6293af69d88dSmrgmesa_format 6294af69d88dSmrg_mesa_validate_texbuffer_format(const struct gl_context *ctx, 6295af69d88dSmrg GLenum internalFormat) 6296af69d88dSmrg{ 629701e04c3fSmrg mesa_format format = _mesa_get_texbuffer_format(ctx, internalFormat); 6298af69d88dSmrg GLenum datatype; 6299af69d88dSmrg 6300af69d88dSmrg if (format == MESA_FORMAT_NONE) 6301af69d88dSmrg return MESA_FORMAT_NONE; 6302af69d88dSmrg 6303af69d88dSmrg datatype = _mesa_get_format_datatype(format); 6304af69d88dSmrg 6305af69d88dSmrg /* The GL_ARB_texture_buffer_object spec says: 6306af69d88dSmrg * 6307af69d88dSmrg * "If ARB_texture_float is not supported, references to the 6308af69d88dSmrg * floating-point internal formats provided by that extension should be 6309af69d88dSmrg * removed, and such formats may not be passed to TexBufferARB." 6310af69d88dSmrg * 6311af69d88dSmrg * As a result, GL_HALF_FLOAT internal format depends on both 6312af69d88dSmrg * GL_ARB_texture_float and GL_ARB_half_float_pixel. 6313af69d88dSmrg */ 6314af69d88dSmrg if ((datatype == GL_FLOAT || datatype == GL_HALF_FLOAT) && 6315af69d88dSmrg !ctx->Extensions.ARB_texture_float) 6316af69d88dSmrg return MESA_FORMAT_NONE; 63173464ebd5Sriastradh 6318af69d88dSmrg if (!ctx->Extensions.ARB_texture_rg) { 6319af69d88dSmrg GLenum base_format = _mesa_get_format_base_format(format); 6320af69d88dSmrg if (base_format == GL_R || base_format == GL_RG) 6321af69d88dSmrg return MESA_FORMAT_NONE; 6322af69d88dSmrg } 6323af69d88dSmrg 6324af69d88dSmrg if (!ctx->Extensions.ARB_texture_buffer_object_rgb32) { 6325af69d88dSmrg GLenum base_format = _mesa_get_format_base_format(format); 6326af69d88dSmrg if (base_format == GL_RGB) 6327af69d88dSmrg return MESA_FORMAT_NONE; 6328af69d88dSmrg } 6329af69d88dSmrg return format; 6330af69d88dSmrg} 6331af69d88dSmrg 6332af69d88dSmrg 633301e04c3fSmrg/** 633401e04c3fSmrg * Do work common to glTexBuffer, glTexBufferRange, glTextureBuffer 633501e04c3fSmrg * and glTextureBufferRange, including some error checking. 633601e04c3fSmrg */ 6337af69d88dSmrgstatic void 633801e04c3fSmrgtexture_buffer_range(struct gl_context *ctx, 633901e04c3fSmrg struct gl_texture_object *texObj, 634001e04c3fSmrg GLenum internalFormat, 634101e04c3fSmrg struct gl_buffer_object *bufObj, 634201e04c3fSmrg GLintptr offset, GLsizeiptr size, 634301e04c3fSmrg const char *caller) 6344af69d88dSmrg{ 634501e04c3fSmrg GLintptr oldOffset = texObj->BufferOffset; 634601e04c3fSmrg GLsizeiptr oldSize = texObj->BufferSize; 6347af69d88dSmrg mesa_format format; 63487ec681f3Smrg mesa_format old_format; 6349af69d88dSmrg 635001e04c3fSmrg /* NOTE: ARB_texture_buffer_object might not be supported in 635101e04c3fSmrg * the compatibility profile. 635201e04c3fSmrg */ 635301e04c3fSmrg if (!_mesa_has_ARB_texture_buffer_object(ctx) && 635401e04c3fSmrg !_mesa_has_OES_texture_buffer(ctx)) { 635501e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 635601e04c3fSmrg "%s(ARB_texture_buffer_object is not" 635701e04c3fSmrg " implemented for the compatibility profile)", caller); 635801e04c3fSmrg return; 635901e04c3fSmrg } 6360af69d88dSmrg 636101e04c3fSmrg if (texObj->HandleAllocated) { 636201e04c3fSmrg /* The ARB_bindless_texture spec says: 636301e04c3fSmrg * 636401e04c3fSmrg * "The error INVALID_OPERATION is generated by TexImage*, CopyTexImage*, 636501e04c3fSmrg * CompressedTexImage*, TexBuffer*, TexParameter*, as well as other 636601e04c3fSmrg * functions defined in terms of these, if the texture object to be 636701e04c3fSmrg * modified is referenced by one or more texture or image handles." 636801e04c3fSmrg */ 636901e04c3fSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(immutable texture)", caller); 6370af69d88dSmrg return; 6371af69d88dSmrg } 6372af69d88dSmrg 6373af69d88dSmrg format = _mesa_validate_texbuffer_format(ctx, internalFormat); 6374af69d88dSmrg if (format == MESA_FORMAT_NONE) { 637501e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalFormat %s)", 637601e04c3fSmrg caller, _mesa_enum_to_string(internalFormat)); 6377af69d88dSmrg return; 6378af69d88dSmrg } 6379af69d88dSmrg 63807ec681f3Smrg FLUSH_VERTICES(ctx, 0, GL_TEXTURE_BIT); 6381af69d88dSmrg 6382af69d88dSmrg _mesa_lock_texture(ctx, texObj); 6383af69d88dSmrg { 63847ec681f3Smrg _mesa_reference_buffer_object_shared(ctx, &texObj->BufferObject, bufObj); 6385af69d88dSmrg texObj->BufferObjectFormat = internalFormat; 63867ec681f3Smrg old_format = texObj->_BufferObjectFormat; 6387af69d88dSmrg texObj->_BufferObjectFormat = format; 6388af69d88dSmrg texObj->BufferOffset = offset; 6389af69d88dSmrg texObj->BufferSize = size; 6390af69d88dSmrg } 6391af69d88dSmrg _mesa_unlock_texture(ctx, texObj); 639201e04c3fSmrg 639301e04c3fSmrg if (ctx->Driver.TexParameter) { 63947ec681f3Smrg if (old_format != format) { 63957ec681f3Smrg ctx->Driver.TexParameter(ctx, texObj, GL_ALL_ATTRIB_BITS); 63967ec681f3Smrg } else { 63977ec681f3Smrg if (offset != oldOffset) { 63987ec681f3Smrg ctx->Driver.TexParameter(ctx, texObj, GL_TEXTURE_BUFFER_OFFSET); 63997ec681f3Smrg } 64007ec681f3Smrg if (size != oldSize) { 64017ec681f3Smrg ctx->Driver.TexParameter(ctx, texObj, GL_TEXTURE_BUFFER_SIZE); 64027ec681f3Smrg } 640301e04c3fSmrg } 640401e04c3fSmrg } 640501e04c3fSmrg 640601e04c3fSmrg ctx->NewDriverState |= ctx->DriverFlags.NewTextureBuffer; 640701e04c3fSmrg 640801e04c3fSmrg if (bufObj) { 640901e04c3fSmrg bufObj->UsageHistory |= USAGE_TEXTURE_BUFFER; 641001e04c3fSmrg } 641101e04c3fSmrg} 641201e04c3fSmrg 641301e04c3fSmrg 641401e04c3fSmrg/** 641501e04c3fSmrg * Make sure the texture buffer target is GL_TEXTURE_BUFFER. 641601e04c3fSmrg * Return true if it is, and return false if it is not 641701e04c3fSmrg * (and throw INVALID ENUM as dictated in the OpenGL 4.5 641801e04c3fSmrg * core spec, 02.02.2015, PDF page 245). 641901e04c3fSmrg */ 642001e04c3fSmrgstatic bool 642101e04c3fSmrgcheck_texture_buffer_target(struct gl_context *ctx, GLenum target, 64227ec681f3Smrg const char *caller, bool dsa) 642301e04c3fSmrg{ 642401e04c3fSmrg if (target != GL_TEXTURE_BUFFER_ARB) { 64257ec681f3Smrg _mesa_error(ctx, dsa ? GL_INVALID_OPERATION : GL_INVALID_ENUM, 642601e04c3fSmrg "%s(texture target is not GL_TEXTURE_BUFFER)", caller); 642701e04c3fSmrg return false; 642801e04c3fSmrg } 642901e04c3fSmrg else 643001e04c3fSmrg return true; 643101e04c3fSmrg} 643201e04c3fSmrg 643301e04c3fSmrg/** 643401e04c3fSmrg * Check for errors related to the texture buffer range. 643501e04c3fSmrg * Return false if errors are found, true if none are found. 643601e04c3fSmrg */ 643701e04c3fSmrgstatic bool 643801e04c3fSmrgcheck_texture_buffer_range(struct gl_context *ctx, 643901e04c3fSmrg struct gl_buffer_object *bufObj, 644001e04c3fSmrg GLintptr offset, GLsizeiptr size, 644101e04c3fSmrg const char *caller) 644201e04c3fSmrg{ 644301e04c3fSmrg /* OpenGL 4.5 core spec (02.02.2015) says in Section 8.9 Buffer 644401e04c3fSmrg * Textures (PDF page 245): 644501e04c3fSmrg * "An INVALID_VALUE error is generated if offset is negative, if 644601e04c3fSmrg * size is less than or equal to zero, or if offset + size is greater 644701e04c3fSmrg * than the value of BUFFER_SIZE for the buffer bound to target." 644801e04c3fSmrg */ 644901e04c3fSmrg if (offset < 0) { 645001e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(offset=%d < 0)", caller, 645101e04c3fSmrg (int) offset); 645201e04c3fSmrg return false; 645301e04c3fSmrg } 645401e04c3fSmrg 645501e04c3fSmrg if (size <= 0) { 645601e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(size=%d <= 0)", caller, 645701e04c3fSmrg (int) size); 645801e04c3fSmrg return false; 645901e04c3fSmrg } 646001e04c3fSmrg 646101e04c3fSmrg if (offset + size > bufObj->Size) { 646201e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, 646301e04c3fSmrg "%s(offset=%d + size=%d > buffer_size=%d)", caller, 646401e04c3fSmrg (int) offset, (int) size, (int) bufObj->Size); 646501e04c3fSmrg return false; 646601e04c3fSmrg } 646701e04c3fSmrg 646801e04c3fSmrg /* OpenGL 4.5 core spec (02.02.2015) says in Section 8.9 Buffer 646901e04c3fSmrg * Textures (PDF page 245): 647001e04c3fSmrg * "An INVALID_VALUE error is generated if offset is not an integer 647101e04c3fSmrg * multiple of the value of TEXTURE_BUFFER_OFFSET_ALIGNMENT." 647201e04c3fSmrg */ 647301e04c3fSmrg if (offset % ctx->Const.TextureBufferOffsetAlignment) { 647401e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, 647501e04c3fSmrg "%s(invalid offset alignment)", caller); 647601e04c3fSmrg return false; 647701e04c3fSmrg } 647801e04c3fSmrg 647901e04c3fSmrg return true; 64803464ebd5Sriastradh} 64813464ebd5Sriastradh 64823464ebd5Sriastradh 64833464ebd5Sriastradh/** GL_ARB_texture_buffer_object */ 64843464ebd5Sriastradhvoid GLAPIENTRY 64853464ebd5Sriastradh_mesa_TexBuffer(GLenum target, GLenum internalFormat, GLuint buffer) 64863464ebd5Sriastradh{ 648701e04c3fSmrg struct gl_texture_object *texObj; 64883464ebd5Sriastradh struct gl_buffer_object *bufObj; 64893464ebd5Sriastradh 64903464ebd5Sriastradh GET_CURRENT_CONTEXT(ctx); 64913464ebd5Sriastradh 649201e04c3fSmrg /* Need to catch a bad target before it gets to 649301e04c3fSmrg * _mesa_get_current_tex_object. 6494af69d88dSmrg */ 64957ec681f3Smrg if (!check_texture_buffer_target(ctx, target, "glTexBuffer", false)) 64963464ebd5Sriastradh return; 64973464ebd5Sriastradh 649801e04c3fSmrg if (buffer) { 649901e04c3fSmrg bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glTexBuffer"); 650001e04c3fSmrg if (!bufObj) 650101e04c3fSmrg return; 650201e04c3fSmrg } else 650301e04c3fSmrg bufObj = NULL; 650401e04c3fSmrg 650501e04c3fSmrg texObj = _mesa_get_current_tex_object(ctx, target); 650601e04c3fSmrg if (!texObj) 65073464ebd5Sriastradh return; 65083464ebd5Sriastradh 650901e04c3fSmrg texture_buffer_range(ctx, texObj, internalFormat, bufObj, 0, 651001e04c3fSmrg buffer ? -1 : 0, "glTexBuffer"); 6511af69d88dSmrg} 6512af69d88dSmrg 6513af69d88dSmrg 6514af69d88dSmrg/** GL_ARB_texture_buffer_range */ 6515af69d88dSmrgvoid GLAPIENTRY 6516af69d88dSmrg_mesa_TexBufferRange(GLenum target, GLenum internalFormat, GLuint buffer, 6517af69d88dSmrg GLintptr offset, GLsizeiptr size) 6518af69d88dSmrg{ 651901e04c3fSmrg struct gl_texture_object *texObj; 6520af69d88dSmrg struct gl_buffer_object *bufObj; 6521af69d88dSmrg 6522af69d88dSmrg GET_CURRENT_CONTEXT(ctx); 6523af69d88dSmrg 652401e04c3fSmrg /* Need to catch a bad target before it gets to 652501e04c3fSmrg * _mesa_get_current_tex_object. 652601e04c3fSmrg */ 65277ec681f3Smrg if (!check_texture_buffer_target(ctx, target, "glTexBufferRange", false)) 65283464ebd5Sriastradh return; 65293464ebd5Sriastradh 653001e04c3fSmrg if (buffer) { 653101e04c3fSmrg bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glTexBufferRange"); 653201e04c3fSmrg if (!bufObj) 6533af69d88dSmrg return; 653401e04c3fSmrg 653501e04c3fSmrg if (!check_texture_buffer_range(ctx, bufObj, offset, size, 653601e04c3fSmrg "glTexBufferRange")) 6537af69d88dSmrg return; 653801e04c3fSmrg 6539af69d88dSmrg } else { 654001e04c3fSmrg /* OpenGL 4.5 core spec (02.02.2015) says in Section 8.9 Buffer 654101e04c3fSmrg * Textures (PDF page 254): 654201e04c3fSmrg * "If buffer is zero, then any buffer object attached to the buffer 654301e04c3fSmrg * texture is detached, the values offset and size are ignored and 654401e04c3fSmrg * the state for offset and size for the buffer texture are reset to 654501e04c3fSmrg * zero." 654601e04c3fSmrg */ 6547af69d88dSmrg offset = 0; 6548af69d88dSmrg size = 0; 654901e04c3fSmrg bufObj = NULL; 6550af69d88dSmrg } 6551af69d88dSmrg 655201e04c3fSmrg texObj = _mesa_get_current_tex_object(ctx, target); 655301e04c3fSmrg if (!texObj) 655401e04c3fSmrg return; 655501e04c3fSmrg 655601e04c3fSmrg texture_buffer_range(ctx, texObj, internalFormat, bufObj, 655701e04c3fSmrg offset, size, "glTexBufferRange"); 6558af69d88dSmrg} 6559af69d88dSmrg 65607ec681f3Smrg 65617ec681f3Smrg/** GL_ARB_texture_buffer_range + GL_EXT_direct_state_access */ 65627ec681f3Smrgvoid GLAPIENTRY 65637ec681f3Smrg_mesa_TextureBufferRangeEXT(GLuint texture, GLenum target, GLenum internalFormat, 65647ec681f3Smrg GLuint buffer, GLintptr offset, GLsizeiptr size) 65657ec681f3Smrg{ 65667ec681f3Smrg struct gl_texture_object *texObj; 65677ec681f3Smrg struct gl_buffer_object *bufObj; 65687ec681f3Smrg 65697ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 65707ec681f3Smrg 65717ec681f3Smrg texObj = _mesa_lookup_or_create_texture(ctx, target, texture, false, true, 65727ec681f3Smrg "glTextureBufferRangeEXT"); 65737ec681f3Smrg if (!texObj) 65747ec681f3Smrg return; 65757ec681f3Smrg 65767ec681f3Smrg if (!check_texture_buffer_target(ctx, target, "glTextureBufferRangeEXT", true)) 65777ec681f3Smrg return; 65787ec681f3Smrg 65797ec681f3Smrg if (buffer) { 65807ec681f3Smrg bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glTextureBufferRangeEXT"); 65817ec681f3Smrg if (!bufObj) 65827ec681f3Smrg return; 65837ec681f3Smrg 65847ec681f3Smrg if (!check_texture_buffer_range(ctx, bufObj, offset, size, 65857ec681f3Smrg "glTextureBufferRangeEXT")) 65867ec681f3Smrg return; 65877ec681f3Smrg 65887ec681f3Smrg } else { 65897ec681f3Smrg /* OpenGL 4.5 core spec (02.02.2015) says in Section 8.9 Buffer 65907ec681f3Smrg * Textures (PDF page 254): 65917ec681f3Smrg * "If buffer is zero, then any buffer object attached to the buffer 65927ec681f3Smrg * texture is detached, the values offset and size are ignored and 65937ec681f3Smrg * the state for offset and size for the buffer texture are reset to 65947ec681f3Smrg * zero." 65957ec681f3Smrg */ 65967ec681f3Smrg offset = 0; 65977ec681f3Smrg size = 0; 65987ec681f3Smrg bufObj = NULL; 65997ec681f3Smrg } 66007ec681f3Smrg 66017ec681f3Smrg texture_buffer_range(ctx, texObj, internalFormat, bufObj, 66027ec681f3Smrg offset, size, "glTextureBufferRangeEXT"); 66037ec681f3Smrg} 66047ec681f3Smrg 66057ec681f3Smrg 660601e04c3fSmrgvoid GLAPIENTRY 660701e04c3fSmrg_mesa_TextureBuffer(GLuint texture, GLenum internalFormat, GLuint buffer) 660801e04c3fSmrg{ 660901e04c3fSmrg struct gl_texture_object *texObj; 661001e04c3fSmrg struct gl_buffer_object *bufObj; 6611af69d88dSmrg 661201e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 661301e04c3fSmrg 661401e04c3fSmrg if (buffer) { 661501e04c3fSmrg bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glTextureBuffer"); 661601e04c3fSmrg if (!bufObj) 661701e04c3fSmrg return; 661801e04c3fSmrg } else 661901e04c3fSmrg bufObj = NULL; 662001e04c3fSmrg 662101e04c3fSmrg /* Get the texture object by Name. */ 662201e04c3fSmrg texObj = _mesa_lookup_texture_err(ctx, texture, "glTextureBuffer"); 662301e04c3fSmrg if (!texObj) 662401e04c3fSmrg return; 662501e04c3fSmrg 66267ec681f3Smrg if (!check_texture_buffer_target(ctx, texObj->Target, "glTextureBuffer", true)) 662701e04c3fSmrg return; 662801e04c3fSmrg 662901e04c3fSmrg texture_buffer_range(ctx, texObj, internalFormat, 663001e04c3fSmrg bufObj, 0, buffer ? -1 : 0, "glTextureBuffer"); 663101e04c3fSmrg} 663201e04c3fSmrg 66337ec681f3Smrgvoid GLAPIENTRY 66347ec681f3Smrg_mesa_TextureBufferEXT(GLuint texture, GLenum target, 66357ec681f3Smrg GLenum internalFormat, GLuint buffer) 66367ec681f3Smrg{ 66377ec681f3Smrg struct gl_texture_object *texObj; 66387ec681f3Smrg struct gl_buffer_object *bufObj; 66397ec681f3Smrg 66407ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 66417ec681f3Smrg 66427ec681f3Smrg if (buffer) { 66437ec681f3Smrg bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glTextureBuffer"); 66447ec681f3Smrg if (!bufObj) 66457ec681f3Smrg return; 66467ec681f3Smrg } else 66477ec681f3Smrg bufObj = NULL; 66487ec681f3Smrg 66497ec681f3Smrg /* Get the texture object by Name. */ 66507ec681f3Smrg texObj = _mesa_lookup_or_create_texture(ctx, target, texture, 66517ec681f3Smrg false, true, 66527ec681f3Smrg "glTextureBufferEXT"); 66537ec681f3Smrg 66547ec681f3Smrg if (!texObj || 66557ec681f3Smrg !check_texture_buffer_target(ctx, texObj->Target, "glTextureBufferEXT", true)) 66567ec681f3Smrg return; 66577ec681f3Smrg 66587ec681f3Smrg texture_buffer_range(ctx, texObj, internalFormat, 66597ec681f3Smrg bufObj, 0, buffer ? -1 : 0, "glTextureBufferEXT"); 66607ec681f3Smrg} 66617ec681f3Smrg 66627ec681f3Smrgvoid GLAPIENTRY 66637ec681f3Smrg_mesa_MultiTexBufferEXT(GLenum texunit, GLenum target, 66647ec681f3Smrg GLenum internalFormat, GLuint buffer) 66657ec681f3Smrg{ 66667ec681f3Smrg struct gl_texture_object *texObj; 66677ec681f3Smrg struct gl_buffer_object *bufObj; 66687ec681f3Smrg 66697ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 66707ec681f3Smrg 66717ec681f3Smrg if (buffer) { 66727ec681f3Smrg bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, "glMultiTexBufferEXT"); 66737ec681f3Smrg if (!bufObj) 66747ec681f3Smrg return; 66757ec681f3Smrg } else 66767ec681f3Smrg bufObj = NULL; 66777ec681f3Smrg 66787ec681f3Smrg /* Get the texture object */ 66797ec681f3Smrg texObj = _mesa_get_texobj_by_target_and_texunit(ctx, target, 66807ec681f3Smrg texunit - GL_TEXTURE0, 66817ec681f3Smrg true, 66827ec681f3Smrg "glMultiTexBufferEXT"); 66837ec681f3Smrg 66847ec681f3Smrg if (!texObj || 66857ec681f3Smrg !check_texture_buffer_target(ctx, texObj->Target, "glMultiTexBufferEXT", false)) 66867ec681f3Smrg return; 66877ec681f3Smrg 66887ec681f3Smrg texture_buffer_range(ctx, texObj, internalFormat, 66897ec681f3Smrg bufObj, 0, buffer ? -1 : 0, "glMultiTexBufferEXT"); 66907ec681f3Smrg} 66917ec681f3Smrg 669201e04c3fSmrgvoid GLAPIENTRY 669301e04c3fSmrg_mesa_TextureBufferRange(GLuint texture, GLenum internalFormat, GLuint buffer, 669401e04c3fSmrg GLintptr offset, GLsizeiptr size) 669501e04c3fSmrg{ 669601e04c3fSmrg struct gl_texture_object *texObj; 669701e04c3fSmrg struct gl_buffer_object *bufObj; 669801e04c3fSmrg 669901e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 670001e04c3fSmrg 670101e04c3fSmrg if (buffer) { 670201e04c3fSmrg bufObj = _mesa_lookup_bufferobj_err(ctx, buffer, 670301e04c3fSmrg "glTextureBufferRange"); 670401e04c3fSmrg if (!bufObj) 670501e04c3fSmrg return; 670601e04c3fSmrg 670701e04c3fSmrg if (!check_texture_buffer_range(ctx, bufObj, offset, size, 670801e04c3fSmrg "glTextureBufferRange")) 670901e04c3fSmrg return; 671001e04c3fSmrg 671101e04c3fSmrg } else { 671201e04c3fSmrg /* OpenGL 4.5 core spec (02.02.2015) says in Section 8.9 Buffer 671301e04c3fSmrg * Textures (PDF page 254): 671401e04c3fSmrg * "If buffer is zero, then any buffer object attached to the buffer 671501e04c3fSmrg * texture is detached, the values offset and size are ignored and 671601e04c3fSmrg * the state for offset and size for the buffer texture are reset to 671701e04c3fSmrg * zero." 671801e04c3fSmrg */ 671901e04c3fSmrg offset = 0; 672001e04c3fSmrg size = 0; 672101e04c3fSmrg bufObj = NULL; 672201e04c3fSmrg } 672301e04c3fSmrg 672401e04c3fSmrg /* Get the texture object by Name. */ 672501e04c3fSmrg texObj = _mesa_lookup_texture_err(ctx, texture, "glTextureBufferRange"); 672601e04c3fSmrg if (!texObj) 672701e04c3fSmrg return; 672801e04c3fSmrg 672901e04c3fSmrg if (!check_texture_buffer_target(ctx, texObj->Target, 67307ec681f3Smrg "glTextureBufferRange", true)) 673101e04c3fSmrg return; 673201e04c3fSmrg 673301e04c3fSmrg texture_buffer_range(ctx, texObj, internalFormat, 673401e04c3fSmrg bufObj, offset, size, "glTextureBufferRange"); 673501e04c3fSmrg} 673601e04c3fSmrg 673701e04c3fSmrgGLboolean 673801e04c3fSmrg_mesa_is_renderable_texture_format(const struct gl_context *ctx, 673901e04c3fSmrg GLenum internalformat) 6740af69d88dSmrg{ 6741af69d88dSmrg /* Everything that is allowed for renderbuffers, 674201e04c3fSmrg * except for a base format of GL_STENCIL_INDEX, unless supported. 6743af69d88dSmrg */ 6744af69d88dSmrg GLenum baseFormat = _mesa_base_fbo_format(ctx, internalformat); 674501e04c3fSmrg if (ctx->Extensions.ARB_texture_stencil8) 674601e04c3fSmrg return baseFormat != 0; 674701e04c3fSmrg else 674801e04c3fSmrg return baseFormat != 0 && baseFormat != GL_STENCIL_INDEX; 6749af69d88dSmrg} 6750af69d88dSmrg 6751af69d88dSmrg 6752af69d88dSmrg/** GL_ARB_texture_multisample */ 6753af69d88dSmrgstatic GLboolean 675401e04c3fSmrgcheck_multisample_target(GLuint dims, GLenum target, bool dsa) 6755af69d88dSmrg{ 6756af69d88dSmrg switch(target) { 6757af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE: 6758af69d88dSmrg return dims == 2; 675901e04c3fSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE: 676001e04c3fSmrg return dims == 2 && !dsa; 6761af69d88dSmrg case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 6762af69d88dSmrg return dims == 3; 676301e04c3fSmrg case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY: 676401e04c3fSmrg return dims == 3 && !dsa; 6765af69d88dSmrg default: 6766af69d88dSmrg return GL_FALSE; 6767af69d88dSmrg } 6768af69d88dSmrg} 6769af69d88dSmrg 6770af69d88dSmrg 6771af69d88dSmrgstatic void 677201e04c3fSmrgtexture_image_multisample(struct gl_context *ctx, GLuint dims, 677301e04c3fSmrg struct gl_texture_object *texObj, 677401e04c3fSmrg struct gl_memory_object *memObj, 677501e04c3fSmrg GLenum target, GLsizei samples, 677601e04c3fSmrg GLint internalformat, GLsizei width, 677701e04c3fSmrg GLsizei height, GLsizei depth, 677801e04c3fSmrg GLboolean fixedsamplelocations, 677901e04c3fSmrg GLboolean immutable, GLuint64 offset, 678001e04c3fSmrg const char *func) 6781af69d88dSmrg{ 6782af69d88dSmrg struct gl_texture_image *texImage; 6783af69d88dSmrg GLboolean sizeOK, dimensionsOK, samplesOK; 6784af69d88dSmrg mesa_format texFormat; 6785af69d88dSmrg GLenum sample_count_error; 678601e04c3fSmrg bool dsa = strstr(func, "ture") ? true : false; 6787af69d88dSmrg 678801e04c3fSmrg if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) { 67897ec681f3Smrg _mesa_debug(ctx, "%s(target=%s, samples=%d, internalformat=%s)\n", func, 67907ec681f3Smrg _mesa_enum_to_string(target), samples, _mesa_enum_to_string(internalformat)); 679101e04c3fSmrg } 6792af69d88dSmrg 679301e04c3fSmrg if (!((ctx->Extensions.ARB_texture_multisample 679401e04c3fSmrg && _mesa_is_desktop_gl(ctx))) && !_mesa_is_gles31(ctx)) { 6795af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(unsupported)", func); 6796af69d88dSmrg return; 6797af69d88dSmrg } 6798af69d88dSmrg 679901e04c3fSmrg if (samples < 1) { 680001e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, "%s(samples < 1)", func); 680101e04c3fSmrg return; 680201e04c3fSmrg } 680301e04c3fSmrg 680401e04c3fSmrg if (!check_multisample_target(dims, target, dsa)) { 680501e04c3fSmrg GLenum err = dsa ? GL_INVALID_OPERATION : GL_INVALID_ENUM; 680601e04c3fSmrg _mesa_error(ctx, err, "%s(target=%s)", func, 680701e04c3fSmrg _mesa_enum_to_string(target)); 6808af69d88dSmrg return; 6809af69d88dSmrg } 6810af69d88dSmrg 6811af69d88dSmrg /* check that the specified internalformat is color/depth/stencil-renderable; 6812af69d88dSmrg * refer GL3.1 spec 4.4.4 6813af69d88dSmrg */ 6814af69d88dSmrg 6815af69d88dSmrg if (immutable && !_mesa_is_legal_tex_storage_format(ctx, internalformat)) { 6816af69d88dSmrg _mesa_error(ctx, GL_INVALID_ENUM, 6817af69d88dSmrg "%s(internalformat=%s not legal for immutable-format)", 681801e04c3fSmrg func, _mesa_enum_to_string(internalformat)); 6819af69d88dSmrg return; 6820af69d88dSmrg } 6821af69d88dSmrg 682201e04c3fSmrg if (!_mesa_is_renderable_texture_format(ctx, internalformat)) { 682301e04c3fSmrg /* Page 172 of OpenGL ES 3.1 spec says: 682401e04c3fSmrg * "An INVALID_ENUM error is generated if sizedinternalformat is not 682501e04c3fSmrg * color-renderable, depth-renderable, or stencil-renderable (as 682601e04c3fSmrg * defined in section 9.4). 682701e04c3fSmrg * 682801e04c3fSmrg * (Same error is also defined for desktop OpenGL for multisample 682901e04c3fSmrg * teximage/texstorage functions.) 683001e04c3fSmrg */ 683101e04c3fSmrg _mesa_error(ctx, GL_INVALID_ENUM, "%s(internalformat=%s)", func, 683201e04c3fSmrg _mesa_enum_to_string(internalformat)); 6833af69d88dSmrg return; 6834af69d88dSmrg } 6835af69d88dSmrg 6836af69d88dSmrg sample_count_error = _mesa_check_sample_count(ctx, target, 683701e04c3fSmrg internalformat, samples, samples); 6838af69d88dSmrg samplesOK = sample_count_error == GL_NO_ERROR; 6839af69d88dSmrg 6840af69d88dSmrg /* Page 254 of OpenGL 4.4 spec says: 6841af69d88dSmrg * "Proxy arrays for two-dimensional multisample and two-dimensional 6842af69d88dSmrg * multisample array textures are operated on in the same way when 6843af69d88dSmrg * TexImage2DMultisample is called with target specified as 6844af69d88dSmrg * PROXY_TEXTURE_2D_MULTISAMPLE, or TexImage3DMultisample is called 6845af69d88dSmrg * with target specified as PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY. 6846af69d88dSmrg * However, if samples is not supported, then no error is generated. 6847af69d88dSmrg */ 6848af69d88dSmrg if (!samplesOK && !_mesa_is_proxy_texture(target)) { 684901e04c3fSmrg _mesa_error(ctx, sample_count_error, "%s(samples=%d)", func, samples); 68503464ebd5Sriastradh return; 68513464ebd5Sriastradh } 68523464ebd5Sriastradh 6853af69d88dSmrg if (immutable && (!texObj || (texObj->Name == 0))) { 6854af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, 6855af69d88dSmrg "%s(texture object 0)", 6856af69d88dSmrg func); 6857af69d88dSmrg return; 68583464ebd5Sriastradh } 6859af69d88dSmrg 6860af69d88dSmrg texImage = _mesa_get_tex_image(ctx, texObj, 0, 0); 6861af69d88dSmrg 6862af69d88dSmrg if (texImage == NULL) { 6863af69d88dSmrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s()", func); 6864af69d88dSmrg return; 6865af69d88dSmrg } 6866af69d88dSmrg 6867af69d88dSmrg texFormat = _mesa_choose_texture_format(ctx, texObj, target, 0, 6868af69d88dSmrg internalformat, GL_NONE, GL_NONE); 6869af69d88dSmrg assert(texFormat != MESA_FORMAT_NONE); 6870af69d88dSmrg 6871af69d88dSmrg dimensionsOK = _mesa_legal_texture_dimensions(ctx, target, 0, 6872af69d88dSmrg width, height, depth, 0); 6873af69d88dSmrg 687401e04c3fSmrg sizeOK = ctx->Driver.TestProxyTexImage(ctx, target, 0, 0, texFormat, 687501e04c3fSmrg samples, width, height, depth); 6876af69d88dSmrg 6877af69d88dSmrg if (_mesa_is_proxy_texture(target)) { 6878af69d88dSmrg if (samplesOK && dimensionsOK && sizeOK) { 687901e04c3fSmrg _mesa_init_teximage_fields_ms(ctx, texImage, width, height, depth, 0, 688001e04c3fSmrg internalformat, texFormat, 688101e04c3fSmrg samples, fixedsamplelocations); 6882af69d88dSmrg } 6883af69d88dSmrg else { 6884af69d88dSmrg /* clear all image fields */ 6885af69d88dSmrg clear_teximage_fields(texImage); 6886af69d88dSmrg } 6887af69d88dSmrg } 6888af69d88dSmrg else { 6889af69d88dSmrg if (!dimensionsOK) { 6890af69d88dSmrg _mesa_error(ctx, GL_INVALID_VALUE, 689101e04c3fSmrg "%s(invalid width=%d or height=%d)", func, width, height); 6892af69d88dSmrg return; 6893af69d88dSmrg } 6894af69d88dSmrg 6895af69d88dSmrg if (!sizeOK) { 689601e04c3fSmrg _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s(texture too large)", func); 6897af69d88dSmrg return; 6898af69d88dSmrg } 6899af69d88dSmrg 6900af69d88dSmrg /* Check if texObj->Immutable is set */ 6901af69d88dSmrg if (texObj->Immutable) { 6902af69d88dSmrg _mesa_error(ctx, GL_INVALID_OPERATION, "%s(immutable)", func); 6903af69d88dSmrg return; 6904af69d88dSmrg } 6905af69d88dSmrg 6906af69d88dSmrg ctx->Driver.FreeTextureImageBuffer(ctx, texImage); 6907af69d88dSmrg 690801e04c3fSmrg _mesa_init_teximage_fields_ms(ctx, texImage, width, height, depth, 0, 690901e04c3fSmrg internalformat, texFormat, 691001e04c3fSmrg samples, fixedsamplelocations); 6911af69d88dSmrg 6912af69d88dSmrg if (width > 0 && height > 0 && depth > 0) { 691301e04c3fSmrg if (memObj) { 691401e04c3fSmrg if (!ctx->Driver.SetTextureStorageForMemoryObject(ctx, texObj, 691501e04c3fSmrg memObj, 1, width, 691601e04c3fSmrg height, depth, 691701e04c3fSmrg offset)) { 691801e04c3fSmrg 691901e04c3fSmrg _mesa_init_teximage_fields(ctx, texImage, 0, 0, 0, 0, 692001e04c3fSmrg internalformat, texFormat); 692101e04c3fSmrg } 692201e04c3fSmrg } else { 692301e04c3fSmrg if (!ctx->Driver.AllocTextureStorage(ctx, texObj, 1, 692401e04c3fSmrg width, height, depth)) { 692501e04c3fSmrg /* tidy up the texture image state. strictly speaking, 692601e04c3fSmrg * we're allowed to just leave this in whatever state we 692701e04c3fSmrg * like, but being tidy is good. 692801e04c3fSmrg */ 692901e04c3fSmrg _mesa_init_teximage_fields(ctx, texImage, 0, 0, 0, 0, 693001e04c3fSmrg internalformat, texFormat); 693101e04c3fSmrg } 6932af69d88dSmrg } 6933af69d88dSmrg } 6934af69d88dSmrg 69357ec681f3Smrg texObj->External = GL_FALSE; 693601e04c3fSmrg texObj->Immutable |= immutable; 6937af69d88dSmrg 6938af69d88dSmrg if (immutable) { 6939af69d88dSmrg _mesa_set_texture_view_state(ctx, texObj, target, 1); 6940af69d88dSmrg } 6941af69d88dSmrg 6942af69d88dSmrg _mesa_update_fbo_texture(ctx, texObj, 0, 0); 6943af69d88dSmrg } 6944af69d88dSmrg} 6945af69d88dSmrg 6946af69d88dSmrg 6947af69d88dSmrgvoid GLAPIENTRY 6948af69d88dSmrg_mesa_TexImage2DMultisample(GLenum target, GLsizei samples, 6949af69d88dSmrg GLenum internalformat, GLsizei width, 6950af69d88dSmrg GLsizei height, GLboolean fixedsamplelocations) 6951af69d88dSmrg{ 695201e04c3fSmrg struct gl_texture_object *texObj; 695301e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 695401e04c3fSmrg 695501e04c3fSmrg texObj = _mesa_get_current_tex_object(ctx, target); 695601e04c3fSmrg if (!texObj) 695701e04c3fSmrg return; 695801e04c3fSmrg 695901e04c3fSmrg texture_image_multisample(ctx, 2, texObj, NULL, target, samples, 696001e04c3fSmrg internalformat, width, height, 1, 696101e04c3fSmrg fixedsamplelocations, GL_FALSE, 0, 696201e04c3fSmrg "glTexImage2DMultisample"); 6963af69d88dSmrg} 6964af69d88dSmrg 6965af69d88dSmrg 6966af69d88dSmrgvoid GLAPIENTRY 6967af69d88dSmrg_mesa_TexImage3DMultisample(GLenum target, GLsizei samples, 6968af69d88dSmrg GLenum internalformat, GLsizei width, 6969af69d88dSmrg GLsizei height, GLsizei depth, 6970af69d88dSmrg GLboolean fixedsamplelocations) 6971af69d88dSmrg{ 697201e04c3fSmrg struct gl_texture_object *texObj; 697301e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 697401e04c3fSmrg 697501e04c3fSmrg texObj = _mesa_get_current_tex_object(ctx, target); 697601e04c3fSmrg if (!texObj) 697701e04c3fSmrg return; 697801e04c3fSmrg 697901e04c3fSmrg texture_image_multisample(ctx, 3, texObj, NULL, target, samples, 698001e04c3fSmrg internalformat, width, height, depth, 698101e04c3fSmrg fixedsamplelocations, GL_FALSE, 0, 698201e04c3fSmrg "glTexImage3DMultisample"); 6983af69d88dSmrg} 6984af69d88dSmrg 698501e04c3fSmrgstatic bool 698601e04c3fSmrgvalid_texstorage_ms_parameters(GLsizei width, GLsizei height, GLsizei depth, 698701e04c3fSmrg unsigned dims) 698801e04c3fSmrg{ 698901e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 699001e04c3fSmrg 699101e04c3fSmrg if (!_mesa_valid_tex_storage_dim(width, height, depth)) { 699201e04c3fSmrg _mesa_error(ctx, GL_INVALID_VALUE, 699301e04c3fSmrg "glTexStorage%uDMultisample(width=%d,height=%d,depth=%d)", 699401e04c3fSmrg dims, width, height, depth); 699501e04c3fSmrg return false; 699601e04c3fSmrg } 699701e04c3fSmrg return true; 699801e04c3fSmrg} 6999af69d88dSmrg 7000af69d88dSmrgvoid GLAPIENTRY 7001af69d88dSmrg_mesa_TexStorage2DMultisample(GLenum target, GLsizei samples, 7002af69d88dSmrg GLenum internalformat, GLsizei width, 7003af69d88dSmrg GLsizei height, GLboolean fixedsamplelocations) 7004af69d88dSmrg{ 700501e04c3fSmrg struct gl_texture_object *texObj; 700601e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 700701e04c3fSmrg 700801e04c3fSmrg texObj = _mesa_get_current_tex_object(ctx, target); 700901e04c3fSmrg if (!texObj) 701001e04c3fSmrg return; 701101e04c3fSmrg 701201e04c3fSmrg if (!valid_texstorage_ms_parameters(width, height, 1, 2)) 701301e04c3fSmrg return; 701401e04c3fSmrg 701501e04c3fSmrg texture_image_multisample(ctx, 2, texObj, NULL, target, samples, 701601e04c3fSmrg internalformat, width, height, 1, 701701e04c3fSmrg fixedsamplelocations, GL_TRUE, 0, 701801e04c3fSmrg "glTexStorage2DMultisample"); 7019af69d88dSmrg} 7020af69d88dSmrg 7021af69d88dSmrgvoid GLAPIENTRY 7022af69d88dSmrg_mesa_TexStorage3DMultisample(GLenum target, GLsizei samples, 7023af69d88dSmrg GLenum internalformat, GLsizei width, 7024af69d88dSmrg GLsizei height, GLsizei depth, 7025af69d88dSmrg GLboolean fixedsamplelocations) 7026af69d88dSmrg{ 702701e04c3fSmrg struct gl_texture_object *texObj; 702801e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 702901e04c3fSmrg 703001e04c3fSmrg texObj = _mesa_get_current_tex_object(ctx, target); 703101e04c3fSmrg if (!texObj) 703201e04c3fSmrg return; 703301e04c3fSmrg 703401e04c3fSmrg if (!valid_texstorage_ms_parameters(width, height, depth, 3)) 703501e04c3fSmrg return; 703601e04c3fSmrg 703701e04c3fSmrg texture_image_multisample(ctx, 3, texObj, NULL, target, samples, 703801e04c3fSmrg internalformat, width, height, depth, 703901e04c3fSmrg fixedsamplelocations, GL_TRUE, 0, 704001e04c3fSmrg "glTexStorage3DMultisample"); 704101e04c3fSmrg} 704201e04c3fSmrg 704301e04c3fSmrgvoid GLAPIENTRY 704401e04c3fSmrg_mesa_TextureStorage2DMultisample(GLuint texture, GLsizei samples, 704501e04c3fSmrg GLenum internalformat, GLsizei width, 704601e04c3fSmrg GLsizei height, 704701e04c3fSmrg GLboolean fixedsamplelocations) 704801e04c3fSmrg{ 704901e04c3fSmrg struct gl_texture_object *texObj; 705001e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 705101e04c3fSmrg 705201e04c3fSmrg texObj = _mesa_lookup_texture_err(ctx, texture, 705301e04c3fSmrg "glTextureStorage2DMultisample"); 705401e04c3fSmrg if (!texObj) 705501e04c3fSmrg return; 705601e04c3fSmrg 705701e04c3fSmrg if (!valid_texstorage_ms_parameters(width, height, 1, 2)) 705801e04c3fSmrg return; 705901e04c3fSmrg 706001e04c3fSmrg texture_image_multisample(ctx, 2, texObj, NULL, texObj->Target, 706101e04c3fSmrg samples, internalformat, width, height, 1, 706201e04c3fSmrg fixedsamplelocations, GL_TRUE, 0, 706301e04c3fSmrg "glTextureStorage2DMultisample"); 706401e04c3fSmrg} 706501e04c3fSmrg 706601e04c3fSmrgvoid GLAPIENTRY 706701e04c3fSmrg_mesa_TextureStorage3DMultisample(GLuint texture, GLsizei samples, 706801e04c3fSmrg GLenum internalformat, GLsizei width, 706901e04c3fSmrg GLsizei height, GLsizei depth, 707001e04c3fSmrg GLboolean fixedsamplelocations) 707101e04c3fSmrg{ 707201e04c3fSmrg struct gl_texture_object *texObj; 707301e04c3fSmrg GET_CURRENT_CONTEXT(ctx); 707401e04c3fSmrg 707501e04c3fSmrg /* Get the texture object by Name. */ 707601e04c3fSmrg texObj = _mesa_lookup_texture_err(ctx, texture, 707701e04c3fSmrg "glTextureStorage3DMultisample"); 707801e04c3fSmrg if (!texObj) 707901e04c3fSmrg return; 708001e04c3fSmrg 708101e04c3fSmrg if (!valid_texstorage_ms_parameters(width, height, depth, 3)) 708201e04c3fSmrg return; 708301e04c3fSmrg 708401e04c3fSmrg texture_image_multisample(ctx, 3, texObj, NULL, texObj->Target, samples, 708501e04c3fSmrg internalformat, width, height, depth, 708601e04c3fSmrg fixedsamplelocations, GL_TRUE, 0, 708701e04c3fSmrg "glTextureStorage3DMultisample"); 708801e04c3fSmrg} 708901e04c3fSmrg 70907ec681f3Smrgvoid GLAPIENTRY 70917ec681f3Smrg_mesa_TextureStorage2DMultisampleEXT(GLuint texture, GLenum target, GLsizei samples, 70927ec681f3Smrg GLenum internalformat, GLsizei width, 70937ec681f3Smrg GLsizei height, 70947ec681f3Smrg GLboolean fixedsamplelocations) 70957ec681f3Smrg{ 70967ec681f3Smrg struct gl_texture_object *texObj; 70977ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 70987ec681f3Smrg 70997ec681f3Smrg texObj = lookup_texture_ext_dsa(ctx, target, texture, 71007ec681f3Smrg "glTextureStorage2DMultisampleEXT"); 71017ec681f3Smrg if (!texObj) 71027ec681f3Smrg return; 71037ec681f3Smrg 71047ec681f3Smrg if (!valid_texstorage_ms_parameters(width, height, 1, 2)) 71057ec681f3Smrg return; 71067ec681f3Smrg 71077ec681f3Smrg texture_image_multisample(ctx, 2, texObj, NULL, texObj->Target, 71087ec681f3Smrg samples, internalformat, width, height, 1, 71097ec681f3Smrg fixedsamplelocations, GL_TRUE, 0, 71107ec681f3Smrg "glTextureStorage2DMultisampleEXT"); 71117ec681f3Smrg} 71127ec681f3Smrg 71137ec681f3Smrgvoid GLAPIENTRY 71147ec681f3Smrg_mesa_TextureStorage3DMultisampleEXT(GLuint texture, GLenum target, GLsizei samples, 71157ec681f3Smrg GLenum internalformat, GLsizei width, 71167ec681f3Smrg GLsizei height, GLsizei depth, 71177ec681f3Smrg GLboolean fixedsamplelocations) 71187ec681f3Smrg{ 71197ec681f3Smrg struct gl_texture_object *texObj; 71207ec681f3Smrg GET_CURRENT_CONTEXT(ctx); 71217ec681f3Smrg 71227ec681f3Smrg texObj = lookup_texture_ext_dsa(ctx, target, texture, 71237ec681f3Smrg "glTextureStorage3DMultisampleEXT"); 71247ec681f3Smrg if (!texObj) 71257ec681f3Smrg return; 71267ec681f3Smrg 71277ec681f3Smrg if (!valid_texstorage_ms_parameters(width, height, depth, 3)) 71287ec681f3Smrg return; 71297ec681f3Smrg 71307ec681f3Smrg texture_image_multisample(ctx, 3, texObj, NULL, texObj->Target, samples, 71317ec681f3Smrg internalformat, width, height, depth, 71327ec681f3Smrg fixedsamplelocations, GL_TRUE, 0, 71337ec681f3Smrg "glTextureStorage3DMultisampleEXT"); 71347ec681f3Smrg} 71357ec681f3Smrg 713601e04c3fSmrgvoid 713701e04c3fSmrg_mesa_texture_storage_ms_memory(struct gl_context *ctx, GLuint dims, 713801e04c3fSmrg struct gl_texture_object *texObj, 713901e04c3fSmrg struct gl_memory_object *memObj, 714001e04c3fSmrg GLenum target, GLsizei samples, 714101e04c3fSmrg GLenum internalFormat, GLsizei width, 714201e04c3fSmrg GLsizei height, GLsizei depth, 714301e04c3fSmrg GLboolean fixedSampleLocations, 714401e04c3fSmrg GLuint64 offset, const char* func) 714501e04c3fSmrg{ 714601e04c3fSmrg assert(memObj); 714701e04c3fSmrg 714801e04c3fSmrg texture_image_multisample(ctx, dims, texObj, memObj, target, samples, 714901e04c3fSmrg internalFormat, width, height, depth, 715001e04c3fSmrg fixedSampleLocations, GL_TRUE, offset, 715101e04c3fSmrg func); 71523464ebd5Sriastradh} 7153