1 // SwiftShader Software Renderer
3 // Copyright(c) 2005-2013 TransGaming Inc.
5 // All rights reserved. No part of this software may be copied, distributed, transmitted,
6 // transcribed, stored in a retrieval system, translated into any human or computer
7 // language by any means, or disclosed to third parties without the explicit written
8 // agreement of TransGaming Inc. Without such an agreement, no rights or licenses, express
9 // or implied, including but not limited to any patent rights, are granted to you.
12 // Framebuffer.cpp: Implements the Framebuffer class. Implements GL framebuffer
13 // objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105.
15 #include "Framebuffer.h"
18 #include "Renderbuffer.h"
20 #include "utilities.h"
25 Framebuffer::Framebuffer()
27 mColorbufferType = GL_NONE;
28 mDepthbufferType = GL_NONE;
29 mStencilbufferType = GL_NONE;
32 Framebuffer::~Framebuffer()
34 mColorbufferPointer = NULL;
35 mDepthbufferPointer = NULL;
36 mStencilbufferPointer = NULL;
39 Renderbuffer *Framebuffer::lookupRenderbuffer(GLenum type, GLuint handle) const
41 Context *context = getContext();
42 Renderbuffer *buffer = NULL;
48 else if(type == GL_RENDERBUFFER)
50 buffer = context->getRenderbuffer(handle);
52 else if(IsTextureTarget(type))
54 buffer = context->getTexture(handle)->getRenderbuffer(type);
64 void Framebuffer::setColorbuffer(GLenum type, GLuint colorbuffer)
66 mColorbufferType = (colorbuffer != 0) ? type : GL_NONE;
67 mColorbufferPointer = lookupRenderbuffer(type, colorbuffer);
70 void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer)
72 mDepthbufferType = (depthbuffer != 0) ? type : GL_NONE;
73 mDepthbufferPointer = lookupRenderbuffer(type, depthbuffer);
76 void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer)
78 mStencilbufferType = (stencilbuffer != 0) ? type : GL_NONE;
79 mStencilbufferPointer = lookupRenderbuffer(type, stencilbuffer);
82 void Framebuffer::detachTexture(GLuint texture)
84 if(mColorbufferPointer.name() == texture && IsTextureTarget(mColorbufferType))
86 mColorbufferType = GL_NONE;
87 mColorbufferPointer = NULL;
90 if(mDepthbufferPointer.name() == texture && IsTextureTarget(mDepthbufferType))
92 mDepthbufferType = GL_NONE;
93 mDepthbufferPointer = NULL;
96 if(mStencilbufferPointer.name() == texture && IsTextureTarget(mStencilbufferType))
98 mStencilbufferType = GL_NONE;
99 mStencilbufferPointer = NULL;
103 void Framebuffer::detachRenderbuffer(GLuint renderbuffer)
105 if(mColorbufferPointer.name() == renderbuffer && mColorbufferType == GL_RENDERBUFFER)
107 mColorbufferType = GL_NONE;
108 mColorbufferPointer = NULL;
111 if(mDepthbufferPointer.name() == renderbuffer && mDepthbufferType == GL_RENDERBUFFER)
113 mDepthbufferType = GL_NONE;
114 mDepthbufferPointer = NULL;
117 if(mStencilbufferPointer.name() == renderbuffer && mStencilbufferType == GL_RENDERBUFFER)
119 mStencilbufferType = GL_NONE;
120 mStencilbufferPointer = NULL;
124 // Increments refcount on surface.
125 // caller must Release() the returned surface
126 egl::Image *Framebuffer::getRenderTarget()
128 Renderbuffer *colorbuffer = mColorbufferPointer;
132 return colorbuffer->getRenderTarget();
138 // Increments refcount on surface.
139 // caller must Release() the returned surface
140 egl::Image *Framebuffer::getDepthStencil()
142 Renderbuffer *depthstencilbuffer = mDepthbufferPointer;
144 if(!depthstencilbuffer)
146 depthstencilbuffer = mStencilbufferPointer;
149 if(depthstencilbuffer)
151 return depthstencilbuffer->getRenderTarget();
157 Renderbuffer *Framebuffer::getColorbuffer()
159 return mColorbufferPointer;
162 Renderbuffer *Framebuffer::getDepthbuffer()
164 return mDepthbufferPointer;
167 Renderbuffer *Framebuffer::getStencilbuffer()
169 return mStencilbufferPointer;
172 GLenum Framebuffer::getColorbufferType()
174 return mColorbufferType;
177 GLenum Framebuffer::getDepthbufferType()
179 return mDepthbufferType;
182 GLenum Framebuffer::getStencilbufferType()
184 return mStencilbufferType;
187 GLuint Framebuffer::getColorbufferName()
189 return mColorbufferPointer.name();
192 GLuint Framebuffer::getDepthbufferName()
194 return mDepthbufferPointer.name();
197 GLuint Framebuffer::getStencilbufferName()
199 return mStencilbufferPointer.name();
202 bool Framebuffer::hasStencil()
204 if(mStencilbufferType != GL_NONE)
206 Renderbuffer *stencilbufferObject = getStencilbuffer();
208 if(stencilbufferObject)
210 return stencilbufferObject->getStencilSize() > 0;
217 GLenum Framebuffer::completeness()
223 return completeness(width, height, samples);
226 GLenum Framebuffer::completeness(int &width, int &height, int &samples)
232 if(mColorbufferType != GL_NONE)
234 Renderbuffer *colorbuffer = getColorbuffer();
238 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
241 if(colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
243 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
246 if(mColorbufferType == GL_RENDERBUFFER)
248 if(!es2::IsColorRenderable(colorbuffer->getFormat()))
250 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
253 else if(IsTextureTarget(mColorbufferType))
255 GLenum format = colorbuffer->getFormat();
257 if(IsCompressed(format) ||
258 format == GL_ALPHA ||
259 format == GL_LUMINANCE ||
260 format == GL_LUMINANCE_ALPHA)
262 return GL_FRAMEBUFFER_UNSUPPORTED;
265 if(es2::IsDepthTexture(format) || es2::IsStencilTexture(format))
267 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
273 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
276 width = colorbuffer->getWidth();
277 height = colorbuffer->getHeight();
278 samples = colorbuffer->getSamples();
281 Renderbuffer *depthbuffer = NULL;
282 Renderbuffer *stencilbuffer = NULL;
284 if(mDepthbufferType != GL_NONE)
286 depthbuffer = getDepthbuffer();
290 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
293 if(depthbuffer->getWidth() == 0 || depthbuffer->getHeight() == 0)
295 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
298 if(mDepthbufferType == GL_RENDERBUFFER)
300 if(!es2::IsDepthRenderable(depthbuffer->getFormat()))
302 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
305 else if(IsTextureTarget(mDepthbufferType))
307 if(!es2::IsDepthTexture(depthbuffer->getFormat()))
309 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
315 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
318 if(width == -1 || height == -1)
320 width = depthbuffer->getWidth();
321 height = depthbuffer->getHeight();
322 samples = depthbuffer->getSamples();
324 else if(width != depthbuffer->getWidth() || height != depthbuffer->getHeight())
326 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
328 else if(samples != depthbuffer->getSamples())
330 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
334 if(mStencilbufferType != GL_NONE)
336 stencilbuffer = getStencilbuffer();
340 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
343 if(stencilbuffer->getWidth() == 0 || stencilbuffer->getHeight() == 0)
345 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
348 if(mStencilbufferType == GL_RENDERBUFFER)
350 if(!es2::IsStencilRenderable(stencilbuffer->getFormat()))
352 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
355 else if(IsTextureTarget(mStencilbufferType))
357 GLenum internalformat = stencilbuffer->getFormat();
359 if(!es2::IsStencilTexture(internalformat))
361 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
367 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
370 if(width == -1 || height == -1)
372 width = stencilbuffer->getWidth();
373 height = stencilbuffer->getHeight();
374 samples = stencilbuffer->getSamples();
376 else if(width != stencilbuffer->getWidth() || height != stencilbuffer->getHeight())
378 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
380 else if(samples != stencilbuffer->getSamples())
382 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
386 // If we have both a depth and stencil buffer, they must refer to the same object
387 // since we only support packed_depth_stencil and not separate depth and stencil
388 if(depthbuffer && stencilbuffer && (depthbuffer != stencilbuffer))
390 return GL_FRAMEBUFFER_UNSUPPORTED;
393 // We need to have at least one attachment to be complete
394 if(width == -1 || height == -1)
396 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
399 return GL_FRAMEBUFFER_COMPLETE;
402 GLenum Framebuffer::getImplementationColorReadFormat()
404 Renderbuffer *colorbuffer = mColorbufferPointer;
408 // Don't return GL_RGBA since that's always supported. Provide a second option here.
409 switch(colorbuffer->getInternalFormat())
411 case sw::FORMAT_A16B16G16R16F: return GL_BGRA_EXT;
412 case sw::FORMAT_A32B32G32R32F: return GL_BGRA_EXT;
413 case sw::FORMAT_A8R8G8B8: return GL_BGRA_EXT;
414 case sw::FORMAT_A8B8G8R8: return GL_BGRA_EXT;
415 case sw::FORMAT_X8R8G8B8: return 0x80E0; // GL_BGR_EXT
416 case sw::FORMAT_X8B8G8R8: return 0x80E0; // GL_BGR_EXT
417 case sw::FORMAT_A1R5G5B5: return GL_BGRA_EXT;
418 case sw::FORMAT_R5G6B5: return 0x80E0; // GL_BGR_EXT
427 GLenum Framebuffer::getImplementationColorReadType()
429 Renderbuffer *colorbuffer = mColorbufferPointer;
433 switch(colorbuffer->getInternalFormat())
435 case sw::FORMAT_A16B16G16R16F: return GL_HALF_FLOAT_OES;
436 case sw::FORMAT_A32B32G32R32F: return GL_FLOAT;
437 case sw::FORMAT_A8R8G8B8: return GL_UNSIGNED_BYTE;
438 case sw::FORMAT_A8B8G8R8: return GL_UNSIGNED_BYTE;
439 case sw::FORMAT_X8R8G8B8: return GL_UNSIGNED_BYTE;
440 case sw::FORMAT_X8B8G8R8: return GL_UNSIGNED_BYTE;
441 case sw::FORMAT_A1R5G5B5: return GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT;
442 case sw::FORMAT_R5G6B5: return GL_UNSIGNED_SHORT_5_6_5;
448 return GL_UNSIGNED_BYTE;
451 DefaultFramebuffer::DefaultFramebuffer(Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
453 mColorbufferPointer = new Renderbuffer(0, colorbuffer);
455 Renderbuffer *depthStencilRenderbuffer = new Renderbuffer(0, depthStencil);
456 mDepthbufferPointer = depthStencilRenderbuffer;
457 mStencilbufferPointer = depthStencilRenderbuffer;
459 mColorbufferType = GL_RENDERBUFFER;
460 mDepthbufferType = (depthStencilRenderbuffer->getDepthSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
461 mStencilbufferType = (depthStencilRenderbuffer->getStencilSize() != 0) ? GL_RENDERBUFFER : GL_NONE;
464 GLenum DefaultFramebuffer::completeness()
466 // The default framebuffer should always be complete
467 ASSERT(Framebuffer::completeness() == GL_FRAMEBUFFER_COMPLETE);
469 return GL_FRAMEBUFFER_COMPLETE;