blob: 64617a5341a126658ebed1225101bb611ac98cb6 [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 Madillac7579c2014-09-17 16:59:33 -040032 const gl::ImageIndex *index = attachment->getTextureImageIndex();
33 ASSERT(index);
34 return textureD3D->getRenderTarget(*index);
Jamie Madill9f0b42a2014-09-12 10:25:27 -040035 }
36
37 gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
38 ASSERT(renderbuffer);
39
40 // TODO: cast to RenderbufferD3D
41 return renderbuffer->getStorage()->getRenderTarget();
42}
43
Jamie Madill612e2e42014-09-12 13:26:55 -040044// Note: RenderTarget serials should ideally be in the RenderTargets themselves.
45unsigned int GetAttachmentSerial(gl::FramebufferAttachment *attachment)
46{
47 if (attachment->isTexture())
48 {
49 gl::Texture *texture = attachment->getTexture();
50 ASSERT(texture);
51 TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
Jamie Madillac7579c2014-09-17 16:59:33 -040052 const gl::ImageIndex *index = attachment->getTextureImageIndex();
53 ASSERT(index);
54 return textureD3D->getRenderTargetSerial(*index);
Jamie Madill612e2e42014-09-12 13:26:55 -040055 }
56
57 gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
58 ASSERT(renderbuffer);
59
60 // TODO: cast to RenderbufferD3D
61 return renderbuffer->getStorage()->getSerial();
62}
63
Jamie Madill9f0b42a2014-09-12 10:25:27 -040064}
65
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000066namespace gl
67{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000068
Shannon Woodsaa2ab7d2014-06-24 17:51:51 -040069Framebuffer::Framebuffer(rx::Renderer *renderer, GLuint id)
Jamie Madille261b442014-06-25 12:42:21 -040070 : mRenderer(renderer),
Shannon Woodsaa2ab7d2014-06-24 17:51:51 -040071 mId(id),
Jamie Madille261b442014-06-25 12:42:21 -040072 mReadBufferState(GL_COLOR_ATTACHMENT0_EXT),
73 mDepthbuffer(NULL),
74 mStencilbuffer(NULL)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000075{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000076 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
77 {
Jamie Madille261b442014-06-25 12:42:21 -040078 mColorbuffers[colorAttachment] = NULL;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000079 mDrawBufferStates[colorAttachment] = GL_NONE;
80 }
81 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000082}
83
84Framebuffer::~Framebuffer()
85{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000086 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
87 {
Jamie Madille261b442014-06-25 12:42:21 -040088 SafeDelete(mColorbuffers[colorAttachment]);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000089 }
Jamie Madille261b442014-06-25 12:42:21 -040090 SafeDelete(mDepthbuffer);
91 SafeDelete(mStencilbuffer);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000092}
93
Jamie Madillaef95de2014-09-05 10:12:41 -040094FramebufferAttachment *Framebuffer::createAttachment(GLenum binding, GLenum type, GLuint handle, GLint level, GLint layer) const
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000095{
Jamie Madill6c7b4ad2014-06-16 10:33:59 -040096 if (handle == 0)
97 {
98 return NULL;
99 }
100
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000101 gl::Context *context = gl::getContext();
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000102
Geoff Lang309c92a2013-07-25 16:23:19 -0400103 switch (type)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000104 {
Geoff Lang309c92a2013-07-25 16:23:19 -0400105 case GL_NONE:
106 return NULL;
107
108 case GL_RENDERBUFFER:
Jamie Madillaef95de2014-09-05 10:12:41 -0400109 return new RenderbufferAttachment(binding, context->getRenderbuffer(handle));
Geoff Lang309c92a2013-07-25 16:23:19 -0400110
111 case GL_TEXTURE_2D:
112 {
113 Texture *texture = context->getTexture(handle);
114 if (texture && texture->getTarget() == GL_TEXTURE_2D)
115 {
Jamie Madilleeb7b0e2014-09-03 15:07:20 -0400116 return new TextureAttachment(binding, texture, ImageIndex::Make2D(level));
Geoff Lang309c92a2013-07-25 16:23:19 -0400117 }
118 else
119 {
120 return NULL;
121 }
122 }
123
124 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
125 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
126 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
127 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
128 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
129 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
130 {
131 Texture *texture = context->getTexture(handle);
132 if (texture && texture->getTarget() == GL_TEXTURE_CUBE_MAP)
133 {
Jamie Madilleeb7b0e2014-09-03 15:07:20 -0400134 return new TextureAttachment(binding, texture, ImageIndex::MakeCube(type, level));
Geoff Lang309c92a2013-07-25 16:23:19 -0400135 }
136 else
137 {
138 return NULL;
139 }
140 }
141
142 case GL_TEXTURE_3D:
143 {
144 Texture *texture = context->getTexture(handle);
145 if (texture && texture->getTarget() == GL_TEXTURE_3D)
146 {
Jamie Madilleeb7b0e2014-09-03 15:07:20 -0400147 return new TextureAttachment(binding, texture, ImageIndex::Make3D(level, layer));
Geoff Lang309c92a2013-07-25 16:23:19 -0400148 }
149 else
150 {
151 return NULL;
152 }
153 }
154
155 case GL_TEXTURE_2D_ARRAY:
156 {
157 Texture *texture = context->getTexture(handle);
158 if (texture && texture->getTarget() == GL_TEXTURE_2D_ARRAY)
159 {
Jamie Madilleeb7b0e2014-09-03 15:07:20 -0400160 return new TextureAttachment(binding, texture, ImageIndex::Make2DArray(level, layer));
Geoff Lang309c92a2013-07-25 16:23:19 -0400161 }
162 else
163 {
164 return NULL;
165 }
166 }
167
168 default:
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000169 UNREACHABLE();
Geoff Lang309c92a2013-07-25 16:23:19 -0400170 return NULL;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000171 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000172}
173
Geoff Lang309c92a2013-07-25 16:23:19 -0400174void Framebuffer::setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer, GLint level, GLint layer)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000175{
176 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
Jamie Madille261b442014-06-25 12:42:21 -0400177 SafeDelete(mColorbuffers[colorAttachment]);
Jamie Madillaef95de2014-09-05 10:12:41 -0400178 GLenum binding = colorAttachment + GL_COLOR_ATTACHMENT0;
179 mColorbuffers[colorAttachment] = createAttachment(binding, type, colorbuffer, level, layer);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000180}
181
Geoff Lang309c92a2013-07-25 16:23:19 -0400182void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level, GLint layer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000183{
Jamie Madille261b442014-06-25 12:42:21 -0400184 SafeDelete(mDepthbuffer);
Jamie Madillaef95de2014-09-05 10:12:41 -0400185 mDepthbuffer = createAttachment(GL_DEPTH_ATTACHMENT, type, depthbuffer, level, layer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000186}
187
Geoff Lang309c92a2013-07-25 16:23:19 -0400188void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level, GLint layer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000189{
Jamie Madille261b442014-06-25 12:42:21 -0400190 SafeDelete(mStencilbuffer);
Jamie Madillaef95de2014-09-05 10:12:41 -0400191 mStencilbuffer = createAttachment(GL_STENCIL_ATTACHMENT, type, stencilbuffer, level, layer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000192}
193
Geoff Lang309c92a2013-07-25 16:23:19 -0400194void Framebuffer::setDepthStencilBuffer(GLenum type, GLuint depthStencilBuffer, GLint level, GLint layer)
Geoff Lang55ba29c2013-07-11 16:57:53 -0400195{
Jamie Madillaef95de2014-09-05 10:12:41 -0400196 FramebufferAttachment *attachment = createAttachment(GL_DEPTH_STENCIL_ATTACHMENT, type, depthStencilBuffer, level, layer);
Jamie Madill6c7b4ad2014-06-16 10:33:59 -0400197
Jamie Madille261b442014-06-25 12:42:21 -0400198 SafeDelete(mDepthbuffer);
199 SafeDelete(mStencilbuffer);
200
201 // ensure this is a legitimate depth+stencil format
Geoff Lange4a492b2014-06-19 14:14:41 -0400202 if (attachment && attachment->getDepthSize() > 0 && attachment->getStencilSize() > 0)
Geoff Lang55ba29c2013-07-11 16:57:53 -0400203 {
Jamie Madille261b442014-06-25 12:42:21 -0400204 mDepthbuffer = attachment;
Jamie Madill28bedaf2014-06-26 13:17:22 -0400205
206 // Make a new attachment object to ensure we do not double-delete
207 // See angle issue 686
Jamie Madillaef95de2014-09-05 10:12:41 -0400208 mStencilbuffer = createAttachment(GL_DEPTH_STENCIL_ATTACHMENT, type, depthStencilBuffer, level, layer);
Geoff Lang55ba29c2013-07-11 16:57:53 -0400209 }
210}
211
Jamie Madille261b442014-06-25 12:42:21 -0400212void Framebuffer::detachTexture(GLuint textureId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000213{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000214 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000215 {
Jamie Madille261b442014-06-25 12:42:21 -0400216 FramebufferAttachment *attachment = mColorbuffers[colorAttachment];
217
218 if (attachment && attachment->isTextureWithId(textureId))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000219 {
Jamie Madille261b442014-06-25 12:42:21 -0400220 SafeDelete(mColorbuffers[colorAttachment]);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000221 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000222 }
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000223
Jamie Madille261b442014-06-25 12:42:21 -0400224 if (mDepthbuffer && mDepthbuffer->isTextureWithId(textureId))
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000225 {
Jamie Madille261b442014-06-25 12:42:21 -0400226 SafeDelete(mDepthbuffer);
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000227 }
228
Jamie Madille261b442014-06-25 12:42:21 -0400229 if (mStencilbuffer && mStencilbuffer->isTextureWithId(textureId))
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000230 {
Jamie Madille261b442014-06-25 12:42:21 -0400231 SafeDelete(mStencilbuffer);
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000232 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000233}
234
Jamie Madille261b442014-06-25 12:42:21 -0400235void Framebuffer::detachRenderbuffer(GLuint renderbufferId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000236{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000237 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000238 {
Jamie Madille261b442014-06-25 12:42:21 -0400239 FramebufferAttachment *attachment = mColorbuffers[colorAttachment];
240
241 if (attachment && attachment->isRenderbufferWithId(renderbufferId))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000242 {
Jamie Madille261b442014-06-25 12:42:21 -0400243 SafeDelete(mColorbuffers[colorAttachment]);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000244 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000245 }
246
Jamie Madille261b442014-06-25 12:42:21 -0400247 if (mDepthbuffer && mDepthbuffer->isRenderbufferWithId(renderbufferId))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000248 {
Jamie Madille261b442014-06-25 12:42:21 -0400249 SafeDelete(mDepthbuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000250 }
251
Jamie Madille261b442014-06-25 12:42:21 -0400252 if (mStencilbuffer && mStencilbuffer->isRenderbufferWithId(renderbufferId))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000253 {
Jamie Madille261b442014-06-25 12:42:21 -0400254 SafeDelete(mStencilbuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000255 }
256}
257
Jamie Madill3c7fa222014-06-05 13:08:51 -0400258FramebufferAttachment *Framebuffer::getColorbuffer(unsigned int colorAttachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000259{
260 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
Jamie Madille261b442014-06-25 12:42:21 -0400261 return mColorbuffers[colorAttachment];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000262}
263
Jamie Madill3c7fa222014-06-05 13:08:51 -0400264FramebufferAttachment *Framebuffer::getDepthbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000265{
Jamie Madille261b442014-06-25 12:42:21 -0400266 return mDepthbuffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000267}
268
Jamie Madill3c7fa222014-06-05 13:08:51 -0400269FramebufferAttachment *Framebuffer::getStencilbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000270{
Jamie Madille261b442014-06-25 12:42:21 -0400271 return mStencilbuffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000272}
273
Jamie Madill3c7fa222014-06-05 13:08:51 -0400274FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
Geoff Lang646559f2013-08-15 11:08:15 -0400275{
Jamie Madille261b442014-06-25 12:42:21 -0400276 return (hasValidDepthStencil() ? mDepthbuffer : NULL);
Geoff Lang646559f2013-08-15 11:08:15 -0400277}
278
Jamie Madill3c7fa222014-06-05 13:08:51 -0400279FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000280{
Jamie Madille261b442014-06-25 12:42:21 -0400281 FramebufferAttachment *depthstencilbuffer = mDepthbuffer;
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000282
283 if (!depthstencilbuffer)
284 {
Jamie Madille261b442014-06-25 12:42:21 -0400285 depthstencilbuffer = mStencilbuffer;
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000286 }
287
288 return depthstencilbuffer;
289}
290
Jamie Madill3c7fa222014-06-05 13:08:51 -0400291FramebufferAttachment *Framebuffer::getReadColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000292{
293 // Will require more logic if glReadBuffers is supported
Jamie Madille261b442014-06-25 12:42:21 -0400294 return mColorbuffers[0];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000295}
296
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000297GLenum Framebuffer::getReadColorbufferType() const
298{
299 // Will require more logic if glReadBuffers is supported
Jamie Madille261b442014-06-25 12:42:21 -0400300 return (mColorbuffers[0] ? mColorbuffers[0]->type() : GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000301}
302
Jamie Madill3c7fa222014-06-05 13:08:51 -0400303FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000304{
305 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
306 {
Jamie Madille261b442014-06-25 12:42:21 -0400307 if (mColorbuffers[colorAttachment])
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000308 {
Jamie Madille261b442014-06-25 12:42:21 -0400309 return mColorbuffers[colorAttachment];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000310 }
311 }
312
313 return NULL;
314}
315
Jamie Madille92a3542014-07-03 10:38:58 -0400316FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000317{
Jamie Madille92a3542014-07-03 10:38:58 -0400318 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
319 {
320 return getColorbuffer(attachment - GL_COLOR_ATTACHMENT0);
321 }
322 else
323 {
324 switch (attachment)
325 {
326 case GL_DEPTH_ATTACHMENT:
327 return getDepthbuffer();
328 case GL_STENCIL_ATTACHMENT:
329 return getStencilbuffer();
330 case GL_DEPTH_STENCIL_ATTACHMENT:
331 return getDepthStencilBuffer();
332 default:
333 UNREACHABLE();
334 return NULL;
335 }
336 }
Geoff Lang55ba29c2013-07-11 16:57:53 -0400337}
338
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000339GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const
340{
341 return mDrawBufferStates[colorAttachment];
342}
343
344void Framebuffer::setDrawBufferState(unsigned int colorAttachment, GLenum drawBuffer)
345{
346 mDrawBufferStates[colorAttachment] = drawBuffer;
347}
348
shannon.woods%transgaming.com@gtempaccount.comdae24092013-04-13 03:31:31 +0000349bool Framebuffer::isEnabledColorAttachment(unsigned int colorAttachment) const
350{
Jamie Madille261b442014-06-25 12:42:21 -0400351 return (mColorbuffers[colorAttachment] && mDrawBufferStates[colorAttachment] != GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comdae24092013-04-13 03:31:31 +0000352}
353
354bool Framebuffer::hasEnabledColorAttachment() const
355{
356 for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
357 {
358 if (isEnabledColorAttachment(colorAttachment))
359 {
360 return true;
361 }
362 }
363
364 return false;
365}
366
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000367bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000368{
Geoff Lange4a492b2014-06-19 14:14:41 -0400369 return (mStencilbuffer && mStencilbuffer->getStencilSize() > 0);
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000370}
371
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000372bool Framebuffer::usingExtendedDrawBuffers() const
373{
374 for (unsigned int colorAttachment = 1; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
375 {
376 if (isEnabledColorAttachment(colorAttachment))
377 {
378 return true;
379 }
380 }
381
382 return false;
383}
384
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000385GLenum Framebuffer::completeness() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000386{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000387 int width = 0;
388 int height = 0;
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000389 unsigned int colorbufferSize = 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000390 int samples = -1;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000391 bool missingAttachment = true;
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000392 GLuint clientVersion = mRenderer->getCurrentClientVersion();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000393
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000394 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000395 {
Jamie Madillbb94f342014-06-23 15:23:02 -0400396 const FramebufferAttachment *colorbuffer = mColorbuffers[colorAttachment];
397
398 if (colorbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000399 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000400 if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000401 {
402 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
403 }
daniel@transgaming.com01868132010-08-24 19:21:17 +0000404
Geoff Langcec35902014-04-16 10:52:36 -0400405 GLenum internalformat = colorbuffer->getInternalFormat();
Geoff Langc0b9ef42014-07-02 10:02:37 -0400406 // TODO(geofflang): use context's texture caps
407 const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400408 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madillbb94f342014-06-23 15:23:02 -0400409 if (colorbuffer->isTexture())
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000410 {
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400411 if (!formatCaps.renderable)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000412 {
413 return GL_FRAMEBUFFER_UNSUPPORTED;
414 }
415
Geoff Lang5d601382014-07-22 15:14:06 -0400416 if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000417 {
418 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
419 }
420 }
421 else
422 {
Geoff Lang5d601382014-07-22 15:14:06 -0400423 if (!formatCaps.renderable || formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400424 {
425 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
426 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000427 }
428
429 if (!missingAttachment)
430 {
431 // all color attachments must have the same width and height
432 if (colorbuffer->getWidth() != width || colorbuffer->getHeight() != height)
433 {
434 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
435 }
436
437 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
438 // all color attachments have the same number of samples for the FBO to be complete.
439 if (colorbuffer->getSamples() != samples)
440 {
441 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
442 }
443
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000444 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
445 // in GLES 3.0, there is no such restriction
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000446 if (clientVersion < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000447 {
Geoff Lang5d601382014-07-22 15:14:06 -0400448 if (formatInfo.pixelBytes != colorbufferSize)
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000449 {
450 return GL_FRAMEBUFFER_UNSUPPORTED;
451 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000452 }
453
454 // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness
455 for (unsigned int previousColorAttachment = 0; previousColorAttachment < colorAttachment; previousColorAttachment++)
456 {
Jamie Madille92a3542014-07-03 10:38:58 -0400457 const FramebufferAttachment *previousAttachment = mColorbuffers[previousColorAttachment];
458
459 if (previousAttachment &&
460 (colorbuffer->id() == previousAttachment->id() &&
461 colorbuffer->type() == previousAttachment->type()))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000462 {
463 return GL_FRAMEBUFFER_UNSUPPORTED;
464 }
465 }
466 }
467 else
468 {
469 width = colorbuffer->getWidth();
470 height = colorbuffer->getHeight();
471 samples = colorbuffer->getSamples();
Geoff Lang5d601382014-07-22 15:14:06 -0400472 colorbufferSize = formatInfo.pixelBytes;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000473 missingAttachment = false;
474 }
475 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000476 }
477
Jamie Madille261b442014-06-25 12:42:21 -0400478 if (mDepthbuffer)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000479 {
Jamie Madille261b442014-06-25 12:42:21 -0400480 if (mDepthbuffer->getWidth() == 0 || mDepthbuffer->getHeight() == 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000481 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000482 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000483 }
484
Jamie Madille261b442014-06-25 12:42:21 -0400485 GLenum internalformat = mDepthbuffer->getInternalFormat();
Geoff Langc0b9ef42014-07-02 10:02:37 -0400486 // TODO(geofflang): use context's texture caps
487 const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400488 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madillbb94f342014-06-23 15:23:02 -0400489 if (mDepthbuffer->isTexture())
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000490 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000491 // depth texture attachments require OES/ANGLE_depth_texture
Geoff Langc0b9ef42014-07-02 10:02:37 -0400492 // TODO(geofflang): use context's extensions
493 if (!mRenderer->getRendererExtensions().depthTextures)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000494 {
495 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
496 }
497
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400498 if (!formatCaps.renderable)
Geoff Langcec35902014-04-16 10:52:36 -0400499 {
500 return GL_FRAMEBUFFER_UNSUPPORTED;
501 }
502
Geoff Lang5d601382014-07-22 15:14:06 -0400503 if (formatInfo.depthBits == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000504 {
505 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
506 }
507 }
508 else
509 {
Geoff Lang5d601382014-07-22 15:14:06 -0400510 if (!formatCaps.renderable || formatInfo.depthBits == 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400511 {
512 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
513 }
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000514 }
515
516 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000517 {
Jamie Madille261b442014-06-25 12:42:21 -0400518 width = mDepthbuffer->getWidth();
519 height = mDepthbuffer->getHeight();
520 samples = mDepthbuffer->getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000521 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000522 }
Jamie Madille261b442014-06-25 12:42:21 -0400523 else if (width != mDepthbuffer->getWidth() || height != mDepthbuffer->getHeight())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000524 {
525 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
526 }
Jamie Madille261b442014-06-25 12:42:21 -0400527 else if (samples != mDepthbuffer->getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000528 {
529 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
530 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000531 }
532
Jamie Madille261b442014-06-25 12:42:21 -0400533 if (mStencilbuffer)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000534 {
Jamie Madille261b442014-06-25 12:42:21 -0400535 if (mStencilbuffer->getWidth() == 0 || mStencilbuffer->getHeight() == 0)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000536 {
537 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
538 }
539
Jamie Madille261b442014-06-25 12:42:21 -0400540 GLenum internalformat = mStencilbuffer->getInternalFormat();
Geoff Langc0b9ef42014-07-02 10:02:37 -0400541 // TODO(geofflang): use context's texture caps
542 const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400543 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madillbb94f342014-06-23 15:23:02 -0400544 if (mStencilbuffer->isTexture())
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000545 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000546 // texture stencil attachments come along as part
547 // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
Geoff Langc0b9ef42014-07-02 10:02:37 -0400548 // TODO(geofflang): use context's extensions
549 if (!mRenderer->getRendererExtensions().depthTextures)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000550 {
551 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
552 }
553
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400554 if (!formatCaps.renderable)
Geoff Langcec35902014-04-16 10:52:36 -0400555 {
556 return GL_FRAMEBUFFER_UNSUPPORTED;
557 }
558
Geoff Lang5d601382014-07-22 15:14:06 -0400559 if (formatInfo.stencilBits == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000560 {
561 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
562 }
563 }
564 else
565 {
Geoff Lang5d601382014-07-22 15:14:06 -0400566 if (!formatCaps.renderable || formatInfo.stencilBits == 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400567 {
568 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
569 }
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000570 }
571
572 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000573 {
Jamie Madille261b442014-06-25 12:42:21 -0400574 width = mStencilbuffer->getWidth();
575 height = mStencilbuffer->getHeight();
576 samples = mStencilbuffer->getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000577 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000578 }
Jamie Madille261b442014-06-25 12:42:21 -0400579 else if (width != mStencilbuffer->getWidth() || height != mStencilbuffer->getHeight())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000580 {
581 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
582 }
Jamie Madille261b442014-06-25 12:42:21 -0400583 else if (samples != mStencilbuffer->getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000584 {
585 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
586 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000587 }
588
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000589 // if we have both a depth and stencil buffer, they must refer to the same object
590 // since we only support packed_depth_stencil and not separate depth and stencil
Jamie Madille261b442014-06-25 12:42:21 -0400591 if (mDepthbuffer && mStencilbuffer && !hasValidDepthStencil())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000592 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000593 return GL_FRAMEBUFFER_UNSUPPORTED;
594 }
595
596 // we need to have at least one attachment to be complete
597 if (missingAttachment)
598 {
599 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000600 }
601
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000602 return GL_FRAMEBUFFER_COMPLETE;
603}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000604
Jamie Madill2d96b9e2014-08-29 15:46:47 -0400605void Framebuffer::invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments)
606{
607 GLuint maxDimension = caps.maxRenderbufferSize;
608 invalidateSub(caps, numAttachments, attachments, 0, 0, maxDimension, maxDimension);
609}
610
611void Framebuffer::invalidateSub(const Caps &caps, GLsizei numAttachments, const GLenum *attachments,
612 GLint x, GLint y, GLsizei width, GLsizei height)
Jamie Madill400a4412014-08-29 15:46:45 -0400613{
614 ASSERT(completeness() == GL_FRAMEBUFFER_COMPLETE);
Jamie Madill6d708262014-09-03 15:07:13 -0400615 for (GLsizei attachIndex = 0; attachIndex < numAttachments; ++attachIndex)
Jamie Madill400a4412014-08-29 15:46:45 -0400616 {
Jamie Madill6d708262014-09-03 15:07:13 -0400617 GLenum attachmentTarget = attachments[attachIndex];
Jamie Madill400a4412014-08-29 15:46:45 -0400618
Jamie Madill6d708262014-09-03 15:07:13 -0400619 gl::FramebufferAttachment *attachment =
620 (attachmentTarget == GL_DEPTH_STENCIL_ATTACHMENT) ? getDepthOrStencilbuffer() :
621 getAttachment(attachmentTarget);
Jamie Madill400a4412014-08-29 15:46:45 -0400622
Jamie Madill6d708262014-09-03 15:07:13 -0400623 if (attachment)
Jamie Madill400a4412014-08-29 15:46:45 -0400624 {
Jamie Madill9f0b42a2014-09-12 10:25:27 -0400625 rx::RenderTarget *renderTarget = rx::GetAttachmentRenderTarget(attachment);
Jamie Madill6d708262014-09-03 15:07:13 -0400626 if (renderTarget)
627 {
628 renderTarget->invalidate(x, y, width, height);
629 }
Jamie Madill400a4412014-08-29 15:46:45 -0400630 }
631 }
632}
633
daniel@transgaming.com16418b12012-11-28 19:32:22 +0000634DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, Colorbuffer *colorbuffer, DepthStencilbuffer *depthStencil)
Shannon Woodsaa2ab7d2014-06-24 17:51:51 -0400635 : Framebuffer(renderer, 0)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000636{
Geoff Lange4a492b2014-06-19 14:14:41 -0400637 Renderbuffer *colorRenderbuffer = new Renderbuffer(0, colorbuffer);
Jamie Madillaef95de2014-09-05 10:12:41 -0400638 mColorbuffers[0] = new RenderbufferAttachment(GL_BACK, colorRenderbuffer);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000639
Jamie Madill04ab0eb2014-11-22 23:07:51 -0500640 GLenum depthStencilActualFormat = depthStencil->getActualFormat();
641 const gl::InternalFormat &depthStencilFormatInfo = GetInternalFormatInfo(depthStencilActualFormat);
Jamie Madill28bedaf2014-06-26 13:17:22 -0400642
Jamie Madill04ab0eb2014-11-22 23:07:51 -0500643 if (depthStencilFormatInfo.depthBits != 0 || depthStencilFormatInfo.stencilBits != 0)
644 {
645 Renderbuffer *depthStencilBuffer = new Renderbuffer(0, depthStencil);
646
647 // Make a new attachment objects to ensure we do not double-delete
648 // See angle issue 686
649 mDepthbuffer = (depthStencilFormatInfo.depthBits != 0 ? new RenderbufferAttachment(GL_DEPTH_ATTACHMENT, depthStencilBuffer) : NULL);
650 mStencilbuffer = (depthStencilFormatInfo.stencilBits != 0 ? new RenderbufferAttachment(GL_STENCIL_ATTACHMENT, depthStencilBuffer) : NULL);
651 }
652 else
653 {
654 // This method transfers ownership, so delete the unused storage if we don't keep it.
655 SafeDelete(depthStencil);
656 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000657
658 mDrawBufferStates[0] = GL_BACK;
659 mReadBufferState = GL_BACK;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000660}
661
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000662int Framebuffer::getSamples() const
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000663{
664 if (completeness() == GL_FRAMEBUFFER_COMPLETE)
665 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000666 // for a complete framebuffer, all attachments must have the same sample count
667 // in this case return the first nonzero sample size
668 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
669 {
Jamie Madille261b442014-06-25 12:42:21 -0400670 if (mColorbuffers[colorAttachment])
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000671 {
Jamie Madille261b442014-06-25 12:42:21 -0400672 return mColorbuffers[colorAttachment]->getSamples();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000673 }
674 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000675 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000676
677 return 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000678}
679
Jamie Madille261b442014-06-25 12:42:21 -0400680bool Framebuffer::hasValidDepthStencil() const
681{
682 // A valid depth-stencil attachment has the same resource bound to both the
683 // depth and stencil attachment points.
684 return (mDepthbuffer && mStencilbuffer &&
685 mDepthbuffer->type() == mStencilbuffer->type() &&
686 mDepthbuffer->id() == mStencilbuffer->id());
687}
688
Jamie Madillce20c7f2014-09-03 11:56:29 -0400689ColorbufferInfo Framebuffer::getColorbuffersForRender() const
690{
691 ColorbufferInfo colorbuffersForRender;
692
693 for (size_t colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; ++colorAttachment)
694 {
695 GLenum drawBufferState = mDrawBufferStates[colorAttachment];
696 FramebufferAttachment *colorbuffer = mColorbuffers[colorAttachment];
697
698 if (colorbuffer != NULL && drawBufferState != GL_NONE)
699 {
700 ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + colorAttachment));
701 colorbuffersForRender.push_back(colorbuffer);
702 }
Jamie Madill3f2e61d2014-09-05 10:38:05 -0400703#if (ANGLE_MRT_PERF_WORKAROUND == ANGLE_WORKAROUND_DISABLED)
Jamie Madillce20c7f2014-09-03 11:56:29 -0400704 else
705 {
706 colorbuffersForRender.push_back(NULL);
707 }
Jamie Madill3f2e61d2014-09-05 10:38:05 -0400708#endif
Jamie Madillce20c7f2014-09-03 11:56:29 -0400709 }
710
711 return colorbuffersForRender;
712}
713
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000714GLenum DefaultFramebuffer::completeness() const
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000715{
shannon.woods@transgaming.com3e3da582013-02-28 23:09:03 +0000716 // The default framebuffer *must* always be complete, though it may not be
717 // subject to the same rules as application FBOs. ie, it could have 0x0 size.
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000718 return GL_FRAMEBUFFER_COMPLETE;
719}
720
Jamie Madille92a3542014-07-03 10:38:58 -0400721FramebufferAttachment *DefaultFramebuffer::getAttachment(GLenum attachment) const
722{
723 switch (attachment)
724 {
Jamie Madill6d708262014-09-03 15:07:13 -0400725 case GL_COLOR:
Jamie Madille92a3542014-07-03 10:38:58 -0400726 case GL_BACK:
727 return getColorbuffer(0);
728 case GL_DEPTH:
729 return getDepthbuffer();
730 case GL_STENCIL:
731 return getStencilbuffer();
732 case GL_DEPTH_STENCIL:
733 return getDepthStencilBuffer();
734 default:
735 UNREACHABLE();
736 return NULL;
737 }
738}
739
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000740}