meta_blit.c revision 848b8605
1/* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 2009 VMware, Inc. All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included 14 * in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25#include "main/glheader.h" 26#include "main/mtypes.h" 27#include "main/imports.h" 28#include "main/arbprogram.h" 29#include "main/arrayobj.h" 30#include "main/blend.h" 31#include "main/condrender.h" 32#include "main/depth.h" 33#include "main/enable.h" 34#include "main/enums.h" 35#include "main/fbobject.h" 36#include "main/image.h" 37#include "main/macros.h" 38#include "main/matrix.h" 39#include "main/multisample.h" 40#include "main/objectlabel.h" 41#include "main/readpix.h" 42#include "main/scissor.h" 43#include "main/shaderapi.h" 44#include "main/texobj.h" 45#include "main/texenv.h" 46#include "main/teximage.h" 47#include "main/texparam.h" 48#include "main/varray.h" 49#include "main/viewport.h" 50#include "swrast/swrast.h" 51#include "drivers/common/meta.h" 52#include "util/ralloc.h" 53 54/** Return offset in bytes of the field within a vertex struct */ 55#define OFFSET(FIELD) ((void *) offsetof(struct vertex, FIELD)) 56 57static void 58setup_glsl_msaa_blit_shader(struct gl_context *ctx, 59 struct blit_state *blit, 60 struct gl_renderbuffer *src_rb, 61 GLenum target) 62{ 63 const char *vs_source; 64 char *fs_source; 65 void *mem_ctx; 66 enum blit_msaa_shader shader_index; 67 bool dst_is_msaa = false; 68 GLenum src_datatype; 69 const char *vec4_prefix; 70 const char *sampler_array_suffix = ""; 71 char *name; 72 const char *texcoord_type = "vec2"; 73 74 if (src_rb) { 75 src_datatype = _mesa_get_format_datatype(src_rb->Format); 76 } else { 77 /* depth-or-color glCopyTexImage fallback path that passes a NULL rb and 78 * doesn't handle integer. 79 */ 80 src_datatype = GL_UNSIGNED_NORMALIZED; 81 } 82 83 if (ctx->DrawBuffer->Visual.samples > 1) { 84 /* If you're calling meta_BlitFramebuffer with the destination 85 * multisampled, this is the only path that will work -- swrast and 86 * CopyTexImage won't work on it either. 87 */ 88 assert(ctx->Extensions.ARB_sample_shading); 89 90 dst_is_msaa = true; 91 92 /* We need shader invocation per sample, not per pixel */ 93 _mesa_set_enable(ctx, GL_MULTISAMPLE, GL_TRUE); 94 _mesa_set_enable(ctx, GL_SAMPLE_SHADING, GL_TRUE); 95 _mesa_MinSampleShading(1.0); 96 } 97 98 switch (target) { 99 case GL_TEXTURE_2D_MULTISAMPLE: 100 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 101 if (src_rb->_BaseFormat == GL_DEPTH_COMPONENT || 102 src_rb->_BaseFormat == GL_DEPTH_STENCIL) { 103 if (dst_is_msaa) 104 shader_index = BLIT_MSAA_SHADER_2D_MULTISAMPLE_DEPTH_COPY; 105 else 106 shader_index = BLIT_MSAA_SHADER_2D_MULTISAMPLE_DEPTH_RESOLVE; 107 } else { 108 if (dst_is_msaa) 109 shader_index = BLIT_MSAA_SHADER_2D_MULTISAMPLE_COPY; 110 else 111 shader_index = BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE; 112 } 113 114 if (target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) { 115 shader_index += (BLIT_MSAA_SHADER_2D_MULTISAMPLE_ARRAY_RESOLVE - 116 BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE); 117 sampler_array_suffix = "Array"; 118 texcoord_type = "vec3"; 119 } 120 break; 121 default: 122 _mesa_problem(ctx, "Unkown texture target %s\n", 123 _mesa_lookup_enum_by_nr(target)); 124 shader_index = BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE; 125 } 126 127 /* We rely on the enum being sorted this way. */ 128 STATIC_ASSERT(BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE_INT == 129 BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE + 1); 130 STATIC_ASSERT(BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE_UINT == 131 BLIT_MSAA_SHADER_2D_MULTISAMPLE_RESOLVE + 2); 132 if (src_datatype == GL_INT) { 133 shader_index++; 134 vec4_prefix = "i"; 135 } else if (src_datatype == GL_UNSIGNED_INT) { 136 shader_index += 2; 137 vec4_prefix = "u"; 138 } else { 139 vec4_prefix = ""; 140 } 141 142 if (blit->msaa_shaders[shader_index]) { 143 _mesa_UseProgram(blit->msaa_shaders[shader_index]); 144 return; 145 } 146 147 mem_ctx = ralloc_context(NULL); 148 149 if (shader_index == BLIT_MSAA_SHADER_2D_MULTISAMPLE_DEPTH_RESOLVE || 150 shader_index == BLIT_MSAA_SHADER_2D_MULTISAMPLE_ARRAY_DEPTH_RESOLVE || 151 shader_index == BLIT_MSAA_SHADER_2D_MULTISAMPLE_ARRAY_DEPTH_COPY || 152 shader_index == BLIT_MSAA_SHADER_2D_MULTISAMPLE_DEPTH_COPY) { 153 char *sample_index; 154 const char *arb_sample_shading_extension_string; 155 156 if (dst_is_msaa) { 157 arb_sample_shading_extension_string = "#extension GL_ARB_sample_shading : enable"; 158 sample_index = "gl_SampleID"; 159 name = "depth MSAA copy"; 160 } else { 161 /* Don't need that extension, since we're drawing to a single-sampled 162 * destination. 163 */ 164 arb_sample_shading_extension_string = ""; 165 /* From the GL 4.3 spec: 166 * 167 * "If there is a multisample buffer (the value of SAMPLE_BUFFERS 168 * is one), then values are obtained from the depth samples in 169 * this buffer. It is recommended that the depth value of the 170 * centermost sample be used, though implementations may choose 171 * any function of the depth sample values at each pixel. 172 * 173 * We're slacking and instead of choosing centermost, we've got 0. 174 */ 175 sample_index = "0"; 176 name = "depth MSAA resolve"; 177 } 178 179 vs_source = ralloc_asprintf(mem_ctx, 180 "#version 130\n" 181 "in vec2 position;\n" 182 "in %s textureCoords;\n" 183 "out %s texCoords;\n" 184 "void main()\n" 185 "{\n" 186 " texCoords = textureCoords;\n" 187 " gl_Position = vec4(position, 0.0, 1.0);\n" 188 "}\n", 189 texcoord_type, 190 texcoord_type); 191 fs_source = ralloc_asprintf(mem_ctx, 192 "#version 130\n" 193 "#extension GL_ARB_texture_multisample : enable\n" 194 "%s\n" 195 "uniform sampler2DMS%s texSampler;\n" 196 "in %s texCoords;\n" 197 "out vec4 out_color;\n" 198 "\n" 199 "void main()\n" 200 "{\n" 201 " gl_FragDepth = texelFetch(texSampler, i%s(texCoords), %s).r;\n" 202 "}\n", 203 arb_sample_shading_extension_string, 204 sampler_array_suffix, 205 texcoord_type, 206 texcoord_type, 207 sample_index); 208 } else { 209 /* You can create 2D_MULTISAMPLE textures with 0 sample count (meaning 1 210 * sample). Yes, this is ridiculous. 211 */ 212 int samples; 213 char *sample_resolve; 214 const char *arb_sample_shading_extension_string; 215 const char *merge_function; 216 name = ralloc_asprintf(mem_ctx, "%svec4 MSAA %s", 217 vec4_prefix, 218 dst_is_msaa ? "copy" : "resolve"); 219 220 samples = MAX2(src_rb->NumSamples, 1); 221 222 if (dst_is_msaa) { 223 arb_sample_shading_extension_string = "#extension GL_ARB_sample_shading : enable"; 224 sample_resolve = ralloc_asprintf(mem_ctx, " out_color = texelFetch(texSampler, i%s(texCoords), gl_SampleID);", texcoord_type); 225 merge_function = ""; 226 } else { 227 int i; 228 int step; 229 230 if (src_datatype == GL_INT || src_datatype == GL_UNSIGNED_INT) { 231 merge_function = 232 "gvec4 merge(gvec4 a, gvec4 b) { return (a >> gvec4(1)) + (b >> gvec4(1)) + (a & b & gvec4(1)); }\n"; 233 } else { 234 /* The divide will happen at the end for floats. */ 235 merge_function = 236 "vec4 merge(vec4 a, vec4 b) { return (a + b); }\n"; 237 } 238 239 arb_sample_shading_extension_string = ""; 240 241 /* We're assuming power of two samples for this resolution procedure. 242 * 243 * To avoid losing any floating point precision if the samples all 244 * happen to have the same value, we merge pairs of values at a time 245 * (so the floating point exponent just gets increased), rather than 246 * doing a naive sum and dividing. 247 */ 248 assert((samples & (samples - 1)) == 0); 249 /* Fetch each individual sample. */ 250 sample_resolve = rzalloc_size(mem_ctx, 1); 251 for (i = 0; i < samples; i++) { 252 ralloc_asprintf_append(&sample_resolve, 253 " gvec4 sample_1_%d = texelFetch(texSampler, i%s(texCoords), %d);\n", 254 i, texcoord_type, i); 255 } 256 /* Now, merge each pair of samples, then merge each pair of those, 257 * etc. 258 */ 259 for (step = 2; step <= samples; step *= 2) { 260 for (i = 0; i < samples; i += step) { 261 ralloc_asprintf_append(&sample_resolve, 262 " gvec4 sample_%d_%d = merge(sample_%d_%d, sample_%d_%d);\n", 263 step, i, 264 step / 2, i, 265 step / 2, i + step / 2); 266 } 267 } 268 269 /* Scale the final result. */ 270 if (src_datatype == GL_UNSIGNED_INT || src_datatype == GL_INT) { 271 ralloc_asprintf_append(&sample_resolve, 272 " out_color = sample_%d_0;\n", 273 samples); 274 } else { 275 ralloc_asprintf_append(&sample_resolve, 276 " gl_FragColor = sample_%d_0 / %f;\n", 277 samples, (float)samples); 278 } 279 } 280 281 vs_source = ralloc_asprintf(mem_ctx, 282 "#version 130\n" 283 "in vec2 position;\n" 284 "in %s textureCoords;\n" 285 "out %s texCoords;\n" 286 "void main()\n" 287 "{\n" 288 " texCoords = textureCoords;\n" 289 " gl_Position = vec4(position, 0.0, 1.0);\n" 290 "}\n", 291 texcoord_type, 292 texcoord_type); 293 fs_source = ralloc_asprintf(mem_ctx, 294 "#version 130\n" 295 "#extension GL_ARB_texture_multisample : enable\n" 296 "%s\n" 297 "#define gvec4 %svec4\n" 298 "uniform %ssampler2DMS%s texSampler;\n" 299 "in %s texCoords;\n" 300 "out gvec4 out_color;\n" 301 "\n" 302 "%s" /* merge_function */ 303 "void main()\n" 304 "{\n" 305 "%s\n" /* sample_resolve */ 306 "}\n", 307 arb_sample_shading_extension_string, 308 vec4_prefix, 309 vec4_prefix, 310 sampler_array_suffix, 311 texcoord_type, 312 merge_function, 313 sample_resolve); 314 } 315 316 _mesa_meta_compile_and_link_program(ctx, vs_source, fs_source, name, 317 &blit->msaa_shaders[shader_index]); 318 319 ralloc_free(mem_ctx); 320} 321 322static void 323setup_glsl_blit_framebuffer(struct gl_context *ctx, 324 struct blit_state *blit, 325 struct gl_renderbuffer *src_rb, 326 GLenum target) 327{ 328 unsigned texcoord_size; 329 330 /* target = GL_TEXTURE_RECTANGLE is not supported in GLES 3.0 */ 331 assert(_mesa_is_desktop_gl(ctx) || target == GL_TEXTURE_2D); 332 333 texcoord_size = 2 + (src_rb->Depth > 1 ? 1 : 0); 334 335 _mesa_meta_setup_vertex_objects(&blit->VAO, &blit->VBO, true, 336 2, texcoord_size, 0); 337 338 if (target == GL_TEXTURE_2D_MULTISAMPLE || 339 target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY) { 340 setup_glsl_msaa_blit_shader(ctx, blit, src_rb, target); 341 } else { 342 _mesa_meta_setup_blit_shader(ctx, target, &blit->shaders); 343 } 344} 345 346/** 347 * Try to do a color or depth glBlitFramebuffer using texturing. 348 * 349 * We can do this when the src renderbuffer is actually a texture, or when the 350 * driver exposes BindRenderbufferTexImage(). 351 */ 352static bool 353blitframebuffer_texture(struct gl_context *ctx, 354 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 355 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, 356 GLenum filter, GLint flipX, GLint flipY, 357 GLboolean glsl_version, GLboolean do_depth) 358{ 359 const struct gl_framebuffer *readFb = ctx->ReadBuffer; 360 int att_index = do_depth ? BUFFER_DEPTH : readFb->_ColorReadBufferIndex; 361 const struct gl_renderbuffer_attachment *readAtt = 362 &readFb->Attachment[att_index]; 363 struct blit_state *blit = &ctx->Meta->Blit; 364 struct fb_tex_blit_state fb_tex_blit; 365 const GLint dstX = MIN2(dstX0, dstX1); 366 const GLint dstY = MIN2(dstY0, dstY1); 367 const GLint dstW = abs(dstX1 - dstX0); 368 const GLint dstH = abs(dstY1 - dstY0); 369 struct gl_texture_object *texObj; 370 GLuint srcLevel; 371 GLenum target; 372 struct gl_renderbuffer *rb = readAtt->Renderbuffer; 373 struct temp_texture *meta_temp_texture; 374 375 if (rb->NumSamples && !ctx->Extensions.ARB_texture_multisample) 376 return false; 377 378 if (filter == GL_SCALED_RESOLVE_FASTEST_EXT || 379 filter == GL_SCALED_RESOLVE_NICEST_EXT) { 380 filter = GL_LINEAR; 381 } 382 383 _mesa_meta_fb_tex_blit_begin(ctx, &fb_tex_blit); 384 385 if (readAtt->Texture && 386 (readAtt->Texture->Target == GL_TEXTURE_2D || 387 readAtt->Texture->Target == GL_TEXTURE_RECTANGLE || 388 readAtt->Texture->Target == GL_TEXTURE_2D_MULTISAMPLE || 389 readAtt->Texture->Target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY)) { 390 /* If there's a texture attached of a type we can handle, then just use 391 * it directly. 392 */ 393 srcLevel = readAtt->TextureLevel; 394 texObj = readAtt->Texture; 395 target = texObj->Target; 396 } else if (!readAtt->Texture && ctx->Driver.BindRenderbufferTexImage) { 397 if (!_mesa_meta_bind_rb_as_tex_image(ctx, rb, &fb_tex_blit.tempTex, 398 &texObj, &target)) 399 return false; 400 401 srcLevel = 0; 402 if (_mesa_is_winsys_fbo(readFb)) { 403 GLint temp = srcY0; 404 srcY0 = rb->Height - srcY1; 405 srcY1 = rb->Height - temp; 406 flipY = -flipY; 407 } 408 } else { 409 GLenum tex_base_format; 410 int srcW = abs(srcX1 - srcX0); 411 int srcH = abs(srcY1 - srcY0); 412 /* Fall back to doing a CopyTexSubImage to get the destination 413 * renderbuffer into a texture. 414 */ 415 if (ctx->Meta->Blit.no_ctsi_fallback) 416 return false; 417 418 if (rb->NumSamples > 1) 419 return false; 420 421 if (do_depth) { 422 meta_temp_texture = _mesa_meta_get_temp_depth_texture(ctx); 423 tex_base_format = GL_DEPTH_COMPONENT; 424 } else { 425 meta_temp_texture = _mesa_meta_get_temp_texture(ctx); 426 tex_base_format = 427 _mesa_base_tex_format(ctx, rb->InternalFormat); 428 } 429 430 srcLevel = 0; 431 target = meta_temp_texture->Target; 432 texObj = _mesa_lookup_texture(ctx, meta_temp_texture->TexObj); 433 if (texObj == NULL) { 434 return false; 435 } 436 437 _mesa_meta_setup_copypix_texture(ctx, meta_temp_texture, 438 srcX0, srcY0, 439 srcW, srcH, 440 tex_base_format, 441 filter); 442 443 444 srcX0 = 0; 445 srcY0 = 0; 446 srcX1 = srcW; 447 srcY1 = srcH; 448 } 449 450 fb_tex_blit.baseLevelSave = texObj->BaseLevel; 451 fb_tex_blit.maxLevelSave = texObj->MaxLevel; 452 fb_tex_blit.stencilSamplingSave = texObj->StencilSampling; 453 454 if (glsl_version) { 455 setup_glsl_blit_framebuffer(ctx, blit, rb, target); 456 } 457 else { 458 _mesa_meta_setup_ff_tnl_for_blit(&ctx->Meta->Blit.VAO, 459 &ctx->Meta->Blit.VBO, 460 2); 461 } 462 463 /* 464 printf("Blit from texture!\n"); 465 printf(" srcAtt %p dstAtt %p\n", readAtt, drawAtt); 466 printf(" srcTex %p dstText %p\n", texObj, drawAtt->Texture); 467 */ 468 469 fb_tex_blit.sampler = _mesa_meta_setup_sampler(ctx, texObj, target, filter, 470 srcLevel); 471 472 /* Always do our blits with no net sRGB decode or encode. 473 * 474 * However, if both the src and dst can be srgb decode/encoded, enable them 475 * so that we do any blending (from scaling or from MSAA resolves) in the 476 * right colorspace. 477 * 478 * Our choice of not doing any net encode/decode is from the GL 3.0 479 * specification: 480 * 481 * "Blit operations bypass the fragment pipeline. The only fragment 482 * operations which affect a blit are the pixel ownership test and the 483 * scissor test." 484 * 485 * The GL 4.4 specification disagrees and says that the sRGB part of the 486 * fragment pipeline applies, but this was found to break applications. 487 */ 488 if (ctx->Extensions.EXT_texture_sRGB_decode) { 489 if (_mesa_get_format_color_encoding(rb->Format) == GL_SRGB && 490 ctx->DrawBuffer->Visual.sRGBCapable) { 491 _mesa_SamplerParameteri(fb_tex_blit.sampler, 492 GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT); 493 _mesa_set_framebuffer_srgb(ctx, GL_TRUE); 494 } else { 495 _mesa_SamplerParameteri(fb_tex_blit.sampler, 496 GL_TEXTURE_SRGB_DECODE_EXT, 497 GL_SKIP_DECODE_EXT); 498 /* set_framebuffer_srgb was set by _mesa_meta_begin(). */ 499 } 500 } 501 502 if (!glsl_version) { 503 _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 504 _mesa_set_enable(ctx, target, GL_TRUE); 505 } 506 507 /* Prepare vertex data (the VBO was previously created and bound) */ 508 { 509 struct vertex verts[4]; 510 GLfloat s0, t0, s1, t1; 511 512 if (target == GL_TEXTURE_2D) { 513 const struct gl_texture_image *texImage 514 = _mesa_select_tex_image(ctx, texObj, target, srcLevel); 515 s0 = srcX0 / (float) texImage->Width; 516 s1 = srcX1 / (float) texImage->Width; 517 t0 = srcY0 / (float) texImage->Height; 518 t1 = srcY1 / (float) texImage->Height; 519 } 520 else { 521 assert(target == GL_TEXTURE_RECTANGLE_ARB || 522 target == GL_TEXTURE_2D_MULTISAMPLE || 523 target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY); 524 s0 = (float) srcX0; 525 s1 = (float) srcX1; 526 t0 = (float) srcY0; 527 t1 = (float) srcY1; 528 } 529 530 /* Silence valgrind warnings about reading uninitialized stack. */ 531 memset(verts, 0, sizeof(verts)); 532 533 /* setup vertex positions */ 534 verts[0].x = -1.0F * flipX; 535 verts[0].y = -1.0F * flipY; 536 verts[1].x = 1.0F * flipX; 537 verts[1].y = -1.0F * flipY; 538 verts[2].x = 1.0F * flipX; 539 verts[2].y = 1.0F * flipY; 540 verts[3].x = -1.0F * flipX; 541 verts[3].y = 1.0F * flipY; 542 543 verts[0].tex[0] = s0; 544 verts[0].tex[1] = t0; 545 verts[0].tex[2] = readAtt->Zoffset; 546 verts[1].tex[0] = s1; 547 verts[1].tex[1] = t0; 548 verts[1].tex[2] = readAtt->Zoffset; 549 verts[2].tex[0] = s1; 550 verts[2].tex[1] = t1; 551 verts[2].tex[2] = readAtt->Zoffset; 552 verts[3].tex[0] = s0; 553 verts[3].tex[1] = t1; 554 verts[3].tex[2] = readAtt->Zoffset; 555 556 _mesa_BufferSubData(GL_ARRAY_BUFFER_ARB, 0, sizeof(verts), verts); 557 } 558 559 /* setup viewport */ 560 _mesa_set_viewport(ctx, 0, dstX, dstY, dstW, dstH); 561 _mesa_ColorMask(!do_depth, !do_depth, !do_depth, !do_depth); 562 _mesa_set_enable(ctx, GL_DEPTH_TEST, do_depth); 563 _mesa_DepthMask(do_depth); 564 _mesa_DepthFunc(GL_ALWAYS); 565 566 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 567 _mesa_meta_fb_tex_blit_end(ctx, target, &fb_tex_blit); 568 569 return true; 570} 571 572void 573_mesa_meta_fb_tex_blit_begin(const struct gl_context *ctx, 574 struct fb_tex_blit_state *blit) 575{ 576 blit->samplerSave = 577 ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler ? 578 ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler->Name : 0; 579 blit->tempTex = 0; 580} 581 582void 583_mesa_meta_fb_tex_blit_end(struct gl_context *ctx, GLenum target, 584 struct fb_tex_blit_state *blit) 585{ 586 /* Restore texture object state, the texture binding will 587 * be restored by _mesa_meta_end(). 588 */ 589 if (target != GL_TEXTURE_RECTANGLE_ARB) { 590 _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, blit->baseLevelSave); 591 _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, blit->maxLevelSave); 592 593 if (ctx->Extensions.ARB_stencil_texturing) { 594 const struct gl_texture_object *texObj = 595 _mesa_get_current_tex_object(ctx, target); 596 597 if (texObj->StencilSampling != blit->stencilSamplingSave) 598 _mesa_TexParameteri(target, GL_DEPTH_STENCIL_TEXTURE_MODE, 599 blit->stencilSamplingSave ? 600 GL_STENCIL_INDEX : GL_DEPTH_COMPONENT); 601 } 602 } 603 604 _mesa_BindSampler(ctx->Texture.CurrentUnit, blit->samplerSave); 605 _mesa_DeleteSamplers(1, &blit->sampler); 606 if (blit->tempTex) 607 _mesa_DeleteTextures(1, &blit->tempTex); 608} 609 610GLboolean 611_mesa_meta_bind_rb_as_tex_image(struct gl_context *ctx, 612 struct gl_renderbuffer *rb, 613 GLuint *tex, 614 struct gl_texture_object **texObj, 615 GLenum *target) 616{ 617 struct gl_texture_image *texImage; 618 619 if (rb->NumSamples > 1) 620 *target = GL_TEXTURE_2D_MULTISAMPLE; 621 else 622 *target = GL_TEXTURE_2D; 623 624 _mesa_GenTextures(1, tex); 625 _mesa_BindTexture(*target, *tex); 626 *texObj = _mesa_lookup_texture(ctx, *tex); 627 texImage = _mesa_get_tex_image(ctx, *texObj, *target, 0); 628 629 if (!ctx->Driver.BindRenderbufferTexImage(ctx, rb, texImage)) { 630 _mesa_DeleteTextures(1, tex); 631 return false; 632 } 633 634 if (ctx->Driver.FinishRenderTexture && !rb->NeedsFinishRenderTexture) { 635 rb->NeedsFinishRenderTexture = true; 636 ctx->Driver.FinishRenderTexture(ctx, rb); 637 } 638 639 return true; 640} 641 642GLuint 643_mesa_meta_setup_sampler(struct gl_context *ctx, 644 const struct gl_texture_object *texObj, 645 GLenum target, GLenum filter, GLuint srcLevel) 646{ 647 GLuint sampler; 648 649 _mesa_GenSamplers(1, &sampler); 650 _mesa_BindSampler(ctx->Texture.CurrentUnit, sampler); 651 652 /* Prepare src texture state */ 653 _mesa_BindTexture(target, texObj->Name); 654 _mesa_SamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, filter); 655 _mesa_SamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, filter); 656 if (target != GL_TEXTURE_RECTANGLE_ARB) { 657 _mesa_TexParameteri(target, GL_TEXTURE_BASE_LEVEL, srcLevel); 658 _mesa_TexParameteri(target, GL_TEXTURE_MAX_LEVEL, srcLevel); 659 } 660 _mesa_SamplerParameteri(sampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 661 _mesa_SamplerParameteri(sampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 662 663 return sampler; 664} 665 666/** 667 * Meta implementation of ctx->Driver.BlitFramebuffer() in terms 668 * of texture mapping and polygon rendering. 669 */ 670GLbitfield 671_mesa_meta_BlitFramebuffer(struct gl_context *ctx, 672 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 673 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, 674 GLbitfield mask, GLenum filter) 675{ 676 const GLint dstW = abs(dstX1 - dstX0); 677 const GLint dstH = abs(dstY1 - dstY0); 678 const GLint dstFlipX = (dstX1 - dstX0) / dstW; 679 const GLint dstFlipY = (dstY1 - dstY0) / dstH; 680 681 struct { 682 GLint srcX0, srcY0, srcX1, srcY1; 683 GLint dstX0, dstY0, dstX1, dstY1; 684 } clip = { 685 srcX0, srcY0, srcX1, srcY1, 686 dstX0, dstY0, dstX1, dstY1 687 }; 688 689 const GLboolean use_glsl_version = ctx->Extensions.ARB_vertex_shader && 690 ctx->Extensions.ARB_fragment_shader; 691 692 /* Multisample texture blit support requires texture multisample. */ 693 if (ctx->ReadBuffer->Visual.samples > 0 && 694 !ctx->Extensions.ARB_texture_multisample) { 695 return mask; 696 } 697 698 /* Clip a copy of the blit coordinates. If these differ from the input 699 * coordinates, then we'll set the scissor. 700 */ 701 if (!_mesa_clip_blit(ctx, &clip.srcX0, &clip.srcY0, &clip.srcX1, &clip.srcY1, 702 &clip.dstX0, &clip.dstY0, &clip.dstX1, &clip.dstY1)) { 703 /* clipped/scissored everything away */ 704 return 0; 705 } 706 707 /* Only scissor affects blit, but we're doing to set a custom scissor if 708 * necessary anyway, so save/clear state. 709 */ 710 _mesa_meta_begin(ctx, MESA_META_ALL & ~MESA_META_DRAW_BUFFERS); 711 712 /* Dithering shouldn't be performed for glBlitFramebuffer */ 713 _mesa_set_enable(ctx, GL_DITHER, GL_FALSE); 714 715 /* If the clipping earlier changed the destination rect at all, then 716 * enable the scissor to clip to it. 717 */ 718 if (clip.dstX0 != dstX0 || clip.dstY0 != dstY0 || 719 clip.dstX1 != dstX1 || clip.dstY1 != dstY1) { 720 _mesa_set_enable(ctx, GL_SCISSOR_TEST, GL_TRUE); 721 _mesa_Scissor(MIN2(clip.dstX0, clip.dstX1), 722 MIN2(clip.dstY0, clip.dstY1), 723 abs(clip.dstX0 - clip.dstX1), 724 abs(clip.dstY0 - clip.dstY1)); 725 } 726 727 /* Try faster, direct texture approach first */ 728 if (mask & GL_COLOR_BUFFER_BIT) { 729 if (blitframebuffer_texture(ctx, srcX0, srcY0, srcX1, srcY1, 730 dstX0, dstY0, dstX1, dstY1, 731 filter, dstFlipX, dstFlipY, 732 use_glsl_version, false)) { 733 mask &= ~GL_COLOR_BUFFER_BIT; 734 } 735 } 736 737 if (mask & GL_DEPTH_BUFFER_BIT && use_glsl_version) { 738 if (blitframebuffer_texture(ctx, srcX0, srcY0, srcX1, srcY1, 739 dstX0, dstY0, dstX1, dstY1, 740 filter, dstFlipX, dstFlipY, 741 use_glsl_version, true)) { 742 mask &= ~GL_DEPTH_BUFFER_BIT; 743 } 744 } 745 746 if (mask & GL_STENCIL_BUFFER_BIT) { 747 /* XXX can't easily do stencil */ 748 } 749 750 _mesa_meta_end(ctx); 751 752 return mask; 753} 754 755void 756_mesa_meta_glsl_blit_cleanup(struct blit_state *blit) 757{ 758 if (blit->VAO) { 759 _mesa_DeleteVertexArrays(1, &blit->VAO); 760 blit->VAO = 0; 761 _mesa_DeleteBuffers(1, &blit->VBO); 762 blit->VBO = 0; 763 } 764 765 _mesa_meta_blit_shader_table_cleanup(&blit->shaders); 766 767 _mesa_DeleteTextures(1, &blit->depthTex.TexObj); 768 blit->depthTex.TexObj = 0; 769} 770 771void 772_mesa_meta_and_swrast_BlitFramebuffer(struct gl_context *ctx, 773 GLint srcX0, GLint srcY0, 774 GLint srcX1, GLint srcY1, 775 GLint dstX0, GLint dstY0, 776 GLint dstX1, GLint dstY1, 777 GLbitfield mask, GLenum filter) 778{ 779 mask = _mesa_meta_BlitFramebuffer(ctx, 780 srcX0, srcY0, srcX1, srcY1, 781 dstX0, dstY0, dstX1, dstY1, 782 mask, filter); 783 if (mask == 0x0) 784 return; 785 786 _swrast_BlitFramebuffer(ctx, 787 srcX0, srcY0, srcX1, srcY1, 788 dstX0, dstY0, dstX1, dstY1, 789 mask, filter); 790} 791