intel_fbo.c revision f77b720cde981d441e482bbbd68115634b3041ce
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/mtypes.h" 32#include "main/fbobject.h" 33#include "main/framebuffer.h" 34#include "main/renderbuffer.h" 35#include "main/context.h" 36#include "main/texformat.h" 37#include "main/texrender.h" 38 39#include "intel_context.h" 40#include "intel_buffers.h" 41#include "intel_fbo.h" 42#include "intel_mipmap_tree.h" 43#include "intel_regions.h" 44 45 46#define FILE_DEBUG_FLAG DEBUG_FBO 47 48 49/** 50 * Create a new framebuffer object. 51 */ 52static struct gl_framebuffer * 53intel_new_framebuffer(GLcontext * ctx, GLuint name) 54{ 55 /* Only drawable state in intel_framebuffer at this time, just use Mesa's 56 * class 57 */ 58 return _mesa_new_framebuffer(ctx, name); 59} 60 61 62/** Called by gl_renderbuffer::Delete() */ 63static void 64intel_delete_renderbuffer(struct gl_renderbuffer *rb) 65{ 66 GET_CURRENT_CONTEXT(ctx); 67 struct intel_context *intel = intel_context(ctx); 68 struct intel_renderbuffer *irb = intel_renderbuffer(rb); 69 70 ASSERT(irb); 71 72 if (irb->span_cache != NULL) 73 _mesa_free(irb->span_cache); 74 75 if (intel && irb->region) { 76 intel_region_release(&irb->region); 77 } 78 79 _mesa_free(irb); 80} 81 82 83/** 84 * Return a pointer to a specific pixel in a renderbuffer. 85 */ 86static void * 87intel_get_pointer(GLcontext * ctx, struct gl_renderbuffer *rb, 88 GLint x, GLint y) 89{ 90 /* By returning NULL we force all software rendering to go through 91 * the span routines. 92 */ 93 return NULL; 94} 95 96 97/** 98 * Called via glRenderbufferStorageEXT() to set the format and allocate 99 * storage for a user-created renderbuffer. 100 */ 101static GLboolean 102intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb, 103 GLenum internalFormat, 104 GLuint width, GLuint height) 105{ 106 struct intel_context *intel = intel_context(ctx); 107 struct intel_renderbuffer *irb = intel_renderbuffer(rb); 108 GLboolean softwareBuffer = GL_FALSE; 109 int cpp; 110 111 ASSERT(rb->Name != 0); 112 113 switch (internalFormat) { 114 case GL_R3_G3_B2: 115 case GL_RGB4: 116 case GL_RGB5: 117 rb->_ActualFormat = GL_RGB5; 118 rb->DataType = GL_UNSIGNED_BYTE; 119 rb->RedBits = 5; 120 rb->GreenBits = 6; 121 rb->BlueBits = 5; 122 cpp = 2; 123 break; 124 case GL_RGB: 125 case GL_RGB8: 126 case GL_RGB10: 127 case GL_RGB12: 128 case GL_RGB16: 129 rb->_ActualFormat = GL_RGB8; 130 rb->DataType = GL_UNSIGNED_BYTE; 131 rb->RedBits = 8; 132 rb->GreenBits = 8; 133 rb->BlueBits = 8; 134 rb->AlphaBits = 0; 135 cpp = 4; 136 break; 137 case GL_RGBA: 138 case GL_RGBA2: 139 case GL_RGBA4: 140 case GL_RGB5_A1: 141 case GL_RGBA8: 142 case GL_RGB10_A2: 143 case GL_RGBA12: 144 case GL_RGBA16: 145 rb->_ActualFormat = GL_RGBA8; 146 rb->DataType = GL_UNSIGNED_BYTE; 147 rb->RedBits = 8; 148 rb->GreenBits = 8; 149 rb->BlueBits = 8; 150 rb->AlphaBits = 8; 151 cpp = 4; 152 break; 153 case GL_STENCIL_INDEX: 154 case GL_STENCIL_INDEX1_EXT: 155 case GL_STENCIL_INDEX4_EXT: 156 case GL_STENCIL_INDEX8_EXT: 157 case GL_STENCIL_INDEX16_EXT: 158 /* alloc a depth+stencil buffer */ 159 rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT; 160 rb->DataType = GL_UNSIGNED_INT_24_8_EXT; 161 rb->StencilBits = 8; 162 cpp = 4; 163 break; 164 case GL_DEPTH_COMPONENT16: 165 rb->_ActualFormat = GL_DEPTH_COMPONENT16; 166 rb->DataType = GL_UNSIGNED_SHORT; 167 rb->DepthBits = 16; 168 cpp = 2; 169 break; 170 case GL_DEPTH_COMPONENT: 171 case GL_DEPTH_COMPONENT24: 172 case GL_DEPTH_COMPONENT32: 173 rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT; 174 rb->DataType = GL_UNSIGNED_INT_24_8_EXT; 175 rb->DepthBits = 24; 176 cpp = 4; 177 break; 178 case GL_DEPTH_STENCIL_EXT: 179 case GL_DEPTH24_STENCIL8_EXT: 180 rb->_ActualFormat = GL_DEPTH24_STENCIL8_EXT; 181 rb->DataType = GL_UNSIGNED_INT_24_8_EXT; 182 rb->DepthBits = 24; 183 rb->StencilBits = 8; 184 cpp = 4; 185 break; 186 default: 187 _mesa_problem(ctx, 188 "Unexpected format in intel_alloc_renderbuffer_storage"); 189 return GL_FALSE; 190 } 191 192 intelFlush(ctx); 193 194 /* free old region */ 195 if (irb->region) { 196 intel_region_release(&irb->region); 197 } 198 199 /* allocate new memory region/renderbuffer */ 200 if (softwareBuffer) { 201 return _mesa_soft_renderbuffer_storage(ctx, rb, internalFormat, 202 width, height); 203 } 204 else { 205 /* Choose a pitch to match hardware requirements: 206 */ 207 GLuint pitch = ((cpp * width + 63) & ~63) / cpp; 208 209 /* alloc hardware renderbuffer */ 210 DBG("Allocating %d x %d Intel RBO (pitch %d)\n", width, 211 height, pitch); 212 213 irb->region = intel_region_alloc(intel, cpp, width, height, pitch, 214 GL_TRUE); 215 if (!irb->region) 216 return GL_FALSE; /* out of memory? */ 217 218 ASSERT(irb->region->buffer); 219 220 rb->Width = width; 221 rb->Height = height; 222 223 return GL_TRUE; 224 } 225} 226 227 228/** 229 * Called for each hardware renderbuffer when a _window_ is resized. 230 * Just update fields. 231 * Not used for user-created renderbuffers! 232 */ 233static GLboolean 234intel_alloc_window_storage(GLcontext * ctx, struct gl_renderbuffer *rb, 235 GLenum internalFormat, GLuint width, GLuint height) 236{ 237 ASSERT(rb->Name == 0); 238 rb->Width = width; 239 rb->Height = height; 240 rb->_ActualFormat = internalFormat; 241 242 return GL_TRUE; 243} 244 245 246static void 247intel_resize_buffers(GLcontext *ctx, struct gl_framebuffer *fb, 248 GLuint width, GLuint height) 249{ 250 struct intel_framebuffer *intel_fb = (struct intel_framebuffer*)fb; 251 int i; 252 253 _mesa_resize_framebuffer(ctx, fb, width, height); 254 255 fb->Initialized = GL_TRUE; /* XXX remove someday */ 256 257 if (fb->Name != 0) { 258 return; 259 } 260 261 /* Make sure all window system renderbuffers are up to date */ 262 for (i = 0; i < 2; i++) { 263 struct gl_renderbuffer *rb = &intel_fb->color_rb[i]->Base; 264 265 /* only resize if size is changing */ 266 if (rb && (rb->Width != width || rb->Height != height)) { 267 rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height); 268 } 269 } 270} 271 272 273/** Dummy function for gl_renderbuffer::AllocStorage() */ 274static GLboolean 275intel_nop_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb, 276 GLenum internalFormat, GLuint width, GLuint height) 277{ 278 _mesa_problem(ctx, "intel_op_alloc_storage should never be called."); 279 return GL_FALSE; 280} 281 282 283void 284intel_renderbuffer_set_region(struct intel_renderbuffer *rb, 285 struct intel_region *region) 286{ 287 struct intel_region *old; 288 289 old = rb->region; 290 rb->region = NULL; 291 intel_region_reference(&rb->region, region); 292 intel_region_release(&old); 293} 294 295 296/** 297 * Create a new intel_renderbuffer which corresponds to an on-screen window, 298 * not a user-created renderbuffer. 299 */ 300struct intel_renderbuffer * 301intel_create_renderbuffer(GLenum intFormat) 302{ 303 GET_CURRENT_CONTEXT(ctx); 304 305 struct intel_renderbuffer *irb; 306 const GLuint name = 0; 307 308 irb = CALLOC_STRUCT(intel_renderbuffer); 309 if (!irb) { 310 _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer"); 311 return NULL; 312 } 313 314 _mesa_init_renderbuffer(&irb->Base, name); 315 irb->Base.ClassID = INTEL_RB_CLASS; 316 317 switch (intFormat) { 318 case GL_RGB5: 319 irb->Base._ActualFormat = GL_RGB5; 320 irb->Base._BaseFormat = GL_RGBA; 321 irb->Base.RedBits = 5; 322 irb->Base.GreenBits = 6; 323 irb->Base.BlueBits = 5; 324 irb->Base.DataType = GL_UNSIGNED_BYTE; 325 break; 326 case GL_RGB8: 327 irb->Base._ActualFormat = GL_RGB8; 328 irb->Base._BaseFormat = GL_RGB; 329 irb->Base.RedBits = 8; 330 irb->Base.GreenBits = 8; 331 irb->Base.BlueBits = 8; 332 irb->Base.AlphaBits = 0; 333 irb->Base.DataType = GL_UNSIGNED_BYTE; 334 break; 335 case GL_RGBA8: 336 irb->Base._ActualFormat = GL_RGBA8; 337 irb->Base._BaseFormat = GL_RGBA; 338 irb->Base.RedBits = 8; 339 irb->Base.GreenBits = 8; 340 irb->Base.BlueBits = 8; 341 irb->Base.AlphaBits = 8; 342 irb->Base.DataType = GL_UNSIGNED_BYTE; 343 break; 344 case GL_STENCIL_INDEX8_EXT: 345 irb->Base._ActualFormat = GL_STENCIL_INDEX8_EXT; 346 irb->Base._BaseFormat = GL_STENCIL_INDEX; 347 irb->Base.StencilBits = 8; 348 irb->Base.DataType = GL_UNSIGNED_BYTE; 349 break; 350 case GL_DEPTH_COMPONENT16: 351 irb->Base._ActualFormat = GL_DEPTH_COMPONENT16; 352 irb->Base._BaseFormat = GL_DEPTH_COMPONENT; 353 irb->Base.DepthBits = 16; 354 irb->Base.DataType = GL_UNSIGNED_SHORT; 355 break; 356 case GL_DEPTH_COMPONENT24: 357 irb->Base._ActualFormat = GL_DEPTH24_STENCIL8_EXT; 358 irb->Base._BaseFormat = GL_DEPTH_COMPONENT; 359 irb->Base.DepthBits = 24; 360 irb->Base.DataType = GL_UNSIGNED_INT; 361 break; 362 case GL_DEPTH24_STENCIL8_EXT: 363 irb->Base._ActualFormat = GL_DEPTH24_STENCIL8_EXT; 364 irb->Base._BaseFormat = GL_DEPTH_STENCIL_EXT; 365 irb->Base.DepthBits = 24; 366 irb->Base.StencilBits = 8; 367 irb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT; 368 break; 369 default: 370 _mesa_problem(NULL, 371 "Unexpected intFormat in intel_create_renderbuffer"); 372 return NULL; 373 } 374 375 irb->Base.InternalFormat = intFormat; 376 377 /* intel-specific methods */ 378 irb->Base.Delete = intel_delete_renderbuffer; 379 irb->Base.AllocStorage = intel_alloc_window_storage; 380 irb->Base.GetPointer = intel_get_pointer; 381 382 return irb; 383} 384 385 386/** 387 * Create a new renderbuffer object. 388 * Typically called via glBindRenderbufferEXT(). 389 */ 390static struct gl_renderbuffer * 391intel_new_renderbuffer(GLcontext * ctx, GLuint name) 392{ 393 /*struct intel_context *intel = intel_context(ctx); */ 394 struct intel_renderbuffer *irb; 395 396 irb = CALLOC_STRUCT(intel_renderbuffer); 397 if (!irb) { 398 _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer"); 399 return NULL; 400 } 401 402 _mesa_init_renderbuffer(&irb->Base, name); 403 irb->Base.ClassID = INTEL_RB_CLASS; 404 405 /* intel-specific methods */ 406 irb->Base.Delete = intel_delete_renderbuffer; 407 irb->Base.AllocStorage = intel_alloc_renderbuffer_storage; 408 irb->Base.GetPointer = intel_get_pointer; 409 /* span routines set in alloc_storage function */ 410 411 return &irb->Base; 412} 413 414 415/** 416 * Called via glBindFramebufferEXT(). 417 */ 418static void 419intel_bind_framebuffer(GLcontext * ctx, GLenum target, 420 struct gl_framebuffer *fb, struct gl_framebuffer *fbread) 421{ 422 if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) { 423 intel_draw_buffer(ctx, fb); 424 } 425 else { 426 /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */ 427 } 428} 429 430 431/** 432 * Called via glFramebufferRenderbufferEXT(). 433 */ 434static void 435intel_framebuffer_renderbuffer(GLcontext * ctx, 436 struct gl_framebuffer *fb, 437 GLenum attachment, struct gl_renderbuffer *rb) 438{ 439 DBG("Intel FramebufferRenderbuffer %u %u\n", fb->Name, rb ? rb->Name : 0); 440 441 intelFlush(ctx); 442 443 _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb); 444 intel_draw_buffer(ctx, fb); 445} 446 447 448static GLboolean 449intel_update_wrapper(GLcontext *ctx, struct intel_renderbuffer *irb, 450 struct gl_texture_image *texImage) 451{ 452 if (texImage->TexFormat == &_mesa_texformat_argb8888) { 453 irb->Base._ActualFormat = GL_RGBA8; 454 irb->Base._BaseFormat = GL_RGBA; 455 irb->Base.DataType = GL_UNSIGNED_BYTE; 456 DBG("Render to RGBA8 texture OK\n"); 457 } 458 else if (texImage->TexFormat == &_mesa_texformat_rgb565) { 459 irb->Base._ActualFormat = GL_RGB5; 460 irb->Base._BaseFormat = GL_RGB; 461 irb->Base.DataType = GL_UNSIGNED_SHORT; 462 DBG("Render to RGB5 texture OK\n"); 463 } 464 else if (texImage->TexFormat == &_mesa_texformat_z16) { 465 irb->Base._ActualFormat = GL_DEPTH_COMPONENT16; 466 irb->Base._BaseFormat = GL_DEPTH_COMPONENT; 467 irb->Base.DataType = GL_UNSIGNED_SHORT; 468 DBG("Render to DEPTH16 texture OK\n"); 469 } 470 else if (texImage->TexFormat == &_mesa_texformat_s8_z24) { 471 irb->Base._ActualFormat = GL_DEPTH24_STENCIL8_EXT; 472 irb->Base._BaseFormat = GL_DEPTH_STENCIL_EXT; 473 irb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT; 474 DBG("Render to DEPTH_STENCIL texture OK\n"); 475 } 476 else { 477 DBG("Render to texture BAD FORMAT %d\n", 478 texImage->TexFormat->MesaFormat); 479 return GL_FALSE; 480 } 481 482 irb->Base.InternalFormat = irb->Base._ActualFormat; 483 irb->Base.Width = texImage->Width; 484 irb->Base.Height = texImage->Height; 485 irb->Base.RedBits = texImage->TexFormat->RedBits; 486 irb->Base.GreenBits = texImage->TexFormat->GreenBits; 487 irb->Base.BlueBits = texImage->TexFormat->BlueBits; 488 irb->Base.AlphaBits = texImage->TexFormat->AlphaBits; 489 irb->Base.DepthBits = texImage->TexFormat->DepthBits; 490 491 irb->Base.Delete = intel_delete_renderbuffer; 492 irb->Base.AllocStorage = intel_nop_alloc_storage; 493 494 return GL_TRUE; 495} 496 497 498/** 499 * When glFramebufferTexture[123]D is called this function sets up the 500 * gl_renderbuffer wrapper around the texture image. 501 * This will have the region info needed for hardware rendering. 502 */ 503static struct intel_renderbuffer * 504intel_wrap_texture(GLcontext * ctx, struct gl_texture_image *texImage) 505{ 506 const GLuint name = ~0; /* not significant, but distinct for debugging */ 507 struct intel_renderbuffer *irb; 508 509 /* make an intel_renderbuffer to wrap the texture image */ 510 irb = CALLOC_STRUCT(intel_renderbuffer); 511 if (!irb) { 512 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture"); 513 return NULL; 514 } 515 516 _mesa_init_renderbuffer(&irb->Base, name); 517 irb->Base.ClassID = INTEL_RB_CLASS; 518 519 if (!intel_update_wrapper(ctx, irb, texImage)) { 520 _mesa_free(irb); 521 return NULL; 522 } 523 524 return irb; 525} 526 527 528/** 529 * Called by glFramebufferTexture[123]DEXT() (and other places) to 530 * prepare for rendering into texture memory. This might be called 531 * many times to choose different texture levels, cube faces, etc 532 * before intel_finish_render_texture() is ever called. 533 */ 534static void 535intel_render_texture(GLcontext * ctx, 536 struct gl_framebuffer *fb, 537 struct gl_renderbuffer_attachment *att) 538{ 539 struct gl_texture_image *newImage 540 = att->Texture->Image[att->CubeMapFace][att->TextureLevel]; 541 struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer); 542 struct intel_texture_image *intel_image; 543 GLuint imageOffset; 544 545 (void) fb; 546 547 ASSERT(newImage); 548 549 if (newImage->Border != 0) { 550 /* Fallback on drawing to a texture with a border, which won't have a 551 * miptree. 552 */ 553 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); 554 _mesa_render_texture(ctx, fb, att); 555 return; 556 } 557 else if (!irb) { 558 irb = intel_wrap_texture(ctx, newImage); 559 if (irb) { 560 /* bind the wrapper to the attachment point */ 561 _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base); 562 } 563 else { 564 /* fallback to software rendering */ 565 _mesa_render_texture(ctx, fb, att); 566 return; 567 } 568 } 569 570 if (!intel_update_wrapper(ctx, irb, newImage)) { 571 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); 572 _mesa_render_texture(ctx, fb, att); 573 return; 574 } 575 576 DBG("Begin render texture tid %x tex=%u w=%d h=%d refcount=%d\n", 577 _glthread_GetID(), 578 att->Texture->Name, newImage->Width, newImage->Height, 579 irb->Base.RefCount); 580 581 /* point the renderbufer's region to the texture image region */ 582 intel_image = intel_texture_image(newImage); 583 if (irb->region != intel_image->mt->region) { 584 if (irb->region) 585 intel_region_release(&irb->region); 586 intel_region_reference(&irb->region, intel_image->mt->region); 587 } 588 589 /* compute offset of the particular 2D image within the texture region */ 590 imageOffset = intel_miptree_image_offset(intel_image->mt, 591 att->CubeMapFace, 592 att->TextureLevel); 593 594 if (att->Texture->Target == GL_TEXTURE_3D) { 595 const GLuint *offsets = intel_miptree_depth_offsets(intel_image->mt, 596 att->TextureLevel); 597 imageOffset += offsets[att->Zoffset]; 598 } 599 600 /* store that offset in the region */ 601 intel_image->mt->region->draw_offset = imageOffset; 602 603 /* update drawing region, etc */ 604 intel_draw_buffer(ctx, fb); 605} 606 607 608/** 609 * Called by Mesa when rendering to a texture is done. 610 */ 611static void 612intel_finish_render_texture(GLcontext * ctx, 613 struct gl_renderbuffer_attachment *att) 614{ 615 struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer); 616 617 DBG("End render texture (tid %x) tex %u\n", _glthread_GetID(), att->Texture->Name); 618 619 if (irb) { 620 /* just release the region */ 621 intel_region_release(&irb->region); 622 } 623 else if (att->Renderbuffer) { 624 /* software fallback */ 625 _mesa_finish_render_texture(ctx, att); 626 /* XXX FBO: Need to unmap the buffer (or in intelSpanRenderStart???) */ 627 } 628} 629 630 631/** 632 * Do additional "completeness" testing of a framebuffer object. 633 */ 634static void 635intel_validate_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb) 636{ 637 struct intel_context *intel = intel_context(ctx); 638 const struct intel_renderbuffer *depthRb = 639 intel_get_renderbuffer(fb, BUFFER_DEPTH); 640 const struct intel_renderbuffer *stencilRb = 641 intel_get_renderbuffer(fb, BUFFER_STENCIL); 642 643 if (stencilRb && stencilRb != depthRb) { 644 /* we only support combined depth/stencil buffers, not separate 645 * stencil buffers. 646 */ 647 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; 648 } 649 650 /* check that texture color buffers are a format we can render into */ 651 { 652 const struct gl_texture_format *supportedFormat; 653 GLuint i; 654 655 /* The texture format we can render into seems to depend on the 656 * screen depth. There currently seems to be a problem when 657 * rendering into a rgb565 texture when the screen is abgr8888. 658 */ 659 if (intel->front_region->cpp == 4) 660 supportedFormat = &_mesa_texformat_argb8888; 661 else 662 supportedFormat = &_mesa_texformat_rgb565; 663 664 for (i = 0; i < ctx->Const.MaxDrawBuffers; i++) { 665 const struct gl_texture_object *texObj = 666 fb->Attachment[BUFFER_COLOR0 + i].Texture; 667 if (texObj) { 668 const struct gl_texture_image *texImg = 669 texObj->Image[0][texObj->BaseLevel]; 670 if (texImg && texImg->TexFormat != supportedFormat) { 671 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; 672 break; 673 } 674 } 675 } 676 } 677} 678 679 680/** 681 * Called from glBlitFramebuffer(). 682 * For now, we're doing an approximation with glCopyPixels(). 683 * XXX we need to bypass all the per-fragment operations, except scissor. 684 */ 685static void 686intel_blit_framebuffer(GLcontext *ctx, 687 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 688 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, 689 GLbitfield mask, GLenum filter) 690{ 691 const GLfloat xZoomSave = ctx->Pixel.ZoomX; 692 const GLfloat yZoomSave = ctx->Pixel.ZoomY; 693 GLsizei width, height; 694 GLfloat xFlip = 1.0F, yFlip = 1.0F; 695 696 if (srcX1 < srcX0) { 697 GLint tmp = srcX1; 698 srcX1 = srcX0; 699 srcX0 = tmp; 700 xFlip = -1.0F; 701 } 702 703 if (srcY1 < srcY0) { 704 GLint tmp = srcY1; 705 srcY1 = srcY0; 706 srcY0 = tmp; 707 yFlip = -1.0F; 708 } 709 710 width = srcX1 - srcX0; 711 height = srcY1 - srcY0; 712 713 ctx->Pixel.ZoomX = xFlip * (dstX1 - dstX0) / (srcX1 - srcY0); 714 ctx->Pixel.ZoomY = yFlip * (dstY1 - dstY0) / (srcY1 - srcY0); 715 716 if (ctx->Pixel.ZoomX < 0.0F) { 717 dstX0 = MAX2(dstX0, dstX1); 718 } 719 else { 720 dstX0 = MIN2(dstX0, dstX1); 721 } 722 723 if (ctx->Pixel.ZoomY < 0.0F) { 724 dstY0 = MAX2(dstY0, dstY1); 725 } 726 else { 727 dstY0 = MIN2(dstY0, dstY1); 728 } 729 730 if (mask & GL_COLOR_BUFFER_BIT) { 731 ctx->Driver.CopyPixels(ctx, srcX0, srcY0, width, height, 732 dstX0, dstY0, GL_COLOR); 733 } 734 if (mask & GL_DEPTH_BUFFER_BIT) { 735 ctx->Driver.CopyPixels(ctx, srcX0, srcY0, width, height, 736 dstX0, dstY0, GL_DEPTH); 737 } 738 if (mask & GL_STENCIL_BUFFER_BIT) { 739 ctx->Driver.CopyPixels(ctx, srcX0, srcY0, width, height, 740 dstX0, dstY0, GL_STENCIL); 741 } 742 743 ctx->Pixel.ZoomX = xZoomSave; 744 ctx->Pixel.ZoomY = yZoomSave; 745} 746 747 748/** 749 * Do one-time context initializations related to GL_EXT_framebuffer_object. 750 * Hook in device driver functions. 751 */ 752void 753intel_fbo_init(struct intel_context *intel) 754{ 755 intel->ctx.Driver.NewFramebuffer = intel_new_framebuffer; 756 intel->ctx.Driver.NewRenderbuffer = intel_new_renderbuffer; 757 intel->ctx.Driver.BindFramebuffer = intel_bind_framebuffer; 758 intel->ctx.Driver.FramebufferRenderbuffer = intel_framebuffer_renderbuffer; 759 intel->ctx.Driver.RenderTexture = intel_render_texture; 760 intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture; 761 intel->ctx.Driver.ResizeBuffers = intel_resize_buffers; 762 intel->ctx.Driver.ValidateFramebuffer = intel_validate_framebuffer; 763 intel->ctx.Driver.BlitFramebuffer = intel_blit_framebuffer; 764} 765