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