Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenteximage.c
Go to the documentation of this file.
00001 /* 00002 * mesa 3-D graphics library 00003 * Version: 7.1 00004 * 00005 * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. 00006 * 00007 * Permission is hereby granted, free of charge, to any person obtaining a 00008 * copy of this software and associated documentation files (the "Software"), 00009 * to deal in the Software without restriction, including without limitation 00010 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 00011 * and/or sell copies of the Software, and to permit persons to whom the 00012 * Software is furnished to do so, subject to the following conditions: 00013 * 00014 * The above copyright notice and this permission notice shall be included 00015 * in all copies or substantial portions of the Software. 00016 * 00017 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00018 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00019 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 00020 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 00021 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 00022 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00023 */ 00024 00025 00032 #include "glheader.h" 00033 #include "bufferobj.h" 00034 #include "context.h" 00035 #if FEATURE_convolve 00036 #include "convolve.h" 00037 #endif 00038 #include "fbobject.h" 00039 #include "framebuffer.h" 00040 #include "image.h" 00041 #include "imports.h" 00042 #include "macros.h" 00043 #include "state.h" 00044 #include "texcompress.h" 00045 #include "texformat.h" 00046 #include "teximage.h" 00047 #include "texstate.h" 00048 #include "texstore.h" 00049 #include "mtypes.h" 00050 00051 00056 void * 00057 _mesa_alloc_texmemory(GLsizei bytes) 00058 { 00059 return _mesa_align_malloc(bytes, 512); 00060 } 00061 00062 00066 void 00067 _mesa_free_texmemory(void *m) 00068 { 00069 _mesa_align_free(m); 00070 } 00071 00072 00073 00074 00075 #if 0 00076 static void PrintTexture(GLcontext *ctx, const struct gl_texture_image *img) 00077 { 00078 #if CHAN_TYPE != GL_UNSIGNED_BYTE 00079 _mesa_problem(NULL, "PrintTexture not supported"); 00080 #else 00081 GLuint i, j, c; 00082 const GLubyte *data = (const GLubyte *) img->Data; 00083 00084 if (!data) { 00085 _mesa_printf("No texture data\n"); 00086 return; 00087 } 00088 00089 switch (img->Format) { 00090 case GL_ALPHA: 00091 case GL_LUMINANCE: 00092 case GL_INTENSITY: 00093 case GL_COLOR_INDEX: 00094 c = 1; 00095 break; 00096 case GL_LUMINANCE_ALPHA: 00097 c = 2; 00098 break; 00099 case GL_RGB: 00100 c = 3; 00101 break; 00102 case GL_RGBA: 00103 c = 4; 00104 break; 00105 default: 00106 _mesa_problem(NULL, "error in PrintTexture\n"); 00107 return; 00108 } 00109 00110 for (i = 0; i < img->Height; i++) { 00111 for (j = 0; j < img->Width; j++) { 00112 if (c==1) 00113 _mesa_printf("%02x ", data[0]); 00114 else if (c==2) 00115 _mesa_printf("%02x%02x ", data[0], data[1]); 00116 else if (c==3) 00117 _mesa_printf("%02x%02x%02x ", data[0], data[1], data[2]); 00118 else if (c==4) 00119 _mesa_printf("%02x%02x%02x%02x ", data[0], data[1], data[2], data[3]); 00120 data += (img->RowStride - img->Width) * c; 00121 } 00122 /* XXX use img->ImageStride here */ 00123 _mesa_printf("\n"); 00124 } 00125 #endif 00126 } 00127 #endif 00128 00129 00130 /* 00131 * Compute floor(log_base_2(n)). 00132 * If n < 0 return -1. 00133 */ 00134 static int 00135 logbase2( int n ) 00136 { 00137 GLint i = 1; 00138 GLint log2 = 0; 00139 00140 if (n < 0) 00141 return -1; 00142 00143 if (n == 0) 00144 return 0; 00145 00146 while ( n > i ) { 00147 i *= 2; 00148 log2++; 00149 } 00150 if (i != n) { 00151 return log2 - 1; 00152 } 00153 else { 00154 return log2; 00155 } 00156 } 00157 00158 00159 00173 GLint 00174 _mesa_base_tex_format( GLcontext *ctx, GLint internalFormat ) 00175 { 00176 switch (internalFormat) { 00177 case GL_ALPHA: 00178 case GL_ALPHA4: 00179 case GL_ALPHA8: 00180 case GL_ALPHA12: 00181 case GL_ALPHA16: 00182 return GL_ALPHA; 00183 case 1: 00184 case GL_LUMINANCE: 00185 case GL_LUMINANCE4: 00186 case GL_LUMINANCE8: 00187 case GL_LUMINANCE12: 00188 case GL_LUMINANCE16: 00189 return GL_LUMINANCE; 00190 case 2: 00191 case GL_LUMINANCE_ALPHA: 00192 case GL_LUMINANCE4_ALPHA4: 00193 case GL_LUMINANCE6_ALPHA2: 00194 case GL_LUMINANCE8_ALPHA8: 00195 case GL_LUMINANCE12_ALPHA4: 00196 case GL_LUMINANCE12_ALPHA12: 00197 case GL_LUMINANCE16_ALPHA16: 00198 return GL_LUMINANCE_ALPHA; 00199 case GL_INTENSITY: 00200 case GL_INTENSITY4: 00201 case GL_INTENSITY8: 00202 case GL_INTENSITY12: 00203 case GL_INTENSITY16: 00204 return GL_INTENSITY; 00205 case 3: 00206 case GL_RGB: 00207 case GL_R3_G3_B2: 00208 case GL_RGB4: 00209 case GL_RGB5: 00210 case GL_RGB8: 00211 case GL_RGB10: 00212 case GL_RGB12: 00213 case GL_RGB16: 00214 return GL_RGB; 00215 case 4: 00216 case GL_RGBA: 00217 case GL_RGBA2: 00218 case GL_RGBA4: 00219 case GL_RGB5_A1: 00220 case GL_RGBA8: 00221 case GL_RGB10_A2: 00222 case GL_RGBA12: 00223 case GL_RGBA16: 00224 return GL_RGBA; 00225 default: 00226 ; /* fallthrough */ 00227 } 00228 00229 if (ctx->Extensions.EXT_paletted_texture) { 00230 switch (internalFormat) { 00231 case GL_COLOR_INDEX: 00232 case GL_COLOR_INDEX1_EXT: 00233 case GL_COLOR_INDEX2_EXT: 00234 case GL_COLOR_INDEX4_EXT: 00235 case GL_COLOR_INDEX8_EXT: 00236 case GL_COLOR_INDEX12_EXT: 00237 case GL_COLOR_INDEX16_EXT: 00238 return GL_COLOR_INDEX; 00239 default: 00240 ; /* fallthrough */ 00241 } 00242 } 00243 00244 if (ctx->Extensions.ARB_depth_texture) { 00245 switch (internalFormat) { 00246 case GL_DEPTH_COMPONENT: 00247 case GL_DEPTH_COMPONENT16: 00248 case GL_DEPTH_COMPONENT24: 00249 case GL_DEPTH_COMPONENT32: 00250 return GL_DEPTH_COMPONENT; 00251 default: 00252 ; /* fallthrough */ 00253 } 00254 } 00255 00256 if (ctx->Extensions.ARB_texture_compression) { 00257 switch (internalFormat) { 00258 case GL_COMPRESSED_ALPHA: 00259 return GL_ALPHA; 00260 case GL_COMPRESSED_LUMINANCE: 00261 return GL_LUMINANCE; 00262 case GL_COMPRESSED_LUMINANCE_ALPHA: 00263 return GL_LUMINANCE_ALPHA; 00264 case GL_COMPRESSED_INTENSITY: 00265 return GL_INTENSITY; 00266 case GL_COMPRESSED_RGB: 00267 return GL_RGB; 00268 case GL_COMPRESSED_RGBA: 00269 return GL_RGBA; 00270 default: 00271 ; /* fallthrough */ 00272 } 00273 } 00274 00275 if (ctx->Extensions.TDFX_texture_compression_FXT1) { 00276 switch (internalFormat) { 00277 case GL_COMPRESSED_RGB_FXT1_3DFX: 00278 return GL_RGB; 00279 case GL_COMPRESSED_RGBA_FXT1_3DFX: 00280 return GL_RGBA; 00281 default: 00282 ; /* fallthrough */ 00283 } 00284 } 00285 00286 if (ctx->Extensions.EXT_texture_compression_s3tc) { 00287 switch (internalFormat) { 00288 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: 00289 return GL_RGB; 00290 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: 00291 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: 00292 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: 00293 return GL_RGBA; 00294 default: 00295 ; /* fallthrough */ 00296 } 00297 } 00298 00299 if (ctx->Extensions.S3_s3tc) { 00300 switch (internalFormat) { 00301 case GL_RGB_S3TC: 00302 case GL_RGB4_S3TC: 00303 return GL_RGB; 00304 case GL_RGBA_S3TC: 00305 case GL_RGBA4_S3TC: 00306 return GL_RGBA; 00307 default: 00308 ; /* fallthrough */ 00309 } 00310 } 00311 00312 if (ctx->Extensions.MESA_ycbcr_texture) { 00313 if (internalFormat == GL_YCBCR_MESA) 00314 return GL_YCBCR_MESA; 00315 } 00316 00317 if (ctx->Extensions.ARB_texture_float) { 00318 switch (internalFormat) { 00319 case GL_ALPHA16F_ARB: 00320 case GL_ALPHA32F_ARB: 00321 return GL_ALPHA; 00322 case GL_RGBA16F_ARB: 00323 case GL_RGBA32F_ARB: 00324 return GL_RGBA; 00325 case GL_RGB16F_ARB: 00326 case GL_RGB32F_ARB: 00327 return GL_RGB; 00328 case GL_INTENSITY16F_ARB: 00329 case GL_INTENSITY32F_ARB: 00330 return GL_INTENSITY; 00331 case GL_LUMINANCE16F_ARB: 00332 case GL_LUMINANCE32F_ARB: 00333 return GL_LUMINANCE; 00334 case GL_LUMINANCE_ALPHA16F_ARB: 00335 case GL_LUMINANCE_ALPHA32F_ARB: 00336 return GL_LUMINANCE_ALPHA; 00337 default: 00338 ; /* fallthrough */ 00339 } 00340 } 00341 00342 if (ctx->Extensions.EXT_packed_depth_stencil) { 00343 switch (internalFormat) { 00344 case GL_DEPTH_STENCIL_EXT: 00345 case GL_DEPTH24_STENCIL8_EXT: 00346 return GL_DEPTH_STENCIL_EXT; 00347 default: 00348 ; /* fallthrough */ 00349 } 00350 } 00351 00352 #if FEATURE_EXT_texture_sRGB 00353 if (ctx->Extensions.EXT_texture_sRGB) { 00354 switch (internalFormat) { 00355 case GL_SRGB_EXT: 00356 case GL_SRGB8_EXT: 00357 case GL_COMPRESSED_SRGB_EXT: 00358 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: 00359 return GL_RGB; 00360 case GL_SRGB_ALPHA_EXT: 00361 case GL_SRGB8_ALPHA8_EXT: 00362 case GL_COMPRESSED_SRGB_ALPHA_EXT: 00363 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: 00364 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: 00365 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: 00366 return GL_RGBA; 00367 case GL_SLUMINANCE_ALPHA_EXT: 00368 case GL_SLUMINANCE8_ALPHA8_EXT: 00369 case GL_COMPRESSED_SLUMINANCE_EXT: 00370 case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT: 00371 return GL_LUMINANCE_ALPHA; 00372 case GL_SLUMINANCE_EXT: 00373 case GL_SLUMINANCE8_EXT: 00374 return GL_LUMINANCE; 00375 default: 00376 ; /* fallthrough */ 00377 } 00378 } 00379 00380 #endif /* FEATURE_EXT_texture_sRGB */ 00381 00382 return -1; /* error */ 00383 } 00384 00385 00393 GLboolean 00394 _mesa_is_color_format(GLenum format) 00395 { 00396 switch (format) { 00397 case GL_RED: 00398 case GL_GREEN: 00399 case GL_BLUE: 00400 case GL_ALPHA: 00401 case GL_ALPHA4: 00402 case GL_ALPHA8: 00403 case GL_ALPHA12: 00404 case GL_ALPHA16: 00405 case 1: 00406 case GL_LUMINANCE: 00407 case GL_LUMINANCE4: 00408 case GL_LUMINANCE8: 00409 case GL_LUMINANCE12: 00410 case GL_LUMINANCE16: 00411 case 2: 00412 case GL_LUMINANCE_ALPHA: 00413 case GL_LUMINANCE4_ALPHA4: 00414 case GL_LUMINANCE6_ALPHA2: 00415 case GL_LUMINANCE8_ALPHA8: 00416 case GL_LUMINANCE12_ALPHA4: 00417 case GL_LUMINANCE12_ALPHA12: 00418 case GL_LUMINANCE16_ALPHA16: 00419 case GL_INTENSITY: 00420 case GL_INTENSITY4: 00421 case GL_INTENSITY8: 00422 case GL_INTENSITY12: 00423 case GL_INTENSITY16: 00424 case 3: 00425 case GL_RGB: 00426 case GL_BGR: 00427 case GL_R3_G3_B2: 00428 case GL_RGB4: 00429 case GL_RGB5: 00430 case GL_RGB8: 00431 case GL_RGB10: 00432 case GL_RGB12: 00433 case GL_RGB16: 00434 case 4: 00435 case GL_ABGR_EXT: 00436 case GL_RGBA: 00437 case GL_BGRA: 00438 case GL_RGBA2: 00439 case GL_RGBA4: 00440 case GL_RGB5_A1: 00441 case GL_RGBA8: 00442 case GL_RGB10_A2: 00443 case GL_RGBA12: 00444 case GL_RGBA16: 00445 /* float texture formats */ 00446 case GL_ALPHA16F_ARB: 00447 case GL_ALPHA32F_ARB: 00448 case GL_LUMINANCE16F_ARB: 00449 case GL_LUMINANCE32F_ARB: 00450 case GL_LUMINANCE_ALPHA16F_ARB: 00451 case GL_LUMINANCE_ALPHA32F_ARB: 00452 case GL_INTENSITY16F_ARB: 00453 case GL_INTENSITY32F_ARB: 00454 case GL_RGB16F_ARB: 00455 case GL_RGB32F_ARB: 00456 case GL_RGBA16F_ARB: 00457 case GL_RGBA32F_ARB: 00458 /* compressed formats */ 00459 case GL_COMPRESSED_ALPHA: 00460 case GL_COMPRESSED_LUMINANCE: 00461 case GL_COMPRESSED_LUMINANCE_ALPHA: 00462 case GL_COMPRESSED_INTENSITY: 00463 case GL_COMPRESSED_RGB: 00464 case GL_COMPRESSED_RGBA: 00465 case GL_RGB_S3TC: 00466 case GL_RGB4_S3TC: 00467 case GL_RGBA_S3TC: 00468 case GL_RGBA4_S3TC: 00469 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT: 00470 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT: 00471 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT: 00472 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: 00473 case GL_COMPRESSED_RGB_FXT1_3DFX: 00474 case GL_COMPRESSED_RGBA_FXT1_3DFX: 00475 #if FEATURE_EXT_texture_sRGB 00476 case GL_SRGB_EXT: 00477 case GL_SRGB8_EXT: 00478 case GL_SRGB_ALPHA_EXT: 00479 case GL_SRGB8_ALPHA8_EXT: 00480 case GL_SLUMINANCE_ALPHA_EXT: 00481 case GL_SLUMINANCE8_ALPHA8_EXT: 00482 case GL_SLUMINANCE_EXT: 00483 case GL_SLUMINANCE8_EXT: 00484 case GL_COMPRESSED_SRGB_EXT: 00485 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT: 00486 case GL_COMPRESSED_SRGB_ALPHA_EXT: 00487 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: 00488 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT: 00489 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: 00490 case GL_COMPRESSED_SLUMINANCE_EXT: 00491 case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT: 00492 #endif /* FEATURE_EXT_texture_sRGB */ 00493 return GL_TRUE; 00494 case GL_YCBCR_MESA: /* not considered to be RGB */ 00495 /* fall-through */ 00496 default: 00497 return GL_FALSE; 00498 } 00499 } 00500 00501 00505 static GLboolean 00506 is_index_format(GLenum format) 00507 { 00508 switch (format) { 00509 case GL_COLOR_INDEX: 00510 case GL_COLOR_INDEX1_EXT: 00511 case GL_COLOR_INDEX2_EXT: 00512 case GL_COLOR_INDEX4_EXT: 00513 case GL_COLOR_INDEX8_EXT: 00514 case GL_COLOR_INDEX12_EXT: 00515 case GL_COLOR_INDEX16_EXT: 00516 return GL_TRUE; 00517 default: 00518 return GL_FALSE; 00519 } 00520 } 00521 00522 00526 static GLboolean 00527 is_depth_format(GLenum format) 00528 { 00529 switch (format) { 00530 case GL_DEPTH_COMPONENT16: 00531 case GL_DEPTH_COMPONENT24: 00532 case GL_DEPTH_COMPONENT32: 00533 case GL_DEPTH_COMPONENT: 00534 return GL_TRUE; 00535 default: 00536 return GL_FALSE; 00537 } 00538 } 00539 00540 00544 static GLboolean 00545 is_ycbcr_format(GLenum format) 00546 { 00547 switch (format) { 00548 case GL_YCBCR_MESA: 00549 return GL_TRUE; 00550 default: 00551 return GL_FALSE; 00552 } 00553 } 00554 00555 00559 static GLboolean 00560 is_depthstencil_format(GLenum format) 00561 { 00562 switch (format) { 00563 case GL_DEPTH24_STENCIL8_EXT: 00564 case GL_DEPTH_STENCIL_EXT: 00565 return GL_TRUE; 00566 default: 00567 return GL_FALSE; 00568 } 00569 } 00570 00571 00572 00584 static GLboolean 00585 is_compressed_format(GLcontext *ctx, GLenum internalFormat) 00586 { 00587 GLint supported[100]; /* 100 should be plenty */ 00588 GLuint i, n; 00589 00590 n = _mesa_get_compressed_formats(ctx, supported, GL_TRUE); 00591 ASSERT(n < 100); 00592 for (i = 0; i < n; i++) { 00593 if ((GLint) internalFormat == supported[i]) { 00594 return GL_TRUE; 00595 } 00596 } 00597 return GL_FALSE; 00598 } 00599 00600 00605 GLuint 00606 _mesa_tex_target_to_face(GLenum target) 00607 { 00608 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 00609 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) 00610 return (GLuint) target - (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X; 00611 else 00612 return 0; 00613 } 00614 00615 00616 00628 void 00629 _mesa_set_tex_image(struct gl_texture_object *tObj, 00630 GLenum target, GLint level, 00631 struct gl_texture_image *texImage) 00632 { 00633 ASSERT(tObj); 00634 ASSERT(texImage); 00635 /* XXX simplify this with _mesa_tex_target_to_face() */ 00636 switch (target) { 00637 case GL_TEXTURE_1D: 00638 case GL_TEXTURE_2D: 00639 case GL_TEXTURE_3D: 00640 case GL_TEXTURE_1D_ARRAY_EXT: 00641 case GL_TEXTURE_2D_ARRAY_EXT: 00642 tObj->Image[0][level] = texImage; 00643 break; 00644 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: 00645 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: 00646 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: 00647 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: 00648 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: 00649 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: 00650 { 00651 GLuint face = ((GLuint) target - 00652 (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X); 00653 tObj->Image[face][level] = texImage; 00654 } 00655 break; 00656 case GL_TEXTURE_RECTANGLE_NV: 00657 ASSERT(level == 0); 00658 tObj->Image[0][level] = texImage; 00659 break; 00660 default: 00661 _mesa_problem(NULL, "bad target in _mesa_set_tex_image()"); 00662 return; 00663 } 00664 /* Set the 'back' pointer */ 00665 texImage->TexObject = tObj; 00666 } 00667 00668 00678 struct gl_texture_image * 00679 _mesa_new_texture_image( GLcontext *ctx ) 00680 { 00681 (void) ctx; 00682 return CALLOC_STRUCT(gl_texture_image); 00683 } 00684 00685 00694 void 00695 _mesa_free_texture_image_data(GLcontext *ctx, 00696 struct gl_texture_image *texImage) 00697 { 00698 (void) ctx; 00699 00700 if (texImage->Data && !texImage->IsClientData) { 00701 /* free the old texture data */ 00702 _mesa_free_texmemory(texImage->Data); 00703 } 00704 00705 texImage->Data = NULL; 00706 } 00707 00708 00716 void 00717 _mesa_delete_texture_image( GLcontext *ctx, struct gl_texture_image *texImage ) 00718 { 00719 /* Free texImage->Data and/or any other driver-specific texture 00720 * image storage. 00721 */ 00722 ASSERT(ctx->Driver.FreeTexImageData); 00723 ctx->Driver.FreeTexImageData( ctx, texImage ); 00724 00725 ASSERT(texImage->Data == NULL); 00726 if (texImage->ImageOffsets) 00727 _mesa_free(texImage->ImageOffsets); 00728 _mesa_free(texImage); 00729 } 00730 00731 00739 GLboolean 00740 _mesa_is_proxy_texture(GLenum target) 00741 { 00742 return (target == GL_PROXY_TEXTURE_1D || 00743 target == GL_PROXY_TEXTURE_2D || 00744 target == GL_PROXY_TEXTURE_3D || 00745 target == GL_PROXY_TEXTURE_CUBE_MAP_ARB || 00746 target == GL_PROXY_TEXTURE_RECTANGLE_NV || 00747 target == GL_PROXY_TEXTURE_1D_ARRAY_EXT || 00748 target == GL_PROXY_TEXTURE_2D_ARRAY_EXT); 00749 } 00750 00751 00763 struct gl_texture_object * 00764 _mesa_select_tex_object(GLcontext *ctx, const struct gl_texture_unit *texUnit, 00765 GLenum target) 00766 { 00767 switch (target) { 00768 case GL_TEXTURE_1D: 00769 return texUnit->CurrentTex[TEXTURE_1D_INDEX]; 00770 case GL_PROXY_TEXTURE_1D: 00771 return ctx->Texture.ProxyTex[TEXTURE_1D_INDEX]; 00772 case GL_TEXTURE_2D: 00773 return texUnit->CurrentTex[TEXTURE_2D_INDEX]; 00774 case GL_PROXY_TEXTURE_2D: 00775 return ctx->Texture.ProxyTex[TEXTURE_2D_INDEX]; 00776 case GL_TEXTURE_3D: 00777 return texUnit->CurrentTex[TEXTURE_3D_INDEX]; 00778 case GL_PROXY_TEXTURE_3D: 00779 return ctx->Texture.ProxyTex[TEXTURE_3D_INDEX]; 00780 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: 00781 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: 00782 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: 00783 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: 00784 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: 00785 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: 00786 case GL_TEXTURE_CUBE_MAP_ARB: 00787 return ctx->Extensions.ARB_texture_cube_map 00788 ? texUnit->CurrentTex[TEXTURE_CUBE_INDEX] : NULL; 00789 case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 00790 return ctx->Extensions.ARB_texture_cube_map 00791 ? ctx->Texture.ProxyTex[TEXTURE_CUBE_INDEX] : NULL; 00792 case GL_TEXTURE_RECTANGLE_NV: 00793 return ctx->Extensions.NV_texture_rectangle 00794 ? texUnit->CurrentTex[TEXTURE_RECT_INDEX] : NULL; 00795 case GL_PROXY_TEXTURE_RECTANGLE_NV: 00796 return ctx->Extensions.NV_texture_rectangle 00797 ? ctx->Texture.ProxyTex[TEXTURE_RECT_INDEX] : NULL; 00798 case GL_TEXTURE_1D_ARRAY_EXT: 00799 return ctx->Extensions.MESA_texture_array 00800 ? texUnit->CurrentTex[TEXTURE_1D_ARRAY_INDEX] : NULL; 00801 case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 00802 return ctx->Extensions.MESA_texture_array 00803 ? ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX] : NULL; 00804 case GL_TEXTURE_2D_ARRAY_EXT: 00805 return ctx->Extensions.MESA_texture_array 00806 ? texUnit->CurrentTex[TEXTURE_2D_ARRAY_INDEX] : NULL; 00807 case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 00808 return ctx->Extensions.MESA_texture_array 00809 ? ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX] : NULL; 00810 default: 00811 _mesa_problem(NULL, "bad target in _mesa_select_tex_object()"); 00812 return NULL; 00813 } 00814 } 00815 00816 00830 struct gl_texture_image * 00831 _mesa_select_tex_image(GLcontext *ctx, const struct gl_texture_object *texObj, 00832 GLenum target, GLint level) 00833 { 00834 ASSERT(texObj); 00835 00836 if (level < 0 || level >= MAX_TEXTURE_LEVELS) 00837 return NULL; 00838 00839 /* XXX simplify this with _mesa_tex_target_to_face() */ 00840 switch (target) { 00841 case GL_TEXTURE_1D: 00842 case GL_PROXY_TEXTURE_1D: 00843 case GL_TEXTURE_2D: 00844 case GL_PROXY_TEXTURE_2D: 00845 case GL_TEXTURE_3D: 00846 case GL_PROXY_TEXTURE_3D: 00847 return texObj->Image[0][level]; 00848 00849 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: 00850 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: 00851 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: 00852 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: 00853 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: 00854 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: 00855 if (ctx->Extensions.ARB_texture_cube_map) { 00856 GLuint face = ((GLuint) target - 00857 (GLuint) GL_TEXTURE_CUBE_MAP_POSITIVE_X); 00858 return texObj->Image[face][level]; 00859 } 00860 else 00861 return NULL; 00862 00863 case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 00864 if (ctx->Extensions.ARB_texture_cube_map) 00865 return texObj->Image[0][level]; 00866 else 00867 return NULL; 00868 00869 case GL_TEXTURE_RECTANGLE_NV: 00870 case GL_PROXY_TEXTURE_RECTANGLE_NV: 00871 if (ctx->Extensions.NV_texture_rectangle && level == 0) 00872 return texObj->Image[0][level]; 00873 else 00874 return NULL; 00875 00876 case GL_TEXTURE_1D_ARRAY_EXT: 00877 case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 00878 case GL_TEXTURE_2D_ARRAY_EXT: 00879 case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 00880 return (ctx->Extensions.MESA_texture_array) 00881 ? texObj->Image[0][level] : NULL; 00882 00883 default: 00884 return NULL; 00885 } 00886 } 00887 00888 00894 struct gl_texture_image * 00895 _mesa_get_tex_image(GLcontext *ctx, struct gl_texture_object *texObj, 00896 GLenum target, GLint level) 00897 { 00898 struct gl_texture_image *texImage; 00899 00900 if (!texObj) 00901 return NULL; 00902 00903 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 00904 if (!texImage) { 00905 texImage = ctx->Driver.NewTextureImage(ctx); 00906 if (!texImage) { 00907 _mesa_error(ctx, GL_OUT_OF_MEMORY, "texture image allocation"); 00908 return NULL; 00909 } 00910 00911 _mesa_set_tex_image(texObj, target, level, texImage); 00912 } 00913 00914 return texImage; 00915 } 00916 00917 00924 struct gl_texture_image * 00925 _mesa_get_proxy_tex_image(GLcontext *ctx, GLenum target, GLint level) 00926 { 00927 struct gl_texture_image *texImage; 00928 00929 if (level < 0 ) 00930 return NULL; 00931 00932 switch (target) { 00933 case GL_PROXY_TEXTURE_1D: 00934 if (level >= ctx->Const.MaxTextureLevels) 00935 return NULL; 00936 texImage = ctx->Texture.ProxyTex[TEXTURE_1D_INDEX]->Image[0][level]; 00937 if (!texImage) { 00938 texImage = ctx->Driver.NewTextureImage(ctx); 00939 if (!texImage) { 00940 _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation"); 00941 return NULL; 00942 } 00943 ctx->Texture.ProxyTex[TEXTURE_1D_INDEX]->Image[0][level] = texImage; 00944 /* Set the 'back' pointer */ 00945 texImage->TexObject = ctx->Texture.ProxyTex[TEXTURE_1D_INDEX]; 00946 } 00947 return texImage; 00948 case GL_PROXY_TEXTURE_2D: 00949 if (level >= ctx->Const.MaxTextureLevels) 00950 return NULL; 00951 texImage = ctx->Texture.ProxyTex[TEXTURE_2D_INDEX]->Image[0][level]; 00952 if (!texImage) { 00953 texImage = ctx->Driver.NewTextureImage(ctx); 00954 if (!texImage) { 00955 _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation"); 00956 return NULL; 00957 } 00958 ctx->Texture.ProxyTex[TEXTURE_2D_INDEX]->Image[0][level] = texImage; 00959 /* Set the 'back' pointer */ 00960 texImage->TexObject = ctx->Texture.ProxyTex[TEXTURE_2D_INDEX]; 00961 } 00962 return texImage; 00963 case GL_PROXY_TEXTURE_3D: 00964 if (level >= ctx->Const.Max3DTextureLevels) 00965 return NULL; 00966 texImage = ctx->Texture.ProxyTex[TEXTURE_3D_INDEX]->Image[0][level]; 00967 if (!texImage) { 00968 texImage = ctx->Driver.NewTextureImage(ctx); 00969 if (!texImage) { 00970 _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation"); 00971 return NULL; 00972 } 00973 ctx->Texture.ProxyTex[TEXTURE_3D_INDEX]->Image[0][level] = texImage; 00974 /* Set the 'back' pointer */ 00975 texImage->TexObject = ctx->Texture.ProxyTex[TEXTURE_3D_INDEX]; 00976 } 00977 return texImage; 00978 case GL_PROXY_TEXTURE_CUBE_MAP: 00979 if (level >= ctx->Const.MaxCubeTextureLevels) 00980 return NULL; 00981 texImage = ctx->Texture.ProxyTex[TEXTURE_CUBE_INDEX]->Image[0][level]; 00982 if (!texImage) { 00983 texImage = ctx->Driver.NewTextureImage(ctx); 00984 if (!texImage) { 00985 _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation"); 00986 return NULL; 00987 } 00988 ctx->Texture.ProxyTex[TEXTURE_CUBE_INDEX]->Image[0][level] = texImage; 00989 /* Set the 'back' pointer */ 00990 texImage->TexObject = ctx->Texture.ProxyTex[TEXTURE_CUBE_INDEX]; 00991 } 00992 return texImage; 00993 case GL_PROXY_TEXTURE_RECTANGLE_NV: 00994 if (level > 0) 00995 return NULL; 00996 texImage = ctx->Texture.ProxyTex[TEXTURE_RECT_INDEX]->Image[0][level]; 00997 if (!texImage) { 00998 texImage = ctx->Driver.NewTextureImage(ctx); 00999 if (!texImage) { 01000 _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation"); 01001 return NULL; 01002 } 01003 ctx->Texture.ProxyTex[TEXTURE_RECT_INDEX]->Image[0][level] = texImage; 01004 /* Set the 'back' pointer */ 01005 texImage->TexObject = ctx->Texture.ProxyTex[TEXTURE_RECT_INDEX]; 01006 } 01007 return texImage; 01008 case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 01009 if (level >= ctx->Const.MaxTextureLevels) 01010 return NULL; 01011 texImage = ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX]->Image[0][level]; 01012 if (!texImage) { 01013 texImage = ctx->Driver.NewTextureImage(ctx); 01014 if (!texImage) { 01015 _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation"); 01016 return NULL; 01017 } 01018 ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX]->Image[0][level] = texImage; 01019 /* Set the 'back' pointer */ 01020 texImage->TexObject = ctx->Texture.ProxyTex[TEXTURE_1D_ARRAY_INDEX]; 01021 } 01022 return texImage; 01023 case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 01024 if (level >= ctx->Const.MaxTextureLevels) 01025 return NULL; 01026 texImage = ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX]->Image[0][level]; 01027 if (!texImage) { 01028 texImage = ctx->Driver.NewTextureImage(ctx); 01029 if (!texImage) { 01030 _mesa_error(ctx, GL_OUT_OF_MEMORY, "proxy texture allocation"); 01031 return NULL; 01032 } 01033 ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX]->Image[0][level] = texImage; 01034 /* Set the 'back' pointer */ 01035 texImage->TexObject = ctx->Texture.ProxyTex[TEXTURE_2D_ARRAY_INDEX]; 01036 } 01037 return texImage; 01038 default: 01039 return NULL; 01040 } 01041 } 01042 01043 01055 GLint 01056 _mesa_max_texture_levels(GLcontext *ctx, GLenum target) 01057 { 01058 switch (target) { 01059 case GL_TEXTURE_1D: 01060 case GL_PROXY_TEXTURE_1D: 01061 case GL_TEXTURE_2D: 01062 case GL_PROXY_TEXTURE_2D: 01063 case GL_TEXTURE_1D_ARRAY_EXT: 01064 case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 01065 case GL_TEXTURE_2D_ARRAY_EXT: 01066 case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 01067 return ctx->Const.MaxTextureLevels; 01068 case GL_TEXTURE_3D: 01069 case GL_PROXY_TEXTURE_3D: 01070 return ctx->Const.Max3DTextureLevels; 01071 case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB: 01072 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB: 01073 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB: 01074 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB: 01075 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB: 01076 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB: 01077 case GL_TEXTURE_CUBE_MAP_ARB: 01078 case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 01079 return ctx->Const.MaxCubeTextureLevels; 01080 case GL_TEXTURE_RECTANGLE_NV: 01081 case GL_PROXY_TEXTURE_RECTANGLE_NV: 01082 return 1; 01083 default: 01084 return 0; /* bad target */ 01085 } 01086 } 01087 01088 01089 01090 #if 000 /* not used anymore */ 01091 /* 01092 * glTexImage[123]D can accept a NULL image pointer. In this case we 01093 * create a texture image with unspecified image contents per the OpenGL 01094 * spec. 01095 */ 01096 static GLubyte * 01097 make_null_texture(GLint width, GLint height, GLint depth, GLenum format) 01098 { 01099 const GLint components = _mesa_components_in_format(format); 01100 const GLint numPixels = width * height * depth; 01101 GLubyte *data = (GLubyte *) MALLOC(numPixels * components * sizeof(GLubyte)); 01102 01103 #ifdef DEBUG 01104 /* 01105 * Let's see if anyone finds this. If glTexImage2D() is called with 01106 * a NULL image pointer then load the texture image with something 01107 * interesting instead of leaving it indeterminate. 01108 */ 01109 if (data) { 01110 static const char message[8][32] = { 01111 " X X XXXXX XXX X ", 01112 " XX XX X X X X X ", 01113 " X X X X X X X ", 01114 " X X XXXX XXX XXXXX ", 01115 " X X X X X X ", 01116 " X X X X X X X ", 01117 " X X XXXXX XXX X X ", 01118 " " 01119 }; 01120 01121 GLubyte *imgPtr = data; 01122 GLint h, i, j, k; 01123 for (h = 0; h < depth; h++) { 01124 for (i = 0; i < height; i++) { 01125 GLint srcRow = 7 - (i % 8); 01126 for (j = 0; j < width; j++) { 01127 GLint srcCol = j % 32; 01128 GLubyte texel = (message[srcRow][srcCol]=='X') ? 255 : 70; 01129 for (k = 0; k < components; k++) { 01130 *imgPtr++ = texel; 01131 } 01132 } 01133 } 01134 } 01135 } 01136 #endif 01137 01138 return data; 01139 } 01140 #endif 01141 01142 01143 01155 static void 01156 clear_teximage_fields(struct gl_texture_image *img) 01157 { 01158 ASSERT(img); 01159 img->_BaseFormat = 0; 01160 img->InternalFormat = 0; 01161 img->Border = 0; 01162 img->Width = 0; 01163 img->Height = 0; 01164 img->Depth = 0; 01165 img->RowStride = 0; 01166 if (img->ImageOffsets) { 01167 _mesa_free(img->ImageOffsets); 01168 img->ImageOffsets = NULL; 01169 } 01170 img->Width2 = 0; 01171 img->Height2 = 0; 01172 img->Depth2 = 0; 01173 img->WidthLog2 = 0; 01174 img->HeightLog2 = 0; 01175 img->DepthLog2 = 0; 01176 img->Data = NULL; 01177 img->TexFormat = &_mesa_null_texformat; 01178 img->FetchTexelc = NULL; 01179 img->FetchTexelf = NULL; 01180 img->IsCompressed = 0; 01181 img->CompressedSize = 0; 01182 } 01183 01184 01200 void 01201 _mesa_init_teximage_fields(GLcontext *ctx, GLenum target, 01202 struct gl_texture_image *img, 01203 GLsizei width, GLsizei height, GLsizei depth, 01204 GLint border, GLenum internalFormat) 01205 { 01206 GLint i; 01207 01208 ASSERT(img); 01209 ASSERT(width >= 0); 01210 ASSERT(height >= 0); 01211 ASSERT(depth >= 0); 01212 01213 img->_BaseFormat = _mesa_base_tex_format( ctx, internalFormat ); 01214 ASSERT(img->_BaseFormat > 0); 01215 img->InternalFormat = internalFormat; 01216 img->Border = border; 01217 img->Width = width; 01218 img->Height = height; 01219 img->Depth = depth; 01220 img->Width2 = width - 2 * border; /* == 1 << img->WidthLog2; */ 01221 img->Height2 = height - 2 * border; /* == 1 << img->HeightLog2; */ 01222 img->Depth2 = depth - 2 * border; /* == 1 << img->DepthLog2; */ 01223 img->WidthLog2 = logbase2(img->Width2); 01224 if (height == 1) /* 1-D texture */ 01225 img->HeightLog2 = 0; 01226 else 01227 img->HeightLog2 = logbase2(img->Height2); 01228 if (depth == 1) /* 2-D texture */ 01229 img->DepthLog2 = 0; 01230 else 01231 img->DepthLog2 = logbase2(img->Depth2); 01232 img->MaxLog2 = MAX2(img->WidthLog2, img->HeightLog2); 01233 img->IsCompressed = GL_FALSE; 01234 img->CompressedSize = 0; 01235 01236 if ((width == 1 || _mesa_is_pow_two(img->Width2)) && 01237 (height == 1 || _mesa_is_pow_two(img->Height2)) && 01238 (depth == 1 || _mesa_is_pow_two(img->Depth2))) 01239 img->_IsPowerOfTwo = GL_TRUE; 01240 else 01241 img->_IsPowerOfTwo = GL_FALSE; 01242 01243 /* RowStride and ImageOffsets[] describe how to address texels in 'Data' */ 01244 img->RowStride = width; 01245 /* Allocate the ImageOffsets array and initialize to typical values. 01246 * We allocate the array for 1D/2D textures too in order to avoid special- 01247 * case code in the texstore routines. 01248 */ 01249 img->ImageOffsets = (GLuint *) _mesa_malloc(depth * sizeof(GLuint)); 01250 for (i = 0; i < depth; i++) { 01251 img->ImageOffsets[i] = i * width * height; 01252 } 01253 01254 /* Compute Width/Height/DepthScale for mipmap lod computation */ 01255 if (target == GL_TEXTURE_RECTANGLE_NV) { 01256 /* scale = 1.0 since texture coords directly map to texels */ 01257 img->WidthScale = 1.0; 01258 img->HeightScale = 1.0; 01259 img->DepthScale = 1.0; 01260 } 01261 else { 01262 img->WidthScale = (GLfloat) img->Width; 01263 img->HeightScale = (GLfloat) img->Height; 01264 img->DepthScale = (GLfloat) img->Depth; 01265 } 01266 } 01267 01268 01293 GLboolean 01294 _mesa_test_proxy_teximage(GLcontext *ctx, GLenum target, GLint level, 01295 GLint internalFormat, GLenum format, GLenum type, 01296 GLint width, GLint height, GLint depth, GLint border) 01297 { 01298 GLint maxSize; 01299 01300 (void) internalFormat; 01301 (void) format; 01302 (void) type; 01303 01304 switch (target) { 01305 case GL_PROXY_TEXTURE_1D: 01306 maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 01307 if (width < 2 * border || width > 2 + maxSize || 01308 (!ctx->Extensions.ARB_texture_non_power_of_two && 01309 width >0 && !_mesa_is_pow_two(width - 2 * border)) || 01310 level >= ctx->Const.MaxTextureLevels) { 01311 /* bad width or level */ 01312 return GL_FALSE; 01313 } 01314 return GL_TRUE; 01315 case GL_PROXY_TEXTURE_2D: 01316 maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 01317 if (width < 2 * border || width > 2 + maxSize || 01318 (!ctx->Extensions.ARB_texture_non_power_of_two && 01319 width > 0 && !_mesa_is_pow_two(width - 2 * border)) || 01320 height < 2 * border || height > 2 + maxSize || 01321 (!ctx->Extensions.ARB_texture_non_power_of_two && 01322 height > 0 && !_mesa_is_pow_two(height - 2 * border)) || 01323 level >= ctx->Const.MaxTextureLevels) { 01324 /* bad width or height or level */ 01325 return GL_FALSE; 01326 } 01327 return GL_TRUE; 01328 case GL_PROXY_TEXTURE_3D: 01329 maxSize = 1 << (ctx->Const.Max3DTextureLevels - 1); 01330 if (width < 2 * border || width > 2 + maxSize || 01331 (!ctx->Extensions.ARB_texture_non_power_of_two && 01332 width > 0 && !_mesa_is_pow_two(width - 2 * border)) || 01333 height < 2 * border || height > 2 + maxSize || 01334 (!ctx->Extensions.ARB_texture_non_power_of_two && 01335 height > 0 && !_mesa_is_pow_two(height - 2 * border)) || 01336 depth < 2 * border || depth > 2 + maxSize || 01337 (!ctx->Extensions.ARB_texture_non_power_of_two && 01338 depth > 0 && !_mesa_is_pow_two(depth - 2 * border)) || 01339 level >= ctx->Const.Max3DTextureLevels) { 01340 /* bad width or height or depth or level */ 01341 return GL_FALSE; 01342 } 01343 return GL_TRUE; 01344 case GL_PROXY_TEXTURE_RECTANGLE_NV: 01345 if (width < 0 || width > ctx->Const.MaxTextureRectSize || 01346 height < 0 || height > ctx->Const.MaxTextureRectSize || 01347 level != 0) { 01348 /* bad width or height or level */ 01349 return GL_FALSE; 01350 } 01351 return GL_TRUE; 01352 case GL_PROXY_TEXTURE_CUBE_MAP_ARB: 01353 maxSize = 1 << (ctx->Const.MaxCubeTextureLevels - 1); 01354 if (width < 2 * border || width > 2 + maxSize || 01355 (!ctx->Extensions.ARB_texture_non_power_of_two && 01356 width > 0 && !_mesa_is_pow_two(width - 2 * border)) || 01357 height < 2 * border || height > 2 + maxSize || 01358 (!ctx->Extensions.ARB_texture_non_power_of_two && 01359 height > 0 && !_mesa_is_pow_two(height - 2 * border)) || 01360 level >= ctx->Const.MaxCubeTextureLevels) { 01361 /* bad width or height */ 01362 return GL_FALSE; 01363 } 01364 return GL_TRUE; 01365 case GL_PROXY_TEXTURE_1D_ARRAY_EXT: 01366 maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 01367 if (width < 2 * border || width > 2 + maxSize || 01368 (!ctx->Extensions.ARB_texture_non_power_of_two && 01369 width > 0 && !_mesa_is_pow_two(width - 2 * border)) || 01370 level >= ctx->Const.MaxTextureLevels) { 01371 /* bad width or level */ 01372 return GL_FALSE; 01373 } 01374 01375 if (height < 1 || height > ctx->Const.MaxArrayTextureLayers) { 01376 return GL_FALSE; 01377 } 01378 return GL_TRUE; 01379 case GL_PROXY_TEXTURE_2D_ARRAY_EXT: 01380 maxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 01381 if (width < 2 * border || width > 2 + maxSize || 01382 (!ctx->Extensions.ARB_texture_non_power_of_two && 01383 width > 0 && !_mesa_is_pow_two(width - 2 * border)) || 01384 height < 2 * border || height > 2 + maxSize || 01385 (!ctx->Extensions.ARB_texture_non_power_of_two && 01386 height > 0 && !_mesa_is_pow_two(height - 2 * border)) || 01387 level >= ctx->Const.MaxTextureLevels) { 01388 /* bad width or height or level */ 01389 return GL_FALSE; 01390 } 01391 if (depth < 1 || depth > ctx->Const.MaxArrayTextureLayers) { 01392 return GL_FALSE; 01393 } 01394 return GL_TRUE; 01395 default: 01396 _mesa_problem(ctx, "Invalid target in _mesa_test_proxy_teximage"); 01397 return GL_FALSE; 01398 } 01399 } 01400 01401 01405 static GLboolean 01406 target_can_be_compressed(GLcontext *ctx, GLenum target) 01407 { 01408 return (((target == GL_TEXTURE_2D || target == GL_PROXY_TEXTURE_2D)) 01409 || ((ctx->Extensions.ARB_texture_cube_map && 01410 (target == GL_PROXY_TEXTURE_CUBE_MAP || 01411 (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && 01412 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z)))) 01413 || ((ctx->Extensions.MESA_texture_array && 01414 ((target == GL_PROXY_TEXTURE_2D_ARRAY_EXT) || 01415 (target == GL_TEXTURE_2D_ARRAY_EXT))))); 01416 } 01417 01418 01440 static GLboolean 01441 texture_error_check( GLcontext *ctx, GLenum target, 01442 GLint level, GLint internalFormat, 01443 GLenum format, GLenum type, 01444 GLuint dimensions, 01445 GLint width, GLint height, 01446 GLint depth, GLint border ) 01447 { 01448 const GLboolean isProxy = _mesa_is_proxy_texture(target); 01449 GLboolean sizeOK = GL_TRUE; 01450 GLboolean colorFormat, indexFormat; 01451 GLenum proxy_target; 01452 01453 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */ 01454 if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 01455 if (!isProxy) { 01456 _mesa_error(ctx, GL_INVALID_VALUE, 01457 "glTexImage%dD(level=%d)", dimensions, level); 01458 } 01459 return GL_TRUE; 01460 } 01461 01462 /* Check border */ 01463 if (border < 0 || border > 1 || 01464 ((target == GL_TEXTURE_RECTANGLE_NV || 01465 target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) { 01466 if (!isProxy) { 01467 _mesa_error(ctx, GL_INVALID_VALUE, 01468 "glTexImage%dD(border=%d)", dimensions, border); 01469 } 01470 return GL_TRUE; 01471 } 01472 01473 if (width < 0 || height < 0 || depth < 0) { 01474 if (!isProxy) { 01475 _mesa_error(ctx, GL_INVALID_VALUE, 01476 "glTexImage%dD(width, height or depth < 0)", dimensions); 01477 } 01478 return GL_TRUE; 01479 } 01480 01481 /* Check target and call ctx->Driver.TestProxyTexImage() to check the 01482 * level, width, height and depth. 01483 */ 01484 if (dimensions == 1) { 01485 if (target == GL_PROXY_TEXTURE_1D || target == GL_TEXTURE_1D) { 01486 proxy_target = GL_PROXY_TEXTURE_1D; 01487 height = 1; 01488 depth = 1; 01489 } 01490 else { 01491 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); 01492 return GL_TRUE; 01493 } 01494 } 01495 else if (dimensions == 2) { 01496 depth = 1; 01497 if (target == GL_PROXY_TEXTURE_2D || target == GL_TEXTURE_2D) { 01498 proxy_target = GL_PROXY_TEXTURE_2D; 01499 } 01500 else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB || 01501 (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 01502 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) { 01503 if (!ctx->Extensions.ARB_texture_cube_map) { 01504 _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)"); 01505 return GL_TRUE; 01506 } 01507 proxy_target = GL_PROXY_TEXTURE_CUBE_MAP_ARB; 01508 sizeOK = (width == height); 01509 } 01510 else if (target == GL_PROXY_TEXTURE_RECTANGLE_NV || 01511 target == GL_TEXTURE_RECTANGLE_NV) { 01512 if (!ctx->Extensions.NV_texture_rectangle) { 01513 _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)"); 01514 return GL_TRUE; 01515 } 01516 proxy_target = GL_PROXY_TEXTURE_RECTANGLE_NV; 01517 } 01518 else if (target == GL_PROXY_TEXTURE_1D_ARRAY_EXT || 01519 target == GL_TEXTURE_1D_ARRAY_EXT) { 01520 proxy_target = GL_PROXY_TEXTURE_1D_ARRAY_EXT; 01521 } 01522 else { 01523 _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage2D(target)"); 01524 return GL_TRUE; 01525 } 01526 } 01527 else if (dimensions == 3) { 01528 if (target == GL_PROXY_TEXTURE_3D || target == GL_TEXTURE_3D) { 01529 proxy_target = GL_PROXY_TEXTURE_3D; 01530 } 01531 else if (target == GL_PROXY_TEXTURE_2D_ARRAY_EXT || 01532 target == GL_TEXTURE_2D_ARRAY_EXT) { 01533 proxy_target = GL_PROXY_TEXTURE_2D_ARRAY_EXT; 01534 } 01535 else { 01536 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" ); 01537 return GL_TRUE; 01538 } 01539 } 01540 else { 01541 _mesa_problem( ctx, "bad dims in texture_error_check" ); 01542 return GL_TRUE; 01543 } 01544 01545 sizeOK = sizeOK && ctx->Driver.TestProxyTexImage(ctx, proxy_target, level, 01546 internalFormat, format, 01547 type, width, height, 01548 depth, border); 01549 if (!sizeOK) { 01550 if (!isProxy) { 01551 _mesa_error(ctx, GL_INVALID_VALUE, 01552 "glTexImage%dD(level=%d, width=%d, height=%d, depth=%d)", 01553 dimensions, level, width, height, depth); 01554 } 01555 return GL_TRUE; 01556 } 01557 01558 /* Check internalFormat */ 01559 if (_mesa_base_tex_format(ctx, internalFormat) < 0) { 01560 if (!isProxy) { 01561 _mesa_error(ctx, GL_INVALID_VALUE, 01562 "glTexImage%dD(internalFormat=0x%x)", 01563 dimensions, internalFormat); 01564 } 01565 return GL_TRUE; 01566 } 01567 01568 /* Check incoming image format and type */ 01569 if (!_mesa_is_legal_format_and_type(ctx, format, type)) { 01570 /* Yes, generate GL_INVALID_OPERATION, not GL_INVALID_ENUM, if there 01571 * is a type/format mismatch. See 1.2 spec page 94, sec 3.6.4. 01572 */ 01573 if (!isProxy) { 01574 _mesa_error(ctx, GL_INVALID_OPERATION, 01575 "glTexImage%dD(format or type)", dimensions); 01576 } 01577 return GL_TRUE; 01578 } 01579 01580 /* make sure internal format and format basically agree */ 01581 colorFormat = _mesa_is_color_format(format); 01582 indexFormat = is_index_format(format); 01583 if ((_mesa_is_color_format(internalFormat) && !colorFormat && !indexFormat) || 01584 (is_index_format(internalFormat) && !indexFormat) || 01585 (is_depth_format(internalFormat) != is_depth_format(format)) || 01586 (is_ycbcr_format(internalFormat) != is_ycbcr_format(format)) || 01587 (is_depthstencil_format(internalFormat) != is_depthstencil_format(format))) { 01588 if (!isProxy) 01589 _mesa_error(ctx, GL_INVALID_OPERATION, 01590 "glTexImage(internalFormat/format)"); 01591 return GL_TRUE; 01592 } 01593 01594 /* additional checks for ycbcr textures */ 01595 if (internalFormat == GL_YCBCR_MESA) { 01596 ASSERT(ctx->Extensions.MESA_ycbcr_texture); 01597 if (type != GL_UNSIGNED_SHORT_8_8_MESA && 01598 type != GL_UNSIGNED_SHORT_8_8_REV_MESA) { 01599 char message[100]; 01600 _mesa_sprintf(message, 01601 "glTexImage%d(format/type YCBCR mismatch", dimensions); 01602 _mesa_error(ctx, GL_INVALID_ENUM, message); 01603 return GL_TRUE; /* error */ 01604 } 01605 if (target != GL_TEXTURE_2D && 01606 target != GL_PROXY_TEXTURE_2D && 01607 target != GL_TEXTURE_RECTANGLE_NV && 01608 target != GL_PROXY_TEXTURE_RECTANGLE_NV) { 01609 if (!isProxy) 01610 _mesa_error(ctx, GL_INVALID_ENUM, "glTexImage(target)"); 01611 return GL_TRUE; 01612 } 01613 if (border != 0) { 01614 if (!isProxy) { 01615 char message[100]; 01616 _mesa_sprintf(message, 01617 "glTexImage%d(format=GL_YCBCR_MESA and border=%d)", 01618 dimensions, border); 01619 _mesa_error(ctx, GL_INVALID_VALUE, message); 01620 } 01621 return GL_TRUE; 01622 } 01623 } 01624 01625 /* additional checks for depth textures */ 01626 if (_mesa_base_tex_format(ctx, internalFormat) == GL_DEPTH_COMPONENT) { 01627 /* Only 1D, 2D and rectangular textures supported, not 3D or cubes */ 01628 if (target != GL_TEXTURE_1D && 01629 target != GL_PROXY_TEXTURE_1D && 01630 target != GL_TEXTURE_2D && 01631 target != GL_PROXY_TEXTURE_2D && 01632 target != GL_TEXTURE_RECTANGLE_ARB && 01633 target != GL_PROXY_TEXTURE_RECTANGLE_ARB) { 01634 if (!isProxy) 01635 _mesa_error(ctx, GL_INVALID_ENUM, 01636 "glTexImage(target/internalFormat)"); 01637 return GL_TRUE; 01638 } 01639 } 01640 01641 /* additional checks for compressed textures */ 01642 if (is_compressed_format(ctx, internalFormat)) { 01643 if (!target_can_be_compressed(ctx, target) && !isProxy) { 01644 _mesa_error(ctx, GL_INVALID_ENUM, 01645 "glTexImage%d(target)", dimensions); 01646 return GL_TRUE; 01647 } 01648 if (border != 0) { 01649 if (!isProxy) { 01650 _mesa_error(ctx, GL_INVALID_OPERATION, 01651 "glTexImage%D(border!=0)", dimensions); 01652 } 01653 return GL_TRUE; 01654 } 01655 } 01656 01657 /* if we get here, the parameters are OK */ 01658 return GL_FALSE; 01659 } 01660 01661 01684 static GLboolean 01685 subtexture_error_check( GLcontext *ctx, GLuint dimensions, 01686 GLenum target, GLint level, 01687 GLint xoffset, GLint yoffset, GLint zoffset, 01688 GLint width, GLint height, GLint depth, 01689 GLenum format, GLenum type ) 01690 { 01691 /* Check target */ 01692 if (dimensions == 1) { 01693 if (target != GL_TEXTURE_1D) { 01694 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage1D(target)" ); 01695 return GL_TRUE; 01696 } 01697 } 01698 else if (dimensions == 2) { 01699 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 01700 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 01701 if (!ctx->Extensions.ARB_texture_cube_map) { 01702 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); 01703 return GL_TRUE; 01704 } 01705 } 01706 else if (target == GL_TEXTURE_RECTANGLE_NV) { 01707 if (!ctx->Extensions.NV_texture_rectangle) { 01708 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); 01709 return GL_TRUE; 01710 } 01711 } 01712 else if (target == GL_TEXTURE_1D_ARRAY_EXT) { 01713 if (!ctx->Extensions.MESA_texture_array) { 01714 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); 01715 return GL_TRUE; 01716 } 01717 } 01718 else if (target != GL_TEXTURE_2D) { 01719 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage2D(target)" ); 01720 return GL_TRUE; 01721 } 01722 } 01723 else if (dimensions == 3) { 01724 if (target == GL_TEXTURE_2D_ARRAY_EXT) { 01725 if (!ctx->Extensions.MESA_texture_array) { 01726 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" ); 01727 return GL_TRUE; 01728 } 01729 } 01730 else if (target != GL_TEXTURE_3D) { 01731 _mesa_error( ctx, GL_INVALID_ENUM, "glTexSubImage3D(target)" ); 01732 return GL_TRUE; 01733 } 01734 } 01735 else { 01736 _mesa_problem( ctx, "invalid dims in texture_error_check" ); 01737 return GL_TRUE; 01738 } 01739 01740 /* Basic level check */ 01741 if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 01742 _mesa_error(ctx, GL_INVALID_ENUM, "glTexSubImage2D(level=%d)", level); 01743 return GL_TRUE; 01744 } 01745 01746 if (width < 0) { 01747 _mesa_error(ctx, GL_INVALID_VALUE, 01748 "glTexSubImage%dD(width=%d)", dimensions, width); 01749 return GL_TRUE; 01750 } 01751 if (height < 0 && dimensions > 1) { 01752 _mesa_error(ctx, GL_INVALID_VALUE, 01753 "glTexSubImage%dD(height=%d)", dimensions, height); 01754 return GL_TRUE; 01755 } 01756 if (depth < 0 && dimensions > 2) { 01757 _mesa_error(ctx, GL_INVALID_VALUE, 01758 "glTexSubImage%dD(depth=%d)", dimensions, depth); 01759 return GL_TRUE; 01760 } 01761 01762 if (!_mesa_is_legal_format_and_type(ctx, format, type)) { 01763 _mesa_error(ctx, GL_INVALID_ENUM, 01764 "glTexSubImage%dD(format or type)", dimensions); 01765 return GL_TRUE; 01766 } 01767 01768 return GL_FALSE; 01769 } 01770 01771 static GLboolean 01772 subtexture_error_check2( GLcontext *ctx, GLuint dimensions, 01773 GLenum target, GLint level, 01774 GLint xoffset, GLint yoffset, GLint zoffset, 01775 GLint width, GLint height, GLint depth, 01776 GLenum format, GLenum type, 01777 const struct gl_texture_image *destTex ) 01778 { 01779 if (!destTex) { 01780 /* undefined image level */ 01781 _mesa_error(ctx, GL_INVALID_OPERATION, "glTexSubImage%dD", dimensions); 01782 return GL_TRUE; 01783 } 01784 01785 if (xoffset < -((GLint)destTex->Border)) { 01786 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset)", 01787 dimensions); 01788 return GL_TRUE; 01789 } 01790 if (xoffset + width > (GLint) (destTex->Width + destTex->Border)) { 01791 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(xoffset+width)", 01792 dimensions); 01793 return GL_TRUE; 01794 } 01795 if (dimensions > 1) { 01796 if (yoffset < -((GLint)destTex->Border)) { 01797 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset)", 01798 dimensions); 01799 return GL_TRUE; 01800 } 01801 if (yoffset + height > (GLint) (destTex->Height + destTex->Border)) { 01802 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage%dD(yoffset+height)", 01803 dimensions); 01804 return GL_TRUE; 01805 } 01806 } 01807 if (dimensions > 2) { 01808 if (zoffset < -((GLint)destTex->Border)) { 01809 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset)"); 01810 return GL_TRUE; 01811 } 01812 if (zoffset + depth > (GLint) (destTex->Depth + destTex->Border)) { 01813 _mesa_error(ctx, GL_INVALID_VALUE, "glTexSubImage3D(zoffset+depth)"); 01814 return GL_TRUE; 01815 } 01816 } 01817 01818 #if FEATURE_EXT_texture_sRGB 01819 if (destTex->InternalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT || 01820 destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT || 01821 destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT || 01822 destTex->InternalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) { 01823 if ((width & 0x3) || (height & 0x3) || 01824 (xoffset & 0x3) || (yoffset & 0x3)) 01825 _mesa_error(ctx, GL_INVALID_OPERATION, 01826 "glTexSubImage%dD(size or offset not multiple of 4)", 01827 dimensions); 01828 return GL_TRUE; 01829 } 01830 #endif 01831 01832 if (destTex->IsCompressed) { 01833 if (!target_can_be_compressed(ctx, target)) { 01834 _mesa_error(ctx, GL_INVALID_ENUM, 01835 "glTexSubImage%D(target)", dimensions); 01836 return GL_TRUE; 01837 } 01838 /* offset must be multiple of 4 */ 01839 if ((xoffset & 3) || (yoffset & 3)) { 01840 _mesa_error(ctx, GL_INVALID_OPERATION, 01841 "glTexSubImage%D(xoffset or yoffset)", dimensions); 01842 return GL_TRUE; 01843 } 01844 /* size must be multiple of 4 or equal to whole texture size */ 01845 if ((width & 3) && (GLuint) width != destTex->Width) { 01846 _mesa_error(ctx, GL_INVALID_OPERATION, 01847 "glTexSubImage%D(width)", dimensions); 01848 return GL_TRUE; 01849 } 01850 if ((height & 3) && (GLuint) height != destTex->Height) { 01851 _mesa_error(ctx, GL_INVALID_OPERATION, 01852 "glTexSubImage%D(width)", dimensions); 01853 return GL_TRUE; 01854 } 01855 } 01856 01857 return GL_FALSE; 01858 } 01859 01860 01880 static GLboolean 01881 copytexture_error_check( GLcontext *ctx, GLuint dimensions, 01882 GLenum target, GLint level, GLint internalFormat, 01883 GLint width, GLint height, GLint border ) 01884 { 01885 GLenum type; 01886 GLboolean sizeOK; 01887 GLint format; 01888 01889 /* Basic level check (more checking in ctx->Driver.TestProxyTexImage) */ 01890 if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 01891 _mesa_error(ctx, GL_INVALID_VALUE, 01892 "glCopyTexImage%dD(level=%d)", dimensions, level); 01893 return GL_TRUE; 01894 } 01895 01896 /* Check that the source buffer is complete */ 01897 if (ctx->ReadBuffer->Name) { 01898 _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer); 01899 if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 01900 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 01901 "glCopyTexImage%dD(invalid readbuffer)", dimensions); 01902 return GL_TRUE; 01903 } 01904 } 01905 01906 /* Check border */ 01907 if (border < 0 || border > 1 || 01908 ((target == GL_TEXTURE_RECTANGLE_NV || 01909 target == GL_PROXY_TEXTURE_RECTANGLE_NV) && border != 0)) { 01910 return GL_TRUE; 01911 } 01912 01913 format = _mesa_base_tex_format(ctx, internalFormat); 01914 if (format < 0) { 01915 _mesa_error(ctx, GL_INVALID_VALUE, 01916 "glCopyTexImage%dD(internalFormat)", dimensions); 01917 return GL_TRUE; 01918 } 01919 01920 /* NOTE: the format and type aren't really significant for 01921 * TestProxyTexImage(). Only the internalformat really matters. 01922 if (!_mesa_source_buffer_exists(ctx, format)) { 01923 _mesa_error(ctx, GL_INVALID_OPERATION, 01924 "glCopyTexImage%dD(missing readbuffer)", dimensions); 01925 return GL_TRUE; 01926 } 01927 01928 */ 01929 type = GL_FLOAT; 01930 01931 /* Check target and call ctx->Driver.TestProxyTexImage() to check the 01932 * level, width, height and depth. 01933 */ 01934 if (dimensions == 1) { 01935 if (target == GL_TEXTURE_1D) { 01936 sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_1D, 01937 level, internalFormat, 01938 format, type, 01939 width, 1, 1, border); 01940 } 01941 else { 01942 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage1D(target)" ); 01943 return GL_TRUE; 01944 } 01945 } 01946 else if (dimensions == 2) { 01947 if (target == GL_TEXTURE_2D) { 01948 sizeOK = ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_2D, 01949 level, internalFormat, 01950 format, type, 01951 width, height, 1, border); 01952 } 01953 else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 01954 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 01955 if (!ctx->Extensions.ARB_texture_cube_map) { 01956 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); 01957 return GL_TRUE; 01958 } 01959 sizeOK = (width == height) && 01960 ctx->Driver.TestProxyTexImage(ctx, GL_PROXY_TEXTURE_CUBE_MAP_ARB, 01961 level, internalFormat, format, type, 01962 width, height, 1, border); 01963 } 01964 else if (target == GL_TEXTURE_RECTANGLE_NV) { 01965 if (!ctx->Extensions.NV_texture_rectangle) { 01966 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); 01967 return GL_TRUE; 01968 } 01969 sizeOK = ctx->Driver.TestProxyTexImage(ctx, 01970 GL_PROXY_TEXTURE_RECTANGLE_NV, 01971 level, internalFormat, 01972 format, type, 01973 width, height, 1, border); 01974 } 01975 else if (target == GL_TEXTURE_1D_ARRAY_EXT) { 01976 if (!ctx->Extensions.MESA_texture_array) { 01977 _mesa_error(ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)"); 01978 return GL_TRUE; 01979 } 01980 sizeOK = ctx->Driver.TestProxyTexImage(ctx, 01981 GL_PROXY_TEXTURE_1D_ARRAY_EXT, 01982 level, internalFormat, 01983 format, type, 01984 width, height, 1, border); 01985 } 01986 else { 01987 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexImage2D(target)" ); 01988 return GL_TRUE; 01989 } 01990 } 01991 else { 01992 _mesa_problem(ctx, "invalid dimensions in copytexture_error_check"); 01993 return GL_TRUE; 01994 } 01995 01996 if (!sizeOK) { 01997 if (dimensions == 1) { 01998 _mesa_error(ctx, GL_INVALID_VALUE, 01999 "glCopyTexImage1D(width=%d)", width); 02000 } 02001 else { 02002 ASSERT(dimensions == 2); 02003 _mesa_error(ctx, GL_INVALID_VALUE, 02004 "glCopyTexImage2D(width=%d, height=%d)", width, height); 02005 } 02006 return GL_TRUE; 02007 } 02008 02009 if (is_compressed_format(ctx, internalFormat)) { 02010 if (!target_can_be_compressed(ctx, target)) { 02011 _mesa_error(ctx, GL_INVALID_ENUM, 02012 "glCopyTexImage%d(target)", dimensions); 02013 return GL_TRUE; 02014 } 02015 if (border != 0) { 02016 _mesa_error(ctx, GL_INVALID_OPERATION, 02017 "glCopyTexImage%D(border!=0)", dimensions); 02018 return GL_TRUE; 02019 } 02020 } 02021 else if (is_depth_format(internalFormat)) { 02022 /* make sure we have depth/stencil buffers */ 02023 if (!ctx->ReadBuffer->_DepthBuffer) { 02024 _mesa_error(ctx, GL_INVALID_OPERATION, 02025 "glCopyTexImage%D(no depth)", dimensions); 02026 return GL_TRUE; 02027 } 02028 } 02029 else if (is_depthstencil_format(internalFormat)) { 02030 /* make sure we have depth/stencil buffers */ 02031 if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) { 02032 _mesa_error(ctx, GL_INVALID_OPERATION, 02033 "glCopyTexImage%D(no depth/stencil buffer)", dimensions); 02034 return GL_TRUE; 02035 } 02036 } 02037 02038 /* if we get here, the parameters are OK */ 02039 return GL_FALSE; 02040 } 02041 02042 02055 static GLboolean 02056 copytexsubimage_error_check1( GLcontext *ctx, GLuint dimensions, 02057 GLenum target, GLint level) 02058 { 02059 /* Check that the source buffer is complete */ 02060 if (ctx->ReadBuffer->Name) { 02061 _mesa_test_framebuffer_completeness(ctx, ctx->ReadBuffer); 02062 if (ctx->ReadBuffer->_Status != GL_FRAMEBUFFER_COMPLETE_EXT) { 02063 _mesa_error(ctx, GL_INVALID_FRAMEBUFFER_OPERATION_EXT, 02064 "glCopyTexImage%dD(invalid readbuffer)", dimensions); 02065 return GL_TRUE; 02066 } 02067 } 02068 02069 /* Check target */ 02070 if (dimensions == 1) { 02071 if (target != GL_TEXTURE_1D) { 02072 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage1D(target)" ); 02073 return GL_TRUE; 02074 } 02075 } 02076 else if (dimensions == 2) { 02077 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 02078 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 02079 if (!ctx->Extensions.ARB_texture_cube_map) { 02080 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); 02081 return GL_TRUE; 02082 } 02083 } 02084 else if (target == GL_TEXTURE_RECTANGLE_NV) { 02085 if (!ctx->Extensions.NV_texture_rectangle) { 02086 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); 02087 return GL_TRUE; 02088 } 02089 } 02090 else if (target == GL_TEXTURE_1D_ARRAY_EXT) { 02091 if (!ctx->Extensions.MESA_texture_array) { 02092 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); 02093 return GL_TRUE; 02094 } 02095 } 02096 else if (target != GL_TEXTURE_2D) { 02097 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage2D(target)" ); 02098 return GL_TRUE; 02099 } 02100 } 02101 else if (dimensions == 3) { 02102 if (((target != GL_TEXTURE_2D_ARRAY_EXT) || 02103 (!ctx->Extensions.MESA_texture_array)) 02104 && (target != GL_TEXTURE_3D)) { 02105 _mesa_error( ctx, GL_INVALID_ENUM, "glCopyTexSubImage3D(target)" ); 02106 return GL_TRUE; 02107 } 02108 } 02109 02110 /* Check level */ 02111 if (level < 0 || level >= MAX_TEXTURE_LEVELS) { 02112 _mesa_error(ctx, GL_INVALID_VALUE, 02113 "glCopyTexSubImage%dD(level=%d)", dimensions, level); 02114 return GL_TRUE; 02115 } 02116 02117 return GL_FALSE; 02118 } 02119 02120 02129 static GLboolean 02130 copytexsubimage_error_check2( GLcontext *ctx, GLuint dimensions, 02131 GLenum target, GLint level, 02132 GLint xoffset, GLint yoffset, GLint zoffset, 02133 GLsizei width, GLsizei height, 02134 const struct gl_texture_image *teximage ) 02135 { 02136 /* check that dest tex image exists */ 02137 if (!teximage) { 02138 _mesa_error(ctx, GL_INVALID_OPERATION, 02139 "glCopyTexSubImage%dD(undefined texture level: %d)", 02140 dimensions, level); 02141 return GL_TRUE; 02142 } 02143 02144 /* Check size */ 02145 if (width < 0) { 02146 _mesa_error(ctx, GL_INVALID_VALUE, 02147 "glCopyTexSubImage%dD(width=%d)", dimensions, width); 02148 return GL_TRUE; 02149 } 02150 if (dimensions > 1 && height < 0) { 02151 _mesa_error(ctx, GL_INVALID_VALUE, 02152 "glCopyTexSubImage%dD(height=%d)", dimensions, height); 02153 return GL_TRUE; 02154 } 02155 02156 /* check x/y offsets */ 02157 if (xoffset < -((GLint)teximage->Border)) { 02158 _mesa_error(ctx, GL_INVALID_VALUE, 02159 "glCopyTexSubImage%dD(xoffset=%d)", dimensions, xoffset); 02160 return GL_TRUE; 02161 } 02162 if (xoffset + width > (GLint) (teximage->Width + teximage->Border)) { 02163 _mesa_error(ctx, GL_INVALID_VALUE, 02164 "glCopyTexSubImage%dD(xoffset+width)", dimensions); 02165 return GL_TRUE; 02166 } 02167 if (dimensions > 1) { 02168 if (yoffset < -((GLint)teximage->Border)) { 02169 _mesa_error(ctx, GL_INVALID_VALUE, 02170 "glCopyTexSubImage%dD(yoffset=%d)", dimensions, yoffset); 02171 return GL_TRUE; 02172 } 02173 /* NOTE: we're adding the border here, not subtracting! */ 02174 if (yoffset + height > (GLint) (teximage->Height + teximage->Border)) { 02175 _mesa_error(ctx, GL_INVALID_VALUE, 02176 "glCopyTexSubImage%dD(yoffset+height)", dimensions); 02177 return GL_TRUE; 02178 } 02179 } 02180 02181 /* check z offset */ 02182 if (dimensions > 2) { 02183 if (zoffset < -((GLint)teximage->Border)) { 02184 _mesa_error(ctx, GL_INVALID_VALUE, 02185 "glCopyTexSubImage%dD(zoffset)", dimensions); 02186 return GL_TRUE; 02187 } 02188 if (zoffset > (GLint) (teximage->Depth + teximage->Border)) { 02189 _mesa_error(ctx, GL_INVALID_VALUE, 02190 "glCopyTexSubImage%dD(zoffset+depth)", dimensions); 02191 return GL_TRUE; 02192 } 02193 } 02194 02195 if (teximage->IsCompressed) { 02196 if (!target_can_be_compressed(ctx, target)) { 02197 _mesa_error(ctx, GL_INVALID_ENUM, 02198 "glCopyTexSubImage%d(target)", dimensions); 02199 return GL_TRUE; 02200 } 02201 /* offset must be multiple of 4 */ 02202 if ((xoffset & 3) || (yoffset & 3)) { 02203 _mesa_error(ctx, GL_INVALID_VALUE, 02204 "glCopyTexSubImage%D(xoffset or yoffset)", dimensions); 02205 return GL_TRUE; 02206 } 02207 /* size must be multiple of 4 */ 02208 if ((width & 3) != 0 && (GLuint) width != teximage->Width) { 02209 _mesa_error(ctx, GL_INVALID_VALUE, 02210 "glCopyTexSubImage%D(width)", dimensions); 02211 return GL_TRUE; 02212 } 02213 if ((height & 3) != 0 && (GLuint) height != teximage->Height) { 02214 _mesa_error(ctx, GL_INVALID_VALUE, 02215 "glCopyTexSubImage%D(height)", dimensions); 02216 return GL_TRUE; 02217 } 02218 } 02219 02220 if (teximage->InternalFormat == GL_YCBCR_MESA) { 02221 _mesa_error(ctx, GL_INVALID_OPERATION, "glCopyTexSubImage2D"); 02222 return GL_TRUE; 02223 } 02224 02225 if (!_mesa_source_buffer_exists(ctx, teximage->_BaseFormat)) { 02226 _mesa_error(ctx, GL_INVALID_OPERATION, 02227 "glCopyTexSubImage%dD(missing readbuffer, format=0x%x)", 02228 dimensions, teximage->_BaseFormat); 02229 return GL_TRUE; 02230 } 02231 02232 if (teximage->_BaseFormat == GL_DEPTH_COMPONENT) { 02233 if (!ctx->ReadBuffer->_DepthBuffer) { 02234 _mesa_error(ctx, GL_INVALID_OPERATION, 02235 "glCopyTexSubImage%D(no depth buffer)", 02236 dimensions); 02237 return GL_TRUE; 02238 } 02239 } 02240 else if (teximage->_BaseFormat == GL_DEPTH_STENCIL_EXT) { 02241 if (!ctx->ReadBuffer->_DepthBuffer || !ctx->ReadBuffer->_StencilBuffer) { 02242 _mesa_error(ctx, GL_INVALID_OPERATION, 02243 "glCopyTexSubImage%D(no depth/stencil buffer)", 02244 dimensions); 02245 return GL_TRUE; 02246 } 02247 } 02248 02249 /* if we get here, the parameters are OK */ 02250 return GL_FALSE; 02251 } 02252 02253 02263 void GLAPIENTRY 02264 _mesa_GetTexImage( GLenum target, GLint level, GLenum format, 02265 GLenum type, GLvoid *pixels ) 02266 { 02267 const struct gl_texture_unit *texUnit; 02268 struct gl_texture_object *texObj; 02269 struct gl_texture_image *texImage; 02270 GLint maxLevels = 0; 02271 GET_CURRENT_CONTEXT(ctx); 02272 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 02273 02274 texUnit = &(ctx->Texture.Unit[ctx->Texture.CurrentUnit]); 02275 texObj = _mesa_select_tex_object(ctx, texUnit, target); 02276 if (!texObj || _mesa_is_proxy_texture(target)) { 02277 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(target)"); 02278 return; 02279 } 02280 02281 maxLevels = _mesa_max_texture_levels(ctx, target); 02282 ASSERT(maxLevels > 0); /* 0 indicates bad target, caught above */ 02283 02284 if (level < 0 || level >= maxLevels) { 02285 _mesa_error( ctx, GL_INVALID_VALUE, "glGetTexImage(level)" ); 02286 return; 02287 } 02288 02289 if (_mesa_sizeof_packed_type(type) <= 0) { 02290 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(type)" ); 02291 return; 02292 } 02293 02294 if (_mesa_components_in_format(format) <= 0 || 02295 format == GL_STENCIL_INDEX) { 02296 _mesa_error( ctx, GL_INVALID_ENUM, "glGetTexImage(format)" ); 02297 return; 02298 } 02299 02300 if (!ctx->Extensions.EXT_paletted_texture && is_index_format(format)) { 02301 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 02302 return; 02303 } 02304 02305 if (!ctx->Extensions.ARB_depth_texture && is_depth_format(format)) { 02306 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 02307 return; 02308 } 02309 02310 if (!ctx->Extensions.MESA_ycbcr_texture && is_ycbcr_format(format)) { 02311 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 02312 return; 02313 } 02314 02315 if (!ctx->Extensions.EXT_packed_depth_stencil 02316 && is_depthstencil_format(format)) { 02317 _mesa_error(ctx, GL_INVALID_ENUM, "glGetTexImage(format)"); 02318 return; 02319 } 02320 02321 _mesa_lock_texture(ctx, texObj); 02322 { 02323 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 02324 if (!texImage) { 02325 /* invalid mipmap level, not an error */ 02326 goto out; 02327 } 02328 02329 02330 /* Make sure the requested image format is compatible with the 02331 * texture's format. Note that a color index texture can be converted 02332 * to RGBA so that combo is allowed. 02333 */ 02334 if (_mesa_is_color_format(format) 02335 && !_mesa_is_color_format(texImage->TexFormat->BaseFormat) 02336 && !is_index_format(texImage->TexFormat->BaseFormat)) { 02337 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 02338 goto out; 02339 } 02340 else if (is_index_format(format) 02341 && !is_index_format(texImage->TexFormat->BaseFormat)) { 02342 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 02343 goto out; 02344 } 02345 else if (is_depth_format(format) 02346 && !is_depth_format(texImage->TexFormat->BaseFormat) 02347 && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) { 02348 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 02349 goto out; 02350 } 02351 else if (is_ycbcr_format(format) 02352 && !is_ycbcr_format(texImage->TexFormat->BaseFormat)) { 02353 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 02354 goto out; 02355 } 02356 else if (is_depthstencil_format(format) 02357 && !is_depthstencil_format(texImage->TexFormat->BaseFormat)) { 02358 _mesa_error(ctx, GL_INVALID_OPERATION, "glGetTexImage(format mismatch)"); 02359 goto out; 02360 } 02361 02362 if (ctx->Pack.BufferObj->Name) { 02363 /* packing texture image into a PBO */ 02364 const GLuint dimensions = (target == GL_TEXTURE_3D) ? 3 : 2; 02365 if (!_mesa_validate_pbo_access(dimensions, &ctx->Pack, texImage->Width, 02366 texImage->Height, texImage->Depth, 02367 format, type, pixels)) { 02368 _mesa_error(ctx, GL_INVALID_OPERATION, 02369 "glGetTexImage(invalid PBO access)"); 02370 goto out; 02371 } 02372 } 02373 02374 /* typically, this will call _mesa_get_teximage() */ 02375 ctx->Driver.GetTexImage(ctx, target, level, format, type, pixels, 02376 texObj, texImage); 02377 02378 } 02379 out: 02380 _mesa_unlock_texture(ctx, texObj); 02381 } 02382 02383 02384 02392 static void 02393 update_fbo_texture(GLcontext *ctx, struct gl_texture_object *texObj, 02394 GLuint face, GLuint level) 02395 { 02396 if (ctx->DrawBuffer->Name) { 02397 GLuint i; 02398 for (i = 0; i < BUFFER_COUNT; i++) { 02399 struct gl_renderbuffer_attachment *att = 02400 ctx->DrawBuffer->Attachment + i; 02401 if (att->Type == GL_TEXTURE && 02402 att->Texture == texObj && 02403 att->TextureLevel == level && 02404 att->CubeMapFace == face) { 02405 ASSERT(att->Texture->Image[att->CubeMapFace][att->TextureLevel]); 02406 /* Tell driver about the new renderbuffer texture */ 02407 ctx->Driver.RenderTexture(ctx, ctx->DrawBuffer, att); 02408 } 02409 } 02410 } 02411 } 02412 02413 02414 02415 /* 02416 * Called from the API. Note that width includes the border. 02417 */ 02418 void GLAPIENTRY 02419 _mesa_TexImage1D( GLenum target, GLint level, GLint internalFormat, 02420 GLsizei width, GLint border, GLenum format, 02421 GLenum type, const GLvoid *pixels ) 02422 { 02423 GLsizei postConvWidth = width; 02424 GET_CURRENT_CONTEXT(ctx); 02425 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 02426 02427 #if FEATURE_convolve 02428 if (_mesa_is_color_format(internalFormat)) { 02429 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 02430 } 02431 #endif 02432 02433 if (target == GL_TEXTURE_1D) { 02434 /* non-proxy target */ 02435 struct gl_texture_unit *texUnit; 02436 struct gl_texture_object *texObj; 02437 struct gl_texture_image *texImage; 02438 const GLuint face = _mesa_tex_target_to_face(target); 02439 02440 if (texture_error_check(ctx, target, level, internalFormat, 02441 format, type, 1, postConvWidth, 1, 1, border)) { 02442 return; /* error was recorded */ 02443 } 02444 02445 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 02446 _mesa_update_state(ctx); 02447 02448 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 02449 texObj = _mesa_select_tex_object(ctx, texUnit, target); 02450 _mesa_lock_texture(ctx, texObj); 02451 { 02452 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 02453 if (!texImage) { 02454 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D"); 02455 goto out; 02456 } 02457 02458 if (texImage->Data) { 02459 ctx->Driver.FreeTexImageData( ctx, texImage ); 02460 } 02461 02462 ASSERT(texImage->Data == NULL); 02463 02464 clear_teximage_fields(texImage); /* not really needed, but helpful */ 02465 _mesa_init_teximage_fields(ctx, target, texImage, 02466 postConvWidth, 1, 1, 02467 border, internalFormat); 02468 02469 ASSERT(ctx->Driver.TexImage1D); 02470 02471 /* Give the texture to the driver! <pixels> may be null! */ 02472 (*ctx->Driver.TexImage1D)(ctx, target, level, internalFormat, 02473 width, border, format, type, pixels, 02474 &ctx->Unpack, texObj, texImage); 02475 02476 ASSERT(texImage->TexFormat); 02477 02478 update_fbo_texture(ctx, texObj, face, level); 02479 02480 /* state update */ 02481 texObj->_Complete = GL_FALSE; 02482 ctx->NewState |= _NEW_TEXTURE; 02483 } 02484 out: 02485 _mesa_unlock_texture(ctx, texObj); 02486 } 02487 else if (target == GL_PROXY_TEXTURE_1D) { 02488 /* Proxy texture: check for errors and update proxy state */ 02489 struct gl_texture_image *texImage; 02490 texImage = _mesa_get_proxy_tex_image(ctx, target, level); 02491 if (texture_error_check(ctx, target, level, internalFormat, 02492 format, type, 1, postConvWidth, 1, 1, border)) { 02493 /* when error, clear all proxy texture image parameters */ 02494 if (texImage) 02495 clear_teximage_fields(texImage); 02496 } 02497 else { 02498 /* no error, set the tex image parameters */ 02499 ASSERT(texImage); 02500 _mesa_init_teximage_fields(ctx, target, texImage, 02501 postConvWidth, 1, 1, 02502 border, internalFormat); 02503 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx, 02504 internalFormat, format, type); 02505 } 02506 } 02507 else { 02508 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage1D(target)" ); 02509 return; 02510 } 02511 } 02512 02513 02514 void GLAPIENTRY 02515 _mesa_TexImage2D( GLenum target, GLint level, GLint internalFormat, 02516 GLsizei width, GLsizei height, GLint border, 02517 GLenum format, GLenum type, 02518 const GLvoid *pixels ) 02519 { 02520 GLsizei postConvWidth = width, postConvHeight = height; 02521 GET_CURRENT_CONTEXT(ctx); 02522 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 02523 02524 #if FEATURE_convolve 02525 if (_mesa_is_color_format(internalFormat)) { 02526 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, 02527 &postConvHeight); 02528 } 02529 #endif 02530 02531 if (target == GL_TEXTURE_2D || 02532 (ctx->Extensions.ARB_texture_cube_map && 02533 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 02534 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) || 02535 (ctx->Extensions.NV_texture_rectangle && 02536 target == GL_TEXTURE_RECTANGLE_NV) || 02537 (ctx->Extensions.MESA_texture_array && 02538 target == GL_TEXTURE_1D_ARRAY_EXT)) { 02539 /* non-proxy target */ 02540 struct gl_texture_unit *texUnit; 02541 struct gl_texture_object *texObj; 02542 struct gl_texture_image *texImage; 02543 const GLuint face = _mesa_tex_target_to_face(target); 02544 02545 if (texture_error_check(ctx, target, level, internalFormat, 02546 format, type, 2, postConvWidth, postConvHeight, 02547 1, border)) { 02548 return; /* error was recorded */ 02549 } 02550 02551 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 02552 _mesa_update_state(ctx); 02553 02554 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 02555 texObj = _mesa_select_tex_object(ctx, texUnit, target); 02556 _mesa_lock_texture(ctx, texObj); 02557 { 02558 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 02559 if (!texImage) { 02560 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D"); 02561 goto out; 02562 } 02563 02564 if (texImage->Data) { 02565 ctx->Driver.FreeTexImageData( ctx, texImage ); 02566 } 02567 02568 ASSERT(texImage->Data == NULL); 02569 clear_teximage_fields(texImage); /* not really needed, but helpful */ 02570 _mesa_init_teximage_fields(ctx, target, texImage, 02571 postConvWidth, postConvHeight, 1, 02572 border, internalFormat); 02573 02574 ASSERT(ctx->Driver.TexImage2D); 02575 02576 /* Give the texture to the driver! <pixels> may be null! */ 02577 (*ctx->Driver.TexImage2D)(ctx, target, level, internalFormat, 02578 width, height, border, format, type, pixels, 02579 &ctx->Unpack, texObj, texImage); 02580 02581 ASSERT(texImage->TexFormat); 02582 02583 update_fbo_texture(ctx, texObj, face, level); 02584 02585 /* state update */ 02586 texObj->_Complete = GL_FALSE; 02587 ctx->NewState |= _NEW_TEXTURE; 02588 } 02589 out: 02590 _mesa_unlock_texture(ctx, texObj); 02591 } 02592 else if (target == GL_PROXY_TEXTURE_2D || 02593 (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB && 02594 ctx->Extensions.ARB_texture_cube_map) || 02595 (target == GL_PROXY_TEXTURE_RECTANGLE_NV && 02596 ctx->Extensions.NV_texture_rectangle) || 02597 (ctx->Extensions.MESA_texture_array && 02598 target == GL_PROXY_TEXTURE_1D_ARRAY_EXT)) { 02599 /* Proxy texture: check for errors and update proxy state */ 02600 struct gl_texture_image *texImage; 02601 texImage = _mesa_get_proxy_tex_image(ctx, target, level); 02602 if (texture_error_check(ctx, target, level, internalFormat, 02603 format, type, 2, postConvWidth, postConvHeight, 02604 1, border)) { 02605 /* when error, clear all proxy texture image parameters */ 02606 if (texImage) 02607 clear_teximage_fields(texImage); 02608 } 02609 else { 02610 /* no error, set the tex image parameters */ 02611 _mesa_init_teximage_fields(ctx, target, texImage, 02612 postConvWidth, postConvHeight, 1, 02613 border, internalFormat); 02614 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx, 02615 internalFormat, format, type); 02616 } 02617 } 02618 else { 02619 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage2D(target)" ); 02620 return; 02621 } 02622 } 02623 02624 02625 /* 02626 * Called by the API or display list executor. 02627 * Note that width and height include the border. 02628 */ 02629 void GLAPIENTRY 02630 _mesa_TexImage3D( GLenum target, GLint level, GLint internalFormat, 02631 GLsizei width, GLsizei height, GLsizei depth, 02632 GLint border, GLenum format, GLenum type, 02633 const GLvoid *pixels ) 02634 { 02635 GET_CURRENT_CONTEXT(ctx); 02636 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 02637 02638 if (target == GL_TEXTURE_3D || 02639 (ctx->Extensions.MESA_texture_array && 02640 target == GL_TEXTURE_2D_ARRAY_EXT)) { 02641 /* non-proxy target */ 02642 struct gl_texture_unit *texUnit; 02643 struct gl_texture_object *texObj; 02644 struct gl_texture_image *texImage; 02645 const GLuint face = _mesa_tex_target_to_face(target); 02646 02647 if (texture_error_check(ctx, target, level, (GLint) internalFormat, 02648 format, type, 3, width, height, depth, border)) { 02649 return; /* error was recorded */ 02650 } 02651 02652 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 02653 _mesa_update_state(ctx); 02654 02655 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 02656 texObj = _mesa_select_tex_object(ctx, texUnit, target); 02657 _mesa_lock_texture(ctx, texObj); 02658 { 02659 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 02660 if (!texImage) { 02661 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage3D"); 02662 goto out; 02663 } 02664 02665 if (texImage->Data) { 02666 ctx->Driver.FreeTexImageData( ctx, texImage ); 02667 } 02668 02669 ASSERT(texImage->Data == NULL); 02670 clear_teximage_fields(texImage); /* not really needed, but helpful */ 02671 _mesa_init_teximage_fields(ctx, target, texImage, 02672 width, height, depth, 02673 border, internalFormat); 02674 02675 ASSERT(ctx->Driver.TexImage3D); 02676 02677 /* Give the texture to the driver! <pixels> may be null! */ 02678 (*ctx->Driver.TexImage3D)(ctx, target, level, internalFormat, 02679 width, height, depth, border, format, type, 02680 pixels, &ctx->Unpack, texObj, texImage); 02681 02682 ASSERT(texImage->TexFormat); 02683 02684 update_fbo_texture(ctx, texObj, face, level); 02685 02686 /* state update */ 02687 texObj->_Complete = GL_FALSE; 02688 ctx->NewState |= _NEW_TEXTURE; 02689 } 02690 out: 02691 _mesa_unlock_texture(ctx, texObj); 02692 } 02693 else if (target == GL_PROXY_TEXTURE_3D || 02694 (ctx->Extensions.MESA_texture_array && 02695 target == GL_PROXY_TEXTURE_2D_ARRAY_EXT)) { 02696 /* Proxy texture: check for errors and update proxy state */ 02697 struct gl_texture_image *texImage; 02698 texImage = _mesa_get_proxy_tex_image(ctx, target, level); 02699 if (texture_error_check(ctx, target, level, internalFormat, 02700 format, type, 3, width, height, depth, border)) { 02701 /* when error, clear all proxy texture image parameters */ 02702 if (texImage) 02703 clear_teximage_fields(texImage); 02704 } 02705 else { 02706 /* no error, set the tex image parameters */ 02707 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 02708 depth, border, internalFormat); 02709 texImage->TexFormat = (*ctx->Driver.ChooseTextureFormat)(ctx, 02710 internalFormat, format, type); 02711 } 02712 } 02713 else { 02714 _mesa_error( ctx, GL_INVALID_ENUM, "glTexImage3D(target)" ); 02715 return; 02716 } 02717 } 02718 02719 02720 void GLAPIENTRY 02721 _mesa_TexImage3DEXT( GLenum target, GLint level, GLenum internalFormat, 02722 GLsizei width, GLsizei height, GLsizei depth, 02723 GLint border, GLenum format, GLenum type, 02724 const GLvoid *pixels ) 02725 { 02726 _mesa_TexImage3D(target, level, (GLint) internalFormat, width, height, 02727 depth, border, format, type, pixels); 02728 } 02729 02730 02731 02732 void GLAPIENTRY 02733 _mesa_TexSubImage1D( GLenum target, GLint level, 02734 GLint xoffset, GLsizei width, 02735 GLenum format, GLenum type, 02736 const GLvoid *pixels ) 02737 { 02738 GLsizei postConvWidth = width; 02739 struct gl_texture_unit *texUnit; 02740 struct gl_texture_object *texObj; 02741 struct gl_texture_image *texImage = NULL; 02742 GET_CURRENT_CONTEXT(ctx); 02743 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 02744 02745 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 02746 _mesa_update_state(ctx); 02747 02748 #if FEATURE_convolve 02749 /* XXX should test internal format */ 02750 if (_mesa_is_color_format(format)) { 02751 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 02752 } 02753 #endif 02754 02755 if (subtexture_error_check(ctx, 1, target, level, xoffset, 0, 0, 02756 postConvWidth, 1, 1, format, type)) { 02757 return; /* error was detected */ 02758 } 02759 02760 02761 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 02762 texObj = _mesa_select_tex_object(ctx, texUnit, target); 02763 assert(texObj); 02764 02765 _mesa_lock_texture(ctx, texObj); 02766 { 02767 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 02768 02769 if (subtexture_error_check2(ctx, 1, target, level, xoffset, 0, 0, 02770 postConvWidth, 1, 1, format, type, texImage)) { 02771 goto out; /* error was detected */ 02772 } 02773 02774 if (width == 0) 02775 goto out; /* no-op, not an error */ 02776 02777 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 02778 xoffset += texImage->Border; 02779 02780 ASSERT(ctx->Driver.TexSubImage1D); 02781 (*ctx->Driver.TexSubImage1D)(ctx, target, level, xoffset, width, 02782 format, type, pixels, &ctx->Unpack, 02783 texObj, texImage); 02784 ctx->NewState |= _NEW_TEXTURE; 02785 } 02786 out: 02787 _mesa_unlock_texture(ctx, texObj); 02788 } 02789 02790 02791 void GLAPIENTRY 02792 _mesa_TexSubImage2D( GLenum target, GLint level, 02793 GLint xoffset, GLint yoffset, 02794 GLsizei width, GLsizei height, 02795 GLenum format, GLenum type, 02796 const GLvoid *pixels ) 02797 { 02798 GLsizei postConvWidth = width, postConvHeight = height; 02799 struct gl_texture_unit *texUnit; 02800 struct gl_texture_object *texObj; 02801 struct gl_texture_image *texImage; 02802 GET_CURRENT_CONTEXT(ctx); 02803 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 02804 02805 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 02806 _mesa_update_state(ctx); 02807 02808 #if FEATURE_convolve 02809 /* XXX should test internal format */ 02810 if (_mesa_is_color_format(format)) { 02811 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, 02812 &postConvHeight); 02813 } 02814 #endif 02815 02816 if (subtexture_error_check(ctx, 2, target, level, xoffset, yoffset, 0, 02817 postConvWidth, postConvHeight, 1, format, type)) { 02818 return; /* error was detected */ 02819 } 02820 02821 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 02822 texObj = _mesa_select_tex_object(ctx, texUnit, target); 02823 _mesa_lock_texture(ctx, texObj); 02824 { 02825 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 02826 02827 if (subtexture_error_check2(ctx, 2, target, level, xoffset, yoffset, 0, 02828 postConvWidth, postConvHeight, 1, format, type, 02829 texImage)) { 02830 goto out; /* error was detected */ 02831 } 02832 02833 if (width == 0 || height == 0) 02834 goto out; /* no-op, not an error */ 02835 02836 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 02837 xoffset += texImage->Border; 02838 yoffset += texImage->Border; 02839 02840 ASSERT(ctx->Driver.TexSubImage2D); 02841 (*ctx->Driver.TexSubImage2D)(ctx, target, level, xoffset, yoffset, 02842 width, height, format, type, pixels, 02843 &ctx->Unpack, texObj, texImage); 02844 ctx->NewState |= _NEW_TEXTURE; 02845 } 02846 out: 02847 _mesa_unlock_texture(ctx, texObj); 02848 } 02849 02850 02851 02852 void GLAPIENTRY 02853 _mesa_TexSubImage3D( GLenum target, GLint level, 02854 GLint xoffset, GLint yoffset, GLint zoffset, 02855 GLsizei width, GLsizei height, GLsizei depth, 02856 GLenum format, GLenum type, 02857 const GLvoid *pixels ) 02858 { 02859 struct gl_texture_unit *texUnit; 02860 struct gl_texture_object *texObj; 02861 struct gl_texture_image *texImage; 02862 GET_CURRENT_CONTEXT(ctx); 02863 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 02864 02865 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 02866 _mesa_update_state(ctx); 02867 02868 if (subtexture_error_check(ctx, 3, target, level, xoffset, yoffset, zoffset, 02869 width, height, depth, format, type)) { 02870 return; /* error was detected */ 02871 } 02872 02873 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 02874 texObj = _mesa_select_tex_object(ctx, texUnit, target); 02875 02876 _mesa_lock_texture(ctx, texObj); 02877 { 02878 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 02879 02880 if (subtexture_error_check2(ctx, 3, target, level, xoffset, yoffset, zoffset, 02881 width, height, depth, format, type, texImage)) { 02882 goto out; /* error was detected */ 02883 } 02884 02885 if (width == 0 || height == 0 || height == 0) 02886 goto out; /* no-op, not an error */ 02887 02888 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 02889 xoffset += texImage->Border; 02890 yoffset += texImage->Border; 02891 zoffset += texImage->Border; 02892 02893 ASSERT(ctx->Driver.TexSubImage3D); 02894 (*ctx->Driver.TexSubImage3D)(ctx, target, level, 02895 xoffset, yoffset, zoffset, 02896 width, height, depth, 02897 format, type, pixels, 02898 &ctx->Unpack, texObj, texImage ); 02899 ctx->NewState |= _NEW_TEXTURE; 02900 } 02901 out: 02902 _mesa_unlock_texture(ctx, texObj); 02903 } 02904 02905 02906 02907 void GLAPIENTRY 02908 _mesa_CopyTexImage1D( GLenum target, GLint level, 02909 GLenum internalFormat, 02910 GLint x, GLint y, 02911 GLsizei width, GLint border ) 02912 { 02913 struct gl_texture_unit *texUnit; 02914 struct gl_texture_object *texObj; 02915 struct gl_texture_image *texImage; 02916 GLsizei postConvWidth = width; 02917 const GLuint face = _mesa_tex_target_to_face(target); 02918 GET_CURRENT_CONTEXT(ctx); 02919 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 02920 02921 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 02922 _mesa_update_state(ctx); 02923 02924 #if FEATURE_convolve 02925 if (_mesa_is_color_format(internalFormat)) { 02926 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 02927 } 02928 #endif 02929 02930 if (copytexture_error_check(ctx, 1, target, level, internalFormat, 02931 postConvWidth, 1, border)) 02932 return; 02933 02934 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 02935 texObj = _mesa_select_tex_object(ctx, texUnit, target); 02936 _mesa_lock_texture(ctx, texObj); 02937 { 02938 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 02939 if (!texImage) { 02940 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage1D"); 02941 goto out; 02942 } 02943 02944 if (texImage->Data) { 02945 ctx->Driver.FreeTexImageData( ctx, texImage ); 02946 } 02947 02948 ASSERT(texImage->Data == NULL); 02949 02950 clear_teximage_fields(texImage); /* not really needed, but helpful */ 02951 _mesa_init_teximage_fields(ctx, target, texImage, postConvWidth, 1, 1, 02952 border, internalFormat); 02953 02954 02955 ASSERT(ctx->Driver.CopyTexImage1D); 02956 (*ctx->Driver.CopyTexImage1D)(ctx, target, level, internalFormat, 02957 x, y, width, border); 02958 02959 ASSERT(texImage->TexFormat); 02960 02961 update_fbo_texture(ctx, texObj, face, level); 02962 02963 /* state update */ 02964 texObj->_Complete = GL_FALSE; 02965 ctx->NewState |= _NEW_TEXTURE; 02966 } 02967 out: 02968 _mesa_unlock_texture(ctx, texObj); 02969 } 02970 02971 02972 02973 void GLAPIENTRY 02974 _mesa_CopyTexImage2D( GLenum target, GLint level, GLenum internalFormat, 02975 GLint x, GLint y, GLsizei width, GLsizei height, 02976 GLint border ) 02977 { 02978 struct gl_texture_unit *texUnit; 02979 struct gl_texture_object *texObj; 02980 struct gl_texture_image *texImage; 02981 GLsizei postConvWidth = width, postConvHeight = height; 02982 const GLuint face = _mesa_tex_target_to_face(target); 02983 GET_CURRENT_CONTEXT(ctx); 02984 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 02985 02986 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 02987 _mesa_update_state(ctx); 02988 02989 #if FEATURE_convolve 02990 if (_mesa_is_color_format(internalFormat)) { 02991 _mesa_adjust_image_for_convolution(ctx, 2, &postConvWidth, 02992 &postConvHeight); 02993 } 02994 #endif 02995 02996 if (copytexture_error_check(ctx, 2, target, level, internalFormat, 02997 postConvWidth, postConvHeight, border)) 02998 return; 02999 03000 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 03001 texObj = _mesa_select_tex_object(ctx, texUnit, target); 03002 03003 _mesa_lock_texture(ctx, texObj); 03004 { 03005 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 03006 03007 if (!texImage) { 03008 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexImage2D"); 03009 goto out; 03010 } 03011 03012 if (texImage->Data) { 03013 ctx->Driver.FreeTexImageData( ctx, texImage ); 03014 } 03015 03016 ASSERT(texImage->Data == NULL); 03017 03018 clear_teximage_fields(texImage); /* not really needed, but helpful */ 03019 _mesa_init_teximage_fields(ctx, target, texImage, 03020 postConvWidth, postConvHeight, 1, 03021 border, internalFormat); 03022 03023 ASSERT(ctx->Driver.CopyTexImage2D); 03024 (*ctx->Driver.CopyTexImage2D)(ctx, target, level, internalFormat, 03025 x, y, width, height, border); 03026 03027 ASSERT(texImage->TexFormat); 03028 03029 update_fbo_texture(ctx, texObj, face, level); 03030 03031 /* state update */ 03032 texObj->_Complete = GL_FALSE; 03033 ctx->NewState |= _NEW_TEXTURE; 03034 } 03035 out: 03036 _mesa_unlock_texture(ctx, texObj); 03037 } 03038 03039 03040 void GLAPIENTRY 03041 _mesa_CopyTexSubImage1D( GLenum target, GLint level, 03042 GLint xoffset, GLint x, GLint y, GLsizei width ) 03043 { 03044 struct gl_texture_unit *texUnit; 03045 struct gl_texture_object *texObj; 03046 struct gl_texture_image *texImage; 03047 GLsizei postConvWidth = width; 03048 GLint yoffset = 0; 03049 GLsizei height = 1; 03050 03051 GET_CURRENT_CONTEXT(ctx); 03052 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 03053 03054 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 03055 _mesa_update_state(ctx); 03056 03057 if (copytexsubimage_error_check1(ctx, 1, target, level)) 03058 return; 03059 03060 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 03061 texObj = _mesa_select_tex_object(ctx, texUnit, target); 03062 03063 _mesa_lock_texture(ctx, texObj); 03064 { 03065 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 03066 03067 #if FEATURE_convolve 03068 if (texImage && _mesa_is_color_format(texImage->InternalFormat)) { 03069 _mesa_adjust_image_for_convolution(ctx, 1, &postConvWidth, NULL); 03070 } 03071 #endif 03072 03073 if (copytexsubimage_error_check2(ctx, 1, target, level, 03074 xoffset, 0, 0, postConvWidth, 1, 03075 texImage)) 03076 goto out; 03077 03078 03079 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 03080 xoffset += texImage->Border; 03081 03082 if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, 03083 &width, &height)) { 03084 ASSERT(ctx->Driver.CopyTexSubImage1D); 03085 ctx->Driver.CopyTexSubImage1D(ctx, target, level, 03086 xoffset, x, y, width); 03087 } 03088 03089 ctx->NewState |= _NEW_TEXTURE; 03090 } 03091 out: 03092 _mesa_unlock_texture(ctx, texObj); 03093 } 03094 03095 03096 03097 void GLAPIENTRY 03098 _mesa_CopyTexSubImage2D( GLenum target, GLint level, 03099 GLint xoffset, GLint yoffset, 03100 GLint x, GLint y, GLsizei width, GLsizei height ) 03101 { 03102 struct gl_texture_unit *texUnit; 03103 struct gl_texture_object *texObj; 03104 struct gl_texture_image *texImage; 03105 GLsizei postConvWidth = width, postConvHeight = height; 03106 GET_CURRENT_CONTEXT(ctx); 03107 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 03108 03109 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 03110 _mesa_update_state(ctx); 03111 03112 if (copytexsubimage_error_check1(ctx, 2, target, level)) 03113 return; 03114 03115 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 03116 texObj = _mesa_select_tex_object(ctx, texUnit, target); 03117 03118 _mesa_lock_texture(ctx, texObj); 03119 { 03120 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 03121 03122 #if FEATURE_convolve 03123 if (texImage && _mesa_is_color_format(texImage->InternalFormat)) { 03124 _mesa_adjust_image_for_convolution(ctx, 2, 03125 &postConvWidth, &postConvHeight); 03126 } 03127 #endif 03128 03129 if (copytexsubimage_error_check2(ctx, 2, target, level, xoffset, yoffset, 0, 03130 postConvWidth, postConvHeight, texImage)) 03131 goto out; 03132 03133 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 03134 xoffset += texImage->Border; 03135 yoffset += texImage->Border; 03136 03137 if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, 03138 &width, &height)) { 03139 ASSERT(ctx->Driver.CopyTexSubImage2D); 03140 ctx->Driver.CopyTexSubImage2D(ctx, target, level, 03141 xoffset, yoffset, x, y, width, height); 03142 } 03143 03144 ctx->NewState |= _NEW_TEXTURE; 03145 } 03146 out: 03147 _mesa_unlock_texture(ctx, texObj); 03148 } 03149 03150 03151 03152 void GLAPIENTRY 03153 _mesa_CopyTexSubImage3D( GLenum target, GLint level, 03154 GLint xoffset, GLint yoffset, GLint zoffset, 03155 GLint x, GLint y, GLsizei width, GLsizei height ) 03156 { 03157 struct gl_texture_unit *texUnit; 03158 struct gl_texture_object *texObj; 03159 struct gl_texture_image *texImage; 03160 GLsizei postConvWidth = width, postConvHeight = height; 03161 GET_CURRENT_CONTEXT(ctx); 03162 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 03163 03164 if (ctx->NewState & _IMAGE_NEW_TRANSFER_STATE) 03165 _mesa_update_state(ctx); 03166 03167 if (copytexsubimage_error_check1(ctx, 3, target, level)) 03168 return; 03169 03170 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 03171 texObj = _mesa_select_tex_object(ctx, texUnit, target); 03172 03173 _mesa_lock_texture(ctx, texObj); 03174 { 03175 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 03176 03177 #if FEATURE_convolve 03178 if (texImage && _mesa_is_color_format(texImage->InternalFormat)) { 03179 _mesa_adjust_image_for_convolution(ctx, 2, 03180 &postConvWidth, &postConvHeight); 03181 } 03182 #endif 03183 03184 if (copytexsubimage_error_check2(ctx, 3, target, level, xoffset, yoffset, 03185 zoffset, postConvWidth, postConvHeight, 03186 texImage)) 03187 goto out; 03188 03189 /* If we have a border, xoffset=-1 is legal. Bias by border width */ 03190 xoffset += texImage->Border; 03191 yoffset += texImage->Border; 03192 zoffset += texImage->Border; 03193 03194 if (_mesa_clip_copytexsubimage(ctx, &xoffset, &yoffset, &x, &y, 03195 &width, &height)) { 03196 ASSERT(ctx->Driver.CopyTexSubImage3D); 03197 ctx->Driver.CopyTexSubImage3D(ctx, target, level, 03198 xoffset, yoffset, zoffset, 03199 x, y, width, height); 03200 } 03201 03202 ctx->NewState |= _NEW_TEXTURE; 03203 } 03204 out: 03205 _mesa_unlock_texture(ctx, texObj); 03206 } 03207 03208 03209 03210 03211 /**********************************************************************/ 03212 /****** Compressed Textures ******/ 03213 /**********************************************************************/ 03214 03215 03220 static GLenum 03221 compressed_texture_error_check(GLcontext *ctx, GLint dimensions, 03222 GLenum target, GLint level, 03223 GLenum internalFormat, GLsizei width, 03224 GLsizei height, GLsizei depth, GLint border, 03225 GLsizei imageSize) 03226 { 03227 GLint expectedSize, maxLevels = 0, maxTextureSize; 03228 03229 if (dimensions == 1) { 03230 /* 1D compressed textures not allowed */ 03231 return GL_INVALID_ENUM; 03232 } 03233 else if (dimensions == 2) { 03234 if (target == GL_PROXY_TEXTURE_2D) { 03235 maxLevels = ctx->Const.MaxTextureLevels; 03236 } 03237 else if (target == GL_TEXTURE_2D) { 03238 maxLevels = ctx->Const.MaxTextureLevels; 03239 } 03240 else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) { 03241 if (!ctx->Extensions.ARB_texture_cube_map) 03242 return GL_INVALID_ENUM; /*target*/ 03243 maxLevels = ctx->Const.MaxCubeTextureLevels; 03244 } 03245 else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 03246 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 03247 if (!ctx->Extensions.ARB_texture_cube_map) 03248 return GL_INVALID_ENUM; /*target*/ 03249 maxLevels = ctx->Const.MaxCubeTextureLevels; 03250 } 03251 else { 03252 return GL_INVALID_ENUM; /*target*/ 03253 } 03254 } 03255 else if (dimensions == 3) { 03256 /* 3D compressed textures not allowed */ 03257 return GL_INVALID_ENUM; 03258 } 03259 03260 maxTextureSize = 1 << (maxLevels - 1); 03261 03262 /* This will detect any invalid internalFormat value */ 03263 if (!is_compressed_format(ctx, internalFormat)) 03264 return GL_INVALID_ENUM; 03265 03266 /* This should really never fail */ 03267 if (_mesa_base_tex_format(ctx, internalFormat) < 0) 03268 return GL_INVALID_ENUM; 03269 03270 if (border != 0) 03271 return GL_INVALID_VALUE; 03272 03273 /* 03274 * XXX We should probably use the proxy texture error check function here. 03275 */ 03276 if (width < 1 || width > maxTextureSize || 03277 (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(width))) 03278 return GL_INVALID_VALUE; 03279 03280 if ((height < 1 || height > maxTextureSize || 03281 (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(height))) 03282 && dimensions > 1) 03283 return GL_INVALID_VALUE; 03284 03285 if ((depth < 1 || depth > maxTextureSize || 03286 (!ctx->Extensions.ARB_texture_non_power_of_two && !_mesa_is_pow_two(depth))) 03287 && dimensions > 2) 03288 return GL_INVALID_VALUE; 03289 03290 /* For cube map, width must equal height */ 03291 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 03292 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB && width != height) 03293 return GL_INVALID_VALUE; 03294 03295 if (level < 0 || level >= maxLevels) 03296 return GL_INVALID_VALUE; 03297 03298 expectedSize = _mesa_compressed_texture_size_glenum(ctx, width, height, 03299 depth, internalFormat); 03300 if (expectedSize != imageSize) 03301 return GL_INVALID_VALUE; 03302 03303 #if FEATURE_EXT_texture_sRGB 03304 if ((internalFormat == GL_COMPRESSED_SRGB_S3TC_DXT1_EXT || 03305 internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT || 03306 internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT || 03307 internalFormat == GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) 03308 && border != 0) { 03309 return GL_INVALID_OPERATION; 03310 } 03311 #endif 03312 03313 return GL_NO_ERROR; 03314 } 03315 03316 03324 static GLenum 03325 compressed_subtexture_error_check(GLcontext *ctx, GLint dimensions, 03326 GLenum target, GLint level, 03327 GLint xoffset, GLint yoffset, GLint zoffset, 03328 GLsizei width, GLsizei height, GLsizei depth, 03329 GLenum format, GLsizei imageSize) 03330 { 03331 GLint expectedSize, maxLevels = 0, maxTextureSize; 03332 (void) zoffset; 03333 03334 if (dimensions == 1) { 03335 /* 1D compressed textures not allowed */ 03336 return GL_INVALID_ENUM; 03337 } 03338 else if (dimensions == 2) { 03339 if (target == GL_PROXY_TEXTURE_2D) { 03340 maxLevels = ctx->Const.MaxTextureLevels; 03341 } 03342 else if (target == GL_TEXTURE_2D) { 03343 maxLevels = ctx->Const.MaxTextureLevels; 03344 } 03345 else if (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB) { 03346 if (!ctx->Extensions.ARB_texture_cube_map) 03347 return GL_INVALID_ENUM; /*target*/ 03348 maxLevels = ctx->Const.MaxCubeTextureLevels; 03349 } 03350 else if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 03351 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB) { 03352 if (!ctx->Extensions.ARB_texture_cube_map) 03353 return GL_INVALID_ENUM; /*target*/ 03354 maxLevels = ctx->Const.MaxCubeTextureLevels; 03355 } 03356 else { 03357 return GL_INVALID_ENUM; /*target*/ 03358 } 03359 } 03360 else if (dimensions == 3) { 03361 /* 3D compressed textures not allowed */ 03362 return GL_INVALID_ENUM; 03363 } 03364 03365 maxTextureSize = 1 << (maxLevels - 1); 03366 03367 /* this will catch any invalid compressed format token */ 03368 if (!is_compressed_format(ctx, format)) 03369 return GL_INVALID_ENUM; 03370 03371 if (width < 1 || width > maxTextureSize) 03372 return GL_INVALID_VALUE; 03373 03374 if ((height < 1 || height > maxTextureSize) 03375 && dimensions > 1) 03376 return GL_INVALID_VALUE; 03377 03378 if (level < 0 || level >= maxLevels) 03379 return GL_INVALID_VALUE; 03380 03381 /* XXX these tests are specific to the compressed format. 03382 * this code should be generalized in some way. 03383 */ 03384 if ((xoffset & 3) != 0 || (yoffset & 3) != 0) 03385 return GL_INVALID_VALUE; 03386 03387 if ((width & 3) != 0 && width != 2 && width != 1) 03388 return GL_INVALID_VALUE; 03389 03390 if ((height & 3) != 0 && height != 2 && height != 1) 03391 return GL_INVALID_VALUE; 03392 03393 expectedSize = _mesa_compressed_texture_size_glenum(ctx, width, height, 03394 depth, format); 03395 if (expectedSize != imageSize) 03396 return GL_INVALID_VALUE; 03397 03398 return GL_NO_ERROR; 03399 } 03400 03401 03402 03403 void GLAPIENTRY 03404 _mesa_CompressedTexImage1DARB(GLenum target, GLint level, 03405 GLenum internalFormat, GLsizei width, 03406 GLint border, GLsizei imageSize, 03407 const GLvoid *data) 03408 { 03409 GET_CURRENT_CONTEXT(ctx); 03410 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 03411 03412 if (target == GL_TEXTURE_1D) { 03413 /* non-proxy target */ 03414 struct gl_texture_unit *texUnit; 03415 struct gl_texture_object *texObj; 03416 struct gl_texture_image *texImage; 03417 GLenum error = compressed_texture_error_check(ctx, 1, target, level, 03418 internalFormat, width, 1, 1, border, imageSize); 03419 if (error) { 03420 _mesa_error(ctx, error, "glCompressedTexImage1D"); 03421 return; 03422 } 03423 03424 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 03425 texObj = _mesa_select_tex_object(ctx, texUnit, target); 03426 03427 _mesa_lock_texture(ctx, texObj); 03428 { 03429 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 03430 if (!texImage) { 03431 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage1D"); 03432 goto out; 03433 } 03434 03435 if (texImage->Data) { 03436 ctx->Driver.FreeTexImageData( ctx, texImage ); 03437 } 03438 ASSERT(texImage->Data == NULL); 03439 03440 _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1, 03441 border, internalFormat); 03442 03443 ASSERT(ctx->Driver.CompressedTexImage1D); 03444 (*ctx->Driver.CompressedTexImage1D)(ctx, target, level, 03445 internalFormat, width, border, 03446 imageSize, data, 03447 texObj, texImage); 03448 03449 /* state update */ 03450 texObj->_Complete = GL_FALSE; 03451 ctx->NewState |= _NEW_TEXTURE; 03452 } 03453 out: 03454 _mesa_unlock_texture(ctx, texObj); 03455 } 03456 else if (target == GL_PROXY_TEXTURE_1D) { 03457 /* Proxy texture: check for errors and update proxy state */ 03458 GLenum error = compressed_texture_error_check(ctx, 1, target, level, 03459 internalFormat, width, 1, 1, border, imageSize); 03460 if (!error) { 03461 ASSERT(ctx->Driver.TestProxyTexImage); 03462 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 03463 internalFormat, GL_NONE, GL_NONE, 03464 width, 1, 1, border); 03465 } 03466 if (error) { 03467 /* if error, clear all proxy texture image parameters */ 03468 struct gl_texture_image *texImage; 03469 texImage = _mesa_get_proxy_tex_image(ctx, target, level); 03470 if (texImage) 03471 clear_teximage_fields(texImage); 03472 } 03473 else { 03474 /* store the teximage parameters */ 03475 struct gl_texture_unit *texUnit; 03476 struct gl_texture_object *texObj; 03477 struct gl_texture_image *texImage; 03478 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 03479 texObj = _mesa_select_tex_object(ctx, texUnit, target); 03480 03481 _mesa_lock_texture(ctx, texObj); 03482 { 03483 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 03484 _mesa_init_teximage_fields(ctx, target, texImage, width, 1, 1, 03485 border, internalFormat); 03486 } 03487 _mesa_unlock_texture(ctx, texObj); 03488 } 03489 } 03490 else { 03491 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage1D(target)"); 03492 return; 03493 } 03494 } 03495 03496 03497 void GLAPIENTRY 03498 _mesa_CompressedTexImage2DARB(GLenum target, GLint level, 03499 GLenum internalFormat, GLsizei width, 03500 GLsizei height, GLint border, GLsizei imageSize, 03501 const GLvoid *data) 03502 { 03503 GET_CURRENT_CONTEXT(ctx); 03504 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 03505 03506 if (target == GL_TEXTURE_2D || 03507 (ctx->Extensions.ARB_texture_cube_map && 03508 target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB && 03509 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB)) { 03510 /* non-proxy target */ 03511 struct gl_texture_unit *texUnit; 03512 struct gl_texture_object *texObj; 03513 struct gl_texture_image *texImage; 03514 GLenum error = compressed_texture_error_check(ctx, 2, target, level, 03515 internalFormat, width, height, 1, border, imageSize); 03516 if (error) { 03517 _mesa_error(ctx, error, "glCompressedTexImage2D"); 03518 return; 03519 } 03520 03521 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 03522 texObj = _mesa_select_tex_object(ctx, texUnit, target); 03523 03524 _mesa_lock_texture(ctx, texObj); 03525 { 03526 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 03527 if (!texImage) { 03528 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage2D"); 03529 goto out; 03530 } 03531 03532 if (texImage->Data) { 03533 ctx->Driver.FreeTexImageData( ctx, texImage ); 03534 } 03535 ASSERT(texImage->Data == NULL); 03536 03537 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1, 03538 border, internalFormat); 03539 03540 ASSERT(ctx->Driver.CompressedTexImage2D); 03541 (*ctx->Driver.CompressedTexImage2D)(ctx, target, level, 03542 internalFormat, width, height, 03543 border, imageSize, data, 03544 texObj, texImage); 03545 03546 /* state update */ 03547 texObj->_Complete = GL_FALSE; 03548 ctx->NewState |= _NEW_TEXTURE; 03549 } 03550 out: 03551 _mesa_unlock_texture(ctx, texObj); 03552 } 03553 else if (target == GL_PROXY_TEXTURE_2D || 03554 (target == GL_PROXY_TEXTURE_CUBE_MAP_ARB && 03555 ctx->Extensions.ARB_texture_cube_map)) { 03556 /* Proxy texture: check for errors and update proxy state */ 03557 GLenum error = compressed_texture_error_check(ctx, 2, target, level, 03558 internalFormat, width, height, 1, border, imageSize); 03559 if (!error) { 03560 ASSERT(ctx->Driver.TestProxyTexImage); 03561 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 03562 internalFormat, GL_NONE, GL_NONE, 03563 width, height, 1, border); 03564 } 03565 if (error) { 03566 /* if error, clear all proxy texture image parameters */ 03567 struct gl_texture_image *texImage; 03568 texImage = _mesa_get_proxy_tex_image(ctx, target, level); 03569 if (texImage) 03570 clear_teximage_fields(texImage); 03571 } 03572 else { 03573 /* store the teximage parameters */ 03574 struct gl_texture_unit *texUnit; 03575 struct gl_texture_object *texObj; 03576 struct gl_texture_image *texImage; 03577 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 03578 texObj = _mesa_select_tex_object(ctx, texUnit, target); 03579 03580 _mesa_lock_texture(ctx, texObj); 03581 { 03582 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 03583 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 1, 03584 border, internalFormat); 03585 } 03586 _mesa_unlock_texture(ctx, texObj); 03587 } 03588 } 03589 else { 03590 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage2D(target)"); 03591 return; 03592 } 03593 } 03594 03595 03596 void GLAPIENTRY 03597 _mesa_CompressedTexImage3DARB(GLenum target, GLint level, 03598 GLenum internalFormat, GLsizei width, 03599 GLsizei height, GLsizei depth, GLint border, 03600 GLsizei imageSize, const GLvoid *data) 03601 { 03602 GET_CURRENT_CONTEXT(ctx); 03603 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 03604 03605 if (target == GL_TEXTURE_3D) { 03606 /* non-proxy target */ 03607 struct gl_texture_unit *texUnit; 03608 struct gl_texture_object *texObj; 03609 struct gl_texture_image *texImage; 03610 GLenum error = compressed_texture_error_check(ctx, 3, target, level, 03611 internalFormat, width, height, depth, border, imageSize); 03612 if (error) { 03613 _mesa_error(ctx, error, "glCompressedTexImage3D"); 03614 return; 03615 } 03616 03617 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 03618 texObj = _mesa_select_tex_object(ctx, texUnit, target); 03619 _mesa_lock_texture(ctx, texObj); 03620 { 03621 texImage = _mesa_get_tex_image(ctx, texObj, target, level); 03622 if (!texImage) { 03623 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexImage3D"); 03624 goto out; 03625 } 03626 03627 if (texImage->Data) { 03628 ctx->Driver.FreeTexImageData( ctx, texImage ); 03629 } 03630 ASSERT(texImage->Data == NULL); 03631 03632 _mesa_init_teximage_fields(ctx, target, texImage, width, height, depth, 03633 border, internalFormat); 03634 03635 ASSERT(ctx->Driver.CompressedTexImage3D); 03636 (*ctx->Driver.CompressedTexImage3D)(ctx, target, level, 03637 internalFormat, 03638 width, height, depth, 03639 border, imageSize, data, 03640 texObj, texImage); 03641 03642 /* state update */ 03643 texObj->_Complete = GL_FALSE; 03644 ctx->NewState |= _NEW_TEXTURE; 03645 } 03646 out: 03647 _mesa_unlock_texture(ctx, texObj); 03648 } 03649 else if (target == GL_PROXY_TEXTURE_3D) { 03650 /* Proxy texture: check for errors and update proxy state */ 03651 GLenum error = compressed_texture_error_check(ctx, 3, target, level, 03652 internalFormat, width, height, depth, border, imageSize); 03653 if (!error) { 03654 ASSERT(ctx->Driver.TestProxyTexImage); 03655 error = !(*ctx->Driver.TestProxyTexImage)(ctx, target, level, 03656 internalFormat, GL_NONE, GL_NONE, 03657 width, height, depth, border); 03658 } 03659 if (error) { 03660 /* if error, clear all proxy texture image parameters */ 03661 struct gl_texture_image *texImage; 03662 texImage = _mesa_get_proxy_tex_image(ctx, target, level); 03663 if (texImage) 03664 clear_teximage_fields(texImage); 03665 } 03666 else { 03667 /* store the teximage parameters */ 03668 struct gl_texture_unit *texUnit; 03669 struct gl_texture_object *texObj; 03670 struct gl_texture_image *texImage; 03671 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 03672 texObj = _mesa_select_tex_object(ctx, texUnit, target); 03673 _mesa_lock_texture(ctx, texObj); 03674 { 03675 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 03676 _mesa_init_teximage_fields(ctx, target, texImage, width, height, 03677 depth, border, internalFormat); 03678 } 03679 _mesa_unlock_texture(ctx, texObj); 03680 } 03681 } 03682 else { 03683 _mesa_error(ctx, GL_INVALID_ENUM, "glCompressedTexImage3D(target)"); 03684 return; 03685 } 03686 } 03687 03688 03689 void GLAPIENTRY 03690 _mesa_CompressedTexSubImage1DARB(GLenum target, GLint level, GLint xoffset, 03691 GLsizei width, GLenum format, 03692 GLsizei imageSize, const GLvoid *data) 03693 { 03694 struct gl_texture_unit *texUnit; 03695 struct gl_texture_object *texObj; 03696 struct gl_texture_image *texImage; 03697 GLenum error; 03698 GET_CURRENT_CONTEXT(ctx); 03699 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 03700 03701 error = compressed_subtexture_error_check(ctx, 1, target, level, 03702 xoffset, 0, 0, /* pos */ 03703 width, 1, 1, /* size */ 03704 format, imageSize); 03705 if (error) { 03706 _mesa_error(ctx, error, "glCompressedTexSubImage1D"); 03707 return; 03708 } 03709 03710 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 03711 texObj = _mesa_select_tex_object(ctx, texUnit, target); 03712 _mesa_lock_texture(ctx, texObj); 03713 { 03714 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 03715 assert(texImage); 03716 03717 if ((GLint) format != texImage->InternalFormat) { 03718 _mesa_error(ctx, GL_INVALID_OPERATION, 03719 "glCompressedTexSubImage1D(format)"); 03720 goto out; 03721 } 03722 03723 if ((width == 1 || width == 2) && (GLuint) width != texImage->Width) { 03724 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage1D(width)"); 03725 goto out; 03726 } 03727 03728 if (width == 0) 03729 goto out; /* no-op, not an error */ 03730 03731 if (ctx->Driver.CompressedTexSubImage1D) { 03732 (*ctx->Driver.CompressedTexSubImage1D)(ctx, target, level, 03733 xoffset, width, 03734 format, imageSize, data, 03735 texObj, texImage); 03736 } 03737 ctx->NewState |= _NEW_TEXTURE; 03738 } 03739 out: 03740 _mesa_unlock_texture(ctx, texObj); 03741 } 03742 03743 03744 void GLAPIENTRY 03745 _mesa_CompressedTexSubImage2DARB(GLenum target, GLint level, GLint xoffset, 03746 GLint yoffset, GLsizei width, GLsizei height, 03747 GLenum format, GLsizei imageSize, 03748 const GLvoid *data) 03749 { 03750 struct gl_texture_unit *texUnit; 03751 struct gl_texture_object *texObj; 03752 struct gl_texture_image *texImage; 03753 GLenum error; 03754 GET_CURRENT_CONTEXT(ctx); 03755 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 03756 03757 error = compressed_subtexture_error_check(ctx, 2, target, level, 03758 xoffset, yoffset, 0, /* pos */ 03759 width, height, 1, /* size */ 03760 format, imageSize); 03761 if (error) { 03762 /* XXX proxy target? */ 03763 _mesa_error(ctx, error, "glCompressedTexSubImage2D"); 03764 return; 03765 } 03766 03767 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 03768 texObj = _mesa_select_tex_object(ctx, texUnit, target); 03769 _mesa_lock_texture(ctx, texObj); 03770 { 03771 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 03772 assert(texImage); 03773 03774 if ((GLint) format != texImage->InternalFormat) { 03775 _mesa_error(ctx, GL_INVALID_OPERATION, 03776 "glCompressedTexSubImage2D(format)"); 03777 goto out; 03778 } 03779 03780 if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) || 03781 ((height == 1 || height == 2) && (GLuint) height != texImage->Height)) { 03782 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage2D(size)"); 03783 goto out; 03784 } 03785 03786 if (width == 0 || height == 0) 03787 goto out; /* no-op, not an error */ 03788 03789 if (ctx->Driver.CompressedTexSubImage2D) { 03790 (*ctx->Driver.CompressedTexSubImage2D)(ctx, target, level, 03791 xoffset, yoffset, width, height, 03792 format, imageSize, data, 03793 texObj, texImage); 03794 } 03795 ctx->NewState |= _NEW_TEXTURE; 03796 } 03797 out: 03798 _mesa_unlock_texture(ctx, texObj); 03799 } 03800 03801 03802 void GLAPIENTRY 03803 _mesa_CompressedTexSubImage3DARB(GLenum target, GLint level, GLint xoffset, 03804 GLint yoffset, GLint zoffset, GLsizei width, 03805 GLsizei height, GLsizei depth, GLenum format, 03806 GLsizei imageSize, const GLvoid *data) 03807 { 03808 struct gl_texture_unit *texUnit; 03809 struct gl_texture_object *texObj; 03810 struct gl_texture_image *texImage; 03811 GLenum error; 03812 GET_CURRENT_CONTEXT(ctx); 03813 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 03814 03815 error = compressed_subtexture_error_check(ctx, 3, target, level, 03816 xoffset, yoffset, zoffset,/*pos*/ 03817 width, height, depth, /*size*/ 03818 format, imageSize); 03819 if (error) { 03820 _mesa_error(ctx, error, "glCompressedTexSubImage3D"); 03821 return; 03822 } 03823 03824 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 03825 texObj = _mesa_select_tex_object(ctx, texUnit, target); 03826 _mesa_lock_texture(ctx, texObj); 03827 { 03828 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 03829 assert(texImage); 03830 03831 if ((GLint) format != texImage->InternalFormat) { 03832 _mesa_error(ctx, GL_INVALID_OPERATION, 03833 "glCompressedTexSubImage3D(format)"); 03834 goto out; 03835 } 03836 03837 if (((width == 1 || width == 2) && (GLuint) width != texImage->Width) || 03838 ((height == 1 || height == 2) && (GLuint) height != texImage->Height) || 03839 ((depth == 1 || depth == 2) && (GLuint) depth != texImage->Depth)) { 03840 _mesa_error(ctx, GL_INVALID_VALUE, "glCompressedTexSubImage3D(size)"); 03841 goto out; 03842 } 03843 03844 if (width == 0 || height == 0 || depth == 0) 03845 goto out; /* no-op, not an error */ 03846 03847 if (ctx->Driver.CompressedTexSubImage3D) { 03848 (*ctx->Driver.CompressedTexSubImage3D)(ctx, target, level, 03849 xoffset, yoffset, zoffset, 03850 width, height, depth, 03851 format, imageSize, data, 03852 texObj, texImage); 03853 } 03854 ctx->NewState |= _NEW_TEXTURE; 03855 } 03856 out: 03857 _mesa_unlock_texture(ctx, texObj); 03858 } 03859 03860 03861 void GLAPIENTRY 03862 _mesa_GetCompressedTexImageARB(GLenum target, GLint level, GLvoid *img) 03863 { 03864 const struct gl_texture_unit *texUnit; 03865 struct gl_texture_object *texObj; 03866 struct gl_texture_image *texImage; 03867 GLint maxLevels; 03868 GET_CURRENT_CONTEXT(ctx); 03869 ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); 03870 03871 texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit]; 03872 texObj = _mesa_select_tex_object(ctx, texUnit, target); 03873 if (!texObj) { 03874 _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB"); 03875 return; 03876 } 03877 03878 maxLevels = _mesa_max_texture_levels(ctx, target); 03879 ASSERT(maxLevels > 0); /* 0 indicates bad target, caught above */ 03880 03881 if (level < 0 || level >= maxLevels) { 03882 _mesa_error(ctx, GL_INVALID_VALUE, "glGetCompressedTexImageARB(level)"); 03883 return; 03884 } 03885 03886 if (_mesa_is_proxy_texture(target)) { 03887 _mesa_error(ctx, GL_INVALID_ENUM, "glGetCompressedTexImageARB(target)"); 03888 return; 03889 } 03890 03891 _mesa_lock_texture(ctx, texObj); 03892 { 03893 texImage = _mesa_select_tex_image(ctx, texObj, target, level); 03894 if (texImage) { 03895 if (texImage->IsCompressed) { 03896 /* this typically calls _mesa_get_compressed_teximage() */ 03897 ctx->Driver.GetCompressedTexImage(ctx, target, level, img, 03898 texObj, texImage); 03899 } 03900 else { 03901 _mesa_error(ctx, GL_INVALID_OPERATION, 03902 "glGetCompressedTexImageARB"); 03903 } 03904 } 03905 else { 03906 /* probably invalid mipmap level */ 03907 _mesa_error(ctx, GL_INVALID_VALUE, 03908 "glGetCompressedTexImageARB(level)"); 03909 } 03910 } 03911 _mesa_unlock_texture(ctx, texObj); 03912 } Generated on Sat May 26 2012 04:19:14 for ReactOS by
1.7.6.1
|