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