2 // Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
7 // Framebuffer.cpp: Implements the gl::Framebuffer class. Implements GL framebuffer
8 // objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105.
10 #include "libGLESv2/Framebuffer.h"
11 #include "libGLESv2/main.h"
12 #include "libGLESv2/formatutils.h"
13 #include "libGLESv2/Texture.h"
14 #include "libGLESv2/Context.h"
15 #include "libGLESv2/Renderbuffer.h"
16 #include "libGLESv2/FramebufferAttachment.h"
17 #include "libGLESv2/renderer/Renderer.h"
18 #include "libGLESv2/renderer/RenderTarget.h"
19 #include "libGLESv2/renderer/Workarounds.h"
20 #include "libGLESv2/renderer/d3d/TextureD3D.h"
22 #include "common/utilities.h"
26 gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget **outRT)
28 if (attachment->isTexture())
30 gl::Texture *texture = attachment->getTexture();
32 TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
33 const gl::ImageIndex *index = attachment->getTextureImageIndex();
35 return textureD3D->getRenderTarget(*index, outRT);
39 gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
42 // TODO: cast to RenderbufferD3D
43 *outRT = renderbuffer->getStorage()->getRenderTarget();
44 return gl::Error(GL_NO_ERROR);
48 // Note: RenderTarget serials should ideally be in the RenderTargets themselves.
49 unsigned int GetAttachmentSerial(gl::FramebufferAttachment *attachment)
51 if (attachment->isTexture())
53 gl::Texture *texture = attachment->getTexture();
55 TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
56 const gl::ImageIndex *index = attachment->getTextureImageIndex();
58 return textureD3D->getRenderTargetSerial(*index);
61 gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
64 // TODO: cast to RenderbufferD3D
65 return renderbuffer->getStorage()->getSerial();
73 Framebuffer::Framebuffer(rx::Renderer *renderer, GLuint id)
74 : mRenderer(renderer),
76 mReadBufferState(GL_COLOR_ATTACHMENT0_EXT),
80 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
82 mColorbuffers[colorAttachment] = NULL;
83 mDrawBufferStates[colorAttachment] = GL_NONE;
85 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
88 Framebuffer::~Framebuffer()
90 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
92 SafeDelete(mColorbuffers[colorAttachment]);
94 SafeDelete(mDepthbuffer);
95 SafeDelete(mStencilbuffer);
98 FramebufferAttachment *Framebuffer::createAttachment(GLenum binding, GLenum type, GLuint handle, GLint level, GLint layer) const
105 gl::Context *context = gl::getContext();
112 case GL_RENDERBUFFER:
113 return new RenderbufferAttachment(binding, context->getRenderbuffer(handle));
117 Texture *texture = context->getTexture(handle);
118 if (texture && texture->getTarget() == GL_TEXTURE_2D)
120 return new TextureAttachment(binding, texture, ImageIndex::Make2D(level));
128 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
129 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
130 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
131 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
132 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
133 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
135 Texture *texture = context->getTexture(handle);
136 if (texture && texture->getTarget() == GL_TEXTURE_CUBE_MAP)
138 return new TextureAttachment(binding, texture, ImageIndex::MakeCube(type, level));
148 Texture *texture = context->getTexture(handle);
149 if (texture && texture->getTarget() == GL_TEXTURE_3D)
151 return new TextureAttachment(binding, texture, ImageIndex::Make3D(level, layer));
159 case GL_TEXTURE_2D_ARRAY:
161 Texture *texture = context->getTexture(handle);
162 if (texture && texture->getTarget() == GL_TEXTURE_2D_ARRAY)
164 return new TextureAttachment(binding, texture, ImageIndex::Make2DArray(level, layer));
178 void Framebuffer::setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer, GLint level, GLint layer)
180 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
181 SafeDelete(mColorbuffers[colorAttachment]);
182 GLenum binding = colorAttachment + GL_COLOR_ATTACHMENT0;
183 mColorbuffers[colorAttachment] = createAttachment(binding, type, colorbuffer, level, layer);
186 void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level, GLint layer)
188 SafeDelete(mDepthbuffer);
189 mDepthbuffer = createAttachment(GL_DEPTH_ATTACHMENT, type, depthbuffer, level, layer);
192 void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level, GLint layer)
194 SafeDelete(mStencilbuffer);
195 mStencilbuffer = createAttachment(GL_STENCIL_ATTACHMENT, type, stencilbuffer, level, layer);
198 void Framebuffer::setDepthStencilBuffer(GLenum type, GLuint depthStencilBuffer, GLint level, GLint layer)
200 FramebufferAttachment *attachment = createAttachment(GL_DEPTH_STENCIL_ATTACHMENT, type, depthStencilBuffer, level, layer);
202 SafeDelete(mDepthbuffer);
203 SafeDelete(mStencilbuffer);
205 // ensure this is a legitimate depth+stencil format
206 if (attachment && attachment->getDepthSize() > 0 && attachment->getStencilSize() > 0)
208 mDepthbuffer = attachment;
210 // Make a new attachment object to ensure we do not double-delete
211 // See angle issue 686
212 mStencilbuffer = createAttachment(GL_DEPTH_STENCIL_ATTACHMENT, type, depthStencilBuffer, level, layer);
216 void Framebuffer::detachTexture(GLuint textureId)
218 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
220 FramebufferAttachment *attachment = mColorbuffers[colorAttachment];
222 if (attachment && attachment->isTextureWithId(textureId))
224 SafeDelete(mColorbuffers[colorAttachment]);
228 if (mDepthbuffer && mDepthbuffer->isTextureWithId(textureId))
230 SafeDelete(mDepthbuffer);
233 if (mStencilbuffer && mStencilbuffer->isTextureWithId(textureId))
235 SafeDelete(mStencilbuffer);
239 void Framebuffer::detachRenderbuffer(GLuint renderbufferId)
241 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
243 FramebufferAttachment *attachment = mColorbuffers[colorAttachment];
245 if (attachment && attachment->isRenderbufferWithId(renderbufferId))
247 SafeDelete(mColorbuffers[colorAttachment]);
251 if (mDepthbuffer && mDepthbuffer->isRenderbufferWithId(renderbufferId))
253 SafeDelete(mDepthbuffer);
256 if (mStencilbuffer && mStencilbuffer->isRenderbufferWithId(renderbufferId))
258 SafeDelete(mStencilbuffer);
262 FramebufferAttachment *Framebuffer::getColorbuffer(unsigned int colorAttachment) const
264 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
265 return mColorbuffers[colorAttachment];
268 FramebufferAttachment *Framebuffer::getDepthbuffer() const
273 FramebufferAttachment *Framebuffer::getStencilbuffer() const
275 return mStencilbuffer;
278 FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
280 return (hasValidDepthStencil() ? mDepthbuffer : NULL);
283 FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
285 FramebufferAttachment *depthstencilbuffer = mDepthbuffer;
287 if (!depthstencilbuffer)
289 depthstencilbuffer = mStencilbuffer;
292 return depthstencilbuffer;
295 FramebufferAttachment *Framebuffer::getReadColorbuffer() const
297 // Will require more logic if glReadBuffers is supported
298 return mColorbuffers[0];
301 GLenum Framebuffer::getReadColorbufferType() const
303 // Will require more logic if glReadBuffers is supported
304 return (mColorbuffers[0] ? mColorbuffers[0]->type() : GL_NONE);
307 FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
309 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
311 if (mColorbuffers[colorAttachment])
313 return mColorbuffers[colorAttachment];
320 FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const
322 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
324 return getColorbuffer(attachment - GL_COLOR_ATTACHMENT0);
330 case GL_DEPTH_ATTACHMENT:
331 return getDepthbuffer();
332 case GL_STENCIL_ATTACHMENT:
333 return getStencilbuffer();
334 case GL_DEPTH_STENCIL_ATTACHMENT:
335 return getDepthStencilBuffer();
343 GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const
345 return mDrawBufferStates[colorAttachment];
348 void Framebuffer::setDrawBufferState(unsigned int colorAttachment, GLenum drawBuffer)
350 mDrawBufferStates[colorAttachment] = drawBuffer;
353 bool Framebuffer::isEnabledColorAttachment(unsigned int colorAttachment) const
355 return (mColorbuffers[colorAttachment] && mDrawBufferStates[colorAttachment] != GL_NONE);
358 bool Framebuffer::hasEnabledColorAttachment() const
360 for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
362 if (isEnabledColorAttachment(colorAttachment))
371 bool Framebuffer::hasStencil() const
373 return (mStencilbuffer && mStencilbuffer->getStencilSize() > 0);
376 bool Framebuffer::usingExtendedDrawBuffers() const
378 for (unsigned int colorAttachment = 1; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
380 if (isEnabledColorAttachment(colorAttachment))
389 GLenum Framebuffer::completeness() const
393 unsigned int colorbufferSize = 0;
395 bool missingAttachment = true;
396 GLuint clientVersion = mRenderer->getCurrentClientVersion();
398 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
400 const FramebufferAttachment *colorbuffer = mColorbuffers[colorAttachment];
404 if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
406 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
409 GLenum internalformat = colorbuffer->getInternalFormat();
410 // TODO(geofflang): use context's texture caps
411 const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
412 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
413 if (colorbuffer->isTexture())
415 if (!formatCaps.renderable)
417 return GL_FRAMEBUFFER_UNSUPPORTED;
420 if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
422 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
427 if (!formatCaps.renderable || formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
429 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
433 if (!missingAttachment)
435 // all color attachments must have the same width and height
436 if (colorbuffer->getWidth() != width || colorbuffer->getHeight() != height)
438 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
441 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
442 // all color attachments have the same number of samples for the FBO to be complete.
443 if (colorbuffer->getSamples() != samples)
445 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
448 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
449 // in GLES 3.0, there is no such restriction
450 if (clientVersion < 3)
452 if (formatInfo.pixelBytes != colorbufferSize)
454 return GL_FRAMEBUFFER_UNSUPPORTED;
458 // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness
459 for (unsigned int previousColorAttachment = 0; previousColorAttachment < colorAttachment; previousColorAttachment++)
461 const FramebufferAttachment *previousAttachment = mColorbuffers[previousColorAttachment];
463 if (previousAttachment &&
464 (colorbuffer->id() == previousAttachment->id() &&
465 colorbuffer->type() == previousAttachment->type()))
467 return GL_FRAMEBUFFER_UNSUPPORTED;
473 width = colorbuffer->getWidth();
474 height = colorbuffer->getHeight();
475 samples = colorbuffer->getSamples();
476 colorbufferSize = formatInfo.pixelBytes;
477 missingAttachment = false;
484 if (mDepthbuffer->getWidth() == 0 || mDepthbuffer->getHeight() == 0)
486 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
489 GLenum internalformat = mDepthbuffer->getInternalFormat();
490 // TODO(geofflang): use context's texture caps
491 const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
492 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
493 if (mDepthbuffer->isTexture())
495 // depth texture attachments require OES/ANGLE_depth_texture
496 // TODO(geofflang): use context's extensions
497 if (!mRenderer->getRendererExtensions().depthTextures)
499 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
502 if (!formatCaps.renderable)
504 return GL_FRAMEBUFFER_UNSUPPORTED;
507 if (formatInfo.depthBits == 0)
509 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
514 if (!formatCaps.renderable || formatInfo.depthBits == 0)
516 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
520 if (missingAttachment)
522 width = mDepthbuffer->getWidth();
523 height = mDepthbuffer->getHeight();
524 samples = mDepthbuffer->getSamples();
525 missingAttachment = false;
527 else if (width != mDepthbuffer->getWidth() || height != mDepthbuffer->getHeight())
529 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
531 else if (samples != mDepthbuffer->getSamples())
533 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
539 if (mStencilbuffer->getWidth() == 0 || mStencilbuffer->getHeight() == 0)
541 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
544 GLenum internalformat = mStencilbuffer->getInternalFormat();
545 // TODO(geofflang): use context's texture caps
546 const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
547 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
548 if (mStencilbuffer->isTexture())
550 // texture stencil attachments come along as part
551 // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
552 // TODO(geofflang): use context's extensions
553 if (!mRenderer->getRendererExtensions().depthTextures)
555 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
558 if (!formatCaps.renderable)
560 return GL_FRAMEBUFFER_UNSUPPORTED;
563 if (formatInfo.stencilBits == 0)
565 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
570 if (!formatCaps.renderable || formatInfo.stencilBits == 0)
572 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
576 if (missingAttachment)
578 width = mStencilbuffer->getWidth();
579 height = mStencilbuffer->getHeight();
580 samples = mStencilbuffer->getSamples();
581 missingAttachment = false;
583 else if (width != mStencilbuffer->getWidth() || height != mStencilbuffer->getHeight())
585 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
587 else if (samples != mStencilbuffer->getSamples())
589 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
593 // if we have both a depth and stencil buffer, they must refer to the same object
594 // since we only support packed_depth_stencil and not separate depth and stencil
595 if (mDepthbuffer && mStencilbuffer && !hasValidDepthStencil())
597 return GL_FRAMEBUFFER_UNSUPPORTED;
600 // we need to have at least one attachment to be complete
601 if (missingAttachment)
603 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
606 return GL_FRAMEBUFFER_COMPLETE;
609 Error Framebuffer::invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments)
611 GLuint maxDimension = caps.maxRenderbufferSize;
612 return invalidateSub(numAttachments, attachments, 0, 0, maxDimension, maxDimension);
615 Error Framebuffer::invalidateSub(GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height)
617 ASSERT(completeness() == GL_FRAMEBUFFER_COMPLETE);
618 for (GLsizei attachIndex = 0; attachIndex < numAttachments; ++attachIndex)
620 GLenum attachmentTarget = attachments[attachIndex];
622 FramebufferAttachment *attachment = (attachmentTarget == GL_DEPTH_STENCIL_ATTACHMENT) ? getDepthOrStencilbuffer()
623 : getAttachment(attachmentTarget);
627 rx::RenderTarget *renderTarget = NULL;
628 Error error = rx::GetAttachmentRenderTarget(attachment, &renderTarget);
634 renderTarget->invalidate(x, y, width, height);
638 return Error(GL_NO_ERROR);
641 DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
642 : Framebuffer(renderer, 0)
644 Renderbuffer *colorRenderbuffer = new Renderbuffer(0, colorbuffer);
645 mColorbuffers[0] = new RenderbufferAttachment(GL_BACK, colorRenderbuffer);
647 GLenum depthStencilActualFormat = depthStencil->getActualFormat();
648 const gl::InternalFormat &depthStencilFormatInfo = GetInternalFormatInfo(depthStencilActualFormat);
650 if (depthStencilFormatInfo.depthBits != 0 || depthStencilFormatInfo.stencilBits != 0)
652 Renderbuffer *depthStencilBuffer = new Renderbuffer(0, depthStencil);
654 // Make a new attachment objects to ensure we do not double-delete
655 // See angle issue 686
656 mDepthbuffer = (depthStencilFormatInfo.depthBits != 0 ? new RenderbufferAttachment(GL_DEPTH_ATTACHMENT, depthStencilBuffer) : NULL);
657 mStencilbuffer = (depthStencilFormatInfo.stencilBits != 0 ? new RenderbufferAttachment(GL_STENCIL_ATTACHMENT, depthStencilBuffer) : NULL);
661 // This method transfers ownership, so delete the unused storage if we don't keep it.
662 SafeDelete(depthStencil);
665 mDrawBufferStates[0] = GL_BACK;
666 mReadBufferState = GL_BACK;
669 int Framebuffer::getSamples() const
671 if (completeness() == GL_FRAMEBUFFER_COMPLETE)
673 // for a complete framebuffer, all attachments must have the same sample count
674 // in this case return the first nonzero sample size
675 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
677 if (mColorbuffers[colorAttachment])
679 return mColorbuffers[colorAttachment]->getSamples();
687 bool Framebuffer::hasValidDepthStencil() const
689 // A valid depth-stencil attachment has the same resource bound to both the
690 // depth and stencil attachment points.
691 return (mDepthbuffer && mStencilbuffer &&
692 mDepthbuffer->type() == mStencilbuffer->type() &&
693 mDepthbuffer->id() == mStencilbuffer->id());
696 ColorbufferInfo Framebuffer::getColorbuffersForRender() const
698 ColorbufferInfo colorbuffersForRender;
700 for (size_t colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; ++colorAttachment)
702 GLenum drawBufferState = mDrawBufferStates[colorAttachment];
703 FramebufferAttachment *colorbuffer = mColorbuffers[colorAttachment];
705 if (colorbuffer != NULL && drawBufferState != GL_NONE)
707 ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + colorAttachment));
708 colorbuffersForRender.push_back(colorbuffer);
710 else if (!mRenderer->getWorkarounds().mrtPerfWorkaround)
712 colorbuffersForRender.push_back(NULL);
716 return colorbuffersForRender;
719 GLenum DefaultFramebuffer::completeness() const
721 // The default framebuffer *must* always be complete, though it may not be
722 // subject to the same rules as application FBOs. ie, it could have 0x0 size.
723 return GL_FRAMEBUFFER_COMPLETE;
726 FramebufferAttachment *DefaultFramebuffer::getAttachment(GLenum attachment) const
732 return getColorbuffer(0);
734 return getDepthbuffer();
736 return getStencilbuffer();
737 case GL_DEPTH_STENCIL:
738 return getDepthStencilBuffer();