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