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