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/arbprogram.h" 28#include "main/arrayobj.h" 29#include "main/blend.h" 30#include "main/depth.h" 31#include "main/enable.h" 32#include "main/enums.h" 33#include "main/fbobject.h" 34#include "main/image.h" 35#include "main/macros.h" 36#include "main/matrix.h" 37#include "main/readpix.h" 38#include "main/scissor.h" 39#include "main/shaderapi.h" 40#include "main/texobj.h" 41#include "main/texenv.h" 42#include "main/teximage.h" 43#include "main/texparam.h" 44#include "main/uniforms.h" 45#include "main/varray.h" 46#include "main/viewport.h" 47#include "swrast/swrast.h" 48#include "drivers/common/meta.h" 49 50static struct gl_texture_object * 51texture_object_from_renderbuffer(struct gl_context *, struct gl_renderbuffer *); 52 53static struct gl_sampler_object * 54setup_sampler(struct gl_context *, struct gl_texture_object *, GLenum target, 55 GLenum filter, GLuint srcLevel); 56 57/** Return offset in bytes of the field within a vertex struct */ 58#define OFFSET(FIELD) ((void *) offsetof(struct vertex, FIELD)) 59 60static void 61setup_glsl_blit_framebuffer(struct gl_context *ctx, 62 struct blit_state *blit, 63 const struct gl_framebuffer *drawFb, 64 struct gl_renderbuffer *src_rb, 65 GLenum target, 66 bool do_depth) 67{ 68 const unsigned texcoord_size = 2 + (src_rb->Depth > 1 ? 1 : 0); 69 70 /* target = GL_TEXTURE_RECTANGLE is not supported in GLES 3.0 */ 71 assert(_mesa_is_desktop_gl(ctx) || target == GL_TEXTURE_2D); 72 73 74 _mesa_meta_setup_vertex_objects(ctx, &blit->VAO, &blit->buf_obj, true, 75 2, texcoord_size, 0); 76 77 _mesa_meta_setup_blit_shader(ctx, target, do_depth, 78 do_depth ? &blit->shaders_with_depth 79 : &blit->shaders_without_depth); 80} 81 82/** 83 * Try to do a color or depth glBlitFramebuffer using texturing. 84 * 85 * We can do this when the src renderbuffer is actually a texture, or when the 86 * driver exposes BindRenderbufferTexImage(). 87 */ 88static bool 89blitframebuffer_texture(struct gl_context *ctx, 90 const struct gl_framebuffer *readFb, 91 const struct gl_framebuffer *drawFb, 92 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 93 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, 94 GLenum filter, GLint flipX, GLint flipY, 95 GLboolean glsl_version, GLboolean do_depth) 96{ 97 int att_index = do_depth ? BUFFER_DEPTH : readFb->_ColorReadBufferIndex; 98 const struct gl_renderbuffer_attachment *readAtt = 99 &readFb->Attachment[att_index]; 100 struct blit_state *blit = &ctx->Meta->Blit; 101 struct fb_tex_blit_state fb_tex_blit; 102 const GLint dstX = MIN2(dstX0, dstX1); 103 const GLint dstY = MIN2(dstY0, dstY1); 104 const GLint dstW = abs(dstX1 - dstX0); 105 const GLint dstH = abs(dstY1 - dstY0); 106 const int srcW = abs(srcX1 - srcX0); 107 const int srcH = abs(srcY1 - srcY0); 108 struct gl_texture_object *texObj; 109 GLuint srcLevel; 110 GLenum target; 111 struct gl_renderbuffer *rb = readAtt->Renderbuffer; 112 struct temp_texture *meta_temp_texture; 113 114 assert(rb->NumSamples == 0); 115 116 _mesa_meta_fb_tex_blit_begin(ctx, &fb_tex_blit); 117 118 if (readAtt->Texture && 119 (readAtt->Texture->Target == GL_TEXTURE_2D || 120 readAtt->Texture->Target == GL_TEXTURE_RECTANGLE)) { 121 /* If there's a texture attached of a type we can handle, then just use 122 * it directly. 123 */ 124 srcLevel = readAtt->TextureLevel; 125 texObj = readAtt->Texture; 126 } else if (!readAtt->Texture && ctx->Driver.BindRenderbufferTexImage) { 127 texObj = texture_object_from_renderbuffer(ctx, rb); 128 if (texObj == NULL) 129 return false; 130 131 fb_tex_blit.temp_tex_obj = texObj; 132 133 srcLevel = 0; 134 if (_mesa_is_winsys_fbo(readFb)) { 135 GLint temp = srcY0; 136 srcY0 = rb->Height - srcY1; 137 srcY1 = rb->Height - temp; 138 flipY = -flipY; 139 } 140 } else { 141 GLenum tex_base_format; 142 /* Fall back to doing a CopyTexSubImage to get the destination 143 * renderbuffer into a texture. 144 */ 145 if (ctx->Meta->Blit.no_ctsi_fallback) 146 return false; 147 148 if (do_depth) { 149 meta_temp_texture = _mesa_meta_get_temp_depth_texture(ctx); 150 tex_base_format = GL_DEPTH_COMPONENT; 151 } else { 152 meta_temp_texture = _mesa_meta_get_temp_texture(ctx); 153 tex_base_format = 154 _mesa_base_tex_format(ctx, rb->InternalFormat); 155 } 156 157 srcLevel = 0; 158 texObj = meta_temp_texture->tex_obj; 159 if (texObj == NULL) { 160 return false; 161 } 162 163 _mesa_meta_setup_copypix_texture(ctx, meta_temp_texture, 164 srcX0, srcY0, 165 srcW, srcH, 166 tex_base_format, 167 filter); 168 169 assert(texObj->Target == meta_temp_texture->Target); 170 171 srcX0 = 0; 172 srcY0 = 0; 173 srcX1 = srcW; 174 srcY1 = srcH; 175 } 176 177 target = texObj->Target; 178 fb_tex_blit.tex_obj = texObj; 179 fb_tex_blit.baseLevelSave = texObj->Attrib.BaseLevel; 180 fb_tex_blit.maxLevelSave = texObj->Attrib.MaxLevel; 181 fb_tex_blit.stencilSamplingSave = texObj->StencilSampling; 182 183 if (glsl_version) { 184 setup_glsl_blit_framebuffer(ctx, blit, drawFb, rb, target, do_depth); 185 } 186 else { 187 _mesa_meta_setup_ff_tnl_for_blit(ctx, 188 &ctx->Meta->Blit.VAO, 189 &ctx->Meta->Blit.buf_obj, 190 2); 191 } 192 193 /* 194 printf("Blit from texture!\n"); 195 printf(" srcAtt %p dstAtt %p\n", readAtt, drawAtt); 196 printf(" srcTex %p dstText %p\n", texObj, drawAtt->Texture); 197 */ 198 199 fb_tex_blit.samp_obj = setup_sampler(ctx, texObj, target, filter, srcLevel); 200 201 if (ctx->Extensions.EXT_texture_sRGB_decode) { 202 /* The GL 4.4 spec, section 18.3.1 ("Blitting Pixel Rectangles") says: 203 * 204 * "When values are taken from the read buffer, if FRAMEBUFFER_SRGB 205 * is enabled and the value of FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING 206 * for the framebuffer attachment corresponding to the read buffer 207 * is SRGB (see section 9.2.3), the red, green, and blue components 208 * are converted from the non-linear sRGB color space according to 209 * equation 3.24. 210 * 211 * When values are written to the draw buffers, blit operations 212 * bypass most of the fragment pipeline. The only fragment 213 * operations which affect a blit are the pixel ownership test, 214 * the scissor test, and sRGB conversion (see section 17.3.9)." 215 * 216 * ES 3.0 contains nearly the exact same text, but omits the part 217 * about GL_FRAMEBUFFER_SRGB as that doesn't exist in ES. Mesa 218 * defaults it to on for ES contexts, so we can safely check it. 219 */ 220 const bool decode = 221 ctx->Color.sRGBEnabled && _mesa_is_format_srgb(rb->Format); 222 223 _mesa_set_sampler_srgb_decode(ctx, fb_tex_blit.samp_obj, 224 decode ? GL_DECODE_EXT 225 : GL_SKIP_DECODE_EXT); 226 } 227 228 if (!glsl_version) { 229 _mesa_TexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); 230 _mesa_set_enable(ctx, target, GL_TRUE); 231 } 232 233 /* Prepare vertex data (the VBO was previously created and bound) */ 234 { 235 struct vertex verts[4]; 236 GLfloat s0, t0, s1, t1; 237 238 if (target == GL_TEXTURE_2D) { 239 const struct gl_texture_image *texImage 240 = _mesa_select_tex_image(texObj, target, srcLevel); 241 s0 = srcX0 / (float) texImage->Width; 242 s1 = srcX1 / (float) texImage->Width; 243 t0 = srcY0 / (float) texImage->Height; 244 t1 = srcY1 / (float) texImage->Height; 245 } 246 else { 247 assert(target == GL_TEXTURE_RECTANGLE_ARB); 248 s0 = (float) srcX0; 249 s1 = (float) srcX1; 250 t0 = (float) srcY0; 251 t1 = (float) srcY1; 252 } 253 254 /* Silence valgrind warnings about reading uninitialized stack. */ 255 memset(verts, 0, sizeof(verts)); 256 257 /* setup vertex positions */ 258 verts[0].x = -1.0F * flipX; 259 verts[0].y = -1.0F * flipY; 260 verts[1].x = 1.0F * flipX; 261 verts[1].y = -1.0F * flipY; 262 verts[2].x = 1.0F * flipX; 263 verts[2].y = 1.0F * flipY; 264 verts[3].x = -1.0F * flipX; 265 verts[3].y = 1.0F * flipY; 266 267 verts[0].tex[0] = s0; 268 verts[0].tex[1] = t0; 269 verts[0].tex[2] = readAtt->Zoffset; 270 verts[1].tex[0] = s1; 271 verts[1].tex[1] = t0; 272 verts[1].tex[2] = readAtt->Zoffset; 273 verts[2].tex[0] = s1; 274 verts[2].tex[1] = t1; 275 verts[2].tex[2] = readAtt->Zoffset; 276 verts[3].tex[0] = s0; 277 verts[3].tex[1] = t1; 278 verts[3].tex[2] = readAtt->Zoffset; 279 280 _mesa_buffer_sub_data(ctx, blit->buf_obj, 0, sizeof(verts), verts); 281 } 282 283 /* setup viewport */ 284 _mesa_set_viewport(ctx, 0, dstX, dstY, dstW, dstH); 285 _mesa_ColorMask(!do_depth, !do_depth, !do_depth, !do_depth); 286 _mesa_set_enable(ctx, GL_DEPTH_TEST, do_depth); 287 _mesa_DepthMask(do_depth); 288 _mesa_DepthFunc(GL_ALWAYS); 289 290 _mesa_DrawArrays(GL_TRIANGLE_FAN, 0, 4); 291 _mesa_meta_fb_tex_blit_end(ctx, target, &fb_tex_blit); 292 293 return true; 294} 295 296void 297_mesa_meta_fb_tex_blit_begin(struct gl_context *ctx, 298 struct fb_tex_blit_state *blit) 299{ 300 /* None of the existing callers preinitialize fb_tex_blit_state to zeros, 301 * and both use stack variables. If samp_obj_save is not NULL, 302 * _mesa_reference_sampler_object will try to dereference it. Leaving 303 * random garbage in samp_obj_save can only lead to crashes. 304 * 305 * Since the state isn't persistent across calls, we won't catch ref 306 * counting problems. 307 */ 308 blit->samp_obj_save = NULL; 309 _mesa_reference_sampler_object(ctx, &blit->samp_obj_save, 310 ctx->Texture.Unit[ctx->Texture.CurrentUnit].Sampler); 311 blit->temp_tex_obj = NULL; 312} 313 314void 315_mesa_meta_fb_tex_blit_end(struct gl_context *ctx, GLenum target, 316 struct fb_tex_blit_state *blit) 317{ 318 struct gl_texture_object *const texObj = 319 _mesa_get_current_tex_object(ctx, target); 320 321 /* Either there is no temporary texture or the temporary texture is bound. */ 322 assert(blit->temp_tex_obj == NULL || blit->temp_tex_obj == texObj); 323 324 /* Restore texture object state, the texture binding will be restored by 325 * _mesa_meta_end(). If the texture is the temporary texture that is about 326 * to be destroyed, don't bother restoring its state. 327 */ 328 if (blit->temp_tex_obj == NULL) { 329 /* If the target restricts values for base level or max level, we assume 330 * that the original values were valid. 331 */ 332 if (blit->baseLevelSave != texObj->Attrib.BaseLevel) 333 _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_BASE_LEVEL, 334 &blit->baseLevelSave, false); 335 336 if (blit->maxLevelSave != texObj->Attrib.MaxLevel) 337 _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_MAX_LEVEL, 338 &blit->maxLevelSave, false); 339 340 /* If ARB_stencil_texturing is not supported, the mode won't have changed. */ 341 if (texObj->StencilSampling != blit->stencilSamplingSave) { 342 /* GLint so the compiler won't complain about type signedness mismatch 343 * in the call to _mesa_texture_parameteriv below. 344 */ 345 const GLint param = blit->stencilSamplingSave ? 346 GL_STENCIL_INDEX : GL_DEPTH_COMPONENT; 347 348 _mesa_texture_parameteriv(ctx, texObj, GL_DEPTH_STENCIL_TEXTURE_MODE, 349 ¶m, false); 350 } 351 } 352 353 _mesa_bind_sampler(ctx, ctx->Texture.CurrentUnit, blit->samp_obj_save); 354 _mesa_reference_sampler_object(ctx, &blit->samp_obj_save, NULL); 355 _mesa_reference_sampler_object(ctx, &blit->samp_obj, NULL); 356 _mesa_delete_nameless_texture(ctx, blit->temp_tex_obj); 357} 358 359static struct gl_texture_object * 360texture_object_from_renderbuffer(struct gl_context *ctx, 361 struct gl_renderbuffer *rb) 362{ 363 struct gl_texture_image *texImage; 364 struct gl_texture_object *texObj; 365 const GLenum target = GL_TEXTURE_2D; 366 367 texObj = ctx->Driver.NewTextureObject(ctx, 0xDEADBEEF, target); 368 texImage = _mesa_get_tex_image(ctx, texObj, target, 0); 369 370 if (!ctx->Driver.BindRenderbufferTexImage(ctx, rb, texImage)) { 371 _mesa_delete_nameless_texture(ctx, texObj); 372 return NULL; 373 } 374 375 if (ctx->Driver.FinishRenderTexture && !rb->NeedsFinishRenderTexture) { 376 rb->NeedsFinishRenderTexture = true; 377 ctx->Driver.FinishRenderTexture(ctx, rb); 378 } 379 380 return texObj; 381} 382 383static struct gl_sampler_object * 384setup_sampler(struct gl_context *ctx, struct gl_texture_object *texObj, 385 GLenum target, GLenum filter, GLuint srcLevel) 386{ 387 struct gl_sampler_object *samp_obj = 388 ctx->Driver.NewSamplerObject(ctx, 0xDEADBEEF); 389 390 if (samp_obj == NULL) 391 return NULL; 392 393 _mesa_bind_sampler(ctx, ctx->Texture.CurrentUnit, samp_obj); 394 _mesa_set_sampler_filters(ctx, samp_obj, filter, filter); 395 _mesa_set_sampler_wrap(ctx, samp_obj, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, 396 samp_obj->Attrib.WrapR); 397 398 /* Prepare src texture state */ 399 _mesa_bind_texture(ctx, target, texObj); 400 if (target != GL_TEXTURE_RECTANGLE_ARB) { 401 _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_BASE_LEVEL, 402 (GLint *) &srcLevel, false); 403 _mesa_texture_parameteriv(ctx, texObj, GL_TEXTURE_MAX_LEVEL, 404 (GLint *) &srcLevel, false); 405 } 406 407 return samp_obj; 408} 409 410/** 411 * Meta implementation of ctx->Driver.BlitFramebuffer() in terms 412 * of texture mapping and polygon rendering. 413 */ 414GLbitfield 415_mesa_meta_BlitFramebuffer(struct gl_context *ctx, 416 const struct gl_framebuffer *readFb, 417 const struct gl_framebuffer *drawFb, 418 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 419 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, 420 GLbitfield mask, GLenum filter) 421{ 422 const GLint dstW = abs(dstX1 - dstX0); 423 const GLint dstH = abs(dstY1 - dstY0); 424 const GLint dstFlipX = (dstX1 - dstX0) / dstW; 425 const GLint dstFlipY = (dstY1 - dstY0) / dstH; 426 427 struct { 428 GLint srcX0, srcY0, srcX1, srcY1; 429 GLint dstX0, dstY0, dstX1, dstY1; 430 } clip = { 431 srcX0, srcY0, srcX1, srcY1, 432 dstX0, dstY0, dstX1, dstY1 433 }; 434 435 const GLboolean use_glsl_version = ctx->Extensions.ARB_vertex_shader && 436 ctx->Extensions.ARB_fragment_shader; 437 438 /* Multisample blit is not supported. */ 439 if (readFb->Visual.samples > 0) 440 return mask; 441 442 /* Clip a copy of the blit coordinates. If these differ from the input 443 * coordinates, then we'll set the scissor. 444 */ 445 if (!_mesa_clip_blit(ctx, readFb, drawFb, 446 &clip.srcX0, &clip.srcY0, &clip.srcX1, &clip.srcY1, 447 &clip.dstX0, &clip.dstY0, &clip.dstX1, &clip.dstY1)) { 448 /* clipped/scissored everything away */ 449 return 0; 450 } 451 452 /* Only scissor and FRAMEBUFFER_SRGB affect blit. Leave sRGB alone, but 453 * save restore scissor as we'll set a custom scissor if necessary. 454 */ 455 _mesa_meta_begin(ctx, MESA_META_ALL & 456 ~(MESA_META_DRAW_BUFFERS | 457 MESA_META_FRAMEBUFFER_SRGB)); 458 459 /* Dithering shouldn't be performed for glBlitFramebuffer */ 460 _mesa_set_enable(ctx, GL_DITHER, GL_FALSE); 461 462 /* If the clipping earlier changed the destination rect at all, then 463 * enable the scissor to clip to it. 464 */ 465 if (clip.dstX0 != dstX0 || clip.dstY0 != dstY0 || 466 clip.dstX1 != dstX1 || clip.dstY1 != dstY1) { 467 _mesa_set_enable(ctx, GL_SCISSOR_TEST, GL_TRUE); 468 _mesa_Scissor(MIN2(clip.dstX0, clip.dstX1), 469 MIN2(clip.dstY0, clip.dstY1), 470 abs(clip.dstX0 - clip.dstX1), 471 abs(clip.dstY0 - clip.dstY1)); 472 } 473 474 /* Try faster, direct texture approach first */ 475 if (mask & GL_COLOR_BUFFER_BIT) { 476 if (blitframebuffer_texture(ctx, readFb, drawFb, 477 srcX0, srcY0, srcX1, srcY1, 478 dstX0, dstY0, dstX1, dstY1, 479 filter, dstFlipX, dstFlipY, 480 use_glsl_version, false)) { 481 mask &= ~GL_COLOR_BUFFER_BIT; 482 } 483 } 484 485 if (mask & GL_DEPTH_BUFFER_BIT && use_glsl_version) { 486 if (blitframebuffer_texture(ctx, readFb, drawFb, 487 srcX0, srcY0, srcX1, srcY1, 488 dstX0, dstY0, dstX1, dstY1, 489 filter, dstFlipX, dstFlipY, 490 use_glsl_version, true)) { 491 mask &= ~GL_DEPTH_BUFFER_BIT; 492 } 493 } 494 495 if (mask & GL_STENCIL_BUFFER_BIT) { 496 /* XXX can't easily do stencil */ 497 } 498 499 _mesa_meta_end(ctx); 500 501 return mask; 502} 503 504void 505_mesa_meta_glsl_blit_cleanup(struct gl_context *ctx, struct blit_state *blit) 506{ 507 if (blit->VAO) { 508 _mesa_DeleteVertexArrays(1, &blit->VAO); 509 blit->VAO = 0; 510 _mesa_reference_buffer_object(ctx, &blit->buf_obj, NULL); 511 } 512 513 _mesa_meta_blit_shader_table_cleanup(ctx, &blit->shaders_with_depth); 514 _mesa_meta_blit_shader_table_cleanup(ctx, &blit->shaders_without_depth); 515 516 if (blit->depthTex.tex_obj != NULL) { 517 _mesa_delete_nameless_texture(ctx, blit->depthTex.tex_obj); 518 blit->depthTex.tex_obj = NULL; 519 } 520} 521 522void 523_mesa_meta_and_swrast_BlitFramebuffer(struct gl_context *ctx, 524 struct gl_framebuffer *readFb, 525 struct gl_framebuffer *drawFb, 526 GLint srcX0, GLint srcY0, 527 GLint srcX1, GLint srcY1, 528 GLint dstX0, GLint dstY0, 529 GLint dstX1, GLint dstY1, 530 GLbitfield mask, GLenum filter) 531{ 532 mask = _mesa_meta_BlitFramebuffer(ctx, readFb, drawFb, 533 srcX0, srcY0, srcX1, srcY1, 534 dstX0, dstY0, dstX1, dstY1, 535 mask, filter); 536 if (mask == 0x0) 537 return; 538 539 _swrast_BlitFramebuffer(ctx, readFb, drawFb, 540 srcX0, srcY0, srcX1, srcY1, 541 dstX0, dstY0, dstX1, dstY1, 542 mask, filter); 543} 544