blob: c4d8f381e6c367646b5ce99e45ee15d83bc99572 [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
Geoff Lang2b5420c2014-11-19 14:20:15 -050010#include "libANGLE/Framebuffer.h"
11#include "libANGLE/formatutils.h"
12#include "libANGLE/Texture.h"
13#include "libANGLE/Context.h"
14#include "libANGLE/Renderbuffer.h"
15#include "libANGLE/FramebufferAttachment.h"
Geoff Langb5d8f232014-12-04 15:43:01 -050016#include "libANGLE/renderer/FramebufferImpl.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050017#include "libANGLE/renderer/Renderer.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050018#include "libANGLE/renderer/RenderbufferImpl.h"
19#include "libANGLE/renderer/Workarounds.h"
Geoff Lang0b7eef72014-06-12 14:10:47 -040020
21#include "common/utilities.h"
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000022
23namespace gl
24{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000025
Geoff Langda88add2014-12-01 10:22:01 -050026Framebuffer::Framebuffer(rx::FramebufferImpl *impl, GLuint id)
27 : mImpl(impl),
28 mId(id),
Jamie Madille261b442014-06-25 12:42:21 -040029 mReadBufferState(GL_COLOR_ATTACHMENT0_EXT),
30 mDepthbuffer(NULL),
31 mStencilbuffer(NULL)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000032{
Geoff Langda88add2014-12-01 10:22:01 -050033 ASSERT(mImpl != nullptr);
34
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000035 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
36 {
Jamie Madille261b442014-06-25 12:42:21 -040037 mColorbuffers[colorAttachment] = NULL;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000038 mDrawBufferStates[colorAttachment] = GL_NONE;
39 }
40 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000041}
42
43Framebuffer::~Framebuffer()
44{
Geoff Langda88add2014-12-01 10:22:01 -050045 SafeDelete(mImpl);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000046 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
47 {
Jamie Madille261b442014-06-25 12:42:21 -040048 SafeDelete(mColorbuffers[colorAttachment]);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000049 }
Jamie Madille261b442014-06-25 12:42:21 -040050 SafeDelete(mDepthbuffer);
51 SafeDelete(mStencilbuffer);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000052}
53
Jamie Madille261b442014-06-25 12:42:21 -040054void Framebuffer::detachTexture(GLuint textureId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000055{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000056 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000057 {
Jamie Madille261b442014-06-25 12:42:21 -040058 FramebufferAttachment *attachment = mColorbuffers[colorAttachment];
59
60 if (attachment && attachment->isTextureWithId(textureId))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000061 {
Jamie Madille261b442014-06-25 12:42:21 -040062 SafeDelete(mColorbuffers[colorAttachment]);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000063 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000064 }
daniel@transgaming.comfbc09532010-04-26 15:33:41 +000065
Jamie Madille261b442014-06-25 12:42:21 -040066 if (mDepthbuffer && mDepthbuffer->isTextureWithId(textureId))
daniel@transgaming.comfbc09532010-04-26 15:33:41 +000067 {
Jamie Madille261b442014-06-25 12:42:21 -040068 SafeDelete(mDepthbuffer);
daniel@transgaming.comfbc09532010-04-26 15:33:41 +000069 }
70
Jamie Madille261b442014-06-25 12:42:21 -040071 if (mStencilbuffer && mStencilbuffer->isTextureWithId(textureId))
daniel@transgaming.comfbc09532010-04-26 15:33:41 +000072 {
Jamie Madille261b442014-06-25 12:42:21 -040073 SafeDelete(mStencilbuffer);
daniel@transgaming.comfbc09532010-04-26 15:33:41 +000074 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000075}
76
Jamie Madille261b442014-06-25 12:42:21 -040077void Framebuffer::detachRenderbuffer(GLuint renderbufferId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000078{
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000079 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000080 {
Jamie Madille261b442014-06-25 12:42:21 -040081 FramebufferAttachment *attachment = mColorbuffers[colorAttachment];
82
83 if (attachment && attachment->isRenderbufferWithId(renderbufferId))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000084 {
Jamie Madille261b442014-06-25 12:42:21 -040085 SafeDelete(mColorbuffers[colorAttachment]);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +000086 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000087 }
88
Jamie Madille261b442014-06-25 12:42:21 -040089 if (mDepthbuffer && mDepthbuffer->isRenderbufferWithId(renderbufferId))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000090 {
Jamie Madille261b442014-06-25 12:42:21 -040091 SafeDelete(mDepthbuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000092 }
93
Jamie Madille261b442014-06-25 12:42:21 -040094 if (mStencilbuffer && mStencilbuffer->isRenderbufferWithId(renderbufferId))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000095 {
Jamie Madille261b442014-06-25 12:42:21 -040096 SafeDelete(mStencilbuffer);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000097 }
98}
99
Jamie Madill3c7fa222014-06-05 13:08:51 -0400100FramebufferAttachment *Framebuffer::getColorbuffer(unsigned int colorAttachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000101{
102 ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
Jamie Madille261b442014-06-25 12:42:21 -0400103 return mColorbuffers[colorAttachment];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000104}
105
Jamie Madill3c7fa222014-06-05 13:08:51 -0400106FramebufferAttachment *Framebuffer::getDepthbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000107{
Jamie Madille261b442014-06-25 12:42:21 -0400108 return mDepthbuffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000109}
110
Jamie Madill3c7fa222014-06-05 13:08:51 -0400111FramebufferAttachment *Framebuffer::getStencilbuffer() const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000112{
Jamie Madille261b442014-06-25 12:42:21 -0400113 return mStencilbuffer;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000114}
115
Jamie Madill3c7fa222014-06-05 13:08:51 -0400116FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
Geoff Lang646559f2013-08-15 11:08:15 -0400117{
Jamie Madille261b442014-06-25 12:42:21 -0400118 return (hasValidDepthStencil() ? mDepthbuffer : NULL);
Geoff Lang646559f2013-08-15 11:08:15 -0400119}
120
Jamie Madill3c7fa222014-06-05 13:08:51 -0400121FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000122{
Jamie Madille261b442014-06-25 12:42:21 -0400123 FramebufferAttachment *depthstencilbuffer = mDepthbuffer;
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000124
125 if (!depthstencilbuffer)
126 {
Jamie Madille261b442014-06-25 12:42:21 -0400127 depthstencilbuffer = mStencilbuffer;
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000128 }
129
130 return depthstencilbuffer;
131}
132
Jamie Madill3c7fa222014-06-05 13:08:51 -0400133FramebufferAttachment *Framebuffer::getReadColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000134{
135 // Will require more logic if glReadBuffers is supported
Jamie Madille261b442014-06-25 12:42:21 -0400136 return mColorbuffers[0];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000137}
138
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000139GLenum Framebuffer::getReadColorbufferType() const
140{
141 // Will require more logic if glReadBuffers is supported
Jamie Madille261b442014-06-25 12:42:21 -0400142 return (mColorbuffers[0] ? mColorbuffers[0]->type() : GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000143}
144
Jamie Madill3c7fa222014-06-05 13:08:51 -0400145FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000146{
147 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
148 {
Jamie Madille261b442014-06-25 12:42:21 -0400149 if (mColorbuffers[colorAttachment])
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000150 {
Jamie Madille261b442014-06-25 12:42:21 -0400151 return mColorbuffers[colorAttachment];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000152 }
153 }
154
155 return NULL;
156}
157
Jamie Madille92a3542014-07-03 10:38:58 -0400158FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000159{
Jamie Madille92a3542014-07-03 10:38:58 -0400160 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
161 {
162 return getColorbuffer(attachment - GL_COLOR_ATTACHMENT0);
163 }
164 else
165 {
166 switch (attachment)
167 {
Geoff Lang528ce3c2014-12-01 10:44:07 -0500168 case GL_COLOR:
169 case GL_BACK:
170 return getColorbuffer(0);
171 case GL_DEPTH:
Jamie Madille92a3542014-07-03 10:38:58 -0400172 case GL_DEPTH_ATTACHMENT:
173 return getDepthbuffer();
Geoff Lang528ce3c2014-12-01 10:44:07 -0500174 case GL_STENCIL:
Jamie Madille92a3542014-07-03 10:38:58 -0400175 case GL_STENCIL_ATTACHMENT:
176 return getStencilbuffer();
Geoff Lang528ce3c2014-12-01 10:44:07 -0500177 case GL_DEPTH_STENCIL:
Jamie Madille92a3542014-07-03 10:38:58 -0400178 case GL_DEPTH_STENCIL_ATTACHMENT:
179 return getDepthStencilBuffer();
180 default:
181 UNREACHABLE();
182 return NULL;
183 }
184 }
Geoff Lang55ba29c2013-07-11 16:57:53 -0400185}
186
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000187GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const
188{
189 return mDrawBufferStates[colorAttachment];
190}
191
Geoff Lang164d54e2014-12-01 10:55:33 -0500192void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000193{
Geoff Lang68439852014-12-04 14:40:16 -0500194 ASSERT(count <= ArraySize(mDrawBufferStates));
Geoff Lang164d54e2014-12-01 10:55:33 -0500195 std::copy(buffers, buffers + count, mDrawBufferStates);
196 std::fill(mDrawBufferStates + count, mDrawBufferStates + ArraySize(mDrawBufferStates), GL_NONE);
Geoff Lang9dd95802014-12-01 11:12:59 -0500197 mImpl->setDrawBuffers(count, buffers);
198}
199
200GLenum Framebuffer::getReadBufferState() const
201{
202 return mReadBufferState;
203}
204
205void Framebuffer::setReadBuffer(GLenum buffer)
206{
207 mReadBufferState = buffer;
208 mImpl->setReadBuffer(buffer);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000209}
210
shannon.woods%transgaming.com@gtempaccount.comdae24092013-04-13 03:31:31 +0000211bool Framebuffer::isEnabledColorAttachment(unsigned int colorAttachment) const
212{
Jamie Madille261b442014-06-25 12:42:21 -0400213 return (mColorbuffers[colorAttachment] && mDrawBufferStates[colorAttachment] != GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comdae24092013-04-13 03:31:31 +0000214}
215
216bool Framebuffer::hasEnabledColorAttachment() const
217{
218 for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
219 {
220 if (isEnabledColorAttachment(colorAttachment))
221 {
222 return true;
223 }
224 }
225
226 return false;
227}
228
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000229bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000230{
Geoff Lange4a492b2014-06-19 14:14:41 -0400231 return (mStencilbuffer && mStencilbuffer->getStencilSize() > 0);
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000232}
233
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000234bool Framebuffer::usingExtendedDrawBuffers() const
235{
236 for (unsigned int colorAttachment = 1; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
237 {
238 if (isEnabledColorAttachment(colorAttachment))
239 {
240 return true;
241 }
242 }
243
244 return false;
245}
246
Geoff Lang748f74e2014-12-01 11:25:34 -0500247GLenum Framebuffer::checkStatus(const gl::Data &data) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000248{
Geoff Lang528ce3c2014-12-01 10:44:07 -0500249 // The default framebuffer *must* always be complete, though it may not be
250 // subject to the same rules as application FBOs. ie, it could have 0x0 size.
251 if (mId == 0)
252 {
253 return GL_FRAMEBUFFER_COMPLETE;
254 }
255
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000256 int width = 0;
257 int height = 0;
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000258 unsigned int colorbufferSize = 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000259 int samples = -1;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000260 bool missingAttachment = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000261
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000262 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000263 {
Jamie Madillbb94f342014-06-23 15:23:02 -0400264 const FramebufferAttachment *colorbuffer = mColorbuffers[colorAttachment];
265
266 if (colorbuffer)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000267 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000268 if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000269 {
270 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
271 }
daniel@transgaming.com01868132010-08-24 19:21:17 +0000272
Geoff Langcec35902014-04-16 10:52:36 -0400273 GLenum internalformat = colorbuffer->getInternalFormat();
Jamie Madill48faf802014-11-06 15:27:22 -0500274 const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400275 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Geoff Lang6a1e6b92014-11-06 10:42:45 -0500276 if (colorbuffer->type() == GL_TEXTURE)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000277 {
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400278 if (!formatCaps.renderable)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000279 {
280 return GL_FRAMEBUFFER_UNSUPPORTED;
281 }
282
Geoff Lang5d601382014-07-22 15:14:06 -0400283 if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000284 {
285 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
286 }
287 }
Geoff Lang6a1e6b92014-11-06 10:42:45 -0500288 else if (colorbuffer->type() == GL_RENDERBUFFER)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000289 {
Geoff Lang5d601382014-07-22 15:14:06 -0400290 if (!formatCaps.renderable || formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400291 {
292 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
293 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000294 }
295
296 if (!missingAttachment)
297 {
298 // all color attachments must have the same width and height
299 if (colorbuffer->getWidth() != width || colorbuffer->getHeight() != height)
300 {
301 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
302 }
303
304 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
305 // all color attachments have the same number of samples for the FBO to be complete.
306 if (colorbuffer->getSamples() != samples)
307 {
308 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
309 }
310
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000311 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
312 // in GLES 3.0, there is no such restriction
Jamie Madill48faf802014-11-06 15:27:22 -0500313 if (data.clientVersion < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000314 {
Geoff Lang5d601382014-07-22 15:14:06 -0400315 if (formatInfo.pixelBytes != colorbufferSize)
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000316 {
317 return GL_FRAMEBUFFER_UNSUPPORTED;
318 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000319 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000320 }
321 else
322 {
323 width = colorbuffer->getWidth();
324 height = colorbuffer->getHeight();
325 samples = colorbuffer->getSamples();
Geoff Lang5d601382014-07-22 15:14:06 -0400326 colorbufferSize = formatInfo.pixelBytes;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000327 missingAttachment = false;
328 }
329 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000330 }
331
Jamie Madille261b442014-06-25 12:42:21 -0400332 if (mDepthbuffer)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000333 {
Jamie Madille261b442014-06-25 12:42:21 -0400334 if (mDepthbuffer->getWidth() == 0 || mDepthbuffer->getHeight() == 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000335 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000336 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000337 }
338
Jamie Madille261b442014-06-25 12:42:21 -0400339 GLenum internalformat = mDepthbuffer->getInternalFormat();
Jamie Madill48faf802014-11-06 15:27:22 -0500340 const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400341 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Geoff Lang6a1e6b92014-11-06 10:42:45 -0500342 if (mDepthbuffer->type() == GL_TEXTURE)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000343 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000344 // depth texture attachments require OES/ANGLE_depth_texture
Jamie Madill48faf802014-11-06 15:27:22 -0500345 if (!data.extensions->depthTextures)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000346 {
347 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
348 }
349
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400350 if (!formatCaps.renderable)
Geoff Langcec35902014-04-16 10:52:36 -0400351 {
352 return GL_FRAMEBUFFER_UNSUPPORTED;
353 }
354
Geoff Lang5d601382014-07-22 15:14:06 -0400355 if (formatInfo.depthBits == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000356 {
357 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
358 }
359 }
Geoff Lang6a1e6b92014-11-06 10:42:45 -0500360 else if (mDepthbuffer->type() == GL_RENDERBUFFER)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000361 {
Geoff Lang5d601382014-07-22 15:14:06 -0400362 if (!formatCaps.renderable || formatInfo.depthBits == 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400363 {
364 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
365 }
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000366 }
367
368 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000369 {
Jamie Madille261b442014-06-25 12:42:21 -0400370 width = mDepthbuffer->getWidth();
371 height = mDepthbuffer->getHeight();
372 samples = mDepthbuffer->getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000373 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000374 }
Jamie Madille261b442014-06-25 12:42:21 -0400375 else if (width != mDepthbuffer->getWidth() || height != mDepthbuffer->getHeight())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000376 {
377 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
378 }
Jamie Madille261b442014-06-25 12:42:21 -0400379 else if (samples != mDepthbuffer->getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000380 {
381 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
382 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000383 }
384
Jamie Madille261b442014-06-25 12:42:21 -0400385 if (mStencilbuffer)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000386 {
Jamie Madille261b442014-06-25 12:42:21 -0400387 if (mStencilbuffer->getWidth() == 0 || mStencilbuffer->getHeight() == 0)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000388 {
389 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
390 }
391
Jamie Madille261b442014-06-25 12:42:21 -0400392 GLenum internalformat = mStencilbuffer->getInternalFormat();
Jamie Madill48faf802014-11-06 15:27:22 -0500393 const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400394 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Geoff Lang6a1e6b92014-11-06 10:42:45 -0500395 if (mStencilbuffer->type() == GL_TEXTURE)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000396 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000397 // texture stencil attachments come along as part
398 // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
Jamie Madill48faf802014-11-06 15:27:22 -0500399 if (!data.extensions->depthTextures)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000400 {
401 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
402 }
403
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400404 if (!formatCaps.renderable)
Geoff Langcec35902014-04-16 10:52:36 -0400405 {
406 return GL_FRAMEBUFFER_UNSUPPORTED;
407 }
408
Geoff Lang5d601382014-07-22 15:14:06 -0400409 if (formatInfo.stencilBits == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000410 {
411 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
412 }
413 }
Geoff Lang6a1e6b92014-11-06 10:42:45 -0500414 else if (mStencilbuffer->type() == GL_RENDERBUFFER)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000415 {
Geoff Lang5d601382014-07-22 15:14:06 -0400416 if (!formatCaps.renderable || formatInfo.stencilBits == 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400417 {
418 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
419 }
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000420 }
421
422 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000423 {
Jamie Madille261b442014-06-25 12:42:21 -0400424 width = mStencilbuffer->getWidth();
425 height = mStencilbuffer->getHeight();
426 samples = mStencilbuffer->getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000427 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000428 }
Jamie Madille261b442014-06-25 12:42:21 -0400429 else if (width != mStencilbuffer->getWidth() || height != mStencilbuffer->getHeight())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000430 {
431 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
432 }
Jamie Madille261b442014-06-25 12:42:21 -0400433 else if (samples != mStencilbuffer->getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000434 {
435 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
436 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000437 }
438
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000439 // if we have both a depth and stencil buffer, they must refer to the same object
440 // since we only support packed_depth_stencil and not separate depth and stencil
Jamie Madille261b442014-06-25 12:42:21 -0400441 if (mDepthbuffer && mStencilbuffer && !hasValidDepthStencil())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000442 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000443 return GL_FRAMEBUFFER_UNSUPPORTED;
444 }
445
446 // we need to have at least one attachment to be complete
447 if (missingAttachment)
448 {
449 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000450 }
451
Geoff Lang748f74e2014-12-01 11:25:34 -0500452 return mImpl->checkStatus();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000453}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000454
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500455Error Framebuffer::invalidate(size_t count, const GLenum *attachments)
Jamie Madill2d96b9e2014-08-29 15:46:47 -0400456{
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500457 return mImpl->invalidate(count, attachments);
Jamie Madill2d96b9e2014-08-29 15:46:47 -0400458}
459
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500460Error Framebuffer::invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area)
Jamie Madill400a4412014-08-29 15:46:45 -0400461{
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500462 return mImpl->invalidateSub(count, attachments, area);
Jamie Madill400a4412014-08-29 15:46:45 -0400463}
464
Geoff Langb04dc822014-12-01 12:02:02 -0500465Error Framebuffer::clear(const State &state, GLbitfield mask)
466{
467 return mImpl->clear(state, mask);
468}
469
470Error Framebuffer::clearBufferfv(const State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values)
471{
472 return mImpl->clearBufferfv(state, buffer, drawbuffer, values);
473}
474
475Error Framebuffer::clearBufferuiv(const State &state, GLenum buffer, GLint drawbuffer, const GLuint *values)
476{
477 return mImpl->clearBufferuiv(state, buffer, drawbuffer, values);
478}
479
480Error Framebuffer::clearBufferiv(const State &state, GLenum buffer, GLint drawbuffer, const GLint *values)
481{
482 return mImpl->clearBufferiv(state, buffer, drawbuffer, values);
483}
484
485Error Framebuffer::clearBufferfi(const State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
486{
487 return mImpl->clearBufferfi(state, buffer, drawbuffer, depth, stencil);
488}
489
Geoff Langbce529e2014-12-01 12:48:41 -0500490GLenum Framebuffer::getImplementationColorReadFormat() const
491{
492 return mImpl->getImplementationColorReadFormat();
493}
494
495GLenum Framebuffer::getImplementationColorReadType() const
496{
497 return mImpl->getImplementationColorReadType();
498}
499
500Error Framebuffer::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const
501{
502 return mImpl->readPixels(state, area, format, type, pixels);
503}
504
Geoff Lang54bd5a42014-12-01 12:51:04 -0500505Error Framebuffer::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
506 GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer)
507{
508 return mImpl->blit(state, sourceArea, destArea, mask, filter, sourceFramebuffer);
509}
510
Jamie Madill48faf802014-11-06 15:27:22 -0500511int Framebuffer::getSamples(const gl::Data &data) const
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000512{
Geoff Lang748f74e2014-12-01 11:25:34 -0500513 if (checkStatus(data) == GL_FRAMEBUFFER_COMPLETE)
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000514 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000515 // for a complete framebuffer, all attachments must have the same sample count
516 // in this case return the first nonzero sample size
517 for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
518 {
Jamie Madille261b442014-06-25 12:42:21 -0400519 if (mColorbuffers[colorAttachment])
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000520 {
Jamie Madille261b442014-06-25 12:42:21 -0400521 return mColorbuffers[colorAttachment]->getSamples();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000522 }
523 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000524 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000525
526 return 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000527}
528
Jamie Madille261b442014-06-25 12:42:21 -0400529bool Framebuffer::hasValidDepthStencil() const
530{
531 // A valid depth-stencil attachment has the same resource bound to both the
532 // depth and stencil attachment points.
533 return (mDepthbuffer && mStencilbuffer &&
534 mDepthbuffer->type() == mStencilbuffer->type() &&
535 mDepthbuffer->id() == mStencilbuffer->id());
536}
537
Jamie Madill48faf802014-11-06 15:27:22 -0500538ColorbufferInfo Framebuffer::getColorbuffersForRender(const rx::Workarounds &workarounds) const
Jamie Madillce20c7f2014-09-03 11:56:29 -0400539{
540 ColorbufferInfo colorbuffersForRender;
541
542 for (size_t colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; ++colorAttachment)
543 {
544 GLenum drawBufferState = mDrawBufferStates[colorAttachment];
545 FramebufferAttachment *colorbuffer = mColorbuffers[colorAttachment];
546
547 if (colorbuffer != NULL && drawBufferState != GL_NONE)
548 {
549 ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + colorAttachment));
550 colorbuffersForRender.push_back(colorbuffer);
551 }
Jamie Madill48faf802014-11-06 15:27:22 -0500552 else if (!workarounds.mrtPerfWorkaround)
Jamie Madillce20c7f2014-09-03 11:56:29 -0400553 {
554 colorbuffersForRender.push_back(NULL);
555 }
556 }
557
558 return colorbuffersForRender;
559}
560
Geoff Langab75a052014-10-15 12:56:37 -0400561void Framebuffer::setTextureAttachment(GLenum attachment, Texture *texture, const ImageIndex &imageIndex)
562{
563 setAttachment(attachment, new TextureAttachment(attachment, texture, imageIndex));
564}
565
566void Framebuffer::setRenderbufferAttachment(GLenum attachment, Renderbuffer *renderbuffer)
567{
568 setAttachment(attachment, new RenderbufferAttachment(attachment, renderbuffer));
569}
570
571void Framebuffer::setNULLAttachment(GLenum attachment)
572{
573 setAttachment(attachment, NULL);
574}
575
576void Framebuffer::setAttachment(GLenum attachment, FramebufferAttachment *attachmentObj)
577{
578 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment < (GL_COLOR_ATTACHMENT0 + IMPLEMENTATION_MAX_DRAW_BUFFERS))
579 {
580 size_t colorAttachment = attachment - GL_COLOR_ATTACHMENT0;
581 SafeDelete(mColorbuffers[colorAttachment]);
582 mColorbuffers[colorAttachment] = attachmentObj;
Geoff Lang9dd95802014-12-01 11:12:59 -0500583 mImpl->setColorAttachment(colorAttachment, attachmentObj);
Geoff Langab75a052014-10-15 12:56:37 -0400584 }
Geoff Lang528ce3c2014-12-01 10:44:07 -0500585 else if (attachment == GL_BACK)
586 {
587 SafeDelete(mColorbuffers[0]);
588 mColorbuffers[0] = attachmentObj;
Geoff Lang9dd95802014-12-01 11:12:59 -0500589 mImpl->setColorAttachment(0, attachmentObj);
Geoff Lang528ce3c2014-12-01 10:44:07 -0500590 }
591 else if (attachment == GL_DEPTH_ATTACHMENT || attachment == GL_DEPTH)
Geoff Langab75a052014-10-15 12:56:37 -0400592 {
593 SafeDelete(mDepthbuffer);
594 mDepthbuffer = attachmentObj;
Geoff Lang9dd95802014-12-01 11:12:59 -0500595 mImpl->setDepthttachment(attachmentObj);
Geoff Langab75a052014-10-15 12:56:37 -0400596 }
Geoff Lang528ce3c2014-12-01 10:44:07 -0500597 else if (attachment == GL_STENCIL_ATTACHMENT || attachment == GL_STENCIL)
Geoff Langab75a052014-10-15 12:56:37 -0400598 {
599 SafeDelete(mStencilbuffer);
600 mStencilbuffer = attachmentObj;
Geoff Lang9dd95802014-12-01 11:12:59 -0500601 mImpl->setStencilAttachment(attachmentObj);
Geoff Langab75a052014-10-15 12:56:37 -0400602 }
Geoff Lang528ce3c2014-12-01 10:44:07 -0500603 else if (attachment == GL_DEPTH_STENCIL_ATTACHMENT || attachment == GL_DEPTH_STENCIL)
Geoff Langab75a052014-10-15 12:56:37 -0400604 {
605 SafeDelete(mDepthbuffer);
606 SafeDelete(mStencilbuffer);
607
608 // ensure this is a legitimate depth+stencil format
609 if (attachmentObj && attachmentObj->getDepthSize() > 0 && attachmentObj->getStencilSize() > 0)
610 {
611 mDepthbuffer = attachmentObj;
Geoff Lang9dd95802014-12-01 11:12:59 -0500612 mImpl->setDepthttachment(attachmentObj);
Geoff Langab75a052014-10-15 12:56:37 -0400613
614 // Make a new attachment object to ensure we do not double-delete
615 // See angle issue 686
Geoff Lang6a1e6b92014-11-06 10:42:45 -0500616 if (attachmentObj->type() == GL_TEXTURE)
Geoff Langab75a052014-10-15 12:56:37 -0400617 {
618 mStencilbuffer = new TextureAttachment(GL_DEPTH_STENCIL_ATTACHMENT, attachmentObj->getTexture(),
619 *attachmentObj->getTextureImageIndex());
Geoff Lang9dd95802014-12-01 11:12:59 -0500620 mImpl->setStencilAttachment(mStencilbuffer);
Geoff Langab75a052014-10-15 12:56:37 -0400621 }
Geoff Lang6a1e6b92014-11-06 10:42:45 -0500622 else if (attachmentObj->type() == GL_RENDERBUFFER)
Geoff Langab75a052014-10-15 12:56:37 -0400623 {
624 mStencilbuffer = new RenderbufferAttachment(GL_DEPTH_STENCIL_ATTACHMENT, attachmentObj->getRenderbuffer());
Geoff Lang9dd95802014-12-01 11:12:59 -0500625 mImpl->setStencilAttachment(mStencilbuffer);
Geoff Langab75a052014-10-15 12:56:37 -0400626 }
Geoff Lang6a1e6b92014-11-06 10:42:45 -0500627 else
628 {
629 UNREACHABLE();
630 }
Geoff Langab75a052014-10-15 12:56:37 -0400631 }
632 }
633 else
634 {
635 UNREACHABLE();
636 }
637}
638
Geoff Lang528ce3c2014-12-01 10:44:07 -0500639DefaultFramebuffer::DefaultFramebuffer(rx::FramebufferImpl *impl, rx::DefaultAttachmentImpl *colorAttachment,
640 rx::DefaultAttachmentImpl *depthAttachment, rx::DefaultAttachmentImpl *stencilAttachment)
641 : Framebuffer(impl, 0)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000642{
Geoff Lang528ce3c2014-12-01 10:44:07 -0500643 ASSERT(colorAttachment);
644 setAttachment(GL_BACK, new DefaultAttachment(GL_BACK, colorAttachment));
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000645
Geoff Lang528ce3c2014-12-01 10:44:07 -0500646 if (depthAttachment)
Jamie Madille92a3542014-07-03 10:38:58 -0400647 {
Geoff Lang528ce3c2014-12-01 10:44:07 -0500648 setAttachment(GL_DEPTH, new DefaultAttachment(GL_DEPTH, depthAttachment));
Jamie Madille92a3542014-07-03 10:38:58 -0400649 }
Geoff Lang528ce3c2014-12-01 10:44:07 -0500650 if (stencilAttachment)
651 {
652 setAttachment(GL_STENCIL, new DefaultAttachment(GL_STENCIL, stencilAttachment));
653 }
654
Geoff Lang9dd95802014-12-01 11:12:59 -0500655 GLenum drawBufferState = GL_BACK;
656 setDrawBuffers(1, &drawBufferState);
657
658 setReadBuffer(GL_BACK);
Jamie Madille92a3542014-07-03 10:38:58 -0400659}
660
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000661}