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