intel_fbo.c revision 19e9b24626c2b9d7abef054d57bb2a52106c545b
1/************************************************************************** 2 * 3 * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. 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 TUNGSTEN GRAPHICS 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/mfeatures.h" 33#include "main/mtypes.h" 34#include "main/fbobject.h" 35#include "main/framebuffer.h" 36#include "main/renderbuffer.h" 37#include "main/context.h" 38#include "main/teximage.h" 39#include "main/image.h" 40 41#include "swrast/swrast.h" 42#include "drivers/common/meta.h" 43 44#include "intel_context.h" 45#include "intel_batchbuffer.h" 46#include "intel_buffers.h" 47#include "intel_blit.h" 48#include "intel_fbo.h" 49#include "intel_mipmap_tree.h" 50#include "intel_regions.h" 51#include "intel_tex.h" 52#include "intel_span.h" 53#ifndef I915 54#include "brw_context.h" 55#endif 56 57#define FILE_DEBUG_FLAG DEBUG_FBO 58 59static struct gl_renderbuffer * 60intel_new_renderbuffer(struct gl_context * ctx, GLuint name); 61 62bool 63intel_framebuffer_has_hiz(struct gl_framebuffer *fb) 64{ 65 struct intel_renderbuffer *rb = NULL; 66 if (fb) 67 rb = intel_get_renderbuffer(fb, BUFFER_DEPTH); 68 return rb && rb->mt && rb->mt->hiz_mt; 69} 70 71struct intel_region* 72intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex) 73{ 74 struct intel_renderbuffer *irb = intel_get_renderbuffer(fb, attIndex); 75 if (irb && irb->mt) { 76 if (attIndex == BUFFER_STENCIL && irb->mt->stencil_mt) 77 return irb->mt->stencil_mt->region; 78 else 79 return irb->mt->region; 80 } else 81 return NULL; 82} 83 84/** 85 * Create a new framebuffer object. 86 */ 87static struct gl_framebuffer * 88intel_new_framebuffer(struct gl_context * ctx, GLuint name) 89{ 90 /* Only drawable state in intel_framebuffer at this time, just use Mesa's 91 * class 92 */ 93 return _mesa_new_framebuffer(ctx, name); 94} 95 96 97/** Called by gl_renderbuffer::Delete() */ 98static void 99intel_delete_renderbuffer(struct gl_renderbuffer *rb) 100{ 101 struct intel_renderbuffer *irb = intel_renderbuffer(rb); 102 103 ASSERT(irb); 104 105 intel_miptree_release(&irb->mt); 106 107 free(irb); 108} 109 110/** 111 * \see dd_function_table::MapRenderbuffer 112 */ 113static void 114intel_map_renderbuffer(struct gl_context *ctx, 115 struct gl_renderbuffer *rb, 116 GLuint x, GLuint y, GLuint w, GLuint h, 117 GLbitfield mode, 118 GLubyte **out_map, 119 GLint *out_stride) 120{ 121 struct intel_context *intel = intel_context(ctx); 122 struct swrast_renderbuffer *srb = (struct swrast_renderbuffer *)rb; 123 struct intel_renderbuffer *irb = intel_renderbuffer(rb); 124 void *map; 125 int stride; 126 127 if (srb->Buffer) { 128 /* this is a malloc'd renderbuffer (accum buffer), not an irb */ 129 GLint bpp = _mesa_get_format_bytes(rb->Format); 130 GLint rowStride = srb->RowStride; 131 *out_map = (GLubyte *) srb->Buffer + y * rowStride + x * bpp; 132 *out_stride = rowStride; 133 return; 134 } 135 136 /* We sometimes get called with this by our intel_span.c usage. */ 137 if (!irb->mt) { 138 *out_map = NULL; 139 *out_stride = 0; 140 return; 141 } 142 143 /* For a window-system renderbuffer, we need to flip the mapping we receive 144 * upside-down. So we need to ask for a rectangle on flipped vertically, and 145 * we then return a pointer to the bottom of it with a negative stride. 146 */ 147 if (rb->Name == 0) { 148 y = rb->Height - y - h; 149 } 150 151 intel_miptree_map(intel, irb->mt, irb->mt_level, irb->mt_layer, 152 x, y, w, h, mode, &map, &stride); 153 154 if (rb->Name == 0) { 155 map += (h - 1) * stride; 156 stride = -stride; 157 } 158 159 DBG("%s: rb %d (%s) mt mapped: (%d, %d) (%dx%d) -> %p/%d\n", 160 __FUNCTION__, rb->Name, _mesa_get_format_name(rb->Format), 161 x, y, w, h, map, stride); 162 163 *out_map = map; 164 *out_stride = stride; 165} 166 167/** 168 * \see dd_function_table::UnmapRenderbuffer 169 */ 170static void 171intel_unmap_renderbuffer(struct gl_context *ctx, 172 struct gl_renderbuffer *rb) 173{ 174 struct intel_context *intel = intel_context(ctx); 175 struct swrast_renderbuffer *srb = (struct swrast_renderbuffer *)rb; 176 struct intel_renderbuffer *irb = intel_renderbuffer(rb); 177 178 DBG("%s: rb %d (%s)\n", __FUNCTION__, 179 rb->Name, _mesa_get_format_name(rb->Format)); 180 181 if (srb->Buffer) { 182 /* this is a malloc'd renderbuffer (accum buffer) */ 183 /* nothing to do */ 184 return; 185 } 186 187 intel_miptree_unmap(intel, irb->mt, irb->mt_level, irb->mt_layer); 188} 189 190 191/** 192 * Round up the requested multisample count to the next supported sample size. 193 */ 194static unsigned 195quantize_num_samples(struct intel_context *intel, unsigned num_samples) 196{ 197 switch (intel->gen) { 198 case 6: 199 /* Gen6 supports only 4x multisampling. */ 200 if (num_samples > 0) 201 return 4; 202 else 203 return 0; 204 case 7: 205 /* TODO: MSAA only implemented on Gen6 */ 206 return 0; 207 default: 208 /* MSAA unsupported */ 209 return 0; 210 } 211} 212 213 214/** 215 * Called via glRenderbufferStorageEXT() to set the format and allocate 216 * storage for a user-created renderbuffer. 217 */ 218GLboolean 219intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, 220 GLenum internalFormat, 221 GLuint width, GLuint height) 222{ 223 struct intel_context *intel = intel_context(ctx); 224 struct intel_renderbuffer *irb = intel_renderbuffer(rb); 225 rb->NumSamples = quantize_num_samples(intel, rb->NumSamples); 226 227 ASSERT(rb->Name != 0); 228 229 switch (internalFormat) { 230 default: 231 /* Use the same format-choice logic as for textures. 232 * Renderbuffers aren't any different from textures for us, 233 * except they're less useful because you can't texture with 234 * them. 235 */ 236 rb->Format = intel->ctx.Driver.ChooseTextureFormat(ctx, internalFormat, 237 GL_NONE, GL_NONE); 238 break; 239 case GL_STENCIL_INDEX: 240 case GL_STENCIL_INDEX1_EXT: 241 case GL_STENCIL_INDEX4_EXT: 242 case GL_STENCIL_INDEX8_EXT: 243 case GL_STENCIL_INDEX16_EXT: 244 /* These aren't actual texture formats, so force them here. */ 245 if (intel->has_separate_stencil) { 246 rb->Format = MESA_FORMAT_S8; 247 } else { 248 assert(!intel->must_use_separate_stencil); 249 rb->Format = MESA_FORMAT_S8_Z24; 250 } 251 break; 252 } 253 254 rb->Width = width; 255 rb->Height = height; 256 rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat); 257 258 intel_miptree_release(&irb->mt); 259 260 DBG("%s: %s: %s (%dx%d)\n", __FUNCTION__, 261 _mesa_lookup_enum_by_nr(internalFormat), 262 _mesa_get_format_name(rb->Format), width, height); 263 264 if (width == 0 || height == 0) 265 return true; 266 267 irb->mt = intel_miptree_create_for_renderbuffer(intel, rb->Format, 268 width, height, 269 rb->NumSamples); 270 if (!irb->mt) 271 return false; 272 273 if (intel->vtbl.is_hiz_depth_format(intel, rb->Format)) { 274 bool ok = intel_miptree_alloc_hiz(intel, irb->mt, rb->NumSamples); 275 if (!ok) { 276 intel_miptree_release(&irb->mt); 277 return false; 278 } 279 } 280 281 return true; 282} 283 284 285#if FEATURE_OES_EGL_image 286static void 287intel_image_target_renderbuffer_storage(struct gl_context *ctx, 288 struct gl_renderbuffer *rb, 289 void *image_handle) 290{ 291 struct intel_context *intel = intel_context(ctx); 292 struct intel_renderbuffer *irb; 293 __DRIscreen *screen; 294 __DRIimage *image; 295 296 screen = intel->intelScreen->driScrnPriv; 297 image = screen->dri2.image->lookupEGLImage(screen, image_handle, 298 screen->loaderPrivate); 299 if (image == NULL) 300 return; 301 302 /* __DRIimage is opaque to the core so it has to be checked here */ 303 switch (image->format) { 304 case MESA_FORMAT_RGBA8888_REV: 305 _mesa_error(&intel->ctx, GL_INVALID_OPERATION, 306 "glEGLImageTargetRenderbufferStorage(unsupported image format"); 307 return; 308 break; 309 default: 310 break; 311 } 312 313 irb = intel_renderbuffer(rb); 314 intel_miptree_release(&irb->mt); 315 irb->mt = intel_miptree_create_for_region(intel, 316 GL_TEXTURE_2D, 317 image->format, 318 image->region); 319 if (!irb->mt) 320 return; 321 322 rb->InternalFormat = image->internal_format; 323 rb->Width = image->region->width; 324 rb->Height = image->region->height; 325 rb->Format = image->format; 326 rb->_BaseFormat = _mesa_base_fbo_format(&intel->ctx, 327 image->internal_format); 328} 329#endif 330 331/** 332 * Called for each hardware renderbuffer when a _window_ is resized. 333 * Just update fields. 334 * Not used for user-created renderbuffers! 335 */ 336static GLboolean 337intel_alloc_window_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, 338 GLenum internalFormat, GLuint width, GLuint height) 339{ 340 ASSERT(rb->Name == 0); 341 rb->Width = width; 342 rb->Height = height; 343 rb->InternalFormat = internalFormat; 344 345 return true; 346} 347 348 349static void 350intel_resize_buffers(struct gl_context *ctx, struct gl_framebuffer *fb, 351 GLuint width, GLuint height) 352{ 353 int i; 354 355 _mesa_resize_framebuffer(ctx, fb, width, height); 356 357 fb->Initialized = true; /* XXX remove someday */ 358 359 if (fb->Name != 0) { 360 return; 361 } 362 363 364 /* Make sure all window system renderbuffers are up to date */ 365 for (i = BUFFER_FRONT_LEFT; i <= BUFFER_BACK_RIGHT; i++) { 366 struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer; 367 368 /* only resize if size is changing */ 369 if (rb && (rb->Width != width || rb->Height != height)) { 370 rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height); 371 } 372 } 373} 374 375 376/** Dummy function for gl_renderbuffer::AllocStorage() */ 377static GLboolean 378intel_nop_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, 379 GLenum internalFormat, GLuint width, GLuint height) 380{ 381 _mesa_problem(ctx, "intel_op_alloc_storage should never be called."); 382 return false; 383} 384 385/** 386 * Create a new intel_renderbuffer which corresponds to an on-screen window, 387 * not a user-created renderbuffer. 388 */ 389struct intel_renderbuffer * 390intel_create_renderbuffer(gl_format format) 391{ 392 struct intel_renderbuffer *irb; 393 struct gl_renderbuffer *rb; 394 395 GET_CURRENT_CONTEXT(ctx); 396 397 irb = CALLOC_STRUCT(intel_renderbuffer); 398 if (!irb) { 399 _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer"); 400 return NULL; 401 } 402 403 rb = &irb->Base.Base; 404 405 _mesa_init_renderbuffer(rb, 0); 406 rb->ClassID = INTEL_RB_CLASS; 407 rb->_BaseFormat = _mesa_get_format_base_format(format); 408 rb->Format = format; 409 rb->InternalFormat = rb->_BaseFormat; 410 411 /* intel-specific methods */ 412 rb->Delete = intel_delete_renderbuffer; 413 rb->AllocStorage = intel_alloc_window_storage; 414 415 return irb; 416} 417 418/** 419 * Create a new renderbuffer object. 420 * Typically called via glBindRenderbufferEXT(). 421 */ 422static struct gl_renderbuffer * 423intel_new_renderbuffer(struct gl_context * ctx, GLuint name) 424{ 425 /*struct intel_context *intel = intel_context(ctx); */ 426 struct intel_renderbuffer *irb; 427 struct gl_renderbuffer *rb; 428 429 irb = CALLOC_STRUCT(intel_renderbuffer); 430 if (!irb) { 431 _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer"); 432 return NULL; 433 } 434 435 rb = &irb->Base.Base; 436 437 _mesa_init_renderbuffer(rb, name); 438 rb->ClassID = INTEL_RB_CLASS; 439 440 /* intel-specific methods */ 441 rb->Delete = intel_delete_renderbuffer; 442 rb->AllocStorage = intel_alloc_renderbuffer_storage; 443 /* span routines set in alloc_storage function */ 444 445 return rb; 446} 447 448 449/** 450 * Called via glBindFramebufferEXT(). 451 */ 452static void 453intel_bind_framebuffer(struct gl_context * ctx, GLenum target, 454 struct gl_framebuffer *fb, struct gl_framebuffer *fbread) 455{ 456 if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) { 457 intel_draw_buffer(ctx); 458 } 459 else { 460 /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */ 461 } 462} 463 464 465/** 466 * Called via glFramebufferRenderbufferEXT(). 467 */ 468static void 469intel_framebuffer_renderbuffer(struct gl_context * ctx, 470 struct gl_framebuffer *fb, 471 GLenum attachment, struct gl_renderbuffer *rb) 472{ 473 DBG("Intel FramebufferRenderbuffer %u %u\n", fb->Name, rb ? rb->Name : 0); 474 475 _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb); 476 intel_draw_buffer(ctx); 477} 478 479/** 480 * \par Special case for separate stencil 481 * 482 * When wrapping a depthstencil texture that uses separate stencil, this 483 * function is recursively called twice: once to create \c 484 * irb->wrapped_depth and again to create \c irb->wrapped_stencil. On the 485 * call to create \c irb->wrapped_depth, the \c format and \c 486 * internal_format parameters do not match \c mt->format. In that case, \c 487 * mt->format is MESA_FORMAT_S8_Z24 and \c format is \c 488 * MESA_FORMAT_X8_Z24. 489 * 490 * @return true on success 491 */ 492 493static bool 494intel_renderbuffer_update_wrapper(struct intel_context *intel, 495 struct intel_renderbuffer *irb, 496 struct gl_texture_image *image, 497 uint32_t layer) 498{ 499 struct gl_renderbuffer *rb = &irb->Base.Base; 500 struct intel_texture_image *intel_image = intel_texture_image(image); 501 struct intel_mipmap_tree *mt = intel_image->mt; 502 int level = image->Level; 503 504 rb->Format = image->TexFormat; 505 rb->InternalFormat = image->InternalFormat; 506 rb->_BaseFormat = image->_BaseFormat; 507 rb->Width = mt->level[level].width; 508 rb->Height = mt->level[level].height; 509 510 rb->Delete = intel_delete_renderbuffer; 511 rb->AllocStorage = intel_nop_alloc_storage; 512 513 intel_miptree_check_level_layer(mt, level, layer); 514 irb->mt_level = level; 515 irb->mt_layer = layer; 516 517 intel_miptree_reference(&irb->mt, mt); 518 519 intel_renderbuffer_set_draw_offset(irb); 520 521 if (mt->hiz_mt == NULL && 522 intel->vtbl.is_hiz_depth_format(intel, rb->Format)) { 523 intel_miptree_alloc_hiz(intel, mt, 0 /* num_samples */); 524 if (!mt->hiz_mt) 525 return false; 526 } 527 528 return true; 529} 530 531void 532intel_renderbuffer_set_draw_offset(struct intel_renderbuffer *irb) 533{ 534 unsigned int dst_x, dst_y; 535 536 /* compute offset of the particular 2D image within the texture region */ 537 intel_miptree_get_image_offset(irb->mt, 538 irb->mt_level, 539 0, /* face, which we ignore */ 540 irb->mt_layer, 541 &dst_x, &dst_y); 542 543 irb->draw_x = dst_x; 544 irb->draw_y = dst_y; 545} 546 547/** 548 * Rendering to tiled buffers requires that the base address of the 549 * buffer be aligned to a page boundary. We generally render to 550 * textures by pointing the surface at the mipmap image level, which 551 * may not be aligned to a tile boundary. 552 * 553 * This function returns an appropriately-aligned base offset 554 * according to the tiling restrictions, plus any required x/y offset 555 * from there. 556 */ 557uint32_t 558intel_renderbuffer_tile_offsets(struct intel_renderbuffer *irb, 559 uint32_t *tile_x, 560 uint32_t *tile_y) 561{ 562 struct intel_region *region = irb->mt->region; 563 uint32_t mask_x, mask_y; 564 565 intel_region_get_tile_masks(region, &mask_x, &mask_y); 566 567 *tile_x = irb->draw_x & mask_x; 568 *tile_y = irb->draw_y & mask_y; 569 return intel_region_get_aligned_offset(region, irb->draw_x & ~mask_x, 570 irb->draw_y & ~mask_y); 571} 572 573/** 574 * Called by glFramebufferTexture[123]DEXT() (and other places) to 575 * prepare for rendering into texture memory. This might be called 576 * many times to choose different texture levels, cube faces, etc 577 * before intel_finish_render_texture() is ever called. 578 */ 579static void 580intel_render_texture(struct gl_context * ctx, 581 struct gl_framebuffer *fb, 582 struct gl_renderbuffer_attachment *att) 583{ 584 struct intel_context *intel = intel_context(ctx); 585 struct gl_texture_image *image = _mesa_get_attachment_teximage(att); 586 struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer); 587 struct intel_texture_image *intel_image = intel_texture_image(image); 588 struct intel_mipmap_tree *mt = intel_image->mt; 589 int layer; 590 591 (void) fb; 592 593 if (att->CubeMapFace > 0) { 594 assert(att->Zoffset == 0); 595 layer = att->CubeMapFace; 596 } else { 597 layer = att->Zoffset; 598 } 599 600 if (!intel_image->mt) { 601 /* Fallback on drawing to a texture that doesn't have a miptree 602 * (has a border, width/height 0, etc.) 603 */ 604 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); 605 _swrast_render_texture(ctx, fb, att); 606 return; 607 } 608 else if (!irb) { 609 intel_miptree_check_level_layer(mt, att->TextureLevel, layer); 610 611 irb = (struct intel_renderbuffer *)intel_new_renderbuffer(ctx, ~0); 612 613 if (irb) { 614 /* bind the wrapper to the attachment point */ 615 _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base.Base); 616 } 617 else { 618 /* fallback to software rendering */ 619 _swrast_render_texture(ctx, fb, att); 620 return; 621 } 622 } 623 624 if (!intel_renderbuffer_update_wrapper(intel, irb, image, layer)) { 625 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); 626 _swrast_render_texture(ctx, fb, att); 627 return; 628 } 629 630 irb->tex_image = image; 631 632 DBG("Begin render %s texture tex=%u w=%d h=%d refcount=%d\n", 633 _mesa_get_format_name(image->TexFormat), 634 att->Texture->Name, image->Width, image->Height, 635 irb->Base.Base.RefCount); 636 637 /* update drawing region, etc */ 638 intel_draw_buffer(ctx); 639} 640 641 642/** 643 * Called by Mesa when rendering to a texture is done. 644 */ 645static void 646intel_finish_render_texture(struct gl_context * ctx, 647 struct gl_renderbuffer_attachment *att) 648{ 649 struct intel_context *intel = intel_context(ctx); 650 struct gl_texture_object *tex_obj = att->Texture; 651 struct gl_texture_image *image = 652 tex_obj->Image[att->CubeMapFace][att->TextureLevel]; 653 struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer); 654 655 DBG("Finish render %s texture tex=%u\n", 656 _mesa_get_format_name(image->TexFormat), att->Texture->Name); 657 658 if (irb) 659 irb->tex_image = NULL; 660 661 /* Since we've (probably) rendered to the texture and will (likely) use 662 * it in the texture domain later on in this batchbuffer, flush the 663 * batch. Once again, we wish for a domain tracker in libdrm to cover 664 * usage inside of a batchbuffer like GEM does in the kernel. 665 */ 666 intel_batchbuffer_emit_mi_flush(intel); 667} 668 669/** 670 * Do additional "completeness" testing of a framebuffer object. 671 */ 672static void 673intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) 674{ 675 struct intel_context *intel = intel_context(ctx); 676 const struct intel_renderbuffer *depthRb = 677 intel_get_renderbuffer(fb, BUFFER_DEPTH); 678 const struct intel_renderbuffer *stencilRb = 679 intel_get_renderbuffer(fb, BUFFER_STENCIL); 680 struct intel_mipmap_tree *depth_mt = NULL, *stencil_mt = NULL; 681 int i; 682 683 DBG("%s() on fb %p (%s)\n", __FUNCTION__, 684 fb, (fb == ctx->DrawBuffer ? "drawbuffer" : 685 (fb == ctx->ReadBuffer ? "readbuffer" : "other buffer"))); 686 687 if (depthRb) 688 depth_mt = depthRb->mt; 689 if (stencilRb) { 690 stencil_mt = stencilRb->mt; 691 if (stencil_mt->stencil_mt) 692 stencil_mt = stencil_mt->stencil_mt; 693 } 694 695 if (depth_mt && stencil_mt) { 696 if (depth_mt == stencil_mt) { 697 /* For true packed depth/stencil (not faked on prefers-separate-stencil 698 * hardware) we need to be sure they're the same level/layer, since 699 * we'll be emitting a single packet describing the packed setup. 700 */ 701 if (depthRb->mt_level != stencilRb->mt_level || 702 depthRb->mt_layer != stencilRb->mt_layer) { 703 DBG("depth image level/layer %d/%d != stencil image %d/%d\n", 704 depthRb->mt_level, 705 depthRb->mt_layer, 706 stencilRb->mt_level, 707 stencilRb->mt_layer); 708 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; 709 } 710 } else { 711 if (!intel->has_separate_stencil) { 712 DBG("separate stencil unsupported\n"); 713 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; 714 } 715 if (stencil_mt->format != MESA_FORMAT_S8) { 716 DBG("separate stencil is %s instead of S8\n", 717 _mesa_get_format_name(stencil_mt->format)); 718 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; 719 } 720 if (intel->gen < 7 && depth_mt->hiz_mt == NULL) { 721 /* Before Gen7, separate depth and stencil buffers can be used 722 * only if HiZ is enabled. From the Sandybridge PRM, Volume 2, 723 * Part 1, Bit 3DSTATE_DEPTH_BUFFER.SeparateStencilBufferEnable: 724 * [DevSNB]: This field must be set to the same value (enabled 725 * or disabled) as Hierarchical Depth Buffer Enable. 726 */ 727 DBG("separate stencil without HiZ\n"); 728 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED; 729 } 730 } 731 } 732 733 for (i = 0; i < Elements(fb->Attachment); i++) { 734 struct gl_renderbuffer *rb; 735 struct intel_renderbuffer *irb; 736 737 if (fb->Attachment[i].Type == GL_NONE) 738 continue; 739 740 /* A supported attachment will have a Renderbuffer set either 741 * from being a Renderbuffer or being a texture that got the 742 * intel_wrap_texture() treatment. 743 */ 744 rb = fb->Attachment[i].Renderbuffer; 745 if (rb == NULL) { 746 DBG("attachment without renderbuffer\n"); 747 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; 748 continue; 749 } 750 751 if (fb->Attachment[i].Type == GL_TEXTURE) { 752 const struct gl_texture_image *img = 753 _mesa_get_attachment_teximage_const(&fb->Attachment[i]); 754 755 if (img->Border) { 756 DBG("texture with border\n"); 757 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; 758 continue; 759 } 760 } 761 762 irb = intel_renderbuffer(rb); 763 if (irb == NULL) { 764 DBG("software rendering renderbuffer\n"); 765 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; 766 continue; 767 } 768 769 if (!intel->vtbl.render_target_supported(intel, rb)) { 770 DBG("Unsupported HW texture/renderbuffer format attached: %s\n", 771 _mesa_get_format_name(intel_rb_format(irb))); 772 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; 773 } 774 } 775} 776 777/** 778 * Try to do a glBlitFramebuffer using glCopyTexSubImage2D 779 * We can do this when the dst renderbuffer is actually a texture and 780 * there is no scaling, mirroring or scissoring. 781 * 782 * \return new buffer mask indicating the buffers left to blit using the 783 * normal path. 784 */ 785static GLbitfield 786intel_blit_framebuffer_copy_tex_sub_image(struct gl_context *ctx, 787 GLint srcX0, GLint srcY0, 788 GLint srcX1, GLint srcY1, 789 GLint dstX0, GLint dstY0, 790 GLint dstX1, GLint dstY1, 791 GLbitfield mask, GLenum filter) 792{ 793 if (mask & GL_COLOR_BUFFER_BIT) { 794 const struct gl_framebuffer *drawFb = ctx->DrawBuffer; 795 const struct gl_framebuffer *readFb = ctx->ReadBuffer; 796 const struct gl_renderbuffer_attachment *drawAtt = 797 &drawFb->Attachment[drawFb->_ColorDrawBufferIndexes[0]]; 798 struct intel_renderbuffer *srcRb = 799 intel_renderbuffer(readFb->_ColorReadBuffer); 800 801 /* If the source and destination are the same size with no 802 mirroring, the rectangles are within the size of the 803 texture and there is no scissor then we can use 804 glCopyTexSubimage2D to implement the blit. This will end 805 up as a fast hardware blit on some drivers */ 806 if (srcRb && drawAtt && drawAtt->Texture && 807 srcX0 - srcX1 == dstX0 - dstX1 && 808 srcY0 - srcY1 == dstY0 - dstY1 && 809 srcX1 >= srcX0 && 810 srcY1 >= srcY0 && 811 srcX0 >= 0 && srcX1 <= readFb->Width && 812 srcY0 >= 0 && srcY1 <= readFb->Height && 813 dstX0 >= 0 && dstX1 <= drawFb->Width && 814 dstY0 >= 0 && dstY1 <= drawFb->Height && 815 !ctx->Scissor.Enabled) { 816 const struct gl_texture_object *texObj = drawAtt->Texture; 817 const GLuint dstLevel = drawAtt->TextureLevel; 818 const GLenum target = texObj->Target; 819 820 struct gl_texture_image *texImage = 821 _mesa_select_tex_image(ctx, texObj, target, dstLevel); 822 823 if (intel_copy_texsubimage(intel_context(ctx), 824 intel_texture_image(texImage), 825 dstX0, dstY0, 826 srcRb, 827 srcX0, srcY0, 828 srcX1 - srcX0, /* width */ 829 srcY1 - srcY0)) 830 mask &= ~GL_COLOR_BUFFER_BIT; 831 } 832 } 833 834 return mask; 835} 836 837static void 838intel_blit_framebuffer(struct gl_context *ctx, 839 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 840 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, 841 GLbitfield mask, GLenum filter) 842{ 843 /* Try faster, glCopyTexSubImage2D approach first which uses the BLT. */ 844 mask = intel_blit_framebuffer_copy_tex_sub_image(ctx, 845 srcX0, srcY0, srcX1, srcY1, 846 dstX0, dstY0, dstX1, dstY1, 847 mask, filter); 848 if (mask == 0x0) 849 return; 850 851#ifndef I915 852 mask = brw_blorp_framebuffer(intel_context(ctx), 853 srcX0, srcY0, srcX1, srcY1, 854 dstX0, dstY0, dstX1, dstY1, 855 mask, filter); 856 if (mask == 0x0) 857 return; 858#endif 859 860 _mesa_meta_BlitFramebuffer(ctx, 861 srcX0, srcY0, srcX1, srcY1, 862 dstX0, dstY0, dstX1, dstY1, 863 mask, filter); 864} 865 866void 867intel_renderbuffer_set_needs_hiz_resolve(struct intel_renderbuffer *irb) 868{ 869 if (irb->mt) { 870 intel_miptree_slice_set_needs_hiz_resolve(irb->mt, 871 irb->mt_level, 872 irb->mt_layer); 873 } 874} 875 876void 877intel_renderbuffer_set_needs_depth_resolve(struct intel_renderbuffer *irb) 878{ 879 if (irb->mt) { 880 intel_miptree_slice_set_needs_depth_resolve(irb->mt, 881 irb->mt_level, 882 irb->mt_layer); 883 } 884} 885 886bool 887intel_renderbuffer_resolve_hiz(struct intel_context *intel, 888 struct intel_renderbuffer *irb) 889{ 890 if (irb->mt) 891 return intel_miptree_slice_resolve_hiz(intel, 892 irb->mt, 893 irb->mt_level, 894 irb->mt_layer); 895 896 return false; 897} 898 899bool 900intel_renderbuffer_resolve_depth(struct intel_context *intel, 901 struct intel_renderbuffer *irb) 902{ 903 if (irb->mt) 904 return intel_miptree_slice_resolve_depth(intel, 905 irb->mt, 906 irb->mt_level, 907 irb->mt_layer); 908 909 return false; 910} 911 912/** 913 * Do one-time context initializations related to GL_EXT_framebuffer_object. 914 * Hook in device driver functions. 915 */ 916void 917intel_fbo_init(struct intel_context *intel) 918{ 919 intel->ctx.Driver.NewFramebuffer = intel_new_framebuffer; 920 intel->ctx.Driver.NewRenderbuffer = intel_new_renderbuffer; 921 intel->ctx.Driver.MapRenderbuffer = intel_map_renderbuffer; 922 intel->ctx.Driver.UnmapRenderbuffer = intel_unmap_renderbuffer; 923 intel->ctx.Driver.BindFramebuffer = intel_bind_framebuffer; 924 intel->ctx.Driver.FramebufferRenderbuffer = intel_framebuffer_renderbuffer; 925 intel->ctx.Driver.RenderTexture = intel_render_texture; 926 intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture; 927 intel->ctx.Driver.ResizeBuffers = intel_resize_buffers; 928 intel->ctx.Driver.ValidateFramebuffer = intel_validate_framebuffer; 929 intel->ctx.Driver.BlitFramebuffer = intel_blit_framebuffer; 930 931#if FEATURE_OES_EGL_image 932 intel->ctx.Driver.EGLImageTargetRenderbufferStorage = 933 intel_image_target_renderbuffer_storage; 934#endif 935} 936