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