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 "libGLESv2/utilities.h" 15 #include "libGLESv2/Texture.h" 16 #include "libGLESv2/Context.h" 17 #include "libGLESv2/renderer/Renderer.h" 18 #include "libGLESv2/Renderbuffer.h" 19 20 namespace gl 21 { 22 23 Framebuffer::Framebuffer(rx::Renderer *renderer) 24 : mRenderer(renderer) 25 { 26 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) 27 { 28 mColorbufferTypes[colorAttachment] = GL_NONE; 29 mDrawBufferStates[colorAttachment] = GL_NONE; 30 } 31 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT; 32 mReadBufferState = GL_COLOR_ATTACHMENT0_EXT; 33 34 mDepthbufferType = GL_NONE; 35 mStencilbufferType = GL_NONE; 36 } 37 38 Framebuffer::~Framebuffer() 39 { 40 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) 41 { 42 mColorbufferPointers[colorAttachment].set(NULL); 43 } 44 mDepthbufferPointer.set(NULL); 45 mStencilbufferPointer.set(NULL); 46 } 47 48 Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const 49 { 50 gl::Context *context = gl::getContext(); 51 Renderbuffer *buffer = NULL; 52 53 if (type == GL_NONE) 54 { 55 buffer = NULL; 56 } 57 else if (type == GL_RENDERBUFFER) 58 { 59 buffer = context->getRenderbuffer(handle); 60 } 61 else if (IsInternalTextureTarget(type)) 62 { 63 buffer = context->getTexture(handle)->getRenderbuffer(type); 64 } 65 else 66 { 67 UNREACHABLE(); 68 } 69 70 return buffer; 71 } 72 73 void Framebuffer::setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer) 74 { 75 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); 76 mColorbufferTypes[colorAttachment] = (colorbuffer != 0) ? type : GL_NONE; 77 mColorbufferPointers[colorAttachment].set(lookupRenderbuffer(type, colorbuffer)); 78 } 79 80 void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer) 81 { 82 mDepthbufferType = (depthbuffer != 0) ? type : GL_NONE; 83 mDepthbufferPointer.set(lookupRenderbuffer(type, depthbuffer)); 84 } 85 86 void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer) 87 { 88 mStencilbufferType = (stencilbuffer != 0) ? type : GL_NONE; 89 mStencilbufferPointer.set(lookupRenderbuffer(type, stencilbuffer)); 90 } 91 92 void Framebuffer::detachTexture(GLuint texture) 93 { 94 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) 95 { 96 if (mColorbufferPointers[colorAttachment].id() == texture && IsInternalTextureTarget(mColorbufferTypes[colorAttachment])) 97 { 98 mColorbufferTypes[colorAttachment] = GL_NONE; 99 mColorbufferPointers[colorAttachment].set(NULL); 100 } 101 } 102 103 if (mDepthbufferPointer.id() == texture && IsInternalTextureTarget(mDepthbufferType)) 104 { 105 mDepthbufferType = GL_NONE; 106 mDepthbufferPointer.set(NULL); 107 } 108 109 if (mStencilbufferPointer.id() == texture && IsInternalTextureTarget(mStencilbufferType)) 110 { 111 mStencilbufferType = GL_NONE; 112 mStencilbufferPointer.set(NULL); 113 } 114 } 115 116 void Framebuffer::detachRenderbuffer(GLuint renderbuffer) 117 { 118 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) 119 { 120 if (mColorbufferPointers[colorAttachment].id() == renderbuffer && mColorbufferTypes[colorAttachment] == GL_RENDERBUFFER) 121 { 122 mColorbufferTypes[colorAttachment] = GL_NONE; 123 mColorbufferPointers[colorAttachment].set(NULL); 124 } 125 } 126 127 if (mDepthbufferPointer.id() == renderbuffer && mDepthbufferType == GL_RENDERBUFFER) 128 { 129 mDepthbufferType = GL_NONE; 130 mDepthbufferPointer.set(NULL); 131 } 132 133 if (mStencilbufferPointer.id() == renderbuffer && mStencilbufferType == GL_RENDERBUFFER) 134 { 135 mStencilbufferType = GL_NONE; 136 mStencilbufferPointer.set(NULL); 137 } 138 } 139 140 unsigned int Framebuffer::getRenderTargetSerial(unsigned int colorAttachment) const 141 { 142 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); 143 144 Renderbuffer *colorbuffer = mColorbufferPointers[colorAttachment].get(); 145 146 if (colorbuffer) 147 { 148 return colorbuffer->getSerial(); 149 } 150 151 return 0; 152 } 153 154 unsigned int Framebuffer::getDepthbufferSerial() const 155 { 156 Renderbuffer *depthbuffer = mDepthbufferPointer.get(); 157 158 if (depthbuffer) 159 { 160 return depthbuffer->getSerial(); 161 } 162 163 return 0; 164 } 165 166 unsigned int Framebuffer::getStencilbufferSerial() const 167 { 168 Renderbuffer *stencilbuffer = mStencilbufferPointer.get(); 169 170 if (stencilbuffer) 171 { 172 return stencilbuffer->getSerial(); 173 } 174 175 return 0; 176 } 177 178 Renderbuffer *Framebuffer::getColorbuffer(unsigned int colorAttachment) const 179 { 180 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); 181 return mColorbufferPointers[colorAttachment].get(); 182 } 183 184 Renderbuffer *Framebuffer::getDepthbuffer() const 185 { 186 return mDepthbufferPointer.get(); 187 } 188 189 Renderbuffer *Framebuffer::getStencilbuffer() const 190 { 191 return mStencilbufferPointer.get(); 192 } 193 194 Renderbuffer *Framebuffer::getDepthOrStencilbuffer() const 195 { 196 Renderbuffer *depthstencilbuffer = mDepthbufferPointer.get(); 197 198 if (!depthstencilbuffer) 199 { 200 depthstencilbuffer = mStencilbufferPointer.get(); 201 } 202 203 return depthstencilbuffer; 204 } 205 206 Renderbuffer *Framebuffer::getReadColorbuffer() const 207 { 208 // Will require more logic if glReadBuffers is supported 209 return mColorbufferPointers[0].get(); 210 } 211 212 GLenum Framebuffer::getReadColorbufferType() const 213 { 214 // Will require more logic if glReadBuffers is supported 215 return mColorbufferTypes[0]; 216 } 217 218 Renderbuffer *Framebuffer::getFirstColorbuffer() const 219 { 220 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) 221 { 222 if (mColorbufferTypes[colorAttachment] != GL_NONE) 223 { 224 return mColorbufferPointers[colorAttachment].get(); 225 } 226 } 227 228 return NULL; 229 } 230 231 GLenum Framebuffer::getColorbufferType(unsigned int colorAttachment) const 232 { 233 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); 234 return mColorbufferTypes[colorAttachment]; 235 } 236 237 GLenum Framebuffer::getDepthbufferType() const 238 { 239 return mDepthbufferType; 240 } 241 242 GLenum Framebuffer::getStencilbufferType() const 243 { 244 return mStencilbufferType; 245 } 246 247 GLuint Framebuffer::getColorbufferHandle(unsigned int colorAttachment) const 248 { 249 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS); 250 return mColorbufferPointers[colorAttachment].id(); 251 } 252 253 GLuint Framebuffer::getDepthbufferHandle() const 254 { 255 return mDepthbufferPointer.id(); 256 } 257 258 GLuint Framebuffer::getStencilbufferHandle() const 259 { 260 return mStencilbufferPointer.id(); 261 } 262 263 GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const 264 { 265 return mDrawBufferStates[colorAttachment]; 266 } 267 268 void Framebuffer::setDrawBufferState(unsigned int colorAttachment, GLenum drawBuffer) 269 { 270 mDrawBufferStates[colorAttachment] = drawBuffer; 271 } 272 273 bool Framebuffer::isEnabledColorAttachment(unsigned int colorAttachment) const 274 { 275 return (mColorbufferTypes[colorAttachment] != GL_NONE && mDrawBufferStates[colorAttachment] != GL_NONE); 276 } 277 278 bool Framebuffer::hasEnabledColorAttachment() const 279 { 280 for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) 281 { 282 if (isEnabledColorAttachment(colorAttachment)) 283 { 284 return true; 285 } 286 } 287 288 return false; 289 } 290 291 bool Framebuffer::hasStencil() const 292 { 293 if (mStencilbufferType != GL_NONE) 294 { 295 const Renderbuffer *stencilbufferObject = getStencilbuffer(); 296 297 if (stencilbufferObject) 298 { 299 return stencilbufferObject->getStencilSize() > 0; 300 } 301 } 302 303 return false; 304 } 305 306 bool Framebuffer::usingExtendedDrawBuffers() const 307 { 308 for (unsigned int colorAttachment = 1; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) 309 { 310 if (isEnabledColorAttachment(colorAttachment)) 311 { 312 return true; 313 } 314 } 315 316 return false; 317 } 318 319 GLenum Framebuffer::completeness() const 320 { 321 int width = 0; 322 int height = 0; 323 int colorbufferSize = 0; 324 int samples = -1; 325 bool missingAttachment = true; 326 327 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) 328 { 329 if (mColorbufferTypes[colorAttachment] != GL_NONE) 330 { 331 const Renderbuffer *colorbuffer = getColorbuffer(colorAttachment); 332 333 if (!colorbuffer) 334 { 335 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 336 } 337 338 if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0) 339 { 340 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 341 } 342 343 if (mColorbufferTypes[colorAttachment] == GL_RENDERBUFFER) 344 { 345 if (!gl::IsColorRenderable(colorbuffer->getInternalFormat())) 346 { 347 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 348 } 349 } 350 else if (IsInternalTextureTarget(mColorbufferTypes[colorAttachment])) 351 { 352 GLint internalformat = colorbuffer->getInternalFormat(); 353 GLenum format = gl::ExtractFormat(internalformat); 354 355 if (IsCompressed(format) || 356 format == GL_ALPHA || 357 format == GL_LUMINANCE || 358 format == GL_LUMINANCE_ALPHA) 359 { 360 return GL_FRAMEBUFFER_UNSUPPORTED; 361 } 362 363 bool filtering, renderable; 364 365 if ((gl::IsFloat32Format(internalformat) && !mRenderer->getFloat32TextureSupport(&filtering, &renderable)) || 366 (gl::IsFloat16Format(internalformat) && !mRenderer->getFloat16TextureSupport(&filtering, &renderable))) 367 { 368 return GL_FRAMEBUFFER_UNSUPPORTED; 369 } 370 371 if (gl::IsDepthTexture(internalformat) || gl::IsStencilTexture(internalformat)) 372 { 373 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 374 } 375 } 376 else 377 { 378 UNREACHABLE(); 379 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 380 } 381 382 if (!missingAttachment) 383 { 384 // all color attachments must have the same width and height 385 if (colorbuffer->getWidth() != width || colorbuffer->getHeight() != height) 386 { 387 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; 388 } 389 390 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that 391 // all color attachments have the same number of samples for the FBO to be complete. 392 if (colorbuffer->getSamples() != samples) 393 { 394 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT; 395 } 396 397 // all color attachments attachments must have the same number of bitplanes 398 if (gl::ComputePixelSize(colorbuffer->getInternalFormat()) != colorbufferSize) 399 { 400 return GL_FRAMEBUFFER_UNSUPPORTED; 401 } 402 403 // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness 404 for (unsigned int previousColorAttachment = 0; previousColorAttachment < colorAttachment; previousColorAttachment++) 405 { 406 if (mColorbufferPointers[colorAttachment].get() == mColorbufferPointers[previousColorAttachment].get()) 407 { 408 return GL_FRAMEBUFFER_UNSUPPORTED; 409 } 410 } 411 } 412 else 413 { 414 width = colorbuffer->getWidth(); 415 height = colorbuffer->getHeight(); 416 samples = colorbuffer->getSamples(); 417 colorbufferSize = gl::ComputePixelSize(colorbuffer->getInternalFormat()); 418 missingAttachment = false; 419 } 420 } 421 } 422 423 const Renderbuffer *depthbuffer = NULL; 424 const Renderbuffer *stencilbuffer = NULL; 425 426 if (mDepthbufferType != GL_NONE) 427 { 428 depthbuffer = getDepthbuffer(); 429 430 if (!depthbuffer) 431 { 432 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 433 } 434 435 if (depthbuffer->getWidth() == 0 || depthbuffer->getHeight() == 0) 436 { 437 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 438 } 439 440 if (mDepthbufferType == GL_RENDERBUFFER) 441 { 442 if (!gl::IsDepthRenderable(depthbuffer->getInternalFormat())) 443 { 444 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 445 } 446 } 447 else if (IsInternalTextureTarget(mDepthbufferType)) 448 { 449 GLint internalformat = depthbuffer->getInternalFormat(); 450 451 // depth texture attachments require OES/ANGLE_depth_texture 452 if (!mRenderer->getDepthTextureSupport()) 453 { 454 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 455 } 456 457 if (!gl::IsDepthTexture(internalformat)) 458 { 459 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 460 } 461 } 462 else 463 { 464 UNREACHABLE(); 465 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 466 } 467 468 if (missingAttachment) 469 { 470 width = depthbuffer->getWidth(); 471 height = depthbuffer->getHeight(); 472 samples = depthbuffer->getSamples(); 473 missingAttachment = false; 474 } 475 else if (width != depthbuffer->getWidth() || height != depthbuffer->getHeight()) 476 { 477 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; 478 } 479 else if (samples != depthbuffer->getSamples()) 480 { 481 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE; 482 } 483 } 484 485 if (mStencilbufferType != GL_NONE) 486 { 487 stencilbuffer = getStencilbuffer(); 488 489 if (!stencilbuffer) 490 { 491 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 492 } 493 494 if (stencilbuffer->getWidth() == 0 || stencilbuffer->getHeight() == 0) 495 { 496 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 497 } 498 499 if (mStencilbufferType == GL_RENDERBUFFER) 500 { 501 if (!gl::IsStencilRenderable(stencilbuffer->getInternalFormat())) 502 { 503 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 504 } 505 } 506 else if (IsInternalTextureTarget(mStencilbufferType)) 507 { 508 GLint internalformat = stencilbuffer->getInternalFormat(); 509 510 // texture stencil attachments come along as part 511 // of OES_packed_depth_stencil + OES/ANGLE_depth_texture 512 if (!mRenderer->getDepthTextureSupport()) 513 { 514 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 515 } 516 517 if (!gl::IsStencilTexture(internalformat)) 518 { 519 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 520 } 521 } 522 else 523 { 524 UNREACHABLE(); 525 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT; 526 } 527 528 if (missingAttachment) 529 { 530 width = stencilbuffer->getWidth(); 531 height = stencilbuffer->getHeight(); 532 samples = stencilbuffer->getSamples(); 533 missingAttachment = false; 534 } 535 else if (width != stencilbuffer->getWidth() || height != stencilbuffer->getHeight()) 536 { 537 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS; 538 } 539 else if (samples != stencilbuffer->getSamples()) 540 { 541 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE; 542 } 543 } 544 545 // if we have both a depth and stencil buffer, they must refer to the same object 546 // since we only support packed_depth_stencil and not separate depth and stencil 547 if (depthbuffer && stencilbuffer && (depthbuffer != stencilbuffer)) 548 { 549 return GL_FRAMEBUFFER_UNSUPPORTED; 550 } 551 552 // we need to have at least one attachment to be complete 553 if (missingAttachment) 554 { 555 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT; 556 } 557 558 return GL_FRAMEBUFFER_COMPLETE; 559 } 560 561 DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil) 562 : Framebuffer(renderer) 563 { 564 mColorbufferPointers[0].set(new Renderbuffer(mRenderer, 0, colorbuffer)); 565 566 Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(mRenderer, 0, depthStencil); 567 mDepthbufferPointer.set(depthStencilRenderbuffer); 568 mStencilbufferPointer.set(depthStencilRenderbuffer); 569 570 mColorbufferTypes[0] = GL_RENDERBUFFER; 571 mDepthbufferType = (depthStencilRenderbuffer->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE; 572 mStencilbufferType = (depthStencilRenderbuffer->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE; 573 574 mDrawBufferStates[0] = GL_BACK; 575 mReadBufferState = GL_BACK; 576 } 577 578 int Framebuffer::getSamples() const 579 { 580 if (completeness() == GL_FRAMEBUFFER_COMPLETE) 581 { 582 // for a complete framebuffer, all attachments must have the same sample count 583 // in this case return the first nonzero sample size 584 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++) 585 { 586 if (mColorbufferTypes[colorAttachment] != GL_NONE) 587 { 588 return getColorbuffer(colorAttachment)->getSamples(); 589 } 590 } 591 } 592 593 return 0; 594 } 595 596 GLenum DefaultFramebuffer::completeness() const 597 { 598 // The default framebuffer *must* always be complete, though it may not be 599 // subject to the same rules as application FBOs. ie, it could have 0x0 size. 600 return GL_FRAMEBUFFER_COMPLETE; 601 } 602 603 } 604