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