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