meta.c revision d1cf5c77b73d6b2c1cfd79ce0e3363e097177b6a
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 /* Core context requires that front and back mode be the same. 855 */ 856 if (ctx->API == API_OPENGL_CORE) { 857 _mesa_PolygonMode(GL_FRONT_AND_BACK, save->FrontPolygonMode); 858 } else { 859 _mesa_PolygonMode(GL_FRONT, save->FrontPolygonMode); 860 _mesa_PolygonMode(GL_BACK, save->BackPolygonMode); 861 } 862 if (ctx->API == API_OPENGL) { 863 _mesa_set_enable(ctx, GL_POLYGON_STIPPLE, save->PolygonStipple); 864 _mesa_set_enable(ctx, GL_POLYGON_SMOOTH, save->PolygonSmooth); 865 } 866 _mesa_set_enable(ctx, GL_POLYGON_OFFSET_FILL, save->PolygonOffset); 867 _mesa_set_enable(ctx, GL_CULL_FACE, save->PolygonCull); 868 } 869 870 if (state & MESA_META_SCISSOR) { 871 _mesa_set_enable(ctx, GL_SCISSOR_TEST, save->Scissor.Enabled); 872 _mesa_Scissor(save->Scissor.X, save->Scissor.Y, 873 save->Scissor.Width, save->Scissor.Height); 874 } 875 876 if (state & MESA_META_SHADER) { 877 if (ctx->API == API_OPENGL && ctx->Extensions.ARB_vertex_program) { 878 _mesa_set_enable(ctx, GL_VERTEX_PROGRAM_ARB, 879 save->VertexProgramEnabled); 880 _mesa_reference_vertprog(ctx, &ctx->VertexProgram.Current, 881 save->VertexProgram); 882 _mesa_reference_vertprog(ctx, &save->VertexProgram, NULL); 883 } 884 885 if (ctx->API == API_OPENGL && ctx->Extensions.ARB_fragment_program) { 886 _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, 887 save->FragmentProgramEnabled); 888 _mesa_reference_fragprog(ctx, &ctx->FragmentProgram.Current, 889 save->FragmentProgram); 890 _mesa_reference_fragprog(ctx, &save->FragmentProgram, NULL); 891 } 892 893 if (ctx->Extensions.ARB_vertex_shader) 894 _mesa_use_shader_program(ctx, GL_VERTEX_SHADER, save->VertexShader); 895 896 if (ctx->Extensions.ARB_geometry_shader4) 897 _mesa_use_shader_program(ctx, GL_GEOMETRY_SHADER_ARB, 898 save->GeometryShader); 899 900 if (ctx->Extensions.ARB_fragment_shader) 901 _mesa_use_shader_program(ctx, GL_FRAGMENT_SHADER, 902 save->FragmentShader); 903 904 _mesa_reference_shader_program(ctx, &ctx->Shader.ActiveProgram, 905 save->ActiveShader); 906 907 _mesa_reference_shader_program(ctx, &save->VertexShader, NULL); 908 _mesa_reference_shader_program(ctx, &save->GeometryShader, NULL); 909 _mesa_reference_shader_program(ctx, &save->FragmentShader, NULL); 910 _mesa_reference_shader_program(ctx, &save->ActiveShader, NULL); 911 } 912 913 if (state & MESA_META_STENCIL_TEST) { 914 const struct gl_stencil_attrib *stencil = &save->Stencil; 915 916 _mesa_set_enable(ctx, GL_STENCIL_TEST, stencil->Enabled); 917 _mesa_ClearStencil(stencil->Clear); 918 if (ctx->API == API_OPENGL && ctx->Extensions.EXT_stencil_two_side) { 919 _mesa_set_enable(ctx, GL_STENCIL_TEST_TWO_SIDE_EXT, 920 stencil->TestTwoSide); 921 _mesa_ActiveStencilFaceEXT(stencil->ActiveFace 922 ? GL_BACK : GL_FRONT); 923 } 924 /* front state */ 925 _mesa_StencilFuncSeparate(GL_FRONT, 926 stencil->Function[0], 927 stencil->Ref[0], 928 stencil->ValueMask[0]); 929 _mesa_StencilMaskSeparate(GL_FRONT, stencil->WriteMask[0]); 930 _mesa_StencilOpSeparate(GL_FRONT, stencil->FailFunc[0], 931 stencil->ZFailFunc[0], 932 stencil->ZPassFunc[0]); 933 /* back state */ 934 _mesa_StencilFuncSeparate(GL_BACK, 935 stencil->Function[1], 936 stencil->Ref[1], 937 stencil->ValueMask[1]); 938 _mesa_StencilMaskSeparate(GL_BACK, stencil->WriteMask[1]); 939 _mesa_StencilOpSeparate(GL_BACK, stencil->FailFunc[1], 940 stencil->ZFailFunc[1], 941 stencil->ZPassFunc[1]); 942 } 943 944 if (state & MESA_META_TEXTURE) { 945 GLuint u, tgt; 946 947 ASSERT(ctx->Texture.CurrentUnit == 0); 948 949 /* restore texenv for unit[0] */ 950 if (ctx->API == API_OPENGL || ctx->API == API_OPENGLES) { 951 _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, save->EnvMode); 952 } 953 954 /* restore texture objects for unit[0] only */ 955 for (tgt = 0; tgt < NUM_TEXTURE_TARGETS; tgt++) { 956 if (ctx->Texture.Unit[0].CurrentTex[tgt] != save->CurrentTexture[tgt]) { 957 FLUSH_VERTICES(ctx, _NEW_TEXTURE); 958 _mesa_reference_texobj(&ctx->Texture.Unit[0].CurrentTex[tgt], 959 save->CurrentTexture[tgt]); 960 } 961 _mesa_reference_texobj(&save->CurrentTexture[tgt], NULL); 962 } 963 964 /* Restore fixed function texture enables, texgen */ 965 if (ctx->API == API_OPENGL || ctx->API == API_OPENGLES) { 966 for (u = 0; u < ctx->Const.MaxTextureUnits; u++) { 967 if (ctx->Texture.Unit[u].Enabled != save->TexEnabled[u]) { 968 FLUSH_VERTICES(ctx, _NEW_TEXTURE); 969 ctx->Texture.Unit[u].Enabled = save->TexEnabled[u]; 970 } 971 972 if (ctx->Texture.Unit[u].TexGenEnabled != save->TexGenEnabled[u]) { 973 FLUSH_VERTICES(ctx, _NEW_TEXTURE); 974 ctx->Texture.Unit[u].TexGenEnabled = save->TexGenEnabled[u]; 975 } 976 } 977 } 978 979 /* restore current unit state */ 980 _mesa_ActiveTextureARB(GL_TEXTURE0 + save->ActiveUnit); 981 _mesa_ClientActiveTextureARB(GL_TEXTURE0 + save->ClientActiveUnit); 982 } 983 984 if (state & MESA_META_TRANSFORM) { 985 GLuint activeTexture = ctx->Texture.CurrentUnit; 986 _mesa_ActiveTextureARB(GL_TEXTURE0); 987 _mesa_MatrixMode(GL_TEXTURE); 988 _mesa_LoadMatrixf(save->TextureMatrix); 989 _mesa_ActiveTextureARB(GL_TEXTURE0 + activeTexture); 990 991 _mesa_MatrixMode(GL_MODELVIEW); 992 _mesa_LoadMatrixf(save->ModelviewMatrix); 993 994 _mesa_MatrixMode(GL_PROJECTION); 995 _mesa_LoadMatrixf(save->ProjectionMatrix); 996 997 _mesa_MatrixMode(save->MatrixMode); 998 } 999 1000 if (state & MESA_META_CLIP) { 1001 if (save->ClipPlanesEnabled) { 1002 GLuint i; 1003 for (i = 0; i < ctx->Const.MaxClipPlanes; i++) { 1004 if (save->ClipPlanesEnabled & (1 << i)) { 1005 _mesa_set_enable(ctx, GL_CLIP_PLANE0 + i, GL_TRUE); 1006 } 1007 } 1008 } 1009 } 1010 1011 if (state & MESA_META_VERTEX) { 1012 /* restore vertex buffer object */ 1013 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, save->ArrayBufferObj->Name); 1014 _mesa_reference_buffer_object(ctx, &save->ArrayBufferObj, NULL); 1015 1016 /* restore vertex array object */ 1017 _mesa_BindVertexArray(save->ArrayObj->Name); 1018 _mesa_reference_array_object(ctx, &save->ArrayObj, NULL); 1019 } 1020 1021 if (state & MESA_META_VIEWPORT) { 1022 if (save->ViewportX != ctx->Viewport.X || 1023 save->ViewportY != ctx->Viewport.Y || 1024 save->ViewportW != ctx->Viewport.Width || 1025 save->ViewportH != ctx->Viewport.Height) { 1026 _mesa_set_viewport(ctx, save->ViewportX, save->ViewportY, 1027 save->ViewportW, save->ViewportH); 1028 } 1029 _mesa_DepthRange(save->DepthNear, save->DepthFar); 1030 } 1031 1032 if (state & MESA_META_CLAMP_FRAGMENT_COLOR) { 1033 _mesa_ClampColorARB(GL_CLAMP_FRAGMENT_COLOR, save->ClampFragmentColor); 1034 } 1035 1036 if (state & MESA_META_CLAMP_VERTEX_COLOR) { 1037 _mesa_ClampColorARB(GL_CLAMP_VERTEX_COLOR, save->ClampVertexColor); 1038 } 1039 1040 if (state & MESA_META_CONDITIONAL_RENDER) { 1041 if (save->CondRenderQuery) 1042 _mesa_BeginConditionalRender(save->CondRenderQuery->Id, 1043 save->CondRenderMode); 1044 } 1045 1046#if FEATURE_feedback 1047 if (state & MESA_META_SELECT_FEEDBACK) { 1048 if (save->RenderMode == GL_SELECT) { 1049 _mesa_RenderMode(GL_SELECT); 1050 ctx->Select = save->Select; 1051 } else if (save->RenderMode == GL_FEEDBACK) { 1052 _mesa_RenderMode(GL_FEEDBACK); 1053 ctx->Feedback = save->Feedback; 1054 } 1055 } 1056#endif 1057 1058 if (state & MESA_META_MULTISAMPLE) { 1059 if (ctx->Multisample.Enabled != save->MultisampleEnabled) 1060 _mesa_set_enable(ctx, GL_MULTISAMPLE, save->MultisampleEnabled); 1061 } 1062 1063 /* misc */ 1064 if (save->Lighting) { 1065 _mesa_set_enable(ctx, GL_LIGHTING, GL_TRUE); 1066 } 1067 if (save->RasterDiscard) { 1068 _mesa_set_enable(ctx, GL_RASTERIZER_DISCARD, GL_TRUE); 1069 } 1070#if FEATURE_EXT_transform_feedback 1071 if (save->TransformFeedbackNeedsResume) 1072 _mesa_ResumeTransformFeedback(); 1073#endif 1074 1075 ctx->Meta->SaveStackDepth--; 1076} 1077 1078 1079/** 1080 * Determine whether Mesa is currently in a meta state. 1081 */ 1082GLboolean 1083_mesa_meta_in_progress(struct gl_context *ctx) 1084{ 1085 return ctx->Meta->SaveStackDepth != 0; 1086} 1087 1088 1089/** 1090 * Convert Z from a normalized value in the range [0, 1] to an object-space 1091 * Z coordinate in [-1, +1] so that drawing at the new Z position with the 1092 * default/identity ortho projection results in the original Z value. 1093 * Used by the meta-Clear, Draw/CopyPixels and Bitmap functions where the Z 1094 * value comes from the clear value or raster position. 1095 */ 1096static INLINE GLfloat 1097invert_z(GLfloat normZ) 1098{ 1099 GLfloat objZ = 1.0f - 2.0f * normZ; 1100 return objZ; 1101} 1102 1103 1104/** 1105 * One-time init for a temp_texture object. 1106 * Choose tex target, compute max tex size, etc. 1107 */ 1108static void 1109init_temp_texture(struct gl_context *ctx, struct temp_texture *tex) 1110{ 1111 /* prefer texture rectangle */ 1112 if (ctx->Extensions.NV_texture_rectangle) { 1113 tex->Target = GL_TEXTURE_RECTANGLE; 1114 tex->MaxSize = ctx->Const.MaxTextureRectSize; 1115 tex->NPOT = GL_TRUE; 1116 } 1117 else { 1118 /* use 2D texture, NPOT if possible */ 1119 tex->Target = GL_TEXTURE_2D; 1120 tex->MaxSize = 1 << (ctx->Const.MaxTextureLevels - 1); 1121 tex->NPOT = ctx->Extensions.ARB_texture_non_power_of_two; 1122 } 1123 tex->MinSize = 16; /* 16 x 16 at least */ 1124 assert(tex->MaxSize > 0); 1125 1126 _mesa_GenTextures(1, &tex->TexObj); 1127} 1128 1129static void 1130cleanup_temp_texture(struct gl_context *ctx, struct temp_texture *tex) 1131{ 1132 if (!tex->TexObj) 1133 return; 1134 _mesa_DeleteTextures(1, &tex->TexObj); 1135 tex->TexObj = 0; 1136} 1137 1138 1139/** 1140 * Return pointer to temp_texture info for non-bitmap ops. 1141 * This does some one-time init if needed. 1142 */ 1143static struct temp_texture * 1144get_temp_texture(struct gl_context *ctx) 1145{ 1146 struct temp_texture *tex = &ctx->Meta->TempTex; 1147 1148 if (!tex->TexObj) { 1149 init_temp_texture(ctx, tex); 1150 } 1151 1152 return tex; 1153} 1154 1155 1156/** 1157 * Return pointer to temp_texture info for _mesa_meta_bitmap(). 1158 * We use a separate texture for bitmaps to reduce texture 1159 * allocation/deallocation. 1160 */ 1161static struct temp_texture * 1162get_bitmap_temp_texture(struct gl_context *ctx) 1163{ 1164 struct temp_texture *tex = &ctx->Meta->Bitmap.Tex; 1165 1166 if (!tex->TexObj) { 1167 init_temp_texture(ctx, tex); 1168 } 1169 1170 return tex; 1171} 1172 1173 1174/** 1175 * Compute the width/height of texture needed to draw an image of the 1176 * given size. Return a flag indicating whether the current texture 1177 * can be re-used (glTexSubImage2D) or if a new texture needs to be 1178 * allocated (glTexImage2D). 1179 * Also, compute s/t texcoords for drawing. 1180 * 1181 * \return GL_TRUE if new texture is needed, GL_FALSE otherwise 1182 */ 1183static GLboolean 1184alloc_texture(struct temp_texture *tex, 1185 GLsizei width, GLsizei height, GLenum intFormat) 1186{ 1187 GLboolean newTex = GL_FALSE; 1188 1189 ASSERT(width <= tex->MaxSize); 1190 ASSERT(height <= tex->MaxSize); 1191 1192 if (width > tex->Width || 1193 height > tex->Height || 1194 intFormat != tex->IntFormat) { 1195 /* alloc new texture (larger or different format) */ 1196 1197 if (tex->NPOT) { 1198 /* use non-power of two size */ 1199 tex->Width = MAX2(tex->MinSize, width); 1200 tex->Height = MAX2(tex->MinSize, height); 1201 } 1202 else { 1203 /* find power of two size */ 1204 GLsizei w, h; 1205 w = h = tex->MinSize; 1206 while (w < width) 1207 w *= 2; 1208 while (h < height) 1209 h *= 2; 1210 tex->Width = w; 1211 tex->Height = h; 1212 } 1213 1214 tex->IntFormat = intFormat; 1215 1216 newTex = GL_TRUE; 1217 } 1218 1219 /* compute texcoords */ 1220 if (tex->Target == GL_TEXTURE_RECTANGLE) { 1221 tex->Sright = (GLfloat) width; 1222 tex->Ttop = (GLfloat) height; 1223 } 1224 else { 1225 tex->Sright = (GLfloat) width / tex->Width; 1226 tex->Ttop = (GLfloat) height / tex->Height; 1227 } 1228 1229 return newTex; 1230} 1231 1232 1233/** 1234 * Setup/load texture for glCopyPixels or glBlitFramebuffer. 1235 */ 1236static void 1237setup_copypix_texture(struct temp_texture *tex, 1238 GLboolean newTex, 1239 GLint srcX, GLint srcY, 1240 GLsizei width, GLsizei height, GLenum intFormat, 1241 GLenum filter) 1242{ 1243 _mesa_BindTexture(tex->Target, tex->TexObj); 1244 _mesa_TexParameteri(tex->Target, GL_TEXTURE_MIN_FILTER, filter); 1245 _mesa_TexParameteri(tex->Target, GL_TEXTURE_MAG_FILTER, filter); 1246 _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 1247 1248 /* copy framebuffer image to texture */ 1249 if (newTex) { 1250 /* create new tex image */ 1251 if (tex->Width == width && tex->Height == height) { 1252 /* create new tex with framebuffer data */ 1253 _mesa_CopyTexImage2D(tex->Target, 0, tex->IntFormat, 1254 srcX, srcY, width, height, 0); 1255 } 1256 else { 1257 /* create empty texture */ 1258 _mesa_TexImage2D(tex->Target, 0, tex->IntFormat, 1259 tex->Width, tex->Height, 0, 1260 intFormat, GL_UNSIGNED_BYTE, NULL); 1261 /* load image */ 1262 _mesa_CopyTexSubImage2D(tex->Target, 0, 1263 0, 0, srcX, srcY, width, height); 1264 } 1265 } 1266 else { 1267 /* replace existing tex image */ 1268 _mesa_CopyTexSubImage2D(tex->Target, 0, 1269 0, 0, srcX, srcY, width, height); 1270 } 1271} 1272 1273 1274/** 1275 * Setup/load texture for glDrawPixels. 1276 */ 1277static void 1278setup_drawpix_texture(struct gl_context *ctx, 1279 struct temp_texture *tex, 1280 GLboolean newTex, 1281 GLenum texIntFormat, 1282 GLsizei width, GLsizei height, 1283 GLenum format, GLenum type, 1284 const GLvoid *pixels) 1285{ 1286 _mesa_BindTexture(tex->Target, tex->TexObj); 1287 _mesa_TexParameteri(tex->Target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 1288 _mesa_TexParameteri(tex->Target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 1289 _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 1290 1291 /* copy pixel data to texture */ 1292 if (newTex) { 1293 /* create new tex image */ 1294 if (tex->Width == width && tex->Height == height) { 1295 /* create new tex and load image data */ 1296 _mesa_TexImage2D(tex->Target, 0, tex->IntFormat, 1297 tex->Width, tex->Height, 0, format, type, pixels); 1298 } 1299 else { 1300 struct gl_buffer_object *save_unpack_obj = NULL; 1301 1302 _mesa_reference_buffer_object(ctx, &save_unpack_obj, 1303 ctx->Unpack.BufferObj); 1304 _mesa_BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0); 1305 /* create empty texture */ 1306 _mesa_TexImage2D(tex->Target, 0, tex->IntFormat, 1307 tex->Width, tex->Height, 0, format, type, NULL); 1308 if (save_unpack_obj != NULL) 1309 _mesa_BindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 1310 save_unpack_obj->Name); 1311 /* load image */ 1312 _mesa_TexSubImage2D(tex->Target, 0, 1313 0, 0, width, height, format, type, pixels); 1314 } 1315 } 1316 else { 1317 /* replace existing tex image */ 1318 _mesa_TexSubImage2D(tex->Target, 0, 1319 0, 0, width, height, format, type, pixels); 1320 } 1321} 1322 1323 1324 1325/** 1326 * One-time init for drawing depth pixels. 1327 */ 1328static void 1329init_blit_depth_pixels(struct gl_context *ctx) 1330{ 1331 static const char *program = 1332 "!!ARBfp1.0\n" 1333 "TEX result.depth, fragment.texcoord[0], texture[0], %s; \n" 1334 "END \n"; 1335 char program2[200]; 1336 struct blit_state *blit = &ctx->Meta->Blit; 1337 struct temp_texture *tex = get_temp_texture(ctx); 1338 const char *texTarget; 1339 1340 assert(blit->DepthFP == 0); 1341 1342 /* replace %s with "RECT" or "2D" */ 1343 assert(strlen(program) + 4 < sizeof(program2)); 1344 if (tex->Target == GL_TEXTURE_RECTANGLE) 1345 texTarget = "RECT"; 1346 else 1347 texTarget = "2D"; 1348 _mesa_snprintf(program2, sizeof(program2), program, texTarget); 1349 1350 _mesa_GenPrograms(1, &blit->DepthFP); 1351 _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, blit->DepthFP); 1352 _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, 1353 strlen(program2), (const GLubyte *) program2); 1354} 1355 1356 1357/** 1358 * Try to do a glBlitFramebuffer using no-copy texturing. 1359 * We can do this when the src renderbuffer is actually a texture. 1360 * But if the src buffer == dst buffer we cannot do this. 1361 * 1362 * \return new buffer mask indicating the buffers left to blit using the 1363 * normal path. 1364 */ 1365static GLbitfield 1366blitframebuffer_texture(struct gl_context *ctx, 1367 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 1368 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, 1369 GLbitfield mask, GLenum filter) 1370{ 1371 if (mask & GL_COLOR_BUFFER_BIT) { 1372 const struct gl_framebuffer *drawFb = ctx->DrawBuffer; 1373 const struct gl_framebuffer *readFb = ctx->ReadBuffer; 1374 const struct gl_renderbuffer_attachment *drawAtt = 1375 &drawFb->Attachment[drawFb->_ColorDrawBufferIndexes[0]]; 1376 const struct gl_renderbuffer_attachment *readAtt = 1377 &readFb->Attachment[readFb->_ColorReadBufferIndex]; 1378 1379 if (readAtt && readAtt->Texture) { 1380 const struct gl_texture_object *texObj = readAtt->Texture; 1381 const GLuint srcLevel = readAtt->TextureLevel; 1382 const GLint baseLevelSave = texObj->BaseLevel; 1383 const GLint maxLevelSave = texObj->MaxLevel; 1384 const GLenum fbo_srgb_save = ctx->Color.sRGBEnabled; 1385 const GLenum target = texObj->Target; 1386 GLuint sampler, samplerSave = 1387 ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler ? 1388 ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler->Name : 0; 1389 1390 if (drawAtt->Texture == readAtt->Texture) { 1391 /* Can't use same texture as both the source and dest. We need 1392 * to handle overlapping blits and besides, some hw may not 1393 * support this. 1394 */ 1395 return mask; 1396 } 1397 1398 if (target != GL_TEXTURE_2D && target != GL_TEXTURE_RECTANGLE_ARB) { 1399 /* Can't handle other texture types at this time */ 1400 return mask; 1401 } 1402 1403 _mesa_GenSamplers(1, &sampler); 1404 _mesa_BindSampler(ctx->Texture.CurrentUnit, sampler); 1405 1406 /* 1407 printf("Blit from texture!\n"); 1408 printf(" srcAtt %p dstAtt %p\n", readAtt, drawAtt); 1409 printf(" srcTex %p dstText %p\n", texObj, drawAtt->Texture); 1410 */ 1411 1412 /* Prepare src texture state */ 1413 _mesa_BindTexture(target, texObj->Name); 1414 _mesa_SamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, filter); 1415 _mesa_SamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, filter); 1416 if (target != GL_TEXTURE_RECTANGLE_ARB) { 1417 _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, srcLevel); 1418 _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, srcLevel); 1419 } 1420 _mesa_SamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 1421 _mesa_SamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 1422 1423 /* Always do our blits with no sRGB decode or encode.*/ 1424 if (ctx->Extensions.EXT_texture_sRGB_decode) { 1425 _mesa_SamplerParameteri(sampler, GL_TEXTURE_SRGB_DECODE_EXT, 1426 GL_SKIP_DECODE_EXT); 1427 } 1428 if (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_framebuffer_sRGB 1429 || _mesa_is_gles3(ctx)) { 1430 _mesa_set_enable(ctx, GL_FRAMEBUFFER_SRGB_EXT, GL_FALSE); 1431 } 1432 1433 _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 1434 _mesa_set_enable(ctx, target, GL_TRUE); 1435 1436 /* Prepare vertex data (the VBO was previously created and bound) */ 1437 { 1438 struct vertex { 1439 GLfloat x, y, s, t; 1440 }; 1441 struct vertex verts[4]; 1442 GLfloat s0, t0, s1, t1; 1443 1444 if (target == GL_TEXTURE_2D) { 1445 const struct gl_texture_image *texImage 1446 = _mesa_select_tex_image(ctx, texObj, target, srcLevel); 1447 s0 = srcX0 / (float) texImage->Width; 1448 s1 = srcX1 / (float) texImage->Width; 1449 t0 = srcY0 / (float) texImage->Height; 1450 t1 = srcY1 / (float) texImage->Height; 1451 } 1452 else { 1453 assert(target == GL_TEXTURE_RECTANGLE_ARB); 1454 s0 = srcX0; 1455 s1 = srcX1; 1456 t0 = srcY0; 1457 t1 = srcY1; 1458 } 1459 1460 verts[0].x = (GLfloat) dstX0; 1461 verts[0].y = (GLfloat) dstY0; 1462 verts[1].x = (GLfloat) dstX1; 1463 verts[1].y = (GLfloat) dstY0; 1464 verts[2].x = (GLfloat) dstX1; 1465 verts[2].y = (GLfloat) dstY1; 1466 verts[3].x = (GLfloat) dstX0; 1467 verts[3].y = (GLfloat) dstY1; 1468 1469 verts[0].s = s0; 1470 verts[0].t = t0; 1471 verts[1].s = s1; 1472 verts[1].t = t0; 1473 verts[2].s = s1; 1474 verts[2].t = t1; 1475 verts[3].s = s0; 1476 verts[3].t = t1; 1477 1478 _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); 1479 } 1480 1481 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 1482 1483 /* Restore texture object state, the texture binding will 1484 * be restored by _mesa_meta_end(). 1485 */ 1486 if (target != GL_TEXTURE_RECTANGLE_ARB) { 1487 _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, baseLevelSave); 1488 _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, maxLevelSave); 1489 } 1490 if (ctx->Extensions.EXT_framebuffer_sRGB && fbo_srgb_save) { 1491 _mesa_set_enable(ctx, GL_FRAMEBUFFER_SRGB_EXT, GL_TRUE); 1492 } 1493 1494 _mesa_BindSampler(ctx->Texture.CurrentUnit, samplerSave); 1495 _mesa_DeleteSamplers(1, &sampler); 1496 1497 /* Done with color buffer */ 1498 mask &= ~GL_COLOR_BUFFER_BIT; 1499 } 1500 } 1501 1502 return mask; 1503} 1504 1505 1506/** 1507 * Meta implementation of ctx->Driver.BlitFramebuffer() in terms 1508 * of texture mapping and polygon rendering. 1509 */ 1510void 1511_mesa_meta_BlitFramebuffer(struct gl_context *ctx, 1512 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 1513 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, 1514 GLbitfield mask, GLenum filter) 1515{ 1516 struct blit_state *blit = &ctx->Meta->Blit; 1517 struct temp_texture *tex = get_temp_texture(ctx); 1518 const GLsizei maxTexSize = tex->MaxSize; 1519 const GLint srcX = MIN2(srcX0, srcX1); 1520 const GLint srcY = MIN2(srcY0, srcY1); 1521 const GLint srcW = abs(srcX1 - srcX0); 1522 const GLint srcH = abs(srcY1 - srcY0); 1523 const GLboolean srcFlipX = srcX1 < srcX0; 1524 const GLboolean srcFlipY = srcY1 < srcY0; 1525 struct vertex { 1526 GLfloat x, y, s, t; 1527 }; 1528 struct vertex verts[4]; 1529 GLboolean newTex; 1530 1531 /* In addition to falling back if the blit size is larger than the maximum 1532 * texture size, fallback if the source is multisampled. This fallback can 1533 * be removed once Mesa gets support ARB_texture_multisample. 1534 */ 1535 if (srcW > maxTexSize || srcH > maxTexSize 1536 || ctx->ReadBuffer->Visual.samples > 0) { 1537 /* XXX avoid this fallback */ 1538 _swrast_BlitFramebuffer(ctx, srcX0, srcY0, srcX1, srcY1, 1539 dstX0, dstY0, dstX1, dstY1, mask, filter); 1540 return; 1541 } 1542 1543 if (srcFlipX) { 1544 GLint tmp = dstX0; 1545 dstX0 = dstX1; 1546 dstX1 = tmp; 1547 } 1548 1549 if (srcFlipY) { 1550 GLint tmp = dstY0; 1551 dstY0 = dstY1; 1552 dstY1 = tmp; 1553 } 1554 1555 /* only scissor effects blit so save/clear all other relevant state */ 1556 _mesa_meta_begin(ctx, ~MESA_META_SCISSOR); 1557 1558 if (blit->ArrayObj == 0) { 1559 /* one-time setup */ 1560 1561 /* create vertex array object */ 1562 _mesa_GenVertexArrays(1, &blit->ArrayObj); 1563 _mesa_BindVertexArray(blit->ArrayObj); 1564 1565 /* create vertex array buffer */ 1566 _mesa_GenBuffersARB(1, &blit->VBO); 1567 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, blit->VBO); 1568 _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts), 1569 NULL, GL_DYNAMIC_DRAW_ARB); 1570 1571 /* setup vertex arrays */ 1572 _mesa_VertexPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(x)); 1573 _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s)); 1574 _mesa_EnableClientState(GL_VERTEX_ARRAY); 1575 _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY); 1576 } 1577 else { 1578 _mesa_BindVertexArray(blit->ArrayObj); 1579 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, blit->VBO); 1580 } 1581 1582 /* Try faster, direct texture approach first */ 1583 mask = blitframebuffer_texture(ctx, srcX0, srcY0, srcX1, srcY1, 1584 dstX0, dstY0, dstX1, dstY1, mask, filter); 1585 if (mask == 0x0) { 1586 _mesa_meta_end(ctx); 1587 return; 1588 } 1589 1590 /* Continue with "normal" approach which involves copying the src rect 1591 * into a temporary texture and is "blitted" by drawing a textured quad. 1592 */ 1593 1594 newTex = alloc_texture(tex, srcW, srcH, GL_RGBA); 1595 1596 /* vertex positions/texcoords (after texture allocation!) */ 1597 { 1598 verts[0].x = (GLfloat) dstX0; 1599 verts[0].y = (GLfloat) dstY0; 1600 verts[1].x = (GLfloat) dstX1; 1601 verts[1].y = (GLfloat) dstY0; 1602 verts[2].x = (GLfloat) dstX1; 1603 verts[2].y = (GLfloat) dstY1; 1604 verts[3].x = (GLfloat) dstX0; 1605 verts[3].y = (GLfloat) dstY1; 1606 1607 verts[0].s = 0.0F; 1608 verts[0].t = 0.0F; 1609 verts[1].s = tex->Sright; 1610 verts[1].t = 0.0F; 1611 verts[2].s = tex->Sright; 1612 verts[2].t = tex->Ttop; 1613 verts[3].s = 0.0F; 1614 verts[3].t = tex->Ttop; 1615 1616 /* upload new vertex data */ 1617 _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); 1618 } 1619 1620 _mesa_set_enable(ctx, tex->Target, GL_TRUE); 1621 1622 if (mask & GL_COLOR_BUFFER_BIT) { 1623 setup_copypix_texture(tex, newTex, srcX, srcY, srcW, srcH, 1624 GL_RGBA, filter); 1625 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 1626 mask &= ~GL_COLOR_BUFFER_BIT; 1627 } 1628 1629 if (mask & GL_DEPTH_BUFFER_BIT) { 1630 GLuint *tmp = (GLuint *) malloc(srcW * srcH * sizeof(GLuint)); 1631 if (tmp) { 1632 if (!blit->DepthFP) 1633 init_blit_depth_pixels(ctx); 1634 1635 /* maybe change tex format here */ 1636 newTex = alloc_texture(tex, srcW, srcH, GL_DEPTH_COMPONENT); 1637 1638 _mesa_ReadPixels(srcX, srcY, srcW, srcH, 1639 GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, tmp); 1640 1641 setup_drawpix_texture(ctx, tex, newTex, GL_DEPTH_COMPONENT, srcW, srcH, 1642 GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, tmp); 1643 1644 _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, blit->DepthFP); 1645 _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_TRUE); 1646 _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 1647 _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_TRUE); 1648 _mesa_DepthFunc(GL_ALWAYS); 1649 _mesa_DepthMask(GL_TRUE); 1650 1651 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 1652 mask &= ~GL_DEPTH_BUFFER_BIT; 1653 1654 free(tmp); 1655 } 1656 } 1657 1658 if (mask & GL_STENCIL_BUFFER_BIT) { 1659 /* XXX can't easily do stencil */ 1660 } 1661 1662 _mesa_set_enable(ctx, tex->Target, GL_FALSE); 1663 1664 _mesa_meta_end(ctx); 1665 1666 if (mask) { 1667 _swrast_BlitFramebuffer(ctx, srcX0, srcY0, srcX1, srcY1, 1668 dstX0, dstY0, dstX1, dstY1, mask, filter); 1669 } 1670} 1671 1672static void 1673meta_glsl_blit_cleanup(struct gl_context *ctx, struct blit_state *blit) 1674{ 1675 if (blit->ArrayObj) { 1676 _mesa_DeleteVertexArraysAPPLE(1, &blit->ArrayObj); 1677 blit->ArrayObj = 0; 1678 _mesa_DeleteBuffersARB(1, &blit->VBO); 1679 blit->VBO = 0; 1680 } 1681 if (blit->DepthFP) { 1682 _mesa_DeletePrograms(1, &blit->DepthFP); 1683 blit->DepthFP = 0; 1684 } 1685} 1686 1687 1688/** 1689 * Meta implementation of ctx->Driver.Clear() in terms of polygon rendering. 1690 */ 1691void 1692_mesa_meta_Clear(struct gl_context *ctx, GLbitfield buffers) 1693{ 1694 struct clear_state *clear = &ctx->Meta->Clear; 1695 struct vertex { 1696 GLfloat x, y, z, r, g, b, a; 1697 }; 1698 struct vertex verts[4]; 1699 /* save all state but scissor, pixel pack/unpack */ 1700 GLbitfield metaSave = (MESA_META_ALL - 1701 MESA_META_SCISSOR - 1702 MESA_META_PIXEL_STORE - 1703 MESA_META_CONDITIONAL_RENDER); 1704 const GLuint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1; 1705 1706 if (buffers & BUFFER_BITS_COLOR) { 1707 /* if clearing color buffers, don't save/restore colormask */ 1708 metaSave -= MESA_META_COLOR_MASK; 1709 } 1710 1711 _mesa_meta_begin(ctx, metaSave); 1712 1713 if (clear->ArrayObj == 0) { 1714 /* one-time setup */ 1715 1716 /* create vertex array object */ 1717 _mesa_GenVertexArrays(1, &clear->ArrayObj); 1718 _mesa_BindVertexArray(clear->ArrayObj); 1719 1720 /* create vertex array buffer */ 1721 _mesa_GenBuffersARB(1, &clear->VBO); 1722 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, clear->VBO); 1723 1724 /* setup vertex arrays */ 1725 _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x)); 1726 _mesa_ColorPointer(4, GL_FLOAT, sizeof(struct vertex), OFFSET(r)); 1727 _mesa_EnableClientState(GL_VERTEX_ARRAY); 1728 _mesa_EnableClientState(GL_COLOR_ARRAY); 1729 } 1730 else { 1731 _mesa_BindVertexArray(clear->ArrayObj); 1732 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, clear->VBO); 1733 } 1734 1735 /* GL_COLOR_BUFFER_BIT */ 1736 if (buffers & BUFFER_BITS_COLOR) { 1737 /* leave colormask, glDrawBuffer state as-is */ 1738 1739 /* Clears never have the color clamped. */ 1740 _mesa_ClampColorARB(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE); 1741 } 1742 else { 1743 ASSERT(metaSave & MESA_META_COLOR_MASK); 1744 _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 1745 } 1746 1747 /* GL_DEPTH_BUFFER_BIT */ 1748 if (buffers & BUFFER_BIT_DEPTH) { 1749 _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_TRUE); 1750 _mesa_DepthFunc(GL_ALWAYS); 1751 _mesa_DepthMask(GL_TRUE); 1752 } 1753 else { 1754 assert(!ctx->Depth.Test); 1755 } 1756 1757 /* GL_STENCIL_BUFFER_BIT */ 1758 if (buffers & BUFFER_BIT_STENCIL) { 1759 _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_TRUE); 1760 _mesa_StencilOpSeparate(GL_FRONT_AND_BACK, 1761 GL_REPLACE, GL_REPLACE, GL_REPLACE); 1762 _mesa_StencilFuncSeparate(GL_FRONT_AND_BACK, GL_ALWAYS, 1763 ctx->Stencil.Clear & stencilMax, 1764 ctx->Stencil.WriteMask[0]); 1765 } 1766 else { 1767 assert(!ctx->Stencil.Enabled); 1768 } 1769 1770 /* vertex positions/colors */ 1771 { 1772 const GLfloat x0 = (GLfloat) ctx->DrawBuffer->_Xmin; 1773 const GLfloat y0 = (GLfloat) ctx->DrawBuffer->_Ymin; 1774 const GLfloat x1 = (GLfloat) ctx->DrawBuffer->_Xmax; 1775 const GLfloat y1 = (GLfloat) ctx->DrawBuffer->_Ymax; 1776 const GLfloat z = invert_z(ctx->Depth.Clear); 1777 GLuint i; 1778 1779 verts[0].x = x0; 1780 verts[0].y = y0; 1781 verts[0].z = z; 1782 verts[1].x = x1; 1783 verts[1].y = y0; 1784 verts[1].z = z; 1785 verts[2].x = x1; 1786 verts[2].y = y1; 1787 verts[2].z = z; 1788 verts[3].x = x0; 1789 verts[3].y = y1; 1790 verts[3].z = z; 1791 1792 /* vertex colors */ 1793 for (i = 0; i < 4; i++) { 1794 verts[i].r = ctx->Color.ClearColor.f[0]; 1795 verts[i].g = ctx->Color.ClearColor.f[1]; 1796 verts[i].b = ctx->Color.ClearColor.f[2]; 1797 verts[i].a = ctx->Color.ClearColor.f[3]; 1798 } 1799 1800 /* upload new vertex data */ 1801 _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts), verts, 1802 GL_DYNAMIC_DRAW_ARB); 1803 } 1804 1805 /* draw quad */ 1806 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 1807 1808 _mesa_meta_end(ctx); 1809} 1810 1811static void 1812meta_glsl_clear_init(struct gl_context *ctx, struct clear_state *clear) 1813{ 1814 const char *vs_source = 1815 "attribute vec4 position;\n" 1816 "void main()\n" 1817 "{\n" 1818 " gl_Position = position;\n" 1819 "}\n"; 1820 const char *fs_source = 1821 "uniform vec4 color;\n" 1822 "void main()\n" 1823 "{\n" 1824 " gl_FragColor = color;\n" 1825 "}\n"; 1826 const char *vs_int_source = 1827 "#version 130\n" 1828 "in vec4 position;\n" 1829 "void main()\n" 1830 "{\n" 1831 " gl_Position = position;\n" 1832 "}\n"; 1833 const char *fs_int_source = 1834 "#version 130\n" 1835 "uniform ivec4 color;\n" 1836 "out ivec4 out_color;\n" 1837 "\n" 1838 "void main()\n" 1839 "{\n" 1840 " out_color = color;\n" 1841 "}\n"; 1842 GLuint vs, fs; 1843 1844 if (clear->ArrayObj != 0) 1845 return; 1846 1847 /* create vertex array object */ 1848 _mesa_GenVertexArrays(1, &clear->ArrayObj); 1849 _mesa_BindVertexArray(clear->ArrayObj); 1850 1851 /* create vertex array buffer */ 1852 _mesa_GenBuffersARB(1, &clear->VBO); 1853 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, clear->VBO); 1854 1855 /* setup vertex arrays */ 1856 _mesa_VertexAttribPointerARB(0, 3, GL_FLOAT, GL_FALSE, 0, (void *)0); 1857 _mesa_EnableVertexAttribArrayARB(0); 1858 1859 vs = _mesa_CreateShaderObjectARB(GL_VERTEX_SHADER); 1860 _mesa_ShaderSourceARB(vs, 1, &vs_source, NULL); 1861 _mesa_CompileShaderARB(vs); 1862 1863 fs = _mesa_CreateShaderObjectARB(GL_FRAGMENT_SHADER); 1864 _mesa_ShaderSourceARB(fs, 1, &fs_source, NULL); 1865 _mesa_CompileShaderARB(fs); 1866 1867 clear->ShaderProg = _mesa_CreateProgramObjectARB(); 1868 _mesa_AttachShader(clear->ShaderProg, fs); 1869 _mesa_DeleteObjectARB(fs); 1870 _mesa_AttachShader(clear->ShaderProg, vs); 1871 _mesa_DeleteObjectARB(vs); 1872 _mesa_BindAttribLocationARB(clear->ShaderProg, 0, "position"); 1873 _mesa_LinkProgramARB(clear->ShaderProg); 1874 1875 clear->ColorLocation = _mesa_GetUniformLocationARB(clear->ShaderProg, 1876 "color"); 1877 1878 if (_mesa_is_desktop_gl(ctx) && ctx->Const.GLSLVersion >= 130) { 1879 vs = compile_shader_with_debug(ctx, GL_VERTEX_SHADER, vs_int_source); 1880 fs = compile_shader_with_debug(ctx, GL_FRAGMENT_SHADER, fs_int_source); 1881 1882 clear->IntegerShaderProg = _mesa_CreateProgramObjectARB(); 1883 _mesa_AttachShader(clear->IntegerShaderProg, fs); 1884 _mesa_DeleteObjectARB(fs); 1885 _mesa_AttachShader(clear->IntegerShaderProg, vs); 1886 _mesa_DeleteObjectARB(vs); 1887 _mesa_BindAttribLocationARB(clear->IntegerShaderProg, 0, "position"); 1888 1889 /* Note that user-defined out attributes get automatically assigned 1890 * locations starting from 0, so we don't need to explicitly 1891 * BindFragDataLocation to 0. 1892 */ 1893 1894 link_program_with_debug(ctx, clear->IntegerShaderProg); 1895 1896 clear->IntegerColorLocation = 1897 _mesa_GetUniformLocationARB(clear->IntegerShaderProg, "color"); 1898 } 1899} 1900 1901static void 1902meta_glsl_clear_cleanup(struct gl_context *ctx, struct clear_state *clear) 1903{ 1904 if (clear->ArrayObj == 0) 1905 return; 1906 _mesa_DeleteVertexArraysAPPLE(1, &clear->ArrayObj); 1907 clear->ArrayObj = 0; 1908 _mesa_DeleteBuffersARB(1, &clear->VBO); 1909 clear->VBO = 0; 1910 _mesa_DeleteObjectARB(clear->ShaderProg); 1911 clear->ShaderProg = 0; 1912 1913 if (clear->IntegerShaderProg) { 1914 _mesa_DeleteObjectARB(clear->IntegerShaderProg); 1915 clear->IntegerShaderProg = 0; 1916 } 1917} 1918 1919/** 1920 * Meta implementation of ctx->Driver.Clear() in terms of polygon rendering. 1921 */ 1922void 1923_mesa_meta_glsl_Clear(struct gl_context *ctx, GLbitfield buffers) 1924{ 1925 struct clear_state *clear = &ctx->Meta->Clear; 1926 GLbitfield metaSave; 1927 const GLuint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1; 1928 struct gl_framebuffer *fb = ctx->DrawBuffer; 1929 const float x0 = ((float)fb->_Xmin / fb->Width) * 2.0f - 1.0f; 1930 const float y0 = ((float)fb->_Ymin / fb->Height) * 2.0f - 1.0f; 1931 const float x1 = ((float)fb->_Xmax / fb->Width) * 2.0f - 1.0f; 1932 const float y1 = ((float)fb->_Ymax / fb->Height) * 2.0f - 1.0f; 1933 const float z = -invert_z(ctx->Depth.Clear); 1934 struct vertex { 1935 GLfloat x, y, z; 1936 } verts[4]; 1937 1938 metaSave = (MESA_META_ALPHA_TEST | 1939 MESA_META_BLEND | 1940 MESA_META_DEPTH_TEST | 1941 MESA_META_RASTERIZATION | 1942 MESA_META_SHADER | 1943 MESA_META_STENCIL_TEST | 1944 MESA_META_VERTEX | 1945 MESA_META_VIEWPORT | 1946 MESA_META_CLIP | 1947 MESA_META_CLAMP_FRAGMENT_COLOR | 1948 MESA_META_MULTISAMPLE); 1949 1950 if (!(buffers & BUFFER_BITS_COLOR)) { 1951 /* We'll use colormask to disable color writes. Otherwise, 1952 * respect color mask 1953 */ 1954 metaSave |= MESA_META_COLOR_MASK; 1955 } 1956 1957 _mesa_meta_begin(ctx, metaSave); 1958 1959 meta_glsl_clear_init(ctx, clear); 1960 1961 if (fb->_IntegerColor) { 1962 _mesa_UseProgramObjectARB(clear->IntegerShaderProg); 1963 _mesa_Uniform4ivARB(clear->IntegerColorLocation, 1, 1964 ctx->Color.ClearColor.i); 1965 } else { 1966 _mesa_UseProgramObjectARB(clear->ShaderProg); 1967 _mesa_Uniform4fvARB(clear->ColorLocation, 1, 1968 ctx->Color.ClearColor.f); 1969 } 1970 1971 _mesa_BindVertexArray(clear->ArrayObj); 1972 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, clear->VBO); 1973 1974 /* GL_COLOR_BUFFER_BIT */ 1975 if (buffers & BUFFER_BITS_COLOR) { 1976 /* leave colormask, glDrawBuffer state as-is */ 1977 1978 /* Clears never have the color clamped. */ 1979 _mesa_ClampColorARB(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE); 1980 } 1981 else { 1982 ASSERT(metaSave & MESA_META_COLOR_MASK); 1983 _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 1984 } 1985 1986 /* GL_DEPTH_BUFFER_BIT */ 1987 if (buffers & BUFFER_BIT_DEPTH) { 1988 _mesa_set_enable(ctx, GL_DEPTH_TEST, GL_TRUE); 1989 _mesa_DepthFunc(GL_ALWAYS); 1990 _mesa_DepthMask(GL_TRUE); 1991 } 1992 else { 1993 assert(!ctx->Depth.Test); 1994 } 1995 1996 /* GL_STENCIL_BUFFER_BIT */ 1997 if (buffers & BUFFER_BIT_STENCIL) { 1998 _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_TRUE); 1999 _mesa_StencilOpSeparate(GL_FRONT_AND_BACK, 2000 GL_REPLACE, GL_REPLACE, GL_REPLACE); 2001 _mesa_StencilFuncSeparate(GL_FRONT_AND_BACK, GL_ALWAYS, 2002 ctx->Stencil.Clear & stencilMax, 2003 ctx->Stencil.WriteMask[0]); 2004 } 2005 else { 2006 assert(!ctx->Stencil.Enabled); 2007 } 2008 2009 /* vertex positions */ 2010 verts[0].x = x0; 2011 verts[0].y = y0; 2012 verts[0].z = z; 2013 verts[1].x = x1; 2014 verts[1].y = y0; 2015 verts[1].z = z; 2016 verts[2].x = x1; 2017 verts[2].y = y1; 2018 verts[2].z = z; 2019 verts[3].x = x0; 2020 verts[3].y = y1; 2021 verts[3].z = z; 2022 2023 /* upload new vertex data */ 2024 _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts), verts, 2025 GL_DYNAMIC_DRAW_ARB); 2026 2027 /* draw quad */ 2028 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 2029 2030 _mesa_meta_end(ctx); 2031} 2032 2033/** 2034 * Meta implementation of ctx->Driver.CopyPixels() in terms 2035 * of texture mapping and polygon rendering and GLSL shaders. 2036 */ 2037void 2038_mesa_meta_CopyPixels(struct gl_context *ctx, GLint srcX, GLint srcY, 2039 GLsizei width, GLsizei height, 2040 GLint dstX, GLint dstY, GLenum type) 2041{ 2042 struct copypix_state *copypix = &ctx->Meta->CopyPix; 2043 struct temp_texture *tex = get_temp_texture(ctx); 2044 struct vertex { 2045 GLfloat x, y, z, s, t; 2046 }; 2047 struct vertex verts[4]; 2048 GLboolean newTex; 2049 GLenum intFormat = GL_RGBA; 2050 2051 if (type != GL_COLOR || 2052 ctx->_ImageTransferState || 2053 ctx->Fog.Enabled || 2054 width > tex->MaxSize || 2055 height > tex->MaxSize) { 2056 /* XXX avoid this fallback */ 2057 _swrast_CopyPixels(ctx, srcX, srcY, width, height, dstX, dstY, type); 2058 return; 2059 } 2060 2061 /* Most GL state applies to glCopyPixels, but a there's a few things 2062 * we need to override: 2063 */ 2064 _mesa_meta_begin(ctx, (MESA_META_RASTERIZATION | 2065 MESA_META_SHADER | 2066 MESA_META_TEXTURE | 2067 MESA_META_TRANSFORM | 2068 MESA_META_CLIP | 2069 MESA_META_VERTEX | 2070 MESA_META_VIEWPORT)); 2071 2072 if (copypix->ArrayObj == 0) { 2073 /* one-time setup */ 2074 2075 /* create vertex array object */ 2076 _mesa_GenVertexArrays(1, ©pix->ArrayObj); 2077 _mesa_BindVertexArray(copypix->ArrayObj); 2078 2079 /* create vertex array buffer */ 2080 _mesa_GenBuffersARB(1, ©pix->VBO); 2081 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, copypix->VBO); 2082 _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts), 2083 NULL, GL_DYNAMIC_DRAW_ARB); 2084 2085 /* setup vertex arrays */ 2086 _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x)); 2087 _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s)); 2088 _mesa_EnableClientState(GL_VERTEX_ARRAY); 2089 _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY); 2090 } 2091 else { 2092 _mesa_BindVertexArray(copypix->ArrayObj); 2093 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, copypix->VBO); 2094 } 2095 2096 newTex = alloc_texture(tex, width, height, intFormat); 2097 2098 /* vertex positions, texcoords (after texture allocation!) */ 2099 { 2100 const GLfloat dstX0 = (GLfloat) dstX; 2101 const GLfloat dstY0 = (GLfloat) dstY; 2102 const GLfloat dstX1 = dstX + width * ctx->Pixel.ZoomX; 2103 const GLfloat dstY1 = dstY + height * ctx->Pixel.ZoomY; 2104 const GLfloat z = invert_z(ctx->Current.RasterPos[2]); 2105 2106 verts[0].x = dstX0; 2107 verts[0].y = dstY0; 2108 verts[0].z = z; 2109 verts[0].s = 0.0F; 2110 verts[0].t = 0.0F; 2111 verts[1].x = dstX1; 2112 verts[1].y = dstY0; 2113 verts[1].z = z; 2114 verts[1].s = tex->Sright; 2115 verts[1].t = 0.0F; 2116 verts[2].x = dstX1; 2117 verts[2].y = dstY1; 2118 verts[2].z = z; 2119 verts[2].s = tex->Sright; 2120 verts[2].t = tex->Ttop; 2121 verts[3].x = dstX0; 2122 verts[3].y = dstY1; 2123 verts[3].z = z; 2124 verts[3].s = 0.0F; 2125 verts[3].t = tex->Ttop; 2126 2127 /* upload new vertex data */ 2128 _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); 2129 } 2130 2131 /* Alloc/setup texture */ 2132 setup_copypix_texture(tex, newTex, srcX, srcY, width, height, 2133 GL_RGBA, GL_NEAREST); 2134 2135 _mesa_set_enable(ctx, tex->Target, GL_TRUE); 2136 2137 /* draw textured quad */ 2138 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 2139 2140 _mesa_set_enable(ctx, tex->Target, GL_FALSE); 2141 2142 _mesa_meta_end(ctx); 2143} 2144 2145 2146 2147/** 2148 * When the glDrawPixels() image size is greater than the max rectangle 2149 * texture size we use this function to break the glDrawPixels() image 2150 * into tiles which fit into the max texture size. 2151 */ 2152static void 2153tiled_draw_pixels(struct gl_context *ctx, 2154 GLint tileSize, 2155 GLint x, GLint y, GLsizei width, GLsizei height, 2156 GLenum format, GLenum type, 2157 const struct gl_pixelstore_attrib *unpack, 2158 const GLvoid *pixels) 2159{ 2160 struct gl_pixelstore_attrib tileUnpack = *unpack; 2161 GLint i, j; 2162 2163 if (tileUnpack.RowLength == 0) 2164 tileUnpack.RowLength = width; 2165 2166 for (i = 0; i < width; i += tileSize) { 2167 const GLint tileWidth = MIN2(tileSize, width - i); 2168 const GLint tileX = (GLint) (x + i * ctx->Pixel.ZoomX); 2169 2170 tileUnpack.SkipPixels = unpack->SkipPixels + i; 2171 2172 for (j = 0; j < height; j += tileSize) { 2173 const GLint tileHeight = MIN2(tileSize, height - j); 2174 const GLint tileY = (GLint) (y + j * ctx->Pixel.ZoomY); 2175 2176 tileUnpack.SkipRows = unpack->SkipRows + j; 2177 2178 _mesa_meta_DrawPixels(ctx, tileX, tileY, tileWidth, tileHeight, 2179 format, type, &tileUnpack, pixels); 2180 } 2181 } 2182} 2183 2184 2185/** 2186 * One-time init for drawing stencil pixels. 2187 */ 2188static void 2189init_draw_stencil_pixels(struct gl_context *ctx) 2190{ 2191 /* This program is run eight times, once for each stencil bit. 2192 * The stencil values to draw are found in an 8-bit alpha texture. 2193 * We read the texture/stencil value and test if bit 'b' is set. 2194 * If the bit is not set, use KIL to kill the fragment. 2195 * Finally, we use the stencil test to update the stencil buffer. 2196 * 2197 * The basic algorithm for checking if a bit is set is: 2198 * if (is_odd(value / (1 << bit))) 2199 * result is one (or non-zero). 2200 * else 2201 * result is zero. 2202 * The program parameter contains three values: 2203 * parm.x = 255 / (1 << bit) 2204 * parm.y = 0.5 2205 * parm.z = 0.0 2206 */ 2207 static const char *program = 2208 "!!ARBfp1.0\n" 2209 "PARAM parm = program.local[0]; \n" 2210 "TEMP t; \n" 2211 "TEX t, fragment.texcoord[0], texture[0], %s; \n" /* NOTE %s here! */ 2212 "# t = t * 255 / bit \n" 2213 "MUL t.x, t.a, parm.x; \n" 2214 "# t = (int) t \n" 2215 "FRC t.y, t.x; \n" 2216 "SUB t.x, t.x, t.y; \n" 2217 "# t = t * 0.5 \n" 2218 "MUL t.x, t.x, parm.y; \n" 2219 "# t = fract(t.x) \n" 2220 "FRC t.x, t.x; # if t.x != 0, then the bit is set \n" 2221 "# t.x = (t.x == 0 ? 1 : 0) \n" 2222 "SGE t.x, -t.x, parm.z; \n" 2223 "KIL -t.x; \n" 2224 "# for debug only \n" 2225 "#MOV result.color, t.x; \n" 2226 "END \n"; 2227 char program2[1000]; 2228 struct drawpix_state *drawpix = &ctx->Meta->DrawPix; 2229 struct temp_texture *tex = get_temp_texture(ctx); 2230 const char *texTarget; 2231 2232 assert(drawpix->StencilFP == 0); 2233 2234 /* replace %s with "RECT" or "2D" */ 2235 assert(strlen(program) + 4 < sizeof(program2)); 2236 if (tex->Target == GL_TEXTURE_RECTANGLE) 2237 texTarget = "RECT"; 2238 else 2239 texTarget = "2D"; 2240 _mesa_snprintf(program2, sizeof(program2), program, texTarget); 2241 2242 _mesa_GenPrograms(1, &drawpix->StencilFP); 2243 _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, drawpix->StencilFP); 2244 _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, 2245 strlen(program2), (const GLubyte *) program2); 2246} 2247 2248 2249/** 2250 * One-time init for drawing depth pixels. 2251 */ 2252static void 2253init_draw_depth_pixels(struct gl_context *ctx) 2254{ 2255 static const char *program = 2256 "!!ARBfp1.0\n" 2257 "PARAM color = program.local[0]; \n" 2258 "TEX result.depth, fragment.texcoord[0], texture[0], %s; \n" 2259 "MOV result.color, color; \n" 2260 "END \n"; 2261 char program2[200]; 2262 struct drawpix_state *drawpix = &ctx->Meta->DrawPix; 2263 struct temp_texture *tex = get_temp_texture(ctx); 2264 const char *texTarget; 2265 2266 assert(drawpix->DepthFP == 0); 2267 2268 /* replace %s with "RECT" or "2D" */ 2269 assert(strlen(program) + 4 < sizeof(program2)); 2270 if (tex->Target == GL_TEXTURE_RECTANGLE) 2271 texTarget = "RECT"; 2272 else 2273 texTarget = "2D"; 2274 _mesa_snprintf(program2, sizeof(program2), program, texTarget); 2275 2276 _mesa_GenPrograms(1, &drawpix->DepthFP); 2277 _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, drawpix->DepthFP); 2278 _mesa_ProgramStringARB(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB, 2279 strlen(program2), (const GLubyte *) program2); 2280} 2281 2282 2283/** 2284 * Meta implementation of ctx->Driver.DrawPixels() in terms 2285 * of texture mapping and polygon rendering. 2286 */ 2287void 2288_mesa_meta_DrawPixels(struct gl_context *ctx, 2289 GLint x, GLint y, GLsizei width, GLsizei height, 2290 GLenum format, GLenum type, 2291 const struct gl_pixelstore_attrib *unpack, 2292 const GLvoid *pixels) 2293{ 2294 struct drawpix_state *drawpix = &ctx->Meta->DrawPix; 2295 struct temp_texture *tex = get_temp_texture(ctx); 2296 const struct gl_pixelstore_attrib unpackSave = ctx->Unpack; 2297 const GLuint origStencilMask = ctx->Stencil.WriteMask[0]; 2298 struct vertex { 2299 GLfloat x, y, z, s, t; 2300 }; 2301 struct vertex verts[4]; 2302 GLenum texIntFormat; 2303 GLboolean fallback, newTex; 2304 GLbitfield metaExtraSave = 0x0; 2305 GLuint vbo; 2306 2307 /* 2308 * Determine if we can do the glDrawPixels with texture mapping. 2309 */ 2310 fallback = GL_FALSE; 2311 if (ctx->Fog.Enabled) { 2312 fallback = GL_TRUE; 2313 } 2314 2315 if (_mesa_is_color_format(format)) { 2316 /* use more compact format when possible */ 2317 /* XXX disable special case for GL_LUMINANCE for now to work around 2318 * apparent i965 driver bug (see bug #23670). 2319 */ 2320 if (/*format == GL_LUMINANCE ||*/ format == GL_LUMINANCE_ALPHA) 2321 texIntFormat = format; 2322 else 2323 texIntFormat = GL_RGBA; 2324 2325 /* If we're not supposed to clamp the resulting color, then just 2326 * promote our texture to fully float. We could do better by 2327 * just going for the matching set of channels, in floating 2328 * point. 2329 */ 2330 if (ctx->Color.ClampFragmentColor != GL_TRUE && 2331 ctx->Extensions.ARB_texture_float) 2332 texIntFormat = GL_RGBA32F; 2333 } 2334 else if (_mesa_is_stencil_format(format)) { 2335 if (ctx->Extensions.ARB_fragment_program && 2336 ctx->Pixel.IndexShift == 0 && 2337 ctx->Pixel.IndexOffset == 0 && 2338 type == GL_UNSIGNED_BYTE) { 2339 /* We'll store stencil as alpha. This only works for GLubyte 2340 * image data because of how incoming values are mapped to alpha 2341 * in [0,1]. 2342 */ 2343 texIntFormat = GL_ALPHA; 2344 metaExtraSave = (MESA_META_COLOR_MASK | 2345 MESA_META_DEPTH_TEST | 2346 MESA_META_PIXEL_TRANSFER | 2347 MESA_META_SHADER | 2348 MESA_META_STENCIL_TEST); 2349 } 2350 else { 2351 fallback = GL_TRUE; 2352 } 2353 } 2354 else if (_mesa_is_depth_format(format)) { 2355 if (ctx->Extensions.ARB_depth_texture && 2356 ctx->Extensions.ARB_fragment_program) { 2357 texIntFormat = GL_DEPTH_COMPONENT; 2358 metaExtraSave = (MESA_META_SHADER); 2359 } 2360 else { 2361 fallback = GL_TRUE; 2362 } 2363 } 2364 else { 2365 fallback = GL_TRUE; 2366 } 2367 2368 if (fallback) { 2369 _swrast_DrawPixels(ctx, x, y, width, height, 2370 format, type, unpack, pixels); 2371 return; 2372 } 2373 2374 /* 2375 * Check image size against max texture size, draw as tiles if needed. 2376 */ 2377 if (width > tex->MaxSize || height > tex->MaxSize) { 2378 tiled_draw_pixels(ctx, tex->MaxSize, x, y, width, height, 2379 format, type, unpack, pixels); 2380 return; 2381 } 2382 2383 /* Most GL state applies to glDrawPixels (like blending, stencil, etc), 2384 * but a there's a few things we need to override: 2385 */ 2386 _mesa_meta_begin(ctx, (MESA_META_RASTERIZATION | 2387 MESA_META_SHADER | 2388 MESA_META_TEXTURE | 2389 MESA_META_TRANSFORM | 2390 MESA_META_CLIP | 2391 MESA_META_VERTEX | 2392 MESA_META_VIEWPORT | 2393 metaExtraSave)); 2394 2395 newTex = alloc_texture(tex, width, height, texIntFormat); 2396 2397 /* vertex positions, texcoords (after texture allocation!) */ 2398 { 2399 const GLfloat x0 = (GLfloat) x; 2400 const GLfloat y0 = (GLfloat) y; 2401 const GLfloat x1 = x + width * ctx->Pixel.ZoomX; 2402 const GLfloat y1 = y + height * ctx->Pixel.ZoomY; 2403 const GLfloat z = invert_z(ctx->Current.RasterPos[2]); 2404 2405 verts[0].x = x0; 2406 verts[0].y = y0; 2407 verts[0].z = z; 2408 verts[0].s = 0.0F; 2409 verts[0].t = 0.0F; 2410 verts[1].x = x1; 2411 verts[1].y = y0; 2412 verts[1].z = z; 2413 verts[1].s = tex->Sright; 2414 verts[1].t = 0.0F; 2415 verts[2].x = x1; 2416 verts[2].y = y1; 2417 verts[2].z = z; 2418 verts[2].s = tex->Sright; 2419 verts[2].t = tex->Ttop; 2420 verts[3].x = x0; 2421 verts[3].y = y1; 2422 verts[3].z = z; 2423 verts[3].s = 0.0F; 2424 verts[3].t = tex->Ttop; 2425 } 2426 2427 if (drawpix->ArrayObj == 0) { 2428 /* one-time setup: create vertex array object */ 2429 _mesa_GenVertexArrays(1, &drawpix->ArrayObj); 2430 } 2431 _mesa_BindVertexArray(drawpix->ArrayObj); 2432 2433 /* create vertex array buffer */ 2434 _mesa_GenBuffersARB(1, &vbo); 2435 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, vbo); 2436 _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts), 2437 verts, GL_DYNAMIC_DRAW_ARB); 2438 2439 /* setup vertex arrays */ 2440 _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x)); 2441 _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s)); 2442 _mesa_EnableClientState(GL_VERTEX_ARRAY); 2443 _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY); 2444 2445 /* set given unpack params */ 2446 ctx->Unpack = *unpack; 2447 2448 _mesa_set_enable(ctx, tex->Target, GL_TRUE); 2449 2450 if (_mesa_is_stencil_format(format)) { 2451 /* Drawing stencil */ 2452 GLint bit; 2453 2454 if (!drawpix->StencilFP) 2455 init_draw_stencil_pixels(ctx); 2456 2457 setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height, 2458 GL_ALPHA, type, pixels); 2459 2460 _mesa_ColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); 2461 2462 _mesa_set_enable(ctx, GL_STENCIL_TEST, GL_TRUE); 2463 2464 /* set all stencil bits to 0 */ 2465 _mesa_StencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); 2466 _mesa_StencilFunc(GL_ALWAYS, 0, 255); 2467 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 2468 2469 /* set stencil bits to 1 where needed */ 2470 _mesa_StencilOp(GL_KEEP, GL_KEEP, GL_REPLACE); 2471 2472 _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, drawpix->StencilFP); 2473 _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_TRUE); 2474 2475 for (bit = 0; bit < ctx->DrawBuffer->Visual.stencilBits; bit++) { 2476 const GLuint mask = 1 << bit; 2477 if (mask & origStencilMask) { 2478 _mesa_StencilFunc(GL_ALWAYS, mask, mask); 2479 _mesa_StencilMask(mask); 2480 2481 _mesa_ProgramLocalParameter4fARB(GL_FRAGMENT_PROGRAM_ARB, 0, 2482 255.0 / mask, 0.5, 0.0, 0.0); 2483 2484 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 2485 } 2486 } 2487 } 2488 else if (_mesa_is_depth_format(format)) { 2489 /* Drawing depth */ 2490 if (!drawpix->DepthFP) 2491 init_draw_depth_pixels(ctx); 2492 2493 _mesa_BindProgram(GL_FRAGMENT_PROGRAM_ARB, drawpix->DepthFP); 2494 _mesa_set_enable(ctx, GL_FRAGMENT_PROGRAM_ARB, GL_TRUE); 2495 2496 /* polygon color = current raster color */ 2497 _mesa_ProgramLocalParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, 0, 2498 ctx->Current.RasterColor); 2499 2500 setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height, 2501 format, type, pixels); 2502 2503 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 2504 } 2505 else { 2506 /* Drawing RGBA */ 2507 setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height, 2508 format, type, pixels); 2509 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 2510 } 2511 2512 _mesa_set_enable(ctx, tex->Target, GL_FALSE); 2513 2514 _mesa_DeleteBuffersARB(1, &vbo); 2515 2516 /* restore unpack params */ 2517 ctx->Unpack = unpackSave; 2518 2519 _mesa_meta_end(ctx); 2520} 2521 2522static GLboolean 2523alpha_test_raster_color(struct gl_context *ctx) 2524{ 2525 GLfloat alpha = ctx->Current.RasterColor[ACOMP]; 2526 GLfloat ref = ctx->Color.AlphaRef; 2527 2528 switch (ctx->Color.AlphaFunc) { 2529 case GL_NEVER: 2530 return GL_FALSE; 2531 case GL_LESS: 2532 return alpha < ref; 2533 case GL_EQUAL: 2534 return alpha == ref; 2535 case GL_LEQUAL: 2536 return alpha <= ref; 2537 case GL_GREATER: 2538 return alpha > ref; 2539 case GL_NOTEQUAL: 2540 return alpha != ref; 2541 case GL_GEQUAL: 2542 return alpha >= ref; 2543 case GL_ALWAYS: 2544 return GL_TRUE; 2545 default: 2546 assert(0); 2547 return GL_FALSE; 2548 } 2549} 2550 2551/** 2552 * Do glBitmap with a alpha texture quad. Use the alpha test to cull 2553 * the 'off' bits. A bitmap cache as in the gallium/mesa state 2554 * tracker would improve performance a lot. 2555 */ 2556void 2557_mesa_meta_Bitmap(struct gl_context *ctx, 2558 GLint x, GLint y, GLsizei width, GLsizei height, 2559 const struct gl_pixelstore_attrib *unpack, 2560 const GLubyte *bitmap1) 2561{ 2562 struct bitmap_state *bitmap = &ctx->Meta->Bitmap; 2563 struct temp_texture *tex = get_bitmap_temp_texture(ctx); 2564 const GLenum texIntFormat = GL_ALPHA; 2565 const struct gl_pixelstore_attrib unpackSave = *unpack; 2566 GLubyte fg, bg; 2567 struct vertex { 2568 GLfloat x, y, z, s, t, r, g, b, a; 2569 }; 2570 struct vertex verts[4]; 2571 GLboolean newTex; 2572 GLubyte *bitmap8; 2573 2574 /* 2575 * Check if swrast fallback is needed. 2576 */ 2577 if (ctx->_ImageTransferState || 2578 ctx->FragmentProgram._Enabled || 2579 ctx->Fog.Enabled || 2580 ctx->Texture._EnabledUnits || 2581 width > tex->MaxSize || 2582 height > tex->MaxSize) { 2583 _swrast_Bitmap(ctx, x, y, width, height, unpack, bitmap1); 2584 return; 2585 } 2586 2587 if (ctx->Color.AlphaEnabled && !alpha_test_raster_color(ctx)) 2588 return; 2589 2590 /* Most GL state applies to glBitmap (like blending, stencil, etc), 2591 * but a there's a few things we need to override: 2592 */ 2593 _mesa_meta_begin(ctx, (MESA_META_ALPHA_TEST | 2594 MESA_META_PIXEL_STORE | 2595 MESA_META_RASTERIZATION | 2596 MESA_META_SHADER | 2597 MESA_META_TEXTURE | 2598 MESA_META_TRANSFORM | 2599 MESA_META_CLIP | 2600 MESA_META_VERTEX | 2601 MESA_META_VIEWPORT)); 2602 2603 if (bitmap->ArrayObj == 0) { 2604 /* one-time setup */ 2605 2606 /* create vertex array object */ 2607 _mesa_GenVertexArraysAPPLE(1, &bitmap->ArrayObj); 2608 _mesa_BindVertexArrayAPPLE(bitmap->ArrayObj); 2609 2610 /* create vertex array buffer */ 2611 _mesa_GenBuffersARB(1, &bitmap->VBO); 2612 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, bitmap->VBO); 2613 _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts), 2614 NULL, GL_DYNAMIC_DRAW_ARB); 2615 2616 /* setup vertex arrays */ 2617 _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x)); 2618 _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(s)); 2619 _mesa_ColorPointer(4, GL_FLOAT, sizeof(struct vertex), OFFSET(r)); 2620 _mesa_EnableClientState(GL_VERTEX_ARRAY); 2621 _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY); 2622 _mesa_EnableClientState(GL_COLOR_ARRAY); 2623 } 2624 else { 2625 _mesa_BindVertexArray(bitmap->ArrayObj); 2626 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, bitmap->VBO); 2627 } 2628 2629 newTex = alloc_texture(tex, width, height, texIntFormat); 2630 2631 /* vertex positions, texcoords, colors (after texture allocation!) */ 2632 { 2633 const GLfloat x0 = (GLfloat) x; 2634 const GLfloat y0 = (GLfloat) y; 2635 const GLfloat x1 = (GLfloat) (x + width); 2636 const GLfloat y1 = (GLfloat) (y + height); 2637 const GLfloat z = invert_z(ctx->Current.RasterPos[2]); 2638 GLuint i; 2639 2640 verts[0].x = x0; 2641 verts[0].y = y0; 2642 verts[0].z = z; 2643 verts[0].s = 0.0F; 2644 verts[0].t = 0.0F; 2645 verts[1].x = x1; 2646 verts[1].y = y0; 2647 verts[1].z = z; 2648 verts[1].s = tex->Sright; 2649 verts[1].t = 0.0F; 2650 verts[2].x = x1; 2651 verts[2].y = y1; 2652 verts[2].z = z; 2653 verts[2].s = tex->Sright; 2654 verts[2].t = tex->Ttop; 2655 verts[3].x = x0; 2656 verts[3].y = y1; 2657 verts[3].z = z; 2658 verts[3].s = 0.0F; 2659 verts[3].t = tex->Ttop; 2660 2661 for (i = 0; i < 4; i++) { 2662 verts[i].r = ctx->Current.RasterColor[0]; 2663 verts[i].g = ctx->Current.RasterColor[1]; 2664 verts[i].b = ctx->Current.RasterColor[2]; 2665 verts[i].a = ctx->Current.RasterColor[3]; 2666 } 2667 2668 /* upload new vertex data */ 2669 _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); 2670 } 2671 2672 /* choose different foreground/background alpha values */ 2673 CLAMPED_FLOAT_TO_UBYTE(fg, ctx->Current.RasterColor[ACOMP]); 2674 bg = (fg > 127 ? 0 : 255); 2675 2676 bitmap1 = _mesa_map_pbo_source(ctx, &unpackSave, bitmap1); 2677 if (!bitmap1) { 2678 _mesa_meta_end(ctx); 2679 return; 2680 } 2681 2682 bitmap8 = (GLubyte *) malloc(width * height); 2683 if (bitmap8) { 2684 memset(bitmap8, bg, width * height); 2685 _mesa_expand_bitmap(width, height, &unpackSave, bitmap1, 2686 bitmap8, width, fg); 2687 2688 _mesa_set_enable(ctx, tex->Target, GL_TRUE); 2689 2690 _mesa_set_enable(ctx, GL_ALPHA_TEST, GL_TRUE); 2691 _mesa_AlphaFunc(GL_NOTEQUAL, UBYTE_TO_FLOAT(bg)); 2692 2693 setup_drawpix_texture(ctx, tex, newTex, texIntFormat, width, height, 2694 GL_ALPHA, GL_UNSIGNED_BYTE, bitmap8); 2695 2696 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 2697 2698 _mesa_set_enable(ctx, tex->Target, GL_FALSE); 2699 2700 free(bitmap8); 2701 } 2702 2703 _mesa_unmap_pbo_source(ctx, &unpackSave); 2704 2705 _mesa_meta_end(ctx); 2706} 2707 2708 2709/** 2710 * Check if the call to _mesa_meta_GenerateMipmap() will require a 2711 * software fallback. The fallback path will require that the texture 2712 * images are mapped. 2713 * \return GL_TRUE if a fallback is needed, GL_FALSE otherwise 2714 */ 2715GLboolean 2716_mesa_meta_check_generate_mipmap_fallback(struct gl_context *ctx, GLenum target, 2717 struct gl_texture_object *texObj) 2718{ 2719 const GLuint fboSave = ctx->DrawBuffer->Name; 2720 struct gen_mipmap_state *mipmap = &ctx->Meta->Mipmap; 2721 struct gl_texture_image *baseImage; 2722 GLuint srcLevel; 2723 GLenum status; 2724 2725 /* check for fallbacks */ 2726 if (!ctx->Extensions.EXT_framebuffer_object || 2727 target == GL_TEXTURE_3D || 2728 target == GL_TEXTURE_1D_ARRAY || 2729 target == GL_TEXTURE_2D_ARRAY) { 2730 return GL_TRUE; 2731 } 2732 2733 srcLevel = texObj->BaseLevel; 2734 baseImage = _mesa_select_tex_image(ctx, texObj, target, srcLevel); 2735 if (!baseImage || _mesa_is_format_compressed(baseImage->TexFormat)) { 2736 return GL_TRUE; 2737 } 2738 2739 if (_mesa_get_format_color_encoding(baseImage->TexFormat) == GL_SRGB && 2740 !ctx->Extensions.EXT_texture_sRGB_decode) { 2741 /* The texture format is sRGB but we can't turn off sRGB->linear 2742 * texture sample conversion. So we won't be able to generate the 2743 * right colors when rendering. Need to use a fallback. 2744 */ 2745 return GL_TRUE; 2746 } 2747 2748 /* 2749 * Test that we can actually render in the texture's format. 2750 */ 2751 if (!mipmap->FBO) 2752 _mesa_GenFramebuffersEXT(1, &mipmap->FBO); 2753 _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, mipmap->FBO); 2754 2755 if (target == GL_TEXTURE_1D) { 2756 _mesa_FramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT, 2757 GL_COLOR_ATTACHMENT0_EXT, 2758 target, texObj->Name, srcLevel); 2759 } 2760#if 0 2761 /* other work is needed to enable 3D mipmap generation */ 2762 else if (target == GL_TEXTURE_3D) { 2763 GLint zoffset = 0; 2764 _mesa_FramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT, 2765 GL_COLOR_ATTACHMENT0_EXT, 2766 target, texObj->Name, srcLevel, zoffset); 2767 } 2768#endif 2769 else { 2770 /* 2D / cube */ 2771 _mesa_FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, 2772 GL_COLOR_ATTACHMENT0_EXT, 2773 target, texObj->Name, srcLevel); 2774 } 2775 2776 status = _mesa_CheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); 2777 2778 _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboSave); 2779 2780 if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { 2781 return GL_TRUE; 2782 } 2783 2784 return GL_FALSE; 2785} 2786 2787 2788/** 2789 * Compute the texture coordinates for the four vertices of a quad for 2790 * drawing a 2D texture image or slice of a cube/3D texture. 2791 * \param faceTarget GL_TEXTURE_1D/2D/3D or cube face name 2792 * \param slice slice of a 1D/2D array texture or 3D texture 2793 * \param width width of the texture image 2794 * \param height height of the texture image 2795 * \param coords0/1/2/3 returns the computed texcoords 2796 */ 2797static void 2798setup_texture_coords(GLenum faceTarget, 2799 GLint slice, 2800 GLint width, 2801 GLint height, 2802 GLfloat coords0[3], 2803 GLfloat coords1[3], 2804 GLfloat coords2[3], 2805 GLfloat coords3[3]) 2806{ 2807 static const GLfloat st[4][2] = { 2808 {0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f} 2809 }; 2810 GLuint i; 2811 GLfloat r; 2812 2813 switch (faceTarget) { 2814 case GL_TEXTURE_1D: 2815 case GL_TEXTURE_2D: 2816 case GL_TEXTURE_3D: 2817 case GL_TEXTURE_2D_ARRAY: 2818 if (faceTarget == GL_TEXTURE_3D) 2819 r = 1.0F / slice; 2820 else if (faceTarget == GL_TEXTURE_2D_ARRAY) 2821 r = slice; 2822 else 2823 r = 0.0F; 2824 coords0[0] = 0.0F; /* s */ 2825 coords0[1] = 0.0F; /* t */ 2826 coords0[2] = r; /* r */ 2827 coords1[0] = 1.0F; 2828 coords1[1] = 0.0F; 2829 coords1[2] = r; 2830 coords2[0] = 1.0F; 2831 coords2[1] = 1.0F; 2832 coords2[2] = r; 2833 coords3[0] = 0.0F; 2834 coords3[1] = 1.0F; 2835 coords3[2] = r; 2836 break; 2837 case GL_TEXTURE_RECTANGLE_ARB: 2838 coords0[0] = 0.0F; /* s */ 2839 coords0[1] = 0.0F; /* t */ 2840 coords0[2] = 0.0F; /* r */ 2841 coords1[0] = width; 2842 coords1[1] = 0.0F; 2843 coords1[2] = 0.0F; 2844 coords2[0] = width; 2845 coords2[1] = height; 2846 coords2[2] = 0.0F; 2847 coords3[0] = 0.0F; 2848 coords3[1] = height; 2849 coords3[2] = 0.0F; 2850 break; 2851 case GL_TEXTURE_1D_ARRAY: 2852 coords0[0] = 0.0F; /* s */ 2853 coords0[1] = slice; /* t */ 2854 coords0[2] = 0.0F; /* r */ 2855 coords1[0] = 1.0f; 2856 coords1[1] = slice; 2857 coords1[2] = 0.0F; 2858 coords2[0] = 1.0F; 2859 coords2[1] = slice; 2860 coords2[2] = 0.0F; 2861 coords3[0] = 0.0F; 2862 coords3[1] = slice; 2863 coords3[2] = 0.0F; 2864 break; 2865 2866 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 2867 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 2868 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 2869 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 2870 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 2871 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 2872 /* loop over quad verts */ 2873 for (i = 0; i < 4; i++) { 2874 /* Compute sc = +/-scale and tc = +/-scale. 2875 * Not +/-1 to avoid cube face selection ambiguity near the edges, 2876 * though that can still sometimes happen with this scale factor... 2877 */ 2878 const GLfloat scale = 0.9999f; 2879 const GLfloat sc = (2.0f * st[i][0] - 1.0f) * scale; 2880 const GLfloat tc = (2.0f * st[i][1] - 1.0f) * scale; 2881 GLfloat *coord; 2882 2883 switch (i) { 2884 case 0: 2885 coord = coords0; 2886 break; 2887 case 1: 2888 coord = coords1; 2889 break; 2890 case 2: 2891 coord = coords2; 2892 break; 2893 case 3: 2894 coord = coords3; 2895 break; 2896 default: 2897 assert(0); 2898 } 2899 2900 switch (faceTarget) { 2901 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 2902 coord[0] = 1.0f; 2903 coord[1] = -tc; 2904 coord[2] = -sc; 2905 break; 2906 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 2907 coord[0] = -1.0f; 2908 coord[1] = -tc; 2909 coord[2] = sc; 2910 break; 2911 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 2912 coord[0] = sc; 2913 coord[1] = 1.0f; 2914 coord[2] = tc; 2915 break; 2916 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 2917 coord[0] = sc; 2918 coord[1] = -1.0f; 2919 coord[2] = -tc; 2920 break; 2921 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 2922 coord[0] = sc; 2923 coord[1] = -tc; 2924 coord[2] = 1.0f; 2925 break; 2926 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 2927 coord[0] = -sc; 2928 coord[1] = -tc; 2929 coord[2] = -1.0f; 2930 break; 2931 default: 2932 assert(0); 2933 } 2934 } 2935 break; 2936 default: 2937 assert(0 && "unexpected target in meta setup_texture_coords()"); 2938 } 2939} 2940 2941 2942static void 2943setup_ff_generate_mipmap(struct gl_context *ctx, 2944 struct gen_mipmap_state *mipmap) 2945{ 2946 struct vertex { 2947 GLfloat x, y, tex[3]; 2948 }; 2949 2950 if (mipmap->ArrayObj == 0) { 2951 /* one-time setup */ 2952 /* create vertex array object */ 2953 _mesa_GenVertexArraysAPPLE(1, &mipmap->ArrayObj); 2954 _mesa_BindVertexArrayAPPLE(mipmap->ArrayObj); 2955 2956 /* create vertex array buffer */ 2957 _mesa_GenBuffersARB(1, &mipmap->VBO); 2958 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, mipmap->VBO); 2959 /* setup vertex arrays */ 2960 _mesa_VertexPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(x)); 2961 _mesa_TexCoordPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(tex)); 2962 _mesa_EnableClientState(GL_VERTEX_ARRAY); 2963 _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY); 2964 } 2965 2966 /* setup projection matrix */ 2967 _mesa_MatrixMode(GL_PROJECTION); 2968 _mesa_LoadIdentity(); 2969 _mesa_Ortho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0); 2970} 2971 2972 2973static void 2974setup_glsl_generate_mipmap(struct gl_context *ctx, 2975 struct gen_mipmap_state *mipmap) 2976{ 2977 struct vertex { 2978 GLfloat x, y, tex[3]; 2979 }; 2980 2981 static const char *vs_source = 2982 "attribute vec2 position;\n" 2983 "attribute vec3 textureCoords;\n" 2984 "varying vec3 texCoords;\n" 2985 "void main()\n" 2986 "{\n" 2987 " texCoords = textureCoords;\n" 2988 " gl_Position = vec4(position, 0.0, 1.0);\n" 2989 "}\n"; 2990 static const char *fs_source = 2991 "uniform sampler2D tex2d;\n" 2992 "varying vec3 texCoords;\n" 2993 "void main()\n" 2994 "{\n" 2995 " gl_FragColor = texture2D(tex2d, texCoords.xy);\n" 2996 "}\n"; 2997 2998 static const char *vs_int_source = 2999 "#version 130\n" 3000 "in vec2 position;\n" 3001 "in vec3 textureCoords;\n" 3002 "out vec3 texCoords;\n" 3003 "void main()\n" 3004 "{\n" 3005 " texCoords = textureCoords;\n" 3006 " gl_Position = gl_Vertex;\n" 3007 "}\n"; 3008 static const char *fs_int_source = 3009 "#version 130\n" 3010 "uniform isampler2D tex2d;\n" 3011 "in vec3 texCoords;\n" 3012 "out ivec4 out_color;\n" 3013 "\n" 3014 "void main()\n" 3015 "{\n" 3016 " out_color = texture(tex2d, texCoords.xy);\n" 3017 "}\n"; 3018 GLuint vs, fs; 3019 3020 /* Check if already initialized */ 3021 if (mipmap->ArrayObj != 0) 3022 return; 3023 /* create vertex array object */ 3024 _mesa_GenVertexArrays(1, &mipmap->ArrayObj); 3025 _mesa_BindVertexArray(mipmap->ArrayObj); 3026 3027 /* create vertex array buffer */ 3028 _mesa_GenBuffersARB(1, &mipmap->VBO); 3029 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, mipmap->VBO); 3030 3031 /* setup vertex arrays */ 3032 _mesa_VertexAttribPointerARB(0, 2, GL_FLOAT, GL_FALSE, 3033 sizeof(struct vertex), OFFSET(x)); 3034 _mesa_VertexAttribPointerARB(1, 3, GL_FLOAT, GL_FALSE, 3035 sizeof(struct vertex), OFFSET(tex)); 3036 3037 vs = compile_shader_with_debug(ctx, GL_VERTEX_SHADER, vs_source); 3038 fs = compile_shader_with_debug(ctx, GL_FRAGMENT_SHADER, fs_source); 3039 3040 mipmap->ShaderProg = _mesa_CreateProgramObjectARB(); 3041 _mesa_AttachShader(mipmap->ShaderProg, fs); 3042 _mesa_DeleteObjectARB(fs); 3043 _mesa_AttachShader(mipmap->ShaderProg, vs); 3044 _mesa_DeleteObjectARB(vs); 3045 _mesa_BindAttribLocationARB(mipmap->ShaderProg, 0, "position"); 3046 _mesa_BindAttribLocationARB(mipmap->ShaderProg, 1, "texcoords"); 3047 _mesa_EnableVertexAttribArrayARB(0); 3048 _mesa_EnableVertexAttribArrayARB(1); 3049 link_program_with_debug(ctx, mipmap->ShaderProg); 3050 3051 if ((_mesa_is_desktop_gl(ctx) && ctx->Const.GLSLVersion >= 130) || 3052 _mesa_is_gles3(ctx)){ 3053 vs = compile_shader_with_debug(ctx, GL_VERTEX_SHADER, vs_int_source); 3054 fs = compile_shader_with_debug(ctx, GL_FRAGMENT_SHADER, fs_int_source); 3055 3056 mipmap->IntegerShaderProg = _mesa_CreateProgramObjectARB(); 3057 _mesa_AttachShader(mipmap->IntegerShaderProg, fs); 3058 _mesa_DeleteObjectARB(fs); 3059 _mesa_AttachShader(mipmap->IntegerShaderProg, vs); 3060 _mesa_DeleteObjectARB(vs); 3061 _mesa_BindAttribLocationARB(mipmap->IntegerShaderProg, 0, "position"); 3062 _mesa_BindAttribLocationARB(mipmap->IntegerShaderProg, 1, "texcoords"); 3063 3064 /* Note that user-defined out attributes get automatically assigned 3065 * locations starting from 0, so we don't need to explicitly 3066 * BindFragDataLocation to 0. 3067 */ 3068 link_program_with_debug(ctx, mipmap->IntegerShaderProg); 3069 } 3070} 3071 3072 3073static void 3074meta_glsl_generate_mipmap_cleanup(struct gl_context *ctx, 3075 struct gen_mipmap_state *mipmap) 3076{ 3077 if (mipmap->ArrayObj == 0) 3078 return; 3079 _mesa_DeleteVertexArraysAPPLE(1, &mipmap->ArrayObj); 3080 mipmap->ArrayObj = 0; 3081 _mesa_DeleteBuffersARB(1, &mipmap->VBO); 3082 mipmap->VBO = 0; 3083 _mesa_DeleteObjectARB(mipmap->ShaderProg); 3084 mipmap->ShaderProg = 0; 3085 3086 if (mipmap->IntegerShaderProg) { 3087 _mesa_DeleteObjectARB(mipmap->IntegerShaderProg); 3088 mipmap->IntegerShaderProg = 0; 3089 } 3090} 3091 3092 3093/** 3094 * Called via ctx->Driver.GenerateMipmap() 3095 * Note: We don't yet support 3D textures, 1D/2D array textures or texture 3096 * borders. 3097 */ 3098void 3099_mesa_meta_GenerateMipmap(struct gl_context *ctx, GLenum target, 3100 struct gl_texture_object *texObj) 3101{ 3102 struct gen_mipmap_state *mipmap = &ctx->Meta->Mipmap; 3103 struct vertex { 3104 GLfloat x, y, tex[3]; 3105 }; 3106 struct vertex verts[4]; 3107 const GLuint baseLevel = texObj->BaseLevel; 3108 const GLuint maxLevel = texObj->MaxLevel; 3109 const GLint maxLevelSave = texObj->MaxLevel; 3110 const GLboolean genMipmapSave = texObj->GenerateMipmap; 3111 const GLenum srgbBufferSave = ctx->Color.sRGBEnabled; 3112 const GLuint fboSave = ctx->DrawBuffer->Name; 3113 const GLuint currentTexUnitSave = ctx->Texture.CurrentUnit; 3114 const GLboolean use_glsl_version = ctx->Extensions.ARB_vertex_shader && 3115 ctx->Extensions.ARB_fragment_shader && 3116 (ctx->API != API_OPENGLES); 3117 GLenum faceTarget; 3118 GLuint dstLevel; 3119 const GLint slice = 0; 3120 GLuint samplerSave; 3121 3122 if (_mesa_meta_check_generate_mipmap_fallback(ctx, target, texObj)) { 3123 _mesa_generate_mipmap(ctx, target, texObj); 3124 return; 3125 } 3126 3127 if (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && 3128 target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z) { 3129 faceTarget = target; 3130 target = GL_TEXTURE_CUBE_MAP; 3131 } 3132 else { 3133 faceTarget = target; 3134 } 3135 3136 _mesa_meta_begin(ctx, MESA_META_ALL); 3137 3138 /* Choose between glsl version and fixed function version of 3139 * GenerateMipmap function. 3140 */ 3141 if (use_glsl_version) { 3142 setup_glsl_generate_mipmap(ctx, mipmap); 3143 3144 if (texObj->_IsIntegerFormat) 3145 _mesa_UseProgramObjectARB(mipmap->IntegerShaderProg); 3146 else 3147 _mesa_UseProgramObjectARB(mipmap->ShaderProg); 3148 } 3149 else { 3150 setup_ff_generate_mipmap(ctx, mipmap); 3151 _mesa_set_enable(ctx, target, GL_TRUE); 3152 } 3153 3154 _mesa_BindVertexArray(mipmap->ArrayObj); 3155 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, mipmap->VBO); 3156 3157 samplerSave = ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler ? 3158 ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler->Name : 0; 3159 3160 if (currentTexUnitSave != 0) 3161 _mesa_BindTexture(target, texObj->Name); 3162 3163 if (!mipmap->FBO) { 3164 _mesa_GenFramebuffersEXT(1, &mipmap->FBO); 3165 } 3166 3167 if (!mipmap->Sampler) { 3168 _mesa_GenSamplers(1, &mipmap->Sampler); 3169 _mesa_BindSampler(ctx->Texture.CurrentUnit, mipmap->Sampler); 3170 3171 if (use_glsl_version && texObj->_IsIntegerFormat) 3172 _mesa_SamplerParameteri(mipmap->Sampler, 3173 GL_TEXTURE_MIN_FILTER, 3174 GL_NEAREST_MIPMAP_NEAREST); 3175 else 3176 _mesa_SamplerParameteri(mipmap->Sampler, 3177 GL_TEXTURE_MIN_FILTER, 3178 GL_LINEAR_MIPMAP_LINEAR); 3179 3180 _mesa_SamplerParameteri(mipmap->Sampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR); 3181 _mesa_SamplerParameteri(mipmap->Sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 3182 _mesa_SamplerParameteri(mipmap->Sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 3183 _mesa_SamplerParameteri(mipmap->Sampler, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); 3184 3185 /* We don't want to encode or decode sRGB values; treat them as linear. 3186 * This is not technically correct for GLES3 but we don't get any API 3187 * error at the moment. 3188 */ 3189 if (ctx->Extensions.EXT_texture_sRGB_decode) { 3190 _mesa_SamplerParameteri(mipmap->Sampler, GL_TEXTURE_SRGB_DECODE_EXT, 3191 GL_SKIP_DECODE_EXT); 3192 } 3193 3194 } else { 3195 _mesa_BindSampler(ctx->Texture.CurrentUnit, mipmap->Sampler); 3196 } 3197 3198 _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, mipmap->FBO); 3199 3200 if (ctx->API == API_OPENGL || ctx->API == API_OPENGLES) 3201 _mesa_TexParameteri(target, GL_GENERATE_MIPMAP, GL_FALSE); 3202 else 3203 assert(!genMipmapSave); 3204 3205 if ((ctx->Extensions.EXT_framebuffer_sRGB && 3206 _mesa_is_desktop_gl(ctx)) || 3207 _mesa_is_gles3(ctx)) { 3208 _mesa_set_enable(ctx, GL_FRAMEBUFFER_SRGB_EXT, GL_FALSE); 3209 } 3210 3211 /* Setup texture coordinates */ 3212 setup_texture_coords(faceTarget, 3213 slice, 3214 0, 0, /* width, height never used here */ 3215 verts[0].tex, 3216 verts[1].tex, 3217 verts[2].tex, 3218 verts[3].tex); 3219 3220 /* setup vertex positions */ 3221 verts[0].x = -1.0F; 3222 verts[0].y = -1.0F; 3223 verts[1].x = 1.0F; 3224 verts[1].y = -1.0F; 3225 verts[2].x = 1.0F; 3226 verts[2].y = 1.0F; 3227 verts[3].x = -1.0F; 3228 verts[3].y = 1.0F; 3229 3230 /* upload vertex data */ 3231 _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts), 3232 verts, GL_DYNAMIC_DRAW_ARB); 3233 3234 /* texture is already locked, unlock now */ 3235 _mesa_unlock_texture(ctx, texObj); 3236 3237 for (dstLevel = baseLevel + 1; dstLevel <= maxLevel; dstLevel++) { 3238 const struct gl_texture_image *srcImage; 3239 const GLuint srcLevel = dstLevel - 1; 3240 GLsizei srcWidth, srcHeight, srcDepth; 3241 GLsizei dstWidth, dstHeight, dstDepth; 3242 GLenum status; 3243 3244 srcImage = _mesa_select_tex_image(ctx, texObj, faceTarget, srcLevel); 3245 assert(srcImage->Border == 0); 3246 3247 /* src size */ 3248 srcWidth = srcImage->Width; 3249 srcHeight = srcImage->Height; 3250 srcDepth = srcImage->Depth; 3251 3252 /* new dst size */ 3253 dstWidth = MAX2(1, srcWidth / 2); 3254 dstHeight = MAX2(1, srcHeight / 2); 3255 dstDepth = MAX2(1, srcDepth / 2); 3256 3257 if (dstWidth == srcImage->Width && 3258 dstHeight == srcImage->Height && 3259 dstDepth == srcImage->Depth) { 3260 /* all done */ 3261 break; 3262 } 3263 3264 /* Allocate storage for the destination mipmap image(s) */ 3265 3266 /* Set MaxLevel large enough to hold the new level when we allocate it */ 3267 _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, dstLevel); 3268 3269 if (!_mesa_prepare_mipmap_level(ctx, texObj, dstLevel, 3270 dstWidth, dstHeight, dstDepth, 3271 srcImage->Border, 3272 srcImage->InternalFormat, 3273 srcImage->TexFormat)) { 3274 /* All done. We either ran out of memory or we would go beyond the 3275 * last valid level of an immutable texture if we continued. 3276 */ 3277 break; 3278 } 3279 3280 /* limit minification to src level */ 3281 _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, srcLevel); 3282 3283 /* Set to draw into the current dstLevel */ 3284 if (target == GL_TEXTURE_1D) { 3285 _mesa_FramebufferTexture1DEXT(GL_FRAMEBUFFER_EXT, 3286 GL_COLOR_ATTACHMENT0_EXT, 3287 target, 3288 texObj->Name, 3289 dstLevel); 3290 } 3291 else if (target == GL_TEXTURE_3D) { 3292 GLint zoffset = 0; /* XXX unfinished */ 3293 _mesa_FramebufferTexture3DEXT(GL_FRAMEBUFFER_EXT, 3294 GL_COLOR_ATTACHMENT0_EXT, 3295 target, 3296 texObj->Name, 3297 dstLevel, zoffset); 3298 } 3299 else { 3300 /* 2D / cube */ 3301 _mesa_FramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, 3302 GL_COLOR_ATTACHMENT0_EXT, 3303 faceTarget, 3304 texObj->Name, 3305 dstLevel); 3306 } 3307 3308 _mesa_DrawBuffer(GL_COLOR_ATTACHMENT0_EXT); 3309 3310 /* sanity check */ 3311 status = _mesa_CheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); 3312 if (status != GL_FRAMEBUFFER_COMPLETE_EXT) { 3313 _mesa_problem(ctx, "Unexpected incomplete framebuffer in " 3314 "_mesa_meta_GenerateMipmap()"); 3315 break; 3316 } 3317 3318 assert(dstWidth == ctx->DrawBuffer->Width); 3319 assert(dstHeight == ctx->DrawBuffer->Height); 3320 3321 /* setup viewport */ 3322 _mesa_set_viewport(ctx, 0, 0, dstWidth, dstHeight); 3323 3324 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 3325 } 3326 3327 if (ctx->Extensions.EXT_framebuffer_sRGB && srgbBufferSave) { 3328 _mesa_set_enable(ctx, GL_FRAMEBUFFER_SRGB_EXT, GL_TRUE); 3329 } 3330 3331 _mesa_lock_texture(ctx, texObj); /* relock */ 3332 3333 _mesa_BindSampler(ctx->Texture.CurrentUnit, samplerSave); 3334 3335 _mesa_meta_end(ctx); 3336 3337 _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, maxLevelSave); 3338 if (genMipmapSave) 3339 _mesa_TexParameteri(target, GL_GENERATE_MIPMAP, genMipmapSave); 3340 3341 _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboSave); 3342} 3343 3344 3345/** 3346 * Determine the GL data type to use for the temporary image read with 3347 * ReadPixels() and passed to Tex[Sub]Image(). 3348 */ 3349static GLenum 3350get_temp_image_type(struct gl_context *ctx, gl_format format) 3351{ 3352 GLenum baseFormat; 3353 3354 baseFormat = _mesa_get_format_base_format(format); 3355 3356 switch (baseFormat) { 3357 case GL_RGBA: 3358 case GL_RGB: 3359 case GL_RG: 3360 case GL_RED: 3361 case GL_ALPHA: 3362 case GL_LUMINANCE: 3363 case GL_LUMINANCE_ALPHA: 3364 case GL_INTENSITY: 3365 if (ctx->DrawBuffer->Visual.redBits <= 8) 3366 return GL_UNSIGNED_BYTE; 3367 else if (ctx->DrawBuffer->Visual.redBits <= 16) 3368 return GL_UNSIGNED_SHORT; 3369 else 3370 return _mesa_get_format_datatype(format); 3371 case GL_DEPTH_COMPONENT: 3372 return GL_UNSIGNED_INT; 3373 case GL_DEPTH_STENCIL: 3374 return GL_UNSIGNED_INT_24_8; 3375 default: 3376 _mesa_problem(ctx, "Unexpected format %d in get_temp_image_type()", 3377 baseFormat); 3378 return 0; 3379 } 3380} 3381 3382 3383/** 3384 * Helper for _mesa_meta_CopyTexSubImage1/2/3D() functions. 3385 * Have to be careful with locking and meta state for pixel transfer. 3386 */ 3387void 3388_mesa_meta_CopyTexSubImage(struct gl_context *ctx, GLuint dims, 3389 struct gl_texture_image *texImage, 3390 GLint xoffset, GLint yoffset, GLint zoffset, 3391 struct gl_renderbuffer *rb, 3392 GLint x, GLint y, 3393 GLsizei width, GLsizei height) 3394{ 3395 struct gl_texture_object *texObj = texImage->TexObject; 3396 GLenum format, type; 3397 GLint bpp; 3398 void *buf; 3399 3400 /* Choose format/type for temporary image buffer */ 3401 format = _mesa_get_format_base_format(texImage->TexFormat); 3402 if (format == GL_LUMINANCE || 3403 format == GL_LUMINANCE_ALPHA || 3404 format == GL_INTENSITY) { 3405 /* We don't want to use GL_LUMINANCE, GL_INTENSITY, etc. for the 3406 * temp image buffer because glReadPixels will do L=R+G+B which is 3407 * not what we want (should be L=R). 3408 */ 3409 format = GL_RGBA; 3410 } 3411 3412 type = get_temp_image_type(ctx, texImage->TexFormat); 3413 if (_mesa_is_format_integer_color(texImage->TexFormat)) { 3414 format = _mesa_base_format_to_integer_format(format); 3415 } 3416 bpp = _mesa_bytes_per_pixel(format, type); 3417 if (bpp <= 0) { 3418 _mesa_problem(ctx, "Bad bpp in _mesa_meta_CopyTexSubImage()"); 3419 return; 3420 } 3421 3422 /* 3423 * Alloc image buffer (XXX could use a PBO) 3424 */ 3425 buf = malloc(width * height * bpp); 3426 if (!buf) { 3427 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyTexSubImage%uD", dims); 3428 return; 3429 } 3430 3431 _mesa_unlock_texture(ctx, texObj); /* need to unlock first */ 3432 3433 /* 3434 * Read image from framebuffer (disable pixel transfer ops) 3435 */ 3436 _mesa_meta_begin(ctx, MESA_META_PIXEL_STORE | MESA_META_PIXEL_TRANSFER); 3437 ctx->Driver.ReadPixels(ctx, x, y, width, height, 3438 format, type, &ctx->Pack, buf); 3439 _mesa_meta_end(ctx); 3440 3441 _mesa_update_state(ctx); /* to update pixel transfer state */ 3442 3443 /* 3444 * Store texture data (with pixel transfer ops) 3445 */ 3446 _mesa_meta_begin(ctx, MESA_META_PIXEL_STORE); 3447 3448 ctx->Driver.TexSubImage(ctx, dims, texImage, 3449 xoffset, yoffset, zoffset, width, height, 1, 3450 format, type, buf, &ctx->Unpack); 3451 3452 _mesa_meta_end(ctx); 3453 3454 _mesa_lock_texture(ctx, texObj); /* re-lock */ 3455 3456 free(buf); 3457} 3458 3459 3460/** 3461 * Decompress a texture image by drawing a quad with the compressed 3462 * texture and reading the pixels out of the color buffer. 3463 * \param slice which slice of a 3D texture or layer of a 1D/2D texture 3464 * \param destFormat format, ala glReadPixels 3465 * \param destType type, ala glReadPixels 3466 * \param dest destination buffer 3467 * \param destRowLength dest image rowLength (ala GL_PACK_ROW_LENGTH) 3468 */ 3469static void 3470decompress_texture_image(struct gl_context *ctx, 3471 struct gl_texture_image *texImage, 3472 GLuint slice, 3473 GLenum destFormat, GLenum destType, 3474 GLvoid *dest) 3475{ 3476 struct decompress_state *decompress = &ctx->Meta->Decompress; 3477 struct gl_texture_object *texObj = texImage->TexObject; 3478 const GLint width = texImage->Width; 3479 const GLint height = texImage->Height; 3480 const GLenum target = texObj->Target; 3481 GLenum faceTarget; 3482 struct vertex { 3483 GLfloat x, y, tex[3]; 3484 }; 3485 struct vertex verts[4]; 3486 GLuint fboDrawSave, fboReadSave; 3487 GLuint rbSave; 3488 GLuint samplerSave; 3489 3490 if (slice > 0) { 3491 assert(target == GL_TEXTURE_3D || 3492 target == GL_TEXTURE_2D_ARRAY); 3493 } 3494 3495 if (target == GL_TEXTURE_CUBE_MAP) { 3496 faceTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + texImage->Face; 3497 } 3498 else { 3499 faceTarget = target; 3500 } 3501 3502 /* save fbo bindings (not saved by _mesa_meta_begin()) */ 3503 fboDrawSave = ctx->DrawBuffer->Name; 3504 fboReadSave = ctx->ReadBuffer->Name; 3505 rbSave = ctx->CurrentRenderbuffer ? ctx->CurrentRenderbuffer->Name : 0; 3506 3507 _mesa_meta_begin(ctx, MESA_META_ALL & ~MESA_META_PIXEL_STORE); 3508 3509 samplerSave = ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler ? 3510 ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler->Name : 0; 3511 3512 /* Create/bind FBO/renderbuffer */ 3513 if (decompress->FBO == 0) { 3514 _mesa_GenFramebuffersEXT(1, &decompress->FBO); 3515 _mesa_GenRenderbuffersEXT(1, &decompress->RBO); 3516 _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, decompress->FBO); 3517 _mesa_BindRenderbufferEXT(GL_RENDERBUFFER_EXT, decompress->RBO); 3518 _mesa_FramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, 3519 GL_COLOR_ATTACHMENT0_EXT, 3520 GL_RENDERBUFFER_EXT, 3521 decompress->RBO); 3522 } 3523 else { 3524 _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, decompress->FBO); 3525 } 3526 3527 /* alloc dest surface */ 3528 if (width > decompress->Width || height > decompress->Height) { 3529 _mesa_BindRenderbufferEXT(GL_RENDERBUFFER_EXT, decompress->RBO); 3530 _mesa_RenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_RGBA, 3531 width, height); 3532 decompress->Width = width; 3533 decompress->Height = height; 3534 } 3535 3536 /* setup VBO data */ 3537 if (decompress->ArrayObj == 0) { 3538 /* create vertex array object */ 3539 _mesa_GenVertexArrays(1, &decompress->ArrayObj); 3540 _mesa_BindVertexArray(decompress->ArrayObj); 3541 3542 /* create vertex array buffer */ 3543 _mesa_GenBuffersARB(1, &decompress->VBO); 3544 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, decompress->VBO); 3545 _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts), 3546 NULL, GL_DYNAMIC_DRAW_ARB); 3547 3548 /* setup vertex arrays */ 3549 _mesa_VertexPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(x)); 3550 _mesa_TexCoordPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(tex)); 3551 _mesa_EnableClientState(GL_VERTEX_ARRAY); 3552 _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY); 3553 } 3554 else { 3555 _mesa_BindVertexArray(decompress->ArrayObj); 3556 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, decompress->VBO); 3557 } 3558 3559 if (!decompress->Sampler) { 3560 _mesa_GenSamplers(1, &decompress->Sampler); 3561 _mesa_BindSampler(ctx->Texture.CurrentUnit, decompress->Sampler); 3562 /* nearest filtering */ 3563 _mesa_SamplerParameteri(decompress->Sampler, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 3564 _mesa_SamplerParameteri(decompress->Sampler, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 3565 /* No sRGB decode or encode.*/ 3566 if (ctx->Extensions.EXT_texture_sRGB_decode) { 3567 _mesa_SamplerParameteri(decompress->Sampler, GL_TEXTURE_SRGB_DECODE_EXT, 3568 GL_SKIP_DECODE_EXT); 3569 } 3570 3571 } else { 3572 _mesa_BindSampler(ctx->Texture.CurrentUnit, decompress->Sampler); 3573 } 3574 3575 setup_texture_coords(faceTarget, slice, width, height, 3576 verts[0].tex, 3577 verts[1].tex, 3578 verts[2].tex, 3579 verts[3].tex); 3580 3581 /* setup vertex positions */ 3582 verts[0].x = 0.0F; 3583 verts[0].y = 0.0F; 3584 verts[1].x = width; 3585 verts[1].y = 0.0F; 3586 verts[2].x = width; 3587 verts[2].y = height; 3588 verts[3].x = 0.0F; 3589 verts[3].y = height; 3590 3591 /* upload new vertex data */ 3592 _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); 3593 3594 /* setup texture state */ 3595 _mesa_BindTexture(target, texObj->Name); 3596 _mesa_set_enable(ctx, target, GL_TRUE); 3597 3598 { 3599 /* save texture object state */ 3600 const GLint baseLevelSave = texObj->BaseLevel; 3601 const GLint maxLevelSave = texObj->MaxLevel; 3602 3603 /* restrict sampling to the texture level of interest */ 3604 if (target != GL_TEXTURE_RECTANGLE_ARB) { 3605 _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, texImage->Level); 3606 _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, texImage->Level); 3607 } 3608 3609 /* No sRGB decode or encode.*/ 3610 if (_mesa_is_desktop_gl(ctx) && ctx->Extensions.EXT_framebuffer_sRGB 3611 || _mesa_is_gles3(ctx)) { 3612 _mesa_set_enable(ctx, GL_FRAMEBUFFER_SRGB_EXT, GL_FALSE); 3613 } 3614 3615 /* render quad w/ texture into renderbuffer */ 3616 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 3617 3618 /* Restore texture object state, the texture binding will 3619 * be restored by _mesa_meta_end(). 3620 */ 3621 if (target != GL_TEXTURE_RECTANGLE_ARB) { 3622 _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, baseLevelSave); 3623 _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, maxLevelSave); 3624 } 3625 3626 } 3627 3628 /* read pixels from renderbuffer */ 3629 { 3630 GLenum baseTexFormat = texImage->_BaseFormat; 3631 3632 /* The pixel transfer state will be set to default values at this point 3633 * (see MESA_META_PIXEL_TRANSFER) so pixel transfer ops are effectively 3634 * turned off (as required by glGetTexImage) but we need to handle some 3635 * special cases. In particular, single-channel texture values are 3636 * returned as red and two-channel texture values are returned as 3637 * red/alpha. 3638 */ 3639 if (baseTexFormat == GL_LUMINANCE || 3640 baseTexFormat == GL_LUMINANCE_ALPHA || 3641 baseTexFormat == GL_INTENSITY) { 3642 /* Green and blue must be zero */ 3643 _mesa_PixelTransferf(GL_GREEN_SCALE, 0.0f); 3644 _mesa_PixelTransferf(GL_BLUE_SCALE, 0.0f); 3645 } 3646 3647 _mesa_ReadPixels(0, 0, width, height, destFormat, destType, dest); 3648 } 3649 3650 /* disable texture unit */ 3651 _mesa_set_enable(ctx, target, GL_FALSE); 3652 3653 _mesa_BindSampler(ctx->Texture.CurrentUnit, samplerSave); 3654 3655 _mesa_meta_end(ctx); 3656 3657 /* restore fbo bindings */ 3658 if (fboDrawSave == fboReadSave) { 3659 _mesa_BindFramebufferEXT(GL_FRAMEBUFFER_EXT, fboDrawSave); 3660 } 3661 else { 3662 _mesa_BindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, fboDrawSave); 3663 _mesa_BindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, fboReadSave); 3664 } 3665 _mesa_BindRenderbufferEXT(GL_RENDERBUFFER_EXT, rbSave); 3666} 3667 3668 3669/** 3670 * This is just a wrapper around _mesa_get_tex_image() and 3671 * decompress_texture_image(). Meta functions should not be directly called 3672 * from core Mesa. 3673 */ 3674void 3675_mesa_meta_GetTexImage(struct gl_context *ctx, 3676 GLenum format, GLenum type, GLvoid *pixels, 3677 struct gl_texture_image *texImage) 3678{ 3679 /* We can only use the decompress-with-blit method here if the texels are 3680 * unsigned, normalized values. We could handle signed and unnormalized 3681 * with floating point renderbuffers... 3682 */ 3683 if (_mesa_is_format_compressed(texImage->TexFormat) && 3684 _mesa_get_format_datatype(texImage->TexFormat) 3685 == GL_UNSIGNED_NORMALIZED) { 3686 struct gl_texture_object *texObj = texImage->TexObject; 3687 const GLuint slice = 0; /* only 2D compressed textures for now */ 3688 /* Need to unlock the texture here to prevent deadlock... */ 3689 _mesa_unlock_texture(ctx, texObj); 3690 decompress_texture_image(ctx, texImage, slice, format, type, pixels); 3691 /* ... and relock it */ 3692 _mesa_lock_texture(ctx, texObj); 3693 } 3694 else { 3695 _mesa_get_teximage(ctx, format, type, pixels, texImage); 3696 } 3697} 3698 3699 3700/** 3701 * Meta implementation of ctx->Driver.DrawTex() in terms 3702 * of polygon rendering. 3703 */ 3704void 3705_mesa_meta_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z, 3706 GLfloat width, GLfloat height) 3707{ 3708#if FEATURE_OES_draw_texture 3709 struct drawtex_state *drawtex = &ctx->Meta->DrawTex; 3710 struct vertex { 3711 GLfloat x, y, z, st[MAX_TEXTURE_UNITS][2]; 3712 }; 3713 struct vertex verts[4]; 3714 GLuint i; 3715 3716 _mesa_meta_begin(ctx, (MESA_META_RASTERIZATION | 3717 MESA_META_SHADER | 3718 MESA_META_TRANSFORM | 3719 MESA_META_VERTEX | 3720 MESA_META_VIEWPORT)); 3721 3722 if (drawtex->ArrayObj == 0) { 3723 /* one-time setup */ 3724 GLint active_texture; 3725 3726 /* create vertex array object */ 3727 _mesa_GenVertexArrays(1, &drawtex->ArrayObj); 3728 _mesa_BindVertexArray(drawtex->ArrayObj); 3729 3730 /* create vertex array buffer */ 3731 _mesa_GenBuffersARB(1, &drawtex->VBO); 3732 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, drawtex->VBO); 3733 _mesa_BufferDataARB(GL_ARRAY_BUFFER_ARB, sizeof(verts), 3734 NULL, GL_DYNAMIC_DRAW_ARB); 3735 3736 /* client active texture is not part of the array object */ 3737 active_texture = ctx->Array.ActiveTexture; 3738 3739 /* setup vertex arrays */ 3740 _mesa_VertexPointer(3, GL_FLOAT, sizeof(struct vertex), OFFSET(x)); 3741 _mesa_EnableClientState(GL_VERTEX_ARRAY); 3742 for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { 3743 _mesa_ClientActiveTextureARB(GL_TEXTURE0 + i); 3744 _mesa_TexCoordPointer(2, GL_FLOAT, sizeof(struct vertex), OFFSET(st[i])); 3745 _mesa_EnableClientState(GL_TEXTURE_COORD_ARRAY); 3746 } 3747 3748 /* restore client active texture */ 3749 _mesa_ClientActiveTextureARB(GL_TEXTURE0 + active_texture); 3750 } 3751 else { 3752 _mesa_BindVertexArray(drawtex->ArrayObj); 3753 _mesa_BindBufferARB(GL_ARRAY_BUFFER_ARB, drawtex->VBO); 3754 } 3755 3756 /* vertex positions, texcoords */ 3757 { 3758 const GLfloat x1 = x + width; 3759 const GLfloat y1 = y + height; 3760 3761 z = CLAMP(z, 0.0, 1.0); 3762 z = invert_z(z); 3763 3764 verts[0].x = x; 3765 verts[0].y = y; 3766 verts[0].z = z; 3767 3768 verts[1].x = x1; 3769 verts[1].y = y; 3770 verts[1].z = z; 3771 3772 verts[2].x = x1; 3773 verts[2].y = y1; 3774 verts[2].z = z; 3775 3776 verts[3].x = x; 3777 verts[3].y = y1; 3778 verts[3].z = z; 3779 3780 for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { 3781 const struct gl_texture_object *texObj; 3782 const struct gl_texture_image *texImage; 3783 GLfloat s, t, s1, t1; 3784 GLuint tw, th; 3785 3786 if (!ctx->Texture.Unit[i]._ReallyEnabled) { 3787 GLuint j; 3788 for (j = 0; j < 4; j++) { 3789 verts[j].st[i][0] = 0.0f; 3790 verts[j].st[i][1] = 0.0f; 3791 } 3792 continue; 3793 } 3794 3795 texObj = ctx->Texture.Unit[i]._Current; 3796 texImage = texObj->Image[0][texObj->BaseLevel]; 3797 tw = texImage->Width2; 3798 th = texImage->Height2; 3799 3800 s = (GLfloat) texObj->CropRect[0] / tw; 3801 t = (GLfloat) texObj->CropRect[1] / th; 3802 s1 = (GLfloat) (texObj->CropRect[0] + texObj->CropRect[2]) / tw; 3803 t1 = (GLfloat) (texObj->CropRect[1] + texObj->CropRect[3]) / th; 3804 3805 verts[0].st[i][0] = s; 3806 verts[0].st[i][1] = t; 3807 3808 verts[1].st[i][0] = s1; 3809 verts[1].st[i][1] = t; 3810 3811 verts[2].st[i][0] = s1; 3812 verts[2].st[i][1] = t1; 3813 3814 verts[3].st[i][0] = s; 3815 verts[3].st[i][1] = t1; 3816 } 3817 3818 _mesa_BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); 3819 } 3820 3821 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 3822 3823 _mesa_meta_end(ctx); 3824#endif /* FEATURE_OES_draw_texture */ 3825} 3826