1 /************************************************************************** 2 * 3 * Copyright 2006 VMware, Inc. 4 * 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 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 29 #include "main/enums.h" 30 #include "main/imports.h" 31 #include "main/macros.h" 32 #include "main/mtypes.h" 33 #include "main/fbobject.h" 34 #include "main/framebuffer.h" 35 #include "main/renderbuffer.h" 36 #include "main/context.h" 37 #include "main/teximage.h" 38 #include "main/image.h" 39 40 #include "swrast/swrast.h" 41 #include "drivers/common/meta.h" 42 43 #include "intel_context.h" 44 #include "intel_batchbuffer.h" 45 #include "intel_buffers.h" 46 #include "intel_blit.h" 47 #include "intel_fbo.h" 48 #include "intel_mipmap_tree.h" 49 #include "intel_regions.h" 50 #include "intel_tex.h" 51 52 #define FILE_DEBUG_FLAG DEBUG_FBO 53 54 static struct gl_renderbuffer * 55 intel_new_renderbuffer(struct gl_context * ctx, GLuint name); 56 57 struct intel_region* 58 intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex) 59 { 60 struct intel_renderbuffer *irb = intel_get_renderbuffer(fb, attIndex); 61 if (irb && irb->mt) 62 return irb->mt->region; 63 else 64 return NULL; 65 } 66 67 /** Called by gl_renderbuffer::Delete() */ 68 static void 69 intel_delete_renderbuffer(struct gl_context *ctx, struct gl_renderbuffer *rb) 70 { 71 struct intel_renderbuffer *irb = intel_renderbuffer(rb); 72 73 assert(irb); 74 75 intel_miptree_release(&irb->mt); 76 77 _mesa_delete_renderbuffer(ctx, rb); 78 } 79 80 /** 81 * \see dd_function_table::MapRenderbuffer 82 */ 83 static void 84 intel_map_renderbuffer(struct gl_context *ctx, 85 struct gl_renderbuffer *rb, 86 GLuint x, GLuint y, GLuint w, GLuint h, 87 GLbitfield mode, 88 GLubyte **out_map, 89 GLint *out_stride) 90 { 91 struct intel_context *intel = intel_context(ctx); 92 struct swrast_renderbuffer *srb = (struct swrast_renderbuffer *)rb; 93 struct intel_renderbuffer *irb = intel_renderbuffer(rb); 94 void *map; 95 int stride; 96 97 if (srb->Buffer) { 98 /* this is a malloc'd renderbuffer (accum buffer), not an irb */ 99 GLint bpp = _mesa_get_format_bytes(rb->Format); 100 GLint rowStride = srb->RowStride; 101 *out_map = (GLubyte *) srb->Buffer + y * rowStride + x * bpp; 102 *out_stride = rowStride; 103 return; 104 } 105 106 intel_prepare_render(intel); 107 108 /* For a window-system renderbuffer, we need to flip the mapping we receive 109 * upside-down. So we need to ask for a rectangle on flipped vertically, and 110 * we then return a pointer to the bottom of it with a negative stride. 111 */ 112 if (rb->Name == 0) { 113 y = rb->Height - y - h; 114 } 115 116 intel_miptree_map(intel, irb->mt, irb->mt_level, irb->mt_layer, 117 x, y, w, h, mode, &map, &stride); 118 119 if (rb->Name == 0) { 120 map += (h - 1) * stride; 121 stride = -stride; 122 } 123 124 DBG("%s: rb %d (%s) mt mapped: (%d, %d) (%dx%d) -> %p/%d\n", 125 __func__, rb->Name, _mesa_get_format_name(rb->Format), 126 x, y, w, h, map, stride); 127 128 *out_map = map; 129 *out_stride = stride; 130 } 131 132 /** 133 * \see dd_function_table::UnmapRenderbuffer 134 */ 135 static void 136 intel_unmap_renderbuffer(struct gl_context *ctx, 137 struct gl_renderbuffer *rb) 138 { 139 struct intel_context *intel = intel_context(ctx); 140 struct swrast_renderbuffer *srb = (struct swrast_renderbuffer *)rb; 141 struct intel_renderbuffer *irb = intel_renderbuffer(rb); 142 143 DBG("%s: rb %d (%s)\n", __func__, 144 rb->Name, _mesa_get_format_name(rb->Format)); 145 146 if (srb->Buffer) { 147 /* this is a malloc'd renderbuffer (accum buffer) */ 148 /* nothing to do */ 149 return; 150 } 151 152 intel_miptree_unmap(intel, irb->mt, irb->mt_level, irb->mt_layer); 153 } 154 155 static mesa_format 156 intel_renderbuffer_format(struct gl_context * ctx, GLenum internalFormat) 157 { 158 struct intel_context *intel = intel_context(ctx); 159 160 switch (internalFormat) { 161 default: 162 /* Use the same format-choice logic as for textures. 163 * Renderbuffers aren't any different from textures for us, 164 * except they're less useful because you can't texture with 165 * them. 166 */ 167 return intel->ctx.Driver.ChooseTextureFormat(ctx, GL_TEXTURE_2D, 168 internalFormat, 169 GL_NONE, GL_NONE); 170 171 case GL_DEPTH_COMPONENT16: 172 return MESA_FORMAT_Z_UNORM16; 173 case GL_DEPTH_COMPONENT: 174 case GL_DEPTH_COMPONENT24: 175 case GL_DEPTH_COMPONENT32: 176 return MESA_FORMAT_Z24_UNORM_X8_UINT; 177 case GL_DEPTH_STENCIL_EXT: 178 case GL_DEPTH24_STENCIL8_EXT: 179 case GL_STENCIL_INDEX: 180 case GL_STENCIL_INDEX1_EXT: 181 case GL_STENCIL_INDEX4_EXT: 182 case GL_STENCIL_INDEX8_EXT: 183 case GL_STENCIL_INDEX16_EXT: 184 /* These aren't actual texture formats, so force them here. */ 185 return MESA_FORMAT_Z24_UNORM_S8_UINT; 186 } 187 } 188 189 static GLboolean 190 intel_alloc_private_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, 191 GLenum internalFormat, 192 GLuint width, GLuint height) 193 { 194 struct intel_context *intel = intel_context(ctx); 195 struct intel_renderbuffer *irb = intel_renderbuffer(rb); 196 197 assert(rb->Format != MESA_FORMAT_NONE); 198 199 rb->Width = width; 200 rb->Height = height; 201 rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat); 202 203 intel_miptree_release(&irb->mt); 204 205 DBG("%s: %s: %s (%dx%d)\n", __func__, 206 _mesa_enum_to_string(internalFormat), 207 _mesa_get_format_name(rb->Format), width, height); 208 209 if (width == 0 || height == 0) 210 return true; 211 212 irb->mt = intel_miptree_create_for_renderbuffer(intel, rb->Format, 213 width, height); 214 if (!irb->mt) 215 return false; 216 217 return true; 218 } 219 220 /** 221 * Called via glRenderbufferStorageEXT() to set the format and allocate 222 * storage for a user-created renderbuffer. 223 */ 224 static GLboolean 225 intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, 226 GLenum internalFormat, 227 GLuint width, GLuint height) 228 { 229 rb->Format = intel_renderbuffer_format(ctx, internalFormat); 230 return intel_alloc_private_renderbuffer_storage(ctx, rb, internalFormat, width, height); 231 } 232 233 static void 234 intel_image_target_renderbuffer_storage(struct gl_context *ctx, 235 struct gl_renderbuffer *rb, 236 void *image_handle) 237 { 238 struct intel_context *intel = intel_context(ctx); 239 struct intel_renderbuffer *irb; 240 __DRIscreen *screen; 241 __DRIimage *image; 242 243 screen = intel->intelScreen->driScrnPriv; 244 image = screen->dri2.image->lookupEGLImage(screen, image_handle, 245 screen->loaderPrivate); 246 if (image == NULL) 247 return; 248 249 /* __DRIimage is opaque to the core so it has to be checked here */ 250 switch (image->format) { 251 case MESA_FORMAT_R8G8B8A8_UNORM: 252 _mesa_error(&intel->ctx, GL_INVALID_OPERATION, 253 "glEGLImageTargetRenderbufferStorage(unsupported image format"); 254 return; 255 break; 256 default: 257 break; 258 } 259 260 irb = intel_renderbuffer(rb); 261 intel_miptree_release(&irb->mt); 262 irb->mt = intel_miptree_create_for_bo(intel, 263 image->region->bo, 264 image->format, 265 image->offset, 266 image->region->width, 267 image->region->height, 268 image->region->pitch, 269 image->region->tiling); 270 if (!irb->mt) 271 return; 272 273 rb->InternalFormat = image->internal_format; 274 rb->Width = image->region->width; 275 rb->Height = image->region->height; 276 rb->Format = image->format; 277 rb->_BaseFormat = _mesa_get_format_base_format(image->format); 278 rb->NeedsFinishRenderTexture = true; 279 } 280 281 /** 282 * Called by _mesa_resize_framebuffer() for each hardware renderbuffer when a 283 * window system framebuffer is resized. 284 * 285 * Any actual buffer reallocations for hardware renderbuffers (which would 286 * have triggered _mesa_resize_framebuffer()) were done by 287 * intel_process_dri2_buffer(). 288 */ 289 static GLboolean 290 intel_alloc_window_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, 291 GLenum internalFormat, GLuint width, GLuint height) 292 { 293 assert(rb->Name == 0); 294 rb->Width = width; 295 rb->Height = height; 296 rb->InternalFormat = internalFormat; 297 298 return true; 299 } 300 301 /** Dummy function for gl_renderbuffer::AllocStorage() */ 302 static GLboolean 303 intel_nop_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, 304 GLenum internalFormat, GLuint width, GLuint height) 305 { 306 _mesa_problem(ctx, "intel_op_alloc_storage should never be called."); 307 return false; 308 } 309 310 /** 311 * Create a new intel_renderbuffer which corresponds to an on-screen window, 312 * not a user-created renderbuffer. 313 */ 314 struct intel_renderbuffer * 315 intel_create_renderbuffer(mesa_format format) 316 { 317 struct intel_renderbuffer *irb; 318 struct gl_renderbuffer *rb; 319 320 GET_CURRENT_CONTEXT(ctx); 321 322 irb = CALLOC_STRUCT(intel_renderbuffer); 323 if (!irb) { 324 _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer"); 325 return NULL; 326 } 327 328 rb = &irb->Base.Base; 329 330 _mesa_init_renderbuffer(rb, 0); 331 rb->ClassID = INTEL_RB_CLASS; 332 rb->_BaseFormat = _mesa_get_format_base_format(format); 333 rb->Format = format; 334 rb->InternalFormat = rb->_BaseFormat; 335 336 /* intel-specific methods */ 337 rb->Delete = intel_delete_renderbuffer; 338 rb->AllocStorage = intel_alloc_window_storage; 339 340 return irb; 341 } 342 343 /** 344 * Private window-system buffers (as opposed to ones shared with the display 345 * server created with intel_create_renderbuffer()) are most similar in their 346 * handling to user-created renderbuffers, but they have a resize handler that 347 * may be called at intel_update_renderbuffers() time. 348 */ 349 struct intel_renderbuffer * 350 intel_create_private_renderbuffer(mesa_format format) 351 { 352 struct intel_renderbuffer *irb; 353 354 irb = intel_create_renderbuffer(format); 355 irb->Base.Base.AllocStorage = intel_alloc_private_renderbuffer_storage; 356 357 return irb; 358 } 359 360 /** 361 * Create a new renderbuffer object. 362 * Typically called via glBindRenderbufferEXT(). 363 */ 364 static struct gl_renderbuffer * 365 intel_new_renderbuffer(struct gl_context * ctx, GLuint name) 366 { 367 /*struct intel_context *intel = intel_context(ctx); */ 368 struct intel_renderbuffer *irb; 369 struct gl_renderbuffer *rb; 370 371 irb = CALLOC_STRUCT(intel_renderbuffer); 372 if (!irb) { 373 _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer"); 374 return NULL; 375 } 376 377 rb = &irb->Base.Base; 378 379 _mesa_init_renderbuffer(rb, name); 380 rb->ClassID = INTEL_RB_CLASS; 381 382 /* intel-specific methods */ 383 rb->Delete = intel_delete_renderbuffer; 384 rb->AllocStorage = intel_alloc_renderbuffer_storage; 385 /* span routines set in alloc_storage function */ 386 387 return rb; 388 } 389 390 391 /** 392 * Called via glBindFramebufferEXT(). 393 */ 394 static void 395 intel_bind_framebuffer(struct gl_context * ctx, GLenum target, 396 struct gl_framebuffer *fb, struct gl_framebuffer *fbread) 397 { 398 if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) { 399 intel_draw_buffer(ctx); 400 } 401 else { 402 /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */ 403 } 404 } 405 406 407 /** 408 * Called via glFramebufferRenderbufferEXT(). 409 */ 410 static void 411 intel_framebuffer_renderbuffer(struct gl_context * ctx, 412 struct gl_framebuffer *fb, 413 GLenum attachment, struct gl_renderbuffer *rb) 414 { 415 DBG("Intel FramebufferRenderbuffer %u %u\n", fb->Name, rb ? rb->Name : 0); 416 417 _mesa_FramebufferRenderbuffer_sw(ctx, fb, attachment, rb); 418 intel_draw_buffer(ctx); 419 } 420 421 static bool 422 intel_renderbuffer_update_wrapper(struct intel_context *intel, 423 struct intel_renderbuffer *irb, 424 struct gl_texture_image *image, 425 uint32_t layer) 426 { 427 struct gl_renderbuffer *rb = &irb->Base.Base; 428 struct intel_texture_image *intel_image = intel_texture_image(image); 429 struct intel_mipmap_tree *mt = intel_image->mt; 430 int level = image->Level; 431 432 rb->AllocStorage = intel_nop_alloc_storage; 433 434 intel_miptree_check_level_layer(mt, level, layer); 435 irb->mt_level = level; 436 irb->mt_layer = layer; 437 438 intel_miptree_reference(&irb->mt, mt); 439 440 intel_renderbuffer_set_draw_offset(irb); 441 442 return true; 443 } 444 445 void 446 intel_renderbuffer_set_draw_offset(struct intel_renderbuffer *irb) 447 { 448 unsigned int dst_x, dst_y; 449 450 /* compute offset of the particular 2D image within the texture region */ 451 intel_miptree_get_image_offset(irb->mt, 452 irb->mt_level, 453 irb->mt_layer, 454 &dst_x, &dst_y); 455 456 irb->draw_x = dst_x; 457 irb->draw_y = dst_y; 458 } 459 460 /** 461 * Called by glFramebufferTexture[123]DEXT() (and other places) to 462 * prepare for rendering into texture memory. This might be called 463 * many times to choose different texture levels, cube faces, etc 464 * before intel_finish_render_texture() is ever called. 465 */ 466 static void 467 intel_render_texture(struct gl_context * ctx, 468 struct gl_framebuffer *fb, 469 struct gl_renderbuffer_attachment *att) 470 { 471 struct intel_context *intel = intel_context(ctx); 472 struct gl_renderbuffer *rb = att->Renderbuffer; 473 struct intel_renderbuffer *irb = intel_renderbuffer(rb); 474 struct gl_texture_image *image = rb->TexImage; 475 struct intel_texture_image *intel_image = intel_texture_image(image); 476 struct intel_mipmap_tree *mt = intel_image->mt; 477 int layer; 478 479 (void) fb; 480 481 if (att->CubeMapFace > 0) { 482 assert(att->Zoffset == 0); 483 layer = att->CubeMapFace; 484 } else { 485 layer = att->Zoffset; 486 } 487 488 if (!intel_image->mt) { 489 /* Fallback on drawing to a texture that doesn't have a miptree 490 * (has a border, width/height 0, etc.) 491 */ 492 _swrast_render_texture(ctx, fb, att); 493 return; 494 } 495 496 intel_miptree_check_level_layer(mt, att->TextureLevel, layer); 497 498 if (!intel_renderbuffer_update_wrapper(intel, irb, image, layer)) { 499 _swrast_render_texture(ctx, fb, att); 500 return; 501 } 502 503 DBG("Begin render %s texture tex=%u w=%d h=%d d=%d refcount=%d\n", 504 _mesa_get_format_name(image->TexFormat), 505 att->Texture->Name, image->Width, image->Height, image->Depth, 506 rb->RefCount); 507 508 /* update drawing region, etc */ 509 intel_draw_buffer(ctx); 510 } 511 512 513 /** 514 * Called by Mesa when rendering to a texture is done. 515 */ 516 static void 517 intel_finish_render_texture(struct gl_context * ctx, struct gl_renderbuffer *rb) 518 { 519 struct intel_context *intel = intel_context(ctx); 520 521 DBG("Finish render %s texture\n", _mesa_get_format_name(rb->Format)); 522 523 /* Since we've (probably) rendered to the texture and will (likely) use 524 * it in the texture domain later on in this batchbuffer, flush the 525 * batch. Once again, we wish for a domain tracker in libdrm to cover 526 * usage inside of a batchbuffer like GEM does in the kernel. 527 */ 528 intel_batchbuffer_emit_mi_flush(intel); 529 } 530 531 #define fbo_incomplete(fb, ...) do { \ 532 static GLuint msg_id = 0; \ 533 if (unlikely(ctx->Const.ContextFlags & GL_CONTEXT_FLAG_DEBUG_BIT)) { \ 534 _mesa_gl_debug(ctx, &msg_id, \ 535 MESA_DEBUG_SOURCE_API, \ 536 MESA_DEBUG_TYPE_OTHER, \ 537 MESA_DEBUG_SEVERITY_MEDIUM, \ 538 __VA_ARGS__); \ 539 } \ 540 DBG(__VA_ARGS__); \ 541 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED; \ 542 } while (0) 543 544 /** 545 * Do additional "completeness" testing of a framebuffer object. 546 */ 547 static void 548 intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) 549 { 550 struct intel_context *intel = intel_context(ctx); 551 struct intel_renderbuffer *depthRb = 552 intel_get_renderbuffer(fb, BUFFER_DEPTH); 553 struct intel_renderbuffer *stencilRb = 554 intel_get_renderbuffer(fb, BUFFER_STENCIL); 555 struct intel_mipmap_tree *depth_mt = NULL, *stencil_mt = NULL; 556 int i; 557 558 DBG("%s() on fb %p (%s)\n", __func__, 559 fb, (fb == ctx->DrawBuffer ? "drawbuffer" : 560 (fb == ctx->ReadBuffer ? "readbuffer" : "other buffer"))); 561 562 if (depthRb) 563 depth_mt = depthRb->mt; 564 if (stencilRb) 565 stencil_mt = stencilRb->mt; 566 567 if (depth_mt && stencil_mt) { 568 /* Make sure that the depth and stencil buffers are actually the same 569 * slice of the same miptree, since we only support packed 570 * depth/stencil. 571 */ 572 if (depth_mt == stencil_mt) { 573 if (depthRb->mt_level != stencilRb->mt_level || 574 depthRb->mt_layer != stencilRb->mt_layer) { 575 fbo_incomplete(fb, 576 "FBO incomplete: depth image level/layer %d/%d != " 577 "stencil image %d/%d\n", 578 depthRb->mt_level, 579 depthRb->mt_layer, 580 stencilRb->mt_level, 581 stencilRb->mt_layer); 582 } 583 } else { 584 fbo_incomplete(fb, "FBO incomplete: separate stencil unsupported\n"); 585 } 586 } 587 588 for (i = 0; i < ARRAY_SIZE(fb->Attachment); i++) { 589 struct gl_renderbuffer *rb; 590 struct intel_renderbuffer *irb; 591 592 if (fb->Attachment[i].Type == GL_NONE) 593 continue; 594 595 /* A supported attachment will have a Renderbuffer set either 596 * from being a Renderbuffer or being a texture that got the 597 * intel_wrap_texture() treatment. 598 */ 599 rb = fb->Attachment[i].Renderbuffer; 600 if (rb == NULL) { 601 fbo_incomplete(fb, "FBO incomplete: attachment without " 602 "renderbuffer\n"); 603 continue; 604 } 605 606 if (fb->Attachment[i].Type == GL_TEXTURE) { 607 if (rb->TexImage->Border) { 608 fbo_incomplete(fb, "FBO incomplete: texture with border\n"); 609 continue; 610 } 611 } 612 613 irb = intel_renderbuffer(rb); 614 if (irb == NULL) { 615 fbo_incomplete(fb, "FBO incomplete: software rendering " 616 "renderbuffer\n"); 617 continue; 618 } 619 620 if (!intel->vtbl.render_target_supported(intel, rb)) { 621 fbo_incomplete(fb, "FBO incomplete: Unsupported HW " 622 "texture/renderbuffer format attached: %s\n", 623 _mesa_get_format_name(intel_rb_format(irb))); 624 } 625 } 626 } 627 628 /** 629 * Try to do a glBlitFramebuffer using glCopyTexSubImage2D 630 * We can do this when the dst renderbuffer is actually a texture and 631 * there is no scaling, mirroring or scissoring. 632 * 633 * \return new buffer mask indicating the buffers left to blit using the 634 * normal path. 635 */ 636 static GLbitfield 637 intel_blit_framebuffer_with_blitter(struct gl_context *ctx, 638 const struct gl_framebuffer *readFb, 639 const struct gl_framebuffer *drawFb, 640 GLint srcX0, GLint srcY0, 641 GLint srcX1, GLint srcY1, 642 GLint dstX0, GLint dstY0, 643 GLint dstX1, GLint dstY1, 644 GLbitfield mask, GLenum filter) 645 { 646 struct intel_context *intel = intel_context(ctx); 647 648 /* Sync up the state of window system buffers. We need to do this before 649 * we go looking for the buffers. 650 */ 651 intel_prepare_render(intel); 652 653 if (mask & GL_COLOR_BUFFER_BIT) { 654 GLint i; 655 struct gl_renderbuffer *src_rb = readFb->_ColorReadBuffer; 656 struct intel_renderbuffer *src_irb = intel_renderbuffer(src_rb); 657 658 if (!src_irb) { 659 perf_debug("glBlitFramebuffer(): missing src renderbuffer. " 660 "Falling back to software rendering.\n"); 661 return mask; 662 } 663 664 /* If the source and destination are the same size with no mirroring, 665 * the rectangles are within the size of the texture and there is no 666 * scissor, then we can probably use the blit engine. 667 */ 668 if (!(srcX0 - srcX1 == dstX0 - dstX1 && 669 srcY0 - srcY1 == dstY0 - dstY1 && 670 srcX1 >= srcX0 && 671 srcY1 >= srcY0 && 672 srcX0 >= 0 && srcX1 <= readFb->Width && 673 srcY0 >= 0 && srcY1 <= readFb->Height && 674 dstX0 >= 0 && dstX1 <= drawFb->Width && 675 dstY0 >= 0 && dstY1 <= drawFb->Height && 676 !ctx->Scissor.EnableFlags)) { 677 perf_debug("glBlitFramebuffer(): non-1:1 blit. " 678 "Falling back to software rendering.\n"); 679 return mask; 680 } 681 682 /* Blit to all active draw buffers. We don't do any pre-checking, 683 * because we assume that copying to MRTs is rare, and failure midway 684 * through copying is even more rare. Even if it was to occur, it's 685 * safe to let meta start the copy over from scratch, because 686 * glBlitFramebuffer completely overwrites the destination pixels, and 687 * results are undefined if any destination pixels have a dependency on 688 * source pixels. 689 */ 690 for (i = 0; i < drawFb->_NumColorDrawBuffers; i++) { 691 struct gl_renderbuffer *dst_rb = drawFb->_ColorDrawBuffers[i]; 692 struct intel_renderbuffer *dst_irb = intel_renderbuffer(dst_rb); 693 694 if (!dst_irb) { 695 perf_debug("glBlitFramebuffer(): missing dst renderbuffer. " 696 "Falling back to software rendering.\n"); 697 return mask; 698 } 699 700 mesa_format src_format = _mesa_get_srgb_format_linear(src_rb->Format); 701 mesa_format dst_format = _mesa_get_srgb_format_linear(dst_rb->Format); 702 if (src_format != dst_format) { 703 perf_debug("glBlitFramebuffer(): unsupported blit from %s to %s. " 704 "Falling back to software rendering.\n", 705 _mesa_get_format_name(src_format), 706 _mesa_get_format_name(dst_format)); 707 return mask; 708 } 709 710 if (!intel_miptree_blit(intel, 711 src_irb->mt, 712 src_irb->mt_level, src_irb->mt_layer, 713 srcX0, srcY0, src_rb->Name == 0, 714 dst_irb->mt, 715 dst_irb->mt_level, dst_irb->mt_layer, 716 dstX0, dstY0, dst_rb->Name == 0, 717 dstX1 - dstX0, dstY1 - dstY0, GL_COPY)) { 718 perf_debug("glBlitFramebuffer(): unknown blit failure. " 719 "Falling back to software rendering.\n"); 720 return mask; 721 } 722 } 723 724 mask &= ~GL_COLOR_BUFFER_BIT; 725 } 726 727 return mask; 728 } 729 730 static void 731 intel_blit_framebuffer(struct gl_context *ctx, 732 struct gl_framebuffer *readFb, 733 struct gl_framebuffer *drawFb, 734 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 735 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, 736 GLbitfield mask, GLenum filter) 737 { 738 /* Try using the BLT engine. */ 739 mask = intel_blit_framebuffer_with_blitter(ctx, readFb, drawFb, 740 srcX0, srcY0, srcX1, srcY1, 741 dstX0, dstY0, dstX1, dstY1, 742 mask, filter); 743 if (mask == 0x0) 744 return; 745 746 747 _mesa_meta_and_swrast_BlitFramebuffer(ctx, readFb, drawFb, 748 srcX0, srcY0, srcX1, srcY1, 749 dstX0, dstY0, dstX1, dstY1, 750 mask, filter); 751 } 752 753 /** 754 * Do one-time context initializations related to GL_EXT_framebuffer_object. 755 * Hook in device driver functions. 756 */ 757 void 758 intel_fbo_init(struct intel_context *intel) 759 { 760 intel->ctx.Driver.NewRenderbuffer = intel_new_renderbuffer; 761 intel->ctx.Driver.MapRenderbuffer = intel_map_renderbuffer; 762 intel->ctx.Driver.UnmapRenderbuffer = intel_unmap_renderbuffer; 763 intel->ctx.Driver.BindFramebuffer = intel_bind_framebuffer; 764 intel->ctx.Driver.FramebufferRenderbuffer = intel_framebuffer_renderbuffer; 765 intel->ctx.Driver.RenderTexture = intel_render_texture; 766 intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture; 767 intel->ctx.Driver.ValidateFramebuffer = intel_validate_framebuffer; 768 intel->ctx.Driver.BlitFramebuffer = intel_blit_framebuffer; 769 intel->ctx.Driver.EGLImageTargetRenderbufferStorage = 770 intel_image_target_renderbuffer_storage; 771 } 772