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