intel_fbo.c revision d332a74e772eb60cf3cef33cafad997436fd9e93
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 if (!irb->region) 215 return GL_FALSE; /* out of memory? */ 216 217 ASSERT(irb->region->buffer); 218 219 rb->Width = width; 220 rb->Height = height; 221 222 return GL_TRUE; 223 } 224} 225 226 227/** 228 * Called for each hardware renderbuffer when a _window_ is resized. 229 * Just update fields. 230 * Not used for user-created renderbuffers! 231 */ 232static GLboolean 233intel_alloc_window_storage(GLcontext * ctx, struct gl_renderbuffer *rb, 234 GLenum internalFormat, GLuint width, GLuint height) 235{ 236 ASSERT(rb->Name == 0); 237 rb->Width = width; 238 rb->Height = height; 239 rb->_ActualFormat = internalFormat; 240 241 return GL_TRUE; 242} 243 244 245static void 246intel_resize_buffers(GLcontext *ctx, struct gl_framebuffer *fb, 247 GLuint width, GLuint height) 248{ 249 struct intel_framebuffer *intel_fb = (struct intel_framebuffer*)fb; 250 int i; 251 252 _mesa_resize_framebuffer(ctx, fb, width, height); 253 254 fb->Initialized = GL_TRUE; /* XXX remove someday */ 255 256 if (fb->Name != 0) { 257 return; 258 } 259 260 /* Make sure all window system renderbuffers are up to date */ 261 for (i = 0; i < 2; i++) { 262 struct gl_renderbuffer *rb = &intel_fb->color_rb[i]->Base; 263 264 /* only resize if size is changing */ 265 if (rb && (rb->Width != width || rb->Height != height)) { 266 rb->AllocStorage(ctx, rb, rb->InternalFormat, width, height); 267 } 268 } 269} 270 271 272/** Dummy function for gl_renderbuffer::AllocStorage() */ 273static GLboolean 274intel_nop_alloc_storage(GLcontext * ctx, struct gl_renderbuffer *rb, 275 GLenum internalFormat, GLuint width, GLuint height) 276{ 277 _mesa_problem(ctx, "intel_op_alloc_storage should never be called."); 278 return GL_FALSE; 279} 280 281 282void 283intel_renderbuffer_set_region(struct intel_renderbuffer *rb, 284 struct intel_region *region) 285{ 286 struct intel_region *old; 287 288 old = rb->region; 289 rb->region = NULL; 290 intel_region_reference(&rb->region, region); 291 intel_region_release(&old); 292} 293 294 295/** 296 * Create a new intel_renderbuffer which corresponds to an on-screen window, 297 * not a user-created renderbuffer. 298 */ 299struct intel_renderbuffer * 300intel_create_renderbuffer(GLenum intFormat) 301{ 302 GET_CURRENT_CONTEXT(ctx); 303 304 struct intel_renderbuffer *irb; 305 const GLuint name = 0; 306 307 irb = CALLOC_STRUCT(intel_renderbuffer); 308 if (!irb) { 309 _mesa_error(ctx, GL_OUT_OF_MEMORY, "creating renderbuffer"); 310 return NULL; 311 } 312 313 _mesa_init_renderbuffer(&irb->Base, name); 314 irb->Base.ClassID = INTEL_RB_CLASS; 315 316 switch (intFormat) { 317 case GL_RGB5: 318 irb->Base._ActualFormat = GL_RGB5; 319 irb->Base._BaseFormat = GL_RGBA; 320 irb->Base.RedBits = 5; 321 irb->Base.GreenBits = 6; 322 irb->Base.BlueBits = 5; 323 irb->Base.DataType = GL_UNSIGNED_BYTE; 324 break; 325 case GL_RGBA8: 326 irb->Base._ActualFormat = GL_RGBA8; 327 irb->Base._BaseFormat = GL_RGBA; 328 irb->Base.RedBits = 8; 329 irb->Base.GreenBits = 8; 330 irb->Base.BlueBits = 8; 331 irb->Base.AlphaBits = 8; 332 irb->Base.DataType = GL_UNSIGNED_BYTE; 333 break; 334 case GL_STENCIL_INDEX8_EXT: 335 irb->Base._ActualFormat = GL_STENCIL_INDEX8_EXT; 336 irb->Base._BaseFormat = GL_STENCIL_INDEX; 337 irb->Base.StencilBits = 8; 338 irb->Base.DataType = GL_UNSIGNED_BYTE; 339 break; 340 case GL_DEPTH_COMPONENT16: 341 irb->Base._ActualFormat = GL_DEPTH_COMPONENT16; 342 irb->Base._BaseFormat = GL_DEPTH_COMPONENT; 343 irb->Base.DepthBits = 16; 344 irb->Base.DataType = GL_UNSIGNED_SHORT; 345 break; 346 case GL_DEPTH_COMPONENT24: 347 irb->Base._ActualFormat = GL_DEPTH24_STENCIL8_EXT; 348 irb->Base._BaseFormat = GL_DEPTH_COMPONENT; 349 irb->Base.DepthBits = 24; 350 irb->Base.DataType = GL_UNSIGNED_INT; 351 break; 352 case GL_DEPTH24_STENCIL8_EXT: 353 irb->Base._ActualFormat = GL_DEPTH24_STENCIL8_EXT; 354 irb->Base._BaseFormat = GL_DEPTH_STENCIL_EXT; 355 irb->Base.DepthBits = 24; 356 irb->Base.StencilBits = 8; 357 irb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT; 358 break; 359 default: 360 _mesa_problem(NULL, 361 "Unexpected intFormat in intel_create_renderbuffer"); 362 return NULL; 363 } 364 365 irb->Base.InternalFormat = intFormat; 366 367 /* intel-specific methods */ 368 irb->Base.Delete = intel_delete_renderbuffer; 369 irb->Base.AllocStorage = intel_alloc_window_storage; 370 irb->Base.GetPointer = intel_get_pointer; 371 372 return irb; 373} 374 375 376/** 377 * Create a new renderbuffer object. 378 * Typically called via glBindRenderbufferEXT(). 379 */ 380static struct gl_renderbuffer * 381intel_new_renderbuffer(GLcontext * ctx, GLuint name) 382{ 383 /*struct intel_context *intel = intel_context(ctx); */ 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, name); 393 irb->Base.ClassID = INTEL_RB_CLASS; 394 395 /* intel-specific methods */ 396 irb->Base.Delete = intel_delete_renderbuffer; 397 irb->Base.AllocStorage = intel_alloc_renderbuffer_storage; 398 irb->Base.GetPointer = intel_get_pointer; 399 /* span routines set in alloc_storage function */ 400 401 return &irb->Base; 402} 403 404 405/** 406 * Called via glBindFramebufferEXT(). 407 */ 408static void 409intel_bind_framebuffer(GLcontext * ctx, GLenum target, 410 struct gl_framebuffer *fb, struct gl_framebuffer *fbread) 411{ 412 if (target == GL_FRAMEBUFFER_EXT || target == GL_DRAW_FRAMEBUFFER_EXT) { 413 intel_draw_buffer(ctx, fb); 414 } 415 else { 416 /* don't need to do anything if target == GL_READ_FRAMEBUFFER_EXT */ 417 } 418} 419 420 421/** 422 * Called via glFramebufferRenderbufferEXT(). 423 */ 424static void 425intel_framebuffer_renderbuffer(GLcontext * ctx, 426 struct gl_framebuffer *fb, 427 GLenum attachment, struct gl_renderbuffer *rb) 428{ 429 DBG("Intel FramebufferRenderbuffer %u %u\n", fb->Name, rb ? rb->Name : 0); 430 431 intelFlush(ctx); 432 433 _mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb); 434 intel_draw_buffer(ctx, fb); 435} 436 437 438static GLboolean 439intel_update_wrapper(GLcontext *ctx, struct intel_renderbuffer *irb, 440 struct gl_texture_image *texImage) 441{ 442 if (texImage->TexFormat == &_mesa_texformat_argb8888) { 443 irb->Base._ActualFormat = GL_RGBA8; 444 irb->Base._BaseFormat = GL_RGBA; 445 irb->Base.DataType = GL_UNSIGNED_BYTE; 446 DBG("Render to RGBA8 texture OK\n"); 447 } 448 else if (texImage->TexFormat == &_mesa_texformat_rgb565) { 449 irb->Base._ActualFormat = GL_RGB5; 450 irb->Base._BaseFormat = GL_RGB; 451 irb->Base.DataType = GL_UNSIGNED_SHORT; 452 DBG("Render to RGB5 texture OK\n"); 453 } 454 else if (texImage->TexFormat == &_mesa_texformat_z16) { 455 irb->Base._ActualFormat = GL_DEPTH_COMPONENT16; 456 irb->Base._BaseFormat = GL_DEPTH_COMPONENT; 457 irb->Base.DataType = GL_UNSIGNED_SHORT; 458 DBG("Render to DEPTH16 texture OK\n"); 459 } 460 else if (texImage->TexFormat == &_mesa_texformat_s8_z24) { 461 irb->Base._ActualFormat = GL_DEPTH24_STENCIL8_EXT; 462 irb->Base._BaseFormat = GL_DEPTH_STENCIL_EXT; 463 irb->Base.DataType = GL_UNSIGNED_INT_24_8_EXT; 464 DBG("Render to DEPTH_STENCIL texture OK\n"); 465 } 466 else { 467 DBG("Render to texture BAD FORMAT %d\n", 468 texImage->TexFormat->MesaFormat); 469 return GL_FALSE; 470 } 471 472 irb->Base.InternalFormat = irb->Base._ActualFormat; 473 irb->Base.Width = texImage->Width; 474 irb->Base.Height = texImage->Height; 475 irb->Base.RedBits = texImage->TexFormat->RedBits; 476 irb->Base.GreenBits = texImage->TexFormat->GreenBits; 477 irb->Base.BlueBits = texImage->TexFormat->BlueBits; 478 irb->Base.AlphaBits = texImage->TexFormat->AlphaBits; 479 irb->Base.DepthBits = texImage->TexFormat->DepthBits; 480 481 irb->Base.Delete = intel_delete_renderbuffer; 482 irb->Base.AllocStorage = intel_nop_alloc_storage; 483 484 irb->RenderToTexture = GL_TRUE; 485 486 return GL_TRUE; 487} 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 } 549 else if (!irb) { 550 irb = intel_wrap_texture(ctx, newImage); 551 if (irb) { 552 /* bind the wrapper to the attachment point */ 553 _mesa_reference_renderbuffer(&att->Renderbuffer, &irb->Base); 554 } 555 else { 556 /* fallback to software rendering */ 557 _mesa_render_texture(ctx, fb, att); 558 return; 559 } 560 } 561 562 if (!intel_update_wrapper(ctx, irb, newImage)) { 563 _mesa_reference_renderbuffer(&att->Renderbuffer, NULL); 564 _mesa_render_texture(ctx, fb, att); 565 return; 566 } 567 568 DBG("Begin render texture tid %x tex=%u w=%d h=%d refcount=%d\n", 569 _glthread_GetID(), 570 att->Texture->Name, newImage->Width, newImage->Height, 571 irb->Base.RefCount); 572 573 /* point the renderbufer's region to the texture image region */ 574 intel_image = intel_texture_image(newImage); 575 if (irb->region != intel_image->mt->region) { 576 if (irb->region) 577 intel_region_release(&irb->region); 578 intel_region_reference(&irb->region, intel_image->mt->region); 579 } 580 581 /* compute offset of the particular 2D image within the texture region */ 582 imageOffset = intel_miptree_image_offset(intel_image->mt, 583 att->CubeMapFace, 584 att->TextureLevel); 585 586 if (att->Texture->Target == GL_TEXTURE_3D) { 587 const GLuint *offsets = intel_miptree_depth_offsets(intel_image->mt, 588 att->TextureLevel); 589 imageOffset += offsets[att->Zoffset]; 590 } 591 592 /* store that offset in the region */ 593 intel_image->mt->region->draw_offset = imageOffset; 594 595 /* update drawing region, etc */ 596 intel_draw_buffer(ctx, fb); 597} 598 599 600/** 601 * Called by Mesa when rendering to a texture is done. 602 */ 603static void 604intel_finish_render_texture(GLcontext * ctx, 605 struct gl_renderbuffer_attachment *att) 606{ 607 struct intel_renderbuffer *irb = intel_renderbuffer(att->Renderbuffer); 608 609 DBG("End render texture (tid %x) tex %u\n", _glthread_GetID(), att->Texture->Name); 610 611 if (irb) { 612 /* just release the region */ 613 intel_region_release(&irb->region); 614 } 615 else if (att->Renderbuffer) { 616 /* software fallback */ 617 _mesa_finish_render_texture(ctx, att); 618 /* XXX FBO: Need to unmap the buffer (or in intelSpanRenderStart???) */ 619 } 620} 621 622 623/** 624 * Do additional "completeness" testing of a framebuffer object. 625 */ 626static void 627intel_validate_framebuffer(GLcontext *ctx, struct gl_framebuffer *fb) 628{ 629 const struct intel_renderbuffer *depthRb = 630 intel_get_renderbuffer(fb, BUFFER_DEPTH); 631 const struct intel_renderbuffer *stencilRb = 632 intel_get_renderbuffer(fb, BUFFER_STENCIL); 633 634 if (stencilRb && stencilRb != depthRb) { 635 /* we only support combined depth/stencil buffers, not separate 636 * stencil buffers. 637 */ 638 fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT; 639 } 640} 641 642 643/** 644 * Called from glBlitFramebuffer(). 645 * For now, we're doing an approximation with glCopyPixels(). 646 * XXX we need to bypass all the per-fragment operations, except scissor. 647 */ 648static void 649intel_blit_framebuffer(GLcontext *ctx, 650 GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, 651 GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, 652 GLbitfield mask, GLenum filter) 653{ 654 const GLfloat xZoomSave = ctx->Pixel.ZoomX; 655 const GLfloat yZoomSave = ctx->Pixel.ZoomY; 656 GLsizei width, height; 657 GLfloat xFlip = 1.0F, yFlip = 1.0F; 658 659 if (srcX1 < srcX0) { 660 GLint tmp = srcX1; 661 srcX1 = srcX0; 662 srcX0 = tmp; 663 xFlip = -1.0F; 664 } 665 666 if (srcY1 < srcY0) { 667 GLint tmp = srcY1; 668 srcY1 = srcY0; 669 srcY0 = tmp; 670 yFlip = -1.0F; 671 } 672 673 width = srcX1 - srcX0; 674 height = srcY1 - srcY0; 675 676 ctx->Pixel.ZoomX = xFlip * (dstX1 - dstX0) / (srcX1 - srcY0); 677 ctx->Pixel.ZoomY = yFlip * (dstY1 - dstY0) / (srcY1 - srcY0); 678 679 if (ctx->Pixel.ZoomX < 0.0F) { 680 dstX0 = MAX2(dstX0, dstX1); 681 } 682 else { 683 dstX0 = MIN2(dstX0, dstX1); 684 } 685 686 if (ctx->Pixel.ZoomY < 0.0F) { 687 dstY0 = MAX2(dstY0, dstY1); 688 } 689 else { 690 dstY0 = MIN2(dstY0, dstY1); 691 } 692 693 if (mask & GL_COLOR_BUFFER_BIT) { 694 ctx->Driver.CopyPixels(ctx, srcX0, srcY0, width, height, 695 dstX0, dstY0, GL_COLOR); 696 } 697 if (mask & GL_DEPTH_BUFFER_BIT) { 698 ctx->Driver.CopyPixels(ctx, srcX0, srcY0, width, height, 699 dstX0, dstY0, GL_DEPTH); 700 } 701 if (mask & GL_STENCIL_BUFFER_BIT) { 702 ctx->Driver.CopyPixels(ctx, srcX0, srcY0, width, height, 703 dstX0, dstY0, GL_STENCIL); 704 } 705 706 ctx->Pixel.ZoomX = xZoomSave; 707 ctx->Pixel.ZoomY = yZoomSave; 708} 709 710 711/** 712 * Do one-time context initializations related to GL_EXT_framebuffer_object. 713 * Hook in device driver functions. 714 */ 715void 716intel_fbo_init(struct intel_context *intel) 717{ 718 intel->ctx.Driver.NewFramebuffer = intel_new_framebuffer; 719 intel->ctx.Driver.NewRenderbuffer = intel_new_renderbuffer; 720 intel->ctx.Driver.BindFramebuffer = intel_bind_framebuffer; 721 intel->ctx.Driver.FramebufferRenderbuffer = intel_framebuffer_renderbuffer; 722 intel->ctx.Driver.RenderTexture = intel_render_texture; 723 intel->ctx.Driver.FinishRenderTexture = intel_finish_render_texture; 724 intel->ctx.Driver.ResizeBuffers = intel_resize_buffers; 725 intel->ctx.Driver.ValidateFramebuffer = intel_validate_framebuffer; 726 intel->ctx.Driver.BlitFramebuffer = intel_blit_framebuffer; 727} 728