blob: e82e34d6450ecbc63905b3ce6f234d61590ba2e9 [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 Madill9f0b42a2014-09-12 10:25:27 -040019#include "libGLESv2/renderer/d3d/TextureD3D.h"
Geoff Lang0b7eef72014-06-12 14:10:47 -040020
21#include "common/utilities.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000022
Jamie Madill9f0b42a2014-09-12 10:25:27 -040023namespace rx
24{
25RenderTarget *GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment)
26{
27 if (attachment->isTexture())
28 {
29 gl::Texture *texture = attachment->getTexture();
30 ASSERT(texture);
31 TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
Jamie Madill612e2e42014-09-12 13:26:55 -040032
Jamie Madill9f0b42a2014-09-12 10:25:27 -040033 return textureD3D->getRenderTarget(attachment->mipLevel(), attachment->layer());
34 }
35
36 gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
37 ASSERT(renderbuffer);
38
39 // TODO: cast to RenderbufferD3D
40 return renderbuffer->getStorage()->getRenderTarget();
41}
42
Jamie Madill612e2e42014-09-12 13:26:55 -040043// Note: RenderTarget serials should ideally be in the RenderTargets themselves.
44unsigned int GetAttachmentSerial(gl::FramebufferAttachment *attachment)
45{
46 if (attachment->isTexture())
47 {
48 gl::Texture *texture = attachment->getTexture();
49 ASSERT(texture);
50 TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
51 return textureD3D->getRenderTargetSerial(attachment->mipLevel(), attachment->layer());
52 }
53
54 gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
55 ASSERT(renderbuffer);
56
57 // TODO: cast to RenderbufferD3D
58 return renderbuffer->getStorage()->getSerial();
59}
60
Jamie Madill9f0b42a2014-09-12 10:25:27 -040061}
62
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000063namespace gl
64{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000065
Shannon Woodsaa2ab7d2014-06-24 17:51:51 -040066Framebuffer::Framebuffer(rx::Renderer *renderer, GLuint id)
Jamie Madille261b442014-06-25 12:42:21 -040067 : mRenderer(renderer),
Shannon Woodsaa2ab7d2014-06-24 17:51:51 -040068 mId(id),
Jamie Madille261b442014-06-25 12:42:21 -040069 mReadBufferState(GL_COLOR_ATTACHMENT0_EXT),
70 mDepthbuffer(NULL),
71 mStencilbuffer(NULL)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000072{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000073 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
74 {
Jamie Madille261b442014-06-25 12:42:21 -040075 mColorbuffers[colorAttachment] = NULL;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000076 mDrawBufferStates[colorAttachment] = GL_NONE;
77 }
78 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000079}
80
81Framebuffer::~Framebuffer()
82{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000083 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
84 {
Jamie Madille261b442014-06-25 12:42:21 -040085 SafeDelete(mColorbuffers[colorAttachment]);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000086 }
Jamie Madille261b442014-06-25 12:42:21 -040087 SafeDelete(mDepthbuffer);
88 SafeDelete(mStencilbuffer);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000089}
90
Jamie Madillaef95de2014-09-05 10:12:41 -040091FramebufferAttachment *Framebuffer::createAttachment(GLenum binding, GLenum type, GLuint handle, GLint level, GLint layer) const
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000092{
Jamie Madill6c7b4ad2014-06-16 10:33:59 -040093 if (handle == 0)
94 {
95 return NULL;
96 }
97
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000098 gl::Context *context = gl::getContext();
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000099
Geoff Lang309c92a2013-07-25 16:23:19 -0400100 switch (type)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000101 {
Geoff Lang309c92a2013-07-25 16:23:19 -0400102 case GL_NONE:
103 return NULL;
104
105 case GL_RENDERBUFFER:
Jamie Madillaef95de2014-09-05 10:12:41 -0400106 return new RenderbufferAttachment(binding, context->getRenderbuffer(handle));
Geoff Lang309c92a2013-07-25 16:23:19 -0400107
108 case GL_TEXTURE_2D:
109 {
110 Texture *texture = context->getTexture(handle);
111 if (texture && texture->getTarget() == GL_TEXTURE_2D)
112 {
Jamie Madilleeb7b0e2014-09-03 15:07:20 -0400113 return new TextureAttachment(binding, texture, ImageIndex::Make2D(level));
Geoff Lang309c92a2013-07-25 16:23:19 -0400114 }
115 else
116 {
117 return NULL;
118 }
119 }
120
121 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
122 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
123 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
124 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
125 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
126 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
127 {
128 Texture *texture = context->getTexture(handle);
129 if (texture && texture->getTarget() == GL_TEXTURE_CUBE_MAP)
130 {
Jamie Madilleeb7b0e2014-09-03 15:07:20 -0400131 return new TextureAttachment(binding, texture, ImageIndex::MakeCube(type, level));
Geoff Lang309c92a2013-07-25 16:23:19 -0400132 }
133 else
134 {
135 return NULL;
136 }
137 }
138
139 case GL_TEXTURE_3D:
140 {
141 Texture *texture = context->getTexture(handle);
142 if (texture && texture->getTarget() == GL_TEXTURE_3D)
143 {
Jamie Madilleeb7b0e2014-09-03 15:07:20 -0400144 return new TextureAttachment(binding, texture, ImageIndex::Make3D(level, layer));
Geoff Lang309c92a2013-07-25 16:23:19 -0400145 }
146 else
147 {
148 return NULL;
149 }
150 }
151
152 case GL_TEXTURE_2D_ARRAY:
153 {
154 Texture *texture = context->getTexture(handle);
155 if (texture && texture->getTarget() == GL_TEXTURE_2D_ARRAY)
156 {
Jamie Madilleeb7b0e2014-09-03 15:07:20 -0400157 return new TextureAttachment(binding, texture, ImageIndex::Make2DArray(level, layer));
Geoff Lang309c92a2013-07-25 16:23:19 -0400158 }
159 else
160 {
161 return NULL;
162 }
163 }
164
165 default:
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000166 UNREACHABLE();
Geoff Lang309c92a2013-07-25 16:23:19 -0400167 return NULL;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000168 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000169}
170
Geoff Lang309c92a2013-07-25 16:23:19 -0400171void Framebuffer::setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer, GLint level, GLint layer)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000172{
173 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
Jamie Madille261b442014-06-25 12:42:21 -0400174 SafeDelete(mColorbuffers[colorAttachment]);
Jamie Madillaef95de2014-09-05 10:12:41 -0400175 GLenum binding = colorAttachment + GL_COLOR_ATTACHMENT0;
176 mColorbuffers[colorAttachment] = createAttachment(binding, type, colorbuffer, level, layer);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000177}
178
Geoff Lang309c92a2013-07-25 16:23:19 -0400179void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level, GLint layer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000180{
Jamie Madille261b442014-06-25 12:42:21 -0400181 SafeDelete(mDepthbuffer);
Jamie Madillaef95de2014-09-05 10:12:41 -0400182 mDepthbuffer = createAttachment(GL_DEPTH_ATTACHMENT, type, depthbuffer, level, layer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000183}
184
Geoff Lang309c92a2013-07-25 16:23:19 -0400185void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level, GLint layer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000186{
Jamie Madille261b442014-06-25 12:42:21 -0400187 SafeDelete(mStencilbuffer);
Jamie Madillaef95de2014-09-05 10:12:41 -0400188 mStencilbuffer = createAttachment(GL_STENCIL_ATTACHMENT, type, stencilbuffer, level, layer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000189}
190
Geoff Lang309c92a2013-07-25 16:23:19 -0400191void Framebuffer::setDepthStencilBuffer(GLenum type, GLuint depthStencilBuffer, GLint level, GLint layer)
Geoff Lang55ba29c2013-07-11 16:57:53 -0400192{
Jamie Madillaef95de2014-09-05 10:12:41 -0400193 FramebufferAttachment *attachment = createAttachment(GL_DEPTH_STENCIL_ATTACHMENT, type, depthStencilBuffer, level, layer);
Jamie Madill6c7b4ad2014-06-16 10:33:59 -0400194
Jamie Madille261b442014-06-25 12:42:21 -0400195 SafeDelete(mDepthbuffer);
196 SafeDelete(mStencilbuffer);
197
198 // ensure this is a legitimate depth+stencil format
Geoff Lange4a492b2014-06-19 14:14:41 -0400199 if (attachment && attachment->getDepthSize() > 0 && attachment->getStencilSize() > 0)
Geoff Lang55ba29c2013-07-11 16:57:53 -0400200 {
Jamie Madille261b442014-06-25 12:42:21 -0400201 mDepthbuffer = attachment;
Jamie Madill28bedaf2014-06-26 13:17:22 -0400202
203 // Make a new attachment object to ensure we do not double-delete
204 // See angle issue 686
Jamie Madillaef95de2014-09-05 10:12:41 -0400205 mStencilbuffer = createAttachment(GL_DEPTH_STENCIL_ATTACHMENT, type, depthStencilBuffer, level, layer);
Geoff Lang55ba29c2013-07-11 16:57:53 -0400206 }
207}
208
Jamie Madille261b442014-06-25 12:42:21 -0400209void Framebuffer::detachTexture(GLuint textureId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000210{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000211 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000212 {
Jamie Madille261b442014-06-25 12:42:21 -0400213 FramebufferAttachment *attachment = mColorbuffers[colorAttachment];
214
215 if (attachment && attachment->isTextureWithId(textureId))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000216 {
Jamie Madille261b442014-06-25 12:42:21 -0400217 SafeDelete(mColorbuffers[colorAttachment]);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000218 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000219 }
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000220
Jamie Madille261b442014-06-25 12:42:21 -0400221 if (mDepthbuffer && mDepthbuffer->isTextureWithId(textureId))
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000222 {
Jamie Madille261b442014-06-25 12:42:21 -0400223 SafeDelete(mDepthbuffer);
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000224 }
225
Jamie Madille261b442014-06-25 12:42:21 -0400226 if (mStencilbuffer && mStencilbuffer->isTextureWithId(textureId))
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000227 {
Jamie Madille261b442014-06-25 12:42:21 -0400228 SafeDelete(mStencilbuffer);
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000229 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000230}
231
Jamie Madille261b442014-06-25 12:42:21 -0400232void Framebuffer::detachRenderbuffer(GLuint renderbufferId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000233{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000234 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000235 {
Jamie Madille261b442014-06-25 12:42:21 -0400236 FramebufferAttachment *attachment = mColorbuffers[colorAttachment];
237
238 if (attachment && attachment->isRenderbufferWithId(renderbufferId))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000239 {
Jamie Madille261b442014-06-25 12:42:21 -0400240 SafeDelete(mColorbuffers[colorAttachment]);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000241 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000242 }
243
Jamie Madille261b442014-06-25 12:42:21 -0400244 if (mDepthbuffer && mDepthbuffer->isRenderbufferWithId(renderbufferId))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000245 {
Jamie Madille261b442014-06-25 12:42:21 -0400246 SafeDelete(mDepthbuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000247 }
248
Jamie Madille261b442014-06-25 12:42:21 -0400249 if (mStencilbuffer && mStencilbuffer->isRenderbufferWithId(renderbufferId))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000250 {
Jamie Madille261b442014-06-25 12:42:21 -0400251 SafeDelete(mStencilbuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000252 }
253}
254
Jamie Madill3c7fa222014-06-05 13:08:51 -0400255FramebufferAttachment *Framebuffer::getColorbuffer(unsigned int colorAttachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000256{
257 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
Jamie Madille261b442014-06-25 12:42:21 -0400258 return mColorbuffers[colorAttachment];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000259}
260
Jamie Madill3c7fa222014-06-05 13:08:51 -0400261FramebufferAttachment *Framebuffer::getDepthbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000262{
Jamie Madille261b442014-06-25 12:42:21 -0400263 return mDepthbuffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000264}
265
Jamie Madill3c7fa222014-06-05 13:08:51 -0400266FramebufferAttachment *Framebuffer::getStencilbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000267{
Jamie Madille261b442014-06-25 12:42:21 -0400268 return mStencilbuffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000269}
270
Jamie Madill3c7fa222014-06-05 13:08:51 -0400271FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
Geoff Lang646559f2013-08-15 11:08:15 -0400272{
Jamie Madille261b442014-06-25 12:42:21 -0400273 return (hasValidDepthStencil() ? mDepthbuffer : NULL);
Geoff Lang646559f2013-08-15 11:08:15 -0400274}
275
Jamie Madill3c7fa222014-06-05 13:08:51 -0400276FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000277{
Jamie Madille261b442014-06-25 12:42:21 -0400278 FramebufferAttachment *depthstencilbuffer = mDepthbuffer;
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000279
280 if (!depthstencilbuffer)
281 {
Jamie Madille261b442014-06-25 12:42:21 -0400282 depthstencilbuffer = mStencilbuffer;
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000283 }
284
285 return depthstencilbuffer;
286}
287
Jamie Madill3c7fa222014-06-05 13:08:51 -0400288FramebufferAttachment *Framebuffer::getReadColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000289{
290 // Will require more logic if glReadBuffers is supported
Jamie Madille261b442014-06-25 12:42:21 -0400291 return mColorbuffers[0];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000292}
293
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000294GLenum Framebuffer::getReadColorbufferType() const
295{
296 // Will require more logic if glReadBuffers is supported
Jamie Madille261b442014-06-25 12:42:21 -0400297 return (mColorbuffers[0] ? mColorbuffers[0]->type() : GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000298}
299
Jamie Madill3c7fa222014-06-05 13:08:51 -0400300FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000301{
302 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
303 {
Jamie Madille261b442014-06-25 12:42:21 -0400304 if (mColorbuffers[colorAttachment])
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000305 {
Jamie Madille261b442014-06-25 12:42:21 -0400306 return mColorbuffers[colorAttachment];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000307 }
308 }
309
310 return NULL;
311}
312
Jamie Madille92a3542014-07-03 10:38:58 -0400313FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000314{
Jamie Madille92a3542014-07-03 10:38:58 -0400315 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
316 {
317 return getColorbuffer(attachment - GL_COLOR_ATTACHMENT0);
318 }
319 else
320 {
321 switch (attachment)
322 {
323 case GL_DEPTH_ATTACHMENT:
324 return getDepthbuffer();
325 case GL_STENCIL_ATTACHMENT:
326 return getStencilbuffer();
327 case GL_DEPTH_STENCIL_ATTACHMENT:
328 return getDepthStencilBuffer();
329 default:
330 UNREACHABLE();
331 return NULL;
332 }
333 }
Geoff Lang55ba29c2013-07-11 16:57:53 -0400334}
335
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000336GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const
337{
338 return mDrawBufferStates[colorAttachment];
339}
340
341void Framebuffer::setDrawBufferState(unsigned int colorAttachment, GLenum drawBuffer)
342{
343 mDrawBufferStates[colorAttachment] = drawBuffer;
344}
345
shannon.woods%transgaming.com@gtempaccount.comdae24092013-04-13 03:31:31 +0000346bool Framebuffer::isEnabledColorAttachment(unsigned int colorAttachment) const
347{
Jamie Madille261b442014-06-25 12:42:21 -0400348 return (mColorbuffers[colorAttachment] && mDrawBufferStates[colorAttachment] != GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comdae24092013-04-13 03:31:31 +0000349}
350
351bool Framebuffer::hasEnabledColorAttachment() const
352{
353 for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
354 {
355 if (isEnabledColorAttachment(colorAttachment))
356 {
357 return true;
358 }
359 }
360
361 return false;
362}
363
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000364bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000365{
Geoff Lange4a492b2014-06-19 14:14:41 -0400366 return (mStencilbuffer && mStencilbuffer->getStencilSize() > 0);
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000367}
368
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000369bool Framebuffer::usingExtendedDrawBuffers() const
370{
371 for (unsigned int colorAttachment = 1; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
372 {
373 if (isEnabledColorAttachment(colorAttachment))
374 {
375 return true;
376 }
377 }
378
379 return false;
380}
381
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000382GLenum Framebuffer::completeness() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000383{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000384 int width = 0;
385 int height = 0;
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000386 unsigned int colorbufferSize = 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000387 int samples = -1;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000388 bool missingAttachment = true;
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000389 GLuint clientVersion = mRenderer->getCurrentClientVersion();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000390
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000391 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000392 {
Jamie Madillbb94f342014-06-23 15:23:02 -0400393 const FramebufferAttachment *colorbuffer = mColorbuffers[colorAttachment];
394
395 if (colorbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000396 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000397 if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000398 {
399 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
400 }
daniel@transgaming.com01868132010-08-24 19:21:17 +0000401
Geoff Langcec35902014-04-16 10:52:36 -0400402 GLenum internalformat = colorbuffer->getInternalFormat();
Geoff Langc0b9ef42014-07-02 10:02:37 -0400403 // TODO(geofflang): use context's texture caps
404 const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400405 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madillbb94f342014-06-23 15:23:02 -0400406 if (colorbuffer->isTexture())
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000407 {
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400408 if (!formatCaps.renderable)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000409 {
410 return GL_FRAMEBUFFER_UNSUPPORTED;
411 }
412
Geoff Lang5d601382014-07-22 15:14:06 -0400413 if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000414 {
415 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
416 }
417 }
418 else
419 {
Geoff Lang5d601382014-07-22 15:14:06 -0400420 if (!formatCaps.renderable || formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400421 {
422 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
423 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000424 }
425
426 if (!missingAttachment)
427 {
428 // all color attachments must have the same width and height
429 if (colorbuffer->getWidth() != width || colorbuffer->getHeight() != height)
430 {
431 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
432 }
433
434 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
435 // all color attachments have the same number of samples for the FBO to be complete.
436 if (colorbuffer->getSamples() != samples)
437 {
438 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
439 }
440
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000441 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
442 // in GLES 3.0, there is no such restriction
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000443 if (clientVersion < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000444 {
Geoff Lang5d601382014-07-22 15:14:06 -0400445 if (formatInfo.pixelBytes != colorbufferSize)
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000446 {
447 return GL_FRAMEBUFFER_UNSUPPORTED;
448 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000449 }
450
451 // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness
452 for (unsigned int previousColorAttachment = 0; previousColorAttachment < colorAttachment; previousColorAttachment++)
453 {
Jamie Madille92a3542014-07-03 10:38:58 -0400454 const FramebufferAttachment *previousAttachment = mColorbuffers[previousColorAttachment];
455
456 if (previousAttachment &&
457 (colorbuffer->id() == previousAttachment->id() &&
458 colorbuffer->type() == previousAttachment->type()))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000459 {
460 return GL_FRAMEBUFFER_UNSUPPORTED;
461 }
462 }
463 }
464 else
465 {
466 width = colorbuffer->getWidth();
467 height = colorbuffer->getHeight();
468 samples = colorbuffer->getSamples();
Geoff Lang5d601382014-07-22 15:14:06 -0400469 colorbufferSize = formatInfo.pixelBytes;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000470 missingAttachment = false;
471 }
472 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000473 }
474
Jamie Madille261b442014-06-25 12:42:21 -0400475 if (mDepthbuffer)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000476 {
Jamie Madille261b442014-06-25 12:42:21 -0400477 if (mDepthbuffer->getWidth() == 0 || mDepthbuffer->getHeight() == 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000478 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000479 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000480 }
481
Jamie Madille261b442014-06-25 12:42:21 -0400482 GLenum internalformat = mDepthbuffer->getInternalFormat();
Geoff Langc0b9ef42014-07-02 10:02:37 -0400483 // TODO(geofflang): use context's texture caps
484 const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400485 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madillbb94f342014-06-23 15:23:02 -0400486 if (mDepthbuffer->isTexture())
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000487 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000488 // depth texture attachments require OES/ANGLE_depth_texture
Geoff Langc0b9ef42014-07-02 10:02:37 -0400489 // TODO(geofflang): use context's extensions
490 if (!mRenderer->getRendererExtensions().depthTextures)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000491 {
492 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
493 }
494
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400495 if (!formatCaps.renderable)
Geoff Langcec35902014-04-16 10:52:36 -0400496 {
497 return GL_FRAMEBUFFER_UNSUPPORTED;
498 }
499
Geoff Lang5d601382014-07-22 15:14:06 -0400500 if (formatInfo.depthBits == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000501 {
502 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
503 }
504 }
505 else
506 {
Geoff Lang5d601382014-07-22 15:14:06 -0400507 if (!formatCaps.renderable || formatInfo.depthBits == 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400508 {
509 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
510 }
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000511 }
512
513 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000514 {
Jamie Madille261b442014-06-25 12:42:21 -0400515 width = mDepthbuffer->getWidth();
516 height = mDepthbuffer->getHeight();
517 samples = mDepthbuffer->getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000518 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000519 }
Jamie Madille261b442014-06-25 12:42:21 -0400520 else if (width != mDepthbuffer->getWidth() || height != mDepthbuffer->getHeight())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000521 {
522 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
523 }
Jamie Madille261b442014-06-25 12:42:21 -0400524 else if (samples != mDepthbuffer->getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000525 {
526 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
527 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000528 }
529
Jamie Madille261b442014-06-25 12:42:21 -0400530 if (mStencilbuffer)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000531 {
Jamie Madille261b442014-06-25 12:42:21 -0400532 if (mStencilbuffer->getWidth() == 0 || mStencilbuffer->getHeight() == 0)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000533 {
534 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
535 }
536
Jamie Madille261b442014-06-25 12:42:21 -0400537 GLenum internalformat = mStencilbuffer->getInternalFormat();
Geoff Langc0b9ef42014-07-02 10:02:37 -0400538 // TODO(geofflang): use context's texture caps
539 const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400540 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madillbb94f342014-06-23 15:23:02 -0400541 if (mStencilbuffer->isTexture())
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000542 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000543 // texture stencil attachments come along as part
544 // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
Geoff Langc0b9ef42014-07-02 10:02:37 -0400545 // TODO(geofflang): use context's extensions
546 if (!mRenderer->getRendererExtensions().depthTextures)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000547 {
548 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
549 }
550
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400551 if (!formatCaps.renderable)
Geoff Langcec35902014-04-16 10:52:36 -0400552 {
553 return GL_FRAMEBUFFER_UNSUPPORTED;
554 }
555
Geoff Lang5d601382014-07-22 15:14:06 -0400556 if (formatInfo.stencilBits == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000557 {
558 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
559 }
560 }
561 else
562 {
Geoff Lang5d601382014-07-22 15:14:06 -0400563 if (!formatCaps.renderable || formatInfo.stencilBits == 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400564 {
565 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
566 }
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000567 }
568
569 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000570 {
Jamie Madille261b442014-06-25 12:42:21 -0400571 width = mStencilbuffer->getWidth();
572 height = mStencilbuffer->getHeight();
573 samples = mStencilbuffer->getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000574 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000575 }
Jamie Madille261b442014-06-25 12:42:21 -0400576 else if (width != mStencilbuffer->getWidth() || height != mStencilbuffer->getHeight())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000577 {
578 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
579 }
Jamie Madille261b442014-06-25 12:42:21 -0400580 else if (samples != mStencilbuffer->getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000581 {
582 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
583 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000584 }
585
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000586 // if we have both a depth and stencil buffer, they must refer to the same object
587 // since we only support packed_depth_stencil and not separate depth and stencil
Jamie Madille261b442014-06-25 12:42:21 -0400588 if (mDepthbuffer && mStencilbuffer && !hasValidDepthStencil())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000589 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000590 return GL_FRAMEBUFFER_UNSUPPORTED;
591 }
592
593 // we need to have at least one attachment to be complete
594 if (missingAttachment)
595 {
596 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000597 }
598
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000599 return GL_FRAMEBUFFER_COMPLETE;
600}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000601
Jamie Madill2d96b9e2014-08-29 15:46:47 -0400602void Framebuffer::invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments)
603{
604 GLuint maxDimension = caps.maxRenderbufferSize;
605 invalidateSub(caps, numAttachments, attachments, 0, 0, maxDimension, maxDimension);
606}
607
608void Framebuffer::invalidateSub(const Caps &caps, GLsizei numAttachments, const GLenum *attachments,
609 GLint x, GLint y, GLsizei width, GLsizei height)
Jamie Madill400a4412014-08-29 15:46:45 -0400610{
611 ASSERT(completeness() == GL_FRAMEBUFFER_COMPLETE);
Jamie Madill6d708262014-09-03 15:07:13 -0400612 for (GLsizei attachIndex = 0; attachIndex < numAttachments; ++attachIndex)
Jamie Madill400a4412014-08-29 15:46:45 -0400613 {
Jamie Madill6d708262014-09-03 15:07:13 -0400614 GLenum attachmentTarget = attachments[attachIndex];
Jamie Madill400a4412014-08-29 15:46:45 -0400615
Jamie Madill6d708262014-09-03 15:07:13 -0400616 gl::FramebufferAttachment *attachment =
617 (attachmentTarget == GL_DEPTH_STENCIL_ATTACHMENT) ? getDepthOrStencilbuffer() :
618 getAttachment(attachmentTarget);
Jamie Madill400a4412014-08-29 15:46:45 -0400619
Jamie Madill6d708262014-09-03 15:07:13 -0400620 if (attachment)
Jamie Madill400a4412014-08-29 15:46:45 -0400621 {
Jamie Madill9f0b42a2014-09-12 10:25:27 -0400622 rx::RenderTarget *renderTarget = rx::GetAttachmentRenderTarget(attachment);
Jamie Madill6d708262014-09-03 15:07:13 -0400623 if (renderTarget)
624 {
625 renderTarget->invalidate(x, y, width, height);
626 }
Jamie Madill400a4412014-08-29 15:46:45 -0400627 }
628 }
629}
630
daniel@transgaming.com16418b12012-11-28 19:32:22 +0000631DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
Shannon Woodsaa2ab7d2014-06-24 17:51:51 -0400632 : Framebuffer(renderer, 0)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000633{
Geoff Lange4a492b2014-06-19 14:14:41 -0400634 Renderbuffer *colorRenderbuffer = new Renderbuffer(0, colorbuffer);
Jamie Madillaef95de2014-09-05 10:12:41 -0400635 mColorbuffers[0] = new RenderbufferAttachment(GL_BACK, colorRenderbuffer);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000636
Jamie Madill28bedaf2014-06-26 13:17:22 -0400637 Renderbuffer *depthStencilBuffer = new Renderbuffer(0, depthStencil);
638
639 // Make a new attachment objects to ensure we do not double-delete
640 // See angle issue 686
Jamie Madillaef95de2014-09-05 10:12:41 -0400641 mDepthbuffer = (depthStencilBuffer->getDepthSize() != 0 ? new RenderbufferAttachment(GL_DEPTH_ATTACHMENT, depthStencilBuffer) : NULL);
642 mStencilbuffer = (depthStencilBuffer->getStencilSize() != 0 ? new RenderbufferAttachment(GL_STENCIL_ATTACHMENT, depthStencilBuffer) : NULL);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000643
644 mDrawBufferStates[0] = GL_BACK;
645 mReadBufferState = GL_BACK;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000646}
647
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000648int Framebuffer::getSamples() const
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000649{
650 if (completeness() == GL_FRAMEBUFFER_COMPLETE)
651 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000652 // for a complete framebuffer, all attachments must have the same sample count
653 // in this case return the first nonzero sample size
654 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
655 {
Jamie Madille261b442014-06-25 12:42:21 -0400656 if (mColorbuffers[colorAttachment])
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000657 {
Jamie Madille261b442014-06-25 12:42:21 -0400658 return mColorbuffers[colorAttachment]->getSamples();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000659 }
660 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000661 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000662
663 return 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000664}
665
Jamie Madille261b442014-06-25 12:42:21 -0400666bool Framebuffer::hasValidDepthStencil() const
667{
668 // A valid depth-stencil attachment has the same resource bound to both the
669 // depth and stencil attachment points.
670 return (mDepthbuffer && mStencilbuffer &&
671 mDepthbuffer->type() == mStencilbuffer->type() &&
672 mDepthbuffer->id() == mStencilbuffer->id());
673}
674
Jamie Madillce20c7f2014-09-03 11:56:29 -0400675ColorbufferInfo Framebuffer::getColorbuffersForRender() const
676{
677 ColorbufferInfo colorbuffersForRender;
678
679 for (size_t colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; ++colorAttachment)
680 {
681 GLenum drawBufferState = mDrawBufferStates[colorAttachment];
682 FramebufferAttachment *colorbuffer = mColorbuffers[colorAttachment];
683
684 if (colorbuffer != NULL && drawBufferState != GL_NONE)
685 {
686 ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + colorAttachment));
687 colorbuffersForRender.push_back(colorbuffer);
688 }
Jamie Madill3f2e61d2014-09-05 10:38:05 -0400689#if (ANGLE_MRT_PERF_WORKAROUND == ANGLE_WORKAROUND_DISABLED)
Jamie Madillce20c7f2014-09-03 11:56:29 -0400690 else
691 {
692 colorbuffersForRender.push_back(NULL);
693 }
Jamie Madill3f2e61d2014-09-05 10:38:05 -0400694#endif
Jamie Madillce20c7f2014-09-03 11:56:29 -0400695 }
696
697 return colorbuffersForRender;
698}
699
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000700GLenum DefaultFramebuffer::completeness() const
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000701{
shannon.woods@transgaming.com3e3da582013-02-28 23:09:03 +0000702 // The default framebuffer *must* always be complete, though it may not be
703 // subject to the same rules as application FBOs. ie, it could have 0x0 size.
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000704 return GL_FRAMEBUFFER_COMPLETE;
705}
706
Jamie Madille92a3542014-07-03 10:38:58 -0400707FramebufferAttachment *DefaultFramebuffer::getAttachment(GLenum attachment) const
708{
709 switch (attachment)
710 {
Jamie Madill6d708262014-09-03 15:07:13 -0400711 case GL_COLOR:
Jamie Madille92a3542014-07-03 10:38:58 -0400712 case GL_BACK:
713 return getColorbuffer(0);
714 case GL_DEPTH:
715 return getDepthbuffer();
716 case GL_STENCIL:
717 return getStencilbuffer();
718 case GL_DEPTH_STENCIL:
719 return getDepthStencilBuffer();
720 default:
721 UNREACHABLE();
722 return NULL;
723 }
724}
725
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000726}