1 #include "precompiled.h" 2 // 3 // Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style license that can be 5 // found in the LICENSE file. 6 // 7 8 // Framebuffer.cpp: Implements the gl::Framebuffer class. Implements GL framebuffer 9 // objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105. 10 11 #include "libGLESv2/Framebuffer.h" 12 13 #include "libGLESv2/main.h" 14 #include "common/utilities.h" 15 #include "libGLESv2/formatutils.h" 16 #include "libGLESv2/Texture.h" 17 #include "libGLESv2/Context.h" 18 #include "libGLESv2/renderer/Renderer.h" 19 #include "libGLESv2/Renderbuffer.h" 20 21 namespace gl 22 { 23 24 Framebuffer::Framebuffer(rx::Renderer *renderer) 25 : mRenderer(renderer) 26 { 27 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) 28 { 29 mDrawBufferStates[colorAttachment] = GL_NONE; 30 } 31 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT; 32 mReadBufferState = GL_COLOR_ATTACHMENT0_EXT; 33 } 34 35 Framebuffer::~Framebuffer() 36 { 37 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) 38 { 39 mColorbuffers[colorAttachment].set(NULL, GL_NONE, 0, 0); 40 } 41 mDepthbuffer.set(NULL, GL_NONE, 0, 0); 42 mStencilbuffer.set(NULL, GL_NONE, 0, 0); 43 } 44 45 FramebufferAttachment *Framebuffer::lookupAttachment(GLenum type, GLuint handle, GLint level, GLint layer) const 46 { 47 gl::Context *context = gl::getContext(); 48 49 switch (type) 50 { 51 case GL_NONE: 52 return NULL; 53 54 case GL_RENDERBUFFER: 55 return context->getRenderbuffer(handle); 56 57 case GL_TEXTURE_2D: 58 { 59 Texture *texture = context->getTexture(handle); 60 if (texture && texture->getTarget() == GL_TEXTURE_2D) 61 { 62 return static_cast<Texture2D*>(texture)->getAttachment(level); 63 } 64 else 65 { 66 return NULL; 67 } 68 } 69 70 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 71 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 72 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 73 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 74 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 75 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 76 { 77 Texture *texture = context->getTexture(handle); 78 if (texture && texture->getTarget() == GL_TEXTURE_CUBE_MAP) 79 { 80 return static_cast<TextureCubeMap*>(texture)->getAttachment(type, level); 81 } 82 else 83 { 84 return NULL; 85 } 86 } 87 88 case GL_TEXTURE_3D: 89 { 90 Texture *texture = context->getTexture(handle); 91 if (texture && texture->getTarget() == GL_TEXTURE_3D) 92 { 93 return static_cast<Texture3D*>(texture)->getAttachment(level, layer); 94 } 95 else 96 { 97 return NULL; 98 } 99 } 100 101 case GL_TEXTURE_2D_ARRAY: 102 { 103 Texture *texture = context->getTexture(handle); 104 if (texture && texture->getTarget() == GL_TEXTURE_2D_ARRAY) 105 { 106 return static_cast<Texture2DArray*>(texture)->getAttachment(level, layer); 107 } 108 else 109 { 110 return NULL; 111 } 112 } 113 114 default: 115 UNREACHABLE(); 116 return NULL; 117 } 118 } 119 120 void Framebuffer::setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer, GLint level, GLint layer) 121 { 122 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); 123 FramebufferAttachment *attachment = lookupAttachment(type, colorbuffer, level, layer); 124 if (attachment) 125 { 126 mColorbuffers[colorAttachment].set(attachment, type, level, layer); 127 } 128 else 129 { 130 mColorbuffers[colorAttachment].set(NULL, GL_NONE, 0, 0); 131 } 132 } 133 134 void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level, GLint layer) 135 { 136 FramebufferAttachment *attachment = lookupAttachment(type, depthbuffer, level, layer); 137 if (attachment) 138 { 139 mDepthbuffer.set(attachment, type, level, layer); 140 } 141 else 142 { 143 mDepthbuffer.set(NULL, GL_NONE, 0, 0); 144 } 145 } 146 147 void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level, GLint layer) 148 { 149 FramebufferAttachment *attachment = lookupAttachment(type, stencilbuffer, level, layer); 150 if (attachment) 151 { 152 mStencilbuffer.set(attachment, type, level, layer); 153 } 154 else 155 { 156 mStencilbuffer.set(NULL, GL_NONE, 0, 0); 157 } 158 } 159 160 void Framebuffer::setDepthStencilBuffer(GLenum type, GLuint depthStencilBuffer, GLint level, GLint layer) 161 { 162 FramebufferAttachment *attachment = lookupAttachment(type, depthStencilBuffer, level, layer); 163 if (attachment && attachment->getDepthSize() > 0 && attachment->getStencilSize() > 0) 164 { 165 mDepthbuffer.set(attachment, type, level, layer); 166 mStencilbuffer.set(attachment, type, level, layer); 167 } 168 else 169 { 170 mDepthbuffer.set(NULL, GL_NONE, 0, 0); 171 mStencilbuffer.set(NULL, GL_NONE, 0, 0); 172 } 173 } 174 175 void Framebuffer::detachTexture(GLuint texture) 176 { 177 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) 178 { 179 if (mColorbuffers[colorAttachment].id() == texture && 180 IsInternalTextureTarget(mColorbuffers[colorAttachment].type(), mRenderer->getCurrentClientVersion())) 181 { 182 mColorbuffers[colorAttachment].set(NULL, GL_NONE, 0, 0); 183 } 184 } 185 186 if (mDepthbuffer.id() == texture && IsInternalTextureTarget(mDepthbuffer.type(), mRenderer->getCurrentClientVersion())) 187 { 188 mDepthbuffer.set(NULL, GL_NONE, 0, 0); 189 } 190 191 if (mStencilbuffer.id() == texture && IsInternalTextureTarget(mStencilbuffer.type(), mRenderer->getCurrentClientVersion())) 192 { 193 mStencilbuffer.set(NULL, GL_NONE, 0, 0); 194 } 195 } 196 197 void Framebuffer::detachRenderbuffer(GLuint renderbuffer) 198 { 199 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) 200 { 201 if (mColorbuffers[colorAttachment].id() == renderbuffer && mColorbuffers[colorAttachment].type() == GL_RENDERBUFFER) 202 { 203 mColorbuffers[colorAttachment].set(NULL, GL_NONE, 0, 0); 204 } 205 } 206 207 if (mDepthbuffer.id() == renderbuffer && mDepthbuffer.type() == GL_RENDERBUFFER) 208 { 209 mDepthbuffer.set(NULL, GL_NONE, 0, 0); 210 } 211 212 if (mStencilbuffer.id() == renderbuffer && mStencilbuffer.type() == GL_RENDERBUFFER) 213 { 214 mStencilbuffer.set(NULL, GL_NONE, 0, 0); 215 } 216 } 217 218 unsigned int Framebuffer::getRenderTargetSerial(unsigned int colorAttachment) const 219 { 220 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); 221 222 FramebufferAttachment *colorbuffer = mColorbuffers[colorAttachment].get(); 223 224 if (colorbuffer) 225 { 226 return colorbuffer->getSerial(); 227 } 228 229 return 0; 230 } 231 232 unsigned int Framebuffer::getDepthbufferSerial() const 233 { 234 FramebufferAttachment *depthbuffer = mDepthbuffer.get(); 235 236 if (depthbuffer) 237 { 238 return depthbuffer->getSerial(); 239 } 240 241 return 0; 242 } 243 244 unsigned int Framebuffer::getStencilbufferSerial() const 245 { 246 FramebufferAttachment *stencilbuffer = mStencilbuffer.get(); 247 248 if (stencilbuffer) 249 { 250 return stencilbuffer->getSerial(); 251 } 252 253 return 0; 254 } 255 256 FramebufferAttachment *Framebuffer::getColorbuffer(unsigned int colorAttachment) const 257 { 258 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); 259 return mColorbuffers[colorAttachment].get(); 260 } 261 262 FramebufferAttachment *Framebuffer::getDepthbuffer() const 263 { 264 return mDepthbuffer.get(); 265 } 266 267 FramebufferAttachment *Framebuffer::getStencilbuffer() const 268 { 269 return mStencilbuffer.get(); 270 } 271 272 FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const 273 { 274 return (mDepthbuffer.id() == mStencilbuffer.id()) ? mDepthbuffer.get() : NULL; 275 } 276 277 FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const 278 { 279 FramebufferAttachment *depthstencilbuffer = mDepthbuffer.get(); 280 281 if (!depthstencilbuffer) 282 { 283 depthstencilbuffer = mStencilbuffer.get(); 284 } 285 286 return depthstencilbuffer; 287 } 288 289 FramebufferAttachment *Framebuffer::getReadColorbuffer() const 290 { 291 // Will require more logic if glReadBuffers is supported 292 return mColorbuffers[0].get(); 293 } 294 295 GLenum Framebuffer::getReadColorbufferType() const 296 { 297 // Will require more logic if glReadBuffers is supported 298 return mColorbuffers[0].type(); 299 } 300 301 FramebufferAttachment *Framebuffer::getFirstColorbuffer() const 302 { 303 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) 304 { 305 if (mColorbuffers[colorAttachment].type() != GL_NONE) 306 { 307 return mColorbuffers[colorAttachment].get(); 308 } 309 } 310 311 return NULL; 312 } 313 314 GLenum Framebuffer::getColorbufferType(unsigned int colorAttachment) const 315 { 316 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); 317 return mColorbuffers[colorAttachment].type(); 318 } 319 320 GLenum Framebuffer::getDepthbufferType() const 321 { 322 return mDepthbuffer.type(); 323 } 324 325 GLenum Framebuffer::getStencilbufferType() const 326 { 327 return mStencilbuffer.type(); 328 } 329 330 GLenum Framebuffer::getDepthStencilbufferType() const 331 { 332 return (mDepthbuffer.id() == mStencilbuffer.id()) ? mDepthbuffer.type() : GL_NONE; 333 } 334 335 GLuint Framebuffer::getColorbufferHandle(unsigned int colorAttachment) const 336 { 337 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); 338 return mColorbuffers[colorAttachment].id(); 339 } 340 341 GLuint Framebuffer::getDepthbufferHandle() const 342 { 343 return mDepthbuffer.id(); 344 } 345 346 GLuint Framebuffer::getStencilbufferHandle() const 347 { 348 return mStencilbuffer.id(); 349 } 350 351 GLenum Framebuffer::getDepthStencilbufferHandle() const 352 { 353 return (mDepthbuffer.id() == mStencilbuffer.id()) ? mDepthbuffer.id() : 0; 354 } 355 356 GLenum Framebuffer::getColorbufferMipLevel(unsigned int colorAttachment) const 357 { 358 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); 359 return mColorbuffers[colorAttachment].mipLevel(); 360 } 361 362 GLenum Framebuffer::getDepthbufferMipLevel() const 363 { 364 return mDepthbuffer.mipLevel(); 365 } 366 367 GLenum Framebuffer::getStencilbufferMipLevel() const 368 { 369 return mStencilbuffer.mipLevel(); 370 } 371 372 GLenum Framebuffer::getDepthStencilbufferMipLevel() const 373 { 374 return (mDepthbuffer.id() == mStencilbuffer.id()) ? mDepthbuffer.mipLevel() : 0; 375 } 376 377 GLenum Framebuffer::getColorbufferLayer(unsigned int colorAttachment) const 378 { 379 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); 380 return mColorbuffers[colorAttachment].layer(); 381 } 382 383 GLenum Framebuffer::getDepthbufferLayer() const 384 { 385 return mDepthbuffer.layer(); 386 } 387 388 GLenum Framebuffer::getStencilbufferLayer() const 389 { 390 return mStencilbuffer.layer(); 391 } 392 393 GLenum Framebuffer::getDepthStencilbufferLayer() const 394 { 395 return (mDepthbuffer.id() == mStencilbuffer.id()) ? mDepthbuffer.layer() : 0; 396 } 397 398 GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const 399 { 400 return mDrawBufferStates[colorAttachment]; 401 } 402 403 void Framebuffer::setDrawBufferState(unsigned int colorAttachment, GLenum drawBuffer) 404 { 405 mDrawBufferStates[colorAttachment] = drawBuffer; 406 } 407 408 bool Framebuffer::isEnabledColorAttachment(unsigned int colorAttachment) const 409 { 410 return (mColorbuffers[colorAttachment].type() != GL_NONE && mDrawBufferStates[colorAttachment] != GL_NONE); 411 } 412 413 bool Framebuffer::hasEnabledColorAttachment() const 414 { 415 for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) 416 { 417 if (isEnabledColorAttachment(colorAttachment)) 418 { 419 return true; 420 } 421 } 422 423 return false; 424 } 425 426 bool Framebuffer::hasStencil() const 427 { 428 if (mStencilbuffer.type() != GL_NONE) 429 { 430 const FramebufferAttachment *stencilbufferObject = getStencilbuffer(); 431 432 if (stencilbufferObject) 433 { 434 return stencilbufferObject->getStencilSize() > 0; 435 } 436 } 437 438 return false; 439 } 440 441 bool Framebuffer::usingExtendedDrawBuffers() const 442 { 443 for (unsigned int colorAttachment = 1; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) 444 { 445 if (isEnabledColorAttachment(colorAttachment)) 446 { 447 return true; 448 } 449 } 450 451 return false; 452 } 453 454 GLenum Framebuffer::completeness() const 455 { 456 int width = 0; 457 int height = 0; 458 unsigned int colorbufferSize = 0; 459 int samples = -1; 460 bool missingAttachment = true; 461 GLuint clientVersion = mRenderer->getCurrentClientVersion(); 462 463 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) 464 { 465 if (mColorbuffers[colorAttachment].type() != GL_NONE) 466 { 467 const FramebufferAttachment *colorbuffer = getColorbuffer(colorAttachment); 468 469 if (!colorbuffer) 470 { 471 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 472 } 473 474 if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0) 475 { 476 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 477 } 478 479 if (mColorbuffers[colorAttachment].type() == GL_RENDERBUFFER) 480 { 481 if (!gl::IsColorRenderingSupported(colorbuffer->getInternalFormat(), mRenderer)) 482 { 483 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 484 } 485 } 486 else if (IsInternalTextureTarget(mColorbuffers[colorAttachment].type(), mRenderer->getCurrentClientVersion())) 487 { 488 GLenum internalformat = colorbuffer->getInternalFormat(); 489 490 if (!gl::IsColorRenderingSupported(internalformat, mRenderer)) 491 { 492 return GL_FRAMEBUFFER_UNSUPPORTED; 493 } 494 495 if (gl::GetDepthBits(internalformat, clientVersion) > 0 || 496 gl::GetStencilBits(internalformat, clientVersion) > 0) 497 { 498 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 499 } 500 } 501 else 502 { 503 UNREACHABLE(); 504 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 505 } 506 507 if (!missingAttachment) 508 { 509 // all color attachments must have the same width and height 510 if (colorbuffer->getWidth() != width || colorbuffer->getHeight() != height) 511 { 512 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; 513 } 514 515 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that 516 // all color attachments have the same number of samples for the FBO to be complete. 517 if (colorbuffer->getSamples() != samples) 518 { 519 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT; 520 } 521 522 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes 523 // in GLES 3.0, there is no such restriction 524 if (clientVersion < 3) 525 { 526 if (gl::GetPixelBytes(colorbuffer->getInternalFormat(), clientVersion) != colorbufferSize) 527 { 528 return GL_FRAMEBUFFER_UNSUPPORTED; 529 } 530 } 531 532 // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness 533 for (unsigned int previousColorAttachment = 0; previousColorAttachment < colorAttachment; previousColorAttachment++) 534 { 535 if (mColorbuffers[colorAttachment].get() == mColorbuffers[previousColorAttachment].get()) 536 { 537 return GL_FRAMEBUFFER_UNSUPPORTED; 538 } 539 } 540 } 541 else 542 { 543 width = colorbuffer->getWidth(); 544 height = colorbuffer->getHeight(); 545 samples = colorbuffer->getSamples(); 546 colorbufferSize = gl::GetPixelBytes(colorbuffer->getInternalFormat(), clientVersion); 547 missingAttachment = false; 548 } 549 } 550 } 551 552 const FramebufferAttachment *depthbuffer = NULL; 553 const FramebufferAttachment *stencilbuffer = NULL; 554 555 if (mDepthbuffer.type() != GL_NONE) 556 { 557 depthbuffer = getDepthbuffer(); 558 559 if (!depthbuffer) 560 { 561 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 562 } 563 564 if (depthbuffer->getWidth() == 0 || depthbuffer->getHeight() == 0) 565 { 566 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 567 } 568 569 if (mDepthbuffer.type() == GL_RENDERBUFFER) 570 { 571 if (!gl::IsDepthRenderingSupported(depthbuffer->getInternalFormat(), mRenderer)) 572 { 573 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 574 } 575 } 576 else if (IsInternalTextureTarget(mDepthbuffer.type(), mRenderer->getCurrentClientVersion())) 577 { 578 GLenum internalformat = depthbuffer->getInternalFormat(); 579 580 // depth texture attachments require OES/ANGLE_depth_texture 581 if (!mRenderer->getDepthTextureSupport()) 582 { 583 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 584 } 585 586 if (gl::GetDepthBits(internalformat, clientVersion) == 0) 587 { 588 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 589 } 590 } 591 else 592 { 593 UNREACHABLE(); 594 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 595 } 596 597 if (missingAttachment) 598 { 599 width = depthbuffer->getWidth(); 600 height = depthbuffer->getHeight(); 601 samples = depthbuffer->getSamples(); 602 missingAttachment = false; 603 } 604 else if (width != depthbuffer->getWidth() || height != depthbuffer->getHeight()) 605 { 606 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; 607 } 608 else if (samples != depthbuffer->getSamples()) 609 { 610 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE; 611 } 612 } 613 614 if (mStencilbuffer.type() != GL_NONE) 615 { 616 stencilbuffer = getStencilbuffer(); 617 618 if (!stencilbuffer) 619 { 620 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 621 } 622 623 if (stencilbuffer->getWidth() == 0 || stencilbuffer->getHeight() == 0) 624 { 625 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 626 } 627 628 if (mStencilbuffer.type() == GL_RENDERBUFFER) 629 { 630 if (!gl::IsStencilRenderingSupported(stencilbuffer->getInternalFormat(), mRenderer)) 631 { 632 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 633 } 634 } 635 else if (IsInternalTextureTarget(mStencilbuffer.type(), mRenderer->getCurrentClientVersion())) 636 { 637 GLenum internalformat = stencilbuffer->getInternalFormat(); 638 639 // texture stencil attachments come along as part 640 // of OES_packed_depth_stencil + OES/ANGLE_depth_texture 641 if (!mRenderer->getDepthTextureSupport()) 642 { 643 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 644 } 645 646 if (gl::GetStencilBits(internalformat, clientVersion) == 0) 647 { 648 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 649 } 650 } 651 else 652 { 653 UNREACHABLE(); 654 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 655 } 656 657 if (missingAttachment) 658 { 659 width = stencilbuffer->getWidth(); 660 height = stencilbuffer->getHeight(); 661 samples = stencilbuffer->getSamples(); 662 missingAttachment = false; 663 } 664 else if (width != stencilbuffer->getWidth() || height != stencilbuffer->getHeight()) 665 { 666 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; 667 } 668 else if (samples != stencilbuffer->getSamples()) 669 { 670 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE; 671 } 672 } 673 674 // if we have both a depth and stencil buffer, they must refer to the same object 675 // since we only support packed_depth_stencil and not separate depth and stencil 676 if (depthbuffer && stencilbuffer && (depthbuffer != stencilbuffer)) 677 { 678 return GL_FRAMEBUFFER_UNSUPPORTED; 679 } 680 681 // we need to have at least one attachment to be complete 682 if (missingAttachment) 683 { 684 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; 685 } 686 687 return GL_FRAMEBUFFER_COMPLETE; 688 } 689 690 DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil) 691 : Framebuffer(renderer) 692 { 693 mColorbuffers[0].set(new FramebufferAttachment(mRenderer, 0, colorbuffer), GL_RENDERBUFFER, 0, 0); 694 695 FramebufferAttachment *depthStencilRenderbuffer = new FramebufferAttachment(mRenderer, 0, depthStencil); 696 mDepthbuffer.set(depthStencilRenderbuffer, (depthStencilRenderbuffer->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE, 0, 0); 697 mStencilbuffer.set(depthStencilRenderbuffer, (depthStencilRenderbuffer->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE, 0, 0); 698 699 mDrawBufferStates[0] = GL_BACK; 700 mReadBufferState = GL_BACK; 701 } 702 703 int Framebuffer::getSamples() const 704 { 705 if (completeness() == GL_FRAMEBUFFER_COMPLETE) 706 { 707 // for a complete framebuffer, all attachments must have the same sample count 708 // in this case return the first nonzero sample size 709 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) 710 { 711 if (mColorbuffers[colorAttachment].type() != GL_NONE) 712 { 713 return getColorbuffer(colorAttachment)->getSamples(); 714 } 715 } 716 } 717 718 return 0; 719 } 720 721 GLenum DefaultFramebuffer::completeness() const 722 { 723 // The default framebuffer *must* always be complete, though it may not be 724 // subject to the same rules as application FBOs. ie, it could have 0x0 size. 725 return GL_FRAMEBUFFER_COMPLETE; 726 } 727 728 } 729