teximage.c revision 4406f79402e8f986913c20c3138d12d0af670bd4
1242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com/* 2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * mesa 3-D graphics library 3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Version: 7.6 4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * 5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright (C) 2009 VMware, Inc. All Rights Reserved. 7242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * 8242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * Permission is hereby granted, free of charge, to any person obtaining a 985302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com * copy of this software and associated documentation files (the "Software"), 1085302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com * to deal in the Software without restriction, including without limitation 111ee76510f5dbf632d30975fc3509ef4f609156d2mtklein * the rights to use, copy, modify, merge, publish, distribute, sublicense, 121ee76510f5dbf632d30975fc3509ef4f609156d2mtklein * and/or sell copies of the Software, and to permit persons to whom the 1385302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com * Software is furnished to do so, subject to the following conditions: 1485302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com * 1585302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com * The above copyright notice and this permission notice shall be included 1685302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com * in all copies or substantial portions of the Software. 1785302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com * 1885302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 1985302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2085302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 2185302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 2285302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 2385302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2485302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com */ 2585302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com 2685302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com 2785302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com/** 2885302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com * \file teximage.c 2985302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com * Texture image-related functions. 3085302969fcf0860d451b0748da372571b2fc9f88bungeman@google.com */ 31ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com 32242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com 339df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com#include "glheader.h" 34242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#include "bufferobj.h" 35242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#include "context.h" 369df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com#if FEATURE_convolve 37242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#include "convolve.h" 38242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#endif 399df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com#include "fbobject.h" 4059bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com#include "framebuffer.h" 41242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#include "hash.h" 42c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com#include "image.h" 43c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com#include "imports.h" 44c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com#include "macros.h" 45c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com#include "state.h" 46c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com#include "texcompress.h" 47c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com#include "texformat.h" 48c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com#include "teximage.h" 49c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com#include "texstate.h" 50c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com#include "texstore.h" 51242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#include "mtypes.h" 5239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com 5339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com 5439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com/** 5539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com * State changes which we care about for glCopyTex[Sub]Image() calls. 5639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com * In particular, we care about pixel transfer state and buffer state 5739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com * (such as glReadBuffer to make sure we read from the right renderbuffer). 5839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com */ 5939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com#define NEW_COPY_TEX_STATE (_MESA_NEW_TRANSFER_STATE | \ 6039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com _NEW_BUFFERS | \ 6139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com _NEW_PIXEL) 6239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com 6339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com 6439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com 6596fcdcc219d2a0d3579719b84b28bede76efba64halcanary/** 6639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com * We allocate texture memory on 512-byte boundaries so we can use MMX/SSE 6739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com * elsewhere. 6839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com */ 6939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.comvoid * 7039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com_mesa_alloc_texmemory(GLsizei bytes) 71242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com{ 7236352bf5e38f45a70ee4f4fc132a38048d38206dmtklein return _mesa_align_malloc(bytes, 512); 7339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com} 7439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com 7539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com 7639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com/** 7739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com * Free texture memory allocated with _mesa_alloc_texmemory() 78242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com */ 79242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.comvoid 8039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com_mesa_free_texmemory(void *m) 8139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com{ 8239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com _mesa_align_free(m); 8339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com} 8439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com 8539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com 8639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com 8739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com 8839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com#if 0 8939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.comstatic void PrintTexture(GLcontext *ctx, const struct gl_texture_image *img) 9039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com{ 9139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com#if CHAN_TYPE != GL_UNSIGNED_BYTE 9239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com _mesa_problem(NULL, "PrintTexture not supported"); 9339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com#else 9439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com GLuint i, j, c; 9539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com const GLubyte *data = (const GLubyte *) img->Data; 9639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com 972a1208017dd676f94a53bbb228197c3978dbdd8ascroggo if (!data) { 9839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com _mesa_printf("No texture data\n"); 9939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com return; 10039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com } 10139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com 10239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com switch (img->Format) { 10339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case GL_ALPHA: 10439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case GL_LUMINANCE: 10539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case GL_INTENSITY: 10639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case GL_COLOR_INDEX: 10796fcdcc219d2a0d3579719b84b28bede76efba64halcanary c = 1; 10839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com break; 10939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case GL_LUMINANCE_ALPHA: 11039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com c = 2; 11139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com break; 112242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGB: 1132e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com c = 3; 1142e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com break; 1152e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com case GL_RGBA: 1162e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com c = 4; 117d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com break; 1182e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com default: 119d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com _mesa_problem(NULL, "error in PrintTexture\n"); 120242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return; 1219df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com } 122242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com 123242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com for (i = 0; i < img->Height; i++) { 124242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com for (j = 0; j < img->Width; j++) { 12596fcdcc219d2a0d3579719b84b28bede76efba64halcanary if (c==1) 126242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com _mesa_printf("%02x ", data[0]); 127242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com else if (c==2) 128242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com _mesa_printf("%02x%02x ", data[0], data[1]); 129242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com else if (c==3) 130d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com _mesa_printf("%02x%02x%02x ", data[0], data[1], data[2]); 131242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com else if (c==4) 1329df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com _mesa_printf("%02x%02x%02x%02x ", data[0], data[1], data[2], data[3]); 133242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com data += (img->RowStride - img->Width) * c; 1349df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com } 135242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com /* XXX use img->ImageStride here */ 136d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com _mesa_printf("\n"); 137242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com } 138242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#endif 139242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com} 14096fcdcc219d2a0d3579719b84b28bede76efba64halcanary#endif 141242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com 142d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 143242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com/* 1449df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com * Compute floor(log_base_2(n)). 145242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * If n < 0 return -1. 146242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com */ 147242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.comstatic int 14896fcdcc219d2a0d3579719b84b28bede76efba64halcanarylogbase2( int n ) 149242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com{ 150242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com GLint i = 1; 151242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com GLint log2 = 0; 152242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com 153d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com if (n < 0) 15439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com return -1; 15596fcdcc219d2a0d3579719b84b28bede76efba64halcanary 15639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com if (n == 0) 15739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com return 0; 15839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com 15939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com while ( n > i ) { 16039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com i *= 2; 16139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com log2++; 16239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com } 16339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com if (i != n) { 16439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com return log2 - 1; 16539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com } 16639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com else { 16739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com return log2; 168242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com } 1699df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com} 170242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com 171242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com 172242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com 173d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com/** 174242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * Return the simple base format for a given internal texture format. 1759df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com * For example, given GL_LUMINANCE12_ALPHA4, return GL_LUMINANCE_ALPHA. 176242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * 177242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * \param ctx GL context. 178242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * \param internalFormat the internal texture format token or 1, 2, 3, or 4. 179242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * 180242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * \return the corresponding \u base internal format (GL_ALPHA, GL_LUMINANCE, 181d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA), or -1 if invalid enum. 182242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * 183242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * This is the format which is used during texture application (i.e. the 184242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * texture format and env mode determine the arithmetic used. 185242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com */ 186242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.comGLint 187242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com_mesa_base_tex_format( GLcontext *ctx, GLint internalFormat ) 188d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com{ 189242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com switch (internalFormat) { 190242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_ALPHA: 191a3264e53ee3f3c5d6a2c813df7e44b5b96d207f2commit-bot@chromium.org case GL_ALPHA4: 19239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case GL_ALPHA8: 193242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_ALPHA12: 194242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_ALPHA16: 19596fcdcc219d2a0d3579719b84b28bede76efba64halcanary return GL_ALPHA; 196242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case 1: 197242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_LUMINANCE: 198242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_LUMINANCE4: 199d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com case GL_LUMINANCE8: 200242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_LUMINANCE12: 2019df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com case GL_LUMINANCE16: 202242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_LUMINANCE; 203242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case 2: 204242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_LUMINANCE_ALPHA: 205d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com case GL_LUMINANCE4_ALPHA4: 2062bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com case GL_LUMINANCE6_ALPHA2: 2072bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com case GL_LUMINANCE8_ALPHA8: 2082bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com case GL_LUMINANCE12_ALPHA4: 2092bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com case GL_LUMINANCE12_ALPHA12: 2102bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com case GL_LUMINANCE16_ALPHA16: 2112bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com return GL_LUMINANCE_ALPHA; 2122bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com case GL_INTENSITY: 213242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_INTENSITY4: 214242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_INTENSITY8: 215242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_INTENSITY12: 2162bbc2c945bb0ecf18fd6473af74ad1a2f5e727a7scroggo@google.com case GL_INTENSITY16: 217242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_INTENSITY; 21896fcdcc219d2a0d3579719b84b28bede76efba64halcanary case 3: 219242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGB: 220242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_R3_G3_B2: 221242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGB4: 222242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGB5: 223d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com case GL_RGB8: 224242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGB10: 2259df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com case GL_RGB12: 226242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGB16: 227242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_RGB; 228242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case 4: 229242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGBA: 230242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGBA2: 231d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com case GL_RGBA4: 232242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGB5_A1: 233242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGBA8: 234955bb0751a0d48e47a341c7c0adda94977bc8170bungeman@google.com case GL_RGB10_A2: 235dbfac8a72393eaf01670aeb3244de0e18d8faf98junov@google.com case GL_RGBA12: 2368b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com case GL_RGBA16: 237242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_RGBA; 23896fcdcc219d2a0d3579719b84b28bede76efba64halcanary default: 239242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com ; /* fallthrough */ 240242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com } 241242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com 242242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com if (ctx->Extensions.EXT_paletted_texture) { 24359bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com switch (internalFormat) { 24459bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com case GL_COLOR_INDEX: 245e7e29b7815e97e9c4db55fa9dac48b419352b2c6reed@google.com case GL_COLOR_INDEX1_EXT: 246383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com case GL_COLOR_INDEX2_EXT: 247383a697692cf46951fd451f6f4c3d03634a6a1cbreed@google.com case GL_COLOR_INDEX4_EXT: 248242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COLOR_INDEX8_EXT: 249d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com case GL_COLOR_INDEX12_EXT: 250242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COLOR_INDEX16_EXT: 251242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_COLOR_INDEX; 252242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com default: 253242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com ; /* fallthrough */ 254242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com } 255b5571b3324cf18629a255ec85e189447069c9b14scroggo@google.com } 2564c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com 257b5571b3324cf18629a255ec85e189447069c9b14scroggo@google.com if (ctx->Extensions.ARB_depth_texture) { 2584c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com switch (internalFormat) { 25996fcdcc219d2a0d3579719b84b28bede76efba64halcanary case GL_DEPTH_COMPONENT: 2604c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com case GL_DEPTH_COMPONENT16: 261385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary case GL_DEPTH_COMPONENT24: 2624c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com case GL_DEPTH_COMPONENT32: 2634c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com return GL_DEPTH_COMPONENT; 2644c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com default: 265242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com ; /* fallthrough */ 266242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com } 267242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com } 268242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com 269b5571b3324cf18629a255ec85e189447069c9b14scroggo@google.com switch (internalFormat) { 27096fcdcc219d2a0d3579719b84b28bede76efba64halcanary case GL_COMPRESSED_ALPHA: 271242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_ALPHA; 272242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COMPRESSED_LUMINANCE: 273242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_LUMINANCE; 274242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COMPRESSED_LUMINANCE_ALPHA: 275242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_LUMINANCE_ALPHA; 276242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COMPRESSED_INTENSITY: 277242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_INTENSITY; 278242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COMPRESSED_RGB: 279242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_RGB; 280242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COMPRESSED_RGBA: 281242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_RGBA; 282242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com default: 283242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com ; /* fallthrough */ 284242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com } 285242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com 286242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com if (ctx->Extensions.TDFX_texture_compression_FXT1) { 28722b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com switch (internalFormat) { 288242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COMPRESSED_RGB_FXT1_3DFX: 289242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_RGB; 290242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COMPRESSED_RGBA_FXT1_3DFX: 291242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_RGBA; 2924c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com default: 2934c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com ; /* fallthrough */ 2944c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com } 2954c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com } 2964c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com 2974c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com if (ctx->Extensions.EXT_texture_compression_s3tc) { 298242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com switch (internalFormat) { 299242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: 300242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_RGB; 301242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: 302242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: 303242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: 304242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_RGBA; 305242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com default: 306242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com ; /* fallthrough */ 307242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com } 30822b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com } 30922b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com 31022b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com if (ctx->Extensions.S3_s3tc) { 31128fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org switch (internalFormat) { 31222b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com case GL_RGB_S3TC: 31322b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com case GL_RGB4_S3TC: 31428fcae2ec77eb16a79e155f8d788b20457f1c951commit-bot@chromium.org return GL_RGB; 31522b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com case GL_RGBA_S3TC: 31622b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com case GL_RGBA4_S3TC: 31722b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com return GL_RGBA; 31822b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com default: 31922b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com ; /* fallthrough */ 32059bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com } 32159bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com } 32259bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com 32359bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com if (ctx->Extensions.MESA_ycbcr_texture) { 32459bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com if (internalFormat == GL_YCBCR_MESA) 32559bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com return GL_YCBCR_MESA; 32659bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com } 32759bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com 32859bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com if (ctx->Extensions.ARB_texture_float) { 32959bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com switch (internalFormat) { 33059bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com case GL_ALPHA16F_ARB: 33159bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com case GL_ALPHA32F_ARB: 33259bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com return GL_ALPHA; 33359bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com case GL_RGBA16F_ARB: 33459bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com case GL_RGBA32F_ARB: 33559bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com return GL_RGBA; 33659bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com case GL_RGB16F_ARB: 337242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGB32F_ARB: 3382e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com return GL_RGB; 3392e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com case GL_INTENSITY16F_ARB: 3402e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com case GL_INTENSITY32F_ARB: 3412e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com return GL_INTENSITY; 342d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com case GL_LUMINANCE16F_ARB: 3432e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com case GL_LUMINANCE32F_ARB: 344d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com return GL_LUMINANCE; 345242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_LUMINANCE_ALPHA16F_ARB: 3469df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com case GL_LUMINANCE_ALPHA32F_ARB: 347242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_LUMINANCE_ALPHA; 348242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com default: 349242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com ; /* fallthrough */ 35096fcdcc219d2a0d3579719b84b28bede76efba64halcanary } 351242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com } 352242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com 353242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com if (ctx->Extensions.ATI_envmap_bumpmap) { 354242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com switch (internalFormat) { 355d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com case GL_DUDV_ATI: 3569df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com case GL_DU8DV8_ATI: 3579df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com return GL_DUDV_ATI; 358242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com default: 3599df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com ; /* fallthrough */ 360242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com } 361d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com } 362242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com 3639df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com if (ctx->Extensions.MESA_texture_signed_rgba) { 364242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com switch (internalFormat) { 36596fcdcc219d2a0d3579719b84b28bede76efba64halcanary case GL_RGBA_SNORM: 366242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGBA8_SNORM: 367d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com return GL_RGBA; 368242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com default: 369242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com ; /* fallthrough */ 370242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com } 371d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com } 372242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com 3739df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com if (ctx->Extensions.EXT_packed_depth_stencil) { 3749df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com switch (internalFormat) { 375242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_DEPTH_STENCIL_EXT: 376242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_DEPTH24_STENCIL8_EXT: 377242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_DEPTH_STENCIL_EXT; 378d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com default: 379242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com ; /* fallthrough */ 380242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com } 381242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com } 382242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com 383242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#if FEATURE_EXT_texture_sRGB 384d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com if (ctx->Extensions.EXT_texture_sRGB) { 385242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com switch (internalFormat) { 386242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_SRGB_EXT: 387242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_SRGB8_EXT: 388242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COMPRESSED_SRGB_EXT: 389d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: 390242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_RGB; 391242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_SRGB_ALPHA_EXT: 392242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_SRGB8_ALPHA8_EXT: 393242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COMPRESSED_SRGB_ALPHA_EXT: 394242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: 395242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: 396242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: 397242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_RGBA; 398242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_SLUMINANCE_ALPHA_EXT: 399d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com case GL_SLUMINANCE8_ALPHA8_EXT: 400242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COMPRESSED_SLUMINANCE_EXT: 40122b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT: 40222b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com return GL_LUMINANCE_ALPHA; 403242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_SLUMINANCE_EXT: 404242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_SLUMINANCE8_EXT: 405242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_LUMINANCE; 406d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com default: 407242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com ; /* fallthrough */ 408242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com } 409242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com } 410242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com 411242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#endif /* FEATURE_EXT_texture_sRGB */ 412242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com 413242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return -1; /* error */ 414242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com} 415242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com 416242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com 417d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com/** 418242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * Test if the given image format is a color/RGBA format (i.e., not color 419242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * index, depth, stencil, etc). 420955bb0751a0d48e47a341c7c0adda94977bc8170bungeman@google.com * \param format the image format value (may by an internal texture format) 4218b169311b59ab84e8ca6f3630a1e960cc1be751erobertphillips@google.com * \return GL_TRUE if its a color/RGBA format, GL_FALSE otherwise. 422242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * XXX maybe move this func to image.c 423242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com */ 4244b18f5767ab1df7fedf0ff2e3a9eac7f7c500c36bungeman@google.comGLboolean 4254b18f5767ab1df7fedf0ff2e3a9eac7f7c500c36bungeman@google.com_mesa_is_color_format(GLenum format) 42622b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com{ 427242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com switch (format) { 428d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com case GL_RED: 429242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_GREEN: 430242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_BLUE: 431242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_ALPHA: 432d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com case GL_ALPHA4: 433242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_ALPHA8: 434242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_ALPHA12: 435242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_ALPHA16: 436d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com case 1: 437242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_LUMINANCE: 438242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_LUMINANCE4: 439242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_LUMINANCE8: 4404c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com case GL_LUMINANCE12: 4414c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com case GL_LUMINANCE16: 4424c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com case 2: 443242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_LUMINANCE_ALPHA: 4444c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com case GL_LUMINANCE4_ALPHA4: 4454c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com case GL_LUMINANCE6_ALPHA2: 4464c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com case GL_LUMINANCE8_ALPHA8: 4474c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com case GL_LUMINANCE12_ALPHA4: 448242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_LUMINANCE12_ALPHA12: 449242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_LUMINANCE16_ALPHA16: 45096fcdcc219d2a0d3579719b84b28bede76efba64halcanary case GL_INTENSITY: 451242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_INTENSITY4: 452385fe4d4b62d7d1dd76116dd570df3290a2f487bhalcanary case GL_INTENSITY8: 453242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_INTENSITY12: 4544c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com case GL_INTENSITY16: 455b5571b3324cf18629a255ec85e189447069c9b14scroggo@google.com case 3: 45639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case GL_RGB: 457b5571b3324cf18629a255ec85e189447069c9b14scroggo@google.com case GL_BGR: 45839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case GL_R3_G3_B2: 45939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case GL_RGB4: 46096fcdcc219d2a0d3579719b84b28bede76efba64halcanary case GL_RGB5: 46139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case GL_RGB8: 46239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case GL_RGB10: 46339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case GL_RGB12: 46439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case GL_RGB16: 46539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case 4: 466b5571b3324cf18629a255ec85e189447069c9b14scroggo@google.com case GL_ABGR_EXT: 4671ee76510f5dbf632d30975fc3509ef4f609156d2mtklein case GL_RGBA: 4681ee76510f5dbf632d30975fc3509ef4f609156d2mtklein case GL_BGRA: 469 case GL_RGBA2: 470 case GL_RGBA4: 471 case GL_RGB5_A1: 472 case GL_RGBA8: 473 case GL_RGB10_A2: 474 case GL_RGBA12: 475 case GL_RGBA16: 476 /* float texture formats */ 477 case GL_ALPHA16F_ARB: 478 case GL_ALPHA32F_ARB: 479 case GL_LUMINANCE16F_ARB: 480 case GL_LUMINANCE32F_ARB: 481 case GL_LUMINANCE_ALPHA16F_ARB: 482 case GL_LUMINANCE_ALPHA32F_ARB: 483 case GL_INTENSITY16F_ARB: 484 case GL_INTENSITY32F_ARB: 485 case GL_RGB16F_ARB: 486 case GL_RGB32F_ARB: 487 case GL_RGBA16F_ARB: 488 case GL_RGBA32F_ARB: 489 /* compressed formats */ 490 case GL_COMPRESSED_ALPHA: 491 case GL_COMPRESSED_LUMINANCE: 492 case GL_COMPRESSED_LUMINANCE_ALPHA: 493 case GL_COMPRESSED_INTENSITY: 494 case GL_COMPRESSED_RGB: 495 case GL_COMPRESSED_RGBA: 496 case GL_RGB_S3TC: 497 case GL_RGB4_S3TC: 498 case GL_RGBA_S3TC: 499 case GL_RGBA4_S3TC: 500 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: 501 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: 502 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: 503 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: 504 case GL_COMPRESSED_RGB_FXT1_3DFX: 505 case GL_COMPRESSED_RGBA_FXT1_3DFX: 506#if FEATURE_EXT_texture_sRGB 507 case GL_SRGB_EXT: 508 case GL_SRGB8_EXT: 509 case GL_SRGB_ALPHA_EXT: 510 case GL_SRGB8_ALPHA8_EXT: 511 case GL_SLUMINANCE_ALPHA_EXT: 512 case GL_SLUMINANCE8_ALPHA8_EXT: 513 case GL_SLUMINANCE_EXT: 514 case GL_SLUMINANCE8_EXT: 515 case GL_COMPRESSED_SRGB_EXT: 516 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: 517 case GL_COMPRESSED_SRGB_ALPHA_EXT: 518 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: 519 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: 520 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: 521 case GL_COMPRESSED_SLUMINANCE_EXT: 522 case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT: 523#endif /* FEATURE_EXT_texture_sRGB */ 524 return GL_TRUE; 525 /* signed texture formats */ 526 case GL_RGBA_SNORM: 527 case GL_RGBA8_SNORM: 528 return GL_TRUE; 529 case GL_YCBCR_MESA: /* not considered to be RGB */ 530 /* fall-through */ 531 default: 532 return GL_FALSE; 533 } 534} 535 536 537/** 538 * Test if the given image format is a color index format. 539 */ 540static GLboolean 541is_index_format(GLenum format) 542{ 543 switch (format) { 544 case GL_COLOR_INDEX: 545 case GL_COLOR_INDEX1_EXT: 546 case GL_COLOR_INDEX2_EXT: 547 case GL_COLOR_INDEX4_EXT: 548 case GL_COLOR_INDEX8_EXT: 549 case GL_COLOR_INDEX12_EXT: 550 case GL_COLOR_INDEX16_EXT: 551 return GL_TRUE; 552 default: 553 return GL_FALSE; 554 } 555} 556 557 558/** 559 * Test if the given image format is a depth component format. 560 */ 561static GLboolean 562is_depth_format(GLenum format) 563{ 564 switch (format) { 565 case GL_DEPTH_COMPONENT16: 566 case GL_DEPTH_COMPONENT24: 567 case GL_DEPTH_COMPONENT32: 568 case GL_DEPTH_COMPONENT: 569 return GL_TRUE; 570 default: 571 return GL_FALSE; 572 } 573} 574 575 576/** 577 * Test if the given image format is a YCbCr format. 578 */ 579static GLboolean 580is_ycbcr_format(GLenum format) 581{ 582 switch (format) { 583 case GL_YCBCR_MESA: 584 return GL_TRUE; 585 default: 586 return GL_FALSE; 587 } 588} 589 590 591/** 592 * Test if the given image format is a Depth/Stencil format. 593 */ 594static GLboolean 595is_depthstencil_format(GLenum format) 596{ 597 switch (format) { 598 case GL_DEPTH24_STENCIL8_EXT: 599 case GL_DEPTH_STENCIL_EXT: 600 return GL_TRUE; 601 default: 602 return GL_FALSE; 603 } 604} 605 606/** 607 * Test if the given image format is a dudv format. 608 */ 609static GLboolean 610is_dudv_format(GLenum format) 611{ 612 switch (format) { 613 case GL_DUDV_ATI: 614 case GL_DU8DV8_ATI: 615 return GL_TRUE; 616 default: 617 return GL_FALSE; 618 } 619} 620 621 622/** 623 * Test if it is a supported compressed format. 624 * 625 * \param internalFormat the internal format token provided by the user. 626 * 627 * \ret GL_TRUE if \p internalFormat is a supported compressed format, or 628 * GL_FALSE otherwise. 629 * 630 * Currently only GL_COMPRESSED_RGB_FXT1_3DFX and GL_COMPRESSED_RGBA_FXT1_3DFX 631 * are supported. 632 */ 633static GLboolean 634is_compressed_format(GLcontext *ctx, GLenum internalFormat) 635{ 636 GLint supported[100]; /* 100 should be plenty */ 637 GLuint i, n; 638 639 n = _mesa_get_compressed_formats(ctx, supported, GL_TRUE); 640 ASSERT(n < 100); 641 for (i = 0; i < n; i++) { 642 if ((GLint) internalFormat == supported[i]) { 643 return GL_TRUE; 644 } 645 } 646 return GL_FALSE; 647} 648 649 650/** 651 * For cube map faces, return a face index in [0,5]. 652 * For other targets return 0; 653 */ 654GLuint 655_mesa_tex_target_to_face(GLenum target) 656{ 657 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 658 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) 659 return (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X; 660 else 661 return 0; 662} 663 664 665 666/** 667 * Store a gl_texture_image pointer in a gl_texture_object structure 668 * according to the target and level parameters. 669 * 670 * \param tObj texture object. 671 * \param target texture target. 672 * \param level image level. 673 * \param texImage texture image. 674 * 675 * This was basically prompted by the introduction of cube maps. 676 */ 677void 678_mesa_set_tex_image(struct gl_texture_object *tObj, 679 GLenum target, GLint level, 680 struct gl_texture_image *texImage) 681{ 682 const GLuint face = _mesa_tex_target_to_face(target); 683 684 ASSERT(tObj); 685 ASSERT(texImage); 686 ASSERT(target != GL_TEXTURE_RECTANGLE_NV || level == 0); 687 688 tObj->Image[face][level] = texImage; 689 690 /* Set the 'back' pointer */ 691 texImage->TexObject = tObj; 692} 693 694 695/** 696 * Allocate a texture image structure. 697 * 698 * Called via ctx->Driver.NewTextureImage() unless overriden by a device 699 * driver. 700 * 701 * \return a pointer to gl_texture_image struct with all fields initialized to 702 * zero. 703 */ 704struct gl_texture_image * 705_mesa_new_texture_image( GLcontext *ctx ) 706{ 707 (void) ctx; 708 return CALLOC_STRUCT(gl_texture_image); 709} 710 711 712/** 713 * Free texture image data. 714 * This function is a fallback called via ctx->Driver.FreeTexImageData(). 715 * 716 * \param texImage texture image. 717 * 718 * Free the texture image data if it's not marked as client data. 719 */ 720void 721_mesa_free_texture_image_data(GLcontext *ctx, 722 struct gl_texture_image *texImage) 723{ 724 (void) ctx; 725 726 if (texImage->Data && !texImage->IsClientData) { 727 /* free the old texture data */ 728 _mesa_free_texmemory(texImage->Data); 729 } 730 731 texImage->Data = NULL; 732} 733 734 735/** 736 * Free texture image. 737 * 738 * \param texImage texture image. 739 * 740 * Free the texture image structure and the associated image data. 741 */ 742void 743_mesa_delete_texture_image( GLcontext *ctx, struct gl_texture_image *texImage ) 744{ 745 /* Free texImage->Data and/or any other driver-specific texture 746 * image storage. 747 */ 748 ASSERT(ctx->Driver.FreeTexImageData); 749 ctx->Driver.FreeTexImageData( ctx, texImage ); 750 751 ASSERT(texImage->Data == NULL); 752 if (texImage->ImageOffsets) 753 _mesa_free(texImage->ImageOffsets); 754 _mesa_free(texImage); 755} 756 757 758/** 759 * Test if a target is a proxy target. 760 * 761 * \param target texture target. 762 * 763 * \return GL_TRUE if the target is a proxy target, GL_FALSE otherwise. 764 */ 765GLboolean 766_mesa_is_proxy_texture(GLenum target) 767{ 768 return (target == GL_PROXY_TEXTURE_1D || 769 target == GL_PROXY_TEXTURE_2D || 770 target == GL_PROXY_TEXTURE_3D || 771 target == GL_PROXY_TEXTURE_CUBE_MAP_ARB || 772 target == GL_PROXY_TEXTURE_RECTANGLE_NV || 773 target == GL_PROXY_TEXTURE_1D_ARRAY_EXT || 774 target == GL_PROXY_TEXTURE_2D_ARRAY_EXT); 775} 776 777 778/** 779 * Return pointer to current texture unit. 780 * This the texture unit set by glActiveTexture(), not glClientActiveTexture(). 781 */ 782static INLINE struct gl_texture_unit * 783get_current_tex_unit(GLcontext *ctx) 784{ 785 ASSERT(ctx->Texture.CurrentUnit < Elements(ctx->Texture.Unit)); 786 return &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]); 787} 788 789 790/** 791 * Get the texture object that corresponds to the target of the given texture unit. 792 * 793 * \param ctx GL context. 794 * \param texUnit texture unit. 795 * \param target texture target. 796 * 797 * \return pointer to the texture object on success, or NULL on failure. 798 * 799 * \sa gl_texture_unit. 800 */ 801struct gl_texture_object * 802_mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit, 803 GLenum target) 804{ 805 switch (target) { 806 case GL_TEXTURE_1D: 807 return texUnit->CurrentTex[TEXTURE_1D_INDEX]; 808 case GL_PROXY_TEXTURE_1D: 809 return ctx->Texture.ProxyTex[TEXTURE_1D_INDEX]; 810 case GL_TEXTURE_2D: 811 return texUnit->CurrentTex[TEXTURE_2D_INDEX]; 812 case GL_PROXY_TEXTURE_2D: 813 return ctx->Texture.ProxyTex[TEXTURE_2D_INDEX]; 814 case GL_TEXTURE_3D: 815 return texUnit->CurrentTex[TEXTURE_3D_INDEX]; 816 case GL_PROXY_TEXTURE_3D: 817 return ctx->Texture.ProxyTex[TEXTURE_3D_INDEX]; 818 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: 819 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: 820 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: 821 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: 822 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: 823 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: 824 case GL_TEXTURE_CUBE_MAP_ARB: 825 return ctx->Extensions.ARB_texture_cube_map 826 ? texUnit->CurrentTex[TEXTURE_CUBE_INDEX] : NULL; 827 case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 828 return ctx->Extensions.ARB_texture_cube_map 829 ? ctx->Texture.ProxyTex[TEXTURE_CUBE_INDEX] : NULL; 830 case GL_TEXTURE_RECTANGLE_NV: 831 return ctx->Extensions.NV_texture_rectangle 832 ? texUnit->CurrentTex[TEXTURE_RECT_INDEX] : NULL; 833 case GL_PROXY_TEXTURE_RECTANGLE_NV: 834 return ctx->Extensions.NV_texture_rectangle 835 ? ctx->Texture.ProxyTex[TEXTURE_RECT_INDEX] : NULL; 836 case GL_TEXTURE_1D_ARRAY_EXT: 837 return ctx->Extensions.MESA_texture_array 838 ? texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX] : NULL; 839 case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 840 return ctx->Extensions.MESA_texture_array 841 ? ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX] : NULL; 842 case GL_TEXTURE_2D_ARRAY_EXT: 843 return ctx->Extensions.MESA_texture_array 844 ? texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX] : NULL; 845 case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 846 return ctx->Extensions.MESA_texture_array 847 ? ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX] : NULL; 848 default: 849 _mesa_problem(NULL, "bad target in _mesa_select_tex_object()"); 850 return NULL; 851 } 852} 853 854 855/** 856 * Get a texture image pointer from a texture object, given a texture 857 * target and mipmap level. The target and level parameters should 858 * have already been error-checked. 859 * 860 * \param ctx GL context. 861 * \param texObj texture unit. 862 * \param target texture target. 863 * \param level image level. 864 * 865 * \return pointer to the texture image structure, or NULL on failure. 866 */ 867struct gl_texture_image * 868_mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_object *texObj, 869 GLenum target, GLint level) 870{ 871 const GLuint face = _mesa_tex_target_to_face(target); 872 873 ASSERT(texObj); 874 ASSERT(level >= 0); 875 ASSERT(level < MAX_TEXTURE_LEVELS); 876 877 return texObj->Image[face][level]; 878} 879 880 881/** 882 * Like _mesa_select_tex_image() but if the image doesn't exist, allocate 883 * it and install it. Only return NULL if passed a bad parameter or run 884 * out of memory. 885 */ 886struct gl_texture_image * 887_mesa_get_tex_image(GLcontext *ctx, struct gl_texture_object *texObj, 888 GLenum target, GLint level) 889{ 890 struct gl_texture_image *texImage; 891 892 if (!texObj) 893 return NULL; 894 895 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 896 if (!texImage) { 897 texImage = ctx->Driver.NewTextureImage(ctx); 898 if (!texImage) { 899 _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture image allocation"); 900 return NULL; 901 } 902 903 _mesa_set_tex_image(texObj, target, level, texImage); 904 } 905 906 return texImage; 907} 908 909 910/** 911 * Return pointer to the specified proxy texture image. 912 * Note that proxy textures are per-context, not per-texture unit. 913 * \return pointer to texture image or NULL if invalid target, invalid 914 * level, or out of memory. 915 */ 916struct gl_texture_image * 917_mesa_get_proxy_tex_image(GLcontext *ctx, GLenum target, GLint level) 918{ 919 struct gl_texture_image *texImage; 920 GLuint texIndex; 921 922 if (level < 0 ) 923 return NULL; 924 925 switch (target) { 926 case GL_PROXY_TEXTURE_1D: 927 if (level >= ctx->Const.MaxTextureLevels) 928 return NULL; 929 texIndex = TEXTURE_1D_INDEX; 930 break; 931 case GL_PROXY_TEXTURE_2D: 932 if (level >= ctx->Const.MaxTextureLevels) 933 return NULL; 934 texIndex = TEXTURE_2D_INDEX; 935 break; 936 case GL_PROXY_TEXTURE_3D: 937 if (level >= ctx->Const.Max3DTextureLevels) 938 return NULL; 939 texIndex = TEXTURE_3D_INDEX; 940 break; 941 case GL_PROXY_TEXTURE_CUBE_MAP: 942 if (level >= ctx->Const.MaxCubeTextureLevels) 943 return NULL; 944 texIndex = TEXTURE_CUBE_INDEX; 945 break; 946 case GL_PROXY_TEXTURE_RECTANGLE_NV: 947 if (level > 0) 948 return NULL; 949 texIndex = TEXTURE_RECT_INDEX; 950 break; 951 case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 952 if (level >= ctx->Const.MaxTextureLevels) 953 return NULL; 954 texIndex = TEXTURE_1D_ARRAY_INDEX; 955 break; 956 case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 957 if (level >= ctx->Const.MaxTextureLevels) 958 return NULL; 959 texIndex = TEXTURE_2D_ARRAY_INDEX; 960 break; 961 default: 962 return NULL; 963 } 964 965 texImage = ctx->Texture.ProxyTex[texIndex]->Image[0][level]; 966 if (!texImage) { 967 texImage = ctx->Driver.NewTextureImage(ctx); 968 if (!texImage) { 969 _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation"); 970 return NULL; 971 } 972 ctx->Texture.ProxyTex[texIndex]->Image[0][level] = texImage; 973 /* Set the 'back' pointer */ 974 texImage->TexObject = ctx->Texture.ProxyTex[texIndex]; 975 } 976 return texImage; 977} 978 979 980/** 981 * Get the maximum number of allowed mipmap levels. 982 * 983 * \param ctx GL context. 984 * \param target texture target. 985 * 986 * \return the maximum number of allowed mipmap levels for the given 987 * texture target, or zero if passed a bad target. 988 * 989 * \sa gl_constants. 990 */ 991GLint 992_mesa_max_texture_levels(GLcontext *ctx, GLenum target) 993{ 994 switch (target) { 995 case GL_TEXTURE_1D: 996 case GL_PROXY_TEXTURE_1D: 997 case GL_TEXTURE_2D: 998 case GL_PROXY_TEXTURE_2D: 999 case GL_TEXTURE_1D_ARRAY_EXT: 1000 case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 1001 case GL_TEXTURE_2D_ARRAY_EXT: 1002 case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 1003 return ctx->Const.MaxTextureLevels; 1004 case GL_TEXTURE_3D: 1005 case GL_PROXY_TEXTURE_3D: 1006 return ctx->Const.Max3DTextureLevels; 1007 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: 1008 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: 1009 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: 1010 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: 1011 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: 1012 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: 1013 case GL_TEXTURE_CUBE_MAP_ARB: 1014 case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 1015 return ctx->Const.MaxCubeTextureLevels; 1016 case GL_TEXTURE_RECTANGLE_NV: 1017 case GL_PROXY_TEXTURE_RECTANGLE_NV: 1018 return 1; 1019 default: 1020 return 0; /* bad target */ 1021 } 1022} 1023 1024 1025 1026#if 000 /* not used anymore */ 1027/* 1028 * glTexImage[123]D can accept a NULL image pointer. In this case we 1029 * create a texture image with unspecified image contents per the OpenGL 1030 * spec. 1031 */ 1032static GLubyte * 1033make_null_texture(GLint width, GLint height, GLint depth, GLenum format) 1034{ 1035 const GLint components = _mesa_components_in_format(format); 1036 const GLint numPixels = width * height * depth; 1037 GLubyte *data = (GLubyte *) MALLOC(numPixels * components * sizeof(GLubyte)); 1038 1039#ifdef DEBUG 1040 /* 1041 * Let's see if anyone finds this. If glTexImage2D() is called with 1042 * a NULL image pointer then load the texture image with something 1043 * interesting instead of leaving it indeterminate. 1044 */ 1045 if (data) { 1046 static const char message[8][32] = { 1047 " X X XXXXX XXX X ", 1048 " XX XX X X X X X ", 1049 " X X X X X X X ", 1050 " X X XXXX XXX XXXXX ", 1051 " X X X X X X ", 1052 " X X X X X X X ", 1053 " X X XXXXX XXX X X ", 1054 " " 1055 }; 1056 1057 GLubyte *imgPtr = data; 1058 GLint h, i, j, k; 1059 for (h = 0; h < depth; h++) { 1060 for (i = 0; i < height; i++) { 1061 GLint srcRow = 7 - (i % 8); 1062 for (j = 0; j < width; j++) { 1063 GLint srcCol = j % 32; 1064 GLubyte texel = (message[srcRow][srcCol]=='X') ? 255 : 70; 1065 for (k = 0; k < components; k++) { 1066 *imgPtr++ = texel; 1067 } 1068 } 1069 } 1070 } 1071 } 1072#endif 1073 1074 return data; 1075} 1076#endif 1077 1078 1079 1080/** 1081 * Reset the fields of a gl_texture_image struct to zero. 1082 * 1083 * \param img texture image structure. 1084 * 1085 * This is called when a proxy texture test fails, we set all the 1086 * image members (except DriverData) to zero. 1087 * It's also used in glTexImage[123]D as a safeguard to be sure all 1088 * required fields get initialized properly by the Driver.TexImage[123]D 1089 * functions. 1090 */ 1091static void 1092clear_teximage_fields(struct gl_texture_image *img) 1093{ 1094 ASSERT(img); 1095 img->_BaseFormat = 0; 1096 img->InternalFormat = 0; 1097 img->Border = 0; 1098 img->Width = 0; 1099 img->Height = 0; 1100 img->Depth = 0; 1101 img->RowStride = 0; 1102 if (img->ImageOffsets) { 1103 _mesa_free(img->ImageOffsets); 1104 img->ImageOffsets = NULL; 1105 } 1106 img->Width2 = 0; 1107 img->Height2 = 0; 1108 img->Depth2 = 0; 1109 img->WidthLog2 = 0; 1110 img->HeightLog2 = 0; 1111 img->DepthLog2 = 0; 1112 img->Data = NULL; 1113 img->TexFormat = &_mesa_null_texformat; 1114 img->FetchTexelc = NULL; 1115 img->FetchTexelf = NULL; 1116 img->IsCompressed = 0; 1117 img->CompressedSize = 0; 1118} 1119 1120 1121/** 1122 * Initialize basic fields of the gl_texture_image struct. 1123 * 1124 * \param ctx GL context. 1125 * \param target texture target (GL_TEXTURE_1D, GL_TEXTURE_RECTANGLE, etc). 1126 * \param img texture image structure to be initialized. 1127 * \param width image width. 1128 * \param height image height. 1129 * \param depth image depth. 1130 * \param border image border. 1131 * \param internalFormat internal format. 1132 * 1133 * Fills in the fields of \p img with the given information. 1134 * Note: width, height and depth include the border. 1135 */ 1136void 1137_mesa_init_teximage_fields(GLcontext *ctx, GLenum target, 1138 struct gl_texture_image *img, 1139 GLsizei width, GLsizei height, GLsizei depth, 1140 GLint border, GLenum internalFormat) 1141{ 1142 GLint i; 1143 1144 ASSERT(img); 1145 ASSERT(width >= 0); 1146 ASSERT(height >= 0); 1147 ASSERT(depth >= 0); 1148 1149 img->_BaseFormat = _mesa_base_tex_format( ctx, internalFormat ); 1150 ASSERT(img->_BaseFormat > 0); 1151 img->InternalFormat = internalFormat; 1152 img->Border = border; 1153 img->Width = width; 1154 img->Height = height; 1155 img->Depth = depth; 1156 1157 img->Width2 = width - 2 * border; /* == 1 << img->WidthLog2; */ 1158 img->WidthLog2 = logbase2(img->Width2); 1159 1160 if (height == 1) { /* 1-D texture */ 1161 img->Height2 = 1; 1162 img->HeightLog2 = 0; 1163 } 1164 else { 1165 img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */ 1166 img->HeightLog2 = logbase2(img->Height2); 1167 } 1168 1169 if (depth == 1) { /* 2-D texture */ 1170 img->Depth2 = 1; 1171 img->DepthLog2 = 0; 1172 } 1173 else { 1174 img->Depth2 = depth - 2 * border; /* == 1 << img->DepthLog2; */ 1175 img->DepthLog2 = logbase2(img->Depth2); 1176 } 1177 1178 img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2); 1179 1180 img->IsCompressed = GL_FALSE; 1181 img->CompressedSize = 0; 1182 1183 if ((width == 1 || _mesa_is_pow_two(img->Width2)) && 1184 (height == 1 || _mesa_is_pow_two(img->Height2)) && 1185 (depth == 1 || _mesa_is_pow_two(img->Depth2))) 1186 img->_IsPowerOfTwo = GL_TRUE; 1187 else 1188 img->_IsPowerOfTwo = GL_FALSE; 1189 1190 /* RowStride and ImageOffsets[] describe how to address texels in 'Data' */ 1191 img->RowStride = width; 1192 /* Allocate the ImageOffsets array and initialize to typical values. 1193 * We allocate the array for 1D/2D textures too in order to avoid special- 1194 * case code in the texstore routines. 1195 */ 1196 if (img->ImageOffsets) 1197 _mesa_free(img->ImageOffsets); 1198 img->ImageOffsets = (GLuint *) _mesa_malloc(depth * sizeof(GLuint)); 1199 for (i = 0; i < depth; i++) { 1200 img->ImageOffsets[i] = i * width * height; 1201 } 1202 1203 /* Compute Width/Height/DepthScale for mipmap lod computation */ 1204 if (target == GL_TEXTURE_RECTANGLE_NV) { 1205 /* scale = 1.0 since texture coords directly map to texels */ 1206 img->WidthScale = 1.0; 1207 img->HeightScale = 1.0; 1208 img->DepthScale = 1.0; 1209 } 1210 else { 1211 img->WidthScale = (GLfloat) img->Width; 1212 img->HeightScale = (GLfloat) img->Height; 1213 img->DepthScale = (GLfloat) img->Depth; 1214 } 1215} 1216 1217 1218/** 1219 * This is the fallback for Driver.TestProxyTexImage(). Test the texture 1220 * level, width, height and depth against the ctx->Const limits for textures. 1221 * 1222 * A hardware driver might override this function if, for example, the 1223 * max 3D texture size is 512x512x64 (i.e. not a cube). 1224 * 1225 * Note that width, height, depth == 0 is not an error. However, a 1226 * texture with zero width/height/depth will be considered "incomplete" 1227 * and texturing will effectively be disabled. 1228 * 1229 * \param target one of GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D, 1230 * GL_PROXY_TEXTURE_3D, GL_PROXY_TEXTURE_RECTANGLE_NV, 1231 * GL_PROXY_TEXTURE_CUBE_MAP_ARB. 1232 * \param level as passed to glTexImage 1233 * \param internalFormat as passed to glTexImage 1234 * \param format as passed to glTexImage 1235 * \param type as passed to glTexImage 1236 * \param width as passed to glTexImage 1237 * \param height as passed to glTexImage 1238 * \param depth as passed to glTexImage 1239 * \param border as passed to glTexImage 1240 * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable. 1241 */ 1242GLboolean 1243_mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level, 1244 GLint internalFormat, GLenum format, GLenum type, 1245 GLint width, GLint height, GLint depth, GLint border) 1246{ 1247 GLint maxSize; 1248 1249 (void) internalFormat; 1250 (void) format; 1251 (void) type; 1252 1253 switch (target) { 1254 case GL_PROXY_TEXTURE_1D: 1255 maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 1256 if (width < 2 * border || width > 2 + maxSize || 1257 (!ctx->Extensions.ARB_texture_non_power_of_two && 1258 width >0 && !_mesa_is_pow_two(width - 2 * border)) || 1259 level >= ctx->Const.MaxTextureLevels) { 1260 /* bad width or level */ 1261 return GL_FALSE; 1262 } 1263 return GL_TRUE; 1264 case GL_PROXY_TEXTURE_2D: 1265 maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 1266 if (width < 2 * border || width > 2 + maxSize || 1267 (!ctx->Extensions.ARB_texture_non_power_of_two && 1268 width > 0 && !_mesa_is_pow_two(width - 2 * border)) || 1269 height < 2 * border || height > 2 + maxSize || 1270 (!ctx->Extensions.ARB_texture_non_power_of_two && 1271 height > 0 && !_mesa_is_pow_two(height - 2 * border)) || 1272 level >= ctx->Const.MaxTextureLevels) { 1273 /* bad width or height or level */ 1274 return GL_FALSE; 1275 } 1276 return GL_TRUE; 1277 case GL_PROXY_TEXTURE_3D: 1278 maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1); 1279 if (width < 2 * border || width > 2 + maxSize || 1280 (!ctx->Extensions.ARB_texture_non_power_of_two && 1281 width > 0 && !_mesa_is_pow_two(width - 2 * border)) || 1282 height < 2 * border || height > 2 + maxSize || 1283 (!ctx->Extensions.ARB_texture_non_power_of_two && 1284 height > 0 && !_mesa_is_pow_two(height - 2 * border)) || 1285 depth < 2 * border || depth > 2 + maxSize || 1286 (!ctx->Extensions.ARB_texture_non_power_of_two && 1287 depth > 0 && !_mesa_is_pow_two(depth - 2 * border)) || 1288 level >= ctx->Const.Max3DTextureLevels) { 1289 /* bad width or height or depth or level */ 1290 return GL_FALSE; 1291 } 1292 return GL_TRUE; 1293 case GL_PROXY_TEXTURE_RECTANGLE_NV: 1294 if (width < 0 || width > ctx->Const.MaxTextureRectSize || 1295 height < 0 || height > ctx->Const.MaxTextureRectSize || 1296 level != 0) { 1297 /* bad width or height or level */ 1298 return GL_FALSE; 1299 } 1300 return GL_TRUE; 1301 case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 1302 maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1); 1303 if (width < 2 * border || width > 2 + maxSize || 1304 (!ctx->Extensions.ARB_texture_non_power_of_two && 1305 width > 0 && !_mesa_is_pow_two(width - 2 * border)) || 1306 height < 2 * border || height > 2 + maxSize || 1307 (!ctx->Extensions.ARB_texture_non_power_of_two && 1308 height > 0 && !_mesa_is_pow_two(height - 2 * border)) || 1309 level >= ctx->Const.MaxCubeTextureLevels) { 1310 /* bad width or height */ 1311 return GL_FALSE; 1312 } 1313 return GL_TRUE; 1314 case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 1315 maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 1316 if (width < 2 * border || width > 2 + maxSize || 1317 (!ctx->Extensions.ARB_texture_non_power_of_two && 1318 width > 0 && !_mesa_is_pow_two(width - 2 * border)) || 1319 level >= ctx->Const.MaxTextureLevels) { 1320 /* bad width or level */ 1321 return GL_FALSE; 1322 } 1323 1324 if (height < 1 || height > ctx->Const.MaxArrayTextureLayers) { 1325 return GL_FALSE; 1326 } 1327 return GL_TRUE; 1328 case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 1329 maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 1330 if (width < 2 * border || width > 2 + maxSize || 1331 (!ctx->Extensions.ARB_texture_non_power_of_two && 1332 width > 0 && !_mesa_is_pow_two(width - 2 * border)) || 1333 height < 2 * border || height > 2 + maxSize || 1334 (!ctx->Extensions.ARB_texture_non_power_of_two && 1335 height > 0 && !_mesa_is_pow_two(height - 2 * border)) || 1336 level >= ctx->Const.MaxTextureLevels) { 1337 /* bad width or height or level */ 1338 return GL_FALSE; 1339 } 1340 if (depth < 1 || depth > ctx->Const.MaxArrayTextureLayers) { 1341 return GL_FALSE; 1342 } 1343 return GL_TRUE; 1344 default: 1345 _mesa_problem(ctx, "Invalid target in _mesa_test_proxy_teximage"); 1346 return GL_FALSE; 1347 } 1348} 1349 1350 1351/** 1352 * Helper function to determine whether a target supports compressed textures 1353 */ 1354static GLboolean 1355target_can_be_compressed(GLcontext *ctx, GLenum target) 1356{ 1357 return (((target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D)) 1358 || ((ctx->Extensions.ARB_texture_cube_map && 1359 (target == GL_PROXY_TEXTURE_CUBE_MAP || 1360 (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && 1361 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)))) 1362 || ((ctx->Extensions.MESA_texture_array && 1363 ((target == GL_PROXY_TEXTURE_2D_ARRAY_EXT) || 1364 (target == GL_TEXTURE_2D_ARRAY_EXT))))); 1365} 1366 1367 1368/** 1369 * Test the glTexImage[123]D() parameters for errors. 1370 * 1371 * \param ctx GL context. 1372 * \param target texture target given by the user. 1373 * \param level image level given by the user. 1374 * \param internalFormat internal format given by the user. 1375 * \param format pixel data format given by the user. 1376 * \param type pixel data type given by the user. 1377 * \param dimensions texture image dimensions (must be 1, 2 or 3). 1378 * \param width image width given by the user. 1379 * \param height image height given by the user. 1380 * \param depth image depth given by the user. 1381 * \param border image border given by the user. 1382 * 1383 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 1384 * 1385 * Verifies each of the parameters against the constants specified in 1386 * __GLcontextRec::Const and the supported extensions, and according to the 1387 * OpenGL specification. 1388 */ 1389static GLboolean 1390texture_error_check( GLcontext *ctx, GLenum target, 1391 GLint level, GLint internalFormat, 1392 GLenum format, GLenum type, 1393 GLuint dimensions, 1394 GLint width, GLint height, 1395 GLint depth, GLint border ) 1396{ 1397 const GLboolean isProxy = _mesa_is_proxy_texture(target); 1398 GLboolean sizeOK = GL_TRUE; 1399 GLboolean colorFormat, indexFormat; 1400 GLenum proxy_target; 1401 1402 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */ 1403 if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 1404 if (!isProxy) { 1405 _mesa_error(ctx, GL_INVALID_VALUE, 1406 "glTexImage%dD(level=%d)", dimensions, level); 1407 } 1408 return GL_TRUE; 1409 } 1410 1411 /* Check border */ 1412 if (border < 0 || border > 1 || 1413 ((target == GL_TEXTURE_RECTANGLE_NV || 1414 target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) { 1415 if (!isProxy) { 1416 _mesa_error(ctx, GL_INVALID_VALUE, 1417 "glTexImage%dD(border=%d)", dimensions, border); 1418 } 1419 return GL_TRUE; 1420 } 1421 1422 if (width < 0 || height < 0 || depth < 0) { 1423 if (!isProxy) { 1424 _mesa_error(ctx, GL_INVALID_VALUE, 1425 "glTexImage%dD(width, height or depth < 0)", dimensions); 1426 } 1427 return GL_TRUE; 1428 } 1429 1430 /* Check target and call ctx->Driver.TestProxyTexImage() to check the 1431 * level, width, height and depth. 1432 */ 1433 if (dimensions == 1) { 1434 if (target == GL_PROXY_TEXTURE_1D || target == GL_TEXTURE_1D) { 1435 proxy_target = GL_PROXY_TEXTURE_1D; 1436 height = 1; 1437 depth = 1; 1438 } 1439 else { 1440 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); 1441 return GL_TRUE; 1442 } 1443 } 1444 else if (dimensions == 2) { 1445 depth = 1; 1446 if (target == GL_PROXY_TEXTURE_2D || target == GL_TEXTURE_2D) { 1447 proxy_target = GL_PROXY_TEXTURE_2D; 1448 } 1449 else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB || 1450 (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 1451 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) { 1452 if (!ctx->Extensions.ARB_texture_cube_map) { 1453 _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)"); 1454 return GL_TRUE; 1455 } 1456 proxy_target = GL_PROXY_TEXTURE_CUBE_MAP_ARB; 1457 sizeOK = (width == height); 1458 } 1459 else if (target == GL_PROXY_TEXTURE_RECTANGLE_NV || 1460 target == GL_TEXTURE_RECTANGLE_NV) { 1461 if (!ctx->Extensions.NV_texture_rectangle) { 1462 _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)"); 1463 return GL_TRUE; 1464 } 1465 proxy_target = GL_PROXY_TEXTURE_RECTANGLE_NV; 1466 } 1467 else if (target == GL_PROXY_TEXTURE_1D_ARRAY_EXT || 1468 target == GL_TEXTURE_1D_ARRAY_EXT) { 1469 proxy_target = GL_PROXY_TEXTURE_1D_ARRAY_EXT; 1470 } 1471 else { 1472 _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)"); 1473 return GL_TRUE; 1474 } 1475 } 1476 else if (dimensions == 3) { 1477 if (target == GL_PROXY_TEXTURE_3D || target == GL_TEXTURE_3D) { 1478 proxy_target = GL_PROXY_TEXTURE_3D; 1479 } 1480 else if (target == GL_PROXY_TEXTURE_2D_ARRAY_EXT || 1481 target == GL_TEXTURE_2D_ARRAY_EXT) { 1482 proxy_target = GL_PROXY_TEXTURE_2D_ARRAY_EXT; 1483 } 1484 else { 1485 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" ); 1486 return GL_TRUE; 1487 } 1488 } 1489 else { 1490 _mesa_problem( ctx, "bad dims in texture_error_check" ); 1491 return GL_TRUE; 1492 } 1493 1494 sizeOK = sizeOK && ctx->Driver.TestProxyTexImage(ctx, proxy_target, level, 1495 internalFormat, format, 1496 type, width, height, 1497 depth, border); 1498 if (!sizeOK) { 1499 if (!isProxy) { 1500 _mesa_error(ctx, GL_INVALID_VALUE, 1501 "glTexImage%dD(level=%d, width=%d, height=%d, depth=%d)", 1502 dimensions, level, width, height, depth); 1503 } 1504 return GL_TRUE; 1505 } 1506 1507 /* Check internalFormat */ 1508 if (_mesa_base_tex_format(ctx, internalFormat) < 0) { 1509 if (!isProxy) { 1510 _mesa_error(ctx, GL_INVALID_VALUE, 1511 "glTexImage%dD(internalFormat=0x%x)", 1512 dimensions, internalFormat); 1513 } 1514 return GL_TRUE; 1515 } 1516 1517 /* Check incoming image format and type */ 1518 if (!_mesa_is_legal_format_and_type(ctx, format, type)) { 1519 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there 1520 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4. 1521 */ 1522 if (!isProxy) { 1523 _mesa_error(ctx, GL_INVALID_OPERATION, 1524 "glTexImage%dD(incompatible format 0x%x, type 0x%x)", 1525 dimensions, format, type); 1526 } 1527 return GL_TRUE; 1528 } 1529 1530 /* make sure internal format and format basically agree */ 1531 colorFormat = _mesa_is_color_format(format); 1532 indexFormat = is_index_format(format); 1533 if ((_mesa_is_color_format(internalFormat) && !colorFormat && !indexFormat) || 1534 (is_index_format(internalFormat) && !indexFormat) || 1535 (is_depth_format(internalFormat) != is_depth_format(format)) || 1536 (is_ycbcr_format(internalFormat) != is_ycbcr_format(format)) || 1537 (is_depthstencil_format(internalFormat) != is_depthstencil_format(format)) || 1538 (is_dudv_format(internalFormat) != is_dudv_format(format))) { 1539 if (!isProxy) 1540 _mesa_error(ctx, GL_INVALID_OPERATION, 1541 "glTexImage%dD(incompatible internalFormat 0x%x, format 0x%x)", 1542 dimensions, internalFormat, format); 1543 return GL_TRUE; 1544 } 1545 1546 /* additional checks for ycbcr textures */ 1547 if (internalFormat == GL_YCBCR_MESA) { 1548 ASSERT(ctx->Extensions.MESA_ycbcr_texture); 1549 if (type != GL_UNSIGNED_SHORT_8_8_MESA && 1550 type != GL_UNSIGNED_SHORT_8_8_REV_MESA) { 1551 char message[100]; 1552 _mesa_sprintf(message, 1553 "glTexImage%d(format/type YCBCR mismatch", dimensions); 1554 _mesa_error(ctx, GL_INVALID_ENUM, message); 1555 return GL_TRUE; /* error */ 1556 } 1557 if (target != GL_TEXTURE_2D && 1558 target != GL_PROXY_TEXTURE_2D && 1559 target != GL_TEXTURE_RECTANGLE_NV && 1560 target != GL_PROXY_TEXTURE_RECTANGLE_NV) { 1561 if (!isProxy) 1562 _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage(target)"); 1563 return GL_TRUE; 1564 } 1565 if (border != 0) { 1566 if (!isProxy) { 1567 char message[100]; 1568 _mesa_sprintf(message, 1569 "glTexImage%d(format=GL_YCBCR_MESA and border=%d)", 1570 dimensions, border); 1571 _mesa_error(ctx, GL_INVALID_VALUE, message); 1572 } 1573 return GL_TRUE; 1574 } 1575 } 1576 1577 /* additional checks for depth textures */ 1578 if (_mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_COMPONENT) { 1579 /* Only 1D, 2D and rectangular textures supported, not 3D or cubes */ 1580 if (target != GL_TEXTURE_1D && 1581 target != GL_PROXY_TEXTURE_1D && 1582 target != GL_TEXTURE_2D && 1583 target != GL_PROXY_TEXTURE_2D && 1584 target != GL_TEXTURE_RECTANGLE_ARB && 1585 target != GL_PROXY_TEXTURE_RECTANGLE_ARB) { 1586 if (!isProxy) 1587 _mesa_error(ctx, GL_INVALID_ENUM, 1588 "glTexImage(target/internalFormat)"); 1589 return GL_TRUE; 1590 } 1591 } 1592 1593 /* additional checks for compressed textures */ 1594 if (is_compressed_format(ctx, internalFormat)) { 1595 if (!target_can_be_compressed(ctx, target) && !isProxy) { 1596 _mesa_error(ctx, GL_INVALID_ENUM, 1597 "glTexImage%d(target)", dimensions); 1598 return GL_TRUE; 1599 } 1600 if (border != 0) { 1601 if (!isProxy) { 1602 _mesa_error(ctx, GL_INVALID_OPERATION, 1603 "glTexImage%D(border!=0)", dimensions); 1604 } 1605 return GL_TRUE; 1606 } 1607 } 1608 1609 /* if we get here, the parameters are OK */ 1610 return GL_FALSE; 1611} 1612 1613 1614/** 1615 * Test glTexSubImage[123]D() parameters for errors. 1616 * 1617 * \param ctx GL context. 1618 * \param dimensions texture image dimensions (must be 1, 2 or 3). 1619 * \param target texture target given by the user. 1620 * \param level image level given by the user. 1621 * \param xoffset sub-image x offset given by the user. 1622 * \param yoffset sub-image y offset given by the user. 1623 * \param zoffset sub-image z offset given by the user. 1624 * \param format pixel data format given by the user. 1625 * \param type pixel data type given by the user. 1626 * \param width image width given by the user. 1627 * \param height image height given by the user. 1628 * \param depth image depth given by the user. 1629 * 1630 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 1631 * 1632 * Verifies each of the parameters against the constants specified in 1633 * __GLcontextRec::Const and the supported extensions, and according to the 1634 * OpenGL specification. 1635 */ 1636static GLboolean 1637subtexture_error_check( GLcontext *ctx, GLuint dimensions, 1638 GLenum target, GLint level, 1639 GLint xoffset, GLint yoffset, GLint zoffset, 1640 GLint width, GLint height, GLint depth, 1641 GLenum format, GLenum type ) 1642{ 1643 /* Check target */ 1644 if (dimensions == 1) { 1645 if (target != GL_TEXTURE_1D) { 1646 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" ); 1647 return GL_TRUE; 1648 } 1649 } 1650 else if (dimensions == 2) { 1651 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 1652 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 1653 if (!ctx->Extensions.ARB_texture_cube_map) { 1654 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); 1655 return GL_TRUE; 1656 } 1657 } 1658 else if (target == GL_TEXTURE_RECTANGLE_NV) { 1659 if (!ctx->Extensions.NV_texture_rectangle) { 1660 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); 1661 return GL_TRUE; 1662 } 1663 } 1664 else if (target == GL_TEXTURE_1D_ARRAY_EXT) { 1665 if (!ctx->Extensions.MESA_texture_array) { 1666 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); 1667 return GL_TRUE; 1668 } 1669 } 1670 else if (target != GL_TEXTURE_2D) { 1671 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); 1672 return GL_TRUE; 1673 } 1674 } 1675 else if (dimensions == 3) { 1676 if (target == GL_TEXTURE_2D_ARRAY_EXT) { 1677 if (!ctx->Extensions.MESA_texture_array) { 1678 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" ); 1679 return GL_TRUE; 1680 } 1681 } 1682 else if (target != GL_TEXTURE_3D) { 1683 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" ); 1684 return GL_TRUE; 1685 } 1686 } 1687 else { 1688 _mesa_problem( ctx, "invalid dims in texture_error_check" ); 1689 return GL_TRUE; 1690 } 1691 1692 /* Basic level check */ 1693 if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 1694 _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level=%d)", level); 1695 return GL_TRUE; 1696 } 1697 1698 if (width < 0) { 1699 _mesa_error(ctx, GL_INVALID_VALUE, 1700 "glTexSubImage%dD(width=%d)", dimensions, width); 1701 return GL_TRUE; 1702 } 1703 if (height < 0 && dimensions > 1) { 1704 _mesa_error(ctx, GL_INVALID_VALUE, 1705 "glTexSubImage%dD(height=%d)", dimensions, height); 1706 return GL_TRUE; 1707 } 1708 if (depth < 0 && dimensions > 2) { 1709 _mesa_error(ctx, GL_INVALID_VALUE, 1710 "glTexSubImage%dD(depth=%d)", dimensions, depth); 1711 return GL_TRUE; 1712 } 1713 1714 if (!_mesa_is_legal_format_and_type(ctx, format, type)) { 1715 _mesa_error(ctx, GL_INVALID_ENUM, 1716 "glTexSubImage%dD(incompatible format 0x%x, type 0x%x)", 1717 dimensions, format, type); 1718 return GL_TRUE; 1719 } 1720 1721 return GL_FALSE; 1722} 1723 1724static GLboolean 1725subtexture_error_check2( GLcontext *ctx, GLuint dimensions, 1726 GLenum target, GLint level, 1727 GLint xoffset, GLint yoffset, GLint zoffset, 1728 GLint width, GLint height, GLint depth, 1729 GLenum format, GLenum type, 1730 const struct gl_texture_image *destTex ) 1731{ 1732 if (!destTex) { 1733 /* undefined image level */ 1734 _mesa_error(ctx, GL_INVALID_OPERATION, "glTexSubImage%dD", dimensions); 1735 return GL_TRUE; 1736 } 1737 1738 if (xoffset < -((GLint)destTex->Border)) { 1739 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset)", 1740 dimensions); 1741 return GL_TRUE; 1742 } 1743 if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) { 1744 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset+width)", 1745 dimensions); 1746 return GL_TRUE; 1747 } 1748 if (dimensions > 1) { 1749 if (yoffset < -((GLint)destTex->Border)) { 1750 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset)", 1751 dimensions); 1752 return GL_TRUE; 1753 } 1754 if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) { 1755 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset+height)", 1756 dimensions); 1757 return GL_TRUE; 1758 } 1759 } 1760 if (dimensions > 2) { 1761 if (zoffset < -((GLint)destTex->Border)) { 1762 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)"); 1763 return GL_TRUE; 1764 } 1765 if (zoffset + depth > (GLint) (destTex->Depth + destTex->Border)) { 1766 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)"); 1767 return GL_TRUE; 1768 } 1769 } 1770 1771#if FEATURE_EXT_texture_sRGB 1772 if (destTex->InternalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT || 1773 destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT || 1774 destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT || 1775 destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) { 1776 if ((width & 0x3) || (height & 0x3) || 1777 (xoffset & 0x3) || (yoffset & 0x3)) 1778 _mesa_error(ctx, GL_INVALID_OPERATION, 1779 "glTexSubImage%dD(size or offset not multiple of 4)", 1780 dimensions); 1781 return GL_TRUE; 1782 } 1783#endif 1784 1785 if (destTex->IsCompressed) { 1786 if (!target_can_be_compressed(ctx, target)) { 1787 _mesa_error(ctx, GL_INVALID_ENUM, 1788 "glTexSubImage%D(target)", dimensions); 1789 return GL_TRUE; 1790 } 1791 /* offset must be multiple of 4 */ 1792 if ((xoffset & 3) || (yoffset & 3)) { 1793 _mesa_error(ctx, GL_INVALID_OPERATION, 1794 "glTexSubImage%D(xoffset or yoffset)", dimensions); 1795 return GL_TRUE; 1796 } 1797 /* size must be multiple of 4 or equal to whole texture size */ 1798 if ((width & 3) && (GLuint) width != destTex->Width) { 1799 _mesa_error(ctx, GL_INVALID_OPERATION, 1800 "glTexSubImage%D(width)", dimensions); 1801 return GL_TRUE; 1802 } 1803 if ((height & 3) && (GLuint) height != destTex->Height) { 1804 _mesa_error(ctx, GL_INVALID_OPERATION, 1805 "glTexSubImage%D(width)", dimensions); 1806 return GL_TRUE; 1807 } 1808 } 1809 1810 return GL_FALSE; 1811} 1812 1813 1814/** 1815 * Test glCopyTexImage[12]D() parameters for errors. 1816 * 1817 * \param ctx GL context. 1818 * \param dimensions texture image dimensions (must be 1, 2 or 3). 1819 * \param target texture target given by the user. 1820 * \param level image level given by the user. 1821 * \param internalFormat internal format given by the user. 1822 * \param width image width given by the user. 1823 * \param height image height given by the user. 1824 * \param border texture border. 1825 * 1826 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 1827 * 1828 * Verifies each of the parameters against the constants specified in 1829 * __GLcontextRec::Const and the supported extensions, and according to the 1830 * OpenGL specification. 1831 */ 1832static GLboolean 1833copytexture_error_check( GLcontext *ctx, GLuint dimensions, 1834 GLenum target, GLint level, GLint internalFormat, 1835 GLint width, GLint height, GLint border ) 1836{ 1837 GLenum type; 1838 GLboolean sizeOK; 1839 GLint format; 1840 1841 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */ 1842 if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 1843 _mesa_error(ctx, GL_INVALID_VALUE, 1844 "glCopyTexImage%dD(level=%d)", dimensions, level); 1845 return GL_TRUE; 1846 } 1847 1848 /* Check that the source buffer is complete */ 1849 if (ctx->ReadBuffer->Name) { 1850 _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer); 1851 if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 1852 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 1853 "glCopyTexImage%dD(invalid readbuffer)", dimensions); 1854 return GL_TRUE; 1855 } 1856 } 1857 1858 /* Check border */ 1859 if (border < 0 || border > 1 || 1860 ((target == GL_TEXTURE_RECTANGLE_NV || 1861 target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) { 1862 return GL_TRUE; 1863 } 1864 1865 format = _mesa_base_tex_format(ctx, internalFormat); 1866 if (format < 0) { 1867 _mesa_error(ctx, GL_INVALID_VALUE, 1868 "glCopyTexImage%dD(internalFormat)", dimensions); 1869 return GL_TRUE; 1870 } 1871 1872 /* NOTE: the format and type aren't really significant for 1873 * TestProxyTexImage(). Only the internalformat really matters. 1874 if (!_mesa_source_buffer_exists(ctx, format)) { 1875 _mesa_error(ctx, GL_INVALID_OPERATION, 1876 "glCopyTexImage%dD(missing readbuffer)", dimensions); 1877 return GL_TRUE; 1878 } 1879 1880 */ 1881 type = GL_FLOAT; 1882 1883 /* Check target and call ctx->Driver.TestProxyTexImage() to check the 1884 * level, width, height and depth. 1885 */ 1886 if (dimensions == 1) { 1887 if (target == GL_TEXTURE_1D) { 1888 sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_1D, 1889 level, internalFormat, 1890 format, type, 1891 width, 1, 1, border); 1892 } 1893 else { 1894 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" ); 1895 return GL_TRUE; 1896 } 1897 } 1898 else if (dimensions == 2) { 1899 if (target == GL_TEXTURE_2D) { 1900 sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_2D, 1901 level, internalFormat, 1902 format, type, 1903 width, height, 1, border); 1904 } 1905 else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 1906 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 1907 if (!ctx->Extensions.ARB_texture_cube_map) { 1908 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); 1909 return GL_TRUE; 1910 } 1911 sizeOK = (width == height) && 1912 ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_CUBE_MAP_ARB, 1913 level, internalFormat, format, type, 1914 width, height, 1, border); 1915 } 1916 else if (target == GL_TEXTURE_RECTANGLE_NV) { 1917 if (!ctx->Extensions.NV_texture_rectangle) { 1918 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); 1919 return GL_TRUE; 1920 } 1921 sizeOK = ctx->Driver.TestProxyTexImage(ctx, 1922 GL_PROXY_TEXTURE_RECTANGLE_NV, 1923 level, internalFormat, 1924 format, type, 1925 width, height, 1, border); 1926 } 1927 else if (target == GL_TEXTURE_1D_ARRAY_EXT) { 1928 if (!ctx->Extensions.MESA_texture_array) { 1929 _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)"); 1930 return GL_TRUE; 1931 } 1932 sizeOK = ctx->Driver.TestProxyTexImage(ctx, 1933 GL_PROXY_TEXTURE_1D_ARRAY_EXT, 1934 level, internalFormat, 1935 format, type, 1936 width, height, 1, border); 1937 } 1938 else { 1939 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); 1940 return GL_TRUE; 1941 } 1942 } 1943 else { 1944 _mesa_problem(ctx, "invalid dimensions in copytexture_error_check"); 1945 return GL_TRUE; 1946 } 1947 1948 if (!sizeOK) { 1949 if (dimensions == 1) { 1950 _mesa_error(ctx, GL_INVALID_VALUE, 1951 "glCopyTexImage1D(width=%d)", width); 1952 } 1953 else { 1954 ASSERT(dimensions == 2); 1955 _mesa_error(ctx, GL_INVALID_VALUE, 1956 "glCopyTexImage2D(width=%d, height=%d)", width, height); 1957 } 1958 return GL_TRUE; 1959 } 1960 1961 if (is_compressed_format(ctx, internalFormat)) { 1962 if (!target_can_be_compressed(ctx, target)) { 1963 _mesa_error(ctx, GL_INVALID_ENUM, 1964 "glCopyTexImage%d(target)", dimensions); 1965 return GL_TRUE; 1966 } 1967 if (border != 0) { 1968 _mesa_error(ctx, GL_INVALID_OPERATION, 1969 "glCopyTexImage%D(border!=0)", dimensions); 1970 return GL_TRUE; 1971 } 1972 } 1973 else if (is_depth_format(internalFormat)) { 1974 /* make sure we have depth/stencil buffers */ 1975 if (!ctx->ReadBuffer->_DepthBuffer) { 1976 _mesa_error(ctx, GL_INVALID_OPERATION, 1977 "glCopyTexImage%D(no depth)", dimensions); 1978 return GL_TRUE; 1979 } 1980 } 1981 else if (is_depthstencil_format(internalFormat)) { 1982 /* make sure we have depth/stencil buffers */ 1983 if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) { 1984 _mesa_error(ctx, GL_INVALID_OPERATION, 1985 "glCopyTexImage%D(no depth/stencil buffer)", dimensions); 1986 return GL_TRUE; 1987 } 1988 } 1989 1990 /* if we get here, the parameters are OK */ 1991 return GL_FALSE; 1992} 1993 1994 1995/** 1996 * Test glCopyTexSubImage[12]D() parameters for errors. 1997 * Note that this is the first part of error checking. 1998 * See also copytexsubimage_error_check2() below for the second part. 1999 * 2000 * \param ctx GL context. 2001 * \param dimensions texture image dimensions (must be 1, 2 or 3). 2002 * \param target texture target given by the user. 2003 * \param level image level given by the user. 2004 * 2005 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 2006 */ 2007static GLboolean 2008copytexsubimage_error_check1( GLcontext *ctx, GLuint dimensions, 2009 GLenum target, GLint level) 2010{ 2011 /* Check that the source buffer is complete */ 2012 if (ctx->ReadBuffer->Name) { 2013 _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer); 2014 if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 2015 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 2016 "glCopyTexImage%dD(invalid readbuffer)", dimensions); 2017 return GL_TRUE; 2018 } 2019 } 2020 2021 /* Check target */ 2022 if (dimensions == 1) { 2023 if (target != GL_TEXTURE_1D) { 2024 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" ); 2025 return GL_TRUE; 2026 } 2027 } 2028 else if (dimensions == 2) { 2029 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 2030 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 2031 if (!ctx->Extensions.ARB_texture_cube_map) { 2032 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); 2033 return GL_TRUE; 2034 } 2035 } 2036 else if (target == GL_TEXTURE_RECTANGLE_NV) { 2037 if (!ctx->Extensions.NV_texture_rectangle) { 2038 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); 2039 return GL_TRUE; 2040 } 2041 } 2042 else if (target == GL_TEXTURE_1D_ARRAY_EXT) { 2043 if (!ctx->Extensions.MESA_texture_array) { 2044 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); 2045 return GL_TRUE; 2046 } 2047 } 2048 else if (target != GL_TEXTURE_2D) { 2049 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); 2050 return GL_TRUE; 2051 } 2052 } 2053 else if (dimensions == 3) { 2054 if (((target != GL_TEXTURE_2D_ARRAY_EXT) || 2055 (!ctx->Extensions.MESA_texture_array)) 2056 && (target != GL_TEXTURE_3D)) { 2057 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" ); 2058 return GL_TRUE; 2059 } 2060 } 2061 2062 /* Check level */ 2063 if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 2064 _mesa_error(ctx, GL_INVALID_VALUE, 2065 "glCopyTexSubImage%dD(level=%d)", dimensions, level); 2066 return GL_TRUE; 2067 } 2068 2069 return GL_FALSE; 2070} 2071 2072 2073/** 2074 * Second part of error checking for glCopyTexSubImage[12]D(). 2075 * \param xoffset sub-image x offset given by the user. 2076 * \param yoffset sub-image y offset given by the user. 2077 * \param zoffset sub-image z offset given by the user. 2078 * \param width image width given by the user. 2079 * \param height image height given by the user. 2080 */ 2081static GLboolean 2082copytexsubimage_error_check2( GLcontext *ctx, GLuint dimensions, 2083 GLenum target, GLint level, 2084 GLint xoffset, GLint yoffset, GLint zoffset, 2085 GLsizei width, GLsizei height, 2086 const struct gl_texture_image *teximage ) 2087{ 2088 /* check that dest tex image exists */ 2089 if (!teximage) { 2090 _mesa_error(ctx, GL_INVALID_OPERATION, 2091 "glCopyTexSubImage%dD(undefined texture level: %d)", 2092 dimensions, level); 2093 return GL_TRUE; 2094 } 2095 2096 /* Check size */ 2097 if (width < 0) { 2098 _mesa_error(ctx, GL_INVALID_VALUE, 2099 "glCopyTexSubImage%dD(width=%d)", dimensions, width); 2100 return GL_TRUE; 2101 } 2102 if (dimensions > 1 && height < 0) { 2103 _mesa_error(ctx, GL_INVALID_VALUE, 2104 "glCopyTexSubImage%dD(height=%d)", dimensions, height); 2105 return GL_TRUE; 2106 } 2107 2108 /* check x/y offsets */ 2109 if (xoffset < -((GLint)teximage->Border)) { 2110 _mesa_error(ctx, GL_INVALID_VALUE, 2111 "glCopyTexSubImage%dD(xoffset=%d)", dimensions, xoffset); 2112 return GL_TRUE; 2113 } 2114 if (xoffset + width > (GLint) (teximage->Width + teximage->Border)) { 2115 _mesa_error(ctx, GL_INVALID_VALUE, 2116 "glCopyTexSubImage%dD(xoffset+width)", dimensions); 2117 return GL_TRUE; 2118 } 2119 if (dimensions > 1) { 2120 if (yoffset < -((GLint)teximage->Border)) { 2121 _mesa_error(ctx, GL_INVALID_VALUE, 2122 "glCopyTexSubImage%dD(yoffset=%d)", dimensions, yoffset); 2123 return GL_TRUE; 2124 } 2125 /* NOTE: we're adding the border here, not subtracting! */ 2126 if (yoffset + height > (GLint) (teximage->Height + teximage->Border)) { 2127 _mesa_error(ctx, GL_INVALID_VALUE, 2128 "glCopyTexSubImage%dD(yoffset+height)", dimensions); 2129 return GL_TRUE; 2130 } 2131 } 2132 2133 /* check z offset */ 2134 if (dimensions > 2) { 2135 if (zoffset < -((GLint)teximage->Border)) { 2136 _mesa_error(ctx, GL_INVALID_VALUE, 2137 "glCopyTexSubImage%dD(zoffset)", dimensions); 2138 return GL_TRUE; 2139 } 2140 if (zoffset > (GLint) (teximage->Depth + teximage->Border)) { 2141 _mesa_error(ctx, GL_INVALID_VALUE, 2142 "glCopyTexSubImage%dD(zoffset+depth)", dimensions); 2143 return GL_TRUE; 2144 } 2145 } 2146 2147 if (teximage->IsCompressed) { 2148 if (!target_can_be_compressed(ctx, target)) { 2149 _mesa_error(ctx, GL_INVALID_ENUM, 2150 "glCopyTexSubImage%d(target)", dimensions); 2151 return GL_TRUE; 2152 } 2153 /* offset must be multiple of 4 */ 2154 if ((xoffset & 3) || (yoffset & 3)) { 2155 _mesa_error(ctx, GL_INVALID_VALUE, 2156 "glCopyTexSubImage%D(xoffset or yoffset)", dimensions); 2157 return GL_TRUE; 2158 } 2159 /* size must be multiple of 4 */ 2160 if ((width & 3) != 0 && (GLuint) width != teximage->Width) { 2161 _mesa_error(ctx, GL_INVALID_VALUE, 2162 "glCopyTexSubImage%D(width)", dimensions); 2163 return GL_TRUE; 2164 } 2165 if ((height & 3) != 0 && (GLuint) height != teximage->Height) { 2166 _mesa_error(ctx, GL_INVALID_VALUE, 2167 "glCopyTexSubImage%D(height)", dimensions); 2168 return GL_TRUE; 2169 } 2170 } 2171 2172 if (teximage->InternalFormat == GL_YCBCR_MESA) { 2173 _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTexSubImage2D"); 2174 return GL_TRUE; 2175 } 2176 2177 if (!_mesa_source_buffer_exists(ctx, teximage->_BaseFormat)) { 2178 _mesa_error(ctx, GL_INVALID_OPERATION, 2179 "glCopyTexSubImage%dD(missing readbuffer, format=0x%x)", 2180 dimensions, teximage->_BaseFormat); 2181 return GL_TRUE; 2182 } 2183 2184 if (teximage->_BaseFormat == GL_DEPTH_COMPONENT) { 2185 if (!ctx->ReadBuffer->_DepthBuffer) { 2186 _mesa_error(ctx, GL_INVALID_OPERATION, 2187 "glCopyTexSubImage%D(no depth buffer)", 2188 dimensions); 2189 return GL_TRUE; 2190 } 2191 } 2192 else if (teximage->_BaseFormat == GL_DEPTH_STENCIL_EXT) { 2193 if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) { 2194 _mesa_error(ctx, GL_INVALID_OPERATION, 2195 "glCopyTexSubImage%D(no depth/stencil buffer)", 2196 dimensions); 2197 return GL_TRUE; 2198 } 2199 } 2200 2201 /* if we get here, the parameters are OK */ 2202 return GL_FALSE; 2203} 2204 2205 2206/** 2207 * Do error checking for a glGetTexImage() call. 2208 * \return GL_TRUE if any error, GL_FALSE if no errors. 2209 */ 2210static GLboolean 2211getteximage_error_check(GLcontext *ctx, GLenum target, GLint level, 2212 GLenum format, GLenum type, GLvoid *pixels ) 2213{ 2214 const struct gl_texture_unit *texUnit; 2215 struct gl_texture_object *texObj; 2216 struct gl_texture_image *texImage; 2217 const GLuint maxLevels = _mesa_max_texture_levels(ctx, target); 2218 2219 ASSERT(maxLevels > 0); /* 0 indicates bad target, caught above */ 2220 2221 if (level < 0 || level >= maxLevels) { 2222 _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" ); 2223 return GL_TRUE; 2224 } 2225 2226 if (_mesa_sizeof_packed_type(type) <= 0) { 2227 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" ); 2228 return GL_TRUE; 2229 } 2230 2231 if (_mesa_components_in_format(format) <= 0 || 2232 format == GL_STENCIL_INDEX) { 2233 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" ); 2234 return GL_TRUE; 2235 } 2236 2237 if (!ctx->Extensions.EXT_paletted_texture && is_index_format(format)) { 2238 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 2239 return GL_TRUE; 2240 } 2241 2242 if (!ctx->Extensions.ARB_depth_texture && is_depth_format(format)) { 2243 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 2244 return GL_TRUE; 2245 } 2246 2247 if (!ctx->Extensions.MESA_ycbcr_texture && is_ycbcr_format(format)) { 2248 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 2249 return GL_TRUE; 2250 } 2251 2252 if (!ctx->Extensions.EXT_packed_depth_stencil 2253 && is_depthstencil_format(format)) { 2254 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 2255 return GL_TRUE; 2256 } 2257 2258 if (!ctx->Extensions.ATI_envmap_bumpmap 2259 && is_dudv_format(format)) { 2260 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 2261 return GL_TRUE; 2262 } 2263 2264 2265 texUnit = get_current_tex_unit(ctx); 2266 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2267 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 2268 if (!texImage) { 2269 /* out of memory */ 2270 return GL_TRUE; 2271 } 2272 2273 /* Make sure the requested image format is compatible with the 2274 * texture's format. Note that a color index texture can be converted 2275 * to RGBA so that combo is allowed. 2276 */ 2277 if (_mesa_is_color_format(format) 2278 && !_mesa_is_color_format(texImage->TexFormat->BaseFormat) 2279 && !is_index_format(texImage->TexFormat->BaseFormat)) { 2280 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 2281 return GL_TRUE; 2282 } 2283 else if (is_index_format(format) 2284 && !is_index_format(texImage->TexFormat->BaseFormat)) { 2285 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 2286 return GL_TRUE; 2287 } 2288 else if (is_depth_format(format) 2289 && !is_depth_format(texImage->TexFormat->BaseFormat) 2290 && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) { 2291 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 2292 return GL_TRUE; 2293 } 2294 else if (is_ycbcr_format(format) 2295 && !is_ycbcr_format(texImage->TexFormat->BaseFormat)) { 2296 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 2297 return GL_TRUE; 2298 } 2299 else if (is_depthstencil_format(format) 2300 && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) { 2301 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 2302 return GL_TRUE; 2303 } 2304 else if (is_dudv_format(format) 2305 && !is_dudv_format(texImage->TexFormat->BaseFormat)) { 2306 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 2307 return GL_TRUE; 2308 } 2309 2310 if (ctx->Pack.BufferObj->Name) { 2311 /* packing texture image into a PBO */ 2312 const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2; 2313 if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width, 2314 texImage->Height, texImage->Depth, 2315 format, type, pixels)) { 2316 _mesa_error(ctx, GL_INVALID_OPERATION, 2317 "glGetTexImage(invalid PBO access)"); 2318 return GL_TRUE; 2319 } 2320 } 2321 2322 return GL_FALSE; 2323} 2324 2325 2326 2327/** 2328 * Get texture image. Called by glGetTexImage. 2329 * 2330 * \param target texture target. 2331 * \param level image level. 2332 * \param format pixel data format for returned image. 2333 * \param type pixel data type for returned image. 2334 * \param pixels returned pixel data. 2335 */ 2336void GLAPIENTRY 2337_mesa_GetTexImage( GLenum target, GLint level, GLenum format, 2338 GLenum type, GLvoid *pixels ) 2339{ 2340 const struct gl_texture_unit *texUnit; 2341 struct gl_texture_object *texObj; 2342 GET_CURRENT_CONTEXT(ctx); 2343 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2344 2345 texUnit = get_current_tex_unit(ctx); 2346 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2347 if (!texObj || _mesa_is_proxy_texture(target)) { 2348 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)"); 2349 return; 2350 } 2351 2352 if (getteximage_error_check(ctx, target, level, format, type, pixels)) { 2353 return; 2354 } 2355 2356 _mesa_lock_texture(ctx, texObj); 2357 { 2358 struct gl_texture_image *texImage = 2359 _mesa_select_tex_image(ctx, texObj, target, level); 2360 2361 /* typically, this will call _mesa_get_teximage() */ 2362 ctx->Driver.GetTexImage(ctx, target, level, format, type, pixels, 2363 texObj, texImage); 2364 } 2365 _mesa_unlock_texture(ctx, texObj); 2366} 2367 2368 2369/** Callback info for walking over FBO hash table */ 2370struct cb_info 2371{ 2372 GLcontext *ctx; 2373 struct gl_texture_object *texObj; 2374 GLuint level, face; 2375}; 2376 2377 2378/** 2379 * Check render to texture callback. Called from _mesa_HashWalk(). 2380 */ 2381static void 2382check_rtt_cb(GLuint key, void *data, void *userData) 2383{ 2384 struct gl_framebuffer *fb = (struct gl_framebuffer *) data; 2385 const struct cb_info *info = (struct cb_info *) userData; 2386 GLcontext *ctx = info->ctx; 2387 const struct gl_texture_object *texObj = info->texObj; 2388 const GLuint level = info->level, face = info->face; 2389 2390 /* If this is a user-created FBO */ 2391 if (fb->Name) { 2392 GLuint i; 2393 /* check if any of the FBO's attachments point to 'texObj' */ 2394 for (i = 0; i < BUFFER_COUNT; i++) { 2395 struct gl_renderbuffer_attachment *att = fb->Attachment + i; 2396 if (att->Type == GL_TEXTURE && 2397 att->Texture == texObj && 2398 att->TextureLevel == level && 2399 att->CubeMapFace == face) { 2400 ASSERT(att->Texture->Image[att->CubeMapFace][att->TextureLevel]); 2401 /* Tell driver about the new renderbuffer texture */ 2402 ctx->Driver.RenderTexture(ctx, ctx->DrawBuffer, att); 2403 /* Mark fb status as indeterminate to force re-validation */ 2404 fb->_Status = 0; 2405 } 2406 } 2407 } 2408} 2409 2410 2411/** 2412 * When a texture image is specified we have to check if it's bound to 2413 * any framebuffer objects (render to texture) in order to detect changes 2414 * in size or format since that effects FBO completeness. 2415 * Any FBOs rendering into the texture must be re-validated. 2416 */ 2417static void 2418update_fbo_texture(GLcontext *ctx, struct gl_texture_object *texObj, 2419 GLuint face, GLuint level) 2420{ 2421 /* Only check this texture if it's been marked as RenderToTexture */ 2422 if (texObj->_RenderToTexture) { 2423 struct cb_info info; 2424 info.ctx = ctx; 2425 info.texObj = texObj; 2426 info.level = level; 2427 info.face = face; 2428 _mesa_HashWalk(ctx->Shared->FrameBuffers, check_rtt_cb, &info); 2429 } 2430} 2431 2432 2433/** Debug helper: override the user-requested internal format */ 2434static GLenum 2435override_internal_format(GLenum internalFormat, GLint width, GLint height) 2436{ 2437#if 0 2438 if (internalFormat == GL_RGBA16F_ARB || 2439 internalFormat == GL_RGBA32F_ARB) { 2440 printf("Convert rgba float tex to int %d x %d\n", width, height); 2441 return GL_RGBA; 2442 } 2443 else if (internalFormat == GL_RGB16F_ARB || 2444 internalFormat == GL_RGB32F_ARB) { 2445 printf("Convert rgb float tex to int %d x %d\n", width, height); 2446 return GL_RGB; 2447 } 2448 else if (internalFormat == GL_LUMINANCE_ALPHA16F_ARB || 2449 internalFormat == GL_LUMINANCE_ALPHA32F_ARB) { 2450 printf("Convert luminance float tex to int %d x %d\n", width, height); 2451 return GL_LUMINANCE_ALPHA; 2452 } 2453 else if (internalFormat == GL_LUMINANCE16F_ARB || 2454 internalFormat == GL_LUMINANCE32F_ARB) { 2455 printf("Convert luminance float tex to int %d x %d\n", width, height); 2456 return GL_LUMINANCE; 2457 } 2458 else if (internalFormat == GL_ALPHA16F_ARB || 2459 internalFormat == GL_ALPHA32F_ARB) { 2460 printf("Convert luminance float tex to int %d x %d\n", width, height); 2461 return GL_ALPHA; 2462 } 2463 /* 2464 else if (internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) { 2465 internalFormat = GL_RGBA; 2466 } 2467 */ 2468 else { 2469 return internalFormat; 2470 } 2471#else 2472 return internalFormat; 2473#endif 2474} 2475 2476 2477/* 2478 * Called from the API. Note that width includes the border. 2479 */ 2480void GLAPIENTRY 2481_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat, 2482 GLsizei width, GLint border, GLenum format, 2483 GLenum type, const GLvoid *pixels ) 2484{ 2485 GLsizei postConvWidth = width; 2486 GET_CURRENT_CONTEXT(ctx); 2487 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2488 2489 internalFormat = override_internal_format(internalFormat, width, 1); 2490 2491#if FEATURE_convolve 2492 if (_mesa_is_color_format(internalFormat)) { 2493 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 2494 } 2495#endif 2496 2497 if (target == GL_TEXTURE_1D) { 2498 /* non-proxy target */ 2499 struct gl_texture_unit *texUnit; 2500 struct gl_texture_object *texObj; 2501 struct gl_texture_image *texImage; 2502 const GLuint face = _mesa_tex_target_to_face(target); 2503 2504 if (texture_error_check(ctx, target, level, internalFormat, 2505 format, type, 1, postConvWidth, 1, 1, border)) { 2506 return; /* error was recorded */ 2507 } 2508 2509 if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) 2510 _mesa_update_state(ctx); 2511 2512 texUnit = get_current_tex_unit(ctx); 2513 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2514 _mesa_lock_texture(ctx, texObj); 2515 { 2516 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 2517 if (!texImage) { 2518 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D"); 2519 goto out; 2520 } 2521 2522 if (texImage->Data) { 2523 ctx->Driver.FreeTexImageData( ctx, texImage ); 2524 } 2525 2526 ASSERT(texImage->Data == NULL); 2527 2528 clear_teximage_fields(texImage); /* not really needed, but helpful */ 2529 _mesa_init_teximage_fields(ctx, target, texImage, 2530 postConvWidth, 1, 1, 2531 border, internalFormat); 2532 2533 ASSERT(ctx->Driver.TexImage1D); 2534 2535 /* Give the texture to the driver! <pixels> may be null! */ 2536 (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat, 2537 width, border, format, type, pixels, 2538 &ctx->Unpack, texObj, texImage); 2539 2540 ASSERT(texImage->TexFormat); 2541 2542 update_fbo_texture(ctx, texObj, face, level); 2543 2544 /* state update */ 2545 texObj->_Complete = GL_FALSE; 2546 ctx->NewState |= _NEW_TEXTURE; 2547 } 2548 out: 2549 _mesa_unlock_texture(ctx, texObj); 2550 } 2551 else if (target == GL_PROXY_TEXTURE_1D) { 2552 /* Proxy texture: check for errors and update proxy state */ 2553 struct gl_texture_image *texImage; 2554 texImage = _mesa_get_proxy_tex_image(ctx, target, level); 2555 if (texture_error_check(ctx, target, level, internalFormat, 2556 format, type, 1, postConvWidth, 1, 1, border)) { 2557 /* when error, clear all proxy texture image parameters */ 2558 if (texImage) 2559 clear_teximage_fields(texImage); 2560 } 2561 else { 2562 /* no error, set the tex image parameters */ 2563 ASSERT(texImage); 2564 _mesa_init_teximage_fields(ctx, target, texImage, 2565 postConvWidth, 1, 1, 2566 border, internalFormat); 2567 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx, 2568 internalFormat, format, type); 2569 } 2570 } 2571 else { 2572 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); 2573 return; 2574 } 2575} 2576 2577 2578void GLAPIENTRY 2579_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat, 2580 GLsizei width, GLsizei height, GLint border, 2581 GLenum format, GLenum type, 2582 const GLvoid *pixels ) 2583{ 2584 GLsizei postConvWidth = width, postConvHeight = height; 2585 GET_CURRENT_CONTEXT(ctx); 2586 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2587 2588 internalFormat = override_internal_format(internalFormat, width, height); 2589 2590#if FEATURE_convolve 2591 if (_mesa_is_color_format(internalFormat)) { 2592 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, 2593 &postConvHeight); 2594 } 2595#endif 2596 2597 if (target == GL_TEXTURE_2D || 2598 (ctx->Extensions.ARB_texture_cube_map && 2599 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 2600 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) || 2601 (ctx->Extensions.NV_texture_rectangle && 2602 target == GL_TEXTURE_RECTANGLE_NV) || 2603 (ctx->Extensions.MESA_texture_array && 2604 target == GL_TEXTURE_1D_ARRAY_EXT)) { 2605 /* non-proxy target */ 2606 struct gl_texture_unit *texUnit; 2607 struct gl_texture_object *texObj; 2608 struct gl_texture_image *texImage; 2609 const GLuint face = _mesa_tex_target_to_face(target); 2610 2611 if (texture_error_check(ctx, target, level, internalFormat, 2612 format, type, 2, postConvWidth, postConvHeight, 2613 1, border)) { 2614 return; /* error was recorded */ 2615 } 2616 2617 if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) 2618 _mesa_update_state(ctx); 2619 2620 texUnit = get_current_tex_unit(ctx); 2621 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2622 _mesa_lock_texture(ctx, texObj); 2623 { 2624 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 2625 if (!texImage) { 2626 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); 2627 goto out; 2628 } 2629 2630 if (texImage->Data) { 2631 ctx->Driver.FreeTexImageData( ctx, texImage ); 2632 } 2633 2634 ASSERT(texImage->Data == NULL); 2635 clear_teximage_fields(texImage); /* not really needed, but helpful */ 2636 _mesa_init_teximage_fields(ctx, target, texImage, 2637 postConvWidth, postConvHeight, 1, 2638 border, internalFormat); 2639 2640 ASSERT(ctx->Driver.TexImage2D); 2641 2642 /* Give the texture to the driver! <pixels> may be null! */ 2643 (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat, 2644 width, height, border, format, type, pixels, 2645 &ctx->Unpack, texObj, texImage); 2646 2647 ASSERT(texImage->TexFormat); 2648 2649 update_fbo_texture(ctx, texObj, face, level); 2650 2651 /* state update */ 2652 texObj->_Complete = GL_FALSE; 2653 ctx->NewState |= _NEW_TEXTURE; 2654 } 2655 out: 2656 _mesa_unlock_texture(ctx, texObj); 2657 } 2658 else if (target == GL_PROXY_TEXTURE_2D || 2659 (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB && 2660 ctx->Extensions.ARB_texture_cube_map) || 2661 (target == GL_PROXY_TEXTURE_RECTANGLE_NV && 2662 ctx->Extensions.NV_texture_rectangle) || 2663 (ctx->Extensions.MESA_texture_array && 2664 target == GL_PROXY_TEXTURE_1D_ARRAY_EXT)) { 2665 /* Proxy texture: check for errors and update proxy state */ 2666 struct gl_texture_image *texImage; 2667 texImage = _mesa_get_proxy_tex_image(ctx, target, level); 2668 if (texture_error_check(ctx, target, level, internalFormat, 2669 format, type, 2, postConvWidth, postConvHeight, 2670 1, border)) { 2671 /* when error, clear all proxy texture image parameters */ 2672 if (texImage) 2673 clear_teximage_fields(texImage); 2674 } 2675 else { 2676 /* no error, set the tex image parameters */ 2677 _mesa_init_teximage_fields(ctx, target, texImage, 2678 postConvWidth, postConvHeight, 1, 2679 border, internalFormat); 2680 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx, 2681 internalFormat, format, type); 2682 } 2683 } 2684 else { 2685 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" ); 2686 return; 2687 } 2688} 2689 2690 2691/* 2692 * Called by the API or display list executor. 2693 * Note that width and height include the border. 2694 */ 2695void GLAPIENTRY 2696_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat, 2697 GLsizei width, GLsizei height, GLsizei depth, 2698 GLint border, GLenum format, GLenum type, 2699 const GLvoid *pixels ) 2700{ 2701 GET_CURRENT_CONTEXT(ctx); 2702 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2703 2704 internalFormat = override_internal_format(internalFormat, width, height); 2705 2706 if (target == GL_TEXTURE_3D || 2707 (ctx->Extensions.MESA_texture_array && 2708 target == GL_TEXTURE_2D_ARRAY_EXT)) { 2709 /* non-proxy target */ 2710 struct gl_texture_unit *texUnit; 2711 struct gl_texture_object *texObj; 2712 struct gl_texture_image *texImage; 2713 const GLuint face = _mesa_tex_target_to_face(target); 2714 2715 if (texture_error_check(ctx, target, level, (GLint) internalFormat, 2716 format, type, 3, width, height, depth, border)) { 2717 return; /* error was recorded */ 2718 } 2719 2720 if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) 2721 _mesa_update_state(ctx); 2722 2723 texUnit = get_current_tex_unit(ctx); 2724 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2725 _mesa_lock_texture(ctx, texObj); 2726 { 2727 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 2728 if (!texImage) { 2729 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D"); 2730 goto out; 2731 } 2732 2733 if (texImage->Data) { 2734 ctx->Driver.FreeTexImageData( ctx, texImage ); 2735 } 2736 2737 ASSERT(texImage->Data == NULL); 2738 clear_teximage_fields(texImage); /* not really needed, but helpful */ 2739 _mesa_init_teximage_fields(ctx, target, texImage, 2740 width, height, depth, 2741 border, internalFormat); 2742 2743 ASSERT(ctx->Driver.TexImage3D); 2744 2745 /* Give the texture to the driver! <pixels> may be null! */ 2746 (*ctx->Driver.TexImage3D)(ctx, target, level, internalFormat, 2747 width, height, depth, border, format, type, 2748 pixels, &ctx->Unpack, texObj, texImage); 2749 2750 ASSERT(texImage->TexFormat); 2751 2752 update_fbo_texture(ctx, texObj, face, level); 2753 2754 /* state update */ 2755 texObj->_Complete = GL_FALSE; 2756 ctx->NewState |= _NEW_TEXTURE; 2757 } 2758 out: 2759 _mesa_unlock_texture(ctx, texObj); 2760 } 2761 else if (target == GL_PROXY_TEXTURE_3D || 2762 (ctx->Extensions.MESA_texture_array && 2763 target == GL_PROXY_TEXTURE_2D_ARRAY_EXT)) { 2764 /* Proxy texture: check for errors and update proxy state */ 2765 struct gl_texture_image *texImage; 2766 texImage = _mesa_get_proxy_tex_image(ctx, target, level); 2767 if (texture_error_check(ctx, target, level, internalFormat, 2768 format, type, 3, width, height, depth, border)) { 2769 /* when error, clear all proxy texture image parameters */ 2770 if (texImage) 2771 clear_teximage_fields(texImage); 2772 } 2773 else { 2774 /* no error, set the tex image parameters */ 2775 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 2776 depth, border, internalFormat); 2777 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx, 2778 internalFormat, format, type); 2779 } 2780 } 2781 else { 2782 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" ); 2783 return; 2784 } 2785} 2786 2787 2788void GLAPIENTRY 2789_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat, 2790 GLsizei width, GLsizei height, GLsizei depth, 2791 GLint border, GLenum format, GLenum type, 2792 const GLvoid *pixels ) 2793{ 2794 _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height, 2795 depth, border, format, type, pixels); 2796} 2797 2798 2799 2800void GLAPIENTRY 2801_mesa_TexSubImage1D( GLenum target, GLint level, 2802 GLint xoffset, GLsizei width, 2803 GLenum format, GLenum type, 2804 const GLvoid *pixels ) 2805{ 2806 GLsizei postConvWidth = width; 2807 struct gl_texture_unit *texUnit; 2808 struct gl_texture_object *texObj; 2809 struct gl_texture_image *texImage = NULL; 2810 GET_CURRENT_CONTEXT(ctx); 2811 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2812 2813 if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) 2814 _mesa_update_state(ctx); 2815 2816#if FEATURE_convolve 2817 /* XXX should test internal format */ 2818 if (_mesa_is_color_format(format)) { 2819 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 2820 } 2821#endif 2822 2823 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0, 2824 postConvWidth, 1, 1, format, type)) { 2825 return; /* error was detected */ 2826 } 2827 2828 2829 texUnit = get_current_tex_unit(ctx); 2830 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2831 assert(texObj); 2832 2833 _mesa_lock_texture(ctx, texObj); 2834 { 2835 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 2836 2837 if (subtexture_error_check2(ctx, 1, target, level, xoffset, 0, 0, 2838 postConvWidth, 1, 1, format, type, texImage)) { 2839 goto out; /* error was detected */ 2840 } 2841 2842 if (width == 0) 2843 goto out; /* no-op, not an error */ 2844 2845 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 2846 xoffset += texImage->Border; 2847 2848 ASSERT(ctx->Driver.TexSubImage1D); 2849 (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width, 2850 format, type, pixels, &ctx->Unpack, 2851 texObj, texImage); 2852 ctx->NewState |= _NEW_TEXTURE; 2853 } 2854 out: 2855 _mesa_unlock_texture(ctx, texObj); 2856} 2857 2858 2859void GLAPIENTRY 2860_mesa_TexSubImage2D( GLenum target, GLint level, 2861 GLint xoffset, GLint yoffset, 2862 GLsizei width, GLsizei height, 2863 GLenum format, GLenum type, 2864 const GLvoid *pixels ) 2865{ 2866 GLsizei postConvWidth = width, postConvHeight = height; 2867 struct gl_texture_unit *texUnit; 2868 struct gl_texture_object *texObj; 2869 struct gl_texture_image *texImage; 2870 GET_CURRENT_CONTEXT(ctx); 2871 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2872 2873 if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) 2874 _mesa_update_state(ctx); 2875 2876#if FEATURE_convolve 2877 /* XXX should test internal format */ 2878 if (_mesa_is_color_format(format)) { 2879 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, 2880 &postConvHeight); 2881 } 2882#endif 2883 2884 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0, 2885 postConvWidth, postConvHeight, 1, format, type)) { 2886 return; /* error was detected */ 2887 } 2888 2889 texUnit = get_current_tex_unit(ctx); 2890 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2891 _mesa_lock_texture(ctx, texObj); 2892 { 2893 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 2894 2895 if (subtexture_error_check2(ctx, 2, target, level, xoffset, yoffset, 0, 2896 postConvWidth, postConvHeight, 1, format, type, 2897 texImage)) { 2898 goto out; /* error was detected */ 2899 } 2900 2901 if (width == 0 || height == 0) 2902 goto out; /* no-op, not an error */ 2903 2904 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 2905 xoffset += texImage->Border; 2906 yoffset += texImage->Border; 2907 2908 ASSERT(ctx->Driver.TexSubImage2D); 2909 (*ctx->Driver.TexSubImage2D)(ctx, target, level, xoffset, yoffset, 2910 width, height, format, type, pixels, 2911 &ctx->Unpack, texObj, texImage); 2912 ctx->NewState |= _NEW_TEXTURE; 2913 } 2914 out: 2915 _mesa_unlock_texture(ctx, texObj); 2916} 2917 2918 2919 2920void GLAPIENTRY 2921_mesa_TexSubImage3D( GLenum target, GLint level, 2922 GLint xoffset, GLint yoffset, GLint zoffset, 2923 GLsizei width, GLsizei height, GLsizei depth, 2924 GLenum format, GLenum type, 2925 const GLvoid *pixels ) 2926{ 2927 struct gl_texture_unit *texUnit; 2928 struct gl_texture_object *texObj; 2929 struct gl_texture_image *texImage; 2930 GET_CURRENT_CONTEXT(ctx); 2931 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2932 2933 if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) 2934 _mesa_update_state(ctx); 2935 2936 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset, 2937 width, height, depth, format, type)) { 2938 return; /* error was detected */ 2939 } 2940 2941 texUnit = get_current_tex_unit(ctx); 2942 texObj = _mesa_select_tex_object(ctx, texUnit, target); 2943 2944 _mesa_lock_texture(ctx, texObj); 2945 { 2946 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 2947 2948 if (subtexture_error_check2(ctx, 3, target, level, xoffset, yoffset, zoffset, 2949 width, height, depth, format, type, texImage)) { 2950 goto out; /* error was detected */ 2951 } 2952 2953 if (width == 0 || height == 0 || height == 0) 2954 goto out; /* no-op, not an error */ 2955 2956 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 2957 xoffset += texImage->Border; 2958 yoffset += texImage->Border; 2959 zoffset += texImage->Border; 2960 2961 ASSERT(ctx->Driver.TexSubImage3D); 2962 (*ctx->Driver.TexSubImage3D)(ctx, target, level, 2963 xoffset, yoffset, zoffset, 2964 width, height, depth, 2965 format, type, pixels, 2966 &ctx->Unpack, texObj, texImage ); 2967 ctx->NewState |= _NEW_TEXTURE; 2968 } 2969 out: 2970 _mesa_unlock_texture(ctx, texObj); 2971} 2972 2973 2974 2975void GLAPIENTRY 2976_mesa_CopyTexImage1D( GLenum target, GLint level, 2977 GLenum internalFormat, 2978 GLint x, GLint y, 2979 GLsizei width, GLint border ) 2980{ 2981 struct gl_texture_unit *texUnit; 2982 struct gl_texture_object *texObj; 2983 struct gl_texture_image *texImage; 2984 GLsizei postConvWidth = width; 2985 const GLuint face = _mesa_tex_target_to_face(target); 2986 GET_CURRENT_CONTEXT(ctx); 2987 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2988 2989 if (ctx->NewState & NEW_COPY_TEX_STATE) 2990 _mesa_update_state(ctx); 2991 2992#if FEATURE_convolve 2993 if (_mesa_is_color_format(internalFormat)) { 2994 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 2995 } 2996#endif 2997 2998 if (copytexture_error_check(ctx, 1, target, level, internalFormat, 2999 postConvWidth, 1, border)) 3000 return; 3001 3002 texUnit = get_current_tex_unit(ctx); 3003 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3004 _mesa_lock_texture(ctx, texObj); 3005 { 3006 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 3007 if (!texImage) { 3008 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D"); 3009 goto out; 3010 } 3011 3012 if (texImage->Data) { 3013 ctx->Driver.FreeTexImageData( ctx, texImage ); 3014 } 3015 3016 ASSERT(texImage->Data == NULL); 3017 3018 clear_teximage_fields(texImage); /* not really needed, but helpful */ 3019 _mesa_init_teximage_fields(ctx, target, texImage, postConvWidth, 1, 1, 3020 border, internalFormat); 3021 3022 3023 ASSERT(ctx->Driver.CopyTexImage1D); 3024 (*ctx->Driver.CopyTexImage1D)(ctx, target, level, internalFormat, 3025 x, y, width, border); 3026 3027 ASSERT(texImage->TexFormat); 3028 3029 update_fbo_texture(ctx, texObj, face, level); 3030 3031 /* state update */ 3032 texObj->_Complete = GL_FALSE; 3033 ctx->NewState |= _NEW_TEXTURE; 3034 } 3035 out: 3036 _mesa_unlock_texture(ctx, texObj); 3037} 3038 3039 3040 3041void GLAPIENTRY 3042_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat, 3043 GLint x, GLint y, GLsizei width, GLsizei height, 3044 GLint border ) 3045{ 3046 struct gl_texture_unit *texUnit; 3047 struct gl_texture_object *texObj; 3048 struct gl_texture_image *texImage; 3049 GLsizei postConvWidth = width, postConvHeight = height; 3050 const GLuint face = _mesa_tex_target_to_face(target); 3051 GET_CURRENT_CONTEXT(ctx); 3052 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3053 3054 if (ctx->NewState & NEW_COPY_TEX_STATE) 3055 _mesa_update_state(ctx); 3056 3057#if FEATURE_convolve 3058 if (_mesa_is_color_format(internalFormat)) { 3059 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, 3060 &postConvHeight); 3061 } 3062#endif 3063 3064 if (copytexture_error_check(ctx, 2, target, level, internalFormat, 3065 postConvWidth, postConvHeight, border)) 3066 return; 3067 3068 texUnit = get_current_tex_unit(ctx); 3069 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3070 3071 _mesa_lock_texture(ctx, texObj); 3072 { 3073 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 3074 3075 if (!texImage) { 3076 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D"); 3077 goto out; 3078 } 3079 3080 if (texImage->Data) { 3081 ctx->Driver.FreeTexImageData( ctx, texImage ); 3082 } 3083 3084 ASSERT(texImage->Data == NULL); 3085 3086 clear_teximage_fields(texImage); /* not really needed, but helpful */ 3087 _mesa_init_teximage_fields(ctx, target, texImage, 3088 postConvWidth, postConvHeight, 1, 3089 border, internalFormat); 3090 3091 ASSERT(ctx->Driver.CopyTexImage2D); 3092 (*ctx->Driver.CopyTexImage2D)(ctx, target, level, internalFormat, 3093 x, y, width, height, border); 3094 3095 ASSERT(texImage->TexFormat); 3096 3097 update_fbo_texture(ctx, texObj, face, level); 3098 3099 /* state update */ 3100 texObj->_Complete = GL_FALSE; 3101 ctx->NewState |= _NEW_TEXTURE; 3102 } 3103 out: 3104 _mesa_unlock_texture(ctx, texObj); 3105} 3106 3107 3108void GLAPIENTRY 3109_mesa_CopyTexSubImage1D( GLenum target, GLint level, 3110 GLint xoffset, GLint x, GLint y, GLsizei width ) 3111{ 3112 struct gl_texture_unit *texUnit; 3113 struct gl_texture_object *texObj; 3114 struct gl_texture_image *texImage; 3115 GLsizei postConvWidth = width; 3116 GLint yoffset = 0; 3117 GLsizei height = 1; 3118 3119 GET_CURRENT_CONTEXT(ctx); 3120 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3121 3122 if (ctx->NewState & NEW_COPY_TEX_STATE) 3123 _mesa_update_state(ctx); 3124 3125 if (copytexsubimage_error_check1(ctx, 1, target, level)) 3126 return; 3127 3128 texUnit = get_current_tex_unit(ctx); 3129 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3130 3131 _mesa_lock_texture(ctx, texObj); 3132 { 3133 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3134 3135#if FEATURE_convolve 3136 if (texImage && _mesa_is_color_format(texImage->InternalFormat)) { 3137 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 3138 } 3139#endif 3140 3141 if (copytexsubimage_error_check2(ctx, 1, target, level, 3142 xoffset, 0, 0, postConvWidth, 1, 3143 texImage)) 3144 goto out; 3145 3146 3147 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 3148 xoffset += texImage->Border; 3149 3150 if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, 3151 &width, &height)) { 3152 ASSERT(ctx->Driver.CopyTexSubImage1D); 3153 ctx->Driver.CopyTexSubImage1D(ctx, target, level, 3154 xoffset, x, y, width); 3155 } 3156 3157 ctx->NewState |= _NEW_TEXTURE; 3158 } 3159 out: 3160 _mesa_unlock_texture(ctx, texObj); 3161} 3162 3163 3164 3165void GLAPIENTRY 3166_mesa_CopyTexSubImage2D( GLenum target, GLint level, 3167 GLint xoffset, GLint yoffset, 3168 GLint x, GLint y, GLsizei width, GLsizei height ) 3169{ 3170 struct gl_texture_unit *texUnit; 3171 struct gl_texture_object *texObj; 3172 struct gl_texture_image *texImage; 3173 GLsizei postConvWidth = width, postConvHeight = height; 3174 GET_CURRENT_CONTEXT(ctx); 3175 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3176 3177 if (ctx->NewState & NEW_COPY_TEX_STATE) 3178 _mesa_update_state(ctx); 3179 3180 if (copytexsubimage_error_check1(ctx, 2, target, level)) 3181 return; 3182 3183 texUnit = get_current_tex_unit(ctx); 3184 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3185 3186 _mesa_lock_texture(ctx, texObj); 3187 { 3188 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3189 3190#if FEATURE_convolve 3191 if (texImage && _mesa_is_color_format(texImage->InternalFormat)) { 3192 _mesa_adjust_image_for_convolution(ctx, 2, 3193 &postConvWidth, &postConvHeight); 3194 } 3195#endif 3196 3197 if (copytexsubimage_error_check2(ctx, 2, target, level, xoffset, yoffset, 0, 3198 postConvWidth, postConvHeight, texImage)) 3199 goto out; 3200 3201 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 3202 xoffset += texImage->Border; 3203 yoffset += texImage->Border; 3204 3205 if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, 3206 &width, &height)) { 3207 ASSERT(ctx->Driver.CopyTexSubImage2D); 3208 ctx->Driver.CopyTexSubImage2D(ctx, target, level, 3209 xoffset, yoffset, x, y, width, height); 3210 } 3211 3212 ctx->NewState |= _NEW_TEXTURE; 3213 } 3214 out: 3215 _mesa_unlock_texture(ctx, texObj); 3216} 3217 3218 3219 3220void GLAPIENTRY 3221_mesa_CopyTexSubImage3D( GLenum target, GLint level, 3222 GLint xoffset, GLint yoffset, GLint zoffset, 3223 GLint x, GLint y, GLsizei width, GLsizei height ) 3224{ 3225 struct gl_texture_unit *texUnit; 3226 struct gl_texture_object *texObj; 3227 struct gl_texture_image *texImage; 3228 GLsizei postConvWidth = width, postConvHeight = height; 3229 GET_CURRENT_CONTEXT(ctx); 3230 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3231 3232 if (ctx->NewState & NEW_COPY_TEX_STATE) 3233 _mesa_update_state(ctx); 3234 3235 if (copytexsubimage_error_check1(ctx, 3, target, level)) 3236 return; 3237 3238 texUnit = get_current_tex_unit(ctx); 3239 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3240 3241 _mesa_lock_texture(ctx, texObj); 3242 { 3243 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3244 3245#if FEATURE_convolve 3246 if (texImage && _mesa_is_color_format(texImage->InternalFormat)) { 3247 _mesa_adjust_image_for_convolution(ctx, 2, 3248 &postConvWidth, &postConvHeight); 3249 } 3250#endif 3251 3252 if (copytexsubimage_error_check2(ctx, 3, target, level, xoffset, yoffset, 3253 zoffset, postConvWidth, postConvHeight, 3254 texImage)) 3255 goto out; 3256 3257 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 3258 xoffset += texImage->Border; 3259 yoffset += texImage->Border; 3260 zoffset += texImage->Border; 3261 3262 if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, 3263 &width, &height)) { 3264 ASSERT(ctx->Driver.CopyTexSubImage3D); 3265 ctx->Driver.CopyTexSubImage3D(ctx, target, level, 3266 xoffset, yoffset, zoffset, 3267 x, y, width, height); 3268 } 3269 3270 ctx->NewState |= _NEW_TEXTURE; 3271 } 3272 out: 3273 _mesa_unlock_texture(ctx, texObj); 3274} 3275 3276 3277 3278 3279/**********************************************************************/ 3280/****** Compressed Textures ******/ 3281/**********************************************************************/ 3282 3283 3284/** 3285 * Error checking for glCompressedTexImage[123]D(). 3286 * \return error code or GL_NO_ERROR. 3287 */ 3288static GLenum 3289compressed_texture_error_check(GLcontext *ctx, GLint dimensions, 3290 GLenum target, GLint level, 3291 GLenum internalFormat, GLsizei width, 3292 GLsizei height, GLsizei depth, GLint border, 3293 GLsizei imageSize) 3294{ 3295 GLint expectedSize, maxLevels = 0, maxTextureSize; 3296 3297 if (dimensions == 1) { 3298 /* 1D compressed textures not allowed */ 3299 return GL_INVALID_ENUM; 3300 } 3301 else if (dimensions == 2) { 3302 if (target == GL_PROXY_TEXTURE_2D) { 3303 maxLevels = ctx->Const.MaxTextureLevels; 3304 } 3305 else if (target == GL_TEXTURE_2D) { 3306 maxLevels = ctx->Const.MaxTextureLevels; 3307 } 3308 else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) { 3309 if (!ctx->Extensions.ARB_texture_cube_map) 3310 return GL_INVALID_ENUM; /*target*/ 3311 maxLevels = ctx->Const.MaxCubeTextureLevels; 3312 } 3313 else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 3314 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 3315 if (!ctx->Extensions.ARB_texture_cube_map) 3316 return GL_INVALID_ENUM; /*target*/ 3317 maxLevels = ctx->Const.MaxCubeTextureLevels; 3318 } 3319 else { 3320 return GL_INVALID_ENUM; /*target*/ 3321 } 3322 } 3323 else if (dimensions == 3) { 3324 /* 3D compressed textures not allowed */ 3325 return GL_INVALID_ENUM; 3326 } 3327 3328 maxTextureSize = 1 << (maxLevels - 1); 3329 3330 /* This will detect any invalid internalFormat value */ 3331 if (!is_compressed_format(ctx, internalFormat)) 3332 return GL_INVALID_ENUM; 3333 3334 /* This should really never fail */ 3335 if (_mesa_base_tex_format(ctx, internalFormat) < 0) 3336 return GL_INVALID_ENUM; 3337 3338 if (border != 0) 3339 return GL_INVALID_VALUE; 3340 3341 /* 3342 * XXX We should probably use the proxy texture error check function here. 3343 */ 3344 if (width < 1 || width > maxTextureSize || 3345 (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(width))) 3346 return GL_INVALID_VALUE; 3347 3348 if ((height < 1 || height > maxTextureSize || 3349 (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(height))) 3350 && dimensions > 1) 3351 return GL_INVALID_VALUE; 3352 3353 if ((depth < 1 || depth > maxTextureSize || 3354 (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(depth))) 3355 && dimensions > 2) 3356 return GL_INVALID_VALUE; 3357 3358 /* For cube map, width must equal height */ 3359 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 3360 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB && width != height) 3361 return GL_INVALID_VALUE; 3362 3363 if (level < 0 || level >= maxLevels) 3364 return GL_INVALID_VALUE; 3365 3366 expectedSize = _mesa_compressed_texture_size_glenum(ctx, width, height, 3367 depth, internalFormat); 3368 if (expectedSize != imageSize) 3369 return GL_INVALID_VALUE; 3370 3371#if FEATURE_EXT_texture_sRGB 3372 if ((internalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT || 3373 internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT || 3374 internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT || 3375 internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) 3376 && border != 0) { 3377 return GL_INVALID_OPERATION; 3378 } 3379#endif 3380 3381 return GL_NO_ERROR; 3382} 3383 3384 3385/** 3386 * Error checking for glCompressedTexSubImage[123]D(). 3387 * \warning There are some bad assumptions here about the size of compressed 3388 * texture tiles (multiple of 4) used to test the validity of the 3389 * offset and size parameters. 3390 * \return error code or GL_NO_ERROR. 3391 */ 3392static GLenum 3393compressed_subtexture_error_check(GLcontext *ctx, GLint dimensions, 3394 GLenum target, GLint level, 3395 GLint xoffset, GLint yoffset, GLint zoffset, 3396 GLsizei width, GLsizei height, GLsizei depth, 3397 GLenum format, GLsizei imageSize) 3398{ 3399 GLint expectedSize, maxLevels = 0, maxTextureSize; 3400 (void) zoffset; 3401 3402 if (dimensions == 1) { 3403 /* 1D compressed textures not allowed */ 3404 return GL_INVALID_ENUM; 3405 } 3406 else if (dimensions == 2) { 3407 if (target == GL_PROXY_TEXTURE_2D) { 3408 maxLevels = ctx->Const.MaxTextureLevels; 3409 } 3410 else if (target == GL_TEXTURE_2D) { 3411 maxLevels = ctx->Const.MaxTextureLevels; 3412 } 3413 else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) { 3414 if (!ctx->Extensions.ARB_texture_cube_map) 3415 return GL_INVALID_ENUM; /*target*/ 3416 maxLevels = ctx->Const.MaxCubeTextureLevels; 3417 } 3418 else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 3419 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 3420 if (!ctx->Extensions.ARB_texture_cube_map) 3421 return GL_INVALID_ENUM; /*target*/ 3422 maxLevels = ctx->Const.MaxCubeTextureLevels; 3423 } 3424 else { 3425 return GL_INVALID_ENUM; /*target*/ 3426 } 3427 } 3428 else if (dimensions == 3) { 3429 /* 3D compressed textures not allowed */ 3430 return GL_INVALID_ENUM; 3431 } 3432 3433 maxTextureSize = 1 << (maxLevels - 1); 3434 3435 /* this will catch any invalid compressed format token */ 3436 if (!is_compressed_format(ctx, format)) 3437 return GL_INVALID_ENUM; 3438 3439 if (width < 1 || width > maxTextureSize) 3440 return GL_INVALID_VALUE; 3441 3442 if ((height < 1 || height > maxTextureSize) 3443 && dimensions > 1) 3444 return GL_INVALID_VALUE; 3445 3446 if (level < 0 || level >= maxLevels) 3447 return GL_INVALID_VALUE; 3448 3449 /* XXX these tests are specific to the compressed format. 3450 * this code should be generalized in some way. 3451 */ 3452 if ((xoffset & 3) != 0 || (yoffset & 3) != 0) 3453 return GL_INVALID_VALUE; 3454 3455 if ((width & 3) != 0 && width != 2 && width != 1) 3456 return GL_INVALID_VALUE; 3457 3458 if ((height & 3) != 0 && height != 2 && height != 1) 3459 return GL_INVALID_VALUE; 3460 3461 expectedSize = _mesa_compressed_texture_size_glenum(ctx, width, height, 3462 depth, format); 3463 if (expectedSize != imageSize) 3464 return GL_INVALID_VALUE; 3465 3466 return GL_NO_ERROR; 3467} 3468 3469 3470 3471void GLAPIENTRY 3472_mesa_CompressedTexImage1DARB(GLenum target, GLint level, 3473 GLenum internalFormat, GLsizei width, 3474 GLint border, GLsizei imageSize, 3475 const GLvoid *data) 3476{ 3477 GET_CURRENT_CONTEXT(ctx); 3478 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3479 3480 if (target == GL_TEXTURE_1D) { 3481 /* non-proxy target */ 3482 struct gl_texture_unit *texUnit; 3483 struct gl_texture_object *texObj; 3484 struct gl_texture_image *texImage; 3485 GLenum error = compressed_texture_error_check(ctx, 1, target, level, 3486 internalFormat, width, 1, 1, border, imageSize); 3487 if (error) { 3488 _mesa_error(ctx, error, "glCompressedTexImage1D"); 3489 return; 3490 } 3491 3492 texUnit = get_current_tex_unit(ctx); 3493 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3494 3495 _mesa_lock_texture(ctx, texObj); 3496 { 3497 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 3498 if (!texImage) { 3499 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1D"); 3500 goto out; 3501 } 3502 3503 if (texImage->Data) { 3504 ctx->Driver.FreeTexImageData( ctx, texImage ); 3505 } 3506 ASSERT(texImage->Data == NULL); 3507 3508 _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1, 3509 border, internalFormat); 3510 3511 ASSERT(ctx->Driver.CompressedTexImage1D); 3512 (*ctx->Driver.CompressedTexImage1D)(ctx, target, level, 3513 internalFormat, width, border, 3514 imageSize, data, 3515 texObj, texImage); 3516 3517 /* state update */ 3518 texObj->_Complete = GL_FALSE; 3519 ctx->NewState |= _NEW_TEXTURE; 3520 } 3521 out: 3522 _mesa_unlock_texture(ctx, texObj); 3523 } 3524 else if (target == GL_PROXY_TEXTURE_1D) { 3525 /* Proxy texture: check for errors and update proxy state */ 3526 GLenum error = compressed_texture_error_check(ctx, 1, target, level, 3527 internalFormat, width, 1, 1, border, imageSize); 3528 if (!error) { 3529 ASSERT(ctx->Driver.TestProxyTexImage); 3530 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 3531 internalFormat, GL_NONE, GL_NONE, 3532 width, 1, 1, border); 3533 } 3534 if (error) { 3535 /* if error, clear all proxy texture image parameters */ 3536 struct gl_texture_image *texImage; 3537 texImage = _mesa_get_proxy_tex_image(ctx, target, level); 3538 if (texImage) 3539 clear_teximage_fields(texImage); 3540 } 3541 else { 3542 /* store the teximage parameters */ 3543 struct gl_texture_unit *texUnit; 3544 struct gl_texture_object *texObj; 3545 struct gl_texture_image *texImage; 3546 texUnit = get_current_tex_unit(ctx); 3547 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3548 3549 _mesa_lock_texture(ctx, texObj); 3550 { 3551 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3552 _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1, 3553 border, internalFormat); 3554 } 3555 _mesa_unlock_texture(ctx, texObj); 3556 } 3557 } 3558 else { 3559 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1D(target)"); 3560 return; 3561 } 3562} 3563 3564 3565void GLAPIENTRY 3566_mesa_CompressedTexImage2DARB(GLenum target, GLint level, 3567 GLenum internalFormat, GLsizei width, 3568 GLsizei height, GLint border, GLsizei imageSize, 3569 const GLvoid *data) 3570{ 3571 GET_CURRENT_CONTEXT(ctx); 3572 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3573 3574 if (target == GL_TEXTURE_2D || 3575 (ctx->Extensions.ARB_texture_cube_map && 3576 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 3577 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) { 3578 /* non-proxy target */ 3579 struct gl_texture_unit *texUnit; 3580 struct gl_texture_object *texObj; 3581 struct gl_texture_image *texImage; 3582 GLenum error = compressed_texture_error_check(ctx, 2, target, level, 3583 internalFormat, width, height, 1, border, imageSize); 3584 if (error) { 3585 _mesa_error(ctx, error, "glCompressedTexImage2D"); 3586 return; 3587 } 3588 3589 texUnit = get_current_tex_unit(ctx); 3590 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3591 3592 _mesa_lock_texture(ctx, texObj); 3593 { 3594 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 3595 if (!texImage) { 3596 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D"); 3597 goto out; 3598 } 3599 3600 if (texImage->Data) { 3601 ctx->Driver.FreeTexImageData( ctx, texImage ); 3602 } 3603 ASSERT(texImage->Data == NULL); 3604 3605 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1, 3606 border, internalFormat); 3607 3608 ASSERT(ctx->Driver.CompressedTexImage2D); 3609 (*ctx->Driver.CompressedTexImage2D)(ctx, target, level, 3610 internalFormat, width, height, 3611 border, imageSize, data, 3612 texObj, texImage); 3613 3614 /* state update */ 3615 texObj->_Complete = GL_FALSE; 3616 ctx->NewState |= _NEW_TEXTURE; 3617 } 3618 out: 3619 _mesa_unlock_texture(ctx, texObj); 3620 } 3621 else if (target == GL_PROXY_TEXTURE_2D || 3622 (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB && 3623 ctx->Extensions.ARB_texture_cube_map)) { 3624 /* Proxy texture: check for errors and update proxy state */ 3625 GLenum error = compressed_texture_error_check(ctx, 2, target, level, 3626 internalFormat, width, height, 1, border, imageSize); 3627 if (!error) { 3628 ASSERT(ctx->Driver.TestProxyTexImage); 3629 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 3630 internalFormat, GL_NONE, GL_NONE, 3631 width, height, 1, border); 3632 } 3633 if (error) { 3634 /* if error, clear all proxy texture image parameters */ 3635 struct gl_texture_image *texImage; 3636 texImage = _mesa_get_proxy_tex_image(ctx, target, level); 3637 if (texImage) 3638 clear_teximage_fields(texImage); 3639 } 3640 else { 3641 /* store the teximage parameters */ 3642 struct gl_texture_unit *texUnit; 3643 struct gl_texture_object *texObj; 3644 struct gl_texture_image *texImage; 3645 texUnit = get_current_tex_unit(ctx); 3646 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3647 3648 _mesa_lock_texture(ctx, texObj); 3649 { 3650 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3651 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1, 3652 border, internalFormat); 3653 } 3654 _mesa_unlock_texture(ctx, texObj); 3655 } 3656 } 3657 else { 3658 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2D(target)"); 3659 return; 3660 } 3661} 3662 3663 3664void GLAPIENTRY 3665_mesa_CompressedTexImage3DARB(GLenum target, GLint level, 3666 GLenum internalFormat, GLsizei width, 3667 GLsizei height, GLsizei depth, GLint border, 3668 GLsizei imageSize, const GLvoid *data) 3669{ 3670 GET_CURRENT_CONTEXT(ctx); 3671 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3672 3673 if (target == GL_TEXTURE_3D) { 3674 /* non-proxy target */ 3675 struct gl_texture_unit *texUnit; 3676 struct gl_texture_object *texObj; 3677 struct gl_texture_image *texImage; 3678 GLenum error = compressed_texture_error_check(ctx, 3, target, level, 3679 internalFormat, width, height, depth, border, imageSize); 3680 if (error) { 3681 _mesa_error(ctx, error, "glCompressedTexImage3D"); 3682 return; 3683 } 3684 3685 texUnit = get_current_tex_unit(ctx); 3686 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3687 _mesa_lock_texture(ctx, texObj); 3688 { 3689 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 3690 if (!texImage) { 3691 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3D"); 3692 goto out; 3693 } 3694 3695 if (texImage->Data) { 3696 ctx->Driver.FreeTexImageData( ctx, texImage ); 3697 } 3698 ASSERT(texImage->Data == NULL); 3699 3700 _mesa_init_teximage_fields(ctx, target, texImage, width, height, depth, 3701 border, internalFormat); 3702 3703 ASSERT(ctx->Driver.CompressedTexImage3D); 3704 (*ctx->Driver.CompressedTexImage3D)(ctx, target, level, 3705 internalFormat, 3706 width, height, depth, 3707 border, imageSize, data, 3708 texObj, texImage); 3709 3710 /* state update */ 3711 texObj->_Complete = GL_FALSE; 3712 ctx->NewState |= _NEW_TEXTURE; 3713 } 3714 out: 3715 _mesa_unlock_texture(ctx, texObj); 3716 } 3717 else if (target == GL_PROXY_TEXTURE_3D) { 3718 /* Proxy texture: check for errors and update proxy state */ 3719 GLenum error = compressed_texture_error_check(ctx, 3, target, level, 3720 internalFormat, width, height, depth, border, imageSize); 3721 if (!error) { 3722 ASSERT(ctx->Driver.TestProxyTexImage); 3723 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 3724 internalFormat, GL_NONE, GL_NONE, 3725 width, height, depth, border); 3726 } 3727 if (error) { 3728 /* if error, clear all proxy texture image parameters */ 3729 struct gl_texture_image *texImage; 3730 texImage = _mesa_get_proxy_tex_image(ctx, target, level); 3731 if (texImage) 3732 clear_teximage_fields(texImage); 3733 } 3734 else { 3735 /* store the teximage parameters */ 3736 struct gl_texture_unit *texUnit; 3737 struct gl_texture_object *texObj; 3738 struct gl_texture_image *texImage; 3739 texUnit = get_current_tex_unit(ctx); 3740 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3741 _mesa_lock_texture(ctx, texObj); 3742 { 3743 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3744 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 3745 depth, border, internalFormat); 3746 } 3747 _mesa_unlock_texture(ctx, texObj); 3748 } 3749 } 3750 else { 3751 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3D(target)"); 3752 return; 3753 } 3754} 3755 3756 3757void GLAPIENTRY 3758_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset, 3759 GLsizei width, GLenum format, 3760 GLsizei imageSize, const GLvoid *data) 3761{ 3762 struct gl_texture_unit *texUnit; 3763 struct gl_texture_object *texObj; 3764 struct gl_texture_image *texImage; 3765 GLenum error; 3766 GET_CURRENT_CONTEXT(ctx); 3767 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3768 3769 error = compressed_subtexture_error_check(ctx, 1, target, level, 3770 xoffset, 0, 0, /* pos */ 3771 width, 1, 1, /* size */ 3772 format, imageSize); 3773 if (error) { 3774 _mesa_error(ctx, error, "glCompressedTexSubImage1D"); 3775 return; 3776 } 3777 3778 texUnit = get_current_tex_unit(ctx); 3779 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3780 _mesa_lock_texture(ctx, texObj); 3781 { 3782 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3783 assert(texImage); 3784 3785 if ((GLint) format != texImage->InternalFormat) { 3786 _mesa_error(ctx, GL_INVALID_OPERATION, 3787 "glCompressedTexSubImage1D(format)"); 3788 goto out; 3789 } 3790 3791 if ((width == 1 || width == 2) && (GLuint) width != texImage->Width) { 3792 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage1D(width)"); 3793 goto out; 3794 } 3795 3796 if (width == 0) 3797 goto out; /* no-op, not an error */ 3798 3799 if (ctx->Driver.CompressedTexSubImage1D) { 3800 (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level, 3801 xoffset, width, 3802 format, imageSize, data, 3803 texObj, texImage); 3804 } 3805 ctx->NewState |= _NEW_TEXTURE; 3806 } 3807 out: 3808 _mesa_unlock_texture(ctx, texObj); 3809} 3810 3811 3812void GLAPIENTRY 3813_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset, 3814 GLint yoffset, GLsizei width, GLsizei height, 3815 GLenum format, GLsizei imageSize, 3816 const GLvoid *data) 3817{ 3818 struct gl_texture_unit *texUnit; 3819 struct gl_texture_object *texObj; 3820 struct gl_texture_image *texImage; 3821 GLenum error; 3822 GET_CURRENT_CONTEXT(ctx); 3823 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3824 3825 error = compressed_subtexture_error_check(ctx, 2, target, level, 3826 xoffset, yoffset, 0, /* pos */ 3827 width, height, 1, /* size */ 3828 format, imageSize); 3829 if (error) { 3830 /* XXX proxy target? */ 3831 _mesa_error(ctx, error, "glCompressedTexSubImage2D"); 3832 return; 3833 } 3834 3835 texUnit = get_current_tex_unit(ctx); 3836 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3837 _mesa_lock_texture(ctx, texObj); 3838 { 3839 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3840 assert(texImage); 3841 3842 if ((GLint) format != texImage->InternalFormat) { 3843 _mesa_error(ctx, GL_INVALID_OPERATION, 3844 "glCompressedTexSubImage2D(format)"); 3845 goto out; 3846 } 3847 3848 if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) || 3849 ((height == 1 || height == 2) && (GLuint) height != texImage->Height)) { 3850 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage2D(size)"); 3851 goto out; 3852 } 3853 3854 if (width == 0 || height == 0) 3855 goto out; /* no-op, not an error */ 3856 3857 if (ctx->Driver.CompressedTexSubImage2D) { 3858 (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level, 3859 xoffset, yoffset, width, height, 3860 format, imageSize, data, 3861 texObj, texImage); 3862 } 3863 ctx->NewState |= _NEW_TEXTURE; 3864 } 3865 out: 3866 _mesa_unlock_texture(ctx, texObj); 3867} 3868 3869 3870void GLAPIENTRY 3871_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset, 3872 GLint yoffset, GLint zoffset, GLsizei width, 3873 GLsizei height, GLsizei depth, GLenum format, 3874 GLsizei imageSize, const GLvoid *data) 3875{ 3876 struct gl_texture_unit *texUnit; 3877 struct gl_texture_object *texObj; 3878 struct gl_texture_image *texImage; 3879 GLenum error; 3880 GET_CURRENT_CONTEXT(ctx); 3881 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3882 3883 error = compressed_subtexture_error_check(ctx, 3, target, level, 3884 xoffset, yoffset, zoffset,/*pos*/ 3885 width, height, depth, /*size*/ 3886 format, imageSize); 3887 if (error) { 3888 _mesa_error(ctx, error, "glCompressedTexSubImage3D"); 3889 return; 3890 } 3891 3892 texUnit = get_current_tex_unit(ctx); 3893 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3894 _mesa_lock_texture(ctx, texObj); 3895 { 3896 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3897 assert(texImage); 3898 3899 if ((GLint) format != texImage->InternalFormat) { 3900 _mesa_error(ctx, GL_INVALID_OPERATION, 3901 "glCompressedTexSubImage3D(format)"); 3902 goto out; 3903 } 3904 3905 if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) || 3906 ((height == 1 || height == 2) && (GLuint) height != texImage->Height) || 3907 ((depth == 1 || depth == 2) && (GLuint) depth != texImage->Depth)) { 3908 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage3D(size)"); 3909 goto out; 3910 } 3911 3912 if (width == 0 || height == 0 || depth == 0) 3913 goto out; /* no-op, not an error */ 3914 3915 if (ctx->Driver.CompressedTexSubImage3D) { 3916 (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level, 3917 xoffset, yoffset, zoffset, 3918 width, height, depth, 3919 format, imageSize, data, 3920 texObj, texImage); 3921 } 3922 ctx->NewState |= _NEW_TEXTURE; 3923 } 3924 out: 3925 _mesa_unlock_texture(ctx, texObj); 3926} 3927 3928 3929void GLAPIENTRY 3930_mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img) 3931{ 3932 const struct gl_texture_unit *texUnit; 3933 struct gl_texture_object *texObj; 3934 struct gl_texture_image *texImage; 3935 GLint maxLevels; 3936 GET_CURRENT_CONTEXT(ctx); 3937 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3938 3939 texUnit = get_current_tex_unit(ctx); 3940 texObj = _mesa_select_tex_object(ctx, texUnit, target); 3941 if (!texObj) { 3942 _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB"); 3943 return; 3944 } 3945 3946 maxLevels = _mesa_max_texture_levels(ctx, target); 3947 ASSERT(maxLevels > 0); /* 0 indicates bad target, caught above */ 3948 3949 if (level < 0 || level >= maxLevels) { 3950 _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)"); 3951 return; 3952 } 3953 3954 if (_mesa_is_proxy_texture(target)) { 3955 _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)"); 3956 return; 3957 } 3958 3959 _mesa_lock_texture(ctx, texObj); 3960 { 3961 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3962 if (texImage) { 3963 if (texImage->IsCompressed) { 3964 /* this typically calls _mesa_get_compressed_teximage() */ 3965 ctx->Driver.GetCompressedTexImage(ctx, target, level, img, 3966 texObj, texImage); 3967 } 3968 else { 3969 _mesa_error(ctx, GL_INVALID_OPERATION, 3970 "glGetCompressedTexImageARB"); 3971 } 3972 } 3973 else { 3974 /* probably invalid mipmap level */ 3975 _mesa_error(ctx, GL_INVALID_VALUE, 3976 "glGetCompressedTexImageARB(level)"); 3977 } 3978 } 3979 _mesa_unlock_texture(ctx, texObj); 3980} 3981