2 // Copyright (c) 2002-2010 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"
12 #include "libGLESv2/main.h"
13 #include "libGLESv2/Renderbuffer.h"
14 #include "libGLESv2/Texture.h"
15 #include "libGLESv2/utilities.h"
20 Framebuffer::Framebuffer()
22 mColorbufferType = GL_NONE;
23 mDepthbufferType = GL_NONE;
24 mStencilbufferType = GL_NONE;
27 Framebuffer::~Framebuffer()
29 mColorbufferPointer.set(NULL);
30 mDepthbufferPointer.set(NULL);
31 mStencilbufferPointer.set(NULL);
34 Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const
36 gl::Context *context = gl::getContext();
37 Renderbuffer *buffer = NULL;
43 else if (type == GL_RENDERBUFFER)
45 buffer = context->getRenderbuffer(handle);
47 else if (IsTextureTarget(type))
49 buffer = context->getTexture(handle)->getRenderbuffer(type);
59 void Framebuffer::setColorbuffer(GLenum type, GLuint colorbuffer)
61 mColorbufferType = type;
62 mColorbufferPointer.set(lookupRenderbuffer(type, colorbuffer));
65 void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer)
67 mDepthbufferType = type;
68 mDepthbufferPointer.set(lookupRenderbuffer(type, depthbuffer));
71 void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer)
73 mStencilbufferType = type;
74 mStencilbufferPointer.set(lookupRenderbuffer(type, stencilbuffer));
77 void Framebuffer::detachTexture(GLuint texture)
79 if (mColorbufferPointer.id() == texture && IsTextureTarget(mColorbufferType))
81 mColorbufferType = GL_NONE;
82 mColorbufferPointer.set(NULL);
85 if (mDepthbufferPointer.id() == texture && IsTextureTarget(mDepthbufferType))
87 mDepthbufferType = GL_NONE;
88 mDepthbufferPointer.set(NULL);
91 if (mStencilbufferPointer.id() == texture && IsTextureTarget(mStencilbufferType))
93 mStencilbufferType = GL_NONE;
94 mStencilbufferPointer.set(NULL);
98 void Framebuffer::detachRenderbuffer(GLuint renderbuffer)
100 if (mColorbufferPointer.id() == renderbuffer && mColorbufferType == GL_RENDERBUFFER)
102 mColorbufferType = GL_NONE;
103 mColorbufferPointer.set(NULL);
106 if (mDepthbufferPointer.id() == renderbuffer && mDepthbufferType == GL_RENDERBUFFER)
108 mDepthbufferType = GL_NONE;
109 mDepthbufferPointer.set(NULL);
112 if (mStencilbufferPointer.id() == renderbuffer && mStencilbufferType == GL_RENDERBUFFER)
114 mStencilbufferType = GL_NONE;
115 mStencilbufferPointer.set(NULL);
119 unsigned int Framebuffer::getRenderTargetSerial()
121 Renderbuffer *colorbuffer = mColorbufferPointer.get();
125 return colorbuffer->getSerial();
131 IDirect3DSurface9 *Framebuffer::getRenderTarget()
133 Renderbuffer *colorbuffer = mColorbufferPointer.get();
137 return colorbuffer->getRenderTarget();
143 IDirect3DSurface9 *Framebuffer::getDepthStencil()
145 Renderbuffer *depthstencilbuffer = mDepthbufferPointer.get();
147 if (!depthstencilbuffer)
149 depthstencilbuffer = mStencilbufferPointer.get();
152 if (depthstencilbuffer)
154 return depthstencilbuffer->getDepthStencil();
160 unsigned int Framebuffer::getDepthbufferSerial()
162 Renderbuffer *depthbuffer = mDepthbufferPointer.get();
166 return depthbuffer->getSerial();
172 unsigned int Framebuffer::getStencilbufferSerial()
174 Renderbuffer *stencilbuffer = mStencilbufferPointer.get();
178 return stencilbuffer->getSerial();
184 Colorbuffer *Framebuffer::getColorbuffer()
186 Renderbuffer *rb = mColorbufferPointer.get();
188 if (rb != NULL && rb->isColorbuffer())
190 return static_cast<Colorbuffer*>(rb->getStorage());
198 DepthStencilbuffer *Framebuffer::getDepthbuffer()
200 Renderbuffer *rb = mDepthbufferPointer.get();
202 if (rb != NULL && rb->isDepthbuffer())
204 return static_cast<DepthStencilbuffer*>(rb->getStorage());
212 DepthStencilbuffer *Framebuffer::getStencilbuffer()
214 Renderbuffer *rb = mStencilbufferPointer.get();
216 if (rb != NULL && rb->isStencilbuffer())
218 return static_cast<DepthStencilbuffer*>(rb->getStorage());
226 GLenum Framebuffer::getColorbufferType()
228 return mColorbufferType;
231 GLenum Framebuffer::getDepthbufferType()
233 return mDepthbufferType;
236 GLenum Framebuffer::getStencilbufferType()
238 return mStencilbufferType;
241 GLuint Framebuffer::getColorbufferHandle()
243 return mColorbufferPointer.id();
246 GLuint Framebuffer::getDepthbufferHandle()
248 return mDepthbufferPointer.id();
251 GLuint Framebuffer::getStencilbufferHandle()
253 return mStencilbufferPointer.id();
256 bool Framebuffer::hasStencil()
258 if (mStencilbufferType != GL_NONE)
260 DepthStencilbuffer *stencilbufferObject = getStencilbuffer();
262 if (stencilbufferObject)
264 return stencilbufferObject->getStencilSize() > 0;
271 GLenum Framebuffer::completeness()
277 if (mColorbufferType != GL_NONE)
279 Colorbuffer *colorbuffer = getColorbuffer();
283 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
286 if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
288 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
291 if (mColorbufferType == GL_RENDERBUFFER)
293 if (!gl::IsColorRenderable(colorbuffer->getInternalFormat()))
295 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
298 else if (IsTextureTarget(mColorbufferType))
300 if (IsCompressed(colorbuffer->getInternalFormat()))
302 return GL_FRAMEBUFFER_UNSUPPORTED;
305 if ((colorbuffer->getType() == GL_FLOAT && !getContext()->supportsFloatRenderableTextures()) ||
306 (colorbuffer->getType() == GL_HALF_FLOAT_OES && !getContext()->supportsHalfFloatRenderableTextures()))
308 return GL_FRAMEBUFFER_UNSUPPORTED;
311 if (colorbuffer->getInternalFormat() == GL_LUMINANCE || colorbuffer->getInternalFormat() == GL_LUMINANCE_ALPHA)
313 return GL_FRAMEBUFFER_UNSUPPORTED;
318 width = colorbuffer->getWidth();
319 height = colorbuffer->getHeight();
320 samples = colorbuffer->getSamples();
324 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
327 DepthStencilbuffer *depthbuffer = NULL;
328 DepthStencilbuffer *stencilbuffer = NULL;
330 if (mDepthbufferType != GL_NONE)
332 if (mDepthbufferType != GL_RENDERBUFFER)
334 return GL_FRAMEBUFFER_UNSUPPORTED; // Requires GL_OES_depth_texture
337 depthbuffer = getDepthbuffer();
341 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
344 if (depthbuffer->getWidth() == 0 || depthbuffer->getHeight() == 0)
346 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
351 width = depthbuffer->getWidth();
352 height = depthbuffer->getHeight();
354 else if (width != depthbuffer->getWidth() || height != depthbuffer->getHeight())
356 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
361 samples = depthbuffer->getSamples();
363 else if (samples != depthbuffer->getSamples())
365 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
369 if (mStencilbufferType != GL_NONE)
371 if (mStencilbufferType != GL_RENDERBUFFER)
373 return GL_FRAMEBUFFER_UNSUPPORTED;
376 stencilbuffer = getStencilbuffer();
380 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
383 if (stencilbuffer->getWidth() == 0 || stencilbuffer->getHeight() == 0)
385 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
390 width = stencilbuffer->getWidth();
391 height = stencilbuffer->getHeight();
393 else if (width != stencilbuffer->getWidth() || height != stencilbuffer->getHeight())
395 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
400 samples = stencilbuffer->getSamples();
402 else if (samples != stencilbuffer->getSamples())
404 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
408 if (mDepthbufferType == GL_RENDERBUFFER && mStencilbufferType == GL_RENDERBUFFER)
410 if (depthbuffer->getInternalFormat() != GL_DEPTH24_STENCIL8_OES ||
411 stencilbuffer->getInternalFormat() != GL_DEPTH24_STENCIL8_OES ||
412 depthbuffer->getSerial() != stencilbuffer->getSerial())
414 return GL_FRAMEBUFFER_UNSUPPORTED;
418 return GL_FRAMEBUFFER_COMPLETE;
421 DefaultFramebuffer::DefaultFramebuffer(Colorbuffer *color, DepthStencilbuffer *depthStencil)
423 mColorbufferType = GL_RENDERBUFFER;
424 mDepthbufferType = (depthStencil->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
425 mStencilbufferType = (depthStencil->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
427 mColorbufferPointer.set(new Renderbuffer(0, color));
429 Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(0, depthStencil);
430 mDepthbufferPointer.set(depthStencilRenderbuffer);
431 mStencilbufferPointer.set(depthStencilRenderbuffer);
434 int Framebuffer::getSamples()
436 if (completeness() == GL_FRAMEBUFFER_COMPLETE)
438 return getColorbuffer()->getSamples();
446 GLenum DefaultFramebuffer::completeness()
448 // The default framebuffer should always be complete
449 ASSERT(Framebuffer::completeness() == GL_FRAMEBUFFER_COMPLETE);
451 return GL_FRAMEBUFFER_COMPLETE;