intel_fbo.c revision 7eb0aa398b9c0f7d8a224f2a4952f7875067e917
1/************************************************************************** 2 * 3 * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 29#include "main/enums.h" 30#include "main/imports.h" 31#include "main/macros.h" 32#include "main/mfeatures.h" 33#include "main/mtypes.h" 34#include "main/fbobject.h" 35#include "main/framebuffer.h" 36#include "main/renderbuffer.h" 37#include "main/context.h" 38#include "main/teximage.h" 39#include "main/image.h" 40 41#include "swrast/swrast.h" 42#include "drivers/common/meta.h" 43 44#include "intel_context.h" 45#include "intel_batchbuffer.h" 46#include "intel_buffers.h" 47#include "intel_blit.h" 48#include "intel_fbo.h" 49#include "intel_mipmap_tree.h" 50#include "intel_regions.h" 51#include "intel_tex.h" 52#include "intel_span.h" 53#ifndef I915 54#include "brw_context.h" 55#endif 56 57#define FILE_DEBUG_FLAG DEBUG_FBO 58 59static struct gl_renderbuffer * 60intel_new_renderbuffer(struct gl_context * ctx, GLuint name); 61 62static bool 63intel_renderbuffer_update_wrapper(struct intel_context *intel, 64 struct intel_renderbuffer *irb, 65 struct intel_mipmap_tree *mt, 66 uint32_t level, 67 uint32_t layer, 68 gl_format format, 69 GLenum internal_format); 70 71bool 72intel_framebuffer_has_hiz(struct gl_framebuffer *fb) 73{ 74 struct intel_renderbuffer *rb = NULL; 75 if (fb) 76 rb = intel_get_renderbuffer(fb, BUFFER_DEPTH); 77 return rb && rb->mt && rb->mt->hiz_mt; 78} 79 80struct intel_region* 81intel_get_rb_region(struct gl_framebuffer *fb, GLuint attIndex) 82{ 83 struct intel_renderbuffer *irb = intel_get_renderbuffer(fb, attIndex); 84 if (irb && irb->mt) 85 return irb->mt->region; 86 else 87 return NULL; 88} 89 90/** 91 * Create a new framebuffer object. 92 */ 93static struct gl_framebuffer * 94intel_new_framebuffer(struct gl_context * ctx, GLuint name) 95{ 96 /* Only drawable state in intel_framebuffer at this time, just use Mesa's 97 * class 98 */ 99 return _mesa_new_framebuffer(ctx, name); 100} 101 102 103/** Called by gl_renderbuffer::Delete() */ 104static void 105intel_delete_renderbuffer(struct gl_renderbuffer *rb) 106{ 107 struct intel_renderbuffer *irb = intel_renderbuffer(rb); 108 109 ASSERT(irb); 110 111 intel_miptree_release(&irb->mt); 112 113 _mesa_reference_renderbuffer(&irb->wrapped_depth, NULL); 114 _mesa_reference_renderbuffer(&irb->wrapped_stencil, NULL); 115 116 free(irb); 117} 118 119/** 120 * \see dd_function_table::MapRenderbuffer 121 */ 122static void 123intel_map_renderbuffer(struct gl_context *ctx, 124 struct gl_renderbuffer *rb, 125 GLuint x, GLuint y, GLuint w, GLuint h, 126 GLbitfield mode, 127 GLubyte **out_map, 128 GLint *out_stride) 129{ 130 struct intel_context *intel = intel_context(ctx); 131 struct intel_renderbuffer *irb = intel_renderbuffer(rb); 132 void *map; 133 int stride; 134 135 /* We sometimes get called with this by our intel_span.c usage. */ 136 if (!irb->mt) { 137 *out_map = NULL; 138 *out_stride = 0; 139 return; 140 } 141 142 /* For a window-system renderbuffer, we need to flip the mapping we receive 143 * upside-down. So we need to ask for a rectangle on flipped vertically, and 144 * we then return a pointer to the bottom of it with a negative stride. 145 */ 146 if (rb->Name == 0) { 147 y = rb->Height - y - h; 148 } 149 150 intel_miptree_map(intel, irb->mt, irb->mt_level, irb->mt_layer, 151 x, y, w, h, mode, &map, &stride); 152 153 if (rb->Name == 0) { 154 map += (h - 1) * stride; 155 stride = -stride; 156 } 157 158 DBG("%s: rb %d (%s) mt mapped: (%d, %d) (%dx%d) -> %p/%d\n", 159 __FUNCTION__, rb->Name, _mesa_get_format_name(rb->Format), 160 x, y, w, h, map, stride); 161 162 *out_map = map; 163 *out_stride = stride; 164} 165 166/** 167 * \see dd_function_table::UnmapRenderbuffer 168 */ 169static void 170intel_unmap_renderbuffer(struct gl_context *ctx, 171 struct gl_renderbuffer *rb) 172{ 173 struct intel_context *intel = intel_context(ctx); 174 struct intel_renderbuffer *irb = intel_renderbuffer(rb); 175 176 DBG("%s: rb %d (%s)\n", __FUNCTION__, 177 rb->Name, _mesa_get_format_name(rb->Format)); 178 179 intel_miptree_unmap(intel, irb->mt, irb->mt_level, irb->mt_layer); 180} 181 182/** 183 * Return a pointer to a specific pixel in a renderbuffer. 184 */ 185static void * 186intel_get_pointer(struct gl_context * ctx, struct gl_renderbuffer *rb, 187 GLint x, GLint y) 188{ 189 /* By returning NULL we force all software rendering to go through 190 * the span routines. 191 */ 192 return NULL; 193} 194 195 196/** 197 * Called via glRenderbufferStorageEXT() to set the format and allocate 198 * storage for a user-created renderbuffer. 199 */ 200GLboolean 201intel_alloc_renderbuffer_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, 202 GLenum internalFormat, 203 GLuint width, GLuint height) 204{ 205 struct intel_context *intel = intel_context(ctx); 206 struct intel_renderbuffer *irb = intel_renderbuffer(rb); 207 208 ASSERT(rb->Name != 0); 209 210 switch (internalFormat) { 211 default: 212 /* Use the same format-choice logic as for textures. 213 * Renderbuffers aren't any different from textures for us, 214 * except they're less useful because you can't texture with 215 * them. 216 */ 217 rb->Format = intel->ctx.Driver.ChooseTextureFormat(ctx, internalFormat, 218 GL_NONE, GL_NONE); 219 break; 220 case GL_STENCIL_INDEX: 221 case GL_STENCIL_INDEX1_EXT: 222 case GL_STENCIL_INDEX4_EXT: 223 case GL_STENCIL_INDEX8_EXT: 224 case GL_STENCIL_INDEX16_EXT: 225 /* These aren't actual texture formats, so force them here. */ 226 if (intel->has_separate_stencil) { 227 rb->Format = MESA_FORMAT_S8; 228 } else { 229 assert(!intel->must_use_separate_stencil); 230 rb->Format = MESA_FORMAT_S8_Z24; 231 } 232 break; 233 } 234 235 rb->Width = width; 236 rb->Height = height; 237 rb->_BaseFormat = _mesa_base_fbo_format(ctx, internalFormat); 238 rb->DataType = intel_mesa_format_to_rb_datatype(rb->Format); 239 240 intel_flush(ctx); 241 242 intel_miptree_release(&irb->mt); 243 244 DBG("%s: %s: %s (%dx%d)\n", __FUNCTION__, 245 _mesa_lookup_enum_by_nr(internalFormat), 246 _mesa_get_format_name(rb->Format), width, height); 247 248 irb->mt = intel_miptree_create_for_renderbuffer(intel, rb->Format, 249 width, height); 250 if (!irb->mt) 251 return false; 252 253 if (intel->vtbl.is_hiz_depth_format(intel, rb->Format)) { 254 bool ok = intel_miptree_alloc_hiz(intel, irb->mt); 255 if (!ok) { 256 intel_miptree_release(&irb->mt); 257 return false; 258 } 259 } 260 261 if (irb->mt->stencil_mt) { 262 bool ok; 263 struct intel_renderbuffer *depth_irb, *stencil_irb; 264 265 /* The RB got allocated as separate stencil. Hook up our wrapped 266 * renderbuffers so that consumers of intel_get_renderbuffer() end up 267 * with pointers to the separate pieces. 268 */ 269 if (!irb->wrapped_depth) { 270 _mesa_reference_renderbuffer(&irb->wrapped_depth, 271 intel_new_renderbuffer(ctx, ~0)); 272 } 273 if (!irb->wrapped_stencil) { 274 _mesa_reference_renderbuffer(&irb->wrapped_stencil, 275 intel_new_renderbuffer(ctx, ~0)); 276 } 277 278 depth_irb = intel_renderbuffer(irb->wrapped_depth); 279 stencil_irb = intel_renderbuffer(irb->wrapped_stencil); 280 if (!depth_irb || !stencil_irb) { 281 intel_miptree_release(&irb->mt); 282 return false; 283 } 284 285 assert(irb->mt->format == MESA_FORMAT_S8_Z24); 286 ok = intel_renderbuffer_update_wrapper(intel, depth_irb, irb->mt, 287 0, 0, /* level, layer */ 288 MESA_FORMAT_X8_Z24, 289 GL_DEPTH_COMPONENT24); 290 assert(ok); 291 292 ok = intel_renderbuffer_update_wrapper(intel, stencil_irb, 293 irb->mt->stencil_mt, 294 0, 0, /* level, layer */ 295 MESA_FORMAT_S8, 296 GL_STENCIL_INDEX); 297 assert(ok); 298 } 299 300 return true; 301} 302 303 304#if FEATURE_OES_EGL_image 305static void 306intel_image_target_renderbuffer_storage(struct gl_context *ctx, 307 struct gl_renderbuffer *rb, 308 void *image_handle) 309{ 310 struct intel_context *intel = intel_context(ctx); 311 struct intel_renderbuffer *irb; 312 __DRIscreen *screen; 313 __DRIimage *image; 314 315 screen = intel->intelScreen->driScrnPriv; 316 image = screen->dri2.image->lookupEGLImage(screen, image_handle, 317 screen->loaderPrivate); 318 if (image == NULL) 319 return; 320 321 /* __DRIimage is opaque to the core so it has to be checked here */ 322 switch (image->format) { 323 case MESA_FORMAT_RGBA8888_REV: 324 _mesa_error(&intel->ctx, GL_INVALID_OPERATION, 325 "glEGLImageTargetRenderbufferStorage(unsupported image format"); 326 return; 327 break; 328 default: 329 break; 330 } 331 332 irb = intel_renderbuffer(rb); 333 intel_miptree_release(&irb->mt); 334 irb->mt = intel_miptree_create_for_region(intel, 335 GL_TEXTURE_2D, 336 image->format, 337 image->region); 338 if (!irb->mt) 339 return; 340 341 rb->InternalFormat = image->internal_format; 342 rb->Width = image->region->width; 343 rb->Height = image->region->height; 344 rb->Format = image->format; 345 rb->DataType = image->data_type; 346 rb->_BaseFormat = _mesa_base_fbo_format(&intel->ctx, 347 image->internal_format); 348} 349#endif 350 351/** 352 * Called for each hardware renderbuffer when a _window_ is resized. 353 * Just update fields. 354 * Not used for user-created renderbuffers! 355 */ 356static GLboolean 357intel_alloc_window_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, 358 GLenum internalFormat, GLuint width, GLuint height) 359{ 360 ASSERT(rb->Name == 0); 361 rb->Width = width; 362 rb->Height = height; 363 rb->InternalFormat = internalFormat; 364 365 return true; 366} 367 368 369static void 370intel_resize_buffers(struct gl_context *ctx, struct gl_framebuffer *fb, 371 GLuint width, GLuint height) 372{ 373 int i; 374 375 _mesa_resize_framebuffer(ctx, fb, width, height); 376 377 fb->Initialized = true; /* XXX remove someday */ 378 379 if (fb->Name != 0) { 380 return; 381 } 382 383 384 /* Make sure all window system renderbuffers are up to date */ 385 for (i = BUFFER_FRONT_LEFT; i <= BUFFER_BACK_RIGHT; i++) { 386 struct gl_renderbuffer *rb = fb->Attachment[i].Renderbuffer; 387 388 /* only resize if size is changing */ 389 if (rb && (rb->Width != width || rb->Height != height)) { 390 rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height); 391 } 392 } 393} 394 395 396/** Dummy function for gl_renderbuffer::AllocStorage() */ 397static GLboolean 398intel_nop_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *rb, 399 GLenum internalFormat, GLuint width, GLuint height) 400{ 401 _mesa_problem(ctx, "intel_op_alloc_storage should never be called."); 402 return false; 403} 404 405/** 406 * Create a new intel_renderbuffer which corresponds to an on-screen window, 407 * not a user-created renderbuffer. 408 */ 409struct intel_renderbuffer * 410intel_create_renderbuffer(gl_format format) 411{ 412 GET_CURRENT_CONTEXT(ctx); 413 414 struct intel_renderbuffer *irb; 415 416 irb = CALLOC_STRUCT(intel_renderbuffer); 417 if (!irb) { 418 _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer"); 419 return NULL; 420 } 421 422 _mesa_init_renderbuffer(&irb->Base, 0); 423 irb->Base.ClassID = INTEL_RB_CLASS; 424 irb->Base._BaseFormat = _mesa_get_format_base_format(format); 425 irb->Base.Format = format; 426 irb->Base.InternalFormat = irb->Base._BaseFormat; 427 irb->Base.DataType = intel_mesa_format_to_rb_datatype(format); 428 429 /* intel-specific methods */ 430 irb->Base.Delete = intel_delete_renderbuffer; 431 irb->Base.AllocStorage = intel_alloc_window_storage; 432 irb->Base.GetPointer = intel_get_pointer; 433 434 return irb; 435} 436 437/** 438 * Create a new renderbuffer object. 439 * Typically called via glBindRenderbufferEXT(). 440 */ 441static struct gl_renderbuffer * 442intel_new_renderbuffer(struct gl_context * ctx, GLuint name) 443{ 444 /*struct intel_context *intel = intel_context(ctx); */ 445 struct intel_renderbuffer *irb; 446 447 irb = CALLOC_STRUCT(intel_renderbuffer); 448 if (!irb) { 449 _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer"); 450 return NULL; 451 } 452 453 _mesa_init_renderbuffer(&irb->Base, name); 454 irb->Base.ClassID = INTEL_RB_CLASS; 455 456 /* intel-specific methods */ 457 irb->Base.Delete = intel_delete_renderbuffer; 458 irb->Base.AllocStorage = intel_alloc_renderbuffer_storage; 459 irb->Base.GetPointer = intel_get_pointer; 460 /* span routines set in alloc_storage function */ 461 462 return &irb->Base; 463} 464 465 466/** 467 * Called via glBindFramebufferEXT(). 468 */ 469static void 470intel_bind_framebuffer(struct gl_context * ctx, GLenum target, 471 struct gl_framebuffer *fb, struct gl_framebuffer *fbread) 472{ 473 if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) { 474 intel_draw_buffer(ctx); 475 } 476 else { 477 /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */ 478 } 479} 480 481 482/** 483 * Called via glFramebufferRenderbufferEXT(). 484 */ 485static void 486intel_framebuffer_renderbuffer(struct gl_context * ctx, 487 struct gl_framebuffer *fb, 488 GLenum attachment, struct gl_renderbuffer *rb) 489{ 490 DBG("Intel FramebufferRenderbuffer %u %u\n", fb->Name, rb ? rb->Name : 0); 491 492 intel_flush(ctx); 493 494 _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb); 495 intel_draw_buffer(ctx); 496} 497 498static struct intel_renderbuffer* 499intel_renderbuffer_wrap_miptree(struct intel_context *intel, 500 struct intel_mipmap_tree *mt, 501 uint32_t level, 502 uint32_t layer, 503 gl_format format, 504 GLenum internal_format); 505 506/** 507 * \par Special case for separate stencil 508 * 509 * When wrapping a depthstencil texture that uses separate stencil, this 510 * function is recursively called twice: once to create \c 511 * irb->wrapped_depth and again to create \c irb->wrapped_stencil. On the 512 * call to create \c irb->wrapped_depth, the \c format and \c 513 * internal_format parameters do not match \c mt->format. In that case, \c 514 * mt->format is MESA_FORMAT_S8_Z24 and \c format is \c 515 * MESA_FORMAT_X8_Z24. 516 * 517 * @return true on success 518 */ 519static bool 520intel_renderbuffer_update_wrapper(struct intel_context *intel, 521 struct intel_renderbuffer *irb, 522 struct intel_mipmap_tree *mt, 523 uint32_t level, 524 uint32_t layer, 525 gl_format format, 526 GLenum internal_format) 527{ 528 struct gl_renderbuffer *rb = &irb->Base; 529 530 rb->Format = format; 531 rb->InternalFormat = internal_format; 532 rb->DataType = intel_mesa_format_to_rb_datatype(rb->Format); 533 rb->_BaseFormat = _mesa_get_format_base_format(rb->Format); 534 rb->Width = mt->level[level].width; 535 rb->Height = mt->level[level].height; 536 537 irb->Base.Delete = intel_delete_renderbuffer; 538 irb->Base.AllocStorage = intel_nop_alloc_storage; 539 540 intel_miptree_check_level_layer(mt, level, layer); 541 irb->mt_level = level; 542 irb->mt_layer = layer; 543 544 if (mt->stencil_mt && _mesa_is_depthstencil_format(rb->InternalFormat)) { 545 assert((irb->wrapped_depth == NULL) == (irb->wrapped_stencil == NULL)); 546 547 struct intel_renderbuffer *depth_irb; 548 struct intel_renderbuffer *stencil_irb; 549 550 if (!irb->wrapped_depth) { 551 depth_irb = intel_renderbuffer_wrap_miptree(intel, 552 mt, level, layer, 553 MESA_FORMAT_X8_Z24, 554 GL_DEPTH_COMPONENT24); 555 stencil_irb = intel_renderbuffer_wrap_miptree(intel, 556 mt->stencil_mt, 557 level, layer, 558 MESA_FORMAT_S8, 559 GL_STENCIL_INDEX8); 560 _mesa_reference_renderbuffer(&irb->wrapped_depth, &depth_irb->Base); 561 _mesa_reference_renderbuffer(&irb->wrapped_stencil, &stencil_irb->Base); 562 563 if (!irb->wrapped_depth || !irb->wrapped_stencil) 564 return false; 565 } else { 566 bool ok = true; 567 568 depth_irb = intel_renderbuffer(irb->wrapped_depth); 569 stencil_irb = intel_renderbuffer(irb->wrapped_stencil); 570 571 ok &= intel_renderbuffer_update_wrapper(intel, 572 depth_irb, 573 mt, 574 level, layer, 575 MESA_FORMAT_X8_Z24, 576 GL_DEPTH_COMPONENT24); 577 ok &= intel_renderbuffer_update_wrapper(intel, 578 stencil_irb, 579 mt->stencil_mt, 580 level, layer, 581 MESA_FORMAT_S8, 582 GL_STENCIL_INDEX8); 583 if (!ok) 584 return false; 585 } 586 587 intel_miptree_reference(&depth_irb->mt->stencil_mt, stencil_irb->mt); 588 intel_miptree_reference(&irb->mt, depth_irb->mt); 589 } else { 590 intel_miptree_reference(&irb->mt, mt); 591 intel_renderbuffer_set_draw_offset(irb); 592 593 if (mt->hiz_mt == NULL && 594 intel->vtbl.is_hiz_depth_format(intel, rb->Format)) { 595 intel_miptree_alloc_hiz(intel, mt); 596 if (!mt->hiz_mt) 597 return false; 598 } 599 } 600 601 return true; 602} 603 604/** 605 * \brief Wrap a renderbuffer around a single slice of a miptree. 606 * 607 * Called by glFramebufferTexture*(). This just allocates a 608 * ``struct intel_renderbuffer`` then calls 609 * intel_renderbuffer_update_wrapper() to do the real work. 610 * 611 * \see intel_renderbuffer_update_wrapper() 612 */ 613static struct intel_renderbuffer* 614intel_renderbuffer_wrap_miptree(struct intel_context *intel, 615 struct intel_mipmap_tree *mt, 616 uint32_t level, 617 uint32_t layer, 618 gl_format format, 619 GLenum internal_format) 620 621{ 622 struct gl_context *ctx = &intel->ctx; 623 struct gl_renderbuffer *rb; 624 struct intel_renderbuffer *irb; 625 626 intel_miptree_check_level_layer(mt, level, layer); 627 628 rb = intel_new_renderbuffer(ctx, ~0); 629 irb = intel_renderbuffer(rb); 630 if (!irb) 631 return NULL; 632 633 if (!intel_renderbuffer_update_wrapper(intel, irb, 634 mt, level, layer, 635 format, internal_format)) { 636 free(irb); 637 return NULL; 638 } 639 640 return irb; 641} 642 643void 644intel_renderbuffer_set_draw_offset(struct intel_renderbuffer *irb) 645{ 646 unsigned int dst_x, dst_y; 647 648 /* compute offset of the particular 2D image within the texture region */ 649 intel_miptree_get_image_offset(irb->mt, 650 irb->mt_level, 651 0, /* face, which we ignore */ 652 irb->mt_layer, 653 &dst_x, &dst_y); 654 655 irb->draw_x = dst_x; 656 irb->draw_y = dst_y; 657} 658 659/** 660 * Rendering to tiled buffers requires that the base address of the 661 * buffer be aligned to a page boundary. We generally render to 662 * textures by pointing the surface at the mipmap image level, which 663 * may not be aligned to a tile boundary. 664 * 665 * This function returns an appropriately-aligned base offset 666 * according to the tiling restrictions, plus any required x/y offset 667 * from there. 668 */ 669uint32_t 670intel_renderbuffer_tile_offsets(struct intel_renderbuffer *irb, 671 uint32_t *tile_x, 672 uint32_t *tile_y) 673{ 674 struct intel_region *region = irb->mt->region; 675 int cpp = region->cpp; 676 uint32_t pitch = region->pitch * cpp; 677 678 if (region->tiling == I915_TILING_NONE) { 679 *tile_x = 0; 680 *tile_y = 0; 681 return irb->draw_x * cpp + irb->draw_y * pitch; 682 } else if (region->tiling == I915_TILING_X) { 683 *tile_x = irb->draw_x % (512 / cpp); 684 *tile_y = irb->draw_y % 8; 685 return ((irb->draw_y / 8) * (8 * pitch) + 686 (irb->draw_x - *tile_x) / (512 / cpp) * 4096); 687 } else { 688 assert(region->tiling == I915_TILING_Y); 689 *tile_x = irb->draw_x % (128 / cpp); 690 *tile_y = irb->draw_y % 32; 691 return ((irb->draw_y / 32) * (32 * pitch) + 692 (irb->draw_x - *tile_x) / (128 / cpp) * 4096); 693 } 694} 695 696#ifndef I915 697static bool 698need_tile_offset_workaround(struct brw_context *brw, 699 struct intel_renderbuffer *irb) 700{ 701 uint32_t tile_x, tile_y; 702 703 if (brw->has_surface_tile_offset) 704 return false; 705 706 intel_renderbuffer_tile_offsets(irb, &tile_x, &tile_y); 707 708 return tile_x != 0 || tile_y != 0; 709} 710#endif 711 712/** 713 * Called by glFramebufferTexture[123]DEXT() (and other places) to 714 * prepare for rendering into texture memory. This might be called 715 * many times to choose different texture levels, cube faces, etc 716 * before intel_finish_render_texture() is ever called. 717 */ 718static void 719intel_render_texture(struct gl_context * ctx, 720 struct gl_framebuffer *fb, 721 struct gl_renderbuffer_attachment *att) 722{ 723 struct intel_context *intel = intel_context(ctx); 724 struct gl_texture_image *image = _mesa_get_attachment_teximage(att); 725 struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer); 726 struct intel_texture_image *intel_image = intel_texture_image(image); 727 struct intel_mipmap_tree *mt = intel_image->mt; 728 729 (void) fb; 730 731 int layer; 732 if (att->CubeMapFace > 0) { 733 assert(att->Zoffset == 0); 734 layer = att->CubeMapFace; 735 } else { 736 layer = att->Zoffset; 737 } 738 739 if (!intel_image->mt) { 740 /* Fallback on drawing to a texture that doesn't have a miptree 741 * (has a border, width/height 0, etc.) 742 */ 743 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); 744 _swrast_render_texture(ctx, fb, att); 745 return; 746 } 747 else if (!irb) { 748 irb = intel_renderbuffer_wrap_miptree(intel, 749 mt, 750 att->TextureLevel, 751 layer, 752 image->TexFormat, 753 image->InternalFormat); 754 755 if (irb) { 756 /* bind the wrapper to the attachment point */ 757 _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base); 758 } 759 else { 760 /* fallback to software rendering */ 761 _swrast_render_texture(ctx, fb, att); 762 return; 763 } 764 } 765 766 if (!intel_renderbuffer_update_wrapper(intel, irb, 767 mt, att->TextureLevel, layer, 768 image->TexFormat, 769 image->InternalFormat)) { 770 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); 771 _swrast_render_texture(ctx, fb, att); 772 return; 773 } 774 775 DBG("Begin render %s texture tex=%u w=%d h=%d refcount=%d\n", 776 _mesa_get_format_name(image->TexFormat), 777 att->Texture->Name, image->Width, image->Height, 778 irb->Base.RefCount); 779 780 intel_image->used_as_render_target = true; 781 782#ifndef I915 783 if (need_tile_offset_workaround(brw_context(ctx), irb)) { 784 /* Original gen4 hardware couldn't draw to a non-tile-aligned 785 * destination in a miptree unless you actually setup your 786 * renderbuffer as a miptree and used the fragile 787 * lod/array_index/etc. controls to select the image. So, 788 * instead, we just make a new single-level miptree and render 789 * into that. 790 */ 791 struct intel_context *intel = intel_context(ctx); 792 struct intel_mipmap_tree *new_mt; 793 int width, height, depth; 794 795 intel_miptree_get_dimensions_for_image(image, &width, &height, &depth); 796 797 new_mt = intel_miptree_create(intel, image->TexObject->Target, 798 intel_image->base.Base.TexFormat, 799 intel_image->base.Base.Level, 800 intel_image->base.Base.Level, 801 width, height, depth, 802 true); 803 804 intel_miptree_copy_teximage(intel, intel_image, new_mt); 805 intel_renderbuffer_set_draw_offset(irb); 806 807 intel_miptree_reference(&irb->mt, intel_image->mt); 808 intel_miptree_release(&new_mt); 809 } 810#endif 811 /* update drawing region, etc */ 812 intel_draw_buffer(ctx); 813} 814 815 816/** 817 * Called by Mesa when rendering to a texture is done. 818 */ 819static void 820intel_finish_render_texture(struct gl_context * ctx, 821 struct gl_renderbuffer_attachment *att) 822{ 823 struct intel_context *intel = intel_context(ctx); 824 struct gl_texture_object *tex_obj = att->Texture; 825 struct gl_texture_image *image = 826 tex_obj->Image[att->CubeMapFace][att->TextureLevel]; 827 struct intel_texture_image *intel_image = intel_texture_image(image); 828 829 DBG("Finish render %s texture tex=%u\n", 830 _mesa_get_format_name(image->TexFormat), att->Texture->Name); 831 832 /* Flag that this image may now be validated into the object's miptree. */ 833 if (intel_image) 834 intel_image->used_as_render_target = false; 835 836 /* Since we've (probably) rendered to the texture and will (likely) use 837 * it in the texture domain later on in this batchbuffer, flush the 838 * batch. Once again, we wish for a domain tracker in libdrm to cover 839 * usage inside of a batchbuffer like GEM does in the kernel. 840 */ 841 intel_batchbuffer_emit_mi_flush(intel); 842} 843 844/** 845 * Do additional "completeness" testing of a framebuffer object. 846 */ 847static void 848intel_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb) 849{ 850 struct intel_context *intel = intel_context(ctx); 851 const struct intel_renderbuffer *depthRb = 852 intel_get_renderbuffer(fb, BUFFER_DEPTH); 853 const struct intel_renderbuffer *stencilRb = 854 intel_get_renderbuffer(fb, BUFFER_STENCIL); 855 struct intel_mipmap_tree *depth_mt = NULL, *stencil_mt = NULL; 856 int i; 857 858 if (depthRb) 859 depth_mt = depthRb->mt; 860 if (stencilRb) 861 stencil_mt = stencilRb->mt; 862 863 if (depth_mt && stencil_mt) { 864 if (depth_mt == stencil_mt) { 865 /* For true packed depth/stencil (not faked on prefers-separate-stencil 866 * hardware) we need to be sure they're the same level/layer, since 867 * we'll be emitting a single packet describing the packed setup. 868 */ 869 if (depthRb->mt_level != stencilRb->mt_level || 870 depthRb->mt_layer != stencilRb->mt_layer) { 871 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; 872 } 873 } else { 874 if (!intel->has_separate_stencil) 875 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; 876 if (stencil_mt->format != MESA_FORMAT_S8) 877 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; 878 } 879 } 880 881 for (i = 0; i < Elements(fb->Attachment); i++) { 882 struct gl_renderbuffer *rb; 883 struct intel_renderbuffer *irb; 884 885 if (fb->Attachment[i].Type == GL_NONE) 886 continue; 887 888 /* A supported attachment will have a Renderbuffer set either 889 * from being a Renderbuffer or being a texture that got the 890 * intel_wrap_texture() treatment. 891 */ 892 rb = fb->Attachment[i].Renderbuffer; 893 if (rb == NULL) { 894 DBG("attachment without renderbuffer\n"); 895 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; 896 continue; 897 } 898 899 irb = intel_renderbuffer(rb); 900 if (irb == NULL) { 901 DBG("software rendering renderbuffer\n"); 902 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; 903 continue; 904 } 905 906 if (!intel->vtbl.render_target_supported(intel, irb->Base.Format)) { 907 DBG("Unsupported HW texture/renderbuffer format attached: %s\n", 908 _mesa_get_format_name(irb->Base.Format)); 909 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; 910 } 911 912#ifdef I915 913 if (!intel_span_supports_format(irb->Base.Format)) { 914 DBG("Unsupported swrast texture/renderbuffer format attached: %s\n", 915 _mesa_get_format_name(irb->Base.Format)); 916 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; 917 } 918#endif 919 } 920} 921 922/** 923 * Try to do a glBlitFramebuffer using glCopyTexSubImage2D 924 * We can do this when the dst renderbuffer is actually a texture and 925 * there is no scaling, mirroring or scissoring. 926 * 927 * \return new buffer mask indicating the buffers left to blit using the 928 * normal path. 929 */ 930static GLbitfield 931intel_blit_framebuffer_copy_tex_sub_image(struct gl_context *ctx, 932 GLint srcX0, GLint srcY0, 933 GLint srcX1, GLint srcY1, 934 GLint dstX0, GLint dstY0, 935 GLint dstX1, GLint dstY1, 936 GLbitfield mask, GLenum filter) 937{ 938 if (mask & GL_COLOR_BUFFER_BIT) { 939 const struct gl_framebuffer *drawFb = ctx->DrawBuffer; 940 const struct gl_framebuffer *readFb = ctx->ReadBuffer; 941 const struct gl_renderbuffer_attachment *drawAtt = 942 &drawFb->Attachment[drawFb->_ColorDrawBufferIndexes[0]]; 943 944 /* If the source and destination are the same size with no 945 mirroring, the rectangles are within the size of the 946 texture and there is no scissor then we can use 947 glCopyTexSubimage2D to implement the blit. This will end 948 up as a fast hardware blit on some drivers */ 949 if (drawAtt && drawAtt->Texture && 950 srcX0 - srcX1 == dstX0 - dstX1 && 951 srcY0 - srcY1 == dstY0 - dstY1 && 952 srcX1 >= srcX0 && 953 srcY1 >= srcY0 && 954 srcX0 >= 0 && srcX1 <= readFb->Width && 955 srcY0 >= 0 && srcY1 <= readFb->Height && 956 dstX0 >= 0 && dstX1 <= drawFb->Width && 957 dstY0 >= 0 && dstY1 <= drawFb->Height && 958 !ctx->Scissor.Enabled) { 959 const struct gl_texture_object *texObj = drawAtt->Texture; 960 const GLuint dstLevel = drawAtt->TextureLevel; 961 const GLenum target = texObj->Target; 962 963 struct gl_texture_image *texImage = 964 _mesa_select_tex_image(ctx, texObj, target, dstLevel); 965 966 if (intel_copy_texsubimage(intel_context(ctx), 967 intel_texture_image(texImage), 968 dstX0, dstY0, 969 srcX0, srcY0, 970 srcX1 - srcX0, /* width */ 971 srcY1 - srcY0)) 972 mask &= ~GL_COLOR_BUFFER_BIT; 973 } 974 } 975 976 return mask; 977} 978 979static void 980intel_blit_framebuffer(struct gl_context *ctx, 981 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 982 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, 983 GLbitfield mask, GLenum filter) 984{ 985 /* Try faster, glCopyTexSubImage2D approach first which uses the BLT. */ 986 mask = intel_blit_framebuffer_copy_tex_sub_image(ctx, 987 srcX0, srcY0, srcX1, srcY1, 988 dstX0, dstY0, dstX1, dstY1, 989 mask, filter); 990 if (mask == 0x0) 991 return; 992 993 _mesa_meta_BlitFramebuffer(ctx, 994 srcX0, srcY0, srcX1, srcY1, 995 dstX0, dstY0, dstX1, dstY1, 996 mask, filter); 997} 998 999void 1000intel_renderbuffer_set_needs_hiz_resolve(struct intel_renderbuffer *irb) 1001{ 1002 if (irb->mt) { 1003 intel_miptree_slice_set_needs_hiz_resolve(irb->mt, 1004 irb->mt_level, 1005 irb->mt_layer); 1006 } else if (irb->wrapped_depth) { 1007 intel_renderbuffer_set_needs_hiz_resolve( 1008 intel_renderbuffer(irb->wrapped_depth)); 1009 } else { 1010 return; 1011 } 1012} 1013 1014void 1015intel_renderbuffer_set_needs_depth_resolve(struct intel_renderbuffer *irb) 1016{ 1017 if (irb->mt) { 1018 intel_miptree_slice_set_needs_depth_resolve(irb->mt, 1019 irb->mt_level, 1020 irb->mt_layer); 1021 } else if (irb->wrapped_depth) { 1022 intel_renderbuffer_set_needs_depth_resolve( 1023 intel_renderbuffer(irb->wrapped_depth)); 1024 } else { 1025 return; 1026 } 1027} 1028 1029bool 1030intel_renderbuffer_resolve_hiz(struct intel_context *intel, 1031 struct intel_renderbuffer *irb) 1032{ 1033 if (irb->mt) 1034 return intel_miptree_slice_resolve_hiz(intel, 1035 irb->mt, 1036 irb->mt_level, 1037 irb->mt_layer); 1038 if (irb->wrapped_depth) 1039 return intel_renderbuffer_resolve_hiz(intel, 1040 intel_renderbuffer(irb->wrapped_depth)); 1041 1042 return false; 1043} 1044 1045bool 1046intel_renderbuffer_resolve_depth(struct intel_context *intel, 1047 struct intel_renderbuffer *irb) 1048{ 1049 if (irb->mt) 1050 return intel_miptree_slice_resolve_depth(intel, 1051 irb->mt, 1052 irb->mt_level, 1053 irb->mt_layer); 1054 1055 if (irb->wrapped_depth) 1056 return intel_renderbuffer_resolve_depth(intel, 1057 intel_renderbuffer(irb->wrapped_depth)); 1058 1059 return false; 1060} 1061 1062/** 1063 * Do one-time context initializations related to GL_EXT_framebuffer_object. 1064 * Hook in device driver functions. 1065 */ 1066void 1067intel_fbo_init(struct intel_context *intel) 1068{ 1069 intel->ctx.Driver.NewFramebuffer = intel_new_framebuffer; 1070 intel->ctx.Driver.NewRenderbuffer = intel_new_renderbuffer; 1071 intel->ctx.Driver.MapRenderbuffer = intel_map_renderbuffer; 1072 intel->ctx.Driver.UnmapRenderbuffer = intel_unmap_renderbuffer; 1073 intel->ctx.Driver.BindFramebuffer = intel_bind_framebuffer; 1074 intel->ctx.Driver.FramebufferRenderbuffer = intel_framebuffer_renderbuffer; 1075 intel->ctx.Driver.RenderTexture = intel_render_texture; 1076 intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture; 1077 intel->ctx.Driver.ResizeBuffers = intel_resize_buffers; 1078 intel->ctx.Driver.ValidateFramebuffer = intel_validate_framebuffer; 1079 intel->ctx.Driver.BlitFramebuffer = intel_blit_framebuffer; 1080 1081#if FEATURE_OES_EGL_image 1082 intel->ctx.Driver.EGLImageTargetRenderbufferStorage = 1083 intel_image_target_renderbuffer_storage; 1084#endif 1085} 1086