teximage.c revision a988ddf3798e0ec568704e4a72b46030079c7e45
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 9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * copy of this software and associated documentation files (the "Software"), 10242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * to deal in the Software without restriction, including without limitation 11242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * the rights to use, copy, modify, merge, publish, distribute, sublicense, 12242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * and/or sell copies of the Software, and to permit persons to whom the 139df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com * Software is furnished to do so, subject to the following conditions: 14242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * 15242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * The above copyright notice and this permission notice shall be included 169df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com * in all copies or substantial portions of the Software. 17242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * 18242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 199df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 2059bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 22c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 23c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com */ 25c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com 26c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com 27c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com/** 28c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com * \file teximage.c 29c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com * Texture image-related functions. 30c18143e89b8ef91cb0a3f64cb490ea765da3549fbungeman@google.com */ 31242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com 3239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com 3339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com#include "glheader.h" 3439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com#include "bufferobj.h" 3539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com#include "context.h" 3639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com#include "enums.h" 3739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com#include "fbobject.h" 3839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com#include "framebuffer.h" 3939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com#include "hash.h" 4039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com#include "image.h" 4139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com#include "imports.h" 4239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com#include "macros.h" 4339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com#include "mfeatures.h" 4439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com#include "state.h" 4539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com#include "texcompress.h" 4639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com#include "texfetch.h" 4739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com#include "teximage.h" 4839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com#include "texstate.h" 4939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com#include "texpal.h" 5039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com#include "mtypes.h" 51242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com 5239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com 5339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com/** 5439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com * State changes which we care about for glCopyTex[Sub]Image() calls. 5539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com * In particular, we care about pixel transfer state and buffer state 5639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com * (such as glReadBuffer to make sure we read from the right renderbuffer). 5739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com */ 58242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#define NEW_COPY_TEX_STATE (_MESA_NEW_TRANSFER_STATE | \ 59242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com _NEW_BUFFERS | \ 6039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com _NEW_PIXEL) 6139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com 6239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com 6339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com 6439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com/** 6539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com * We allocate texture memory on 512-byte boundaries so we can use MMX/SSE 6639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com * elsewhere. 6739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com */ 6839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.comvoid * 6939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com_mesa_alloc_texmemory(GLsizei bytes) 7039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com{ 7139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com return _mesa_align_malloc(bytes, 512); 7239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com} 7339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com 7439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com 7539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com/** 7639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com * Free texture memory allocated with _mesa_alloc_texmemory() 77242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com */ 7839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.comvoid 7939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com_mesa_free_texmemory(void *m) 8039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com{ 8139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com _mesa_align_free(m); 8239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com} 8339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com 8439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com 8539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com/* 8639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com * Compute floor(log_base_2(n)). 8739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com * If n < 0 return -1. 8839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com */ 8939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.comstatic int 9039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.comlogbase2( int n ) 9139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com{ 92242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com GLint i = 1; 932e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com GLint log2 = 0; 942e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com 952e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com if (n < 0) 962e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com return -1; 97d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 982e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com if (n == 0) 99d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com return 0; 100242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com 1019df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com while ( n > i ) { 102242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com i *= 2; 103242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com log2++; 104242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com } 105242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com if (i != n) { 106242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return log2 - 1; 107242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com } 108242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com else { 109242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return log2; 110d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com } 111242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com} 1129df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com 113242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com 1149df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com 115242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com/** 116d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com * Return the simple base format for a given internal texture format. 117242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * For example, given GL_LUMINANCE12_ALPHA4, return GL_LUMINANCE_ALPHA. 118242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * 119242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * \param ctx GL context. 120242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * \param internalFormat the internal texture format token or 1, 2, 3, or 4. 121242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * 122d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com * \return the corresponding \u base internal format (GL_ALPHA, GL_LUMINANCE, 123242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * GL_LUMANCE_ALPHA, GL_INTENSITY, GL_RGB, or GL_RGBA), or -1 if invalid enum. 1249df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com * 125242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * This is the format which is used during texture application (i.e. the 126242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * texture format and env mode determine the arithmetic used. 127242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * 128242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com * XXX this could be static 129242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com */ 130242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.comGLint 131242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com_mesa_base_tex_format( struct gl_context *ctx, GLint internalFormat ) 132242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com{ 133d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com switch (internalFormat) { 13439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case GL_ALPHA: 13539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case GL_ALPHA4: 13639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case GL_ALPHA8: 13739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case GL_ALPHA12: 13839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case GL_ALPHA16: 13939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com return GL_ALPHA; 14039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case 1: 14139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case GL_LUMINANCE: 14239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case GL_LUMINANCE4: 14339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case GL_LUMINANCE8: 14439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case GL_LUMINANCE12: 14539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case GL_LUMINANCE16: 14639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com return GL_LUMINANCE; 14739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case 2: 148242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_LUMINANCE_ALPHA: 1499df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com case GL_LUMINANCE4_ALPHA4: 150242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_LUMINANCE6_ALPHA2: 151242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_LUMINANCE8_ALPHA8: 152242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_LUMINANCE12_ALPHA4: 153d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com case GL_LUMINANCE12_ALPHA12: 154242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_LUMINANCE16_ALPHA16: 1559df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com return GL_LUMINANCE_ALPHA; 156242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_INTENSITY: 157242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_INTENSITY4: 158242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_INTENSITY8: 159242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_INTENSITY12: 160242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_INTENSITY16: 161d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com return GL_INTENSITY; 162242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case 3: 163242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGB: 164242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_R3_G3_B2: 165242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGB4: 166242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGB5: 167242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGB8: 168d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com case GL_RGB10: 169242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGB12: 170242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGB16: 171242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_RGB; 17239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case 4: 173242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGBA: 174242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGBA2: 175242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGBA4: 176242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGB5_A1: 177242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGBA8: 178242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGB10_A2: 179d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com case GL_RGBA12: 180242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGBA16: 1819df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com return GL_RGBA; 182242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com default: 183242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com ; /* fallthrough */ 184242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com } 185d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 186242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com if (ctx->Extensions.EXT_paletted_texture) { 187242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com switch (internalFormat) { 188242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COLOR_INDEX: 189242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COLOR_INDEX1_EXT: 190242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COLOR_INDEX2_EXT: 191242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COLOR_INDEX4_EXT: 192242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COLOR_INDEX8_EXT: 193242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COLOR_INDEX12_EXT: 194242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COLOR_INDEX16_EXT: 195242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_COLOR_INDEX; 196d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com default: 197242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com ; /* fallthrough */ 1989df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com } 199242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com } 200242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com 201242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com if (ctx->Extensions.ARB_depth_texture) { 202242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com switch (internalFormat) { 203242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_DEPTH_COMPONENT: 204d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com case GL_DEPTH_COMPONENT16: 205242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_DEPTH_COMPONENT24: 206242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_DEPTH_COMPONENT32: 207955bb0751a0d48e47a341c7c0adda94977bc8170bungeman@google.com return GL_DEPTH_COMPONENT; 208dbfac8a72393eaf01670aeb3244de0e18d8faf98junov@google.com default: 209242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com ; /* fallthrough */ 210242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com } 211242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com } 212242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com 213242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com switch (internalFormat) { 214242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COMPRESSED_ALPHA: 215242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_ALPHA; 21659bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com case GL_COMPRESSED_LUMINANCE: 21759bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com return GL_LUMINANCE; 21859bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com case GL_COMPRESSED_LUMINANCE_ALPHA: 219242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_LUMINANCE_ALPHA; 220d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com case GL_COMPRESSED_INTENSITY: 221242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_INTENSITY; 222242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COMPRESSED_RGB: 223242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_RGB; 224242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COMPRESSED_RGBA: 225242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_RGBA; 2264c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com default: 2274c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com ; /* fallthrough */ 228242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com } 2294c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com 2304c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com if (ctx->Extensions.TDFX_texture_compression_FXT1) { 2314c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com switch (internalFormat) { 2324c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com case GL_COMPRESSED_RGB_FXT1_3DFX: 2334c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com return GL_RGB; 2344c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com case GL_COMPRESSED_RGBA_FXT1_3DFX: 2354c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com return GL_RGBA; 236242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com default: 237242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com ; /* fallthrough */ 238242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com } 239242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com } 240242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com 241242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com if (ctx->Extensions.EXT_texture_compression_s3tc) { 242242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com switch (internalFormat) { 243242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: 244242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_RGB; 245242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: 246242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: 247242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: 248242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_RGBA; 249242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com default: 250242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com ; /* fallthrough */ 251242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com } 252242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com } 253242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com 254242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com if (ctx->Extensions.S3_s3tc) { 255242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com switch (internalFormat) { 256242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGB_S3TC: 257242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGB4_S3TC: 25822b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com return GL_RGB; 259242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGBA_S3TC: 260242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGBA4_S3TC: 261242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_RGBA; 262242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com default: 2634c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com ; /* fallthrough */ 2644c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com } 2654c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com } 2664c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com 2674c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com if (ctx->Extensions.MESA_ycbcr_texture) { 2684c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com if (internalFormat == GL_YCBCR_MESA) 269242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_YCBCR_MESA; 270242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com } 271242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com 272242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com if (ctx->Extensions.ARB_texture_float) { 273242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com switch (internalFormat) { 274242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_ALPHA16F_ARB: 275242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_ALPHA32F_ARB: 276242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_ALPHA; 277242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGBA16F_ARB: 278242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGBA32F_ARB: 27922b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com return GL_RGBA; 28022b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com case GL_RGB16F_ARB: 28122b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com case GL_RGB32F_ARB: 28259bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com return GL_RGB; 28322b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com case GL_INTENSITY16F_ARB: 28422b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com case GL_INTENSITY32F_ARB: 28522b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com return GL_INTENSITY; 28622b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com case GL_LUMINANCE16F_ARB: 28722b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com case GL_LUMINANCE32F_ARB: 28822b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com return GL_LUMINANCE; 28922b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com case GL_LUMINANCE_ALPHA16F_ARB: 29022b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com case GL_LUMINANCE_ALPHA32F_ARB: 29159bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com return GL_LUMINANCE_ALPHA; 29259bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com default: 29359bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com ; /* fallthrough */ 29459bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com } 29559bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com } 29659bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com 29759bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com if (ctx->Extensions.ATI_envmap_bumpmap) { 29859bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com switch (internalFormat) { 29959bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com case GL_DUDV_ATI: 30059bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com case GL_DU8DV8_ATI: 30159bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com return GL_DUDV_ATI; 30259bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com default: 30359bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com ; /* fallthrough */ 30459bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com } 30559bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com } 30659bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com 30759bfb1240666b0f70109ac8ab04a280765ff8563robertphillips@google.com if (ctx->Extensions.MESA_texture_signed_rgba) { 308242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com switch (internalFormat) { 3092e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com case GL_RGBA_SNORM: 3102e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com case GL_RGBA8_SNORM: 3112e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com return GL_RGBA; 3122e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com default: 313d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com ; /* fallthrough */ 3142e2f3f58b5b0599c776f20bb55845d3e6005a01cbungeman@google.com } 315d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com } 316242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com 3179df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com if (ctx->Extensions.EXT_packed_depth_stencil) { 318242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com switch (internalFormat) { 319242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_DEPTH_STENCIL_EXT: 320242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_DEPTH24_STENCIL8_EXT: 321242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_DEPTH_STENCIL_EXT; 322242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com default: 323242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com ; /* fallthrough */ 324242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com } 325242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com } 326d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 3279df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com#if FEATURE_EXT_texture_sRGB 3289df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com if (ctx->Extensions.EXT_texture_sRGB) { 329242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com switch (internalFormat) { 3309df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com case GL_SRGB_EXT: 331242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_SRGB8_EXT: 332d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com case GL_COMPRESSED_SRGB_EXT: 333242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: 3349df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com return GL_RGB; 335242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_SRGB_ALPHA_EXT: 336242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_SRGB8_ALPHA8_EXT: 337242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COMPRESSED_SRGB_ALPHA_EXT: 338d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: 339242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: 340242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: 341242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_RGBA; 342d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com case GL_SLUMINANCE_ALPHA_EXT: 343242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_SLUMINANCE8_ALPHA8_EXT: 3449df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT: 3459df621da5024dda2ffd77cfa6e6c0a0f68e4aa86bungeman@google.com return GL_LUMINANCE_ALPHA; 346242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_SLUMINANCE_EXT: 347242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_SLUMINANCE8_EXT: 348242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_COMPRESSED_SLUMINANCE_EXT: 349d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com return GL_LUMINANCE; 350242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com default: 351242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com ; /* fallthrough */ 352242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com } 353242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com } 354242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com#endif /* FEATURE_EXT_texture_sRGB */ 355d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com 356242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com if (ctx->Extensions.EXT_texture_integer) { 357242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com switch (internalFormat) { 358242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGBA8UI_EXT: 359242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGBA16UI_EXT: 360d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com case GL_RGBA32UI_EXT: 361242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGBA8I_EXT: 362242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGBA16I_EXT: 363242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGBA32I_EXT: 364242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_RGBA; 365242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGB8UI_EXT: 366242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGB16UI_EXT: 367242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGB32UI_EXT: 368242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGB8I_EXT: 369242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_RGB16I_EXT: 370d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com case GL_RGB32I_EXT: 371242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_RGB; 37222b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com case GL_ALPHA8UI_EXT: 37322b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com case GL_ALPHA16UI_EXT: 374242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_ALPHA32UI_EXT: 375242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_ALPHA8I_EXT: 376242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_ALPHA16I_EXT: 377d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com case GL_ALPHA32I_EXT: 378242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_ALPHA; 379242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_INTENSITY8UI_EXT: 380242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_INTENSITY16UI_EXT: 381242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_INTENSITY32UI_EXT: 382242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_INTENSITY8I_EXT: 383242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_INTENSITY16I_EXT: 384242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_INTENSITY32I_EXT: 385242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_INTENSITY; 386242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_LUMINANCE8UI_EXT: 387242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_LUMINANCE16UI_EXT: 388d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com case GL_LUMINANCE32UI_EXT: 389242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_LUMINANCE8I_EXT: 390242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_LUMINANCE16I_EXT: 391955bb0751a0d48e47a341c7c0adda94977bc8170bungeman@google.com case GL_LUMINANCE32I_EXT: 392242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_LUMINANCE; 393242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_LUMINANCE_ALPHA8UI_EXT: 39422b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com case GL_LUMINANCE_ALPHA16UI_EXT: 39522b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com case GL_LUMINANCE_ALPHA32UI_EXT: 39622b4950f60c18d79b985bceb39784840e3d30004bungeman@google.com case GL_LUMINANCE_ALPHA8I_EXT: 397242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_LUMINANCE_ALPHA16I_EXT: 398d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com case GL_LUMINANCE_ALPHA32I_EXT: 399242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com return GL_LUMINANCE_ALPHA; 400242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com default: 401242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com ; /* fallthrough */ 402d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com } 403242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com } 404242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com 405242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com if (ctx->Extensions.ARB_texture_rg) { 406d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com switch (internalFormat) { 407242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_R16F: 408242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com /* R16F depends on both ARB_half_float_pixel and ARB_texture_float. 409242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com */ 4104c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com if (!ctx->Extensions.ARB_half_float_pixel) 4114c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com break; 4124c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com /* FALLTHROUGH */ 4134c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com case GL_R32F: 4144c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com if (!ctx->Extensions.ARB_texture_float) 415242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com break; 4164c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com return GL_RED; 4174c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com case GL_R8I: 4184c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com case GL_R8UI: 4194c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com case GL_R16I: 420242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_R16UI: 421242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_R32I: 422242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com case GL_R32UI: 423242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com if (!ctx->Extensions.EXT_texture_integer) 424242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com break; 425242bb89c0d239662b05f5a396d45ad4f28b1596ebungeman@google.com /* FALLTHROUGH */ 4264c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com case GL_R8: 4274c6adf9a089dbdd541f25d01d257ec05aedcb57dscroggo@google.com case GL_R16: 42839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case GL_RED: 42939edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case GL_COMPRESSED_RED: 43039edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com return GL_RED; 43139edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com 43239edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case GL_RG16F: 43339edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com /* RG16F depends on both ARB_half_float_pixel and ARB_texture_float. 43439edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com */ 43539edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com if (!ctx->Extensions.ARB_half_float_pixel) 43639edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com break; 43739edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com /* FALLTHROUGH */ 43839edf4cd94e6fbeb8c1187a588b314e9795c81e4scroggo@google.com case GL_RG32F: 439 if (!ctx->Extensions.ARB_texture_float) 440 break; 441 return GL_RG; 442 case GL_RG8I: 443 case GL_RG8UI: 444 case GL_RG16I: 445 case GL_RG16UI: 446 case GL_RG32I: 447 case GL_RG32UI: 448 if (!ctx->Extensions.EXT_texture_integer) 449 break; 450 /* FALLTHROUGH */ 451 case GL_RG: 452 case GL_RG8: 453 case GL_RG16: 454 case GL_COMPRESSED_RG: 455 return GL_RG; 456 default: 457 ; /* fallthrough */ 458 } 459 } 460 461 if (ctx->Extensions.EXT_texture_shared_exponent) { 462 switch (internalFormat) { 463 case GL_RGB9_E5_EXT: 464 return GL_RGB; 465 default: 466 ; /* fallthrough */ 467 } 468 } 469 470 if (ctx->Extensions.EXT_packed_float) { 471 switch (internalFormat) { 472 case GL_R11F_G11F_B10F_EXT: 473 return GL_RGB; 474 default: 475 ; /* fallthrough */ 476 } 477 } 478 479 if (ctx->Extensions.ARB_depth_buffer_float) { 480 switch (internalFormat) { 481 case GL_DEPTH_COMPONENT32F: 482 return GL_DEPTH_COMPONENT; 483 case GL_DEPTH32F_STENCIL8: 484 return GL_DEPTH_STENCIL; 485 default: 486 ; /* fallthrough */ 487 } 488 } 489 490 if (ctx->Extensions.ARB_texture_compression_rgtc) { 491 switch (internalFormat) { 492 case GL_COMPRESSED_RED_RGTC1: 493 case GL_COMPRESSED_SIGNED_RED_RGTC1: 494 return GL_RED; 495 case GL_COMPRESSED_RG_RGTC2: 496 case GL_COMPRESSED_SIGNED_RG_RGTC2: 497 return GL_RG; 498 default: 499 ; /* fallthrough */ 500 } 501 } 502 503 return -1; /* error */ 504} 505 506 507/** 508 * For cube map faces, return a face index in [0,5]. 509 * For other targets return 0; 510 */ 511GLuint 512_mesa_tex_target_to_face(GLenum target) 513{ 514 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 515 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) 516 return (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X; 517 else 518 return 0; 519} 520 521 522 523/** 524 * Store a gl_texture_image pointer in a gl_texture_object structure 525 * according to the target and level parameters. 526 * 527 * \param tObj texture object. 528 * \param target texture target. 529 * \param level image level. 530 * \param texImage texture image. 531 * 532 * This was basically prompted by the introduction of cube maps. 533 */ 534void 535_mesa_set_tex_image(struct gl_texture_object *tObj, 536 GLenum target, GLint level, 537 struct gl_texture_image *texImage) 538{ 539 const GLuint face = _mesa_tex_target_to_face(target); 540 541 ASSERT(tObj); 542 ASSERT(texImage); 543 ASSERT(target != GL_TEXTURE_RECTANGLE_NV || level == 0); 544 545 tObj->Image[face][level] = texImage; 546 547 /* Set the 'back' pointer */ 548 texImage->TexObject = tObj; 549} 550 551 552/** 553 * Allocate a texture image structure. 554 * 555 * Called via ctx->Driver.NewTextureImage() unless overriden by a device 556 * driver. 557 * 558 * \return a pointer to gl_texture_image struct with all fields initialized to 559 * zero. 560 */ 561struct gl_texture_image * 562_mesa_new_texture_image( struct gl_context *ctx ) 563{ 564 (void) ctx; 565 return CALLOC_STRUCT(gl_texture_image); 566} 567 568 569/** 570 * Free texture image data. 571 * This function is a fallback called via ctx->Driver.FreeTexImageData(). 572 * 573 * \param texImage texture image. 574 * 575 * Free the texture image data if it's not marked as client data. 576 */ 577void 578_mesa_free_texture_image_data(struct gl_context *ctx, 579 struct gl_texture_image *texImage) 580{ 581 (void) ctx; 582 583 if (texImage->Data && !texImage->IsClientData) { 584 /* free the old texture data */ 585 _mesa_free_texmemory(texImage->Data); 586 } 587 588 texImage->Data = NULL; 589} 590 591 592/** 593 * Free texture image. 594 * 595 * \param texImage texture image. 596 * 597 * Free the texture image structure and the associated image data. 598 */ 599void 600_mesa_delete_texture_image(struct gl_context *ctx, 601 struct gl_texture_image *texImage) 602{ 603 /* Free texImage->Data and/or any other driver-specific texture 604 * image storage. 605 */ 606 ASSERT(ctx->Driver.FreeTexImageData); 607 ctx->Driver.FreeTexImageData( ctx, texImage ); 608 609 ASSERT(texImage->Data == NULL); 610 if (texImage->ImageOffsets) 611 free(texImage->ImageOffsets); 612 free(texImage); 613} 614 615 616/** 617 * Test if a target is a proxy target. 618 * 619 * \param target texture target. 620 * 621 * \return GL_TRUE if the target is a proxy target, GL_FALSE otherwise. 622 */ 623GLboolean 624_mesa_is_proxy_texture(GLenum target) 625{ 626 /* NUM_TEXTURE_TARGETS should match number of terms below */ 627 assert(NUM_TEXTURE_TARGETS == 7); 628 629 return (target == GL_PROXY_TEXTURE_1D || 630 target == GL_PROXY_TEXTURE_2D || 631 target == GL_PROXY_TEXTURE_3D || 632 target == GL_PROXY_TEXTURE_CUBE_MAP_ARB || 633 target == GL_PROXY_TEXTURE_RECTANGLE_NV || 634 target == GL_PROXY_TEXTURE_1D_ARRAY_EXT || 635 target == GL_PROXY_TEXTURE_2D_ARRAY_EXT); 636} 637 638 639/** 640 * Return the proxy target which corresponds to the given texture target 641 */ 642static GLenum 643get_proxy_target(GLenum target) 644{ 645 switch (target) { 646 case GL_TEXTURE_1D: 647 case GL_PROXY_TEXTURE_1D: 648 return GL_PROXY_TEXTURE_1D; 649 case GL_TEXTURE_2D: 650 case GL_PROXY_TEXTURE_2D: 651 return GL_PROXY_TEXTURE_2D; 652 case GL_TEXTURE_3D: 653 case GL_PROXY_TEXTURE_3D: 654 return GL_PROXY_TEXTURE_3D; 655 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: 656 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: 657 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: 658 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: 659 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: 660 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: 661 case GL_TEXTURE_CUBE_MAP_ARB: 662 case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 663 return GL_PROXY_TEXTURE_CUBE_MAP_ARB; 664 case GL_TEXTURE_RECTANGLE_NV: 665 case GL_PROXY_TEXTURE_RECTANGLE_NV: 666 return GL_PROXY_TEXTURE_RECTANGLE_NV; 667 case GL_TEXTURE_1D_ARRAY_EXT: 668 case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 669 return GL_PROXY_TEXTURE_1D_ARRAY_EXT; 670 case GL_TEXTURE_2D_ARRAY_EXT: 671 case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 672 return GL_PROXY_TEXTURE_2D_ARRAY_EXT; 673 default: 674 _mesa_problem(NULL, "unexpected target in get_proxy_target()"); 675 return 0; 676 } 677} 678 679 680/** 681 * Get the texture object that corresponds to the target of the given 682 * texture unit. 683 * 684 * \param ctx GL context. 685 * \param texUnit texture unit. 686 * \param target texture target. 687 * 688 * \return pointer to the texture object on success, or NULL on failure. 689 * 690 * \sa gl_texture_unit. 691 */ 692struct gl_texture_object * 693_mesa_select_tex_object(struct gl_context *ctx, 694 const struct gl_texture_unit *texUnit, 695 GLenum target) 696{ 697 switch (target) { 698 case GL_TEXTURE_1D: 699 return texUnit->CurrentTex[TEXTURE_1D_INDEX]; 700 case GL_PROXY_TEXTURE_1D: 701 return ctx->Texture.ProxyTex[TEXTURE_1D_INDEX]; 702 case GL_TEXTURE_2D: 703 return texUnit->CurrentTex[TEXTURE_2D_INDEX]; 704 case GL_PROXY_TEXTURE_2D: 705 return ctx->Texture.ProxyTex[TEXTURE_2D_INDEX]; 706 case GL_TEXTURE_3D: 707 return texUnit->CurrentTex[TEXTURE_3D_INDEX]; 708 case GL_PROXY_TEXTURE_3D: 709 return ctx->Texture.ProxyTex[TEXTURE_3D_INDEX]; 710 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: 711 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: 712 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: 713 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: 714 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: 715 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: 716 case GL_TEXTURE_CUBE_MAP_ARB: 717 return ctx->Extensions.ARB_texture_cube_map 718 ? texUnit->CurrentTex[TEXTURE_CUBE_INDEX] : NULL; 719 case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 720 return ctx->Extensions.ARB_texture_cube_map 721 ? ctx->Texture.ProxyTex[TEXTURE_CUBE_INDEX] : NULL; 722 case GL_TEXTURE_RECTANGLE_NV: 723 return ctx->Extensions.NV_texture_rectangle 724 ? texUnit->CurrentTex[TEXTURE_RECT_INDEX] : NULL; 725 case GL_PROXY_TEXTURE_RECTANGLE_NV: 726 return ctx->Extensions.NV_texture_rectangle 727 ? ctx->Texture.ProxyTex[TEXTURE_RECT_INDEX] : NULL; 728 case GL_TEXTURE_1D_ARRAY_EXT: 729 return ctx->Extensions.MESA_texture_array 730 ? texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX] : NULL; 731 case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 732 return ctx->Extensions.MESA_texture_array 733 ? ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX] : NULL; 734 case GL_TEXTURE_2D_ARRAY_EXT: 735 return ctx->Extensions.MESA_texture_array 736 ? texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX] : NULL; 737 case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 738 return ctx->Extensions.MESA_texture_array 739 ? ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX] : NULL; 740 default: 741 _mesa_problem(NULL, "bad target in _mesa_select_tex_object()"); 742 return NULL; 743 } 744} 745 746 747/** 748 * Return pointer to texture object for given target on current texture unit. 749 */ 750struct gl_texture_object * 751_mesa_get_current_tex_object(struct gl_context *ctx, GLenum target) 752{ 753 struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx); 754 return _mesa_select_tex_object(ctx, texUnit, target); 755} 756 757 758/** 759 * Get a texture image pointer from a texture object, given a texture 760 * target and mipmap level. The target and level parameters should 761 * have already been error-checked. 762 * 763 * \param ctx GL context. 764 * \param texObj texture unit. 765 * \param target texture target. 766 * \param level image level. 767 * 768 * \return pointer to the texture image structure, or NULL on failure. 769 */ 770struct gl_texture_image * 771_mesa_select_tex_image(struct gl_context *ctx, 772 const struct gl_texture_object *texObj, 773 GLenum target, GLint level) 774{ 775 const GLuint face = _mesa_tex_target_to_face(target); 776 777 ASSERT(texObj); 778 ASSERT(level >= 0); 779 ASSERT(level < MAX_TEXTURE_LEVELS); 780 781 return texObj->Image[face][level]; 782} 783 784 785/** 786 * Like _mesa_select_tex_image() but if the image doesn't exist, allocate 787 * it and install it. Only return NULL if passed a bad parameter or run 788 * out of memory. 789 */ 790struct gl_texture_image * 791_mesa_get_tex_image(struct gl_context *ctx, struct gl_texture_object *texObj, 792 GLenum target, GLint level) 793{ 794 struct gl_texture_image *texImage; 795 796 if (!texObj) 797 return NULL; 798 799 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 800 if (!texImage) { 801 texImage = ctx->Driver.NewTextureImage(ctx); 802 if (!texImage) { 803 _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture image allocation"); 804 return NULL; 805 } 806 807 _mesa_set_tex_image(texObj, target, level, texImage); 808 } 809 810 return texImage; 811} 812 813 814/** 815 * Return pointer to the specified proxy texture image. 816 * Note that proxy textures are per-context, not per-texture unit. 817 * \return pointer to texture image or NULL if invalid target, invalid 818 * level, or out of memory. 819 */ 820struct gl_texture_image * 821_mesa_get_proxy_tex_image(struct gl_context *ctx, GLenum target, GLint level) 822{ 823 struct gl_texture_image *texImage; 824 GLuint texIndex; 825 826 if (level < 0 ) 827 return NULL; 828 829 switch (target) { 830 case GL_PROXY_TEXTURE_1D: 831 if (level >= ctx->Const.MaxTextureLevels) 832 return NULL; 833 texIndex = TEXTURE_1D_INDEX; 834 break; 835 case GL_PROXY_TEXTURE_2D: 836 if (level >= ctx->Const.MaxTextureLevels) 837 return NULL; 838 texIndex = TEXTURE_2D_INDEX; 839 break; 840 case GL_PROXY_TEXTURE_3D: 841 if (level >= ctx->Const.Max3DTextureLevels) 842 return NULL; 843 texIndex = TEXTURE_3D_INDEX; 844 break; 845 case GL_PROXY_TEXTURE_CUBE_MAP: 846 if (level >= ctx->Const.MaxCubeTextureLevels) 847 return NULL; 848 texIndex = TEXTURE_CUBE_INDEX; 849 break; 850 case GL_PROXY_TEXTURE_RECTANGLE_NV: 851 if (level > 0) 852 return NULL; 853 texIndex = TEXTURE_RECT_INDEX; 854 break; 855 case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 856 if (level >= ctx->Const.MaxTextureLevels) 857 return NULL; 858 texIndex = TEXTURE_1D_ARRAY_INDEX; 859 break; 860 case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 861 if (level >= ctx->Const.MaxTextureLevels) 862 return NULL; 863 texIndex = TEXTURE_2D_ARRAY_INDEX; 864 break; 865 default: 866 return NULL; 867 } 868 869 texImage = ctx->Texture.ProxyTex[texIndex]->Image[0][level]; 870 if (!texImage) { 871 texImage = ctx->Driver.NewTextureImage(ctx); 872 if (!texImage) { 873 _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation"); 874 return NULL; 875 } 876 ctx->Texture.ProxyTex[texIndex]->Image[0][level] = texImage; 877 /* Set the 'back' pointer */ 878 texImage->TexObject = ctx->Texture.ProxyTex[texIndex]; 879 } 880 return texImage; 881} 882 883 884/** 885 * Get the maximum number of allowed mipmap levels. 886 * 887 * \param ctx GL context. 888 * \param target texture target. 889 * 890 * \return the maximum number of allowed mipmap levels for the given 891 * texture target, or zero if passed a bad target. 892 * 893 * \sa gl_constants. 894 */ 895GLint 896_mesa_max_texture_levels(struct gl_context *ctx, GLenum target) 897{ 898 switch (target) { 899 case GL_TEXTURE_1D: 900 case GL_PROXY_TEXTURE_1D: 901 case GL_TEXTURE_2D: 902 case GL_PROXY_TEXTURE_2D: 903 return ctx->Const.MaxTextureLevels; 904 case GL_TEXTURE_3D: 905 case GL_PROXY_TEXTURE_3D: 906 return ctx->Const.Max3DTextureLevels; 907 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: 908 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: 909 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: 910 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: 911 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: 912 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: 913 case GL_TEXTURE_CUBE_MAP_ARB: 914 case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 915 return ctx->Extensions.ARB_texture_cube_map 916 ? ctx->Const.MaxCubeTextureLevels : 0; 917 case GL_TEXTURE_RECTANGLE_NV: 918 case GL_PROXY_TEXTURE_RECTANGLE_NV: 919 return ctx->Extensions.NV_texture_rectangle ? 1 : 0; 920 case GL_TEXTURE_1D_ARRAY_EXT: 921 case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 922 case GL_TEXTURE_2D_ARRAY_EXT: 923 case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 924 return ctx->Extensions.MESA_texture_array 925 ? ctx->Const.MaxTextureLevels : 0; 926 default: 927 return 0; /* bad target */ 928 } 929} 930 931 932/** 933 * Return number of dimensions per mipmap level for the given texture target. 934 */ 935GLint 936_mesa_get_texture_dimensions(GLenum target) 937{ 938 switch (target) { 939 case GL_TEXTURE_1D: 940 case GL_PROXY_TEXTURE_1D: 941 return 1; 942 case GL_TEXTURE_2D: 943 case GL_TEXTURE_RECTANGLE: 944 case GL_TEXTURE_CUBE_MAP: 945 case GL_PROXY_TEXTURE_2D: 946 case GL_PROXY_TEXTURE_RECTANGLE: 947 case GL_PROXY_TEXTURE_CUBE_MAP: 948 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 949 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 950 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 951 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 952 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 953 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 954 case GL_TEXTURE_1D_ARRAY: 955 case GL_PROXY_TEXTURE_1D_ARRAY: 956 return 2; 957 case GL_TEXTURE_3D: 958 case GL_PROXY_TEXTURE_3D: 959 case GL_TEXTURE_2D_ARRAY: 960 case GL_PROXY_TEXTURE_2D_ARRAY: 961 return 3; 962 default: 963 _mesa_problem(NULL, "invalid target 0x%x in get_texture_dimensions()", 964 target); 965 return 2; 966 } 967} 968 969 970 971 972#if 000 /* not used anymore */ 973/* 974 * glTexImage[123]D can accept a NULL image pointer. In this case we 975 * create a texture image with unspecified image contents per the OpenGL 976 * spec. 977 */ 978static GLubyte * 979make_null_texture(GLint width, GLint height, GLint depth, GLenum format) 980{ 981 const GLint components = _mesa_components_in_format(format); 982 const GLint numPixels = width * height * depth; 983 GLubyte *data = (GLubyte *) MALLOC(numPixels * components * sizeof(GLubyte)); 984 985#ifdef DEBUG 986 /* 987 * Let's see if anyone finds this. If glTexImage2D() is called with 988 * a NULL image pointer then load the texture image with something 989 * interesting instead of leaving it indeterminate. 990 */ 991 if (data) { 992 static const char message[8][32] = { 993 " X X XXXXX XXX X ", 994 " XX XX X X X X X ", 995 " X X X X X X X ", 996 " X X XXXX XXX XXXXX ", 997 " X X X X X X ", 998 " X X X X X X X ", 999 " X X XXXXX XXX X X ", 1000 " " 1001 }; 1002 1003 GLubyte *imgPtr = data; 1004 GLint h, i, j, k; 1005 for (h = 0; h < depth; h++) { 1006 for (i = 0; i < height; i++) { 1007 GLint srcRow = 7 - (i % 8); 1008 for (j = 0; j < width; j++) { 1009 GLint srcCol = j % 32; 1010 GLubyte texel = (message[srcRow][srcCol]=='X') ? 255 : 70; 1011 for (k = 0; k < components; k++) { 1012 *imgPtr++ = texel; 1013 } 1014 } 1015 } 1016 } 1017 } 1018#endif 1019 1020 return data; 1021} 1022#endif 1023 1024 1025 1026/** 1027 * Reset the fields of a gl_texture_image struct to zero. 1028 * 1029 * \param img texture image structure. 1030 * 1031 * This is called when a proxy texture test fails, we set all the 1032 * image members (except DriverData) to zero. 1033 * It's also used in glTexImage[123]D as a safeguard to be sure all 1034 * required fields get initialized properly by the Driver.TexImage[123]D 1035 * functions. 1036 */ 1037static void 1038clear_teximage_fields(struct gl_texture_image *img) 1039{ 1040 ASSERT(img); 1041 img->_BaseFormat = 0; 1042 img->InternalFormat = 0; 1043 img->Border = 0; 1044 img->Width = 0; 1045 img->Height = 0; 1046 img->Depth = 0; 1047 img->RowStride = 0; 1048 if (img->ImageOffsets) { 1049 free(img->ImageOffsets); 1050 img->ImageOffsets = NULL; 1051 } 1052 img->Width2 = 0; 1053 img->Height2 = 0; 1054 img->Depth2 = 0; 1055 img->WidthLog2 = 0; 1056 img->HeightLog2 = 0; 1057 img->DepthLog2 = 0; 1058 img->Data = NULL; 1059 img->TexFormat = MESA_FORMAT_NONE; 1060 img->FetchTexelc = NULL; 1061 img->FetchTexelf = NULL; 1062} 1063 1064 1065/** 1066 * Initialize basic fields of the gl_texture_image struct. 1067 * 1068 * \param ctx GL context. 1069 * \param target texture target (GL_TEXTURE_1D, GL_TEXTURE_RECTANGLE, etc). 1070 * \param img texture image structure to be initialized. 1071 * \param width image width. 1072 * \param height image height. 1073 * \param depth image depth. 1074 * \param border image border. 1075 * \param internalFormat internal format. 1076 * \param format the actual hardware format (one of MESA_FORMAT_*) 1077 * 1078 * Fills in the fields of \p img with the given information. 1079 * Note: width, height and depth include the border. 1080 */ 1081void 1082_mesa_init_teximage_fields(struct gl_context *ctx, GLenum target, 1083 struct gl_texture_image *img, 1084 GLsizei width, GLsizei height, GLsizei depth, 1085 GLint border, GLenum internalFormat, 1086 gl_format format) 1087{ 1088 GLint i, dims; 1089 1090 ASSERT(img); 1091 ASSERT(width >= 0); 1092 ASSERT(height >= 0); 1093 ASSERT(depth >= 0); 1094 1095 img->_BaseFormat = _mesa_base_tex_format( ctx, internalFormat ); 1096 ASSERT(img->_BaseFormat > 0); 1097 img->InternalFormat = internalFormat; 1098 img->Border = border; 1099 img->Width = width; 1100 img->Height = height; 1101 img->Depth = depth; 1102 1103 img->Width2 = width - 2 * border; /* == 1 << img->WidthLog2; */ 1104 img->WidthLog2 = logbase2(img->Width2); 1105 1106 if (height == 1) { /* 1-D texture */ 1107 img->Height2 = 1; 1108 img->HeightLog2 = 0; 1109 } 1110 else { 1111 img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */ 1112 img->HeightLog2 = logbase2(img->Height2); 1113 } 1114 1115 if (depth == 1) { /* 2-D texture */ 1116 img->Depth2 = 1; 1117 img->DepthLog2 = 0; 1118 } 1119 else { 1120 img->Depth2 = depth - 2 * border; /* == 1 << img->DepthLog2; */ 1121 img->DepthLog2 = logbase2(img->Depth2); 1122 } 1123 1124 img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2); 1125 1126 if ((width == 1 || _mesa_is_pow_two(img->Width2)) && 1127 (height == 1 || _mesa_is_pow_two(img->Height2)) && 1128 (depth == 1 || _mesa_is_pow_two(img->Depth2))) 1129 img->_IsPowerOfTwo = GL_TRUE; 1130 else 1131 img->_IsPowerOfTwo = GL_FALSE; 1132 1133 /* RowStride and ImageOffsets[] describe how to address texels in 'Data' */ 1134 img->RowStride = width; 1135 /* Allocate the ImageOffsets array and initialize to typical values. 1136 * We allocate the array for 1D/2D textures too in order to avoid special- 1137 * case code in the texstore routines. 1138 */ 1139 if (img->ImageOffsets) 1140 free(img->ImageOffsets); 1141 img->ImageOffsets = (GLuint *) malloc(depth * sizeof(GLuint)); 1142 for (i = 0; i < depth; i++) { 1143 img->ImageOffsets[i] = i * width * height; 1144 } 1145 1146 /* Compute Width/Height/DepthScale for mipmap lod computation */ 1147 if (target == GL_TEXTURE_RECTANGLE_NV) { 1148 /* scale = 1.0 since texture coords directly map to texels */ 1149 img->WidthScale = 1.0; 1150 img->HeightScale = 1.0; 1151 img->DepthScale = 1.0; 1152 } 1153 else { 1154 img->WidthScale = (GLfloat) img->Width; 1155 img->HeightScale = (GLfloat) img->Height; 1156 img->DepthScale = (GLfloat) img->Depth; 1157 } 1158 1159 img->TexFormat = format; 1160 1161 dims = _mesa_get_texture_dimensions(target); 1162 1163 _mesa_set_fetch_functions(img, dims); 1164} 1165 1166 1167/** 1168 * Free and clear fields of the gl_texture_image struct. 1169 * 1170 * \param ctx GL context. 1171 * \param texImage texture image structure to be cleared. 1172 * 1173 * After the call, \p texImage will have no data associated with it. Its 1174 * fields are cleared so that its parent object will test incomplete. 1175 */ 1176void 1177_mesa_clear_texture_image(struct gl_context *ctx, 1178 struct gl_texture_image *texImage) 1179{ 1180 ctx->Driver.FreeTexImageData(ctx, texImage); 1181 clear_teximage_fields(texImage); 1182} 1183 1184 1185/** 1186 * This is the fallback for Driver.TestProxyTexImage(). Test the texture 1187 * level, width, height and depth against the ctx->Const limits for textures. 1188 * 1189 * A hardware driver might override this function if, for example, the 1190 * max 3D texture size is 512x512x64 (i.e. not a cube). 1191 * 1192 * Note that width, height, depth == 0 is not an error. However, a 1193 * texture with zero width/height/depth will be considered "incomplete" 1194 * and texturing will effectively be disabled. 1195 * 1196 * \param target one of GL_PROXY_TEXTURE_1D, GL_PROXY_TEXTURE_2D, 1197 * GL_PROXY_TEXTURE_3D, GL_PROXY_TEXTURE_RECTANGLE_NV, 1198 * GL_PROXY_TEXTURE_CUBE_MAP_ARB. 1199 * \param level as passed to glTexImage 1200 * \param internalFormat as passed to glTexImage 1201 * \param format as passed to glTexImage 1202 * \param type as passed to glTexImage 1203 * \param width as passed to glTexImage 1204 * \param height as passed to glTexImage 1205 * \param depth as passed to glTexImage 1206 * \param border as passed to glTexImage 1207 * \return GL_TRUE if the image is acceptable, GL_FALSE if not acceptable. 1208 */ 1209GLboolean 1210_mesa_test_proxy_teximage(struct gl_context *ctx, GLenum target, GLint level, 1211 GLint internalFormat, GLenum format, GLenum type, 1212 GLint width, GLint height, GLint depth, GLint border) 1213{ 1214 GLint maxSize; 1215 1216 (void) internalFormat; 1217 (void) format; 1218 (void) type; 1219 1220 switch (target) { 1221 case GL_PROXY_TEXTURE_1D: 1222 maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 1223 if (width < 2 * border || width > 2 + maxSize) 1224 return GL_FALSE; 1225 if (level >= ctx->Const.MaxTextureLevels) 1226 return GL_FALSE; 1227 if (!ctx->Extensions.ARB_texture_non_power_of_two) { 1228 if (width > 0 && !_mesa_is_pow_two(width - 2 * border)) 1229 return GL_FALSE; 1230 } 1231 return GL_TRUE; 1232 1233 case GL_PROXY_TEXTURE_2D: 1234 maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 1235 if (width < 2 * border || width > 2 + maxSize) 1236 return GL_FALSE; 1237 if (height < 2 * border || height > 2 + maxSize) 1238 return GL_FALSE; 1239 if (level >= ctx->Const.MaxTextureLevels) 1240 return GL_FALSE; 1241 if (!ctx->Extensions.ARB_texture_non_power_of_two) { 1242 if (width > 0 && !_mesa_is_pow_two(width - 2 * border)) 1243 return GL_FALSE; 1244 if (height > 0 && !_mesa_is_pow_two(height - 2 * border)) 1245 return GL_FALSE; 1246 } 1247 return GL_TRUE; 1248 1249 case GL_PROXY_TEXTURE_3D: 1250 maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1); 1251 if (width < 2 * border || width > 2 + maxSize) 1252 return GL_FALSE; 1253 if (height < 2 * border || height > 2 + maxSize) 1254 return GL_FALSE; 1255 if (depth < 2 * border || depth > 2 + maxSize) 1256 return GL_FALSE; 1257 if (level >= ctx->Const.Max3DTextureLevels) 1258 return GL_FALSE; 1259 if (!ctx->Extensions.ARB_texture_non_power_of_two) { 1260 if (width > 0 && !_mesa_is_pow_two(width - 2 * border)) 1261 return GL_FALSE; 1262 if (height > 0 && !_mesa_is_pow_two(height - 2 * border)) 1263 return GL_FALSE; 1264 if (depth > 0 && !_mesa_is_pow_two(depth - 2 * border)) 1265 return GL_FALSE; 1266 } 1267 return GL_TRUE; 1268 1269 case GL_PROXY_TEXTURE_RECTANGLE_NV: 1270 maxSize = ctx->Const.MaxTextureRectSize; 1271 if (width < 0 || width > maxSize) 1272 return GL_FALSE; 1273 if (height < 0 || height > maxSize) 1274 return GL_FALSE; 1275 if (level != 0) 1276 return GL_FALSE; 1277 return GL_TRUE; 1278 1279 case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 1280 maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1); 1281 if (width < 2 * border || width > 2 + maxSize) 1282 return GL_FALSE; 1283 if (height < 2 * border || height > 2 + maxSize) 1284 return GL_FALSE; 1285 if (level >= ctx->Const.MaxCubeTextureLevels) 1286 return GL_FALSE; 1287 if (!ctx->Extensions.ARB_texture_non_power_of_two) { 1288 if (width > 0 && !_mesa_is_pow_two(width - 2 * border)) 1289 return GL_FALSE; 1290 if (height > 0 && !_mesa_is_pow_two(height - 2 * border)) 1291 return GL_FALSE; 1292 } 1293 return GL_TRUE; 1294 1295 case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 1296 maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 1297 if (width < 2 * border || width > 2 + maxSize) 1298 return GL_FALSE; 1299 if (height < 1 || height > ctx->Const.MaxArrayTextureLayers) 1300 return GL_FALSE; 1301 if (level >= ctx->Const.MaxTextureLevels) 1302 return GL_FALSE; 1303 if (!ctx->Extensions.ARB_texture_non_power_of_two) { 1304 if (width > 0 && !_mesa_is_pow_two(width - 2 * border)) 1305 return GL_FALSE; 1306 } 1307 return GL_TRUE; 1308 1309 case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 1310 maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 1311 if (width < 2 * border || width > 2 + maxSize) 1312 return GL_FALSE; 1313 if (height < 2 * border || height > 2 + maxSize) 1314 return GL_FALSE; 1315 if (depth < 1 || depth > ctx->Const.MaxArrayTextureLayers) 1316 return GL_FALSE; 1317 if (level >= ctx->Const.MaxTextureLevels) 1318 return GL_FALSE; 1319 if (!ctx->Extensions.ARB_texture_non_power_of_two) { 1320 if (width > 0 && !_mesa_is_pow_two(width - 2 * border)) 1321 return GL_FALSE; 1322 if (height > 0 && !_mesa_is_pow_two(height - 2 * border)) 1323 return GL_FALSE; 1324 } 1325 return GL_TRUE; 1326 1327 default: 1328 _mesa_problem(ctx, "Invalid target in _mesa_test_proxy_teximage"); 1329 return GL_FALSE; 1330 } 1331} 1332 1333 1334/** 1335 * Check if the memory used by the texture would exceed the driver's limit. 1336 * This lets us support a max 3D texture size of 8K (for example) but 1337 * prevents allocating a full 8K x 8K x 8K texture. 1338 * XXX this could be rolled into the proxy texture size test (above) but 1339 * we don't have the actual texture internal format at that point. 1340 */ 1341static GLboolean 1342legal_texture_size(struct gl_context *ctx, gl_format format, 1343 GLint width, GLint height, GLint depth) 1344{ 1345 uint64_t bytes = _mesa_format_image_size64(format, width, height, depth); 1346 uint64_t mbytes = bytes / (1024 * 1024); /* convert to MB */ 1347 return mbytes <= (uint64_t) ctx->Const.MaxTextureMbytes; 1348} 1349 1350 1351 1352/** 1353 * Helper function to determine whether a target and specific compression 1354 * format are supported. 1355 */ 1356static GLboolean 1357target_can_be_compressed(const struct gl_context *ctx, GLenum target, 1358 GLenum intFormat) 1359{ 1360 (void) intFormat; /* not used yet */ 1361 1362 switch (target) { 1363 case GL_TEXTURE_2D: 1364 case GL_PROXY_TEXTURE_2D: 1365 return GL_TRUE; /* true for any compressed format so far */ 1366 case GL_PROXY_TEXTURE_CUBE_MAP: 1367 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 1368 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 1369 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 1370 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 1371 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 1372 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 1373 return ctx->Extensions.ARB_texture_cube_map; 1374 case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 1375 case GL_TEXTURE_2D_ARRAY_EXT: 1376 return ctx->Extensions.MESA_texture_array; 1377 default: 1378 return GL_FALSE; 1379 } 1380} 1381 1382 1383/** 1384 * Check if the given texture target value is legal for a 1385 * glTexImage1/2/3D call. 1386 */ 1387static GLboolean 1388legal_teximage_target(struct gl_context *ctx, GLuint dims, GLenum target) 1389{ 1390 switch (dims) { 1391 case 1: 1392 switch (target) { 1393 case GL_TEXTURE_1D: 1394 case GL_PROXY_TEXTURE_1D: 1395 return GL_TRUE; 1396 default: 1397 return GL_FALSE; 1398 } 1399 case 2: 1400 switch (target) { 1401 case GL_TEXTURE_2D: 1402 case GL_PROXY_TEXTURE_2D: 1403 return GL_TRUE; 1404 case GL_PROXY_TEXTURE_CUBE_MAP: 1405 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 1406 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 1407 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 1408 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 1409 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 1410 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 1411 return ctx->Extensions.ARB_texture_cube_map; 1412 case GL_TEXTURE_RECTANGLE_NV: 1413 case GL_PROXY_TEXTURE_RECTANGLE_NV: 1414 return ctx->Extensions.NV_texture_rectangle; 1415 case GL_TEXTURE_1D_ARRAY_EXT: 1416 case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 1417 return ctx->Extensions.MESA_texture_array; 1418 default: 1419 return GL_FALSE; 1420 } 1421 case 3: 1422 switch (target) { 1423 case GL_TEXTURE_3D: 1424 case GL_PROXY_TEXTURE_3D: 1425 return GL_TRUE; 1426 case GL_TEXTURE_2D_ARRAY_EXT: 1427 case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 1428 return ctx->Extensions.MESA_texture_array; 1429 default: 1430 return GL_FALSE; 1431 } 1432 default: 1433 _mesa_problem(ctx, "invalid dims=%u in legal_teximage_target()", dims); 1434 return GL_FALSE; 1435 } 1436} 1437 1438 1439/** 1440 * Check if the given texture target value is legal for a 1441 * glTexSubImage, glCopyTexSubImage or glCopyTexImage call. 1442 * The difference compared to legal_teximage_target() above is that 1443 * proxy targets are not supported. 1444 */ 1445static GLboolean 1446legal_texsubimage_target(struct gl_context *ctx, GLuint dims, GLenum target) 1447{ 1448 switch (dims) { 1449 case 1: 1450 return target == GL_TEXTURE_1D; 1451 case 2: 1452 switch (target) { 1453 case GL_TEXTURE_2D: 1454 return GL_TRUE; 1455 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 1456 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 1457 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 1458 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 1459 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 1460 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 1461 return ctx->Extensions.ARB_texture_cube_map; 1462 case GL_TEXTURE_RECTANGLE_NV: 1463 return ctx->Extensions.NV_texture_rectangle; 1464 case GL_TEXTURE_1D_ARRAY_EXT: 1465 return ctx->Extensions.MESA_texture_array; 1466 default: 1467 return GL_FALSE; 1468 } 1469 case 3: 1470 switch (target) { 1471 case GL_TEXTURE_3D: 1472 return GL_TRUE; 1473 case GL_TEXTURE_2D_ARRAY_EXT: 1474 return ctx->Extensions.MESA_texture_array; 1475 default: 1476 return GL_FALSE; 1477 } 1478 default: 1479 _mesa_problem(ctx, "invalid dims=%u in legal_texsubimage_target()", 1480 dims); 1481 return GL_FALSE; 1482 } 1483} 1484 1485 1486/** 1487 * Test the glTexImage[123]D() parameters for errors. 1488 * 1489 * \param ctx GL context. 1490 * \param dimensions texture image dimensions (must be 1, 2 or 3). 1491 * \param target texture target given by the user. 1492 * \param level image level given by the user. 1493 * \param internalFormat internal format given by the user. 1494 * \param format pixel data format given by the user. 1495 * \param type pixel data type given by the user. 1496 * \param width image width given by the user. 1497 * \param height image height given by the user. 1498 * \param depth image depth given by the user. 1499 * \param border image border given by the user. 1500 * 1501 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 1502 * 1503 * Verifies each of the parameters against the constants specified in 1504 * __struct gl_contextRec::Const and the supported extensions, and according 1505 * to the OpenGL specification. 1506 */ 1507static GLboolean 1508texture_error_check( struct gl_context *ctx, 1509 GLuint dimensions, GLenum target, 1510 GLint level, GLint internalFormat, 1511 GLenum format, GLenum type, 1512 GLint width, GLint height, 1513 GLint depth, GLint border ) 1514{ 1515 const GLenum proxyTarget = get_proxy_target(target); 1516 const GLboolean isProxy = target == proxyTarget; 1517 GLboolean sizeOK = GL_TRUE; 1518 GLboolean colorFormat, indexFormat; 1519 1520 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */ 1521 if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 1522 if (!isProxy) { 1523 _mesa_error(ctx, GL_INVALID_VALUE, 1524 "glTexImage%dD(level=%d)", dimensions, level); 1525 } 1526 return GL_TRUE; 1527 } 1528 1529 /* Check border */ 1530 if (border < 0 || border > 1 || 1531 ((target == GL_TEXTURE_RECTANGLE_NV || 1532 target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) { 1533 if (!isProxy) { 1534 _mesa_error(ctx, GL_INVALID_VALUE, 1535 "glTexImage%dD(border=%d)", dimensions, border); 1536 } 1537 return GL_TRUE; 1538 } 1539 1540 if (width < 0 || height < 0 || depth < 0) { 1541 if (!isProxy) { 1542 _mesa_error(ctx, GL_INVALID_VALUE, 1543 "glTexImage%dD(width, height or depth < 0)", dimensions); 1544 } 1545 return GL_TRUE; 1546 } 1547 1548 /* Do this simple check before calling the TestProxyTexImage() function */ 1549 if (proxyTarget == GL_PROXY_TEXTURE_CUBE_MAP_ARB) { 1550 sizeOK = (width == height); 1551 } 1552 1553 /* 1554 * Use the proxy texture driver hook to see if the size/level/etc are 1555 * legal. 1556 */ 1557 sizeOK = sizeOK && ctx->Driver.TestProxyTexImage(ctx, proxyTarget, level, 1558 internalFormat, format, 1559 type, width, height, 1560 depth, border); 1561 if (!sizeOK) { 1562 if (!isProxy) { 1563 _mesa_error(ctx, GL_INVALID_VALUE, 1564 "glTexImage%dD(level=%d, width=%d, height=%d, depth=%d)", 1565 dimensions, level, width, height, depth); 1566 } 1567 return GL_TRUE; 1568 } 1569 1570 /* Check internalFormat */ 1571 if (_mesa_base_tex_format(ctx, internalFormat) < 0) { 1572 if (!isProxy) { 1573 _mesa_error(ctx, GL_INVALID_VALUE, 1574 "glTexImage%dD(internalFormat=%s)", 1575 dimensions, _mesa_lookup_enum_by_nr(internalFormat)); 1576 } 1577 return GL_TRUE; 1578 } 1579 1580 /* Check incoming image format and type */ 1581 if (!_mesa_is_legal_format_and_type(ctx, format, type)) { 1582 /* Normally, GL_INVALID_OPERATION is generated by a format/type 1583 * mismatch (see the 1.2 spec page 94, sec 3.6.4.). But with the 1584 * GL_EXT_texture_integer extension, some combinations should generate 1585 * GL_INVALID_ENUM instead (grr!). 1586 */ 1587 if (!isProxy) { 1588 GLenum error = _mesa_is_integer_format(format) 1589 ? GL_INVALID_ENUM : GL_INVALID_OPERATION; 1590 _mesa_error(ctx, error, 1591 "glTexImage%dD(incompatible format 0x%x, type 0x%x)", 1592 dimensions, format, type); 1593 } 1594 return GL_TRUE; 1595 } 1596 1597 /* make sure internal format and format basically agree */ 1598 colorFormat = _mesa_is_color_format(format); 1599 indexFormat = _mesa_is_index_format(format); 1600 if ((_mesa_is_color_format(internalFormat) && !colorFormat && !indexFormat) || 1601 (_mesa_is_index_format(internalFormat) && !indexFormat) || 1602 (_mesa_is_depth_format(internalFormat) != _mesa_is_depth_format(format)) || 1603 (_mesa_is_ycbcr_format(internalFormat) != _mesa_is_ycbcr_format(format)) || 1604 (_mesa_is_depthstencil_format(internalFormat) != _mesa_is_depthstencil_format(format)) || 1605 (_mesa_is_dudv_format(internalFormat) != _mesa_is_dudv_format(format))) { 1606 if (!isProxy) 1607 _mesa_error(ctx, GL_INVALID_OPERATION, 1608 "glTexImage%dD(incompatible internalFormat 0x%x, format 0x%x)", 1609 dimensions, internalFormat, format); 1610 return GL_TRUE; 1611 } 1612 1613 /* additional checks for ycbcr textures */ 1614 if (internalFormat == GL_YCBCR_MESA) { 1615 ASSERT(ctx->Extensions.MESA_ycbcr_texture); 1616 if (type != GL_UNSIGNED_SHORT_8_8_MESA && 1617 type != GL_UNSIGNED_SHORT_8_8_REV_MESA) { 1618 char message[100]; 1619 _mesa_snprintf(message, sizeof(message), 1620 "glTexImage%dD(format/type YCBCR mismatch", dimensions); 1621 _mesa_error(ctx, GL_INVALID_ENUM, "%s", message); 1622 return GL_TRUE; /* error */ 1623 } 1624 if (target != GL_TEXTURE_2D && 1625 target != GL_PROXY_TEXTURE_2D && 1626 target != GL_TEXTURE_RECTANGLE_NV && 1627 target != GL_PROXY_TEXTURE_RECTANGLE_NV) { 1628 if (!isProxy) 1629 _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage(target)"); 1630 return GL_TRUE; 1631 } 1632 if (border != 0) { 1633 if (!isProxy) { 1634 char message[100]; 1635 _mesa_snprintf(message, sizeof(message), 1636 "glTexImage%dD(format=GL_YCBCR_MESA and border=%d)", 1637 dimensions, border); 1638 _mesa_error(ctx, GL_INVALID_VALUE, "%s", message); 1639 } 1640 return GL_TRUE; 1641 } 1642 } 1643 1644 /* additional checks for depth textures */ 1645 if (_mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_COMPONENT) { 1646 /* Only 1D, 2D and rectangular textures supported, not 3D or cubes */ 1647 if (target != GL_TEXTURE_1D && 1648 target != GL_PROXY_TEXTURE_1D && 1649 target != GL_TEXTURE_2D && 1650 target != GL_PROXY_TEXTURE_2D && 1651 target != GL_TEXTURE_RECTANGLE_ARB && 1652 target != GL_PROXY_TEXTURE_RECTANGLE_ARB) { 1653 if (!isProxy) 1654 _mesa_error(ctx, GL_INVALID_ENUM, 1655 "glTexImage(target/internalFormat)"); 1656 return GL_TRUE; 1657 } 1658 } 1659 1660 /* additional checks for compressed textures */ 1661 if (_mesa_is_compressed_format(ctx, internalFormat)) { 1662 if (!target_can_be_compressed(ctx, target, internalFormat)) { 1663 if (!isProxy) 1664 _mesa_error(ctx, GL_INVALID_ENUM, 1665 "glTexImage%dD(target)", dimensions); 1666 return GL_TRUE; 1667 } 1668 if (border != 0) { 1669 if (!isProxy) { 1670 _mesa_error(ctx, GL_INVALID_OPERATION, 1671 "glTexImage%dD(border!=0)", dimensions); 1672 } 1673 return GL_TRUE; 1674 } 1675 } 1676 1677 /* additional checks for integer textures */ 1678 if (ctx->Extensions.EXT_texture_integer && 1679 (_mesa_is_integer_format(format) != 1680 _mesa_is_integer_format(internalFormat))) { 1681 if (!isProxy) { 1682 _mesa_error(ctx, GL_INVALID_OPERATION, 1683 "glTexImage%dD(integer/non-integer format mismatch)", 1684 dimensions); 1685 } 1686 return GL_TRUE; 1687 } 1688 1689 /* if we get here, the parameters are OK */ 1690 return GL_FALSE; 1691} 1692 1693 1694/** 1695 * Test glTexSubImage[123]D() parameters for errors. 1696 * 1697 * \param ctx GL context. 1698 * \param dimensions texture image dimensions (must be 1, 2 or 3). 1699 * \param target texture target given by the user. 1700 * \param level image level given by the user. 1701 * \param xoffset sub-image x offset given by the user. 1702 * \param yoffset sub-image y offset given by the user. 1703 * \param zoffset sub-image z offset given by the user. 1704 * \param format pixel data format given by the user. 1705 * \param type pixel data type given by the user. 1706 * \param width image width given by the user. 1707 * \param height image height given by the user. 1708 * \param depth image depth given by the user. 1709 * 1710 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 1711 * 1712 * Verifies each of the parameters against the constants specified in 1713 * __struct gl_contextRec::Const and the supported extensions, and according 1714 * to the OpenGL specification. 1715 */ 1716static GLboolean 1717subtexture_error_check( struct gl_context *ctx, GLuint dimensions, 1718 GLenum target, GLint level, 1719 GLint xoffset, GLint yoffset, GLint zoffset, 1720 GLint width, GLint height, GLint depth, 1721 GLenum format, GLenum type ) 1722{ 1723 /* Basic level check */ 1724 if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 1725 _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level=%d)", level); 1726 return GL_TRUE; 1727 } 1728 1729 /* Check for negative sizes */ 1730 if (width < 0) { 1731 _mesa_error(ctx, GL_INVALID_VALUE, 1732 "glTexSubImage%dD(width=%d)", dimensions, width); 1733 return GL_TRUE; 1734 } 1735 if (height < 0 && dimensions > 1) { 1736 _mesa_error(ctx, GL_INVALID_VALUE, 1737 "glTexSubImage%dD(height=%d)", dimensions, height); 1738 return GL_TRUE; 1739 } 1740 if (depth < 0 && dimensions > 2) { 1741 _mesa_error(ctx, GL_INVALID_VALUE, 1742 "glTexSubImage%dD(depth=%d)", dimensions, depth); 1743 return GL_TRUE; 1744 } 1745 1746 if (!_mesa_is_legal_format_and_type(ctx, format, type)) { 1747 /* As with the glTexImage2D check above, the error code here 1748 * depends on texture integer. 1749 */ 1750 GLenum error = _mesa_is_integer_format(format) 1751 ? GL_INVALID_OPERATION : GL_INVALID_ENUM; 1752 _mesa_error(ctx, error, 1753 "glTexSubImage%dD(incompatible format 0x%x, type 0x%x)", 1754 dimensions, format, type); 1755 return GL_TRUE; 1756 } 1757 1758 return GL_FALSE; 1759} 1760 1761 1762/** 1763 * Do second part of glTexSubImage which depends on the destination texture. 1764 * \return GL_TRUE if error recorded, GL_FALSE otherwise 1765 */ 1766static GLboolean 1767subtexture_error_check2( struct gl_context *ctx, GLuint dimensions, 1768 GLenum target, GLint level, 1769 GLint xoffset, GLint yoffset, GLint zoffset, 1770 GLint width, GLint height, GLint depth, 1771 GLenum format, GLenum type, 1772 const struct gl_texture_image *destTex ) 1773{ 1774 if (!destTex) { 1775 /* undefined image level */ 1776 _mesa_error(ctx, GL_INVALID_OPERATION, "glTexSubImage%dD", dimensions); 1777 return GL_TRUE; 1778 } 1779 1780 if (xoffset < -((GLint)destTex->Border)) { 1781 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset)", 1782 dimensions); 1783 return GL_TRUE; 1784 } 1785 if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) { 1786 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset+width)", 1787 dimensions); 1788 return GL_TRUE; 1789 } 1790 if (dimensions > 1) { 1791 if (yoffset < -((GLint)destTex->Border)) { 1792 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset)", 1793 dimensions); 1794 return GL_TRUE; 1795 } 1796 if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) { 1797 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset+height)", 1798 dimensions); 1799 return GL_TRUE; 1800 } 1801 } 1802 if (dimensions > 2) { 1803 if (zoffset < -((GLint)destTex->Border)) { 1804 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)"); 1805 return GL_TRUE; 1806 } 1807 if (zoffset + depth > (GLint) (destTex->Depth + destTex->Border)) { 1808 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)"); 1809 return GL_TRUE; 1810 } 1811 } 1812 1813 if (_mesa_is_format_compressed(destTex->TexFormat)) { 1814 GLuint bw, bh; 1815 1816 /* do tests which depend on compression block size */ 1817 _mesa_get_format_block_size(destTex->TexFormat, &bw, &bh); 1818 1819 /* offset must be multiple of block size */ 1820 if ((xoffset % bw != 0) || (yoffset % bh != 0)) { 1821 _mesa_error(ctx, GL_INVALID_OPERATION, 1822 "glTexSubImage%dD(xoffset = %d, yoffset = %d)", 1823 dimensions, xoffset, yoffset); 1824 return GL_TRUE; 1825 } 1826 /* size must be multiple of bw by bh or equal to whole texture size */ 1827 if ((width % bw != 0) && (GLuint) width != destTex->Width) { 1828 _mesa_error(ctx, GL_INVALID_OPERATION, 1829 "glTexSubImage%dD(width = %d)", dimensions, width); 1830 return GL_TRUE; 1831 } 1832 if ((height % bh != 0) && (GLuint) height != destTex->Height) { 1833 _mesa_error(ctx, GL_INVALID_OPERATION, 1834 "glTexSubImage%dD(height = %d)", dimensions, height); 1835 return GL_TRUE; 1836 } 1837 } 1838 1839 return GL_FALSE; 1840} 1841 1842 1843/** 1844 * Test glCopyTexImage[12]D() parameters for errors. 1845 * 1846 * \param ctx GL context. 1847 * \param dimensions texture image dimensions (must be 1, 2 or 3). 1848 * \param target texture target given by the user. 1849 * \param level image level given by the user. 1850 * \param internalFormat internal format given by the user. 1851 * \param width image width given by the user. 1852 * \param height image height given by the user. 1853 * \param border texture border. 1854 * 1855 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 1856 * 1857 * Verifies each of the parameters against the constants specified in 1858 * __struct gl_contextRec::Const and the supported extensions, and according 1859 * to the OpenGL specification. 1860 */ 1861static GLboolean 1862copytexture_error_check( struct gl_context *ctx, GLuint dimensions, 1863 GLenum target, GLint level, GLint internalFormat, 1864 GLint width, GLint height, GLint border ) 1865{ 1866 const GLenum proxyTarget = get_proxy_target(target); 1867 const GLenum type = GL_FLOAT; 1868 GLboolean sizeOK; 1869 GLint format; 1870 1871 /* check target */ 1872 if (!legal_texsubimage_target(ctx, dimensions, target)) { 1873 _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexImage%uD(target=%s)", 1874 dimensions, _mesa_lookup_enum_by_nr(target)); 1875 return GL_TRUE; 1876 } 1877 1878 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */ 1879 if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 1880 _mesa_error(ctx, GL_INVALID_VALUE, 1881 "glCopyTexImage%dD(level=%d)", dimensions, level); 1882 return GL_TRUE; 1883 } 1884 1885 /* Check that the source buffer is complete */ 1886 if (ctx->ReadBuffer->Name) { 1887 _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer); 1888 if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 1889 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 1890 "glCopyTexImage%dD(invalid readbuffer)", dimensions); 1891 return GL_TRUE; 1892 } 1893 } 1894 1895 /* Check border */ 1896 if (border < 0 || border > 1 || 1897 ((target == GL_TEXTURE_RECTANGLE_NV || 1898 target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) { 1899 return GL_TRUE; 1900 } 1901 1902 format = _mesa_base_tex_format(ctx, internalFormat); 1903 if (format < 0) { 1904 _mesa_error(ctx, GL_INVALID_VALUE, 1905 "glCopyTexImage%dD(internalFormat)", dimensions); 1906 return GL_TRUE; 1907 } 1908 1909 if (!_mesa_source_buffer_exists(ctx, format)) { 1910 _mesa_error(ctx, GL_INVALID_OPERATION, 1911 "glCopyTexImage%dD(missing readbuffer)", dimensions); 1912 return GL_TRUE; 1913 } 1914 1915 /* Do size, level checking */ 1916 sizeOK = (proxyTarget == GL_PROXY_TEXTURE_CUBE_MAP_ARB) 1917 ? (width == height) : 1; 1918 1919 sizeOK = sizeOK && ctx->Driver.TestProxyTexImage(ctx, proxyTarget, level, 1920 internalFormat, format, 1921 type, width, height, 1922 1, border); 1923 1924 if (!sizeOK) { 1925 if (dimensions == 1) { 1926 _mesa_error(ctx, GL_INVALID_VALUE, 1927 "glCopyTexImage1D(width=%d)", width); 1928 } 1929 else { 1930 ASSERT(dimensions == 2); 1931 _mesa_error(ctx, GL_INVALID_VALUE, 1932 "glCopyTexImage2D(width=%d, height=%d)", width, height); 1933 } 1934 return GL_TRUE; 1935 } 1936 1937 if (_mesa_is_compressed_format(ctx, internalFormat)) { 1938 if (!target_can_be_compressed(ctx, target, internalFormat)) { 1939 _mesa_error(ctx, GL_INVALID_ENUM, 1940 "glCopyTexImage%dD(target)", dimensions); 1941 return GL_TRUE; 1942 } 1943 if (border != 0) { 1944 _mesa_error(ctx, GL_INVALID_OPERATION, 1945 "glCopyTexImage%dD(border!=0)", dimensions); 1946 return GL_TRUE; 1947 } 1948 } 1949 else if (_mesa_is_depth_format(internalFormat)) { 1950 /* make sure we have depth/stencil buffers */ 1951 if (!ctx->ReadBuffer->_DepthBuffer) { 1952 _mesa_error(ctx, GL_INVALID_OPERATION, 1953 "glCopyTexImage%dD(no depth)", dimensions); 1954 return GL_TRUE; 1955 } 1956 } 1957 else if (_mesa_is_depthstencil_format(internalFormat)) { 1958 /* make sure we have depth/stencil buffers */ 1959 if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) { 1960 _mesa_error(ctx, GL_INVALID_OPERATION, 1961 "glCopyTexImage%dD(no depth/stencil buffer)", dimensions); 1962 return GL_TRUE; 1963 } 1964 } 1965 1966 /* if we get here, the parameters are OK */ 1967 return GL_FALSE; 1968} 1969 1970 1971/** 1972 * Test glCopyTexSubImage[12]D() parameters for errors. 1973 * Note that this is the first part of error checking. 1974 * See also copytexsubimage_error_check2() below for the second part. 1975 * 1976 * \param ctx GL context. 1977 * \param dimensions texture image dimensions (must be 1, 2 or 3). 1978 * \param target texture target given by the user. 1979 * \param level image level given by the user. 1980 * 1981 * \return GL_TRUE if an error was detected, or GL_FALSE if no errors. 1982 */ 1983static GLboolean 1984copytexsubimage_error_check1( struct gl_context *ctx, GLuint dimensions, 1985 GLenum target, GLint level) 1986{ 1987 /* Check that the source buffer is complete */ 1988 if (ctx->ReadBuffer->Name) { 1989 _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer); 1990 if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 1991 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 1992 "glCopyTexImage%dD(invalid readbuffer)", dimensions); 1993 return GL_TRUE; 1994 } 1995 } 1996 1997 /* check target (proxies not allowed) */ 1998 if (!legal_texsubimage_target(ctx, dimensions, target)) { 1999 _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexSubImage%uD(target=%s)", 2000 dimensions, _mesa_lookup_enum_by_nr(target)); 2001 return GL_TRUE; 2002 } 2003 2004 /* Check level */ 2005 if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 2006 _mesa_error(ctx, GL_INVALID_VALUE, 2007 "glCopyTexSubImage%dD(level=%d)", dimensions, level); 2008 return GL_TRUE; 2009 } 2010 2011 return GL_FALSE; 2012} 2013 2014 2015/** 2016 * Second part of error checking for glCopyTexSubImage[12]D(). 2017 * \param xoffset sub-image x offset given by the user. 2018 * \param yoffset sub-image y offset given by the user. 2019 * \param zoffset sub-image z offset given by the user. 2020 * \param width image width given by the user. 2021 * \param height image height given by the user. 2022 */ 2023static GLboolean 2024copytexsubimage_error_check2( struct gl_context *ctx, GLuint dimensions, 2025 GLenum target, GLint level, 2026 GLint xoffset, GLint yoffset, GLint zoffset, 2027 GLsizei width, GLsizei height, 2028 const struct gl_texture_image *teximage ) 2029{ 2030 /* check that dest tex image exists */ 2031 if (!teximage) { 2032 _mesa_error(ctx, GL_INVALID_OPERATION, 2033 "glCopyTexSubImage%dD(undefined texture level: %d)", 2034 dimensions, level); 2035 return GL_TRUE; 2036 } 2037 2038 /* Check size */ 2039 if (width < 0) { 2040 _mesa_error(ctx, GL_INVALID_VALUE, 2041 "glCopyTexSubImage%dD(width=%d)", dimensions, width); 2042 return GL_TRUE; 2043 } 2044 if (dimensions > 1 && height < 0) { 2045 _mesa_error(ctx, GL_INVALID_VALUE, 2046 "glCopyTexSubImage%dD(height=%d)", dimensions, height); 2047 return GL_TRUE; 2048 } 2049 2050 /* check x/y offsets */ 2051 if (xoffset < -((GLint)teximage->Border)) { 2052 _mesa_error(ctx, GL_INVALID_VALUE, 2053 "glCopyTexSubImage%dD(xoffset=%d)", dimensions, xoffset); 2054 return GL_TRUE; 2055 } 2056 if (xoffset + width > (GLint) (teximage->Width + teximage->Border)) { 2057 _mesa_error(ctx, GL_INVALID_VALUE, 2058 "glCopyTexSubImage%dD(xoffset+width)", dimensions); 2059 return GL_TRUE; 2060 } 2061 if (dimensions > 1) { 2062 if (yoffset < -((GLint)teximage->Border)) { 2063 _mesa_error(ctx, GL_INVALID_VALUE, 2064 "glCopyTexSubImage%dD(yoffset=%d)", dimensions, yoffset); 2065 return GL_TRUE; 2066 } 2067 /* NOTE: we're adding the border here, not subtracting! */ 2068 if (yoffset + height > (GLint) (teximage->Height + teximage->Border)) { 2069 _mesa_error(ctx, GL_INVALID_VALUE, 2070 "glCopyTexSubImage%dD(yoffset+height)", dimensions); 2071 return GL_TRUE; 2072 } 2073 } 2074 2075 /* check z offset */ 2076 if (dimensions > 2) { 2077 if (zoffset < -((GLint)teximage->Border)) { 2078 _mesa_error(ctx, GL_INVALID_VALUE, 2079 "glCopyTexSubImage%dD(zoffset)", dimensions); 2080 return GL_TRUE; 2081 } 2082 if (zoffset > (GLint) (teximage->Depth + teximage->Border)) { 2083 _mesa_error(ctx, GL_INVALID_VALUE, 2084 "glCopyTexSubImage%dD(zoffset+depth)", dimensions); 2085 return GL_TRUE; 2086 } 2087 } 2088 2089 if (_mesa_is_format_compressed(teximage->TexFormat)) { 2090 /* offset must be multiple of 4 */ 2091 if ((xoffset & 3) || (yoffset & 3)) { 2092 _mesa_error(ctx, GL_INVALID_VALUE, 2093 "glCopyTexSubImage%dD(xoffset or yoffset)", dimensions); 2094 return GL_TRUE; 2095 } 2096 /* size must be multiple of 4 */ 2097 if ((width & 3) != 0 && (GLuint) width != teximage->Width) { 2098 _mesa_error(ctx, GL_INVALID_VALUE, 2099 "glCopyTexSubImage%dD(width)", dimensions); 2100 return GL_TRUE; 2101 } 2102 if ((height & 3) != 0 && (GLuint) height != teximage->Height) { 2103 _mesa_error(ctx, GL_INVALID_VALUE, 2104 "glCopyTexSubImage%dD(height)", dimensions); 2105 return GL_TRUE; 2106 } 2107 } 2108 2109 if (teximage->InternalFormat == GL_YCBCR_MESA) { 2110 _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTexSubImage2D"); 2111 return GL_TRUE; 2112 } 2113 2114 if (!_mesa_source_buffer_exists(ctx, teximage->_BaseFormat)) { 2115 _mesa_error(ctx, GL_INVALID_OPERATION, 2116 "glCopyTexSubImage%dD(missing readbuffer, format=0x%x)", 2117 dimensions, teximage->_BaseFormat); 2118 return GL_TRUE; 2119 } 2120 2121 if (teximage->_BaseFormat == GL_DEPTH_COMPONENT) { 2122 if (!ctx->ReadBuffer->_DepthBuffer) { 2123 _mesa_error(ctx, GL_INVALID_OPERATION, 2124 "glCopyTexSubImage%dD(no depth buffer)", 2125 dimensions); 2126 return GL_TRUE; 2127 } 2128 } 2129 else if (teximage->_BaseFormat == GL_DEPTH_STENCIL_EXT) { 2130 if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) { 2131 _mesa_error(ctx, GL_INVALID_OPERATION, 2132 "glCopyTexSubImage%dD(no depth/stencil buffer)", 2133 dimensions); 2134 return GL_TRUE; 2135 } 2136 } 2137 2138 /* If copying into an integer texture, the source buffer must also be 2139 * integer-valued. 2140 */ 2141 if (_mesa_is_format_integer_color(teximage->TexFormat)) { 2142 struct gl_renderbuffer *rb = ctx->ReadBuffer->_ColorReadBuffer; 2143 if (!_mesa_is_format_integer_color(rb->Format)) { 2144 _mesa_error(ctx, GL_INVALID_OPERATION, 2145 "glCopyTexSubImage%dD(source buffer is not integer format)", 2146 dimensions); 2147 return GL_TRUE; 2148 } 2149 } 2150 2151 /* if we get here, the parameters are OK */ 2152 return GL_FALSE; 2153} 2154 2155 2156/** Callback info for walking over FBO hash table */ 2157struct cb_info 2158{ 2159 struct gl_context *ctx; 2160 struct gl_texture_object *texObj; 2161 GLuint level, face; 2162}; 2163 2164 2165/** 2166 * Check render to texture callback. Called from _mesa_HashWalk(). 2167 */ 2168static void 2169check_rtt_cb(GLuint key, void *data, void *userData) 2170{ 2171 struct gl_framebuffer *fb = (struct gl_framebuffer *) data; 2172 const struct cb_info *info = (struct cb_info *) userData; 2173 struct gl_context *ctx = info->ctx; 2174 const struct gl_texture_object *texObj = info->texObj; 2175 const GLuint level = info->level, face = info->face; 2176 2177 /* If this is a user-created FBO */ 2178 if (fb->Name) { 2179 GLuint i; 2180 /* check if any of the FBO's attachments point to 'texObj' */ 2181 for (i = 0; i < BUFFER_COUNT; i++) { 2182 struct gl_renderbuffer_attachment *att = fb->Attachment + i; 2183 if (att->Type == GL_TEXTURE && 2184 att->Texture == texObj && 2185 att->TextureLevel == level && 2186 att->CubeMapFace == face) { 2187 ASSERT(att->Texture->Image[att->CubeMapFace][att->TextureLevel]); 2188 /* Tell driver about the new renderbuffer texture */ 2189 ctx->Driver.RenderTexture(ctx, ctx->DrawBuffer, att); 2190 /* Mark fb status as indeterminate to force re-validation */ 2191 fb->_Status = 0; 2192 } 2193 } 2194 } 2195} 2196 2197 2198/** 2199 * When a texture image is specified we have to check if it's bound to 2200 * any framebuffer objects (render to texture) in order to detect changes 2201 * in size or format since that effects FBO completeness. 2202 * Any FBOs rendering into the texture must be re-validated. 2203 */ 2204static void 2205update_fbo_texture(struct gl_context *ctx, struct gl_texture_object *texObj, 2206 GLuint face, GLuint level) 2207{ 2208 /* Only check this texture if it's been marked as RenderToTexture */ 2209 if (texObj->_RenderToTexture) { 2210 struct cb_info info; 2211 info.ctx = ctx; 2212 info.texObj = texObj; 2213 info.level = level; 2214 info.face = face; 2215 _mesa_HashWalk(ctx->Shared->FrameBuffers, check_rtt_cb, &info); 2216 } 2217} 2218 2219 2220/** 2221 * If the texture object's GenerateMipmap flag is set and we've 2222 * changed the texture base level image, regenerate the rest of the 2223 * mipmap levels now. 2224 */ 2225static INLINE void 2226check_gen_mipmap(struct gl_context *ctx, GLenum target, 2227 struct gl_texture_object *texObj, GLint level) 2228{ 2229 ASSERT(target != GL_TEXTURE_CUBE_MAP); 2230 if (texObj->GenerateMipmap && 2231 level == texObj->BaseLevel && 2232 level < texObj->MaxLevel) { 2233 ASSERT(ctx->Driver.GenerateMipmap); 2234 ctx->Driver.GenerateMipmap(ctx, target, texObj); 2235 } 2236} 2237 2238 2239/** Debug helper: override the user-requested internal format */ 2240static GLenum 2241override_internal_format(GLenum internalFormat, GLint width, GLint height) 2242{ 2243#if 0 2244 if (internalFormat == GL_RGBA16F_ARB || 2245 internalFormat == GL_RGBA32F_ARB) { 2246 printf("Convert rgba float tex to int %d x %d\n", width, height); 2247 return GL_RGBA; 2248 } 2249 else if (internalFormat == GL_RGB16F_ARB || 2250 internalFormat == GL_RGB32F_ARB) { 2251 printf("Convert rgb float tex to int %d x %d\n", width, height); 2252 return GL_RGB; 2253 } 2254 else if (internalFormat == GL_LUMINANCE_ALPHA16F_ARB || 2255 internalFormat == GL_LUMINANCE_ALPHA32F_ARB) { 2256 printf("Convert luminance float tex to int %d x %d\n", width, height); 2257 return GL_LUMINANCE_ALPHA; 2258 } 2259 else if (internalFormat == GL_LUMINANCE16F_ARB || 2260 internalFormat == GL_LUMINANCE32F_ARB) { 2261 printf("Convert luminance float tex to int %d x %d\n", width, height); 2262 return GL_LUMINANCE; 2263 } 2264 else if (internalFormat == GL_ALPHA16F_ARB || 2265 internalFormat == GL_ALPHA32F_ARB) { 2266 printf("Convert luminance float tex to int %d x %d\n", width, height); 2267 return GL_ALPHA; 2268 } 2269 /* 2270 else if (internalFormat == GL_COMPRESSED_RGBA_S3TC_DXT1_EXT) { 2271 internalFormat = GL_RGBA; 2272 } 2273 */ 2274 else { 2275 return internalFormat; 2276 } 2277#else 2278 return internalFormat; 2279#endif 2280} 2281 2282 2283/** 2284 * Choose the actual hardware format for a texture image. 2285 * Try to use the same format as the previous image level when possible. 2286 * Otherwise, ask the driver for the best format. 2287 * It's important to try to choose a consistant format for all levels 2288 * for efficient texture memory layout/allocation. In particular, this 2289 * comes up during automatic mipmap generation. 2290 */ 2291gl_format 2292_mesa_choose_texture_format(struct gl_context *ctx, 2293 struct gl_texture_object *texObj, 2294 GLenum target, GLint level, 2295 GLenum internalFormat, GLenum format, GLenum type) 2296{ 2297 gl_format f; 2298 2299 /* see if we've already chosen a format for the previous level */ 2300 if (level > 0) { 2301 struct gl_texture_image *prevImage = 2302 _mesa_select_tex_image(ctx, texObj, target, level - 1); 2303 /* See if the prev level is defined and has an internal format which 2304 * matches the new internal format. 2305 */ 2306 if (prevImage && 2307 prevImage->Width > 0 && 2308 prevImage->InternalFormat == internalFormat) { 2309 /* use the same format */ 2310 ASSERT(prevImage->TexFormat != MESA_FORMAT_NONE); 2311 return prevImage->TexFormat; 2312 } 2313 } 2314 2315 /* choose format from scratch */ 2316 f = ctx->Driver.ChooseTextureFormat(ctx, internalFormat, format, type); 2317 ASSERT(f != MESA_FORMAT_NONE); 2318 return f; 2319} 2320 2321 2322/** 2323 * Common code to implement all the glTexImage1D/2D/3D functions. 2324 */ 2325static void 2326teximage(struct gl_context *ctx, GLuint dims, 2327 GLenum target, GLint level, GLint internalFormat, 2328 GLsizei width, GLsizei height, GLsizei depth, 2329 GLint border, GLenum format, GLenum type, 2330 const GLvoid *pixels) 2331{ 2332 GLboolean error; 2333 2334 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2335 2336 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 2337 _mesa_debug(ctx, "glTexImage%uD %s %d %s %d %d %d %d %s %s %p\n", 2338 dims, 2339 _mesa_lookup_enum_by_nr(target), level, 2340 _mesa_lookup_enum_by_nr(internalFormat), 2341 width, height, depth, border, 2342 _mesa_lookup_enum_by_nr(format), 2343 _mesa_lookup_enum_by_nr(type), pixels); 2344 2345 internalFormat = override_internal_format(internalFormat, width, height); 2346 2347 /* target error checking */ 2348 if (!legal_teximage_target(ctx, dims, target)) { 2349 _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage%uD(target=%s)", 2350 dims, _mesa_lookup_enum_by_nr(target)); 2351 return; 2352 } 2353 2354 /* general error checking */ 2355 error = texture_error_check(ctx, dims, target, level, internalFormat, 2356 format, type, width, height, depth, border); 2357 2358 if (_mesa_is_proxy_texture(target)) { 2359 /* Proxy texture: just clear or set state depending on error checking */ 2360 struct gl_texture_image *texImage = 2361 _mesa_get_proxy_tex_image(ctx, target, level); 2362 2363 if (error) { 2364 /* when error, clear all proxy texture image parameters */ 2365 if (texImage) 2366 clear_teximage_fields(texImage); 2367 } 2368 else { 2369 /* no error, set the tex image parameters */ 2370 struct gl_texture_object *texObj = 2371 _mesa_get_current_tex_object(ctx, target); 2372 gl_format texFormat = _mesa_choose_texture_format(ctx, texObj, 2373 target, level, 2374 internalFormat, 2375 format, type); 2376 2377 if (legal_texture_size(ctx, texFormat, width, height, depth)) { 2378 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 2379 depth, border, internalFormat, 2380 texFormat); 2381 } 2382 else if (texImage) { 2383 clear_teximage_fields(texImage); 2384 } 2385 } 2386 } 2387 else { 2388 /* non-proxy target */ 2389 const GLuint face = _mesa_tex_target_to_face(target); 2390 struct gl_texture_object *texObj; 2391 struct gl_texture_image *texImage; 2392 2393 if (error) { 2394 return; /* error was recorded */ 2395 } 2396 2397 if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) 2398 _mesa_update_state(ctx); 2399 2400 texObj = _mesa_get_current_tex_object(ctx, target); 2401 2402 _mesa_lock_texture(ctx, texObj); 2403 { 2404 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 2405 2406 if (!texImage) { 2407 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage%uD", dims); 2408 } 2409 else { 2410 gl_format texFormat; 2411 2412 if (texImage->Data) { 2413 ctx->Driver.FreeTexImageData( ctx, texImage ); 2414 } 2415 2416 ASSERT(texImage->Data == NULL); 2417 texFormat = _mesa_choose_texture_format(ctx, texObj, target, level, 2418 internalFormat, format, 2419 type); 2420 2421 if (legal_texture_size(ctx, texFormat, width, height, depth)) { 2422 _mesa_init_teximage_fields(ctx, target, texImage, 2423 width, height, depth, 2424 border, internalFormat, texFormat); 2425 2426 /* Give the texture to the driver. <pixels> may be null. */ 2427 ASSERT(ctx->Driver.TexImage3D); 2428 switch (dims) { 2429 case 1: 2430 ctx->Driver.TexImage1D(ctx, target, level, internalFormat, 2431 width, border, format, 2432 type, pixels, &ctx->Unpack, texObj, 2433 texImage); 2434 break; 2435 case 2: 2436 ctx->Driver.TexImage2D(ctx, target, level, internalFormat, 2437 width, height, border, format, 2438 type, pixels, &ctx->Unpack, texObj, 2439 texImage); 2440 break; 2441 case 3: 2442 ctx->Driver.TexImage3D(ctx, target, level, internalFormat, 2443 width, height, depth, border, format, 2444 type, pixels, &ctx->Unpack, texObj, 2445 texImage); 2446 break; 2447 default: 2448 _mesa_problem(ctx, "invalid dims=%u in teximage()", dims); 2449 } 2450 2451 check_gen_mipmap(ctx, target, texObj, level); 2452 2453 update_fbo_texture(ctx, texObj, face, level); 2454 2455 /* state update */ 2456 texObj->_Complete = GL_FALSE; 2457 ctx->NewState |= _NEW_TEXTURE; 2458 } 2459 else { 2460 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage%uD", dims); 2461 } 2462 } 2463 } 2464 _mesa_unlock_texture(ctx, texObj); 2465 } 2466} 2467 2468 2469/* 2470 * Called from the API. Note that width includes the border. 2471 */ 2472void GLAPIENTRY 2473_mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat, 2474 GLsizei width, GLint border, GLenum format, 2475 GLenum type, const GLvoid *pixels ) 2476{ 2477 GET_CURRENT_CONTEXT(ctx); 2478 teximage(ctx, 1, target, level, internalFormat, width, 1, 1, 2479 border, format, type, pixels); 2480} 2481 2482 2483void GLAPIENTRY 2484_mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat, 2485 GLsizei width, GLsizei height, GLint border, 2486 GLenum format, GLenum type, 2487 const GLvoid *pixels ) 2488{ 2489 GET_CURRENT_CONTEXT(ctx); 2490 teximage(ctx, 2, target, level, internalFormat, width, height, 1, 2491 border, format, type, pixels); 2492} 2493 2494 2495/* 2496 * Called by the API or display list executor. 2497 * Note that width and height include the border. 2498 */ 2499void GLAPIENTRY 2500_mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat, 2501 GLsizei width, GLsizei height, GLsizei depth, 2502 GLint border, GLenum format, GLenum type, 2503 const GLvoid *pixels ) 2504{ 2505 GET_CURRENT_CONTEXT(ctx); 2506 teximage(ctx, 3, target, level, internalFormat, width, height, depth, 2507 border, format, type, pixels); 2508} 2509 2510 2511void GLAPIENTRY 2512_mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat, 2513 GLsizei width, GLsizei height, GLsizei depth, 2514 GLint border, GLenum format, GLenum type, 2515 const GLvoid *pixels ) 2516{ 2517 _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height, 2518 depth, border, format, type, pixels); 2519} 2520 2521 2522#if FEATURE_OES_EGL_image 2523void GLAPIENTRY 2524_mesa_EGLImageTargetTexture2DOES (GLenum target, GLeglImageOES image) 2525{ 2526 struct gl_texture_object *texObj; 2527 struct gl_texture_image *texImage; 2528 GET_CURRENT_CONTEXT(ctx); 2529 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2530 2531 if (!ctx->Extensions.OES_EGL_image) { 2532 _mesa_error(ctx, GL_INVALID_OPERATION, 2533 "glEGLImageTargetTexture2DOES(unsupported)"); 2534 return; 2535 } 2536 2537 if (target != GL_TEXTURE_2D) { 2538 _mesa_error(ctx, GL_INVALID_ENUM, 2539 "glEGLImageTargetTexture2D(target=%d)", target); 2540 return; 2541 } 2542 2543 if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) 2544 _mesa_update_state(ctx); 2545 2546 texObj = _mesa_get_current_tex_object(ctx, target); 2547 _mesa_lock_texture(ctx, texObj); 2548 2549 texImage = _mesa_get_tex_image(ctx, texObj, target, 0); 2550 if (!texImage) { 2551 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glEGLImageTargetTexture2D"); 2552 } else { 2553 if (texImage->Data) 2554 ctx->Driver.FreeTexImageData( ctx, texImage ); 2555 2556 ASSERT(texImage->Data == NULL); 2557 ctx->Driver.EGLImageTargetTexture2D(ctx, target, 2558 texObj, texImage, image); 2559 2560 /* state update */ 2561 texObj->_Complete = GL_FALSE; 2562 ctx->NewState |= _NEW_TEXTURE; 2563 } 2564 _mesa_unlock_texture(ctx, texObj); 2565 2566} 2567#endif 2568 2569 2570 2571/** 2572 * Implement all the glTexSubImage1/2/3D() functions. 2573 */ 2574static void 2575texsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level, 2576 GLint xoffset, GLint yoffset, GLint zoffset, 2577 GLsizei width, GLsizei height, GLsizei depth, 2578 GLenum format, GLenum type, const GLvoid *pixels ) 2579{ 2580 struct gl_texture_object *texObj; 2581 struct gl_texture_image *texImage; 2582 2583 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2584 2585 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 2586 _mesa_debug(ctx, "glTexSubImage%uD %s %d %d %d %d %d %d %d %s %s %p\n", 2587 dims, 2588 _mesa_lookup_enum_by_nr(target), level, 2589 xoffset, yoffset, zoffset, width, height, depth, 2590 _mesa_lookup_enum_by_nr(format), 2591 _mesa_lookup_enum_by_nr(type), pixels); 2592 2593 /* check target (proxies not allowed) */ 2594 if (!legal_texsubimage_target(ctx, dims, target)) { 2595 _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage%uD(target=%s)", 2596 dims, _mesa_lookup_enum_by_nr(target)); 2597 return; 2598 } 2599 2600 if (ctx->NewState & _MESA_NEW_TRANSFER_STATE) 2601 _mesa_update_state(ctx); 2602 2603 if (subtexture_error_check(ctx, dims, target, level, xoffset, yoffset, zoffset, 2604 width, height, depth, format, type)) { 2605 return; /* error was detected */ 2606 } 2607 2608 texObj = _mesa_get_current_tex_object(ctx, target); 2609 2610 _mesa_lock_texture(ctx, texObj); 2611 { 2612 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 2613 2614 if (subtexture_error_check2(ctx, dims, target, level, 2615 xoffset, yoffset, zoffset, 2616 width, height, depth, 2617 format, type, texImage)) { 2618 /* error was recorded */ 2619 } 2620 else if (width > 0 && height > 0 && height > 0) { 2621 /* If we have a border, offset=-1 is legal. Bias by border width. */ 2622 switch (dims) { 2623 case 3: 2624 zoffset += texImage->Border; 2625 /* fall-through */ 2626 case 2: 2627 yoffset += texImage->Border; 2628 /* fall-through */ 2629 case 1: 2630 xoffset += texImage->Border; 2631 } 2632 2633 switch (dims) { 2634 case 1: 2635 ctx->Driver.TexSubImage1D(ctx, target, level, 2636 xoffset, width, 2637 format, type, pixels, 2638 &ctx->Unpack, texObj, texImage ); 2639 break; 2640 case 2: 2641 ctx->Driver.TexSubImage2D(ctx, target, level, 2642 xoffset, yoffset, width, height, 2643 format, type, pixels, 2644 &ctx->Unpack, texObj, texImage ); 2645 break; 2646 case 3: 2647 ctx->Driver.TexSubImage3D(ctx, target, level, 2648 xoffset, yoffset, zoffset, 2649 width, height, depth, 2650 format, type, pixels, 2651 &ctx->Unpack, texObj, texImage ); 2652 break; 2653 default: 2654 _mesa_problem(ctx, "unexpected dims in subteximage()"); 2655 } 2656 2657 check_gen_mipmap(ctx, target, texObj, level); 2658 2659 ctx->NewState |= _NEW_TEXTURE; 2660 } 2661 } 2662 _mesa_unlock_texture(ctx, texObj); 2663} 2664 2665 2666void GLAPIENTRY 2667_mesa_TexSubImage1D( GLenum target, GLint level, 2668 GLint xoffset, GLsizei width, 2669 GLenum format, GLenum type, 2670 const GLvoid *pixels ) 2671{ 2672 GET_CURRENT_CONTEXT(ctx); 2673 texsubimage(ctx, 1, target, level, 2674 xoffset, 0, 0, 2675 width, 1, 1, 2676 format, type, pixels); 2677} 2678 2679 2680void GLAPIENTRY 2681_mesa_TexSubImage2D( GLenum target, GLint level, 2682 GLint xoffset, GLint yoffset, 2683 GLsizei width, GLsizei height, 2684 GLenum format, GLenum type, 2685 const GLvoid *pixels ) 2686{ 2687 GET_CURRENT_CONTEXT(ctx); 2688 texsubimage(ctx, 2, target, level, 2689 xoffset, yoffset, 0, 2690 width, height, 1, 2691 format, type, pixels); 2692} 2693 2694 2695 2696void GLAPIENTRY 2697_mesa_TexSubImage3D( GLenum target, GLint level, 2698 GLint xoffset, GLint yoffset, GLint zoffset, 2699 GLsizei width, GLsizei height, GLsizei depth, 2700 GLenum format, GLenum type, 2701 const GLvoid *pixels ) 2702{ 2703 GET_CURRENT_CONTEXT(ctx); 2704 texsubimage(ctx, 3, target, level, 2705 xoffset, yoffset, zoffset, 2706 width, height, depth, 2707 format, type, pixels); 2708} 2709 2710 2711 2712/** 2713 * Implement the glCopyTexImage1/2D() functions. 2714 */ 2715static void 2716copyteximage(struct gl_context *ctx, GLuint dims, 2717 GLenum target, GLint level, GLenum internalFormat, 2718 GLint x, GLint y, GLsizei width, GLsizei height, GLint border ) 2719{ 2720 struct gl_texture_object *texObj; 2721 struct gl_texture_image *texImage; 2722 const GLuint face = _mesa_tex_target_to_face(target); 2723 2724 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2725 2726 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 2727 _mesa_debug(ctx, "glCopyTexImage%uD %s %d %s %d %d %d %d %d\n", 2728 dims, 2729 _mesa_lookup_enum_by_nr(target), level, 2730 _mesa_lookup_enum_by_nr(internalFormat), 2731 x, y, width, height, border); 2732 2733 if (ctx->NewState & NEW_COPY_TEX_STATE) 2734 _mesa_update_state(ctx); 2735 2736 if (copytexture_error_check(ctx, dims, target, level, internalFormat, 2737 width, height, border)) 2738 return; 2739 2740 texObj = _mesa_get_current_tex_object(ctx, target); 2741 2742 _mesa_lock_texture(ctx, texObj); 2743 { 2744 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 2745 2746 if (!texImage) { 2747 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage%uD", dims); 2748 } 2749 else { 2750 gl_format texFormat; 2751 2752 if (texImage->Data) { 2753 ctx->Driver.FreeTexImageData( ctx, texImage ); 2754 } 2755 2756 ASSERT(texImage->Data == NULL); 2757 2758 texFormat = _mesa_choose_texture_format(ctx, texObj, target, level, 2759 internalFormat, GL_NONE, 2760 GL_NONE); 2761 2762 if (legal_texture_size(ctx, texFormat, width, height, 1)) { 2763 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1, 2764 border, internalFormat, texFormat); 2765 2766 ASSERT(ctx->Driver.CopyTexImage2D); 2767 if (dims == 1) 2768 ctx->Driver.CopyTexImage1D(ctx, target, level, internalFormat, 2769 x, y, width, border); 2770 else 2771 ctx->Driver.CopyTexImage2D(ctx, target, level, internalFormat, 2772 x, y, width, height, border); 2773 2774 check_gen_mipmap(ctx, target, texObj, level); 2775 2776 update_fbo_texture(ctx, texObj, face, level); 2777 2778 /* state update */ 2779 texObj->_Complete = GL_FALSE; 2780 ctx->NewState |= _NEW_TEXTURE; 2781 } 2782 else { 2783 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage%uD", dims); 2784 } 2785 } 2786 } 2787 _mesa_unlock_texture(ctx, texObj); 2788} 2789 2790 2791 2792void GLAPIENTRY 2793_mesa_CopyTexImage1D( GLenum target, GLint level, 2794 GLenum internalFormat, 2795 GLint x, GLint y, 2796 GLsizei width, GLint border ) 2797{ 2798 GET_CURRENT_CONTEXT(ctx); 2799 copyteximage(ctx, 1, target, level, internalFormat, x, y, width, 1, border); 2800} 2801 2802 2803 2804void GLAPIENTRY 2805_mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat, 2806 GLint x, GLint y, GLsizei width, GLsizei height, 2807 GLint border ) 2808{ 2809 GET_CURRENT_CONTEXT(ctx); 2810 copyteximage(ctx, 2, target, level, internalFormat, 2811 x, y, width, height, border); 2812} 2813 2814 2815 2816/** 2817 * Implementation for glCopyTexSubImage1/2/3D() functions. 2818 */ 2819static void 2820copytexsubimage(struct gl_context *ctx, GLuint dims, GLenum target, GLint level, 2821 GLint xoffset, GLint yoffset, GLint zoffset, 2822 GLint x, GLint y, GLsizei width, GLsizei height) 2823{ 2824 struct gl_texture_object *texObj; 2825 struct gl_texture_image *texImage; 2826 2827 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 2828 2829 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 2830 _mesa_debug(ctx, "glCopyTexSubImage%uD %s %d %d %d %d %d %d %d %d\n", 2831 dims, 2832 _mesa_lookup_enum_by_nr(target), 2833 level, xoffset, yoffset, zoffset, x, y, width, height); 2834 2835 if (ctx->NewState & NEW_COPY_TEX_STATE) 2836 _mesa_update_state(ctx); 2837 2838 if (copytexsubimage_error_check1(ctx, dims, target, level)) 2839 return; 2840 2841 texObj = _mesa_get_current_tex_object(ctx, target); 2842 2843 _mesa_lock_texture(ctx, texObj); 2844 { 2845 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 2846 2847 if (copytexsubimage_error_check2(ctx, dims, target, level, xoffset, yoffset, 2848 zoffset, width, height, texImage)) { 2849 /* error was recored */ 2850 } 2851 else { 2852 /* If we have a border, offset=-1 is legal. Bias by border width. */ 2853 switch (dims) { 2854 case 3: 2855 zoffset += texImage->Border; 2856 /* fall-through */ 2857 case 2: 2858 yoffset += texImage->Border; 2859 /* fall-through */ 2860 case 1: 2861 xoffset += texImage->Border; 2862 } 2863 2864 if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, 2865 &width, &height)) { 2866 switch (dims) { 2867 case 1: 2868 ctx->Driver.CopyTexSubImage1D(ctx, target, level, 2869 xoffset, x, y, width); 2870 break; 2871 case 2: 2872 ctx->Driver.CopyTexSubImage2D(ctx, target, level, 2873 xoffset, yoffset, 2874 x, y, width, height); 2875 break; 2876 case 3: 2877 ctx->Driver.CopyTexSubImage3D(ctx, target, level, 2878 xoffset, yoffset, zoffset, 2879 x, y, width, height); 2880 break; 2881 default: 2882 _mesa_problem(ctx, "bad dims in copytexsubimage()"); 2883 } 2884 2885 check_gen_mipmap(ctx, target, texObj, level); 2886 2887 ctx->NewState |= _NEW_TEXTURE; 2888 } 2889 } 2890 } 2891 _mesa_unlock_texture(ctx, texObj); 2892} 2893 2894 2895void GLAPIENTRY 2896_mesa_CopyTexSubImage1D( GLenum target, GLint level, 2897 GLint xoffset, GLint x, GLint y, GLsizei width ) 2898{ 2899 GET_CURRENT_CONTEXT(ctx); 2900 copytexsubimage(ctx, 1, target, level, xoffset, 0, 0, x, y, width, 1); 2901} 2902 2903 2904 2905void GLAPIENTRY 2906_mesa_CopyTexSubImage2D( GLenum target, GLint level, 2907 GLint xoffset, GLint yoffset, 2908 GLint x, GLint y, GLsizei width, GLsizei height ) 2909{ 2910 GET_CURRENT_CONTEXT(ctx); 2911 copytexsubimage(ctx, 2, target, level, xoffset, yoffset, 0, x, y, 2912 width, height); 2913} 2914 2915 2916 2917void GLAPIENTRY 2918_mesa_CopyTexSubImage3D( GLenum target, GLint level, 2919 GLint xoffset, GLint yoffset, GLint zoffset, 2920 GLint x, GLint y, GLsizei width, GLsizei height ) 2921{ 2922 GET_CURRENT_CONTEXT(ctx); 2923 copytexsubimage(ctx, 3, target, level, xoffset, yoffset, zoffset, 2924 x, y, width, height); 2925} 2926 2927 2928 2929 2930/**********************************************************************/ 2931/****** Compressed Textures ******/ 2932/**********************************************************************/ 2933 2934 2935/** 2936 * Return expected size of a compressed texture. 2937 */ 2938static GLuint 2939compressed_tex_size(GLsizei width, GLsizei height, GLsizei depth, 2940 GLenum glformat) 2941{ 2942 gl_format mesaFormat = _mesa_glenum_to_compressed_format(glformat); 2943 return _mesa_format_image_size(mesaFormat, width, height, depth); 2944} 2945 2946 2947/* 2948 * Return compressed texture block size, in pixels. 2949 */ 2950static void 2951get_compressed_block_size(GLenum glformat, GLuint *bw, GLuint *bh) 2952{ 2953 gl_format mesaFormat = _mesa_glenum_to_compressed_format(glformat); 2954 _mesa_get_format_block_size(mesaFormat, bw, bh); 2955} 2956 2957 2958/** 2959 * Error checking for glCompressedTexImage[123]D(). 2960 * \return error code or GL_NO_ERROR. 2961 */ 2962static GLenum 2963compressed_texture_error_check(struct gl_context *ctx, GLint dimensions, 2964 GLenum target, GLint level, 2965 GLenum internalFormat, GLsizei width, 2966 GLsizei height, GLsizei depth, GLint border, 2967 GLsizei imageSize) 2968{ 2969 const GLenum proxyTarget = get_proxy_target(target); 2970 const GLint maxLevels = _mesa_max_texture_levels(ctx, target); 2971 GLint expectedSize; 2972 2973 /* check level */ 2974 if (level < 0 || level >= maxLevels) 2975 return GL_INVALID_VALUE; 2976 2977 if (!target_can_be_compressed(ctx, target, internalFormat)) { 2978 return GL_INVALID_ENUM; 2979 } 2980 2981 /* This will detect any invalid internalFormat value */ 2982 if (!_mesa_is_compressed_format(ctx, internalFormat)) 2983 return GL_INVALID_ENUM; 2984 2985 /* This should really never fail */ 2986 if (_mesa_base_tex_format(ctx, internalFormat) < 0) 2987 return GL_INVALID_ENUM; 2988 2989 /* No compressed formats support borders at this time */ 2990 if (border != 0) 2991 return GL_INVALID_VALUE; 2992 2993 /* For cube map, width must equal height */ 2994 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 2995 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB && width != height) 2996 return GL_INVALID_VALUE; 2997 2998 /* check image size against compression block size */ 2999 { 3000 gl_format texFormat = 3001 ctx->Driver.ChooseTextureFormat(ctx, internalFormat, 3002 GL_NONE, GL_NONE); 3003 GLuint bw, bh; 3004 3005 _mesa_get_format_block_size(texFormat, &bw, &bh); 3006 if ((width > bw && width % bw > 0) || 3007 (height > bh && height % bh > 0)) { 3008 /* 3009 * Per GL_ARB_texture_compression: GL_INVALID_OPERATION is 3010 * generated [...] if any parameter combinations are not 3011 * supported by the specific compressed internal format. 3012 */ 3013 return GL_INVALID_OPERATION; 3014 } 3015 } 3016 3017 /* check image sizes */ 3018 if (!ctx->Driver.TestProxyTexImage(ctx, proxyTarget, level, 3019 internalFormat, GL_NONE, GL_NONE, 3020 width, height, depth, border)) { 3021 /* See error comment above */ 3022 return GL_INVALID_OPERATION; 3023 } 3024 3025 /* check image size in bytes */ 3026 expectedSize = compressed_tex_size(width, height, depth, internalFormat); 3027 if (expectedSize != imageSize) { 3028 /* Per GL_ARB_texture_compression: GL_INVALID_VALUE is generated [...] 3029 * if <imageSize> is not consistent with the format, dimensions, and 3030 * contents of the specified image. 3031 */ 3032 return GL_INVALID_VALUE; 3033 } 3034 3035 return GL_NO_ERROR; 3036} 3037 3038 3039/** 3040 * Error checking for glCompressedTexSubImage[123]D(). 3041 * \warning There are some bad assumptions here about the size of compressed 3042 * texture tiles (multiple of 4) used to test the validity of the 3043 * offset and size parameters. 3044 * \return error code or GL_NO_ERROR. 3045 */ 3046static GLenum 3047compressed_subtexture_error_check(struct gl_context *ctx, GLint dimensions, 3048 GLenum target, GLint level, 3049 GLint xoffset, GLint yoffset, GLint zoffset, 3050 GLsizei width, GLsizei height, GLsizei depth, 3051 GLenum format, GLsizei imageSize) 3052{ 3053 GLint expectedSize, maxLevels = 0, maxTextureSize; 3054 GLuint bw, bh; 3055 (void) zoffset; 3056 3057 if (dimensions == 1) { 3058 /* 1D compressed textures not allowed */ 3059 return GL_INVALID_ENUM; 3060 } 3061 else if (dimensions == 2) { 3062 if (target == GL_PROXY_TEXTURE_2D) { 3063 maxLevels = ctx->Const.MaxTextureLevels; 3064 } 3065 else if (target == GL_TEXTURE_2D) { 3066 maxLevels = ctx->Const.MaxTextureLevels; 3067 } 3068 else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) { 3069 if (!ctx->Extensions.ARB_texture_cube_map) 3070 return GL_INVALID_ENUM; /*target*/ 3071 maxLevels = ctx->Const.MaxCubeTextureLevels; 3072 } 3073 else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 3074 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 3075 if (!ctx->Extensions.ARB_texture_cube_map) 3076 return GL_INVALID_ENUM; /*target*/ 3077 maxLevels = ctx->Const.MaxCubeTextureLevels; 3078 } 3079 else { 3080 return GL_INVALID_ENUM; /*target*/ 3081 } 3082 } 3083 else if (dimensions == 3) { 3084 /* 3D compressed textures not allowed */ 3085 return GL_INVALID_ENUM; 3086 } 3087 3088 maxTextureSize = 1 << (maxLevels - 1); 3089 3090 /* this will catch any invalid compressed format token */ 3091 if (!_mesa_is_compressed_format(ctx, format)) 3092 return GL_INVALID_ENUM; 3093 3094 if (width < 1 || width > maxTextureSize) 3095 return GL_INVALID_VALUE; 3096 3097 if ((height < 1 || height > maxTextureSize) 3098 && dimensions > 1) 3099 return GL_INVALID_VALUE; 3100 3101 if (level < 0 || level >= maxLevels) 3102 return GL_INVALID_VALUE; 3103 3104 /* 3105 * do checks which depend on compression block size 3106 */ 3107 get_compressed_block_size(format, &bw, &bh); 3108 3109 if ((xoffset % bw != 0) || (yoffset % bh != 0)) 3110 return GL_INVALID_VALUE; 3111 3112 if ((width % bw != 0) && width != 2 && width != 1) 3113 return GL_INVALID_VALUE; 3114 3115 if ((height % bh != 0) && height != 2 && height != 1) 3116 return GL_INVALID_VALUE; 3117 3118 expectedSize = compressed_tex_size(width, height, depth, format); 3119 if (expectedSize != imageSize) 3120 return GL_INVALID_VALUE; 3121 3122 return GL_NO_ERROR; 3123} 3124 3125 3126/** 3127 * Do second part of glCompressedTexSubImage error checking. 3128 * \return GL_TRUE if error found, GL_FALSE otherwise. 3129 */ 3130static GLboolean 3131compressed_subtexture_error_check2(struct gl_context *ctx, GLuint dims, 3132 GLsizei width, GLsizei height, 3133 GLsizei depth, GLenum format, 3134 struct gl_texture_image *texImage) 3135{ 3136 3137 if ((GLint) format != texImage->InternalFormat) { 3138 _mesa_error(ctx, GL_INVALID_OPERATION, 3139 "glCompressedTexSubImage%uD(format=0x%x)", dims, format); 3140 return GL_TRUE; 3141 } 3142 3143 if (((width == 1 || width == 2) && 3144 width != (GLsizei) texImage->Width) || 3145 (width > (GLsizei) texImage->Width)) { 3146 _mesa_error(ctx, GL_INVALID_VALUE, 3147 "glCompressedTexSubImage%uD(width=%d)", dims, width); 3148 return GL_TRUE; 3149 } 3150 3151 if (dims >= 2) { 3152 if (((height == 1 || height == 2) && 3153 height != (GLsizei) texImage->Height) || 3154 (height > (GLsizei) texImage->Height)) { 3155 _mesa_error(ctx, GL_INVALID_VALUE, 3156 "glCompressedTexSubImage%uD(height=%d)", dims, height); 3157 return GL_TRUE; 3158 } 3159 } 3160 3161 if (dims >= 3) { 3162 if (((depth == 1 || depth == 2) && 3163 depth != (GLsizei) texImage->Depth) || 3164 (depth > (GLsizei) texImage->Depth)) { 3165 _mesa_error(ctx, GL_INVALID_VALUE, 3166 "glCompressedTexSubImage%uD(depth=%d)", dims, depth); 3167 return GL_TRUE; 3168 } 3169 } 3170 3171 return GL_FALSE; 3172} 3173 3174 3175/** 3176 * Implementation of the glCompressedTexImage1/2/3D() functions. 3177 */ 3178static void 3179compressedteximage(struct gl_context *ctx, GLuint dims, 3180 GLenum target, GLint level, 3181 GLenum internalFormat, GLsizei width, 3182 GLsizei height, GLsizei depth, GLint border, 3183 GLsizei imageSize, const GLvoid *data) 3184{ 3185 GLenum error; 3186 3187 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3188 3189 if (MESA_VERBOSE & (VERBOSE_API|VERBOSE_TEXTURE)) 3190 _mesa_debug(ctx, 3191 "glCompressedTexImage%uDARB %s %d %s %d %d %d %d %d %p\n", 3192 dims, 3193 _mesa_lookup_enum_by_nr(target), level, 3194 _mesa_lookup_enum_by_nr(internalFormat), 3195 width, height, depth, border, imageSize, data); 3196 3197 /* check target */ 3198 if (!legal_teximage_target(ctx, dims, target)) { 3199 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage%uD(target=%s)", 3200 dims, _mesa_lookup_enum_by_nr(target)); 3201 return; 3202 } 3203 3204 error = compressed_texture_error_check(ctx, dims, target, level, 3205 internalFormat, width, height, depth, 3206 border, imageSize); 3207 3208#if FEATURE_ES 3209 /* XXX this is kind of a hack */ 3210 if (error) { 3211 _mesa_error(ctx, error, "glTexImage2D"); 3212 return; 3213 } 3214 3215 if (dims == 2) { 3216 switch (internalFormat) { 3217 case GL_PALETTE4_RGB8_OES: 3218 case GL_PALETTE4_RGBA8_OES: 3219 case GL_PALETTE4_R5_G6_B5_OES: 3220 case GL_PALETTE4_RGBA4_OES: 3221 case GL_PALETTE4_RGB5_A1_OES: 3222 case GL_PALETTE8_RGB8_OES: 3223 case GL_PALETTE8_RGBA8_OES: 3224 case GL_PALETTE8_R5_G6_B5_OES: 3225 case GL_PALETTE8_RGBA4_OES: 3226 case GL_PALETTE8_RGB5_A1_OES: 3227 _mesa_cpal_compressed_teximage2d(target, level, internalFormat, 3228 width, height, imageSize, data); 3229 return; 3230 } 3231 } 3232#endif 3233 3234 if (_mesa_is_proxy_texture(target)) { 3235 /* Proxy texture: just check for errors and update proxy state */ 3236 struct gl_texture_image *texImage; 3237 3238 if (!error) { 3239 struct gl_texture_object *texObj = 3240 _mesa_get_current_tex_object(ctx, target); 3241 gl_format texFormat = 3242 _mesa_choose_texture_format(ctx, texObj, target, level, 3243 internalFormat, GL_NONE, GL_NONE); 3244 if (!legal_texture_size(ctx, texFormat, width, height, depth)) { 3245 error = GL_OUT_OF_MEMORY; 3246 } 3247 } 3248 3249 texImage = _mesa_get_proxy_tex_image(ctx, target, level); 3250 if (texImage) { 3251 if (error) { 3252 /* if error, clear all proxy texture image parameters */ 3253 clear_teximage_fields(texImage); 3254 } 3255 else { 3256 /* no error: store the teximage parameters */ 3257 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 3258 depth, border, internalFormat, 3259 MESA_FORMAT_NONE); 3260 } 3261 } 3262 } 3263 else { 3264 /* non-proxy target */ 3265 struct gl_texture_object *texObj; 3266 struct gl_texture_image *texImage; 3267 3268 if (error) { 3269 _mesa_error(ctx, error, "glCompressedTexImage%uD", dims); 3270 return; 3271 } 3272 3273 texObj = _mesa_get_current_tex_object(ctx, target); 3274 3275 _mesa_lock_texture(ctx, texObj); 3276 { 3277 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 3278 if (!texImage) { 3279 _mesa_error(ctx, GL_OUT_OF_MEMORY, 3280 "glCompressedTexImage%uD", dims); 3281 } 3282 else { 3283 gl_format texFormat; 3284 3285 if (texImage->Data) { 3286 ctx->Driver.FreeTexImageData( ctx, texImage ); 3287 } 3288 ASSERT(texImage->Data == NULL); 3289 3290 texFormat = _mesa_choose_texture_format(ctx, texObj, target, level, 3291 internalFormat, GL_NONE, 3292 GL_NONE); 3293 3294 if (legal_texture_size(ctx, texFormat, width, height, depth)) { 3295 _mesa_init_teximage_fields(ctx, target, texImage, 3296 width, height, depth, 3297 border, internalFormat, texFormat); 3298 3299 switch (dims) { 3300 case 1: 3301 ASSERT(ctx->Driver.CompressedTexImage1D); 3302 ctx->Driver.CompressedTexImage1D(ctx, target, level, 3303 internalFormat, 3304 width, 3305 border, imageSize, data, 3306 texObj, texImage); 3307 break; 3308 case 2: 3309 ASSERT(ctx->Driver.CompressedTexImage2D); 3310 ctx->Driver.CompressedTexImage2D(ctx, target, level, 3311 internalFormat, 3312 width, height, 3313 border, imageSize, data, 3314 texObj, texImage); 3315 break; 3316 case 3: 3317 ASSERT(ctx->Driver.CompressedTexImage3D); 3318 ctx->Driver.CompressedTexImage3D(ctx, target, level, 3319 internalFormat, 3320 width, height, depth, 3321 border, imageSize, data, 3322 texObj, texImage); 3323 break; 3324 default: 3325 _mesa_problem(ctx, "bad dims in compressedteximage"); 3326 } 3327 3328 check_gen_mipmap(ctx, target, texObj, level); 3329 3330 /* state update */ 3331 texObj->_Complete = GL_FALSE; 3332 ctx->NewState |= _NEW_TEXTURE; 3333 } 3334 else { 3335 _mesa_error(ctx, GL_OUT_OF_MEMORY, 3336 "glCompressedTexImage%uD", dims); 3337 } 3338 } 3339 } 3340 _mesa_unlock_texture(ctx, texObj); 3341 } 3342} 3343 3344 3345void GLAPIENTRY 3346_mesa_CompressedTexImage1DARB(GLenum target, GLint level, 3347 GLenum internalFormat, GLsizei width, 3348 GLint border, GLsizei imageSize, 3349 const GLvoid *data) 3350{ 3351 GET_CURRENT_CONTEXT(ctx); 3352 compressedteximage(ctx, 1, target, level, internalFormat, 3353 width, 1, 1, border, imageSize, data); 3354} 3355 3356 3357void GLAPIENTRY 3358_mesa_CompressedTexImage2DARB(GLenum target, GLint level, 3359 GLenum internalFormat, GLsizei width, 3360 GLsizei height, GLint border, GLsizei imageSize, 3361 const GLvoid *data) 3362{ 3363 GET_CURRENT_CONTEXT(ctx); 3364 compressedteximage(ctx, 2, target, level, internalFormat, 3365 width, height, 1, border, imageSize, data); 3366} 3367 3368 3369void GLAPIENTRY 3370_mesa_CompressedTexImage3DARB(GLenum target, GLint level, 3371 GLenum internalFormat, GLsizei width, 3372 GLsizei height, GLsizei depth, GLint border, 3373 GLsizei imageSize, const GLvoid *data) 3374{ 3375 GET_CURRENT_CONTEXT(ctx); 3376 compressedteximage(ctx, 3, target, level, internalFormat, 3377 width, height, depth, border, imageSize, data); 3378} 3379 3380 3381/** 3382 * Common helper for glCompressedTexSubImage1/2/3D(). 3383 */ 3384static void 3385compressed_tex_sub_image(GLuint dims, GLenum target, GLint level, 3386 GLint xoffset, GLint yoffset, GLint zoffset, 3387 GLsizei width, GLsizei height, GLsizei depth, 3388 GLenum format, GLsizei imageSize, const GLvoid *data) 3389{ 3390 struct gl_texture_object *texObj; 3391 struct gl_texture_image *texImage; 3392 GLenum error; 3393 GET_CURRENT_CONTEXT(ctx); 3394 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 3395 3396 error = compressed_subtexture_error_check(ctx, dims, target, level, 3397 xoffset, 0, 0, /* pos */ 3398 width, height, depth, /* size */ 3399 format, imageSize); 3400 if (error) { 3401 _mesa_error(ctx, error, "glCompressedTexSubImage%uD", dims); 3402 return; 3403 } 3404 3405 texObj = _mesa_get_current_tex_object(ctx, target); 3406 3407 _mesa_lock_texture(ctx, texObj); 3408 { 3409 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 3410 assert(texImage); 3411 3412 if (compressed_subtexture_error_check2(ctx, dims, width, height, depth, 3413 format, texImage)) { 3414 /* error was recorded */ 3415 } 3416 else if (width > 0 && height > 0 && depth > 0) { 3417 switch (dims) { 3418 case 1: 3419 if (ctx->Driver.CompressedTexSubImage1D) { 3420 ctx->Driver.CompressedTexSubImage1D(ctx, target, level, 3421 xoffset, width, 3422 format, imageSize, data, 3423 texObj, texImage); 3424 } 3425 break; 3426 case 2: 3427 if (ctx->Driver.CompressedTexSubImage2D) { 3428 ctx->Driver.CompressedTexSubImage2D(ctx, target, level, 3429 xoffset, yoffset, 3430 width, height, 3431 format, imageSize, data, 3432 texObj, texImage); 3433 } 3434 break; 3435 case 3: 3436 if (ctx->Driver.CompressedTexSubImage3D) { 3437 ctx->Driver.CompressedTexSubImage3D(ctx, target, level, 3438 xoffset, yoffset, zoffset, 3439 width, height, depth, 3440 format, imageSize, data, 3441 texObj, texImage); 3442 } 3443 break; 3444 default: 3445 ; 3446 } 3447 3448 check_gen_mipmap(ctx, target, texObj, level); 3449 3450 ctx->NewState |= _NEW_TEXTURE; 3451 } 3452 } 3453 _mesa_unlock_texture(ctx, texObj); 3454} 3455 3456 3457void GLAPIENTRY 3458_mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset, 3459 GLsizei width, GLenum format, 3460 GLsizei imageSize, const GLvoid *data) 3461{ 3462 compressed_tex_sub_image(1, target, level, xoffset, 0, 0, width, 1, 1, 3463 format, imageSize, data); 3464} 3465 3466 3467void GLAPIENTRY 3468_mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset, 3469 GLint yoffset, GLsizei width, GLsizei height, 3470 GLenum format, GLsizei imageSize, 3471 const GLvoid *data) 3472{ 3473 compressed_tex_sub_image(2, target, level, xoffset, yoffset, 0, 3474 width, height, 1, format, imageSize, data); 3475} 3476 3477 3478void GLAPIENTRY 3479_mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset, 3480 GLint yoffset, GLint zoffset, GLsizei width, 3481 GLsizei height, GLsizei depth, GLenum format, 3482 GLsizei imageSize, const GLvoid *data) 3483{ 3484 compressed_tex_sub_image(3, target, level, xoffset, yoffset, zoffset, 3485 width, height, depth, format, imageSize, data); 3486} 3487