meta.c revision d638da23d2ec2e9c52655b1ea138249e7f8bcccb
1/* 2 * Mesa 3-D graphics library 3 * Version: 7.6 4 * 5 * Copyright (C) 2009 VMware, Inc. All Rights Reserved. 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a 8 * copy of this software and associated documentation files (the "Software"), 9 * to deal in the Software without restriction, including without limitation 10 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 11 * and/or sell copies of the Software, and to permit persons to whom the 12 * Software is furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included 15 * in all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25/** 26 * Meta operations. Some GL operations can be expressed in terms of 27 * other GL operations. For example, glBlitFramebuffer() can be done 28 * with texture mapping and glClear() can be done with polygon rendering. 29 * 30 * \author Brian Paul 31 */ 32 33 34#include "main/glheader.h" 35#include "main/mtypes.h" 36#include "main/imports.h" 37#include "main/arbprogram.h" 38#include "main/arrayobj.h" 39#include "main/blend.h" 40#include "main/bufferobj.h" 41#include "main/buffers.h" 42#include "main/colortab.h" 43#include "main/condrender.h" 44#include "main/depth.h" 45#include "main/enable.h" 46#include "main/fbobject.h" 47#include "main/feedback.h" 48#include "main/formats.h" 49#include "main/glformats.h" 50#include "main/image.h" 51#include "main/macros.h" 52#include "main/matrix.h" 53#include "main/mipmap.h" 54#include "main/pixel.h" 55#include "main/pbo.h" 56#include "main/polygon.h" 57#include "main/readpix.h" 58#include "main/scissor.h" 59#include "main/shaderapi.h" 60#include "main/shaderobj.h" 61#include "main/state.h" 62#include "main/stencil.h" 63#include "main/texobj.h" 64#include "main/texenv.h" 65#include "main/texgetimage.h" 66#include "main/teximage.h" 67#include "main/texparam.h" 68#include "main/texstate.h" 69#include "main/transformfeedback.h" 70#include "main/uniforms.h" 71#include "main/varray.h" 72#include "main/viewport.h" 73#include "main/samplerobj.h" 74#include "program/program.h" 75#include "swrast/swrast.h" 76#include "drivers/common/meta.h" 77#include "main/enums.h" 78#include "main/glformats.h" 79 80 81/** Return offset in bytes of the field within a vertex struct */ 82#define OFFSET(FIELD) ((void *) offsetof(struct vertex, FIELD)) 83 84/** 85 * State which we may save/restore across meta ops. 86 * XXX this may be incomplete... 87 */ 88struct save_state 89{ 90 GLbitfield SavedState; /**< bitmask of MESA_META_* flags */ 91 92 /** MESA_META_ALPHA_TEST */ 93 GLboolean AlphaEnabled; 94 GLenum AlphaFunc; 95 GLclampf AlphaRef; 96 97 /** MESA_META_BLEND */ 98 GLbitfield BlendEnabled; 99 GLboolean ColorLogicOpEnabled; 100 101 /** MESA_META_COLOR_MASK */ 102 GLubyte ColorMask[MAX_DRAW_BUFFERS][4]; 103 104 /** MESA_META_DEPTH_TEST */ 105 struct gl_depthbuffer_attrib Depth; 106 107 /** MESA_META_FOG */ 108 GLboolean Fog; 109 110 /** MESA_META_PIXEL_STORE */ 111 struct gl_pixelstore_attrib Pack, Unpack; 112 113 /** MESA_META_PIXEL_TRANSFER */ 114 GLfloat RedBias, RedScale; 115 GLfloat GreenBias, GreenScale; 116 GLfloat BlueBias, BlueScale; 117 GLfloat AlphaBias, AlphaScale; 118 GLfloat DepthBias, DepthScale; 119 GLboolean MapColorFlag; 120 121 /** MESA_META_RASTERIZATION */ 122 GLenum FrontPolygonMode, BackPolygonMode; 123 GLboolean PolygonOffset; 124 GLboolean PolygonSmooth; 125 GLboolean PolygonStipple; 126 GLboolean PolygonCull; 127 128 /** MESA_META_SCISSOR */ 129 struct gl_scissor_attrib Scissor; 130 131 /** MESA_META_SHADER */ 132 GLboolean VertexProgramEnabled; 133 struct gl_vertex_program *VertexProgram; 134 GLboolean FragmentProgramEnabled; 135 struct gl_fragment_program *FragmentProgram; 136 struct gl_shader_program *VertexShader; 137 struct gl_shader_program *GeometryShader; 138 struct gl_shader_program *FragmentShader; 139 struct gl_shader_program *ActiveShader; 140 141 /** MESA_META_STENCIL_TEST */ 142 struct gl_stencil_attrib Stencil; 143 144 /** MESA_META_TRANSFORM */ 145 GLenum MatrixMode; 146 GLfloat ModelviewMatrix[16]; 147 GLfloat ProjectionMatrix[16]; 148 GLfloat TextureMatrix[16]; 149 150 /** MESA_META_CLIP */ 151 GLbitfield ClipPlanesEnabled; 152 153 /** MESA_META_TEXTURE */ 154 GLuint ActiveUnit; 155 GLuint ClientActiveUnit; 156 /** for unit[0] only */ 157 struct gl_texture_object *CurrentTexture[NUM_TEXTURE_TARGETS]; 158 /** mask of TEXTURE_2D_BIT, etc */ 159 GLbitfield TexEnabled[MAX_TEXTURE_UNITS]; 160 GLbitfield TexGenEnabled[MAX_TEXTURE_UNITS]; 161 GLuint EnvMode; /* unit[0] only */ 162 163 /** MESA_META_VERTEX */ 164 struct gl_array_object *ArrayObj; 165 struct gl_buffer_object *ArrayBufferObj; 166 167 /** MESA_META_VIEWPORT */ 168 GLint ViewportX, ViewportY, ViewportW, ViewportH; 169 GLclampd DepthNear, DepthFar; 170 171 /** MESA_META_CLAMP_FRAGMENT_COLOR */ 172 GLenum ClampFragmentColor; 173 174 /** MESA_META_CLAMP_VERTEX_COLOR */ 175 GLenum ClampVertexColor; 176 177 /** MESA_META_CONDITIONAL_RENDER */ 178 struct gl_query_object *CondRenderQuery; 179 GLenum CondRenderMode; 180 181#if FEATURE_feedback 182 /** MESA_META_SELECT_FEEDBACK */ 183 GLenum RenderMode; 184 struct gl_selection Select; 185 struct gl_feedback Feedback; 186#endif 187 188 /** MESA_META_MULTISAMPLE */ 189 GLboolean MultisampleEnabled; 190 191 /** Miscellaneous (always disabled) */ 192 GLboolean Lighting; 193 GLboolean RasterDiscard; 194#if FEATURE_EXT_transform_feedback 195 GLboolean TransformFeedbackNeedsResume; 196#endif 197}; 198 199/** 200 * Temporary texture used for glBlitFramebuffer, glDrawPixels, etc. 201 * This is currently shared by all the meta ops. But we could create a 202 * separate one for each of glDrawPixel, glBlitFramebuffer, glCopyPixels, etc. 203 */ 204struct temp_texture 205{ 206 GLuint TexObj; 207 GLenum Target; /**< GL_TEXTURE_2D or GL_TEXTURE_RECTANGLE */ 208 GLsizei MinSize; /**< Min texture size to allocate */ 209 GLsizei MaxSize; /**< Max possible texture size */ 210 GLboolean NPOT; /**< Non-power of two size OK? */ 211 GLsizei Width, Height; /**< Current texture size */ 212 GLenum IntFormat; 213 GLfloat Sright, Ttop; /**< right, top texcoords */ 214}; 215 216 217/** 218 * State for glBlitFramebufer() 219 */ 220struct blit_state 221{ 222 GLuint ArrayObj; 223 GLuint VBO; 224 GLuint DepthFP; 225}; 226 227 228/** 229 * State for glClear() 230 */ 231struct clear_state 232{ 233 GLuint ArrayObj; 234 GLuint VBO; 235 GLuint ShaderProg; 236 GLint ColorLocation; 237 238 GLuint IntegerShaderProg; 239 GLint IntegerColorLocation; 240}; 241 242 243/** 244 * State for glCopyPixels() 245 */ 246struct copypix_state 247{ 248 GLuint ArrayObj; 249 GLuint VBO; 250}; 251 252 253/** 254 * State for glDrawPixels() 255 */ 256struct drawpix_state 257{ 258 GLuint ArrayObj; 259 260 GLuint StencilFP; /**< Fragment program for drawing stencil images */ 261 GLuint DepthFP; /**< Fragment program for drawing depth images */ 262}; 263 264 265/** 266 * State for glBitmap() 267 */ 268struct bitmap_state 269{ 270 GLuint ArrayObj; 271 GLuint VBO; 272 struct temp_texture Tex; /**< separate texture from other meta ops */ 273}; 274 275 276/** 277 * State for _mesa_meta_generate_mipmap() 278 */ 279struct gen_mipmap_state 280{ 281 GLuint ArrayObj; 282 GLuint VBO; 283 GLuint FBO; 284 GLuint Sampler; 285 GLuint ShaderProg; 286 GLuint IntegerShaderProg; 287}; 288 289 290/** 291 * State for texture decompression 292 */ 293struct decompress_state 294{ 295 GLuint ArrayObj; 296 GLuint VBO, FBO, RBO, Sampler; 297 GLint Width, Height; 298}; 299 300/** 301 * State for glDrawTex() 302 */ 303struct drawtex_state 304{ 305 GLuint ArrayObj; 306 GLuint VBO; 307}; 308 309#define MAX_META_OPS_DEPTH 8 310/** 311 * All per-context meta state. 312 */ 313struct gl_meta_state 314{ 315 /** Stack of state saved during meta-ops */ 316 struct save_state Save[MAX_META_OPS_DEPTH]; 317 /** Save stack depth */ 318 GLuint SaveStackDepth; 319 320 struct temp_texture TempTex; 321 322 struct blit_state Blit; /**< For _mesa_meta_BlitFramebuffer() */ 323 struct clear_state Clear; /**< For _mesa_meta_Clear() */ 324 struct copypix_state CopyPix; /**< For _mesa_meta_CopyPixels() */ 325 struct drawpix_state DrawPix; /**< For _mesa_meta_DrawPixels() */ 326 struct bitmap_state Bitmap; /**< For _mesa_meta_Bitmap() */ 327 struct gen_mipmap_state Mipmap; /**< For _mesa_meta_GenerateMipmap() */ 328 struct decompress_state Decompress; /**< For texture decompression */ 329 struct drawtex_state DrawTex; /**< For _mesa_meta_DrawTex() */ 330}; 331 332static void meta_glsl_blit_cleanup(struct gl_context *ctx, struct blit_state *blit); 333static void cleanup_temp_texture(struct gl_context *ctx, struct temp_texture *tex); 334static void meta_glsl_clear_cleanup(struct gl_context *ctx, struct clear_state *clear); 335static void meta_glsl_generate_mipmap_cleanup(struct gl_context *ctx, 336 struct gen_mipmap_state *mipmap); 337 338static GLuint 339compile_shader_with_debug(struct gl_context *ctx, GLenum target, const GLcharARB *source) 340{ 341 GLuint shader; 342 GLint ok, size; 343 GLchar *info; 344 345 shader = _mesa_CreateShaderObjectARB(target); 346 _mesa_ShaderSourceARB(shader, 1, &source, NULL); 347 _mesa_CompileShaderARB(shader); 348 349 _mesa_GetShaderiv(shader, GL_COMPILE_STATUS, &ok); 350 if (ok) 351 return shader; 352 353 _mesa_GetShaderiv(shader, GL_INFO_LOG_LENGTH, &size); 354 if (size == 0) { 355 _mesa_DeleteObjectARB(shader); 356 return 0; 357 } 358 359 info = malloc(size); 360 if (!info) { 361 _mesa_DeleteObjectARB(shader); 362 return 0; 363 } 364 365 _mesa_GetProgramInfoLog(shader, size, NULL, info); 366 _mesa_problem(ctx, 367 "meta program compile failed:\n%s\n" 368 "source:\n%s\n", 369 info, source); 370 371 free(info); 372 _mesa_DeleteObjectARB(shader); 373 374 return 0; 375} 376 377static GLuint 378link_program_with_debug(struct gl_context *ctx, GLuint program) 379{ 380 GLint ok, size; 381 GLchar *info; 382 383 _mesa_LinkProgramARB(program); 384 385 _mesa_GetProgramiv(program, GL_LINK_STATUS, &ok); 386 if (ok) 387 return program; 388 389 _mesa_GetProgramiv(program, GL_INFO_LOG_LENGTH, &size); 390 if (size == 0) 391 return 0; 392 393 info = malloc(size); 394 if (!info) 395 return 0; 396 397 _mesa_GetProgramInfoLog(program, size, NULL, info); 398 _mesa_problem(ctx, "meta program link failed:\n%s", info); 399 400 free(info); 401 402 return 0; 403} 404 405/** 406 * Initialize meta-ops for a context. 407 * To be called once during context creation. 408 */ 409void 410_mesa_meta_init(struct gl_context *ctx) 411{ 412 ASSERT(!ctx->Meta); 413 414 ctx->Meta = CALLOC_STRUCT(gl_meta_state); 415} 416 417 418/** 419 * Free context meta-op state. 420 * To be called once during context destruction. 421 */ 422void 423_mesa_meta_free(struct gl_context *ctx) 424{ 425 GET_CURRENT_CONTEXT(old_context); 426 _mesa_make_current(ctx, NULL, NULL); 427 meta_glsl_blit_cleanup(ctx, &ctx->Meta->Blit); 428 meta_glsl_clear_cleanup(ctx, &ctx->Meta->Clear); 429 meta_glsl_generate_mipmap_cleanup(ctx, &ctx->Meta->Mipmap); 430 cleanup_temp_texture(ctx, &ctx->Meta->TempTex); 431 if (old_context) 432 _mesa_make_current(old_context, old_context->WinSysDrawBuffer, old_context->WinSysReadBuffer); 433 else 434 _mesa_make_current(NULL, NULL, NULL); 435 free(ctx->Meta); 436 ctx->Meta = NULL; 437} 438 439 440/** 441 * Enter meta state. This is like a light-weight version of glPushAttrib 442 * but it also resets most GL state back to default values. 443 * 444 * \param state bitmask of MESA_META_* flags indicating which attribute groups 445 * to save and reset to their defaults 446 */ 447void 448_mesa_meta_begin(struct gl_context *ctx, GLbitfield state) 449{ 450 struct save_state *save; 451 452 /* hope MAX_META_OPS_DEPTH is large enough */ 453 assert(ctx->Meta->SaveStackDepth < MAX_META_OPS_DEPTH); 454 455 save = &ctx->Meta->Save[ctx->Meta->SaveStackDepth++]; 456 memset(save, 0, sizeof(*save)); 457 save->SavedState = state; 458 459#if FEATURE_EXT_transform_feedback 460 /* Pausing transform feedback needs to be done early, or else we won't be 461 * able to change other state. 462 */ 463 save->TransformFeedbackNeedsResume = 464 ctx->TransformFeedback.CurrentObject->Active && 465 !ctx->TransformFeedback.CurrentObject->Paused; 466 if (save->TransformFeedbackNeedsResume) 467 _mesa_PauseTransformFeedback(); 468#endif 469 470 if (state & MESA_META_ALPHA_TEST) { 471 save->AlphaEnabled = ctx->Color.AlphaEnabled; 472 save->AlphaFunc = ctx->Color.AlphaFunc; 473 save->AlphaRef = ctx->Color.AlphaRef; 474 if (ctx->Color.AlphaEnabled) 475 _mesa_set_enable(ctx, GL_ALPHA_TEST, GL_FALSE); 476 } 477 478 if (state & MESA_META_BLEND) { 479 save->BlendEnabled = ctx->Color.BlendEnabled; 480 if (ctx->Color.BlendEnabled) { 481 if (ctx->Extensions.EXT_draw_buffers2) { 482 GLuint i; 483 for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) { 484 _mesa_set_enablei(ctx, GL_BLEND, i, GL_FALSE); 485 } 486 } 487 else { 488 _mesa_set_enable(ctx, GL_BLEND, GL_FALSE); 489 } 490 } 491 save->ColorLogicOpEnabled = ctx->Color.ColorLogicOpEnabled; 492 if (ctx->Color.ColorLogicOpEnabled) 493 _mesa_set_enable(ctx, GL_COLOR_LOGIC_OP, GL_FALSE); 494 } 495 496 if (state & MESA_META_COLOR_MASK) { 497 memcpy(save->ColorMask, ctx->Color.ColorMask, 498 sizeof(ctx->Color.ColorMask)); 499 if (!ctx->Color.ColorMask[0][0] || 500 !ctx->Color.ColorMask[0][1] || 501 !ctx->Color.ColorMask[0][2] || 502 !ctx->Color.ColorMask[0][3]) 503 _mesa_ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); 504 } 505 506 if (state & MESA_META_DEPTH_TEST) { 507 save->Depth = ctx->Depth; /* struct copy */ 508 if (ctx->Depth.Test) 509 _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_FALSE); 510 } 511 512 if (state & MESA_META_FOG) { 513 save->Fog = ctx->Fog.Enabled; 514 if (ctx->Fog.Enabled) 515 _mesa_set_enable(ctx, GL_FOG, GL_FALSE); 516 } 517 518 if (state & MESA_META_PIXEL_STORE) { 519 save->Pack = ctx->Pack; 520 save->Unpack = ctx->Unpack; 521 ctx->Pack = ctx->DefaultPacking; 522 ctx->Unpack = ctx->DefaultPacking; 523 } 524 525 if (state & MESA_META_PIXEL_TRANSFER) { 526 save->RedScale = ctx->Pixel.RedScale; 527 save->RedBias = ctx->Pixel.RedBias; 528 save->GreenScale = ctx->Pixel.GreenScale; 529 save->GreenBias = ctx->Pixel.GreenBias; 530 save->BlueScale = ctx->Pixel.BlueScale; 531 save->BlueBias = ctx->Pixel.BlueBias; 532 save->AlphaScale = ctx->Pixel.AlphaScale; 533 save->AlphaBias = ctx->Pixel.AlphaBias; 534 save->MapColorFlag = ctx->Pixel.MapColorFlag; 535 ctx->Pixel.RedScale = 1.0F; 536 ctx->Pixel.RedBias = 0.0F; 537 ctx->Pixel.GreenScale = 1.0F; 538 ctx->Pixel.GreenBias = 0.0F; 539 ctx->Pixel.BlueScale = 1.0F; 540 ctx->Pixel.BlueBias = 0.0F; 541 ctx->Pixel.AlphaScale = 1.0F; 542 ctx->Pixel.AlphaBias = 0.0F; 543 ctx->Pixel.MapColorFlag = GL_FALSE; 544 /* XXX more state */ 545 ctx->NewState |=_NEW_PIXEL; 546 } 547 548 if (state & MESA_META_RASTERIZATION) { 549 save->FrontPolygonMode = ctx->Polygon.FrontMode; 550 save->BackPolygonMode = ctx->Polygon.BackMode; 551 save->PolygonOffset = ctx->Polygon.OffsetFill; 552 save->PolygonSmooth = ctx->Polygon.SmoothFlag; 553 save->PolygonStipple = ctx->Polygon.StippleFlag; 554 save->PolygonCull = ctx->Polygon.CullFlag; 555 _mesa_PolygonMode(GL_FRONT_AND_BACK, GL_FILL); 556 _mesa_set_enable(ctx, GL_POLYGON_OFFSET_FILL, GL_FALSE); 557 if (ctx->API == API_OPENGL) { 558 _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, GL_FALSE); 559 _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, GL_FALSE); 560 } 561 _mesa_set_enable(ctx, GL_CULL_FACE, GL_FALSE); 562 } 563 564 if (state & MESA_META_SCISSOR) { 565 save->Scissor = ctx->Scissor; /* struct copy */ 566 _mesa_set_enable(ctx, GL_SCISSOR_TEST, GL_FALSE); 567 } 568 569 if (state & MESA_META_SHADER) { 570 if (ctx->API == API_OPENGL && ctx->Extensions.ARB_vertex_program) { 571 save->VertexProgramEnabled = ctx->VertexProgram.Enabled; 572 _mesa_reference_vertprog(ctx, &save->VertexProgram, 573 ctx->VertexProgram.Current); 574 _mesa_set_enable(ctx, GL_VERTEX_PROGRAM_ARB, GL_FALSE); 575 } 576 577 if (ctx->API == API_OPENGL && ctx->Extensions.ARB_fragment_program) { 578 save->FragmentProgramEnabled = ctx->FragmentProgram.Enabled; 579 _mesa_reference_fragprog(ctx, &save->FragmentProgram, 580 ctx->FragmentProgram.Current); 581 _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_FALSE); 582 } 583 584 if (ctx->Extensions.ARB_shader_objects) { 585 _mesa_reference_shader_program(ctx, &save->VertexShader, 586 ctx->Shader.CurrentVertexProgram); 587 _mesa_reference_shader_program(ctx, &save->GeometryShader, 588 ctx->Shader.CurrentGeometryProgram); 589 _mesa_reference_shader_program(ctx, &save->FragmentShader, 590 ctx->Shader.CurrentFragmentProgram); 591 _mesa_reference_shader_program(ctx, &save->ActiveShader, 592 ctx->Shader.ActiveProgram); 593 594 _mesa_UseProgramObjectARB(0); 595 } 596 } 597 598 if (state & MESA_META_STENCIL_TEST) { 599 save->Stencil = ctx->Stencil; /* struct copy */ 600 if (ctx->Stencil.Enabled) 601 _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_FALSE); 602 /* NOTE: other stencil state not reset */ 603 } 604 605 if (state & MESA_META_TEXTURE) { 606 GLuint u, tgt; 607 608 save->ActiveUnit = ctx->Texture.CurrentUnit; 609 save->ClientActiveUnit = ctx->Array.ActiveTexture; 610 save->EnvMode = ctx->Texture.Unit[0].EnvMode; 611 612 /* Disable all texture units */ 613 if (ctx->API == API_OPENGL || ctx->API == API_OPENGLES) { 614 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { 615 save->TexEnabled[u] = ctx->Texture.Unit[u].Enabled; 616 save->TexGenEnabled[u] = ctx->Texture.Unit[u].TexGenEnabled; 617 if (ctx->Texture.Unit[u].Enabled || 618 ctx->Texture.Unit[u].TexGenEnabled) { 619 _mesa_ActiveTextureARB(GL_TEXTURE0 + u); 620 _mesa_set_enable(ctx, GL_TEXTURE_1D, GL_FALSE); 621 _mesa_set_enable(ctx, GL_TEXTURE_2D, GL_FALSE); 622 _mesa_set_enable(ctx, GL_TEXTURE_3D, GL_FALSE); 623 if (ctx->Extensions.ARB_texture_cube_map) 624 _mesa_set_enable(ctx, GL_TEXTURE_CUBE_MAP, GL_FALSE); 625 if (ctx->Extensions.NV_texture_rectangle) 626 _mesa_set_enable(ctx, GL_TEXTURE_RECTANGLE, GL_FALSE); 627 if (ctx->Extensions.OES_EGL_image_external) 628 _mesa_set_enable(ctx, GL_TEXTURE_EXTERNAL_OES, GL_FALSE); 629 _mesa_set_enable(ctx, GL_TEXTURE_GEN_S, GL_FALSE); 630 _mesa_set_enable(ctx, GL_TEXTURE_GEN_T, GL_FALSE); 631 _mesa_set_enable(ctx, GL_TEXTURE_GEN_R, GL_FALSE); 632 _mesa_set_enable(ctx, GL_TEXTURE_GEN_Q, GL_FALSE); 633 } 634 } 635 } 636 637 /* save current texture objects for unit[0] only */ 638 for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) { 639 _mesa_reference_texobj(&save->CurrentTexture[tgt], 640 ctx->Texture.Unit[0].CurrentTex[tgt]); 641 } 642 643 /* set defaults for unit[0] */ 644 _mesa_ActiveTextureARB(GL_TEXTURE0); 645 _mesa_ClientActiveTextureARB(GL_TEXTURE0); 646 if (ctx->API == API_OPENGL || ctx->API == API_OPENGLES) { 647 _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 648 } 649 } 650 651 if (state & MESA_META_TRANSFORM) { 652 GLuint activeTexture = ctx->Texture.CurrentUnit; 653 memcpy(save->ModelviewMatrix, ctx->ModelviewMatrixStack.Top->m, 654 16 * sizeof(GLfloat)); 655 memcpy(save->ProjectionMatrix, ctx->ProjectionMatrixStack.Top->m, 656 16 * sizeof(GLfloat)); 657 memcpy(save->TextureMatrix, ctx->TextureMatrixStack[0].Top->m, 658 16 * sizeof(GLfloat)); 659 save->MatrixMode = ctx->Transform.MatrixMode; 660 /* set 1:1 vertex:pixel coordinate transform */ 661 _mesa_ActiveTextureARB(GL_TEXTURE0); 662 _mesa_MatrixMode(GL_TEXTURE); 663 _mesa_LoadIdentity(); 664 _mesa_ActiveTextureARB(GL_TEXTURE0 + activeTexture); 665 _mesa_MatrixMode(GL_MODELVIEW); 666 _mesa_LoadIdentity(); 667 _mesa_MatrixMode(GL_PROJECTION); 668 _mesa_LoadIdentity(); 669 _mesa_Ortho(0.0, ctx->DrawBuffer->Width, 670 0.0, ctx->DrawBuffer->Height, 671 -1.0, 1.0); 672 } 673 674 if (state & MESA_META_CLIP) { 675 save->ClipPlanesEnabled = ctx->Transform.ClipPlanesEnabled; 676 if (ctx->Transform.ClipPlanesEnabled) { 677 GLuint i; 678 for (i = 0; i < ctx->Const.MaxClipPlanes; i++) { 679 _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_FALSE); 680 } 681 } 682 } 683 684 if (state & MESA_META_VERTEX) { 685 /* save vertex array object state */ 686 _mesa_reference_array_object(ctx, &save->ArrayObj, 687 ctx->Array.ArrayObj); 688 _mesa_reference_buffer_object(ctx, &save->ArrayBufferObj, 689 ctx->Array.ArrayBufferObj); 690 /* set some default state? */ 691 } 692 693 if (state & MESA_META_VIEWPORT) { 694 /* save viewport state */ 695 save->ViewportX = ctx->Viewport.X; 696 save->ViewportY = ctx->Viewport.Y; 697 save->ViewportW = ctx->Viewport.Width; 698 save->ViewportH = ctx->Viewport.Height; 699 /* set viewport to match window size */ 700 if (ctx->Viewport.X != 0 || 701 ctx->Viewport.Y != 0 || 702 ctx->Viewport.Width != ctx->DrawBuffer->Width || 703 ctx->Viewport.Height != ctx->DrawBuffer->Height) { 704 _mesa_set_viewport(ctx, 0, 0, 705 ctx->DrawBuffer->Width, ctx->DrawBuffer->Height); 706 } 707 /* save depth range state */ 708 save->DepthNear = ctx->Viewport.Near; 709 save->DepthFar = ctx->Viewport.Far; 710 /* set depth range to default */ 711 _mesa_DepthRange(0.0, 1.0); 712 } 713 714 if (state & MESA_META_CLAMP_FRAGMENT_COLOR) { 715 save->ClampFragmentColor = ctx->Color.ClampFragmentColor; 716 717 /* Generally in here we want to do clamping according to whether 718 * it's for the pixel path (ClampFragmentColor is GL_TRUE), 719 * regardless of the internal implementation of the metaops. 720 */ 721 if (ctx->Color.ClampFragmentColor != GL_TRUE) 722 _mesa_ClampColorARB(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE); 723 } 724 725 if (state & MESA_META_CLAMP_VERTEX_COLOR) { 726 save->ClampVertexColor = ctx->Light.ClampVertexColor; 727 728 /* Generally in here we never want vertex color clamping -- 729 * result clamping is only dependent on fragment clamping. 730 */ 731 _mesa_ClampColorARB(GL_CLAMP_VERTEX_COLOR, GL_FALSE); 732 } 733 734 if (state & MESA_META_CONDITIONAL_RENDER) { 735 save->CondRenderQuery = ctx->Query.CondRenderQuery; 736 save->CondRenderMode = ctx->Query.CondRenderMode; 737 738 if (ctx->Query.CondRenderQuery) 739 _mesa_EndConditionalRender(); 740 } 741 742#if FEATURE_feedback 743 if (state & MESA_META_SELECT_FEEDBACK) { 744 save->RenderMode = ctx->RenderMode; 745 if (ctx->RenderMode == GL_SELECT) { 746 save->Select = ctx->Select; /* struct copy */ 747 _mesa_RenderMode(GL_RENDER); 748 } else if (ctx->RenderMode == GL_FEEDBACK) { 749 save->Feedback = ctx->Feedback; /* struct copy */ 750 _mesa_RenderMode(GL_RENDER); 751 } 752 } 753#endif 754 755 if (state & MESA_META_MULTISAMPLE) { 756 save->MultisampleEnabled = ctx->Multisample.Enabled; 757 if (ctx->Multisample.Enabled) 758 _mesa_set_enable(ctx, GL_MULTISAMPLE, GL_FALSE); 759 } 760 761 /* misc */ 762 { 763 save->Lighting = ctx->Light.Enabled; 764 if (ctx->Light.Enabled) 765 _mesa_set_enable(ctx, GL_LIGHTING, GL_FALSE); 766 save->RasterDiscard = ctx->RasterDiscard; 767 if (ctx->RasterDiscard) 768 _mesa_set_enable(ctx, GL_RASTERIZER_DISCARD, GL_FALSE); 769 } 770} 771 772 773/** 774 * Leave meta state. This is like a light-weight version of glPopAttrib(). 775 */ 776void 777_mesa_meta_end(struct gl_context *ctx) 778{ 779 struct save_state *save = &ctx->Meta->Save[ctx->Meta->SaveStackDepth - 1]; 780 const GLbitfield state = save->SavedState; 781 782 if (state & MESA_META_ALPHA_TEST) { 783 if (ctx->Color.AlphaEnabled != save->AlphaEnabled) 784 _mesa_set_enable(ctx, GL_ALPHA_TEST, save->AlphaEnabled); 785 _mesa_AlphaFunc(save->AlphaFunc, save->AlphaRef); 786 } 787 788 if (state & MESA_META_BLEND) { 789 if (ctx->Color.BlendEnabled != save->BlendEnabled) { 790 if (ctx->Extensions.EXT_draw_buffers2) { 791 GLuint i; 792 for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) { 793 _mesa_set_enablei(ctx, GL_BLEND, i, (save->BlendEnabled >> i) & 1); 794 } 795 } 796 else { 797 _mesa_set_enable(ctx, GL_BLEND, (save->BlendEnabled & 1)); 798 } 799 } 800 if (ctx->Color.ColorLogicOpEnabled != save->ColorLogicOpEnabled) 801 _mesa_set_enable(ctx, GL_COLOR_LOGIC_OP, save->ColorLogicOpEnabled); 802 } 803 804 if (state & MESA_META_COLOR_MASK) { 805 GLuint i; 806 for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) { 807 if (!TEST_EQ_4V(ctx->Color.ColorMask[i], save->ColorMask[i])) { 808 if (i == 0) { 809 _mesa_ColorMask(save->ColorMask[i][0], save->ColorMask[i][1], 810 save->ColorMask[i][2], save->ColorMask[i][3]); 811 } 812 else { 813 _mesa_ColorMaskIndexed(i, 814 save->ColorMask[i][0], 815 save->ColorMask[i][1], 816 save->ColorMask[i][2], 817 save->ColorMask[i][3]); 818 } 819 } 820 } 821 } 822 823 if (state & MESA_META_DEPTH_TEST) { 824 if (ctx->Depth.Test != save->Depth.Test) 825 _mesa_set_enable(ctx, GL_DEPTH_TEST, save->Depth.Test); 826 _mesa_DepthFunc(save->Depth.Func); 827 _mesa_DepthMask(save->Depth.Mask); 828 } 829 830 if (state & MESA_META_FOG) { 831 _mesa_set_enable(ctx, GL_FOG, save->Fog); 832 } 833 834 if (state & MESA_META_PIXEL_STORE) { 835 ctx->Pack = save->Pack; 836 ctx->Unpack = save->Unpack; 837 } 838 839 if (state & MESA_META_PIXEL_TRANSFER) { 840 ctx->Pixel.RedScale = save->RedScale; 841 ctx->Pixel.RedBias = save->RedBias; 842 ctx->Pixel.GreenScale = save->GreenScale; 843 ctx->Pixel.GreenBias = save->GreenBias; 844 ctx->Pixel.BlueScale = save->BlueScale; 845 ctx->Pixel.BlueBias = save->BlueBias; 846 ctx->Pixel.AlphaScale = save->AlphaScale; 847 ctx->Pixel.AlphaBias = save->AlphaBias; 848 ctx->Pixel.MapColorFlag = save->MapColorFlag; 849 /* XXX more state */ 850 ctx->NewState |=_NEW_PIXEL; 851 } 852 853 if (state & MESA_META_RASTERIZATION) { 854 _mesa_PolygonMode(GL_FRONT, save->FrontPolygonMode); 855 _mesa_PolygonMode(GL_BACK, save->BackPolygonMode); 856 if (ctx->API == API_OPENGL) { 857 _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, save->PolygonStipple); 858 _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, save->PolygonSmooth); 859 } 860 _mesa_set_enable(ctx, GL_POLYGON_OFFSET_FILL, save->PolygonOffset); 861 _mesa_set_enable(ctx, GL_CULL_FACE, save->PolygonCull); 862 } 863 864 if (state & MESA_META_SCISSOR) { 865 _mesa_set_enable(ctx, GL_SCISSOR_TEST, save->Scissor.Enabled); 866 _mesa_Scissor(save->Scissor.X, save->Scissor.Y, 867 save->Scissor.Width, save->Scissor.Height); 868 } 869 870 if (state & MESA_META_SHADER) { 871 if (ctx->API == API_OPENGL && ctx->Extensions.ARB_vertex_program) { 872 _mesa_set_enable(ctx, GL_VERTEX_PROGRAM_ARB, 873 save->VertexProgramEnabled); 874 _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, 875 save->VertexProgram); 876 _mesa_reference_vertprog(ctx, &save->VertexProgram, NULL); 877 } 878 879 if (ctx->API == API_OPENGL && ctx->Extensions.ARB_fragment_program) { 880 _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, 881 save->FragmentProgramEnabled); 882 _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, 883 save->FragmentProgram); 884 _mesa_reference_fragprog(ctx, &save->FragmentProgram, NULL); 885 } 886 887 if (ctx->Extensions.ARB_vertex_shader) 888 _mesa_use_shader_program(ctx, GL_VERTEX_SHADER, save->VertexShader); 889 890 if (ctx->Extensions.ARB_geometry_shader4) 891 _mesa_use_shader_program(ctx, GL_GEOMETRY_SHADER_ARB, 892 save->GeometryShader); 893 894 if (ctx->Extensions.ARB_fragment_shader) 895 _mesa_use_shader_program(ctx, GL_FRAGMENT_SHADER, 896 save->FragmentShader); 897 898 _mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram, 899 save->ActiveShader); 900 901 _mesa_reference_shader_program(ctx, &save->VertexShader, NULL); 902 _mesa_reference_shader_program(ctx, &save->GeometryShader, NULL); 903 _mesa_reference_shader_program(ctx, &save->FragmentShader, NULL); 904 _mesa_reference_shader_program(ctx, &save->ActiveShader, NULL); 905 } 906 907 if (state & MESA_META_STENCIL_TEST) { 908 const struct gl_stencil_attrib *stencil = &save->Stencil; 909 910 _mesa_set_enable(ctx, GL_STENCIL_TEST, stencil->Enabled); 911 _mesa_ClearStencil(stencil->Clear); 912 if (ctx->API == API_OPENGL && ctx->Extensions.EXT_stencil_two_side) { 913 _mesa_set_enable(ctx, GL_STENCIL_TEST_TWO_SIDE_EXT, 914 stencil->TestTwoSide); 915 _mesa_ActiveStencilFaceEXT(stencil->ActiveFace 916 ? GL_BACK : GL_FRONT); 917 } 918 /* front state */ 919 _mesa_StencilFuncSeparate(GL_FRONT, 920 stencil->Function[0], 921 stencil->Ref[0], 922 stencil->ValueMask[0]); 923 _mesa_StencilMaskSeparate(GL_FRONT, stencil->WriteMask[0]); 924 _mesa_StencilOpSeparate(GL_FRONT, stencil->FailFunc[0], 925 stencil->ZFailFunc[0], 926 stencil->ZPassFunc[0]); 927 /* back state */ 928 _mesa_StencilFuncSeparate(GL_BACK, 929 stencil->Function[1], 930 stencil->Ref[1], 931 stencil->ValueMask[1]); 932 _mesa_StencilMaskSeparate(GL_BACK, stencil->WriteMask[1]); 933 _mesa_StencilOpSeparate(GL_BACK, stencil->FailFunc[1], 934 stencil->ZFailFunc[1], 935 stencil->ZPassFunc[1]); 936 } 937 938 if (state & MESA_META_TEXTURE) { 939 GLuint u, tgt; 940 941 ASSERT(ctx->Texture.CurrentUnit == 0); 942 943 /* restore texenv for unit[0] */ 944 if (ctx->API == API_OPENGL || ctx->API == API_OPENGLES) { 945 _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, save->EnvMode); 946 } 947 948 /* restore texture objects for unit[0] only */ 949 for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) { 950 if (ctx->Texture.Unit[0].CurrentTex[tgt] != save->CurrentTexture[tgt]) { 951 FLUSH_VERTICES(ctx, _NEW_TEXTURE); 952 _mesa_reference_texobj(&ctx->Texture.Unit[0].CurrentTex[tgt], 953 save->CurrentTexture[tgt]); 954 } 955 _mesa_reference_texobj(&save->CurrentTexture[tgt], NULL); 956 } 957 958 /* Restore fixed function texture enables, texgen */ 959 if (ctx->API == API_OPENGL || ctx->API == API_OPENGLES) { 960 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { 961 if (ctx->Texture.Unit[u].Enabled != save->TexEnabled[u]) { 962 FLUSH_VERTICES(ctx, _NEW_TEXTURE); 963 ctx->Texture.Unit[u].Enabled = save->TexEnabled[u]; 964 } 965 966 if (ctx->Texture.Unit[u].TexGenEnabled != save->TexGenEnabled[u]) { 967 FLUSH_VERTICES(ctx, _NEW_TEXTURE); 968 ctx->Texture.Unit[u].TexGenEnabled = save->TexGenEnabled[u]; 969 } 970 } 971 } 972 973 /* restore current unit state */ 974 _mesa_ActiveTextureARB(GL_TEXTURE0 + save->ActiveUnit); 975 _mesa_ClientActiveTextureARB(GL_TEXTURE0 + save->ClientActiveUnit); 976 } 977 978 if (state & MESA_META_TRANSFORM) { 979 GLuint activeTexture = ctx->Texture.CurrentUnit; 980 _mesa_ActiveTextureARB(GL_TEXTURE0); 981 _mesa_MatrixMode(GL_TEXTURE); 982 _mesa_LoadMatrixf(save->TextureMatrix); 983 _mesa_ActiveTextureARB(GL_TEXTURE0 + activeTexture); 984 985 _mesa_MatrixMode(GL_MODELVIEW); 986 _mesa_LoadMatrixf(save->ModelviewMatrix); 987 988 _mesa_MatrixMode(GL_PROJECTION); 989 _mesa_LoadMatrixf(save->ProjectionMatrix); 990 991 _mesa_MatrixMode(save->MatrixMode); 992 } 993 994 if (state & MESA_META_CLIP) { 995 if (save->ClipPlanesEnabled) { 996 GLuint i; 997 for (i = 0; i < ctx->Const.MaxClipPlanes; i++) { 998 if (save->ClipPlanesEnabled & (1 << i)) { 999 _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_TRUE); 1000 } 1001 } 1002 } 1003 } 1004 1005 if (state & MESA_META_VERTEX) { 1006 /* restore vertex buffer object */ 1007 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, save->ArrayBufferObj->Name); 1008 _mesa_reference_buffer_object(ctx, &save->ArrayBufferObj, NULL); 1009 1010 /* restore vertex array object */ 1011 _mesa_BindVertexArray(save->ArrayObj->Name); 1012 _mesa_reference_array_object(ctx, &save->ArrayObj, NULL); 1013 } 1014 1015 if (state & MESA_META_VIEWPORT) { 1016 if (save->ViewportX != ctx->Viewport.X || 1017 save->ViewportY != ctx->Viewport.Y || 1018 save->ViewportW != ctx->Viewport.Width || 1019 save->ViewportH != ctx->Viewport.Height) { 1020 _mesa_set_viewport(ctx, save->ViewportX, save->ViewportY, 1021 save->ViewportW, save->ViewportH); 1022 } 1023 _mesa_DepthRange(save->DepthNear, save->DepthFar); 1024 } 1025 1026 if (state & MESA_META_CLAMP_FRAGMENT_COLOR) { 1027 _mesa_ClampColorARB(GL_CLAMP_FRAGMENT_COLOR, save->ClampFragmentColor); 1028 } 1029 1030 if (state & MESA_META_CLAMP_VERTEX_COLOR) { 1031 _mesa_ClampColorARB(GL_CLAMP_VERTEX_COLOR, save->ClampVertexColor); 1032 } 1033 1034 if (state & MESA_META_CONDITIONAL_RENDER) { 1035 if (save->CondRenderQuery) 1036 _mesa_BeginConditionalRender(save->CondRenderQuery->Id, 1037 save->CondRenderMode); 1038 } 1039 1040#if FEATURE_feedback 1041 if (state & MESA_META_SELECT_FEEDBACK) { 1042 if (save->RenderMode == GL_SELECT) { 1043 _mesa_RenderMode(GL_SELECT); 1044 ctx->Select = save->Select; 1045 } else if (save->RenderMode == GL_FEEDBACK) { 1046 _mesa_RenderMode(GL_FEEDBACK); 1047 ctx->Feedback = save->Feedback; 1048 } 1049 } 1050#endif 1051 1052 if (state & MESA_META_MULTISAMPLE) { 1053 if (ctx->Multisample.Enabled != save->MultisampleEnabled) 1054 _mesa_set_enable(ctx, GL_MULTISAMPLE, save->MultisampleEnabled); 1055 } 1056 1057 /* misc */ 1058 if (save->Lighting) { 1059 _mesa_set_enable(ctx, GL_LIGHTING, GL_TRUE); 1060 } 1061 if (save->RasterDiscard) { 1062 _mesa_set_enable(ctx, GL_RASTERIZER_DISCARD, GL_TRUE); 1063 } 1064#if FEATURE_EXT_transform_feedback 1065 if (save->TransformFeedbackNeedsResume) 1066 _mesa_ResumeTransformFeedback(); 1067#endif 1068 1069 ctx->Meta->SaveStackDepth--; 1070} 1071 1072 1073/** 1074 * Determine whether Mesa is currently in a meta state. 1075 */ 1076GLboolean 1077_mesa_meta_in_progress(struct gl_context *ctx) 1078{ 1079 return ctx->Meta->SaveStackDepth != 0; 1080} 1081 1082 1083/** 1084 * Convert Z from a normalized value in the range [0, 1] to an object-space 1085 * Z coordinate in [-1, +1] so that drawing at the new Z position with the 1086 * default/identity ortho projection results in the original Z value. 1087 * Used by the meta-Clear, Draw/CopyPixels and Bitmap functions where the Z 1088 * value comes from the clear value or raster position. 1089 */ 1090static INLINE GLfloat 1091invert_z(GLfloat normZ) 1092{ 1093 GLfloat objZ = 1.0f - 2.0f * normZ; 1094 return objZ; 1095} 1096 1097 1098/** 1099 * One-time init for a temp_texture object. 1100 * Choose tex target, compute max tex size, etc. 1101 */ 1102static void 1103init_temp_texture(struct gl_context *ctx, struct temp_texture *tex) 1104{ 1105 /* prefer texture rectangle */ 1106 if (ctx->Extensions.NV_texture_rectangle) { 1107 tex->Target = GL_TEXTURE_RECTANGLE; 1108 tex->MaxSize = ctx->Const.MaxTextureRectSize; 1109 tex->NPOT = GL_TRUE; 1110 } 1111 else { 1112 /* use 2D texture, NPOT if possible */ 1113 tex->Target = GL_TEXTURE_2D; 1114 tex->MaxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 1115 tex->NPOT = ctx->Extensions.ARB_texture_non_power_of_two; 1116 } 1117 tex->MinSize = 16; /* 16 x 16 at least */ 1118 assert(tex->MaxSize > 0); 1119 1120 _mesa_GenTextures(1, &tex->TexObj); 1121} 1122 1123static void 1124cleanup_temp_texture(struct gl_context *ctx, struct temp_texture *tex) 1125{ 1126 if (!tex->TexObj) 1127 return; 1128 _mesa_DeleteTextures(1, &tex->TexObj); 1129 tex->TexObj = 0; 1130} 1131 1132 1133/** 1134 * Return pointer to temp_texture info for non-bitmap ops. 1135 * This does some one-time init if needed. 1136 */ 1137static struct temp_texture * 1138get_temp_texture(struct gl_context *ctx) 1139{ 1140 struct temp_texture *tex = &ctx->Meta->TempTex; 1141 1142 if (!tex->TexObj) { 1143 init_temp_texture(ctx, tex); 1144 } 1145 1146 return tex; 1147} 1148 1149 1150/** 1151 * Return pointer to temp_texture info for _mesa_meta_bitmap(). 1152 * We use a separate texture for bitmaps to reduce texture 1153 * allocation/deallocation. 1154 */ 1155static struct temp_texture * 1156get_bitmap_temp_texture(struct gl_context *ctx) 1157{ 1158 struct temp_texture *tex = &ctx->Meta->Bitmap.Tex; 1159 1160 if (!tex->TexObj) { 1161 init_temp_texture(ctx, tex); 1162 } 1163 1164 return tex; 1165} 1166 1167 1168/** 1169 * Compute the width/height of texture needed to draw an image of the 1170 * given size. Return a flag indicating whether the current texture 1171 * can be re-used (glTexSubImage2D) or if a new texture needs to be 1172 * allocated (glTexImage2D). 1173 * Also, compute s/t texcoords for drawing. 1174 * 1175 * \return GL_TRUE if new texture is needed, GL_FALSE otherwise 1176 */ 1177static GLboolean 1178alloc_texture(struct temp_texture *tex, 1179 GLsizei width, GLsizei height, GLenum intFormat) 1180{ 1181 GLboolean newTex = GL_FALSE; 1182 1183 ASSERT(width <= tex->MaxSize); 1184 ASSERT(height <= tex->MaxSize); 1185 1186 if (width > tex->Width || 1187 height > tex->Height || 1188 intFormat != tex->IntFormat) { 1189 /* alloc new texture (larger or different format) */ 1190 1191 if (tex->NPOT) { 1192 /* use non-power of two size */ 1193 tex->Width = MAX2(tex->MinSize, width); 1194 tex->Height = MAX2(tex->MinSize, height); 1195 } 1196 else { 1197 /* find power of two size */ 1198 GLsizei w, h; 1199 w = h = tex->MinSize; 1200 while (w < width) 1201 w *= 2; 1202 while (h < height) 1203 h *= 2; 1204 tex->Width = w; 1205 tex->Height = h; 1206 } 1207 1208 tex->IntFormat = intFormat; 1209 1210 newTex = GL_TRUE; 1211 } 1212 1213 /* compute texcoords */ 1214 if (tex->Target == GL_TEXTURE_RECTANGLE) { 1215 tex->Sright = (GLfloat) width; 1216 tex->Ttop = (GLfloat) height; 1217 } 1218 else { 1219 tex->Sright = (GLfloat) width / tex->Width; 1220 tex->Ttop = (GLfloat) height / tex->Height; 1221 } 1222 1223 return newTex; 1224} 1225 1226 1227/** 1228 * Setup/load texture for glCopyPixels or glBlitFramebuffer. 1229 */ 1230static void 1231setup_copypix_texture(struct temp_texture *tex, 1232 GLboolean newTex, 1233 GLint srcX, GLint srcY, 1234 GLsizei width, GLsizei height, GLenum intFormat, 1235 GLenum filter) 1236{ 1237 _mesa_BindTexture(tex->Target, tex->TexObj); 1238 _mesa_TexParameteri(tex->Target, GL_TEXTURE_MIN_FILTER, filter); 1239 _mesa_TexParameteri(tex->Target, GL_TEXTURE_MAG_FILTER, filter); 1240 _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 1241 1242 /* copy framebuffer image to texture */ 1243 if (newTex) { 1244 /* create new tex image */ 1245 if (tex->Width == width && tex->Height == height) { 1246 /* create new tex with framebuffer data */ 1247 _mesa_CopyTexImage2D(tex->Target, 0, tex->IntFormat, 1248 srcX, srcY, width, height, 0); 1249 } 1250 else { 1251 /* create empty texture */ 1252 _mesa_TexImage2D(tex->Target, 0, tex->IntFormat, 1253 tex->Width, tex->Height, 0, 1254 intFormat, GL_UNSIGNED_BYTE, NULL); 1255 /* load image */ 1256 _mesa_CopyTexSubImage2D(tex->Target, 0, 1257 0, 0, srcX, srcY, width, height); 1258 } 1259 } 1260 else { 1261 /* replace existing tex image */ 1262 _mesa_CopyTexSubImage2D(tex->Target, 0, 1263 0, 0, srcX, srcY, width, height); 1264 } 1265} 1266 1267 1268/** 1269 * Setup/load texture for glDrawPixels. 1270 */ 1271static void 1272setup_drawpix_texture(struct gl_context *ctx, 1273 struct temp_texture *tex, 1274 GLboolean newTex, 1275 GLenum texIntFormat, 1276 GLsizei width, GLsizei height, 1277 GLenum format, GLenum type, 1278 const GLvoid *pixels) 1279{ 1280 _mesa_BindTexture(tex->Target, tex->TexObj); 1281 _mesa_TexParameteri(tex->Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 1282 _mesa_TexParameteri(tex->Target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1283 _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 1284 1285 /* copy pixel data to texture */ 1286 if (newTex) { 1287 /* create new tex image */ 1288 if (tex->Width == width && tex->Height == height) { 1289 /* create new tex and load image data */ 1290 _mesa_TexImage2D(tex->Target, 0, tex->IntFormat, 1291 tex->Width, tex->Height, 0, format, type, pixels); 1292 } 1293 else { 1294 struct gl_buffer_object *save_unpack_obj = NULL; 1295 1296 _mesa_reference_buffer_object(ctx, &save_unpack_obj, 1297 ctx->Unpack.BufferObj); 1298 _mesa_BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); 1299 /* create empty texture */ 1300 _mesa_TexImage2D(tex->Target, 0, tex->IntFormat, 1301 tex->Width, tex->Height, 0, format, type, NULL); 1302 if (save_unpack_obj != NULL) 1303 _mesa_BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 1304 save_unpack_obj->Name); 1305 /* load image */ 1306 _mesa_TexSubImage2D(tex->Target, 0, 1307 0, 0, width, height, format, type, pixels); 1308 } 1309 } 1310 else { 1311 /* replace existing tex image */ 1312 _mesa_TexSubImage2D(tex->Target, 0, 1313 0, 0, width, height, format, type, pixels); 1314 } 1315} 1316 1317 1318 1319/** 1320 * One-time init for drawing depth pixels. 1321 */ 1322static void 1323init_blit_depth_pixels(struct gl_context *ctx) 1324{ 1325 static const char *program = 1326 "!!ARBfp1.0\n" 1327 "TEX result.depth, fragment.texcoord[0], texture[0], %s; \n" 1328 "END \n"; 1329 char program2[200]; 1330 struct blit_state *blit = &ctx->Meta->Blit; 1331 struct temp_texture *tex = get_temp_texture(ctx); 1332 const char *texTarget; 1333 1334 assert(blit->DepthFP == 0); 1335 1336 /* replace %s with "RECT" or "2D" */ 1337 assert(strlen(program) + 4 < sizeof(program2)); 1338 if (tex->Target == GL_TEXTURE_RECTANGLE) 1339 texTarget = "RECT"; 1340 else 1341 texTarget = "2D"; 1342 _mesa_snprintf(program2, sizeof(program2), program, texTarget); 1343 1344 _mesa_GenPrograms(1, &blit->DepthFP); 1345 _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, blit->DepthFP); 1346 _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, 1347 strlen(program2), (const GLubyte *) program2); 1348} 1349 1350 1351/** 1352 * Try to do a glBlitFramebuffer using no-copy texturing. 1353 * We can do this when the src renderbuffer is actually a texture. 1354 * But if the src buffer == dst buffer we cannot do this. 1355 * 1356 * \return new buffer mask indicating the buffers left to blit using the 1357 * normal path. 1358 */ 1359static GLbitfield 1360blitframebuffer_texture(struct gl_context *ctx, 1361 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 1362 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, 1363 GLbitfield mask, GLenum filter) 1364{ 1365 if (mask & GL_COLOR_BUFFER_BIT) { 1366 const struct gl_framebuffer *drawFb = ctx->DrawBuffer; 1367 const struct gl_framebuffer *readFb = ctx->ReadBuffer; 1368 const struct gl_renderbuffer_attachment *drawAtt = 1369 &drawFb->Attachment[drawFb->_ColorDrawBufferIndexes[0]]; 1370 const struct gl_renderbuffer_attachment *readAtt = 1371 &readFb->Attachment[readFb->_ColorReadBufferIndex]; 1372 1373 if (readAtt && readAtt->Texture) { 1374 const struct gl_texture_object *texObj = readAtt->Texture; 1375 const GLuint srcLevel = readAtt->TextureLevel; 1376 const GLint baseLevelSave = texObj->BaseLevel; 1377 const GLint maxLevelSave = texObj->MaxLevel; 1378 const GLenum fbo_srgb_save = ctx->Color.sRGBEnabled; 1379 const GLenum target = texObj->Target; 1380 GLuint sampler, samplerSave = 1381 ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler ? 1382 ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler->Name : 0; 1383 1384 if (drawAtt->Texture == readAtt->Texture) { 1385 /* Can't use same texture as both the source and dest. We need 1386 * to handle overlapping blits and besides, some hw may not 1387 * support this. 1388 */ 1389 return mask; 1390 } 1391 1392 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_RECTANGLE_ARB) { 1393 /* Can't handle other texture types at this time */ 1394 return mask; 1395 } 1396 1397 _mesa_GenSamplers(1, &sampler); 1398 _mesa_BindSampler(ctx->Texture.CurrentUnit, sampler); 1399 1400 /* 1401 printf("Blit from texture!\n"); 1402 printf(" srcAtt %p dstAtt %p\n", readAtt, drawAtt); 1403 printf(" srcTex %p dstText %p\n", texObj, drawAtt->Texture); 1404 */ 1405 1406 /* Prepare src texture state */ 1407 _mesa_BindTexture(target, texObj->Name); 1408 _mesa_SamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, filter); 1409 _mesa_SamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, filter); 1410 if (target != GL_TEXTURE_RECTANGLE_ARB) { 1411 _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, srcLevel); 1412 _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, srcLevel); 1413 } 1414 _mesa_SamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 1415 _mesa_SamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 1416 1417 /* Always do our blits with no sRGB decode or encode.*/ 1418 if (ctx->Extensions.EXT_texture_sRGB_decode) { 1419 _mesa_SamplerParameteri(sampler, GL_TEXTURE_SRGB_DECODE_EXT, 1420 GL_SKIP_DECODE_EXT); 1421 } 1422 if (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_framebuffer_sRGB 1423 || _mesa_is_gles3(ctx)) { 1424 _mesa_set_enable(ctx, GL_FRAMEBUFFER_SRGB_EXT, GL_FALSE); 1425 } 1426 1427 _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 1428 _mesa_set_enable(ctx, target, GL_TRUE); 1429 1430 /* Prepare vertex data (the VBO was previously created and bound) */ 1431 { 1432 struct vertex { 1433 GLfloat x, y, s, t; 1434 }; 1435 struct vertex verts[4]; 1436 GLfloat s0, t0, s1, t1; 1437 1438 if (target == GL_TEXTURE_2D) { 1439 const struct gl_texture_image *texImage 1440 = _mesa_select_tex_image(ctx, texObj, target, srcLevel); 1441 s0 = srcX0 / (float) texImage->Width; 1442 s1 = srcX1 / (float) texImage->Width; 1443 t0 = srcY0 / (float) texImage->Height; 1444 t1 = srcY1 / (float) texImage->Height; 1445 } 1446 else { 1447 assert(target == GL_TEXTURE_RECTANGLE_ARB); 1448 s0 = srcX0; 1449 s1 = srcX1; 1450 t0 = srcY0; 1451 t1 = srcY1; 1452 } 1453 1454 verts[0].x = (GLfloat) dstX0; 1455 verts[0].y = (GLfloat) dstY0; 1456 verts[1].x = (GLfloat) dstX1; 1457 verts[1].y = (GLfloat) dstY0; 1458 verts[2].x = (GLfloat) dstX1; 1459 verts[2].y = (GLfloat) dstY1; 1460 verts[3].x = (GLfloat) dstX0; 1461 verts[3].y = (GLfloat) dstY1; 1462 1463 verts[0].s = s0; 1464 verts[0].t = t0; 1465 verts[1].s = s1; 1466 verts[1].t = t0; 1467 verts[2].s = s1; 1468 verts[2].t = t1; 1469 verts[3].s = s0; 1470 verts[3].t = t1; 1471 1472 _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); 1473 } 1474 1475 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 1476 1477 /* Restore texture object state, the texture binding will 1478 * be restored by _mesa_meta_end(). 1479 */ 1480 if (target != GL_TEXTURE_RECTANGLE_ARB) { 1481 _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, baseLevelSave); 1482 _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, maxLevelSave); 1483 } 1484 if (ctx->Extensions.EXT_framebuffer_sRGB && fbo_srgb_save) { 1485 _mesa_set_enable(ctx, GL_FRAMEBUFFER_SRGB_EXT, GL_TRUE); 1486 } 1487 1488 _mesa_BindSampler(ctx->Texture.CurrentUnit, samplerSave); 1489 _mesa_DeleteSamplers(1, &sampler); 1490 1491 /* Done with color buffer */ 1492 mask &= ~GL_COLOR_BUFFER_BIT; 1493 } 1494 } 1495 1496 return mask; 1497} 1498 1499 1500/** 1501 * Meta implementation of ctx->Driver.BlitFramebuffer() in terms 1502 * of texture mapping and polygon rendering. 1503 */ 1504void 1505_mesa_meta_BlitFramebuffer(struct gl_context *ctx, 1506 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 1507 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, 1508 GLbitfield mask, GLenum filter) 1509{ 1510 struct blit_state *blit = &ctx->Meta->Blit; 1511 struct temp_texture *tex = get_temp_texture(ctx); 1512 const GLsizei maxTexSize = tex->MaxSize; 1513 const GLint srcX = MIN2(srcX0, srcX1); 1514 const GLint srcY = MIN2(srcY0, srcY1); 1515 const GLint srcW = abs(srcX1 - srcX0); 1516 const GLint srcH = abs(srcY1 - srcY0); 1517 const GLboolean srcFlipX = srcX1 < srcX0; 1518 const GLboolean srcFlipY = srcY1 < srcY0; 1519 struct vertex { 1520 GLfloat x, y, s, t; 1521 }; 1522 struct vertex verts[4]; 1523 GLboolean newTex; 1524 1525 /* In addition to falling back if the blit size is larger than the maximum 1526 * texture size, fallback if the source is multisampled. This fallback can 1527 * be removed once Mesa gets support ARB_texture_multisample. 1528 */ 1529 if (srcW > maxTexSize || srcH > maxTexSize 1530 || ctx->ReadBuffer->Visual.samples > 0) { 1531 /* XXX avoid this fallback */ 1532 _swrast_BlitFramebuffer(ctx, srcX0, srcY0, srcX1, srcY1, 1533 dstX0, dstY0, dstX1, dstY1, mask, filter); 1534 return; 1535 } 1536 1537 if (srcFlipX) { 1538 GLint tmp = dstX0; 1539 dstX0 = dstX1; 1540 dstX1 = tmp; 1541 } 1542 1543 if (srcFlipY) { 1544 GLint tmp = dstY0; 1545 dstY0 = dstY1; 1546 dstY1 = tmp; 1547 } 1548 1549 /* only scissor effects blit so save/clear all other relevant state */ 1550 _mesa_meta_begin(ctx, ~MESA_META_SCISSOR); 1551 1552 if (blit->ArrayObj == 0) { 1553 /* one-time setup */ 1554 1555 /* create vertex array object */ 1556 _mesa_GenVertexArrays(1, &blit->ArrayObj); 1557 _mesa_BindVertexArray(blit->ArrayObj); 1558 1559 /* create vertex array buffer */ 1560 _mesa_GenBuffersARB(1, &blit->VBO); 1561 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, blit->VBO); 1562 _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts), 1563 NULL, GL_DYNAMIC_DRAW_ARB); 1564 1565 /* setup vertex arrays */ 1566 _mesa_VertexPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(x)); 1567 _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s)); 1568 _mesa_EnableClientState(GL_VERTEX_ARRAY); 1569 _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY); 1570 } 1571 else { 1572 _mesa_BindVertexArray(blit->ArrayObj); 1573 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, blit->VBO); 1574 } 1575 1576 /* Try faster, direct texture approach first */ 1577 mask = blitframebuffer_texture(ctx, srcX0, srcY0, srcX1, srcY1, 1578 dstX0, dstY0, dstX1, dstY1, mask, filter); 1579 if (mask == 0x0) { 1580 _mesa_meta_end(ctx); 1581 return; 1582 } 1583 1584 /* Continue with "normal" approach which involves copying the src rect 1585 * into a temporary texture and is "blitted" by drawing a textured quad. 1586 */ 1587 1588 newTex = alloc_texture(tex, srcW, srcH, GL_RGBA); 1589 1590 /* vertex positions/texcoords (after texture allocation!) */ 1591 { 1592 verts[0].x = (GLfloat) dstX0; 1593 verts[0].y = (GLfloat) dstY0; 1594 verts[1].x = (GLfloat) dstX1; 1595 verts[1].y = (GLfloat) dstY0; 1596 verts[2].x = (GLfloat) dstX1; 1597 verts[2].y = (GLfloat) dstY1; 1598 verts[3].x = (GLfloat) dstX0; 1599 verts[3].y = (GLfloat) dstY1; 1600 1601 verts[0].s = 0.0F; 1602 verts[0].t = 0.0F; 1603 verts[1].s = tex->Sright; 1604 verts[1].t = 0.0F; 1605 verts[2].s = tex->Sright; 1606 verts[2].t = tex->Ttop; 1607 verts[3].s = 0.0F; 1608 verts[3].t = tex->Ttop; 1609 1610 /* upload new vertex data */ 1611 _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); 1612 } 1613 1614 _mesa_set_enable(ctx, tex->Target, GL_TRUE); 1615 1616 if (mask & GL_COLOR_BUFFER_BIT) { 1617 setup_copypix_texture(tex, newTex, srcX, srcY, srcW, srcH, 1618 GL_RGBA, filter); 1619 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 1620 mask &= ~GL_COLOR_BUFFER_BIT; 1621 } 1622 1623 if (mask & GL_DEPTH_BUFFER_BIT) { 1624 GLuint *tmp = (GLuint *) malloc(srcW * srcH * sizeof(GLuint)); 1625 if (tmp) { 1626 if (!blit->DepthFP) 1627 init_blit_depth_pixels(ctx); 1628 1629 /* maybe change tex format here */ 1630 newTex = alloc_texture(tex, srcW, srcH, GL_DEPTH_COMPONENT); 1631 1632 _mesa_ReadPixels(srcX, srcY, srcW, srcH, 1633 GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, tmp); 1634 1635 setup_drawpix_texture(ctx, tex, newTex, GL_DEPTH_COMPONENT, srcW, srcH, 1636 GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, tmp); 1637 1638 _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, blit->DepthFP); 1639 _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_TRUE); 1640 _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 1641 _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_TRUE); 1642 _mesa_DepthFunc(GL_ALWAYS); 1643 _mesa_DepthMask(GL_TRUE); 1644 1645 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 1646 mask &= ~GL_DEPTH_BUFFER_BIT; 1647 1648 free(tmp); 1649 } 1650 } 1651 1652 if (mask & GL_STENCIL_BUFFER_BIT) { 1653 /* XXX can't easily do stencil */ 1654 } 1655 1656 _mesa_set_enable(ctx, tex->Target, GL_FALSE); 1657 1658 _mesa_meta_end(ctx); 1659 1660 if (mask) { 1661 _swrast_BlitFramebuffer(ctx, srcX0, srcY0, srcX1, srcY1, 1662 dstX0, dstY0, dstX1, dstY1, mask, filter); 1663 } 1664} 1665 1666static void 1667meta_glsl_blit_cleanup(struct gl_context *ctx, struct blit_state *blit) 1668{ 1669 if (blit->ArrayObj) { 1670 _mesa_DeleteVertexArraysAPPLE(1, &blit->ArrayObj); 1671 blit->ArrayObj = 0; 1672 _mesa_DeleteBuffersARB(1, &blit->VBO); 1673 blit->VBO = 0; 1674 } 1675 if (blit->DepthFP) { 1676 _mesa_DeletePrograms(1, &blit->DepthFP); 1677 blit->DepthFP = 0; 1678 } 1679} 1680 1681 1682/** 1683 * Meta implementation of ctx->Driver.Clear() in terms of polygon rendering. 1684 */ 1685void 1686_mesa_meta_Clear(struct gl_context *ctx, GLbitfield buffers) 1687{ 1688 struct clear_state *clear = &ctx->Meta->Clear; 1689 struct vertex { 1690 GLfloat x, y, z, r, g, b, a; 1691 }; 1692 struct vertex verts[4]; 1693 /* save all state but scissor, pixel pack/unpack */ 1694 GLbitfield metaSave = (MESA_META_ALL - 1695 MESA_META_SCISSOR - 1696 MESA_META_PIXEL_STORE - 1697 MESA_META_CONDITIONAL_RENDER); 1698 const GLuint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1; 1699 1700 if (buffers & BUFFER_BITS_COLOR) { 1701 /* if clearing color buffers, don't save/restore colormask */ 1702 metaSave -= MESA_META_COLOR_MASK; 1703 } 1704 1705 _mesa_meta_begin(ctx, metaSave); 1706 1707 if (clear->ArrayObj == 0) { 1708 /* one-time setup */ 1709 1710 /* create vertex array object */ 1711 _mesa_GenVertexArrays(1, &clear->ArrayObj); 1712 _mesa_BindVertexArray(clear->ArrayObj); 1713 1714 /* create vertex array buffer */ 1715 _mesa_GenBuffersARB(1, &clear->VBO); 1716 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, clear->VBO); 1717 1718 /* setup vertex arrays */ 1719 _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x)); 1720 _mesa_ColorPointer(4, GL_FLOAT, sizeof(struct vertex), OFFSET(r)); 1721 _mesa_EnableClientState(GL_VERTEX_ARRAY); 1722 _mesa_EnableClientState(GL_COLOR_ARRAY); 1723 } 1724 else { 1725 _mesa_BindVertexArray(clear->ArrayObj); 1726 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, clear->VBO); 1727 } 1728 1729 /* GL_COLOR_BUFFER_BIT */ 1730 if (buffers & BUFFER_BITS_COLOR) { 1731 /* leave colormask, glDrawBuffer state as-is */ 1732 1733 /* Clears never have the color clamped. */ 1734 _mesa_ClampColorARB(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE); 1735 } 1736 else { 1737 ASSERT(metaSave & MESA_META_COLOR_MASK); 1738 _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 1739 } 1740 1741 /* GL_DEPTH_BUFFER_BIT */ 1742 if (buffers & BUFFER_BIT_DEPTH) { 1743 _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_TRUE); 1744 _mesa_DepthFunc(GL_ALWAYS); 1745 _mesa_DepthMask(GL_TRUE); 1746 } 1747 else { 1748 assert(!ctx->Depth.Test); 1749 } 1750 1751 /* GL_STENCIL_BUFFER_BIT */ 1752 if (buffers & BUFFER_BIT_STENCIL) { 1753 _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_TRUE); 1754 _mesa_StencilOpSeparate(GL_FRONT_AND_BACK, 1755 GL_REPLACE, GL_REPLACE, GL_REPLACE); 1756 _mesa_StencilFuncSeparate(GL_FRONT_AND_BACK, GL_ALWAYS, 1757 ctx->Stencil.Clear & stencilMax, 1758 ctx->Stencil.WriteMask[0]); 1759 } 1760 else { 1761 assert(!ctx->Stencil.Enabled); 1762 } 1763 1764 /* vertex positions/colors */ 1765 { 1766 const GLfloat x0 = (GLfloat) ctx->DrawBuffer->_Xmin; 1767 const GLfloat y0 = (GLfloat) ctx->DrawBuffer->_Ymin; 1768 const GLfloat x1 = (GLfloat) ctx->DrawBuffer->_Xmax; 1769 const GLfloat y1 = (GLfloat) ctx->DrawBuffer->_Ymax; 1770 const GLfloat z = invert_z(ctx->Depth.Clear); 1771 GLuint i; 1772 1773 verts[0].x = x0; 1774 verts[0].y = y0; 1775 verts[0].z = z; 1776 verts[1].x = x1; 1777 verts[1].y = y0; 1778 verts[1].z = z; 1779 verts[2].x = x1; 1780 verts[2].y = y1; 1781 verts[2].z = z; 1782 verts[3].x = x0; 1783 verts[3].y = y1; 1784 verts[3].z = z; 1785 1786 /* vertex colors */ 1787 for (i = 0; i < 4; i++) { 1788 verts[i].r = ctx->Color.ClearColor.f[0]; 1789 verts[i].g = ctx->Color.ClearColor.f[1]; 1790 verts[i].b = ctx->Color.ClearColor.f[2]; 1791 verts[i].a = ctx->Color.ClearColor.f[3]; 1792 } 1793 1794 /* upload new vertex data */ 1795 _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts), verts, 1796 GL_DYNAMIC_DRAW_ARB); 1797 } 1798 1799 /* draw quad */ 1800 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 1801 1802 _mesa_meta_end(ctx); 1803} 1804 1805static void 1806meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear) 1807{ 1808 const char *vs_source = 1809 "attribute vec4 position;\n" 1810 "void main()\n" 1811 "{\n" 1812 " gl_Position = position;\n" 1813 "}\n"; 1814 const char *fs_source = 1815 "uniform vec4 color;\n" 1816 "void main()\n" 1817 "{\n" 1818 " gl_FragColor = color;\n" 1819 "}\n"; 1820 const char *vs_int_source = 1821 "#version 130\n" 1822 "attribute vec4 position;\n" 1823 "void main()\n" 1824 "{\n" 1825 " gl_Position = position;\n" 1826 "}\n"; 1827 const char *fs_int_source = 1828 "#version 130\n" 1829 "uniform ivec4 color;\n" 1830 "out ivec4 out_color;\n" 1831 "\n" 1832 "void main()\n" 1833 "{\n" 1834 " out_color = color;\n" 1835 "}\n"; 1836 GLuint vs, fs; 1837 1838 if (clear->ArrayObj != 0) 1839 return; 1840 1841 /* create vertex array object */ 1842 _mesa_GenVertexArrays(1, &clear->ArrayObj); 1843 _mesa_BindVertexArray(clear->ArrayObj); 1844 1845 /* create vertex array buffer */ 1846 _mesa_GenBuffersARB(1, &clear->VBO); 1847 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, clear->VBO); 1848 1849 /* setup vertex arrays */ 1850 _mesa_VertexAttribPointerARB(0, 3, GL_FLOAT, GL_FALSE, 0, (void *)0); 1851 _mesa_EnableVertexAttribArrayARB(0); 1852 1853 vs = _mesa_CreateShaderObjectARB(GL_VERTEX_SHADER); 1854 _mesa_ShaderSourceARB(vs, 1, &vs_source, NULL); 1855 _mesa_CompileShaderARB(vs); 1856 1857 fs = _mesa_CreateShaderObjectARB(GL_FRAGMENT_SHADER); 1858 _mesa_ShaderSourceARB(fs, 1, &fs_source, NULL); 1859 _mesa_CompileShaderARB(fs); 1860 1861 clear->ShaderProg = _mesa_CreateProgramObjectARB(); 1862 _mesa_AttachShader(clear->ShaderProg, fs); 1863 _mesa_DeleteObjectARB(fs); 1864 _mesa_AttachShader(clear->ShaderProg, vs); 1865 _mesa_DeleteObjectARB(vs); 1866 _mesa_BindAttribLocationARB(clear->ShaderProg, 0, "position"); 1867 _mesa_LinkProgramARB(clear->ShaderProg); 1868 1869 clear->ColorLocation = _mesa_GetUniformLocationARB(clear->ShaderProg, 1870 "color"); 1871 1872 if (_mesa_is_desktop_gl(ctx) && ctx->Const.GLSLVersion >= 130) { 1873 vs = compile_shader_with_debug(ctx, GL_VERTEX_SHADER, vs_int_source); 1874 fs = compile_shader_with_debug(ctx, GL_FRAGMENT_SHADER, fs_int_source); 1875 1876 clear->IntegerShaderProg = _mesa_CreateProgramObjectARB(); 1877 _mesa_AttachShader(clear->IntegerShaderProg, fs); 1878 _mesa_DeleteObjectARB(fs); 1879 _mesa_AttachShader(clear->IntegerShaderProg, vs); 1880 _mesa_DeleteObjectARB(vs); 1881 _mesa_BindAttribLocationARB(clear->IntegerShaderProg, 0, "position"); 1882 1883 /* Note that user-defined out attributes get automatically assigned 1884 * locations starting from 0, so we don't need to explicitly 1885 * BindFragDataLocation to 0. 1886 */ 1887 1888 link_program_with_debug(ctx, clear->IntegerShaderProg); 1889 1890 clear->IntegerColorLocation = 1891 _mesa_GetUniformLocationARB(clear->IntegerShaderProg, "color"); 1892 } 1893} 1894 1895static void 1896meta_glsl_clear_cleanup(struct gl_context *ctx, struct clear_state *clear) 1897{ 1898 if (clear->ArrayObj == 0) 1899 return; 1900 _mesa_DeleteVertexArraysAPPLE(1, &clear->ArrayObj); 1901 clear->ArrayObj = 0; 1902 _mesa_DeleteBuffersARB(1, &clear->VBO); 1903 clear->VBO = 0; 1904 _mesa_DeleteObjectARB(clear->ShaderProg); 1905 clear->ShaderProg = 0; 1906 1907 if (clear->IntegerShaderProg) { 1908 _mesa_DeleteObjectARB(clear->IntegerShaderProg); 1909 clear->IntegerShaderProg = 0; 1910 } 1911} 1912 1913/** 1914 * Meta implementation of ctx->Driver.Clear() in terms of polygon rendering. 1915 */ 1916void 1917_mesa_meta_glsl_Clear(struct gl_context *ctx, GLbitfield buffers) 1918{ 1919 struct clear_state *clear = &ctx->Meta->Clear; 1920 GLbitfield metaSave; 1921 const GLuint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1; 1922 struct gl_framebuffer *fb = ctx->DrawBuffer; 1923 const float x0 = ((float)fb->_Xmin / fb->Width) * 2.0f - 1.0f; 1924 const float y0 = ((float)fb->_Ymin / fb->Height) * 2.0f - 1.0f; 1925 const float x1 = ((float)fb->_Xmax / fb->Width) * 2.0f - 1.0f; 1926 const float y1 = ((float)fb->_Ymax / fb->Height) * 2.0f - 1.0f; 1927 const float z = -invert_z(ctx->Depth.Clear); 1928 struct vertex { 1929 GLfloat x, y, z; 1930 } verts[4]; 1931 1932 metaSave = (MESA_META_ALPHA_TEST | 1933 MESA_META_BLEND | 1934 MESA_META_DEPTH_TEST | 1935 MESA_META_RASTERIZATION | 1936 MESA_META_SHADER | 1937 MESA_META_STENCIL_TEST | 1938 MESA_META_VERTEX | 1939 MESA_META_VIEWPORT | 1940 MESA_META_CLIP | 1941 MESA_META_CLAMP_FRAGMENT_COLOR | 1942 MESA_META_MULTISAMPLE); 1943 1944 if (!(buffers & BUFFER_BITS_COLOR)) { 1945 /* We'll use colormask to disable color writes. Otherwise, 1946 * respect color mask 1947 */ 1948 metaSave |= MESA_META_COLOR_MASK; 1949 } 1950 1951 _mesa_meta_begin(ctx, metaSave); 1952 1953 meta_glsl_clear_init(ctx, clear); 1954 1955 if (fb->_IntegerColor) { 1956 _mesa_UseProgramObjectARB(clear->IntegerShaderProg); 1957 _mesa_Uniform4ivARB(clear->IntegerColorLocation, 1, 1958 ctx->Color.ClearColor.i); 1959 } else { 1960 _mesa_UseProgramObjectARB(clear->ShaderProg); 1961 _mesa_Uniform4fvARB(clear->ColorLocation, 1, 1962 ctx->Color.ClearColor.f); 1963 } 1964 1965 _mesa_BindVertexArray(clear->ArrayObj); 1966 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, clear->VBO); 1967 1968 /* GL_COLOR_BUFFER_BIT */ 1969 if (buffers & BUFFER_BITS_COLOR) { 1970 /* leave colormask, glDrawBuffer state as-is */ 1971 1972 /* Clears never have the color clamped. */ 1973 _mesa_ClampColorARB(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE); 1974 } 1975 else { 1976 ASSERT(metaSave & MESA_META_COLOR_MASK); 1977 _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 1978 } 1979 1980 /* GL_DEPTH_BUFFER_BIT */ 1981 if (buffers & BUFFER_BIT_DEPTH) { 1982 _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_TRUE); 1983 _mesa_DepthFunc(GL_ALWAYS); 1984 _mesa_DepthMask(GL_TRUE); 1985 } 1986 else { 1987 assert(!ctx->Depth.Test); 1988 } 1989 1990 /* GL_STENCIL_BUFFER_BIT */ 1991 if (buffers & BUFFER_BIT_STENCIL) { 1992 _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_TRUE); 1993 _mesa_StencilOpSeparate(GL_FRONT_AND_BACK, 1994 GL_REPLACE, GL_REPLACE, GL_REPLACE); 1995 _mesa_StencilFuncSeparate(GL_FRONT_AND_BACK, GL_ALWAYS, 1996 ctx->Stencil.Clear & stencilMax, 1997 ctx->Stencil.WriteMask[0]); 1998 } 1999 else { 2000 assert(!ctx->Stencil.Enabled); 2001 } 2002 2003 /* vertex positions */ 2004 verts[0].x = x0; 2005 verts[0].y = y0; 2006 verts[0].z = z; 2007 verts[1].x = x1; 2008 verts[1].y = y0; 2009 verts[1].z = z; 2010 verts[2].x = x1; 2011 verts[2].y = y1; 2012 verts[2].z = z; 2013 verts[3].x = x0; 2014 verts[3].y = y1; 2015 verts[3].z = z; 2016 2017 /* upload new vertex data */ 2018 _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts), verts, 2019 GL_DYNAMIC_DRAW_ARB); 2020 2021 /* draw quad */ 2022 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 2023 2024 _mesa_meta_end(ctx); 2025} 2026 2027/** 2028 * Meta implementation of ctx->Driver.CopyPixels() in terms 2029 * of texture mapping and polygon rendering and GLSL shaders. 2030 */ 2031void 2032_mesa_meta_CopyPixels(struct gl_context *ctx, GLint srcX, GLint srcY, 2033 GLsizei width, GLsizei height, 2034 GLint dstX, GLint dstY, GLenum type) 2035{ 2036 struct copypix_state *copypix = &ctx->Meta->CopyPix; 2037 struct temp_texture *tex = get_temp_texture(ctx); 2038 struct vertex { 2039 GLfloat x, y, z, s, t; 2040 }; 2041 struct vertex verts[4]; 2042 GLboolean newTex; 2043 GLenum intFormat = GL_RGBA; 2044 2045 if (type != GL_COLOR || 2046 ctx->_ImageTransferState || 2047 ctx->Fog.Enabled || 2048 width > tex->MaxSize || 2049 height > tex->MaxSize) { 2050 /* XXX avoid this fallback */ 2051 _swrast_CopyPixels(ctx, srcX, srcY, width, height, dstX, dstY, type); 2052 return; 2053 } 2054 2055 /* Most GL state applies to glCopyPixels, but a there's a few things 2056 * we need to override: 2057 */ 2058 _mesa_meta_begin(ctx, (MESA_META_RASTERIZATION | 2059 MESA_META_SHADER | 2060 MESA_META_TEXTURE | 2061 MESA_META_TRANSFORM | 2062 MESA_META_CLIP | 2063 MESA_META_VERTEX | 2064 MESA_META_VIEWPORT)); 2065 2066 if (copypix->ArrayObj == 0) { 2067 /* one-time setup */ 2068 2069 /* create vertex array object */ 2070 _mesa_GenVertexArrays(1, ©pix->ArrayObj); 2071 _mesa_BindVertexArray(copypix->ArrayObj); 2072 2073 /* create vertex array buffer */ 2074 _mesa_GenBuffersARB(1, ©pix->VBO); 2075 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, copypix->VBO); 2076 _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts), 2077 NULL, GL_DYNAMIC_DRAW_ARB); 2078 2079 /* setup vertex arrays */ 2080 _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x)); 2081 _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s)); 2082 _mesa_EnableClientState(GL_VERTEX_ARRAY); 2083 _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY); 2084 } 2085 else { 2086 _mesa_BindVertexArray(copypix->ArrayObj); 2087 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, copypix->VBO); 2088 } 2089 2090 newTex = alloc_texture(tex, width, height, intFormat); 2091 2092 /* vertex positions, texcoords (after texture allocation!) */ 2093 { 2094 const GLfloat dstX0 = (GLfloat) dstX; 2095 const GLfloat dstY0 = (GLfloat) dstY; 2096 const GLfloat dstX1 = dstX + width * ctx->Pixel.ZoomX; 2097 const GLfloat dstY1 = dstY + height * ctx->Pixel.ZoomY; 2098 const GLfloat z = invert_z(ctx->Current.RasterPos[2]); 2099 2100 verts[0].x = dstX0; 2101 verts[0].y = dstY0; 2102 verts[0].z = z; 2103 verts[0].s = 0.0F; 2104 verts[0].t = 0.0F; 2105 verts[1].x = dstX1; 2106 verts[1].y = dstY0; 2107 verts[1].z = z; 2108 verts[1].s = tex->Sright; 2109 verts[1].t = 0.0F; 2110 verts[2].x = dstX1; 2111 verts[2].y = dstY1; 2112 verts[2].z = z; 2113 verts[2].s = tex->Sright; 2114 verts[2].t = tex->Ttop; 2115 verts[3].x = dstX0; 2116 verts[3].y = dstY1; 2117 verts[3].z = z; 2118 verts[3].s = 0.0F; 2119 verts[3].t = tex->Ttop; 2120 2121 /* upload new vertex data */ 2122 _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); 2123 } 2124 2125 /* Alloc/setup texture */ 2126 setup_copypix_texture(tex, newTex, srcX, srcY, width, height, 2127 GL_RGBA, GL_NEAREST); 2128 2129 _mesa_set_enable(ctx, tex->Target, GL_TRUE); 2130 2131 /* draw textured quad */ 2132 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 2133 2134 _mesa_set_enable(ctx, tex->Target, GL_FALSE); 2135 2136 _mesa_meta_end(ctx); 2137} 2138 2139 2140 2141/** 2142 * When the glDrawPixels() image size is greater than the max rectangle 2143 * texture size we use this function to break the glDrawPixels() image 2144 * into tiles which fit into the max texture size. 2145 */ 2146static void 2147tiled_draw_pixels(struct gl_context *ctx, 2148 GLint tileSize, 2149 GLint x, GLint y, GLsizei width, GLsizei height, 2150 GLenum format, GLenum type, 2151 const struct gl_pixelstore_attrib *unpack, 2152 const GLvoid *pixels) 2153{ 2154 struct gl_pixelstore_attrib tileUnpack = *unpack; 2155 GLint i, j; 2156 2157 if (tileUnpack.RowLength == 0) 2158 tileUnpack.RowLength = width; 2159 2160 for (i = 0; i < width; i += tileSize) { 2161 const GLint tileWidth = MIN2(tileSize, width - i); 2162 const GLint tileX = (GLint) (x + i * ctx->Pixel.ZoomX); 2163 2164 tileUnpack.SkipPixels = unpack->SkipPixels + i; 2165 2166 for (j = 0; j < height; j += tileSize) { 2167 const GLint tileHeight = MIN2(tileSize, height - j); 2168 const GLint tileY = (GLint) (y + j * ctx->Pixel.ZoomY); 2169 2170 tileUnpack.SkipRows = unpack->SkipRows + j; 2171 2172 _mesa_meta_DrawPixels(ctx, tileX, tileY, tileWidth, tileHeight, 2173 format, type, &tileUnpack, pixels); 2174 } 2175 } 2176} 2177 2178 2179/** 2180 * One-time init for drawing stencil pixels. 2181 */ 2182static void 2183init_draw_stencil_pixels(struct gl_context *ctx) 2184{ 2185 /* This program is run eight times, once for each stencil bit. 2186 * The stencil values to draw are found in an 8-bit alpha texture. 2187 * We read the texture/stencil value and test if bit 'b' is set. 2188 * If the bit is not set, use KIL to kill the fragment. 2189 * Finally, we use the stencil test to update the stencil buffer. 2190 * 2191 * The basic algorithm for checking if a bit is set is: 2192 * if (is_odd(value / (1 << bit))) 2193 * result is one (or non-zero). 2194 * else 2195 * result is zero. 2196 * The program parameter contains three values: 2197 * parm.x = 255 / (1 << bit) 2198 * parm.y = 0.5 2199 * parm.z = 0.0 2200 */ 2201 static const char *program = 2202 "!!ARBfp1.0\n" 2203 "PARAM parm = program.local[0]; \n" 2204 "TEMP t; \n" 2205 "TEX t, fragment.texcoord[0], texture[0], %s; \n" /* NOTE %s here! */ 2206 "# t = t * 255 / bit \n" 2207 "MUL t.x, t.a, parm.x; \n" 2208 "# t = (int) t \n" 2209 "FRC t.y, t.x; \n" 2210 "SUB t.x, t.x, t.y; \n" 2211 "# t = t * 0.5 \n" 2212 "MUL t.x, t.x, parm.y; \n" 2213 "# t = fract(t.x) \n" 2214 "FRC t.x, t.x; # if t.x != 0, then the bit is set \n" 2215 "# t.x = (t.x == 0 ? 1 : 0) \n" 2216 "SGE t.x, -t.x, parm.z; \n" 2217 "KIL -t.x; \n" 2218 "# for debug only \n" 2219 "#MOV result.color, t.x; \n" 2220 "END \n"; 2221 char program2[1000]; 2222 struct drawpix_state *drawpix = &ctx->Meta->DrawPix; 2223 struct temp_texture *tex = get_temp_texture(ctx); 2224 const char *texTarget; 2225 2226 assert(drawpix->StencilFP == 0); 2227 2228 /* replace %s with "RECT" or "2D" */ 2229 assert(strlen(program) + 4 < sizeof(program2)); 2230 if (tex->Target == GL_TEXTURE_RECTANGLE) 2231 texTarget = "RECT"; 2232 else 2233 texTarget = "2D"; 2234 _mesa_snprintf(program2, sizeof(program2), program, texTarget); 2235 2236 _mesa_GenPrograms(1, &drawpix->StencilFP); 2237 _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, drawpix->StencilFP); 2238 _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, 2239 strlen(program2), (const GLubyte *) program2); 2240} 2241 2242 2243/** 2244 * One-time init for drawing depth pixels. 2245 */ 2246static void 2247init_draw_depth_pixels(struct gl_context *ctx) 2248{ 2249 static const char *program = 2250 "!!ARBfp1.0\n" 2251 "PARAM color = program.local[0]; \n" 2252 "TEX result.depth, fragment.texcoord[0], texture[0], %s; \n" 2253 "MOV result.color, color; \n" 2254 "END \n"; 2255 char program2[200]; 2256 struct drawpix_state *drawpix = &ctx->Meta->DrawPix; 2257 struct temp_texture *tex = get_temp_texture(ctx); 2258 const char *texTarget; 2259 2260 assert(drawpix->DepthFP == 0); 2261 2262 /* replace %s with "RECT" or "2D" */ 2263 assert(strlen(program) + 4 < sizeof(program2)); 2264 if (tex->Target == GL_TEXTURE_RECTANGLE) 2265 texTarget = "RECT"; 2266 else 2267 texTarget = "2D"; 2268 _mesa_snprintf(program2, sizeof(program2), program, texTarget); 2269 2270 _mesa_GenPrograms(1, &drawpix->DepthFP); 2271 _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, drawpix->DepthFP); 2272 _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, 2273 strlen(program2), (const GLubyte *) program2); 2274} 2275 2276 2277/** 2278 * Meta implementation of ctx->Driver.DrawPixels() in terms 2279 * of texture mapping and polygon rendering. 2280 */ 2281void 2282_mesa_meta_DrawPixels(struct gl_context *ctx, 2283 GLint x, GLint y, GLsizei width, GLsizei height, 2284 GLenum format, GLenum type, 2285 const struct gl_pixelstore_attrib *unpack, 2286 const GLvoid *pixels) 2287{ 2288 struct drawpix_state *drawpix = &ctx->Meta->DrawPix; 2289 struct temp_texture *tex = get_temp_texture(ctx); 2290 const struct gl_pixelstore_attrib unpackSave = ctx->Unpack; 2291 const GLuint origStencilMask = ctx->Stencil.WriteMask[0]; 2292 struct vertex { 2293 GLfloat x, y, z, s, t; 2294 }; 2295 struct vertex verts[4]; 2296 GLenum texIntFormat; 2297 GLboolean fallback, newTex; 2298 GLbitfield metaExtraSave = 0x0; 2299 GLuint vbo; 2300 2301 /* 2302 * Determine if we can do the glDrawPixels with texture mapping. 2303 */ 2304 fallback = GL_FALSE; 2305 if (ctx->Fog.Enabled) { 2306 fallback = GL_TRUE; 2307 } 2308 2309 if (_mesa_is_color_format(format)) { 2310 /* use more compact format when possible */ 2311 /* XXX disable special case for GL_LUMINANCE for now to work around 2312 * apparent i965 driver bug (see bug #23670). 2313 */ 2314 if (/*format == GL_LUMINANCE ||*/ format == GL_LUMINANCE_ALPHA) 2315 texIntFormat = format; 2316 else 2317 texIntFormat = GL_RGBA; 2318 2319 /* If we're not supposed to clamp the resulting color, then just 2320 * promote our texture to fully float. We could do better by 2321 * just going for the matching set of channels, in floating 2322 * point. 2323 */ 2324 if (ctx->Color.ClampFragmentColor != GL_TRUE && 2325 ctx->Extensions.ARB_texture_float) 2326 texIntFormat = GL_RGBA32F; 2327 } 2328 else if (_mesa_is_stencil_format(format)) { 2329 if (ctx->Extensions.ARB_fragment_program && 2330 ctx->Pixel.IndexShift == 0 && 2331 ctx->Pixel.IndexOffset == 0 && 2332 type == GL_UNSIGNED_BYTE) { 2333 /* We'll store stencil as alpha. This only works for GLubyte 2334 * image data because of how incoming values are mapped to alpha 2335 * in [0,1]. 2336 */ 2337 texIntFormat = GL_ALPHA; 2338 metaExtraSave = (MESA_META_COLOR_MASK | 2339 MESA_META_DEPTH_TEST | 2340 MESA_META_PIXEL_TRANSFER | 2341 MESA_META_SHADER | 2342 MESA_META_STENCIL_TEST); 2343 } 2344 else { 2345 fallback = GL_TRUE; 2346 } 2347 } 2348 else if (_mesa_is_depth_format(format)) { 2349 if (ctx->Extensions.ARB_depth_texture && 2350 ctx->Extensions.ARB_fragment_program) { 2351 texIntFormat = GL_DEPTH_COMPONENT; 2352 metaExtraSave = (MESA_META_SHADER); 2353 } 2354 else { 2355 fallback = GL_TRUE; 2356 } 2357 } 2358 else { 2359 fallback = GL_TRUE; 2360 } 2361 2362 if (fallback) { 2363 _swrast_DrawPixels(ctx, x, y, width, height, 2364 format, type, unpack, pixels); 2365 return; 2366 } 2367 2368 /* 2369 * Check image size against max texture size, draw as tiles if needed. 2370 */ 2371 if (width > tex->MaxSize || height > tex->MaxSize) { 2372 tiled_draw_pixels(ctx, tex->MaxSize, x, y, width, height, 2373 format, type, unpack, pixels); 2374 return; 2375 } 2376 2377 /* Most GL state applies to glDrawPixels (like blending, stencil, etc), 2378 * but a there's a few things we need to override: 2379 */ 2380 _mesa_meta_begin(ctx, (MESA_META_RASTERIZATION | 2381 MESA_META_SHADER | 2382 MESA_META_TEXTURE | 2383 MESA_META_TRANSFORM | 2384 MESA_META_CLIP | 2385 MESA_META_VERTEX | 2386 MESA_META_VIEWPORT | 2387 metaExtraSave)); 2388 2389 newTex = alloc_texture(tex, width, height, texIntFormat); 2390 2391 /* vertex positions, texcoords (after texture allocation!) */ 2392 { 2393 const GLfloat x0 = (GLfloat) x; 2394 const GLfloat y0 = (GLfloat) y; 2395 const GLfloat x1 = x + width * ctx->Pixel.ZoomX; 2396 const GLfloat y1 = y + height * ctx->Pixel.ZoomY; 2397 const GLfloat z = invert_z(ctx->Current.RasterPos[2]); 2398 2399 verts[0].x = x0; 2400 verts[0].y = y0; 2401 verts[0].z = z; 2402 verts[0].s = 0.0F; 2403 verts[0].t = 0.0F; 2404 verts[1].x = x1; 2405 verts[1].y = y0; 2406 verts[1].z = z; 2407 verts[1].s = tex->Sright; 2408 verts[1].t = 0.0F; 2409 verts[2].x = x1; 2410 verts[2].y = y1; 2411 verts[2].z = z; 2412 verts[2].s = tex->Sright; 2413 verts[2].t = tex->Ttop; 2414 verts[3].x = x0; 2415 verts[3].y = y1; 2416 verts[3].z = z; 2417 verts[3].s = 0.0F; 2418 verts[3].t = tex->Ttop; 2419 } 2420 2421 if (drawpix->ArrayObj == 0) { 2422 /* one-time setup: create vertex array object */ 2423 _mesa_GenVertexArrays(1, &drawpix->ArrayObj); 2424 } 2425 _mesa_BindVertexArray(drawpix->ArrayObj); 2426 2427 /* create vertex array buffer */ 2428 _mesa_GenBuffersARB(1, &vbo); 2429 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, vbo); 2430 _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts), 2431 verts, GL_DYNAMIC_DRAW_ARB); 2432 2433 /* setup vertex arrays */ 2434 _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x)); 2435 _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s)); 2436 _mesa_EnableClientState(GL_VERTEX_ARRAY); 2437 _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY); 2438 2439 /* set given unpack params */ 2440 ctx->Unpack = *unpack; 2441 2442 _mesa_set_enable(ctx, tex->Target, GL_TRUE); 2443 2444 if (_mesa_is_stencil_format(format)) { 2445 /* Drawing stencil */ 2446 GLint bit; 2447 2448 if (!drawpix->StencilFP) 2449 init_draw_stencil_pixels(ctx); 2450 2451 setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height, 2452 GL_ALPHA, type, pixels); 2453 2454 _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 2455 2456 _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_TRUE); 2457 2458 /* set all stencil bits to 0 */ 2459 _mesa_StencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); 2460 _mesa_StencilFunc(GL_ALWAYS, 0, 255); 2461 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 2462 2463 /* set stencil bits to 1 where needed */ 2464 _mesa_StencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); 2465 2466 _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, drawpix->StencilFP); 2467 _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_TRUE); 2468 2469 for (bit = 0; bit < ctx->DrawBuffer->Visual.stencilBits; bit++) { 2470 const GLuint mask = 1 << bit; 2471 if (mask & origStencilMask) { 2472 _mesa_StencilFunc(GL_ALWAYS, mask, mask); 2473 _mesa_StencilMask(mask); 2474 2475 _mesa_ProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, 2476 255.0 / mask, 0.5, 0.0, 0.0); 2477 2478 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 2479 } 2480 } 2481 } 2482 else if (_mesa_is_depth_format(format)) { 2483 /* Drawing depth */ 2484 if (!drawpix->DepthFP) 2485 init_draw_depth_pixels(ctx); 2486 2487 _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, drawpix->DepthFP); 2488 _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_TRUE); 2489 2490 /* polygon color = current raster color */ 2491 _mesa_ProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 0, 2492 ctx->Current.RasterColor); 2493 2494 setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height, 2495 format, type, pixels); 2496 2497 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 2498 } 2499 else { 2500 /* Drawing RGBA */ 2501 setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height, 2502 format, type, pixels); 2503 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 2504 } 2505 2506 _mesa_set_enable(ctx, tex->Target, GL_FALSE); 2507 2508 _mesa_DeleteBuffersARB(1, &vbo); 2509 2510 /* restore unpack params */ 2511 ctx->Unpack = unpackSave; 2512 2513 _mesa_meta_end(ctx); 2514} 2515 2516static GLboolean 2517alpha_test_raster_color(struct gl_context *ctx) 2518{ 2519 GLfloat alpha = ctx->Current.RasterColor[ACOMP]; 2520 GLfloat ref = ctx->Color.AlphaRef; 2521 2522 switch (ctx->Color.AlphaFunc) { 2523 case GL_NEVER: 2524 return GL_FALSE; 2525 case GL_LESS: 2526 return alpha < ref; 2527 case GL_EQUAL: 2528 return alpha == ref; 2529 case GL_LEQUAL: 2530 return alpha <= ref; 2531 case GL_GREATER: 2532 return alpha > ref; 2533 case GL_NOTEQUAL: 2534 return alpha != ref; 2535 case GL_GEQUAL: 2536 return alpha >= ref; 2537 case GL_ALWAYS: 2538 return GL_TRUE; 2539 default: 2540 assert(0); 2541 return GL_FALSE; 2542 } 2543} 2544 2545/** 2546 * Do glBitmap with a alpha texture quad. Use the alpha test to cull 2547 * the 'off' bits. A bitmap cache as in the gallium/mesa state 2548 * tracker would improve performance a lot. 2549 */ 2550void 2551_mesa_meta_Bitmap(struct gl_context *ctx, 2552 GLint x, GLint y, GLsizei width, GLsizei height, 2553 const struct gl_pixelstore_attrib *unpack, 2554 const GLubyte *bitmap1) 2555{ 2556 struct bitmap_state *bitmap = &ctx->Meta->Bitmap; 2557 struct temp_texture *tex = get_bitmap_temp_texture(ctx); 2558 const GLenum texIntFormat = GL_ALPHA; 2559 const struct gl_pixelstore_attrib unpackSave = *unpack; 2560 GLubyte fg, bg; 2561 struct vertex { 2562 GLfloat x, y, z, s, t, r, g, b, a; 2563 }; 2564 struct vertex verts[4]; 2565 GLboolean newTex; 2566 GLubyte *bitmap8; 2567 2568 /* 2569 * Check if swrast fallback is needed. 2570 */ 2571 if (ctx->_ImageTransferState || 2572 ctx->FragmentProgram._Enabled || 2573 ctx->Fog.Enabled || 2574 ctx->Texture._EnabledUnits || 2575 width > tex->MaxSize || 2576 height > tex->MaxSize) { 2577 _swrast_Bitmap(ctx, x, y, width, height, unpack, bitmap1); 2578 return; 2579 } 2580 2581 if (ctx->Color.AlphaEnabled && !alpha_test_raster_color(ctx)) 2582 return; 2583 2584 /* Most GL state applies to glBitmap (like blending, stencil, etc), 2585 * but a there's a few things we need to override: 2586 */ 2587 _mesa_meta_begin(ctx, (MESA_META_ALPHA_TEST | 2588 MESA_META_PIXEL_STORE | 2589 MESA_META_RASTERIZATION | 2590 MESA_META_SHADER | 2591 MESA_META_TEXTURE | 2592 MESA_META_TRANSFORM | 2593 MESA_META_CLIP | 2594 MESA_META_VERTEX | 2595 MESA_META_VIEWPORT)); 2596 2597 if (bitmap->ArrayObj == 0) { 2598 /* one-time setup */ 2599 2600 /* create vertex array object */ 2601 _mesa_GenVertexArraysAPPLE(1, &bitmap->ArrayObj); 2602 _mesa_BindVertexArrayAPPLE(bitmap->ArrayObj); 2603 2604 /* create vertex array buffer */ 2605 _mesa_GenBuffersARB(1, &bitmap->VBO); 2606 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, bitmap->VBO); 2607 _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts), 2608 NULL, GL_DYNAMIC_DRAW_ARB); 2609 2610 /* setup vertex arrays */ 2611 _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x)); 2612 _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s)); 2613 _mesa_ColorPointer(4, GL_FLOAT, sizeof(struct vertex), OFFSET(r)); 2614 _mesa_EnableClientState(GL_VERTEX_ARRAY); 2615 _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY); 2616 _mesa_EnableClientState(GL_COLOR_ARRAY); 2617 } 2618 else { 2619 _mesa_BindVertexArray(bitmap->ArrayObj); 2620 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, bitmap->VBO); 2621 } 2622 2623 newTex = alloc_texture(tex, width, height, texIntFormat); 2624 2625 /* vertex positions, texcoords, colors (after texture allocation!) */ 2626 { 2627 const GLfloat x0 = (GLfloat) x; 2628 const GLfloat y0 = (GLfloat) y; 2629 const GLfloat x1 = (GLfloat) (x + width); 2630 const GLfloat y1 = (GLfloat) (y + height); 2631 const GLfloat z = invert_z(ctx->Current.RasterPos[2]); 2632 GLuint i; 2633 2634 verts[0].x = x0; 2635 verts[0].y = y0; 2636 verts[0].z = z; 2637 verts[0].s = 0.0F; 2638 verts[0].t = 0.0F; 2639 verts[1].x = x1; 2640 verts[1].y = y0; 2641 verts[1].z = z; 2642 verts[1].s = tex->Sright; 2643 verts[1].t = 0.0F; 2644 verts[2].x = x1; 2645 verts[2].y = y1; 2646 verts[2].z = z; 2647 verts[2].s = tex->Sright; 2648 verts[2].t = tex->Ttop; 2649 verts[3].x = x0; 2650 verts[3].y = y1; 2651 verts[3].z = z; 2652 verts[3].s = 0.0F; 2653 verts[3].t = tex->Ttop; 2654 2655 for (i = 0; i < 4; i++) { 2656 verts[i].r = ctx->Current.RasterColor[0]; 2657 verts[i].g = ctx->Current.RasterColor[1]; 2658 verts[i].b = ctx->Current.RasterColor[2]; 2659 verts[i].a = ctx->Current.RasterColor[3]; 2660 } 2661 2662 /* upload new vertex data */ 2663 _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); 2664 } 2665 2666 /* choose different foreground/background alpha values */ 2667 CLAMPED_FLOAT_TO_UBYTE(fg, ctx->Current.RasterColor[ACOMP]); 2668 bg = (fg > 127 ? 0 : 255); 2669 2670 bitmap1 = _mesa_map_pbo_source(ctx, &unpackSave, bitmap1); 2671 if (!bitmap1) { 2672 _mesa_meta_end(ctx); 2673 return; 2674 } 2675 2676 bitmap8 = (GLubyte *) malloc(width * height); 2677 if (bitmap8) { 2678 memset(bitmap8, bg, width * height); 2679 _mesa_expand_bitmap(width, height, &unpackSave, bitmap1, 2680 bitmap8, width, fg); 2681 2682 _mesa_set_enable(ctx, tex->Target, GL_TRUE); 2683 2684 _mesa_set_enable(ctx, GL_ALPHA_TEST, GL_TRUE); 2685 _mesa_AlphaFunc(GL_NOTEQUAL, UBYTE_TO_FLOAT(bg)); 2686 2687 setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height, 2688 GL_ALPHA, GL_UNSIGNED_BYTE, bitmap8); 2689 2690 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 2691 2692 _mesa_set_enable(ctx, tex->Target, GL_FALSE); 2693 2694 free(bitmap8); 2695 } 2696 2697 _mesa_unmap_pbo_source(ctx, &unpackSave); 2698 2699 _mesa_meta_end(ctx); 2700} 2701 2702 2703/** 2704 * Check if the call to _mesa_meta_GenerateMipmap() will require a 2705 * software fallback. The fallback path will require that the texture 2706 * images are mapped. 2707 * \return GL_TRUE if a fallback is needed, GL_FALSE otherwise 2708 */ 2709GLboolean 2710_mesa_meta_check_generate_mipmap_fallback(struct gl_context *ctx, GLenum target, 2711 struct gl_texture_object *texObj) 2712{ 2713 const GLuint fboSave = ctx->DrawBuffer->Name; 2714 struct gen_mipmap_state *mipmap = &ctx->Meta->Mipmap; 2715 struct gl_texture_image *baseImage; 2716 GLuint srcLevel; 2717 GLenum status; 2718 2719 /* check for fallbacks */ 2720 if (!ctx->Extensions.EXT_framebuffer_object || 2721 target == GL_TEXTURE_3D || 2722 target == GL_TEXTURE_1D_ARRAY || 2723 target == GL_TEXTURE_2D_ARRAY) { 2724 return GL_TRUE; 2725 } 2726 2727 srcLevel = texObj->BaseLevel; 2728 baseImage = _mesa_select_tex_image(ctx, texObj, target, srcLevel); 2729 if (!baseImage || _mesa_is_format_compressed(baseImage->TexFormat)) { 2730 return GL_TRUE; 2731 } 2732 2733 if (_mesa_get_format_color_encoding(baseImage->TexFormat) == GL_SRGB && 2734 !ctx->Extensions.EXT_texture_sRGB_decode) { 2735 /* The texture format is sRGB but we can't turn off sRGB->linear 2736 * texture sample conversion. So we won't be able to generate the 2737 * right colors when rendering. Need to use a fallback. 2738 */ 2739 return GL_TRUE; 2740 } 2741 2742 /* 2743 * Test that we can actually render in the texture's format. 2744 */ 2745 if (!mipmap->FBO) 2746 _mesa_GenFramebuffersEXT(1, &mipmap->FBO); 2747 _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, mipmap->FBO); 2748 2749 if (target == GL_TEXTURE_1D) { 2750 _mesa_FramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT, 2751 GL_COLOR_ATTACHMENT0_EXT, 2752 target, texObj->Name, srcLevel); 2753 } 2754#if 0 2755 /* other work is needed to enable 3D mipmap generation */ 2756 else if (target == GL_TEXTURE_3D) { 2757 GLint zoffset = 0; 2758 _mesa_FramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT, 2759 GL_COLOR_ATTACHMENT0_EXT, 2760 target, texObj->Name, srcLevel, zoffset); 2761 } 2762#endif 2763 else { 2764 /* 2D / cube */ 2765 _mesa_FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, 2766 GL_COLOR_ATTACHMENT0_EXT, 2767 target, texObj->Name, srcLevel); 2768 } 2769 2770 status = _mesa_CheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); 2771 2772 _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboSave); 2773 2774 if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { 2775 return GL_TRUE; 2776 } 2777 2778 return GL_FALSE; 2779} 2780 2781 2782/** 2783 * Compute the texture coordinates for the four vertices of a quad for 2784 * drawing a 2D texture image or slice of a cube/3D texture. 2785 * \param faceTarget GL_TEXTURE_1D/2D/3D or cube face name 2786 * \param slice slice of a 1D/2D array texture or 3D texture 2787 * \param width width of the texture image 2788 * \param height height of the texture image 2789 * \param coords0/1/2/3 returns the computed texcoords 2790 */ 2791static void 2792setup_texture_coords(GLenum faceTarget, 2793 GLint slice, 2794 GLint width, 2795 GLint height, 2796 GLfloat coords0[3], 2797 GLfloat coords1[3], 2798 GLfloat coords2[3], 2799 GLfloat coords3[3]) 2800{ 2801 static const GLfloat st[4][2] = { 2802 {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f} 2803 }; 2804 GLuint i; 2805 GLfloat r; 2806 2807 switch (faceTarget) { 2808 case GL_TEXTURE_1D: 2809 case GL_TEXTURE_2D: 2810 case GL_TEXTURE_3D: 2811 case GL_TEXTURE_2D_ARRAY: 2812 if (faceTarget == GL_TEXTURE_3D) 2813 r = 1.0F / slice; 2814 else if (faceTarget == GL_TEXTURE_2D_ARRAY) 2815 r = slice; 2816 else 2817 r = 0.0F; 2818 coords0[0] = 0.0F; /* s */ 2819 coords0[1] = 0.0F; /* t */ 2820 coords0[2] = r; /* r */ 2821 coords1[0] = 1.0F; 2822 coords1[1] = 0.0F; 2823 coords1[2] = r; 2824 coords2[0] = 1.0F; 2825 coords2[1] = 1.0F; 2826 coords2[2] = r; 2827 coords3[0] = 0.0F; 2828 coords3[1] = 1.0F; 2829 coords3[2] = r; 2830 break; 2831 case GL_TEXTURE_RECTANGLE_ARB: 2832 coords0[0] = 0.0F; /* s */ 2833 coords0[1] = 0.0F; /* t */ 2834 coords0[2] = 0.0F; /* r */ 2835 coords1[0] = width; 2836 coords1[1] = 0.0F; 2837 coords1[2] = 0.0F; 2838 coords2[0] = width; 2839 coords2[1] = height; 2840 coords2[2] = 0.0F; 2841 coords3[0] = 0.0F; 2842 coords3[1] = height; 2843 coords3[2] = 0.0F; 2844 break; 2845 case GL_TEXTURE_1D_ARRAY: 2846 coords0[0] = 0.0F; /* s */ 2847 coords0[1] = slice; /* t */ 2848 coords0[2] = 0.0F; /* r */ 2849 coords1[0] = 1.0f; 2850 coords1[1] = slice; 2851 coords1[2] = 0.0F; 2852 coords2[0] = 1.0F; 2853 coords2[1] = slice; 2854 coords2[2] = 0.0F; 2855 coords3[0] = 0.0F; 2856 coords3[1] = slice; 2857 coords3[2] = 0.0F; 2858 break; 2859 2860 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 2861 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 2862 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 2863 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 2864 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 2865 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 2866 /* loop over quad verts */ 2867 for (i = 0; i < 4; i++) { 2868 /* Compute sc = +/-scale and tc = +/-scale. 2869 * Not +/-1 to avoid cube face selection ambiguity near the edges, 2870 * though that can still sometimes happen with this scale factor... 2871 */ 2872 const GLfloat scale = 0.9999f; 2873 const GLfloat sc = (2.0f * st[i][0] - 1.0f) * scale; 2874 const GLfloat tc = (2.0f * st[i][1] - 1.0f) * scale; 2875 GLfloat *coord; 2876 2877 switch (i) { 2878 case 0: 2879 coord = coords0; 2880 break; 2881 case 1: 2882 coord = coords1; 2883 break; 2884 case 2: 2885 coord = coords2; 2886 break; 2887 case 3: 2888 coord = coords3; 2889 break; 2890 default: 2891 assert(0); 2892 } 2893 2894 switch (faceTarget) { 2895 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 2896 coord[0] = 1.0f; 2897 coord[1] = -tc; 2898 coord[2] = -sc; 2899 break; 2900 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 2901 coord[0] = -1.0f; 2902 coord[1] = -tc; 2903 coord[2] = sc; 2904 break; 2905 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 2906 coord[0] = sc; 2907 coord[1] = 1.0f; 2908 coord[2] = tc; 2909 break; 2910 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 2911 coord[0] = sc; 2912 coord[1] = -1.0f; 2913 coord[2] = -tc; 2914 break; 2915 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 2916 coord[0] = sc; 2917 coord[1] = -tc; 2918 coord[2] = 1.0f; 2919 break; 2920 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 2921 coord[0] = -sc; 2922 coord[1] = -tc; 2923 coord[2] = -1.0f; 2924 break; 2925 default: 2926 assert(0); 2927 } 2928 } 2929 break; 2930 default: 2931 assert(0 && "unexpected target in meta setup_texture_coords()"); 2932 } 2933} 2934 2935 2936static void 2937setup_ff_generate_mipmap(struct gl_context *ctx, 2938 struct gen_mipmap_state *mipmap) 2939{ 2940 struct vertex { 2941 GLfloat x, y, tex[3]; 2942 }; 2943 2944 if (mipmap->ArrayObj == 0) { 2945 /* one-time setup */ 2946 /* create vertex array object */ 2947 _mesa_GenVertexArraysAPPLE(1, &mipmap->ArrayObj); 2948 _mesa_BindVertexArrayAPPLE(mipmap->ArrayObj); 2949 2950 /* create vertex array buffer */ 2951 _mesa_GenBuffersARB(1, &mipmap->VBO); 2952 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, mipmap->VBO); 2953 /* setup vertex arrays */ 2954 _mesa_VertexPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(x)); 2955 _mesa_TexCoordPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(tex)); 2956 _mesa_EnableClientState(GL_VERTEX_ARRAY); 2957 _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY); 2958 } 2959 2960 /* setup projection matrix */ 2961 _mesa_MatrixMode(GL_PROJECTION); 2962 _mesa_LoadIdentity(); 2963 _mesa_Ortho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); 2964} 2965 2966 2967static void 2968setup_glsl_generate_mipmap(struct gl_context *ctx, 2969 struct gen_mipmap_state *mipmap) 2970{ 2971 struct vertex { 2972 GLfloat x, y, tex[3]; 2973 }; 2974 2975 static const char *vs_source = 2976 "attribute vec2 position;\n" 2977 "attribute vec3 textureCoords;\n" 2978 "varying vec3 texCoords;\n" 2979 "void main()\n" 2980 "{\n" 2981 " texCoords = textureCoords;\n" 2982 " gl_Position = vec4(position, 0.0, 1.0);\n" 2983 "}\n"; 2984 static const char *fs_source = 2985 "uniform sampler2D tex2d;\n" 2986 "varying vec3 texCoords;\n" 2987 "void main()\n" 2988 "{\n" 2989 " gl_FragColor = texture2D(tex2d, texCoords.xy);\n" 2990 "}\n"; 2991 2992 static const char *vs_int_source = 2993 "#version 130\n" 2994 "in vec2 position;\n" 2995 "in vec3 textureCoords;\n" 2996 "out vec3 texCoords;\n" 2997 "void main()\n" 2998 "{\n" 2999 " texCoords = textureCoords;\n" 3000 " gl_Position = gl_Vertex;\n" 3001 "}\n"; 3002 static const char *fs_int_source = 3003 "#version 130\n" 3004 "uniform isampler2D tex2d;\n" 3005 "in vec3 texCoords;\n" 3006 "out ivec4 out_color;\n" 3007 "\n" 3008 "void main()\n" 3009 "{\n" 3010 " out_color = texture(tex2d, texCoords.xy);\n" 3011 "}\n"; 3012 GLuint vs, fs; 3013 3014 /* Check if already initialized */ 3015 if (mipmap->ArrayObj != 0) 3016 return; 3017 /* create vertex array object */ 3018 _mesa_GenVertexArrays(1, &mipmap->ArrayObj); 3019 _mesa_BindVertexArray(mipmap->ArrayObj); 3020 3021 /* create vertex array buffer */ 3022 _mesa_GenBuffersARB(1, &mipmap->VBO); 3023 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, mipmap->VBO); 3024 3025 /* setup vertex arrays */ 3026 _mesa_VertexAttribPointerARB(0, 2, GL_FLOAT, GL_FALSE, 3027 sizeof(struct vertex), OFFSET(x)); 3028 _mesa_VertexAttribPointerARB(1, 3, GL_FLOAT, GL_FALSE, 3029 sizeof(struct vertex), OFFSET(tex)); 3030 3031 vs = compile_shader_with_debug(ctx, GL_VERTEX_SHADER, vs_source); 3032 fs = compile_shader_with_debug(ctx, GL_FRAGMENT_SHADER, fs_source); 3033 3034 mipmap->ShaderProg = _mesa_CreateProgramObjectARB(); 3035 _mesa_AttachShader(mipmap->ShaderProg, fs); 3036 _mesa_DeleteObjectARB(fs); 3037 _mesa_AttachShader(mipmap->ShaderProg, vs); 3038 _mesa_DeleteObjectARB(vs); 3039 _mesa_BindAttribLocationARB(mipmap->ShaderProg, 0, "position"); 3040 _mesa_BindAttribLocationARB(mipmap->ShaderProg, 1, "texcoords"); 3041 _mesa_EnableVertexAttribArrayARB(0); 3042 _mesa_EnableVertexAttribArrayARB(1); 3043 link_program_with_debug(ctx, mipmap->ShaderProg); 3044 3045 if ((_mesa_is_desktop_gl(ctx) && ctx->Const.GLSLVersion >= 130) || 3046 _mesa_is_gles3(ctx)){ 3047 vs = compile_shader_with_debug(ctx, GL_VERTEX_SHADER, vs_int_source); 3048 fs = compile_shader_with_debug(ctx, GL_FRAGMENT_SHADER, fs_int_source); 3049 3050 mipmap->IntegerShaderProg = _mesa_CreateProgramObjectARB(); 3051 _mesa_AttachShader(mipmap->IntegerShaderProg, fs); 3052 _mesa_DeleteObjectARB(fs); 3053 _mesa_AttachShader(mipmap->IntegerShaderProg, vs); 3054 _mesa_DeleteObjectARB(vs); 3055 _mesa_BindAttribLocationARB(mipmap->IntegerShaderProg, 0, "position"); 3056 _mesa_BindAttribLocationARB(mipmap->IntegerShaderProg, 1, "texcoords"); 3057 3058 /* Note that user-defined out attributes get automatically assigned 3059 * locations starting from 0, so we don't need to explicitly 3060 * BindFragDataLocation to 0. 3061 */ 3062 link_program_with_debug(ctx, mipmap->IntegerShaderProg); 3063 } 3064} 3065 3066 3067static void 3068meta_glsl_generate_mipmap_cleanup(struct gl_context *ctx, 3069 struct gen_mipmap_state *mipmap) 3070{ 3071 if (mipmap->ArrayObj == 0) 3072 return; 3073 _mesa_DeleteVertexArraysAPPLE(1, &mipmap->ArrayObj); 3074 mipmap->ArrayObj = 0; 3075 _mesa_DeleteBuffersARB(1, &mipmap->VBO); 3076 mipmap->VBO = 0; 3077 _mesa_DeleteObjectARB(mipmap->ShaderProg); 3078 mipmap->ShaderProg = 0; 3079 3080 if (mipmap->IntegerShaderProg) { 3081 _mesa_DeleteObjectARB(mipmap->IntegerShaderProg); 3082 mipmap->IntegerShaderProg = 0; 3083 } 3084} 3085 3086 3087/** 3088 * Called via ctx->Driver.GenerateMipmap() 3089 * Note: We don't yet support 3D textures, 1D/2D array textures or texture 3090 * borders. 3091 */ 3092void 3093_mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target, 3094 struct gl_texture_object *texObj) 3095{ 3096 struct gen_mipmap_state *mipmap = &ctx->Meta->Mipmap; 3097 struct vertex { 3098 GLfloat x, y, tex[3]; 3099 }; 3100 struct vertex verts[4]; 3101 const GLuint baseLevel = texObj->BaseLevel; 3102 const GLuint maxLevel = texObj->MaxLevel; 3103 const GLint maxLevelSave = texObj->MaxLevel; 3104 const GLboolean genMipmapSave = texObj->GenerateMipmap; 3105 const GLenum srgbBufferSave = ctx->Color.sRGBEnabled; 3106 const GLuint fboSave = ctx->DrawBuffer->Name; 3107 const GLuint currentTexUnitSave = ctx->Texture.CurrentUnit; 3108 const GLboolean use_glsl_version = ctx->Extensions.ARB_vertex_shader && 3109 ctx->Extensions.ARB_fragment_shader && 3110 (ctx->API != API_OPENGLES); 3111 GLenum faceTarget; 3112 GLuint dstLevel; 3113 const GLint slice = 0; 3114 GLuint samplerSave; 3115 3116 if (_mesa_meta_check_generate_mipmap_fallback(ctx, target, texObj)) { 3117 _mesa_generate_mipmap(ctx, target, texObj); 3118 return; 3119 } 3120 3121 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && 3122 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) { 3123 faceTarget = target; 3124 target = GL_TEXTURE_CUBE_MAP; 3125 } 3126 else { 3127 faceTarget = target; 3128 } 3129 3130 _mesa_meta_begin(ctx, MESA_META_ALL); 3131 3132 /* Choose between glsl version and fixed function version of 3133 * GenerateMipmap function. 3134 */ 3135 if (use_glsl_version) { 3136 setup_glsl_generate_mipmap(ctx, mipmap); 3137 3138 if (texObj->_IsIntegerFormat) 3139 _mesa_UseProgramObjectARB(mipmap->IntegerShaderProg); 3140 else 3141 _mesa_UseProgramObjectARB(mipmap->ShaderProg); 3142 } 3143 else { 3144 setup_ff_generate_mipmap(ctx, mipmap); 3145 _mesa_set_enable(ctx, target, GL_TRUE); 3146 } 3147 3148 _mesa_BindVertexArray(mipmap->ArrayObj); 3149 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, mipmap->VBO); 3150 3151 samplerSave = ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler ? 3152 ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler->Name : 0; 3153 3154 if (currentTexUnitSave != 0) 3155 _mesa_BindTexture(target, texObj->Name); 3156 3157 if (!mipmap->FBO) { 3158 _mesa_GenFramebuffersEXT(1, &mipmap->FBO); 3159 } 3160 3161 if (!mipmap->Sampler) { 3162 _mesa_GenSamplers(1, &mipmap->Sampler); 3163 _mesa_BindSampler(ctx->Texture.CurrentUnit, mipmap->Sampler); 3164 3165 if (use_glsl_version && texObj->_IsIntegerFormat) 3166 _mesa_SamplerParameteri(mipmap->Sampler, 3167 GL_TEXTURE_MIN_FILTER, 3168 GL_NEAREST_MIPMAP_NEAREST); 3169 else 3170 _mesa_SamplerParameteri(mipmap->Sampler, 3171 GL_TEXTURE_MIN_FILTER, 3172 GL_LINEAR_MIPMAP_LINEAR); 3173 3174 _mesa_SamplerParameteri(mipmap->Sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 3175 _mesa_SamplerParameteri(mipmap->Sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 3176 _mesa_SamplerParameteri(mipmap->Sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 3177 _mesa_SamplerParameteri(mipmap->Sampler, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); 3178 3179 /* We don't want to encode or decode sRGB values; treat them as linear. 3180 * This is not technically correct for GLES3 but we don't get any API 3181 * error at the moment. 3182 */ 3183 if (ctx->Extensions.EXT_texture_sRGB_decode) { 3184 _mesa_SamplerParameteri(mipmap->Sampler, GL_TEXTURE_SRGB_DECODE_EXT, 3185 GL_SKIP_DECODE_EXT); 3186 } 3187 3188 } else { 3189 _mesa_BindSampler(ctx->Texture.CurrentUnit, mipmap->Sampler); 3190 } 3191 3192 _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, mipmap->FBO); 3193 3194 if (ctx->API == API_OPENGL || ctx->API == API_OPENGLES) 3195 _mesa_TexParameteri(target, GL_GENERATE_MIPMAP, GL_FALSE); 3196 else 3197 assert(!genMipmapSave); 3198 3199 if ((ctx->Extensions.EXT_framebuffer_sRGB && 3200 _mesa_is_desktop_gl(ctx)) || 3201 _mesa_is_gles3(ctx)) { 3202 _mesa_set_enable(ctx, GL_FRAMEBUFFER_SRGB_EXT, GL_FALSE); 3203 } 3204 3205 /* Setup texture coordinates */ 3206 setup_texture_coords(faceTarget, 3207 slice, 3208 0, 0, /* width, height never used here */ 3209 verts[0].tex, 3210 verts[1].tex, 3211 verts[2].tex, 3212 verts[3].tex); 3213 3214 /* setup vertex positions */ 3215 verts[0].x = -1.0F; 3216 verts[0].y = -1.0F; 3217 verts[1].x = 1.0F; 3218 verts[1].y = -1.0F; 3219 verts[2].x = 1.0F; 3220 verts[2].y = 1.0F; 3221 verts[3].x = -1.0F; 3222 verts[3].y = 1.0F; 3223 3224 /* upload vertex data */ 3225 _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts), 3226 verts, GL_DYNAMIC_DRAW_ARB); 3227 3228 /* texture is already locked, unlock now */ 3229 _mesa_unlock_texture(ctx, texObj); 3230 3231 for (dstLevel = baseLevel + 1; dstLevel <= maxLevel; dstLevel++) { 3232 const struct gl_texture_image *srcImage; 3233 const GLuint srcLevel = dstLevel - 1; 3234 GLsizei srcWidth, srcHeight, srcDepth; 3235 GLsizei dstWidth, dstHeight, dstDepth; 3236 GLenum status; 3237 3238 srcImage = _mesa_select_tex_image(ctx, texObj, faceTarget, srcLevel); 3239 assert(srcImage->Border == 0); 3240 3241 /* src size */ 3242 srcWidth = srcImage->Width; 3243 srcHeight = srcImage->Height; 3244 srcDepth = srcImage->Depth; 3245 3246 /* new dst size */ 3247 dstWidth = MAX2(1, srcWidth / 2); 3248 dstHeight = MAX2(1, srcHeight / 2); 3249 dstDepth = MAX2(1, srcDepth / 2); 3250 3251 if (dstWidth == srcImage->Width && 3252 dstHeight == srcImage->Height && 3253 dstDepth == srcImage->Depth) { 3254 /* all done */ 3255 break; 3256 } 3257 3258 /* Allocate storage for the destination mipmap image(s) */ 3259 3260 /* Set MaxLevel large enough to hold the new level when we allocate it */ 3261 _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, dstLevel); 3262 3263 if (!_mesa_prepare_mipmap_level(ctx, texObj, dstLevel, 3264 dstWidth, dstHeight, dstDepth, 3265 srcImage->Border, 3266 srcImage->InternalFormat, 3267 srcImage->TexFormat)) { 3268 /* All done. We either ran out of memory or we would go beyond the 3269 * last valid level of an immutable texture if we continued. 3270 */ 3271 break; 3272 } 3273 3274 /* limit minification to src level */ 3275 _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, srcLevel); 3276 3277 /* Set to draw into the current dstLevel */ 3278 if (target == GL_TEXTURE_1D) { 3279 _mesa_FramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT, 3280 GL_COLOR_ATTACHMENT0_EXT, 3281 target, 3282 texObj->Name, 3283 dstLevel); 3284 } 3285 else if (target == GL_TEXTURE_3D) { 3286 GLint zoffset = 0; /* XXX unfinished */ 3287 _mesa_FramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT, 3288 GL_COLOR_ATTACHMENT0_EXT, 3289 target, 3290 texObj->Name, 3291 dstLevel, zoffset); 3292 } 3293 else { 3294 /* 2D / cube */ 3295 _mesa_FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, 3296 GL_COLOR_ATTACHMENT0_EXT, 3297 faceTarget, 3298 texObj->Name, 3299 dstLevel); 3300 } 3301 3302 _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0_EXT); 3303 3304 /* sanity check */ 3305 status = _mesa_CheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); 3306 if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { 3307 _mesa_problem(ctx, "Unexpected incomplete framebuffer in " 3308 "_mesa_meta_GenerateMipmap()"); 3309 break; 3310 } 3311 3312 assert(dstWidth == ctx->DrawBuffer->Width); 3313 assert(dstHeight == ctx->DrawBuffer->Height); 3314 3315 /* setup viewport */ 3316 _mesa_set_viewport(ctx, 0, 0, dstWidth, dstHeight); 3317 3318 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 3319 } 3320 3321 if (ctx->Extensions.EXT_framebuffer_sRGB && srgbBufferSave) { 3322 _mesa_set_enable(ctx, GL_FRAMEBUFFER_SRGB_EXT, GL_TRUE); 3323 } 3324 3325 _mesa_lock_texture(ctx, texObj); /* relock */ 3326 3327 _mesa_BindSampler(ctx->Texture.CurrentUnit, samplerSave); 3328 3329 _mesa_meta_end(ctx); 3330 3331 _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, maxLevelSave); 3332 if (genMipmapSave) 3333 _mesa_TexParameteri(target, GL_GENERATE_MIPMAP, genMipmapSave); 3334 3335 _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboSave); 3336} 3337 3338 3339/** 3340 * Determine the GL data type to use for the temporary image read with 3341 * ReadPixels() and passed to Tex[Sub]Image(). 3342 */ 3343static GLenum 3344get_temp_image_type(struct gl_context *ctx, gl_format format) 3345{ 3346 GLenum baseFormat; 3347 3348 baseFormat = _mesa_get_format_base_format(format); 3349 3350 switch (baseFormat) { 3351 case GL_RGBA: 3352 case GL_RGB: 3353 case GL_RG: 3354 case GL_RED: 3355 case GL_ALPHA: 3356 case GL_LUMINANCE: 3357 case GL_LUMINANCE_ALPHA: 3358 case GL_INTENSITY: 3359 if (ctx->DrawBuffer->Visual.redBits <= 8) 3360 return GL_UNSIGNED_BYTE; 3361 else if (ctx->DrawBuffer->Visual.redBits <= 16) 3362 return GL_UNSIGNED_SHORT; 3363 else 3364 return _mesa_get_format_datatype(format); 3365 case GL_DEPTH_COMPONENT: 3366 return GL_UNSIGNED_INT; 3367 case GL_DEPTH_STENCIL: 3368 return GL_UNSIGNED_INT_24_8; 3369 default: 3370 _mesa_problem(ctx, "Unexpected format %d in get_temp_image_type()", 3371 baseFormat); 3372 return 0; 3373 } 3374} 3375 3376 3377/** 3378 * Helper for _mesa_meta_CopyTexSubImage1/2/3D() functions. 3379 * Have to be careful with locking and meta state for pixel transfer. 3380 */ 3381void 3382_mesa_meta_CopyTexSubImage(struct gl_context *ctx, GLuint dims, 3383 struct gl_texture_image *texImage, 3384 GLint xoffset, GLint yoffset, GLint zoffset, 3385 struct gl_renderbuffer *rb, 3386 GLint x, GLint y, 3387 GLsizei width, GLsizei height) 3388{ 3389 struct gl_texture_object *texObj = texImage->TexObject; 3390 GLenum format, type; 3391 GLint bpp; 3392 void *buf; 3393 3394 /* Choose format/type for temporary image buffer */ 3395 format = _mesa_get_format_base_format(texImage->TexFormat); 3396 if (format == GL_LUMINANCE || 3397 format == GL_LUMINANCE_ALPHA || 3398 format == GL_INTENSITY) { 3399 /* We don't want to use GL_LUMINANCE, GL_INTENSITY, etc. for the 3400 * temp image buffer because glReadPixels will do L=R+G+B which is 3401 * not what we want (should be L=R). 3402 */ 3403 format = GL_RGBA; 3404 } 3405 3406 type = get_temp_image_type(ctx, texImage->TexFormat); 3407 if (_mesa_is_format_integer_color(texImage->TexFormat)) { 3408 format = _mesa_base_format_to_integer_format(format); 3409 } 3410 bpp = _mesa_bytes_per_pixel(format, type); 3411 if (bpp <= 0) { 3412 _mesa_problem(ctx, "Bad bpp in _mesa_meta_CopyTexSubImage()"); 3413 return; 3414 } 3415 3416 /* 3417 * Alloc image buffer (XXX could use a PBO) 3418 */ 3419 buf = malloc(width * height * bpp); 3420 if (!buf) { 3421 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage%uD", dims); 3422 return; 3423 } 3424 3425 _mesa_unlock_texture(ctx, texObj); /* need to unlock first */ 3426 3427 /* 3428 * Read image from framebuffer (disable pixel transfer ops) 3429 */ 3430 _mesa_meta_begin(ctx, MESA_META_PIXEL_STORE | MESA_META_PIXEL_TRANSFER); 3431 ctx->Driver.ReadPixels(ctx, x, y, width, height, 3432 format, type, &ctx->Pack, buf); 3433 _mesa_meta_end(ctx); 3434 3435 _mesa_update_state(ctx); /* to update pixel transfer state */ 3436 3437 /* 3438 * Store texture data (with pixel transfer ops) 3439 */ 3440 _mesa_meta_begin(ctx, MESA_META_PIXEL_STORE); 3441 3442 ctx->Driver.TexSubImage(ctx, dims, texImage, 3443 xoffset, yoffset, zoffset, width, height, 1, 3444 format, type, buf, &ctx->Unpack); 3445 3446 _mesa_meta_end(ctx); 3447 3448 _mesa_lock_texture(ctx, texObj); /* re-lock */ 3449 3450 free(buf); 3451} 3452 3453 3454/** 3455 * Decompress a texture image by drawing a quad with the compressed 3456 * texture and reading the pixels out of the color buffer. 3457 * \param slice which slice of a 3D texture or layer of a 1D/2D texture 3458 * \param destFormat format, ala glReadPixels 3459 * \param destType type, ala glReadPixels 3460 * \param dest destination buffer 3461 * \param destRowLength dest image rowLength (ala GL_PACK_ROW_LENGTH) 3462 */ 3463static void 3464decompress_texture_image(struct gl_context *ctx, 3465 struct gl_texture_image *texImage, 3466 GLuint slice, 3467 GLenum destFormat, GLenum destType, 3468 GLvoid *dest) 3469{ 3470 struct decompress_state *decompress = &ctx->Meta->Decompress; 3471 struct gl_texture_object *texObj = texImage->TexObject; 3472 const GLint width = texImage->Width; 3473 const GLint height = texImage->Height; 3474 const GLenum target = texObj->Target; 3475 GLenum faceTarget; 3476 struct vertex { 3477 GLfloat x, y, tex[3]; 3478 }; 3479 struct vertex verts[4]; 3480 GLuint fboDrawSave, fboReadSave; 3481 GLuint rbSave; 3482 GLuint samplerSave; 3483 3484 if (slice > 0) { 3485 assert(target == GL_TEXTURE_3D || 3486 target == GL_TEXTURE_2D_ARRAY); 3487 } 3488 3489 if (target == GL_TEXTURE_CUBE_MAP) { 3490 faceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + texImage->Face; 3491 } 3492 else { 3493 faceTarget = target; 3494 } 3495 3496 /* save fbo bindings (not saved by _mesa_meta_begin()) */ 3497 fboDrawSave = ctx->DrawBuffer->Name; 3498 fboReadSave = ctx->ReadBuffer->Name; 3499 rbSave = ctx->CurrentRenderbuffer ? ctx->CurrentRenderbuffer->Name : 0; 3500 3501 _mesa_meta_begin(ctx, MESA_META_ALL & ~MESA_META_PIXEL_STORE); 3502 3503 samplerSave = ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler ? 3504 ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler->Name : 0; 3505 3506 /* Create/bind FBO/renderbuffer */ 3507 if (decompress->FBO == 0) { 3508 _mesa_GenFramebuffersEXT(1, &decompress->FBO); 3509 _mesa_GenRenderbuffersEXT(1, &decompress->RBO); 3510 _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, decompress->FBO); 3511 _mesa_BindRenderbufferEXT(GL_RENDERBUFFER_EXT, decompress->RBO); 3512 _mesa_FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, 3513 GL_COLOR_ATTACHMENT0_EXT, 3514 GL_RENDERBUFFER_EXT, 3515 decompress->RBO); 3516 } 3517 else { 3518 _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, decompress->FBO); 3519 } 3520 3521 /* alloc dest surface */ 3522 if (width > decompress->Width || height > decompress->Height) { 3523 _mesa_BindRenderbufferEXT(GL_RENDERBUFFER_EXT, decompress->RBO); 3524 _mesa_RenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA, 3525 width, height); 3526 decompress->Width = width; 3527 decompress->Height = height; 3528 } 3529 3530 /* setup VBO data */ 3531 if (decompress->ArrayObj == 0) { 3532 /* create vertex array object */ 3533 _mesa_GenVertexArrays(1, &decompress->ArrayObj); 3534 _mesa_BindVertexArray(decompress->ArrayObj); 3535 3536 /* create vertex array buffer */ 3537 _mesa_GenBuffersARB(1, &decompress->VBO); 3538 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, decompress->VBO); 3539 _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts), 3540 NULL, GL_DYNAMIC_DRAW_ARB); 3541 3542 /* setup vertex arrays */ 3543 _mesa_VertexPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(x)); 3544 _mesa_TexCoordPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(tex)); 3545 _mesa_EnableClientState(GL_VERTEX_ARRAY); 3546 _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY); 3547 } 3548 else { 3549 _mesa_BindVertexArray(decompress->ArrayObj); 3550 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, decompress->VBO); 3551 } 3552 3553 if (!decompress->Sampler) { 3554 _mesa_GenSamplers(1, &decompress->Sampler); 3555 _mesa_BindSampler(ctx->Texture.CurrentUnit, decompress->Sampler); 3556 /* nearest filtering */ 3557 _mesa_SamplerParameteri(decompress->Sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3558 _mesa_SamplerParameteri(decompress->Sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3559 /* No sRGB decode or encode.*/ 3560 if (ctx->Extensions.EXT_texture_sRGB_decode) { 3561 _mesa_SamplerParameteri(decompress->Sampler, GL_TEXTURE_SRGB_DECODE_EXT, 3562 GL_SKIP_DECODE_EXT); 3563 } 3564 3565 } else { 3566 _mesa_BindSampler(ctx->Texture.CurrentUnit, decompress->Sampler); 3567 } 3568 3569 setup_texture_coords(faceTarget, slice, width, height, 3570 verts[0].tex, 3571 verts[1].tex, 3572 verts[2].tex, 3573 verts[3].tex); 3574 3575 /* setup vertex positions */ 3576 verts[0].x = 0.0F; 3577 verts[0].y = 0.0F; 3578 verts[1].x = width; 3579 verts[1].y = 0.0F; 3580 verts[2].x = width; 3581 verts[2].y = height; 3582 verts[3].x = 0.0F; 3583 verts[3].y = height; 3584 3585 /* upload new vertex data */ 3586 _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); 3587 3588 /* setup texture state */ 3589 _mesa_BindTexture(target, texObj->Name); 3590 _mesa_set_enable(ctx, target, GL_TRUE); 3591 3592 { 3593 /* save texture object state */ 3594 const GLint baseLevelSave = texObj->BaseLevel; 3595 const GLint maxLevelSave = texObj->MaxLevel; 3596 3597 /* restrict sampling to the texture level of interest */ 3598 if (target != GL_TEXTURE_RECTANGLE_ARB) { 3599 _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, texImage->Level); 3600 _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, texImage->Level); 3601 } 3602 3603 /* No sRGB decode or encode.*/ 3604 if (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_framebuffer_sRGB 3605 || _mesa_is_gles3(ctx)) { 3606 _mesa_set_enable(ctx, GL_FRAMEBUFFER_SRGB_EXT, GL_FALSE); 3607 } 3608 3609 /* render quad w/ texture into renderbuffer */ 3610 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 3611 3612 /* Restore texture object state, the texture binding will 3613 * be restored by _mesa_meta_end(). 3614 */ 3615 if (target != GL_TEXTURE_RECTANGLE_ARB) { 3616 _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, baseLevelSave); 3617 _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, maxLevelSave); 3618 } 3619 3620 } 3621 3622 /* read pixels from renderbuffer */ 3623 { 3624 GLenum baseTexFormat = texImage->_BaseFormat; 3625 3626 /* The pixel transfer state will be set to default values at this point 3627 * (see MESA_META_PIXEL_TRANSFER) so pixel transfer ops are effectively 3628 * turned off (as required by glGetTexImage) but we need to handle some 3629 * special cases. In particular, single-channel texture values are 3630 * returned as red and two-channel texture values are returned as 3631 * red/alpha. 3632 */ 3633 if (baseTexFormat == GL_LUMINANCE || 3634 baseTexFormat == GL_LUMINANCE_ALPHA || 3635 baseTexFormat == GL_INTENSITY) { 3636 /* Green and blue must be zero */ 3637 _mesa_PixelTransferf(GL_GREEN_SCALE, 0.0f); 3638 _mesa_PixelTransferf(GL_BLUE_SCALE, 0.0f); 3639 } 3640 3641 _mesa_ReadPixels(0, 0, width, height, destFormat, destType, dest); 3642 } 3643 3644 /* disable texture unit */ 3645 _mesa_set_enable(ctx, target, GL_FALSE); 3646 3647 _mesa_BindSampler(ctx->Texture.CurrentUnit, samplerSave); 3648 3649 _mesa_meta_end(ctx); 3650 3651 /* restore fbo bindings */ 3652 if (fboDrawSave == fboReadSave) { 3653 _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboDrawSave); 3654 } 3655 else { 3656 _mesa_BindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fboDrawSave); 3657 _mesa_BindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, fboReadSave); 3658 } 3659 _mesa_BindRenderbufferEXT(GL_RENDERBUFFER_EXT, rbSave); 3660} 3661 3662 3663/** 3664 * This is just a wrapper around _mesa_get_tex_image() and 3665 * decompress_texture_image(). Meta functions should not be directly called 3666 * from core Mesa. 3667 */ 3668void 3669_mesa_meta_GetTexImage(struct gl_context *ctx, 3670 GLenum format, GLenum type, GLvoid *pixels, 3671 struct gl_texture_image *texImage) 3672{ 3673 /* We can only use the decompress-with-blit method here if the texels are 3674 * unsigned, normalized values. We could handle signed and unnormalized 3675 * with floating point renderbuffers... 3676 */ 3677 if (_mesa_is_format_compressed(texImage->TexFormat) && 3678 _mesa_get_format_datatype(texImage->TexFormat) 3679 == GL_UNSIGNED_NORMALIZED) { 3680 struct gl_texture_object *texObj = texImage->TexObject; 3681 const GLuint slice = 0; /* only 2D compressed textures for now */ 3682 /* Need to unlock the texture here to prevent deadlock... */ 3683 _mesa_unlock_texture(ctx, texObj); 3684 decompress_texture_image(ctx, texImage, slice, format, type, pixels); 3685 /* ... and relock it */ 3686 _mesa_lock_texture(ctx, texObj); 3687 } 3688 else { 3689 _mesa_get_teximage(ctx, format, type, pixels, texImage); 3690 } 3691} 3692 3693 3694/** 3695 * Meta implementation of ctx->Driver.DrawTex() in terms 3696 * of polygon rendering. 3697 */ 3698void 3699_mesa_meta_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, 3700 GLfloat width, GLfloat height) 3701{ 3702#if FEATURE_OES_draw_texture 3703 struct drawtex_state *drawtex = &ctx->Meta->DrawTex; 3704 struct vertex { 3705 GLfloat x, y, z, st[MAX_TEXTURE_UNITS][2]; 3706 }; 3707 struct vertex verts[4]; 3708 GLuint i; 3709 3710 _mesa_meta_begin(ctx, (MESA_META_RASTERIZATION | 3711 MESA_META_SHADER | 3712 MESA_META_TRANSFORM | 3713 MESA_META_VERTEX | 3714 MESA_META_VIEWPORT)); 3715 3716 if (drawtex->ArrayObj == 0) { 3717 /* one-time setup */ 3718 GLint active_texture; 3719 3720 /* create vertex array object */ 3721 _mesa_GenVertexArrays(1, &drawtex->ArrayObj); 3722 _mesa_BindVertexArray(drawtex->ArrayObj); 3723 3724 /* create vertex array buffer */ 3725 _mesa_GenBuffersARB(1, &drawtex->VBO); 3726 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, drawtex->VBO); 3727 _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts), 3728 NULL, GL_DYNAMIC_DRAW_ARB); 3729 3730 /* client active texture is not part of the array object */ 3731 active_texture = ctx->Array.ActiveTexture; 3732 3733 /* setup vertex arrays */ 3734 _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x)); 3735 _mesa_EnableClientState(GL_VERTEX_ARRAY); 3736 for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { 3737 _mesa_ClientActiveTextureARB(GL_TEXTURE0 + i); 3738 _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(st[i])); 3739 _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY); 3740 } 3741 3742 /* restore client active texture */ 3743 _mesa_ClientActiveTextureARB(GL_TEXTURE0 + active_texture); 3744 } 3745 else { 3746 _mesa_BindVertexArray(drawtex->ArrayObj); 3747 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, drawtex->VBO); 3748 } 3749 3750 /* vertex positions, texcoords */ 3751 { 3752 const GLfloat x1 = x + width; 3753 const GLfloat y1 = y + height; 3754 3755 z = CLAMP(z, 0.0, 1.0); 3756 z = invert_z(z); 3757 3758 verts[0].x = x; 3759 verts[0].y = y; 3760 verts[0].z = z; 3761 3762 verts[1].x = x1; 3763 verts[1].y = y; 3764 verts[1].z = z; 3765 3766 verts[2].x = x1; 3767 verts[2].y = y1; 3768 verts[2].z = z; 3769 3770 verts[3].x = x; 3771 verts[3].y = y1; 3772 verts[3].z = z; 3773 3774 for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { 3775 const struct gl_texture_object *texObj; 3776 const struct gl_texture_image *texImage; 3777 GLfloat s, t, s1, t1; 3778 GLuint tw, th; 3779 3780 if (!ctx->Texture.Unit[i]._ReallyEnabled) { 3781 GLuint j; 3782 for (j = 0; j < 4; j++) { 3783 verts[j].st[i][0] = 0.0f; 3784 verts[j].st[i][1] = 0.0f; 3785 } 3786 continue; 3787 } 3788 3789 texObj = ctx->Texture.Unit[i]._Current; 3790 texImage = texObj->Image[0][texObj->BaseLevel]; 3791 tw = texImage->Width2; 3792 th = texImage->Height2; 3793 3794 s = (GLfloat) texObj->CropRect[0] / tw; 3795 t = (GLfloat) texObj->CropRect[1] / th; 3796 s1 = (GLfloat) (texObj->CropRect[0] + texObj->CropRect[2]) / tw; 3797 t1 = (GLfloat) (texObj->CropRect[1] + texObj->CropRect[3]) / th; 3798 3799 verts[0].st[i][0] = s; 3800 verts[0].st[i][1] = t; 3801 3802 verts[1].st[i][0] = s1; 3803 verts[1].st[i][1] = t; 3804 3805 verts[2].st[i][0] = s1; 3806 verts[2].st[i][1] = t1; 3807 3808 verts[3].st[i][0] = s; 3809 verts[3].st[i][1] = t1; 3810 } 3811 3812 _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); 3813 } 3814 3815 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 3816 3817 _mesa_meta_end(ctx); 3818#endif /* FEATURE_OES_draw_texture */ 3819} 3820