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