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