blob: e2a970dba1320a2205efbe29b969a690ac58298f [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"
Shannon Woodse2632d22014-10-17 13:08:51 -040019#include "libGLESv2/renderer/RenderbufferImpl.h"
Jamie Madill7acae0a2014-09-24 17:10:51 -040020#include "libGLESv2/renderer/Workarounds.h"
Jamie Madill9f0b42a2014-09-12 10:25:27 -040021#include "libGLESv2/renderer/d3d/TextureD3D.h"
Shannon Woodse2632d22014-10-17 13:08:51 -040022#include "libGLESv2/renderer/d3d/RenderbufferD3D.h"
Geoff Lang0b7eef72014-06-12 14:10:47 -040023
24#include "common/utilities.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000025
Jamie Madill9f0b42a2014-09-12 10:25:27 -040026namespace rx
27{
Shannon Woodse2632d22014-10-17 13:08:51 -040028// TODO: Move these functions, and the D3D-specific header inclusions above,
29// to FramebufferD3D.
Geoff Lang64f23f62014-09-10 14:40:12 -040030gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget **outRT)
Jamie Madill9f0b42a2014-09-12 10:25:27 -040031{
32 if (attachment->isTexture())
33 {
34 gl::Texture *texture = attachment->getTexture();
35 ASSERT(texture);
36 TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
Jamie Madillac7579c2014-09-17 16:59:33 -040037 const gl::ImageIndex *index = attachment->getTextureImageIndex();
38 ASSERT(index);
Geoff Lang64f23f62014-09-10 14:40:12 -040039 return textureD3D->getRenderTarget(*index, outRT);
Jamie Madill9f0b42a2014-09-12 10:25:27 -040040 }
Geoff Lang64f23f62014-09-10 14:40:12 -040041 else
42 {
43 gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
44 ASSERT(renderbuffer);
Shannon Woodse2632d22014-10-17 13:08:51 -040045 RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation());
46 *outRT = renderbufferD3D->getRenderTarget();
Geoff Lang64f23f62014-09-10 14:40:12 -040047 return gl::Error(GL_NO_ERROR);
48 }
Jamie Madill9f0b42a2014-09-12 10:25:27 -040049}
50
Jamie Madill612e2e42014-09-12 13:26:55 -040051// Note: RenderTarget serials should ideally be in the RenderTargets themselves.
52unsigned int GetAttachmentSerial(gl::FramebufferAttachment *attachment)
53{
54 if (attachment->isTexture())
55 {
56 gl::Texture *texture = attachment->getTexture();
57 ASSERT(texture);
58 TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
Jamie Madillac7579c2014-09-17 16:59:33 -040059 const gl::ImageIndex *index = attachment->getTextureImageIndex();
60 ASSERT(index);
61 return textureD3D->getRenderTargetSerial(*index);
Jamie Madill612e2e42014-09-12 13:26:55 -040062 }
63
64 gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
65 ASSERT(renderbuffer);
Shannon Woodse2632d22014-10-17 13:08:51 -040066 RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation());
67 return renderbufferD3D->getRenderTargetSerial();
Jamie Madill612e2e42014-09-12 13:26:55 -040068}
69
Jamie Madill9f0b42a2014-09-12 10:25:27 -040070}
71
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000072namespace gl
73{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000074
Shannon Woodsaa2ab7d2014-06-24 17:51:51 -040075Framebuffer::Framebuffer(rx::Renderer *renderer, GLuint id)
Jamie Madille261b442014-06-25 12:42:21 -040076 : mRenderer(renderer),
Shannon Woodsaa2ab7d2014-06-24 17:51:51 -040077 mId(id),
Jamie Madille261b442014-06-25 12:42:21 -040078 mReadBufferState(GL_COLOR_ATTACHMENT0_EXT),
79 mDepthbuffer(NULL),
80 mStencilbuffer(NULL)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000081{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000082 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
83 {
Jamie Madille261b442014-06-25 12:42:21 -040084 mColorbuffers[colorAttachment] = NULL;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000085 mDrawBufferStates[colorAttachment] = GL_NONE;
86 }
87 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000088}
89
90Framebuffer::~Framebuffer()
91{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000092 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
93 {
Jamie Madille261b442014-06-25 12:42:21 -040094 SafeDelete(mColorbuffers[colorAttachment]);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000095 }
Jamie Madille261b442014-06-25 12:42:21 -040096 SafeDelete(mDepthbuffer);
97 SafeDelete(mStencilbuffer);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000098}
99
Jamie Madillaef95de2014-09-05 10:12:41 -0400100FramebufferAttachment *Framebuffer::createAttachment(GLenum binding, GLenum type, GLuint handle, GLint level, GLint layer) const
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000101{
Jamie Madill6c7b4ad2014-06-16 10:33:59 -0400102 if (handle == 0)
103 {
104 return NULL;
105 }
106
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000107 gl::Context *context = gl::getContext();
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000108
Geoff Lang309c92a2013-07-25 16:23:19 -0400109 switch (type)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000110 {
Geoff Lang309c92a2013-07-25 16:23:19 -0400111 case GL_NONE:
112 return NULL;
113
114 case GL_RENDERBUFFER:
Jamie Madillaef95de2014-09-05 10:12:41 -0400115 return new RenderbufferAttachment(binding, context->getRenderbuffer(handle));
Geoff Lang309c92a2013-07-25 16:23:19 -0400116
117 case GL_TEXTURE_2D:
118 {
119 Texture *texture = context->getTexture(handle);
120 if (texture && texture->getTarget() == GL_TEXTURE_2D)
121 {
Jamie Madilleeb7b0e2014-09-03 15:07:20 -0400122 return new TextureAttachment(binding, texture, ImageIndex::Make2D(level));
Geoff Lang309c92a2013-07-25 16:23:19 -0400123 }
124 else
125 {
126 return NULL;
127 }
128 }
129
130 case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
131 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
132 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
133 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
134 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
135 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
136 {
137 Texture *texture = context->getTexture(handle);
138 if (texture && texture->getTarget() == GL_TEXTURE_CUBE_MAP)
139 {
Jamie Madilleeb7b0e2014-09-03 15:07:20 -0400140 return new TextureAttachment(binding, texture, ImageIndex::MakeCube(type, level));
Geoff Lang309c92a2013-07-25 16:23:19 -0400141 }
142 else
143 {
144 return NULL;
145 }
146 }
147
148 case GL_TEXTURE_3D:
149 {
150 Texture *texture = context->getTexture(handle);
151 if (texture && texture->getTarget() == GL_TEXTURE_3D)
152 {
Jamie Madilleeb7b0e2014-09-03 15:07:20 -0400153 return new TextureAttachment(binding, texture, ImageIndex::Make3D(level, layer));
Geoff Lang309c92a2013-07-25 16:23:19 -0400154 }
155 else
156 {
157 return NULL;
158 }
159 }
160
161 case GL_TEXTURE_2D_ARRAY:
162 {
163 Texture *texture = context->getTexture(handle);
164 if (texture && texture->getTarget() == GL_TEXTURE_2D_ARRAY)
165 {
Jamie Madilleeb7b0e2014-09-03 15:07:20 -0400166 return new TextureAttachment(binding, texture, ImageIndex::Make2DArray(level, layer));
Geoff Lang309c92a2013-07-25 16:23:19 -0400167 }
168 else
169 {
170 return NULL;
171 }
172 }
173
174 default:
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000175 UNREACHABLE();
Geoff Lang309c92a2013-07-25 16:23:19 -0400176 return NULL;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000177 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000178}
179
Geoff Lang309c92a2013-07-25 16:23:19 -0400180void Framebuffer::setColorbuffer(unsigned int colorAttachment, GLenum type, GLuint colorbuffer, GLint level, GLint layer)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000181{
182 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
Jamie Madille261b442014-06-25 12:42:21 -0400183 SafeDelete(mColorbuffers[colorAttachment]);
Jamie Madillaef95de2014-09-05 10:12:41 -0400184 GLenum binding = colorAttachment + GL_COLOR_ATTACHMENT0;
185 mColorbuffers[colorAttachment] = createAttachment(binding, type, colorbuffer, level, layer);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000186}
187
Geoff Lang309c92a2013-07-25 16:23:19 -0400188void Framebuffer::setDepthbuffer(GLenum type, GLuint depthbuffer, GLint level, GLint layer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000189{
Jamie Madille261b442014-06-25 12:42:21 -0400190 SafeDelete(mDepthbuffer);
Jamie Madillaef95de2014-09-05 10:12:41 -0400191 mDepthbuffer = createAttachment(GL_DEPTH_ATTACHMENT, type, depthbuffer, level, layer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000192}
193
Geoff Lang309c92a2013-07-25 16:23:19 -0400194void Framebuffer::setStencilbuffer(GLenum type, GLuint stencilbuffer, GLint level, GLint layer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000195{
Jamie Madille261b442014-06-25 12:42:21 -0400196 SafeDelete(mStencilbuffer);
Jamie Madillaef95de2014-09-05 10:12:41 -0400197 mStencilbuffer = createAttachment(GL_STENCIL_ATTACHMENT, type, stencilbuffer, level, layer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000198}
199
Geoff Lang309c92a2013-07-25 16:23:19 -0400200void Framebuffer::setDepthStencilBuffer(GLenum type, GLuint depthStencilBuffer, GLint level, GLint layer)
Geoff Lang55ba29c2013-07-11 16:57:53 -0400201{
Jamie Madillaef95de2014-09-05 10:12:41 -0400202 FramebufferAttachment *attachment = createAttachment(GL_DEPTH_STENCIL_ATTACHMENT, type, depthStencilBuffer, level, layer);
Jamie Madill6c7b4ad2014-06-16 10:33:59 -0400203
Jamie Madille261b442014-06-25 12:42:21 -0400204 SafeDelete(mDepthbuffer);
205 SafeDelete(mStencilbuffer);
206
207 // ensure this is a legitimate depth+stencil format
Geoff Lange4a492b2014-06-19 14:14:41 -0400208 if (attachment && attachment->getDepthSize() > 0 && attachment->getStencilSize() > 0)
Geoff Lang55ba29c2013-07-11 16:57:53 -0400209 {
Jamie Madille261b442014-06-25 12:42:21 -0400210 mDepthbuffer = attachment;
Jamie Madill28bedaf2014-06-26 13:17:22 -0400211
212 // Make a new attachment object to ensure we do not double-delete
213 // See angle issue 686
Jamie Madillaef95de2014-09-05 10:12:41 -0400214 mStencilbuffer = createAttachment(GL_DEPTH_STENCIL_ATTACHMENT, type, depthStencilBuffer, level, layer);
Geoff Lang55ba29c2013-07-11 16:57:53 -0400215 }
216}
217
Jamie Madille261b442014-06-25 12:42:21 -0400218void Framebuffer::detachTexture(GLuint textureId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000219{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000220 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000221 {
Jamie Madille261b442014-06-25 12:42:21 -0400222 FramebufferAttachment *attachment = mColorbuffers[colorAttachment];
223
224 if (attachment && attachment->isTextureWithId(textureId))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000225 {
Jamie Madille261b442014-06-25 12:42:21 -0400226 SafeDelete(mColorbuffers[colorAttachment]);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000227 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000228 }
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000229
Jamie Madille261b442014-06-25 12:42:21 -0400230 if (mDepthbuffer && mDepthbuffer->isTextureWithId(textureId))
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000231 {
Jamie Madille261b442014-06-25 12:42:21 -0400232 SafeDelete(mDepthbuffer);
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000233 }
234
Jamie Madille261b442014-06-25 12:42:21 -0400235 if (mStencilbuffer && mStencilbuffer->isTextureWithId(textureId))
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000236 {
Jamie Madille261b442014-06-25 12:42:21 -0400237 SafeDelete(mStencilbuffer);
daniel@transgaming.comfbc09532010-04-26 15:33:41 +0000238 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000239}
240
Jamie Madille261b442014-06-25 12:42:21 -0400241void Framebuffer::detachRenderbuffer(GLuint renderbufferId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000242{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000243 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000244 {
Jamie Madille261b442014-06-25 12:42:21 -0400245 FramebufferAttachment *attachment = mColorbuffers[colorAttachment];
246
247 if (attachment && attachment->isRenderbufferWithId(renderbufferId))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000248 {
Jamie Madille261b442014-06-25 12:42:21 -0400249 SafeDelete(mColorbuffers[colorAttachment]);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000250 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000251 }
252
Jamie Madille261b442014-06-25 12:42:21 -0400253 if (mDepthbuffer && mDepthbuffer->isRenderbufferWithId(renderbufferId))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000254 {
Jamie Madille261b442014-06-25 12:42:21 -0400255 SafeDelete(mDepthbuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000256 }
257
Jamie Madille261b442014-06-25 12:42:21 -0400258 if (mStencilbuffer && mStencilbuffer->isRenderbufferWithId(renderbufferId))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000259 {
Jamie Madille261b442014-06-25 12:42:21 -0400260 SafeDelete(mStencilbuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000261 }
262}
263
Jamie Madill3c7fa222014-06-05 13:08:51 -0400264FramebufferAttachment *Framebuffer::getColorbuffer(unsigned int colorAttachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000265{
266 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
Jamie Madille261b442014-06-25 12:42:21 -0400267 return mColorbuffers[colorAttachment];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000268}
269
Jamie Madill3c7fa222014-06-05 13:08:51 -0400270FramebufferAttachment *Framebuffer::getDepthbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000271{
Jamie Madille261b442014-06-25 12:42:21 -0400272 return mDepthbuffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000273}
274
Jamie Madill3c7fa222014-06-05 13:08:51 -0400275FramebufferAttachment *Framebuffer::getStencilbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000276{
Jamie Madille261b442014-06-25 12:42:21 -0400277 return mStencilbuffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000278}
279
Jamie Madill3c7fa222014-06-05 13:08:51 -0400280FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
Geoff Lang646559f2013-08-15 11:08:15 -0400281{
Jamie Madille261b442014-06-25 12:42:21 -0400282 return (hasValidDepthStencil() ? mDepthbuffer : NULL);
Geoff Lang646559f2013-08-15 11:08:15 -0400283}
284
Jamie Madill3c7fa222014-06-05 13:08:51 -0400285FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000286{
Jamie Madille261b442014-06-25 12:42:21 -0400287 FramebufferAttachment *depthstencilbuffer = mDepthbuffer;
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000288
289 if (!depthstencilbuffer)
290 {
Jamie Madille261b442014-06-25 12:42:21 -0400291 depthstencilbuffer = mStencilbuffer;
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000292 }
293
294 return depthstencilbuffer;
295}
296
Jamie Madill3c7fa222014-06-05 13:08:51 -0400297FramebufferAttachment *Framebuffer::getReadColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000298{
299 // Will require more logic if glReadBuffers is supported
Jamie Madille261b442014-06-25 12:42:21 -0400300 return mColorbuffers[0];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000301}
302
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000303GLenum Framebuffer::getReadColorbufferType() const
304{
305 // Will require more logic if glReadBuffers is supported
Jamie Madille261b442014-06-25 12:42:21 -0400306 return (mColorbuffers[0] ? mColorbuffers[0]->type() : GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000307}
308
Jamie Madill3c7fa222014-06-05 13:08:51 -0400309FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000310{
311 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
312 {
Jamie Madille261b442014-06-25 12:42:21 -0400313 if (mColorbuffers[colorAttachment])
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000314 {
Jamie Madille261b442014-06-25 12:42:21 -0400315 return mColorbuffers[colorAttachment];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000316 }
317 }
318
319 return NULL;
320}
321
Jamie Madille92a3542014-07-03 10:38:58 -0400322FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000323{
Jamie Madille92a3542014-07-03 10:38:58 -0400324 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
325 {
326 return getColorbuffer(attachment - GL_COLOR_ATTACHMENT0);
327 }
328 else
329 {
330 switch (attachment)
331 {
332 case GL_DEPTH_ATTACHMENT:
333 return getDepthbuffer();
334 case GL_STENCIL_ATTACHMENT:
335 return getStencilbuffer();
336 case GL_DEPTH_STENCIL_ATTACHMENT:
337 return getDepthStencilBuffer();
338 default:
339 UNREACHABLE();
340 return NULL;
341 }
342 }
Geoff Lang55ba29c2013-07-11 16:57:53 -0400343}
344
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000345GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const
346{
347 return mDrawBufferStates[colorAttachment];
348}
349
350void Framebuffer::setDrawBufferState(unsigned int colorAttachment, GLenum drawBuffer)
351{
352 mDrawBufferStates[colorAttachment] = drawBuffer;
353}
354
shannon.woods%transgaming.com@gtempaccount.comdae24092013-04-13 03:31:31 +0000355bool Framebuffer::isEnabledColorAttachment(unsigned int colorAttachment) const
356{
Jamie Madille261b442014-06-25 12:42:21 -0400357 return (mColorbuffers[colorAttachment] && mDrawBufferStates[colorAttachment] != GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comdae24092013-04-13 03:31:31 +0000358}
359
360bool Framebuffer::hasEnabledColorAttachment() const
361{
362 for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
363 {
364 if (isEnabledColorAttachment(colorAttachment))
365 {
366 return true;
367 }
368 }
369
370 return false;
371}
372
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000373bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000374{
Geoff Lange4a492b2014-06-19 14:14:41 -0400375 return (mStencilbuffer && mStencilbuffer->getStencilSize() > 0);
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000376}
377
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000378bool Framebuffer::usingExtendedDrawBuffers() const
379{
380 for (unsigned int colorAttachment = 1; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
381 {
382 if (isEnabledColorAttachment(colorAttachment))
383 {
384 return true;
385 }
386 }
387
388 return false;
389}
390
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000391GLenum Framebuffer::completeness() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000392{
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000393 int width = 0;
394 int height = 0;
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000395 unsigned int colorbufferSize = 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000396 int samples = -1;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000397 bool missingAttachment = true;
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000398 GLuint clientVersion = mRenderer->getCurrentClientVersion();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000399
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000400 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000401 {
Jamie Madillbb94f342014-06-23 15:23:02 -0400402 const FramebufferAttachment *colorbuffer = mColorbuffers[colorAttachment];
403
404 if (colorbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000405 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000406 if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000407 {
408 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
409 }
daniel@transgaming.com01868132010-08-24 19:21:17 +0000410
Geoff Langcec35902014-04-16 10:52:36 -0400411 GLenum internalformat = colorbuffer->getInternalFormat();
Geoff Langc0b9ef42014-07-02 10:02:37 -0400412 // TODO(geofflang): use context's texture caps
413 const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400414 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madillbb94f342014-06-23 15:23:02 -0400415 if (colorbuffer->isTexture())
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000416 {
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400417 if (!formatCaps.renderable)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000418 {
419 return GL_FRAMEBUFFER_UNSUPPORTED;
420 }
421
Geoff Lang5d601382014-07-22 15:14:06 -0400422 if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000423 {
424 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
425 }
426 }
427 else
428 {
Geoff Lang5d601382014-07-22 15:14:06 -0400429 if (!formatCaps.renderable || formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400430 {
431 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
432 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000433 }
434
435 if (!missingAttachment)
436 {
437 // all color attachments must have the same width and height
438 if (colorbuffer->getWidth() != width || colorbuffer->getHeight() != height)
439 {
440 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
441 }
442
443 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
444 // all color attachments have the same number of samples for the FBO to be complete.
445 if (colorbuffer->getSamples() != samples)
446 {
447 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
448 }
449
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000450 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
451 // in GLES 3.0, there is no such restriction
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000452 if (clientVersion < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000453 {
Geoff Lang5d601382014-07-22 15:14:06 -0400454 if (formatInfo.pixelBytes != colorbufferSize)
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000455 {
456 return GL_FRAMEBUFFER_UNSUPPORTED;
457 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000458 }
459
460 // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness
461 for (unsigned int previousColorAttachment = 0; previousColorAttachment < colorAttachment; previousColorAttachment++)
462 {
Jamie Madille92a3542014-07-03 10:38:58 -0400463 const FramebufferAttachment *previousAttachment = mColorbuffers[previousColorAttachment];
464
465 if (previousAttachment &&
466 (colorbuffer->id() == previousAttachment->id() &&
467 colorbuffer->type() == previousAttachment->type()))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000468 {
469 return GL_FRAMEBUFFER_UNSUPPORTED;
470 }
471 }
472 }
473 else
474 {
475 width = colorbuffer->getWidth();
476 height = colorbuffer->getHeight();
477 samples = colorbuffer->getSamples();
Geoff Lang5d601382014-07-22 15:14:06 -0400478 colorbufferSize = formatInfo.pixelBytes;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000479 missingAttachment = false;
480 }
481 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000482 }
483
Jamie Madille261b442014-06-25 12:42:21 -0400484 if (mDepthbuffer)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000485 {
Jamie Madille261b442014-06-25 12:42:21 -0400486 if (mDepthbuffer->getWidth() == 0 || mDepthbuffer->getHeight() == 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000487 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000488 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000489 }
490
Jamie Madille261b442014-06-25 12:42:21 -0400491 GLenum internalformat = mDepthbuffer->getInternalFormat();
Geoff Langc0b9ef42014-07-02 10:02:37 -0400492 // TODO(geofflang): use context's texture caps
493 const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400494 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madillbb94f342014-06-23 15:23:02 -0400495 if (mDepthbuffer->isTexture())
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000496 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000497 // depth texture attachments require OES/ANGLE_depth_texture
Geoff Langc0b9ef42014-07-02 10:02:37 -0400498 // TODO(geofflang): use context's extensions
499 if (!mRenderer->getRendererExtensions().depthTextures)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000500 {
501 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
502 }
503
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400504 if (!formatCaps.renderable)
Geoff Langcec35902014-04-16 10:52:36 -0400505 {
506 return GL_FRAMEBUFFER_UNSUPPORTED;
507 }
508
Geoff Lang5d601382014-07-22 15:14:06 -0400509 if (formatInfo.depthBits == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000510 {
511 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
512 }
513 }
514 else
515 {
Geoff Lang5d601382014-07-22 15:14:06 -0400516 if (!formatCaps.renderable || formatInfo.depthBits == 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400517 {
518 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
519 }
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000520 }
521
522 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000523 {
Jamie Madille261b442014-06-25 12:42:21 -0400524 width = mDepthbuffer->getWidth();
525 height = mDepthbuffer->getHeight();
526 samples = mDepthbuffer->getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000527 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000528 }
Jamie Madille261b442014-06-25 12:42:21 -0400529 else if (width != mDepthbuffer->getWidth() || height != mDepthbuffer->getHeight())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000530 {
531 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
532 }
Jamie Madille261b442014-06-25 12:42:21 -0400533 else if (samples != mDepthbuffer->getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000534 {
535 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
536 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000537 }
538
Jamie Madille261b442014-06-25 12:42:21 -0400539 if (mStencilbuffer)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000540 {
Jamie Madille261b442014-06-25 12:42:21 -0400541 if (mStencilbuffer->getWidth() == 0 || mStencilbuffer->getHeight() == 0)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000542 {
543 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
544 }
545
Jamie Madille261b442014-06-25 12:42:21 -0400546 GLenum internalformat = mStencilbuffer->getInternalFormat();
Geoff Langc0b9ef42014-07-02 10:02:37 -0400547 // TODO(geofflang): use context's texture caps
548 const TextureCaps &formatCaps = mRenderer->getRendererTextureCaps().get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400549 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madillbb94f342014-06-23 15:23:02 -0400550 if (mStencilbuffer->isTexture())
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000551 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000552 // texture stencil attachments come along as part
553 // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
Geoff Langc0b9ef42014-07-02 10:02:37 -0400554 // TODO(geofflang): use context's extensions
555 if (!mRenderer->getRendererExtensions().depthTextures)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000556 {
557 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
558 }
559
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400560 if (!formatCaps.renderable)
Geoff Langcec35902014-04-16 10:52:36 -0400561 {
562 return GL_FRAMEBUFFER_UNSUPPORTED;
563 }
564
Geoff Lang5d601382014-07-22 15:14:06 -0400565 if (formatInfo.stencilBits == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000566 {
567 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
568 }
569 }
570 else
571 {
Geoff Lang5d601382014-07-22 15:14:06 -0400572 if (!formatCaps.renderable || formatInfo.stencilBits == 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400573 {
574 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
575 }
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000576 }
577
578 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000579 {
Jamie Madille261b442014-06-25 12:42:21 -0400580 width = mStencilbuffer->getWidth();
581 height = mStencilbuffer->getHeight();
582 samples = mStencilbuffer->getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000583 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000584 }
Jamie Madille261b442014-06-25 12:42:21 -0400585 else if (width != mStencilbuffer->getWidth() || height != mStencilbuffer->getHeight())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000586 {
587 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
588 }
Jamie Madille261b442014-06-25 12:42:21 -0400589 else if (samples != mStencilbuffer->getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000590 {
591 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
592 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000593 }
594
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000595 // if we have both a depth and stencil buffer, they must refer to the same object
596 // since we only support packed_depth_stencil and not separate depth and stencil
Jamie Madille261b442014-06-25 12:42:21 -0400597 if (mDepthbuffer && mStencilbuffer && !hasValidDepthStencil())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000598 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000599 return GL_FRAMEBUFFER_UNSUPPORTED;
600 }
601
602 // we need to have at least one attachment to be complete
603 if (missingAttachment)
604 {
605 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000606 }
607
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000608 return GL_FRAMEBUFFER_COMPLETE;
609}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000610
Geoff Lang64f23f62014-09-10 14:40:12 -0400611Error Framebuffer::invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments)
Jamie Madill2d96b9e2014-08-29 15:46:47 -0400612{
613 GLuint maxDimension = caps.maxRenderbufferSize;
Geoff Lang64f23f62014-09-10 14:40:12 -0400614 return invalidateSub(numAttachments, attachments, 0, 0, maxDimension, maxDimension);
Jamie Madill2d96b9e2014-08-29 15:46:47 -0400615}
616
Geoff Lang64f23f62014-09-10 14:40:12 -0400617Error Framebuffer::invalidateSub(GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height)
Jamie Madill400a4412014-08-29 15:46:45 -0400618{
619 ASSERT(completeness() == GL_FRAMEBUFFER_COMPLETE);
Jamie Madill6d708262014-09-03 15:07:13 -0400620 for (GLsizei attachIndex = 0; attachIndex < numAttachments; ++attachIndex)
Jamie Madill400a4412014-08-29 15:46:45 -0400621 {
Jamie Madill6d708262014-09-03 15:07:13 -0400622 GLenum attachmentTarget = attachments[attachIndex];
Jamie Madill400a4412014-08-29 15:46:45 -0400623
Geoff Lang64f23f62014-09-10 14:40:12 -0400624 FramebufferAttachment *attachment = (attachmentTarget == GL_DEPTH_STENCIL_ATTACHMENT) ? getDepthOrStencilbuffer()
625 : getAttachment(attachmentTarget);
Jamie Madill400a4412014-08-29 15:46:45 -0400626
Jamie Madill6d708262014-09-03 15:07:13 -0400627 if (attachment)
Jamie Madill400a4412014-08-29 15:46:45 -0400628 {
Geoff Lang64f23f62014-09-10 14:40:12 -0400629 rx::RenderTarget *renderTarget = NULL;
630 Error error = rx::GetAttachmentRenderTarget(attachment, &renderTarget);
631 if (error.isError())
Jamie Madill6d708262014-09-03 15:07:13 -0400632 {
Geoff Lang64f23f62014-09-10 14:40:12 -0400633 return error;
Jamie Madill6d708262014-09-03 15:07:13 -0400634 }
Geoff Lang64f23f62014-09-10 14:40:12 -0400635
636 renderTarget->invalidate(x, y, width, height);
Jamie Madill400a4412014-08-29 15:46:45 -0400637 }
638 }
Geoff Lang64f23f62014-09-10 14:40:12 -0400639
640 return Error(GL_NO_ERROR);
Jamie Madill400a4412014-08-29 15:46:45 -0400641}
642
Shannon Woodse2632d22014-10-17 13:08:51 -0400643DefaultFramebuffer::DefaultFramebuffer(rx::Renderer *renderer, rx::RenderbufferImpl *colorbuffer, rx::RenderbufferImpl *depthStencil)
Shannon Woodsaa2ab7d2014-06-24 17:51:51 -0400644 : Framebuffer(renderer, 0)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000645{
Shannon Woodse2632d22014-10-17 13:08:51 -0400646 Renderbuffer *colorRenderbuffer = new Renderbuffer(colorbuffer, 0);
Jamie Madillaef95de2014-09-05 10:12:41 -0400647 mColorbuffers[0] = new RenderbufferAttachment(GL_BACK, colorRenderbuffer);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000648
Shannon Woodse2632d22014-10-17 13:08:51 -0400649 Renderbuffer *depthStencilBuffer = new Renderbuffer(depthStencil, 0);
Jamie Madill28bedaf2014-06-26 13:17:22 -0400650
651 // Make a new attachment objects to ensure we do not double-delete
652 // See angle issue 686
Jamie Madillaef95de2014-09-05 10:12:41 -0400653 mDepthbuffer = (depthStencilBuffer->getDepthSize() != 0 ? new RenderbufferAttachment(GL_DEPTH_ATTACHMENT, depthStencilBuffer) : NULL);
654 mStencilbuffer = (depthStencilBuffer->getStencilSize() != 0 ? new RenderbufferAttachment(GL_STENCIL_ATTACHMENT, depthStencilBuffer) : NULL);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000655
656 mDrawBufferStates[0] = GL_BACK;
657 mReadBufferState = GL_BACK;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000658}
659
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000660int Framebuffer::getSamples() const
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000661{
662 if (completeness() == GL_FRAMEBUFFER_COMPLETE)
663 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000664 // for a complete framebuffer, all attachments must have the same sample count
665 // in this case return the first nonzero sample size
666 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
667 {
Jamie Madille261b442014-06-25 12:42:21 -0400668 if (mColorbuffers[colorAttachment])
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000669 {
Jamie Madille261b442014-06-25 12:42:21 -0400670 return mColorbuffers[colorAttachment]->getSamples();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000671 }
672 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000673 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000674
675 return 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000676}
677
Jamie Madille261b442014-06-25 12:42:21 -0400678bool Framebuffer::hasValidDepthStencil() const
679{
680 // A valid depth-stencil attachment has the same resource bound to both the
681 // depth and stencil attachment points.
682 return (mDepthbuffer && mStencilbuffer &&
683 mDepthbuffer->type() == mStencilbuffer->type() &&
684 mDepthbuffer->id() == mStencilbuffer->id());
685}
686
Jamie Madillce20c7f2014-09-03 11:56:29 -0400687ColorbufferInfo Framebuffer::getColorbuffersForRender() const
688{
689 ColorbufferInfo colorbuffersForRender;
690
691 for (size_t colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; ++colorAttachment)
692 {
693 GLenum drawBufferState = mDrawBufferStates[colorAttachment];
694 FramebufferAttachment *colorbuffer = mColorbuffers[colorAttachment];
695
696 if (colorbuffer != NULL && drawBufferState != GL_NONE)
697 {
698 ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + colorAttachment));
699 colorbuffersForRender.push_back(colorbuffer);
700 }
Jamie Madill7acae0a2014-09-24 17:10:51 -0400701 else if (!mRenderer->getWorkarounds().mrtPerfWorkaround)
Jamie Madillce20c7f2014-09-03 11:56:29 -0400702 {
703 colorbuffersForRender.push_back(NULL);
704 }
705 }
706
707 return colorbuffersForRender;
708}
709
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000710GLenum DefaultFramebuffer::completeness() const
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000711{
shannon.woods@transgaming.com3e3da582013-02-28 23:09:03 +0000712 // The default framebuffer *must* always be complete, though it may not be
713 // subject to the same rules as application FBOs. ie, it could have 0x0 size.
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000714 return GL_FRAMEBUFFER_COMPLETE;
715}
716
Jamie Madille92a3542014-07-03 10:38:58 -0400717FramebufferAttachment *DefaultFramebuffer::getAttachment(GLenum attachment) const
718{
719 switch (attachment)
720 {
Jamie Madill6d708262014-09-03 15:07:13 -0400721 case GL_COLOR:
Jamie Madille92a3542014-07-03 10:38:58 -0400722 case GL_BACK:
723 return getColorbuffer(0);
724 case GL_DEPTH:
725 return getDepthbuffer();
726 case GL_STENCIL:
727 return getStencilbuffer();
728 case GL_DEPTH_STENCIL:
729 return getDepthStencilBuffer();
730 default:
731 UNREACHABLE();
732 return NULL;
733 }
734}
735
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000736}