blob: 5f9d244009192f70262d1c877a56dc2d98d087e5 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
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.
9
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000010#include "libGLESv2/Framebuffer.h"
daniel@transgaming.combbf56f72010-04-20 18:52:13 +000011#include "libGLESv2/main.h"
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +000012#include "libGLESv2/formatutils.h"
shannon.woods@transgaming.com486d9e92013-02-28 23:15:41 +000013#include "libGLESv2/Texture.h"
14#include "libGLESv2/Context.h"
shannon.woods@transgaming.com486d9e92013-02-28 23:15:41 +000015#include "libGLESv2/Renderbuffer.h"
Jamie Madille261b442014-06-25 12:42:21 -040016#include "libGLESv2/FramebufferAttachment.h"
Geoff Lang0b7eef72014-06-12 14:10:47 -040017#include "libGLESv2/renderer/Renderer.h"
Jamie Madill400a4412014-08-29 15:46:45 -040018#include "libGLESv2/renderer/RenderTarget.h"
Jamie Madill7acae0a2014-09-24 17:10:51 -040019#include "libGLESv2/renderer/Workarounds.h"
Jamie Madill9f0b42a2014-09-12 10:25:27 -040020#include "libGLESv2/renderer/d3d/TextureD3D.h"
Geoff Lang0b7eef72014-06-12 14:10:47 -040021
22#include "common/utilities.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000023
Jamie Madill9f0b42a2014-09-12 10:25:27 -040024namespace rx
25{
26RenderTarget *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment)
27{
28 if (attachment->isTexture())
29 {
30 gl::Texture *texture = attachment->getTexture();
31 ASSERT(texture);
32 TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
Jamie Madillac7579c2014-09-17 16:59:33 -040033 const gl::ImageIndex *index = attachment->getTextureImageIndex();
34 ASSERT(index);
35 return textureD3D->getRenderTarget(*index);
Jamie Madill9f0b42a2014-09-12 10:25:27 -040036 }
37
38 gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
39 ASSERT(renderbuffer);
40
41 // TODO: cast to RenderbufferD3D
42 return renderbuffer->getStorage()->getRenderTarget();
43}
44
Jamie Madill612e2e42014-09-12 13:26:55 -040045// Note: RenderTarget serials should ideally be in the RenderTargets themselves.
46unsigned int GetAttachmentSerial(gl::FramebufferAttachment *attachment)
47{
48 if (attachment->isTexture())
49 {
50 gl::Texture *texture = attachment->getTexture();
51 ASSERT(texture);
52 TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
Jamie Madillac7579c2014-09-17 16:59:33 -040053 const gl::ImageIndex *index = attachment->getTextureImageIndex();
54 ASSERT(index);
55 return textureD3D->getRenderTargetSerial(*index);
Jamie Madill612e2e42014-09-12 13:26:55 -040056 }
57
58 gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
59 ASSERT(renderbuffer);
60
61 // TODO: cast to RenderbufferD3D
62 return renderbuffer->getStorage()->getSerial();
63}
64
Jamie Madill9f0b42a2014-09-12 10:25:27 -040065}
66
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000067namespace gl
68{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000069
Shannon Woodsaa2ab7d2014-06-24 17:51:51 -040070Framebuffer::Framebuffer(rx::Renderer *renderer, GLuint id)
Jamie Madille261b442014-06-25 12:42:21 -040071 : mRenderer(renderer),
Shannon Woodsaa2ab7d2014-06-24 17:51:51 -040072 mId(id),
Jamie Madille261b442014-06-25 12:42:21 -040073 mReadBufferState(GL_COLOR_ATTACHMENT0_EXT),
74 mDepthbuffer(NULL),
75 mStencilbuffer(NULL)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000076{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000077 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
78 {
Jamie Madille261b442014-06-25 12:42:21 -040079 mColorbuffers[colorAttachment] = NULL;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000080 mDrawBufferStates[colorAttachment] = GL_NONE;
81 }
82 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000083}
84
85Framebuffer::~Framebuffer()
86{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000087 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
88 {
Jamie Madille261b442014-06-25 12:42:21 -040089 SafeDelete(mColorbuffers[colorAttachment]);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000090 }
Jamie Madille261b442014-06-25 12:42:21 -040091 SafeDelete(mDepthbuffer);
92 SafeDelete(mStencilbuffer);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000093}
94
Jamie Madillaef95de2014-09-05 10:12:41 -040095FramebufferAttachment *Framebuffer::createAttachment(GLenum binding, GLenum type, GLuint handle, GLint level, GLint layer) const
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000096{
Jamie Madill6c7b4ad2014-06-16 10:33:59 -040097 if (handle == 0)
98 {
99 return NULL;
100 }
101
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000102 gl::Context *context = gl::getContext();
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000103
Geoff Lang309c92a2013-07-25 16:23:19 -0400104 switch (type)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000105 {
Geoff Lang309c92a2013-07-25 16:23:19 -0400106 case GL_NONE:
107 return NULL;
108
109 case GL_RENDERBUFFER:
Jamie Madillaef95de2014-09-05 10:12:41 -0400110 return new RenderbufferAttachment(binding, context->getRenderbuffer(handle));
Geoff Lang309c92a2013-07-25 16:23:19 -0400111
112 case GL_TEXTURE_2D:
113 {
114 Texture *texture = context->getTexture(handle);
115 if (texture && texture->getTarget() == GL_TEXTURE_2D)
116 {
Jamie Madilleeb7b0e2014-09-03 15:07:20 -0400117 return new TextureAttachment(binding, texture, ImageIndex::Make2D(level));
Geoff Lang309c92a2013-07-25 16:23:19 -0400118 }
119 else
120 {
121 return NULL;
122 }
123 }
124
125 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
126 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
127 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
128 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
129 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
130 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
131 {
132 Texture *texture = context->getTexture(handle);
133 if (texture && texture->getTarget() == GL_TEXTURE_CUBE_MAP)
134 {
Jamie Madilleeb7b0e2014-09-03 15:07:20 -0400135 return new TextureAttachment(binding, texture, ImageIndex::MakeCube(type, level));
Geoff Lang309c92a2013-07-25 16:23:19 -0400136 }
137 else
138 {
139 return NULL;
140 }
141 }
142
143 case GL_TEXTURE_3D:
144 {
145 Texture *texture = context->getTexture(handle);
146 if (texture && texture->getTarget() == GL_TEXTURE_3D)
147 {
Jamie Madilleeb7b0e2014-09-03 15:07:20 -0400148 return new TextureAttachment(binding, texture, ImageIndex::Make3D(level, layer));
Geoff Lang309c92a2013-07-25 16:23:19 -0400149 }
150 else
151 {
152 return NULL;
153 }
154 }
155
156 case GL_TEXTURE_2D_ARRAY:
157 {
158 Texture *texture = context->getTexture(handle);
159 if (texture && texture->getTarget() == GL_TEXTURE_2D_ARRAY)
160 {
Jamie Madilleeb7b0e2014-09-03 15:07:20 -0400161 return new TextureAttachment(binding, texture, ImageIndex::Make2DArray(level, layer));
Geoff Lang309c92a2013-07-25 16:23:19 -0400162 }
163 else
164 {
165 return NULL;
166 }
167 }
168
169 default:
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000170 UNREACHABLE();
Geoff Lang309c92a2013-07-25 16:23:19 -0400171 return NULL;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000172 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000173}
174
Geoff Lang309c92a2013-07-25 16:23:19 -0400175void Framebuffer::setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer, GLint level, GLint layer)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000176{
177 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
Jamie Madille261b442014-06-25 12:42:21 -0400178 SafeDelete(mColorbuffers[colorAttachment]);
Jamie Madillaef95de2014-09-05 10:12:41 -0400179 GLenum binding = colorAttachment + GL_COLOR_ATTACHMENT0;
180 mColorbuffers[colorAttachment] = createAttachment(binding, type, colorbuffer, level, layer);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000181}
182
Geoff Lang309c92a2013-07-25 16:23:19 -0400183void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level, GLint layer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000184{
Jamie Madille261b442014-06-25 12:42:21 -0400185 SafeDelete(mDepthbuffer);
Jamie Madillaef95de2014-09-05 10:12:41 -0400186 mDepthbuffer = createAttachment(GL_DEPTH_ATTACHMENT, type, depthbuffer, level, layer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000187}
188
Geoff Lang309c92a2013-07-25 16:23:19 -0400189void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level, GLint layer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000190{
Jamie Madille261b442014-06-25 12:42:21 -0400191 SafeDelete(mStencilbuffer);
Jamie Madillaef95de2014-09-05 10:12:41 -0400192 mStencilbuffer = createAttachment(GL_STENCIL_ATTACHMENT, type, stencilbuffer, level, layer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000193}
194
Geoff Lang309c92a2013-07-25 16:23:19 -0400195void Framebuffer::setDepthStencilBuffer(GLenum type, GLuint depthStencilBuffer, GLint level, GLint layer)
Geoff Lang55ba29c2013-07-11 16:57:53 -0400196{
Jamie Madillaef95de2014-09-05 10:12:41 -0400197 FramebufferAttachment *attachment = createAttachment(GL_DEPTH_STENCIL_ATTACHMENT, type, depthStencilBuffer, level, layer);
Jamie Madill6c7b4ad2014-06-16 10:33:59 -0400198
Jamie Madille261b442014-06-25 12:42:21 -0400199 SafeDelete(mDepthbuffer);
200 SafeDelete(mStencilbuffer);
201
202 // ensure this is a legitimate depth+stencil format
Geoff Lange4a492b2014-06-19 14:14:41 -0400203 if (attachment && attachment->getDepthSize() > 0 && attachment->getStencilSize() > 0)
Geoff Lang55ba29c2013-07-11 16:57:53 -0400204 {
Jamie Madille261b442014-06-25 12:42:21 -0400205 mDepthbuffer = attachment;
Jamie Madill28bedaf2014-06-26 13:17:22 -0400206
207 // Make a new attachment object to ensure we do not double-delete
208 // See angle issue 686
Jamie Madillaef95de2014-09-05 10:12:41 -0400209 mStencilbuffer = createAttachment(GL_DEPTH_STENCIL_ATTACHMENT, type, depthStencilBuffer, level, layer);
Geoff Lang55ba29c2013-07-11 16:57:53 -0400210 }
211}
212
Jamie Madille261b442014-06-25 12:42:21 -0400213void Framebuffer::detachTexture(GLuint textureId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000214{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000215 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000216 {
Jamie Madille261b442014-06-25 12:42:21 -0400217 FramebufferAttachment *attachment = mColorbuffers[colorAttachment];
218
219 if (attachment && attachment->isTextureWithId(textureId))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000220 {
Jamie Madille261b442014-06-25 12:42:21 -0400221 SafeDelete(mColorbuffers[colorAttachment]);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000222 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000223 }
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000224
Jamie Madille261b442014-06-25 12:42:21 -0400225 if (mDepthbuffer && mDepthbuffer->isTextureWithId(textureId))
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000226 {
Jamie Madille261b442014-06-25 12:42:21 -0400227 SafeDelete(mDepthbuffer);
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000228 }
229
Jamie Madille261b442014-06-25 12:42:21 -0400230 if (mStencilbuffer && mStencilbuffer->isTextureWithId(textureId))
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000231 {
Jamie Madille261b442014-06-25 12:42:21 -0400232 SafeDelete(mStencilbuffer);
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000233 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000234}
235
Jamie Madille261b442014-06-25 12:42:21 -0400236void Framebuffer::detachRenderbuffer(GLuint renderbufferId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000237{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000238 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000239 {
Jamie Madille261b442014-06-25 12:42:21 -0400240 FramebufferAttachment *attachment = mColorbuffers[colorAttachment];
241
242 if (attachment && attachment->isRenderbufferWithId(renderbufferId))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000243 {
Jamie Madille261b442014-06-25 12:42:21 -0400244 SafeDelete(mColorbuffers[colorAttachment]);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000245 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000246 }
247
Jamie Madille261b442014-06-25 12:42:21 -0400248 if (mDepthbuffer && mDepthbuffer->isRenderbufferWithId(renderbufferId))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000249 {
Jamie Madille261b442014-06-25 12:42:21 -0400250 SafeDelete(mDepthbuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000251 }
252
Jamie Madille261b442014-06-25 12:42:21 -0400253 if (mStencilbuffer && mStencilbuffer->isRenderbufferWithId(renderbufferId))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000254 {
Jamie Madille261b442014-06-25 12:42:21 -0400255 SafeDelete(mStencilbuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000256 }
257}
258
Jamie Madill3c7fa222014-06-05 13:08:51 -0400259FramebufferAttachment *Framebuffer::getColorbuffer(unsigned int colorAttachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000260{
261 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
Jamie Madille261b442014-06-25 12:42:21 -0400262 return mColorbuffers[colorAttachment];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000263}
264
Jamie Madill3c7fa222014-06-05 13:08:51 -0400265FramebufferAttachment *Framebuffer::getDepthbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000266{
Jamie Madille261b442014-06-25 12:42:21 -0400267 return mDepthbuffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000268}
269
Jamie Madill3c7fa222014-06-05 13:08:51 -0400270FramebufferAttachment *Framebuffer::getStencilbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000271{
Jamie Madille261b442014-06-25 12:42:21 -0400272 return mStencilbuffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000273}
274
Jamie Madill3c7fa222014-06-05 13:08:51 -0400275FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
Geoff Lang646559f2013-08-15 11:08:15 -0400276{
Jamie Madille261b442014-06-25 12:42:21 -0400277 return (hasValidDepthStencil() ? mDepthbuffer : NULL);
Geoff Lang646559f2013-08-15 11:08:15 -0400278}
279
Jamie Madill3c7fa222014-06-05 13:08:51 -0400280FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000281{
Jamie Madille261b442014-06-25 12:42:21 -0400282 FramebufferAttachment *depthstencilbuffer = mDepthbuffer;
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000283
284 if (!depthstencilbuffer)
285 {
Jamie Madille261b442014-06-25 12:42:21 -0400286 depthstencilbuffer = mStencilbuffer;
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000287 }
288
289 return depthstencilbuffer;
290}
291
Jamie Madill3c7fa222014-06-05 13:08:51 -0400292FramebufferAttachment *Framebuffer::getReadColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000293{
294 // Will require more logic if glReadBuffers is supported
Jamie Madille261b442014-06-25 12:42:21 -0400295 return mColorbuffers[0];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000296}
297
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000298GLenum Framebuffer::getReadColorbufferType() const
299{
300 // Will require more logic if glReadBuffers is supported
Jamie Madille261b442014-06-25 12:42:21 -0400301 return (mColorbuffers[0] ? mColorbuffers[0]->type() : GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000302}
303
Jamie Madill3c7fa222014-06-05 13:08:51 -0400304FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000305{
306 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
307 {
Jamie Madille261b442014-06-25 12:42:21 -0400308 if (mColorbuffers[colorAttachment])
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000309 {
Jamie Madille261b442014-06-25 12:42:21 -0400310 return mColorbuffers[colorAttachment];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000311 }
312 }
313
314 return NULL;
315}
316
Jamie Madille92a3542014-07-03 10:38:58 -0400317FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000318{
Jamie Madille92a3542014-07-03 10:38:58 -0400319 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
320 {
321 return getColorbuffer(attachment - GL_COLOR_ATTACHMENT0);
322 }
323 else
324 {
325 switch (attachment)
326 {
327 case GL_DEPTH_ATTACHMENT:
328 return getDepthbuffer();
329 case GL_STENCIL_ATTACHMENT:
330 return getStencilbuffer();
331 case GL_DEPTH_STENCIL_ATTACHMENT:
332 return getDepthStencilBuffer();
333 default:
334 UNREACHABLE();
335 return NULL;
336 }
337 }
Geoff Lang55ba29c2013-07-11 16:57:53 -0400338}
339
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000340GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const
341{
342 return mDrawBufferStates[colorAttachment];
343}
344
345void Framebuffer::setDrawBufferState(unsigned int colorAttachment, GLenum drawBuffer)
346{
347 mDrawBufferStates[colorAttachment] = drawBuffer;
348}
349
shannon.woods%transgaming.com@gtempaccount.comdae24092013-04-13 03:31:31 +0000350bool Framebuffer::isEnabledColorAttachment(unsigned int colorAttachment) const
351{
Jamie Madille261b442014-06-25 12:42:21 -0400352 return (mColorbuffers[colorAttachment] && mDrawBufferStates[colorAttachment] != GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comdae24092013-04-13 03:31:31 +0000353}
354
355bool Framebuffer::hasEnabledColorAttachment() const
356{
357 for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
358 {
359 if (isEnabledColorAttachment(colorAttachment))
360 {
361 return true;
362 }
363 }
364
365 return false;
366}
367
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000368bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000369{
Geoff Lange4a492b2014-06-19 14:14:41 -0400370 return (mStencilbuffer && mStencilbuffer->getStencilSize() > 0);
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000371}
372
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000373bool Framebuffer::usingExtendedDrawBuffers() const
374{
375 for (unsigned int colorAttachment = 1; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
376 {
377 if (isEnabledColorAttachment(colorAttachment))
378 {
379 return true;
380 }
381 }
382
383 return false;
384}
385
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000386GLenum Framebuffer::completeness() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000387{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000388 int width = 0;
389 int height = 0;
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000390 unsigned int colorbufferSize = 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000391 int samples = -1;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000392 bool missingAttachment = true;
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000393 GLuint clientVersion = mRenderer->getCurrentClientVersion();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000394
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000395 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000396 {
Jamie Madillbb94f342014-06-23 15:23:02 -0400397 const FramebufferAttachment *colorbuffer = mColorbuffers[colorAttachment];
398
399 if (colorbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000400 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000401 if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000402 {
403 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
404 }
daniel@transgaming.com01868132010-08-24 19:21:17 +0000405
Geoff Langcec35902014-04-16 10:52:36 -0400406 GLenum internalformat = colorbuffer->getInternalFormat();
Geoff Langc0b9ef42014-07-02 10:02:37 -0400407 // TODO(geofflang): use context's texture caps
408 const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400409 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madillbb94f342014-06-23 15:23:02 -0400410 if (colorbuffer->isTexture())
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000411 {
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400412 if (!formatCaps.renderable)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000413 {
414 return GL_FRAMEBUFFER_UNSUPPORTED;
415 }
416
Geoff Lang5d601382014-07-22 15:14:06 -0400417 if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000418 {
419 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
420 }
421 }
422 else
423 {
Geoff Lang5d601382014-07-22 15:14:06 -0400424 if (!formatCaps.renderable || formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400425 {
426 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
427 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000428 }
429
430 if (!missingAttachment)
431 {
432 // all color attachments must have the same width and height
433 if (colorbuffer->getWidth() != width || colorbuffer->getHeight() != height)
434 {
435 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
436 }
437
438 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
439 // all color attachments have the same number of samples for the FBO to be complete.
440 if (colorbuffer->getSamples() != samples)
441 {
442 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
443 }
444
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000445 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
446 // in GLES 3.0, there is no such restriction
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000447 if (clientVersion < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000448 {
Geoff Lang5d601382014-07-22 15:14:06 -0400449 if (formatInfo.pixelBytes != colorbufferSize)
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000450 {
451 return GL_FRAMEBUFFER_UNSUPPORTED;
452 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000453 }
454
455 // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness
456 for (unsigned int previousColorAttachment = 0; previousColorAttachment < colorAttachment; previousColorAttachment++)
457 {
Jamie Madille92a3542014-07-03 10:38:58 -0400458 const FramebufferAttachment *previousAttachment = mColorbuffers[previousColorAttachment];
459
460 if (previousAttachment &&
461 (colorbuffer->id() == previousAttachment->id() &&
462 colorbuffer->type() == previousAttachment->type()))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000463 {
464 return GL_FRAMEBUFFER_UNSUPPORTED;
465 }
466 }
467 }
468 else
469 {
470 width = colorbuffer->getWidth();
471 height = colorbuffer->getHeight();
472 samples = colorbuffer->getSamples();
Geoff Lang5d601382014-07-22 15:14:06 -0400473 colorbufferSize = formatInfo.pixelBytes;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000474 missingAttachment = false;
475 }
476 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000477 }
478
Jamie Madille261b442014-06-25 12:42:21 -0400479 if (mDepthbuffer)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000480 {
Jamie Madille261b442014-06-25 12:42:21 -0400481 if (mDepthbuffer->getWidth() == 0 || mDepthbuffer->getHeight() == 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000482 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000483 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000484 }
485
Jamie Madille261b442014-06-25 12:42:21 -0400486 GLenum internalformat = mDepthbuffer->getInternalFormat();
Geoff Langc0b9ef42014-07-02 10:02:37 -0400487 // TODO(geofflang): use context's texture caps
488 const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400489 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madillbb94f342014-06-23 15:23:02 -0400490 if (mDepthbuffer->isTexture())
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000491 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000492 // depth texture attachments require OES/ANGLE_depth_texture
Geoff Langc0b9ef42014-07-02 10:02:37 -0400493 // TODO(geofflang): use context's extensions
494 if (!mRenderer->getRendererExtensions().depthTextures)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000495 {
496 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
497 }
498
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400499 if (!formatCaps.renderable)
Geoff Langcec35902014-04-16 10:52:36 -0400500 {
501 return GL_FRAMEBUFFER_UNSUPPORTED;
502 }
503
Geoff Lang5d601382014-07-22 15:14:06 -0400504 if (formatInfo.depthBits == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000505 {
506 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
507 }
508 }
509 else
510 {
Geoff Lang5d601382014-07-22 15:14:06 -0400511 if (!formatCaps.renderable || formatInfo.depthBits == 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400512 {
513 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
514 }
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000515 }
516
517 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000518 {
Jamie Madille261b442014-06-25 12:42:21 -0400519 width = mDepthbuffer->getWidth();
520 height = mDepthbuffer->getHeight();
521 samples = mDepthbuffer->getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000522 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000523 }
Jamie Madille261b442014-06-25 12:42:21 -0400524 else if (width != mDepthbuffer->getWidth() || height != mDepthbuffer->getHeight())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000525 {
526 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
527 }
Jamie Madille261b442014-06-25 12:42:21 -0400528 else if (samples != mDepthbuffer->getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000529 {
530 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
531 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000532 }
533
Jamie Madille261b442014-06-25 12:42:21 -0400534 if (mStencilbuffer)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000535 {
Jamie Madille261b442014-06-25 12:42:21 -0400536 if (mStencilbuffer->getWidth() == 0 || mStencilbuffer->getHeight() == 0)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000537 {
538 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
539 }
540
Jamie Madille261b442014-06-25 12:42:21 -0400541 GLenum internalformat = mStencilbuffer->getInternalFormat();
Geoff Langc0b9ef42014-07-02 10:02:37 -0400542 // TODO(geofflang): use context's texture caps
543 const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400544 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madillbb94f342014-06-23 15:23:02 -0400545 if (mStencilbuffer->isTexture())
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000546 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000547 // texture stencil attachments come along as part
548 // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
Geoff Langc0b9ef42014-07-02 10:02:37 -0400549 // TODO(geofflang): use context's extensions
550 if (!mRenderer->getRendererExtensions().depthTextures)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000551 {
552 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
553 }
554
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400555 if (!formatCaps.renderable)
Geoff Langcec35902014-04-16 10:52:36 -0400556 {
557 return GL_FRAMEBUFFER_UNSUPPORTED;
558 }
559
Geoff Lang5d601382014-07-22 15:14:06 -0400560 if (formatInfo.stencilBits == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000561 {
562 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
563 }
564 }
565 else
566 {
Geoff Lang5d601382014-07-22 15:14:06 -0400567 if (!formatCaps.renderable || formatInfo.stencilBits == 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400568 {
569 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
570 }
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000571 }
572
573 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000574 {
Jamie Madille261b442014-06-25 12:42:21 -0400575 width = mStencilbuffer->getWidth();
576 height = mStencilbuffer->getHeight();
577 samples = mStencilbuffer->getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000578 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000579 }
Jamie Madille261b442014-06-25 12:42:21 -0400580 else if (width != mStencilbuffer->getWidth() || height != mStencilbuffer->getHeight())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000581 {
582 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
583 }
Jamie Madille261b442014-06-25 12:42:21 -0400584 else if (samples != mStencilbuffer->getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000585 {
586 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
587 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000588 }
589
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000590 // if we have both a depth and stencil buffer, they must refer to the same object
591 // since we only support packed_depth_stencil and not separate depth and stencil
Jamie Madille261b442014-06-25 12:42:21 -0400592 if (mDepthbuffer && mStencilbuffer && !hasValidDepthStencil())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000593 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000594 return GL_FRAMEBUFFER_UNSUPPORTED;
595 }
596
597 // we need to have at least one attachment to be complete
598 if (missingAttachment)
599 {
600 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000601 }
602
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000603 return GL_FRAMEBUFFER_COMPLETE;
604}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000605
Jamie Madill2d96b9e2014-08-29 15:46:47 -0400606void Framebuffer::invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments)
607{
608 GLuint maxDimension = caps.maxRenderbufferSize;
609 invalidateSub(caps, numAttachments, attachments, 0, 0, maxDimension, maxDimension);
610}
611
612void Framebuffer::invalidateSub(const Caps &caps, GLsizei numAttachments, const GLenum *attachments,
613 GLint x, GLint y, GLsizei width, GLsizei height)
Jamie Madill400a4412014-08-29 15:46:45 -0400614{
615 ASSERT(completeness() == GL_FRAMEBUFFER_COMPLETE);
Jamie Madill6d708262014-09-03 15:07:13 -0400616 for (GLsizei attachIndex = 0; attachIndex < numAttachments; ++attachIndex)
Jamie Madill400a4412014-08-29 15:46:45 -0400617 {
Jamie Madill6d708262014-09-03 15:07:13 -0400618 GLenum attachmentTarget = attachments[attachIndex];
Jamie Madill400a4412014-08-29 15:46:45 -0400619
Jamie Madill6d708262014-09-03 15:07:13 -0400620 gl::FramebufferAttachment *attachment =
621 (attachmentTarget == GL_DEPTH_STENCIL_ATTACHMENT) ? getDepthOrStencilbuffer() :
622 getAttachment(attachmentTarget);
Jamie Madill400a4412014-08-29 15:46:45 -0400623
Jamie Madill6d708262014-09-03 15:07:13 -0400624 if (attachment)
Jamie Madill400a4412014-08-29 15:46:45 -0400625 {
Jamie Madill9f0b42a2014-09-12 10:25:27 -0400626 rx::RenderTarget *renderTarget = rx::GetAttachmentRenderTarget(attachment);
Jamie Madill6d708262014-09-03 15:07:13 -0400627 if (renderTarget)
628 {
629 renderTarget->invalidate(x, y, width, height);
630 }
Jamie Madill400a4412014-08-29 15:46:45 -0400631 }
632 }
633}
634
daniel@transgaming.com16418b12012-11-28 19:32:22 +0000635DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
Shannon Woodsaa2ab7d2014-06-24 17:51:51 -0400636 : Framebuffer(renderer, 0)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000637{
Geoff Lange4a492b2014-06-19 14:14:41 -0400638 Renderbuffer *colorRenderbuffer = new Renderbuffer(0, colorbuffer);
Jamie Madillaef95de2014-09-05 10:12:41 -0400639 mColorbuffers[0] = new RenderbufferAttachment(GL_BACK, colorRenderbuffer);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000640
Jamie Madill28bedaf2014-06-26 13:17:22 -0400641 Renderbuffer *depthStencilBuffer = new Renderbuffer(0, depthStencil);
642
643 // Make a new attachment objects to ensure we do not double-delete
644 // See angle issue 686
Jamie Madillaef95de2014-09-05 10:12:41 -0400645 mDepthbuffer = (depthStencilBuffer->getDepthSize() != 0 ? new RenderbufferAttachment(GL_DEPTH_ATTACHMENT, depthStencilBuffer) : NULL);
646 mStencilbuffer = (depthStencilBuffer->getStencilSize() != 0 ? new RenderbufferAttachment(GL_STENCIL_ATTACHMENT, depthStencilBuffer) : NULL);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000647
648 mDrawBufferStates[0] = GL_BACK;
649 mReadBufferState = GL_BACK;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000650}
651
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000652int Framebuffer::getSamples() const
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000653{
654 if (completeness() == GL_FRAMEBUFFER_COMPLETE)
655 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000656 // for a complete framebuffer, all attachments must have the same sample count
657 // in this case return the first nonzero sample size
658 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
659 {
Jamie Madille261b442014-06-25 12:42:21 -0400660 if (mColorbuffers[colorAttachment])
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000661 {
Jamie Madille261b442014-06-25 12:42:21 -0400662 return mColorbuffers[colorAttachment]->getSamples();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000663 }
664 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000665 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000666
667 return 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000668}
669
Jamie Madille261b442014-06-25 12:42:21 -0400670bool Framebuffer::hasValidDepthStencil() const
671{
672 // A valid depth-stencil attachment has the same resource bound to both the
673 // depth and stencil attachment points.
674 return (mDepthbuffer && mStencilbuffer &&
675 mDepthbuffer->type() == mStencilbuffer->type() &&
676 mDepthbuffer->id() == mStencilbuffer->id());
677}
678
Jamie Madillce20c7f2014-09-03 11:56:29 -0400679ColorbufferInfo Framebuffer::getColorbuffersForRender() const
680{
681 ColorbufferInfo colorbuffersForRender;
682
683 for (size_t colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; ++colorAttachment)
684 {
685 GLenum drawBufferState = mDrawBufferStates[colorAttachment];
686 FramebufferAttachment *colorbuffer = mColorbuffers[colorAttachment];
687
688 if (colorbuffer != NULL && drawBufferState != GL_NONE)
689 {
690 ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + colorAttachment));
691 colorbuffersForRender.push_back(colorbuffer);
692 }
Jamie Madill7acae0a2014-09-24 17:10:51 -0400693 else if (!mRenderer->getWorkarounds().mrtPerfWorkaround)
Jamie Madillce20c7f2014-09-03 11:56:29 -0400694 {
695 colorbuffersForRender.push_back(NULL);
696 }
697 }
698
699 return colorbuffersForRender;
700}
701
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000702GLenum DefaultFramebuffer::completeness() const
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000703{
shannon.woods@transgaming.com3e3da582013-02-28 23:09:03 +0000704 // The default framebuffer *must* always be complete, though it may not be
705 // subject to the same rules as application FBOs. ie, it could have 0x0 size.
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000706 return GL_FRAMEBUFFER_COMPLETE;
707}
708
Jamie Madille92a3542014-07-03 10:38:58 -0400709FramebufferAttachment *DefaultFramebuffer::getAttachment(GLenum attachment) const
710{
711 switch (attachment)
712 {
Jamie Madill6d708262014-09-03 15:07:13 -0400713 case GL_COLOR:
Jamie Madille92a3542014-07-03 10:38:58 -0400714 case GL_BACK:
715 return getColorbuffer(0);
716 case GL_DEPTH:
717 return getDepthbuffer();
718 case GL_STENCIL:
719 return getStencilbuffer();
720 case GL_DEPTH_STENCIL:
721 return getDepthStencilBuffer();
722 default:
723 UNREACHABLE();
724 return NULL;
725 }
726}
727
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000728}