intel_fbo.c revision 9c5fdbb721147f7304faaa8960f5b64e25a8f673
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 86 free(irb); 87} 88 89 90/** 91 * Return a pointer to a specific pixel in a renderbuffer. 92 */ 93static void * 94intel_get_pointer(struct gl_context * ctx, struct gl_renderbuffer *rb, 95 GLint x, GLint y) 96{ 97 /* By returning NULL we force all software rendering to go through 98 * the span routines. 99 */ 100 return NULL; 101} 102 103 104/** 105 * Called via glRenderbufferStorageEXT() to set the format and allocate 106 * storage for a user-created renderbuffer. 107 */ 108static GLboolean 109intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, 110 GLenum internalFormat, 111 GLuint width, GLuint height) 112{ 113 struct intel_context *intel = intel_context(ctx); 114 struct intel_renderbuffer *irb = intel_renderbuffer(rb); 115 int cpp, tiling; 116 117 ASSERT(rb->Name != 0); 118 119 switch (internalFormat) { 120 default: 121 /* Use the same format-choice logic as for textures. 122 * Renderbuffers aren't any different from textures for us, 123 * except they're less useful because you can't texture with 124 * them. 125 */ 126 rb->Format = intel->ctx.Driver.ChooseTextureFormat(ctx, internalFormat, 127 GL_NONE, GL_NONE); 128 break; 129 case GL_STENCIL_INDEX: 130 case GL_STENCIL_INDEX1_EXT: 131 case GL_STENCIL_INDEX4_EXT: 132 case GL_STENCIL_INDEX8_EXT: 133 case GL_STENCIL_INDEX16_EXT: 134 /* These aren't actual texture formats, so force them here. */ 135 if (intel->has_separate_stencil) { 136 rb->Format = MESA_FORMAT_S8; 137 } else { 138 assert(!intel->must_use_separate_stencil); 139 rb->Format = MESA_FORMAT_S8_Z24; 140 } 141 break; 142 } 143 144 rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat); 145 rb->DataType = intel_mesa_format_to_rb_datatype(rb->Format); 146 cpp = _mesa_get_format_bytes(rb->Format); 147 148 intel_flush(ctx); 149 150 /* free old region */ 151 if (irb->region) { 152 intel_region_release(&irb->region); 153 } 154 if (irb->hiz_region) { 155 intel_region_release(&irb->hiz_region); 156 } 157 158 /* allocate new memory region/renderbuffer */ 159 160 /* alloc hardware renderbuffer */ 161 DBG("Allocating %d x %d Intel RBO\n", width, height); 162 163 tiling = I915_TILING_NONE; 164 if (intel->use_texture_tiling) { 165 GLenum base_format = _mesa_get_format_base_format(rb->Format); 166 167 if (intel->gen >= 4 && (base_format == GL_DEPTH_COMPONENT || 168 base_format == GL_STENCIL_INDEX || 169 base_format == GL_DEPTH_STENCIL)) 170 tiling = I915_TILING_Y; 171 else 172 tiling = I915_TILING_X; 173 } 174 175 if (irb->Base.Format == MESA_FORMAT_S8) { 176 /* 177 * The stencil buffer has quirky pitch requirements. From Vol 2a, 178 * 11.5.6.2.1 3DSTATE_STENCIL_BUFFER, field "Surface Pitch": 179 * The pitch must be set to 2x the value computed based on width, as 180 * the stencil buffer is stored with two rows interleaved. 181 * To accomplish this, we resort to the nasty hack of doubling the drm 182 * region's cpp and halving its height. 183 * 184 * If we neglect to double the pitch, then drm_intel_gem_bo_map_gtt() 185 * maps the memory incorrectly. 186 */ 187 irb->region = intel_region_alloc(intel->intelScreen, 188 I915_TILING_Y, 189 cpp * 2, 190 width, 191 height / 2, 192 GL_TRUE); 193 } else { 194 irb->region = intel_region_alloc(intel->intelScreen, tiling, cpp, 195 width, height, GL_TRUE); 196 } 197 198 if (!irb->region) 199 return GL_FALSE; /* out of memory? */ 200 201 ASSERT(irb->region->buffer); 202 203 if (intel->vtbl.is_hiz_depth_format(intel, rb->Format)) { 204 irb->hiz_region = intel_region_alloc(intel->intelScreen, 205 I915_TILING_Y, 206 irb->region->cpp, 207 irb->region->width, 208 irb->region->height, 209 GL_TRUE); 210 if (!irb->hiz_region) { 211 intel_region_release(&irb->region); 212 return GL_FALSE; 213 } 214 } 215 216 rb->Width = width; 217 rb->Height = height; 218 219 return GL_TRUE; 220} 221 222 223#if FEATURE_OES_EGL_image 224static void 225intel_image_target_renderbuffer_storage(struct gl_context *ctx, 226 struct gl_renderbuffer *rb, 227 void *image_handle) 228{ 229 struct intel_context *intel = intel_context(ctx); 230 struct intel_renderbuffer *irb; 231 __DRIscreen *screen; 232 __DRIimage *image; 233 234 screen = intel->intelScreen->driScrnPriv; 235 image = screen->dri2.image->lookupEGLImage(screen, image_handle, 236 screen->loaderPrivate); 237 if (image == NULL) 238 return; 239 240 irb = intel_renderbuffer(rb); 241 if (irb->region) 242 intel_region_release(&irb->region); 243 intel_region_reference(&irb->region, image->region); 244 245 rb->InternalFormat = image->internal_format; 246 rb->Width = image->region->width; 247 rb->Height = image->region->height; 248 rb->Format = image->format; 249 rb->DataType = image->data_type; 250 rb->_BaseFormat = _mesa_base_fbo_format(&intel->ctx, 251 image->internal_format); 252} 253#endif 254 255/** 256 * Called for each hardware renderbuffer when a _window_ is resized. 257 * Just update fields. 258 * Not used for user-created renderbuffers! 259 */ 260static GLboolean 261intel_alloc_window_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, 262 GLenum internalFormat, GLuint width, GLuint height) 263{ 264 ASSERT(rb->Name == 0); 265 rb->Width = width; 266 rb->Height = height; 267 rb->InternalFormat = internalFormat; 268 269 return GL_TRUE; 270} 271 272 273static void 274intel_resize_buffers(struct gl_context *ctx, struct gl_framebuffer *fb, 275 GLuint width, GLuint height) 276{ 277 int i; 278 279 _mesa_resize_framebuffer(ctx, fb, width, height); 280 281 fb->Initialized = GL_TRUE; /* XXX remove someday */ 282 283 if (fb->Name != 0) { 284 return; 285 } 286 287 288 /* Make sure all window system renderbuffers are up to date */ 289 for (i = BUFFER_FRONT_LEFT; i <= BUFFER_BACK_RIGHT; i++) { 290 struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer; 291 292 /* only resize if size is changing */ 293 if (rb && (rb->Width != width || rb->Height != height)) { 294 rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height); 295 } 296 } 297} 298 299 300/** Dummy function for gl_renderbuffer::AllocStorage() */ 301static GLboolean 302intel_nop_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, 303 GLenum internalFormat, GLuint width, GLuint height) 304{ 305 _mesa_problem(ctx, "intel_op_alloc_storage should never be called."); 306 return GL_FALSE; 307} 308 309 310void 311intel_renderbuffer_set_region(struct intel_context *intel, 312 struct intel_renderbuffer *rb, 313 struct intel_region *region) 314{ 315 struct intel_region *old; 316 317 old = rb->region; 318 rb->region = NULL; 319 intel_region_reference(&rb->region, region); 320 intel_region_release(&old); 321} 322 323 324void 325intel_renderbuffer_set_hiz_region(struct intel_context *intel, 326 struct intel_renderbuffer *rb, 327 struct intel_region *region) 328{ 329 struct intel_region *old = rb->hiz_region; 330 rb->hiz_region = NULL; 331 intel_region_reference(&rb->hiz_region, region); 332 intel_region_release(&old); 333} 334 335 336/** 337 * Create a new intel_renderbuffer which corresponds to an on-screen window, 338 * not a user-created renderbuffer. 339 */ 340struct intel_renderbuffer * 341intel_create_renderbuffer(gl_format format) 342{ 343 GET_CURRENT_CONTEXT(ctx); 344 345 struct intel_renderbuffer *irb; 346 347 irb = CALLOC_STRUCT(intel_renderbuffer); 348 if (!irb) { 349 _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer"); 350 return NULL; 351 } 352 353 _mesa_init_renderbuffer(&irb->Base, 0); 354 irb->Base.ClassID = INTEL_RB_CLASS; 355 irb->Base._BaseFormat = _mesa_get_format_base_format(format); 356 irb->Base.Format = format; 357 irb->Base.InternalFormat = irb->Base._BaseFormat; 358 irb->Base.DataType = intel_mesa_format_to_rb_datatype(format); 359 360 /* intel-specific methods */ 361 irb->Base.Delete = intel_delete_renderbuffer; 362 irb->Base.AllocStorage = intel_alloc_window_storage; 363 irb->Base.GetPointer = intel_get_pointer; 364 365 return irb; 366} 367 368 369/** 370 * Create a new renderbuffer object. 371 * Typically called via glBindRenderbufferEXT(). 372 */ 373static struct gl_renderbuffer * 374intel_new_renderbuffer(struct gl_context * ctx, GLuint name) 375{ 376 /*struct intel_context *intel = intel_context(ctx); */ 377 struct intel_renderbuffer *irb; 378 379 irb = CALLOC_STRUCT(intel_renderbuffer); 380 if (!irb) { 381 _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer"); 382 return NULL; 383 } 384 385 _mesa_init_renderbuffer(&irb->Base, name); 386 irb->Base.ClassID = INTEL_RB_CLASS; 387 388 /* intel-specific methods */ 389 irb->Base.Delete = intel_delete_renderbuffer; 390 irb->Base.AllocStorage = intel_alloc_renderbuffer_storage; 391 irb->Base.GetPointer = intel_get_pointer; 392 /* span routines set in alloc_storage function */ 393 394 return &irb->Base; 395} 396 397 398/** 399 * Called via glBindFramebufferEXT(). 400 */ 401static void 402intel_bind_framebuffer(struct gl_context * ctx, GLenum target, 403 struct gl_framebuffer *fb, struct gl_framebuffer *fbread) 404{ 405 if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) { 406 intel_draw_buffer(ctx, fb); 407 } 408 else { 409 /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */ 410 } 411} 412 413 414/** 415 * Called via glFramebufferRenderbufferEXT(). 416 */ 417static void 418intel_framebuffer_renderbuffer(struct gl_context * ctx, 419 struct gl_framebuffer *fb, 420 GLenum attachment, struct gl_renderbuffer *rb) 421{ 422 DBG("Intel FramebufferRenderbuffer %u %u\n", fb->Name, rb ? rb->Name : 0); 423 424 intel_flush(ctx); 425 426 _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb); 427 intel_draw_buffer(ctx, fb); 428} 429 430 431static GLboolean 432intel_update_wrapper(struct gl_context *ctx, struct intel_renderbuffer *irb, 433 struct gl_texture_image *texImage) 434{ 435 struct intel_context *intel = intel_context(ctx); 436 struct intel_texture_image *intel_image = intel_texture_image(texImage); 437 438 if (!intel_span_supports_format(texImage->TexFormat)) { 439 DBG("Render to texture BAD FORMAT %s\n", 440 _mesa_get_format_name(texImage->TexFormat)); 441 return GL_FALSE; 442 } else { 443 DBG("Render to texture %s\n", _mesa_get_format_name(texImage->TexFormat)); 444 } 445 446 irb->Base.Format = texImage->TexFormat; 447 irb->Base.DataType = intel_mesa_format_to_rb_datatype(texImage->TexFormat); 448 irb->Base.InternalFormat = texImage->InternalFormat; 449 irb->Base._BaseFormat = _mesa_base_tex_format(ctx, irb->Base.InternalFormat); 450 irb->Base.Width = texImage->Width; 451 irb->Base.Height = texImage->Height; 452 453 irb->Base.Delete = intel_delete_renderbuffer; 454 irb->Base.AllocStorage = intel_nop_alloc_storage; 455 456 /* Point the renderbuffer's region to the texture's region. */ 457 if (irb->region != intel_image->mt->region) { 458 intel_region_release(&irb->region); 459 intel_region_reference(&irb->region, intel_image->mt->region); 460 } 461 462 /* Allocate the texture's hiz region if necessary. */ 463 if (intel->vtbl.is_hiz_depth_format(intel, texImage->TexFormat) 464 && !intel_image->mt->hiz_region) { 465 intel_image->mt->hiz_region = 466 intel_region_alloc(intel->intelScreen, 467 I915_TILING_Y, 468 _mesa_get_format_bytes(texImage->TexFormat), 469 texImage->Width, 470 texImage->Height, 471 GL_TRUE); 472 if (!intel_image->mt->hiz_region) 473 return GL_FALSE; 474 } 475 476 /* Point the renderbuffer's hiz region to the texture's hiz region. */ 477 if (irb->hiz_region != intel_image->mt->hiz_region) { 478 intel_region_release(&irb->hiz_region); 479 intel_region_reference(&irb->hiz_region, intel_image->mt->hiz_region); 480 } 481 482 return GL_TRUE; 483} 484 485 486/** 487 * When glFramebufferTexture[123]D is called this function sets up the 488 * gl_renderbuffer wrapper around the texture image. 489 * This will have the region info needed for hardware rendering. 490 */ 491static struct intel_renderbuffer * 492intel_wrap_texture(struct gl_context * ctx, struct gl_texture_image *texImage) 493{ 494 const GLuint name = ~0; /* not significant, but distinct for debugging */ 495 struct intel_renderbuffer *irb; 496 497 /* make an intel_renderbuffer to wrap the texture image */ 498 irb = CALLOC_STRUCT(intel_renderbuffer); 499 if (!irb) { 500 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture"); 501 return NULL; 502 } 503 504 _mesa_init_renderbuffer(&irb->Base, name); 505 irb->Base.ClassID = INTEL_RB_CLASS; 506 507 if (!intel_update_wrapper(ctx, irb, texImage)) { 508 free(irb); 509 return NULL; 510 } 511 512 return irb; 513} 514 515static void 516intel_renderbuffer_set_draw_offset(struct intel_renderbuffer *irb, 517 struct intel_texture_image *intel_image, 518 int zoffset) 519{ 520 struct intel_mipmap_tree *mt = intel_image->mt; 521 unsigned int dst_x, dst_y; 522 523 /* compute offset of the particular 2D image within the texture region */ 524 intel_miptree_get_image_offset(intel_image->mt, 525 intel_image->level, 526 intel_image->face, 527 zoffset, 528 &dst_x, &dst_y); 529 530 irb->draw_offset = (dst_y * mt->region->pitch + dst_x) * mt->cpp; 531 irb->draw_x = dst_x; 532 irb->draw_y = dst_y; 533} 534 535/** 536 * Rendering to tiled buffers requires that the base address of the 537 * buffer be aligned to a page boundary. We generally render to 538 * textures by pointing the surface at the mipmap image level, which 539 * may not be aligned to a tile boundary. 540 * 541 * This function returns an appropriately-aligned base offset 542 * according to the tiling restrictions, plus any required x/y offset 543 * from there. 544 */ 545uint32_t 546intel_renderbuffer_tile_offsets(struct intel_renderbuffer *irb, 547 uint32_t *tile_x, 548 uint32_t *tile_y) 549{ 550 int cpp = irb->region->cpp; 551 uint32_t pitch = irb->region->pitch * cpp; 552 553 if (irb->region->tiling == I915_TILING_NONE) { 554 *tile_x = 0; 555 *tile_y = 0; 556 return irb->draw_x * cpp + irb->draw_y * pitch; 557 } else if (irb->region->tiling == I915_TILING_X) { 558 *tile_x = irb->draw_x % (512 / cpp); 559 *tile_y = irb->draw_y % 8; 560 return ((irb->draw_y / 8) * (8 * pitch) + 561 (irb->draw_x - *tile_x) / (512 / cpp) * 4096); 562 } else { 563 assert(irb->region->tiling == I915_TILING_Y); 564 *tile_x = irb->draw_x % (128 / cpp); 565 *tile_y = irb->draw_y % 32; 566 return ((irb->draw_y / 32) * (32 * pitch) + 567 (irb->draw_x - *tile_x) / (128 / cpp) * 4096); 568 } 569} 570 571/** 572 * Called by glFramebufferTexture[123]DEXT() (and other places) to 573 * prepare for rendering into texture memory. This might be called 574 * many times to choose different texture levels, cube faces, etc 575 * before intel_finish_render_texture() is ever called. 576 */ 577static void 578intel_render_texture(struct gl_context * ctx, 579 struct gl_framebuffer *fb, 580 struct gl_renderbuffer_attachment *att) 581{ 582 struct gl_texture_image *image = _mesa_get_attachment_teximage(att); 583 struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer); 584 struct intel_texture_image *intel_image = intel_texture_image(image); 585 586 (void) fb; 587 588 if (!intel_image->mt) { 589 /* Fallback on drawing to a texture that doesn't have a miptree 590 * (has a border, width/height 0, etc.) 591 */ 592 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); 593 _swrast_render_texture(ctx, fb, att); 594 return; 595 } 596 else if (!irb) { 597 irb = intel_wrap_texture(ctx, image); 598 if (irb) { 599 /* bind the wrapper to the attachment point */ 600 _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base); 601 } 602 else { 603 /* fallback to software rendering */ 604 _swrast_render_texture(ctx, fb, att); 605 return; 606 } 607 } 608 609 if (!intel_update_wrapper(ctx, irb, image)) { 610 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); 611 _swrast_render_texture(ctx, fb, att); 612 return; 613 } 614 615 DBG("Begin render texture tid %lx tex=%u w=%d h=%d refcount=%d\n", 616 _glthread_GetID(), 617 att->Texture->Name, image->Width, image->Height, 618 irb->Base.RefCount); 619 620 intel_renderbuffer_set_draw_offset(irb, intel_image, att->Zoffset); 621 intel_image->used_as_render_target = GL_TRUE; 622 623#ifndef I915 624 if (!brw_context(ctx)->has_surface_tile_offset && 625 (irb->draw_offset & 4095) != 0) { 626 /* Original gen4 hardware couldn't draw to a non-tile-aligned 627 * destination in a miptree unless you actually setup your 628 * renderbuffer as a miptree and used the fragile 629 * lod/array_index/etc. controls to select the image. So, 630 * instead, we just make a new single-level miptree and render 631 * into that. 632 */ 633 struct intel_context *intel = intel_context(ctx); 634 struct intel_mipmap_tree *old_mt = intel_image->mt; 635 struct intel_mipmap_tree *new_mt; 636 int comp_byte = 0, texel_bytes; 637 638 if (_mesa_is_format_compressed(intel_image->base.TexFormat)) 639 comp_byte = intel_compressed_num_bytes(intel_image->base.TexFormat); 640 641 texel_bytes = _mesa_get_format_bytes(intel_image->base.TexFormat); 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 texel_bytes, comp_byte, 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