blob: 2a8fe8b2d4392cf94c0c07add356ec7f8598aab2 [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"
Jamie Madillc46f45d2015-03-31 13:20:55 -040011
Jamie Madillcc86d642015-11-24 13:00:07 -050012#include "common/Optional.h"
Jamie Madillc46f45d2015-03-31 13:20:55 -040013#include "common/utilities.h"
14#include "libANGLE/Config.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050015#include "libANGLE/Context.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050016#include "libANGLE/FramebufferAttachment.h"
Jamie Madillc46f45d2015-03-31 13:20:55 -040017#include "libANGLE/Renderbuffer.h"
18#include "libANGLE/Surface.h"
19#include "libANGLE/Texture.h"
20#include "libANGLE/formatutils.h"
Geoff Langb5d8f232014-12-04 15:43:01 -050021#include "libANGLE/renderer/FramebufferImpl.h"
Jamie Madill48115b62015-03-16 10:46:57 -040022#include "libANGLE/renderer/ImplFactory.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050023#include "libANGLE/renderer/RenderbufferImpl.h"
Corentin Wallez37c39792015-08-20 14:19:46 -040024#include "libANGLE/renderer/SurfaceImpl.h"
Geoff Lang0b7eef72014-06-12 14:10:47 -040025
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000026namespace gl
27{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000028
Jamie Madilld1405e52015-03-05 15:41:39 -050029namespace
30{
Jamie Madill2d06b732015-04-20 12:53:28 -040031void DetachMatchingAttachment(FramebufferAttachment *attachment, GLenum matchType, GLuint matchId)
Jamie Madilld1405e52015-03-05 15:41:39 -050032{
Jamie Madill2d06b732015-04-20 12:53:28 -040033 if (attachment->isAttached() &&
34 attachment->type() == matchType &&
35 attachment->id() == matchId)
Jamie Madilld1405e52015-03-05 15:41:39 -050036 {
Jamie Madill2d06b732015-04-20 12:53:28 -040037 attachment->detach();
Jamie Madilld1405e52015-03-05 15:41:39 -050038 }
39}
40}
41
Corentin Wallez37c39792015-08-20 14:19:46 -040042Framebuffer::Data::Data()
Geoff Lang70d0f492015-12-10 17:45:46 -050043 : mLabel(),
44 mColorAttachments(1),
Corentin Wallez37c39792015-08-20 14:19:46 -040045 mDrawBufferStates(1, GL_NONE),
46 mReadBufferState(GL_COLOR_ATTACHMENT0_EXT)
47{
48 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
49}
50
Jamie Madilld1405e52015-03-05 15:41:39 -050051Framebuffer::Data::Data(const Caps &caps)
Geoff Lang70d0f492015-12-10 17:45:46 -050052 : mLabel(),
53 mColorAttachments(caps.maxColorAttachments),
Jamie Madilld1405e52015-03-05 15:41:39 -050054 mDrawBufferStates(caps.maxDrawBuffers, GL_NONE),
55 mReadBufferState(GL_COLOR_ATTACHMENT0_EXT)
56{
57 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
58}
59
60Framebuffer::Data::~Data()
61{
Jamie Madilld1405e52015-03-05 15:41:39 -050062}
63
Geoff Lang70d0f492015-12-10 17:45:46 -050064const std::string &Framebuffer::Data::getLabel()
65{
66 return mLabel;
67}
68
Jamie Madillb6bda4a2015-04-20 12:53:26 -040069const FramebufferAttachment *Framebuffer::Data::getReadAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -050070{
71 ASSERT(mReadBufferState == GL_BACK || (mReadBufferState >= GL_COLOR_ATTACHMENT0 && mReadBufferState <= GL_COLOR_ATTACHMENT15));
72 size_t readIndex = (mReadBufferState == GL_BACK ? 0 : static_cast<size_t>(mReadBufferState - GL_COLOR_ATTACHMENT0));
73 ASSERT(readIndex < mColorAttachments.size());
Jamie Madill2d06b732015-04-20 12:53:28 -040074 return mColorAttachments[readIndex].isAttached() ? &mColorAttachments[readIndex] : nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -050075}
76
Jamie Madillb6bda4a2015-04-20 12:53:26 -040077const FramebufferAttachment *Framebuffer::Data::getFirstColorAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -050078{
Jamie Madill2d06b732015-04-20 12:53:28 -040079 for (const FramebufferAttachment &colorAttachment : mColorAttachments)
Jamie Madill7147f012015-03-05 15:41:40 -050080 {
Jamie Madill2d06b732015-04-20 12:53:28 -040081 if (colorAttachment.isAttached())
Jamie Madill7147f012015-03-05 15:41:40 -050082 {
Jamie Madill2d06b732015-04-20 12:53:28 -040083 return &colorAttachment;
Jamie Madill7147f012015-03-05 15:41:40 -050084 }
85 }
86
87 return nullptr;
88}
89
Jamie Madillb6bda4a2015-04-20 12:53:26 -040090const FramebufferAttachment *Framebuffer::Data::getDepthOrStencilAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -050091{
Jamie Madill2d06b732015-04-20 12:53:28 -040092 if (mDepthAttachment.isAttached())
93 {
94 return &mDepthAttachment;
95 }
96 if (mStencilAttachment.isAttached())
97 {
98 return &mStencilAttachment;
99 }
100 return nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500101}
102
Corentin Wallez37c39792015-08-20 14:19:46 -0400103const FramebufferAttachment *Framebuffer::Data::getColorAttachment(size_t colorAttachment) const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400104{
105 ASSERT(colorAttachment < mColorAttachments.size());
Jamie Madill2d06b732015-04-20 12:53:28 -0400106 return mColorAttachments[colorAttachment].isAttached() ?
107 &mColorAttachments[colorAttachment] :
108 nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400109}
110
Jamie Madille3ef7152015-04-28 16:55:17 +0000111const FramebufferAttachment *Framebuffer::Data::getDepthAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400112{
Jamie Madill2d06b732015-04-20 12:53:28 -0400113 return mDepthAttachment.isAttached() ? &mDepthAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400114}
115
Jamie Madille3ef7152015-04-28 16:55:17 +0000116const FramebufferAttachment *Framebuffer::Data::getStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400117{
Jamie Madill2d06b732015-04-20 12:53:28 -0400118 return mStencilAttachment.isAttached() ? &mStencilAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400119}
120
Jamie Madille3ef7152015-04-28 16:55:17 +0000121const FramebufferAttachment *Framebuffer::Data::getDepthStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400122{
123 // A valid depth-stencil attachment has the same resource bound to both the
124 // depth and stencil attachment points.
Jamie Madill2d06b732015-04-20 12:53:28 -0400125 if (mDepthAttachment.isAttached() && mStencilAttachment.isAttached() &&
126 mDepthAttachment.type() == mStencilAttachment.type() &&
127 mDepthAttachment.id() == mStencilAttachment.id())
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400128 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400129 return &mDepthAttachment;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400130 }
131
132 return nullptr;
133}
134
Jamie Madillcc86d642015-11-24 13:00:07 -0500135bool Framebuffer::Data::attachmentsHaveSameDimensions() const
136{
137 Optional<Extents> attachmentSize;
138
139 auto hasMismatchedSize = [&attachmentSize](const FramebufferAttachment &attachment)
140 {
141 if (!attachment.isAttached())
142 {
143 return false;
144 }
145
146 if (!attachmentSize.valid())
147 {
148 attachmentSize = attachment.getSize();
149 return false;
150 }
151
152 return (attachment.getSize() != attachmentSize.value());
153 };
154
155 for (const auto &attachment : mColorAttachments)
156 {
157 if (hasMismatchedSize(attachment))
158 {
159 return false;
160 }
161 }
162
163 if (hasMismatchedSize(mDepthAttachment))
164 {
165 return false;
166 }
167
168 return !hasMismatchedSize(mStencilAttachment);
169}
170
Jamie Madill48115b62015-03-16 10:46:57 -0400171Framebuffer::Framebuffer(const Caps &caps, rx::ImplFactory *factory, GLuint id)
Corentin Wallez37c39792015-08-20 14:19:46 -0400172 : mData(caps), mImpl(factory->createFramebuffer(mData)), mId(id)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000173{
Corentin Wallez37c39792015-08-20 14:19:46 -0400174 ASSERT(mId != 0);
175 ASSERT(mImpl != nullptr);
176}
177
178Framebuffer::Framebuffer(rx::SurfaceImpl *surface)
179 : mData(), mImpl(surface->createDefaultFramebuffer(mData)), mId(0)
180{
Geoff Langda88add2014-12-01 10:22:01 -0500181 ASSERT(mImpl != nullptr);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000182}
183
184Framebuffer::~Framebuffer()
185{
Geoff Langda88add2014-12-01 10:22:01 -0500186 SafeDelete(mImpl);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000187}
188
Geoff Lang70d0f492015-12-10 17:45:46 -0500189void Framebuffer::setLabel(const std::string &label)
190{
191 mData.mLabel = label;
192}
193
194const std::string &Framebuffer::getLabel() const
195{
196 return mData.mLabel;
197}
198
Jamie Madille261b442014-06-25 12:42:21 -0400199void Framebuffer::detachTexture(GLuint textureId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000200{
Jamie Madilld1405e52015-03-05 15:41:39 -0500201 detachResourceById(GL_TEXTURE, textureId);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000202}
203
Jamie Madille261b442014-06-25 12:42:21 -0400204void Framebuffer::detachRenderbuffer(GLuint renderbufferId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000205{
Jamie Madilld1405e52015-03-05 15:41:39 -0500206 detachResourceById(GL_RENDERBUFFER, renderbufferId);
207}
Jamie Madille261b442014-06-25 12:42:21 -0400208
Jamie Madilld1405e52015-03-05 15:41:39 -0500209void Framebuffer::detachResourceById(GLenum resourceType, GLuint resourceId)
210{
211 for (auto &colorAttachment : mData.mColorAttachments)
212 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400213 DetachMatchingAttachment(&colorAttachment, resourceType, resourceId);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000214 }
215
Jamie Madill2d06b732015-04-20 12:53:28 -0400216 DetachMatchingAttachment(&mData.mDepthAttachment, resourceType, resourceId);
217 DetachMatchingAttachment(&mData.mStencilAttachment, resourceType, resourceId);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000218}
219
Corentin Wallez37c39792015-08-20 14:19:46 -0400220const FramebufferAttachment *Framebuffer::getColorbuffer(size_t colorAttachment) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000221{
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400222 return mData.getColorAttachment(colorAttachment);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000223}
224
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400225const FramebufferAttachment *Framebuffer::getDepthbuffer() const
Geoff Lang646559f2013-08-15 11:08:15 -0400226{
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400227 return mData.getDepthAttachment();
Geoff Lang646559f2013-08-15 11:08:15 -0400228}
229
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400230const FramebufferAttachment *Framebuffer::getStencilbuffer() const
231{
232 return mData.getStencilAttachment();
233}
234
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400235const FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
236{
237 return mData.getDepthStencilAttachment();
238}
239
240const FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000241{
Jamie Madill7147f012015-03-05 15:41:40 -0500242 return mData.getDepthOrStencilAttachment();
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000243}
244
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400245const FramebufferAttachment *Framebuffer::getReadColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000246{
Jamie Madill7147f012015-03-05 15:41:40 -0500247 return mData.getReadAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000248}
249
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000250GLenum Framebuffer::getReadColorbufferType() const
251{
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400252 const FramebufferAttachment *readAttachment = mData.getReadAttachment();
253 return (readAttachment != nullptr ? readAttachment->type() : GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000254}
255
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400256const FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000257{
Jamie Madill7147f012015-03-05 15:41:40 -0500258 return mData.getFirstColorAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000259}
260
Jamie Madill2d06b732015-04-20 12:53:28 -0400261const FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000262{
Jamie Madille92a3542014-07-03 10:38:58 -0400263 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
264 {
Jamie Madille3ef7152015-04-28 16:55:17 +0000265 return mData.getColorAttachment(attachment - GL_COLOR_ATTACHMENT0);
Jamie Madille92a3542014-07-03 10:38:58 -0400266 }
267 else
268 {
269 switch (attachment)
270 {
Geoff Lang528ce3c2014-12-01 10:44:07 -0500271 case GL_COLOR:
272 case GL_BACK:
Jamie Madille3ef7152015-04-28 16:55:17 +0000273 return mData.getColorAttachment(0);
Geoff Lang528ce3c2014-12-01 10:44:07 -0500274 case GL_DEPTH:
Jamie Madille92a3542014-07-03 10:38:58 -0400275 case GL_DEPTH_ATTACHMENT:
Jamie Madille3ef7152015-04-28 16:55:17 +0000276 return mData.getDepthAttachment();
Geoff Lang528ce3c2014-12-01 10:44:07 -0500277 case GL_STENCIL:
Jamie Madille92a3542014-07-03 10:38:58 -0400278 case GL_STENCIL_ATTACHMENT:
Jamie Madille3ef7152015-04-28 16:55:17 +0000279 return mData.getStencilAttachment();
Geoff Lang528ce3c2014-12-01 10:44:07 -0500280 case GL_DEPTH_STENCIL:
Jamie Madille92a3542014-07-03 10:38:58 -0400281 case GL_DEPTH_STENCIL_ATTACHMENT:
282 return getDepthStencilBuffer();
283 default:
284 UNREACHABLE();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400285 return nullptr;
Jamie Madille92a3542014-07-03 10:38:58 -0400286 }
287 }
Geoff Lang55ba29c2013-07-11 16:57:53 -0400288}
289
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000290GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const
291{
Jamie Madilld1405e52015-03-05 15:41:39 -0500292 ASSERT(colorAttachment < mData.mDrawBufferStates.size());
293 return mData.mDrawBufferStates[colorAttachment];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000294}
295
Geoff Lang164d54e2014-12-01 10:55:33 -0500296void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000297{
Jamie Madilld1405e52015-03-05 15:41:39 -0500298 auto &drawStates = mData.mDrawBufferStates;
299
300 ASSERT(count <= drawStates.size());
301 std::copy(buffers, buffers + count, drawStates.begin());
302 std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500303 mDirtyBits.set(DIRTY_BIT_DRAW_BUFFERS);
Geoff Lang9dd95802014-12-01 11:12:59 -0500304}
305
306GLenum Framebuffer::getReadBufferState() const
307{
Jamie Madilld1405e52015-03-05 15:41:39 -0500308 return mData.mReadBufferState;
Geoff Lang9dd95802014-12-01 11:12:59 -0500309}
310
311void Framebuffer::setReadBuffer(GLenum buffer)
312{
Jamie Madillb885e572015-02-03 16:16:04 -0500313 ASSERT(buffer == GL_BACK || buffer == GL_NONE ||
314 (buffer >= GL_COLOR_ATTACHMENT0 &&
Jamie Madilld1405e52015-03-05 15:41:39 -0500315 (buffer - GL_COLOR_ATTACHMENT0) < mData.mColorAttachments.size()));
316 mData.mReadBufferState = buffer;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500317 mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000318}
319
Corentin Wallez37c39792015-08-20 14:19:46 -0400320bool Framebuffer::isEnabledColorAttachment(size_t colorAttachment) const
shannon.woods%transgaming.com@gtempaccount.comdae24092013-04-13 03:31:31 +0000321{
Jamie Madilld1405e52015-03-05 15:41:39 -0500322 ASSERT(colorAttachment < mData.mColorAttachments.size());
Jamie Madill2d06b732015-04-20 12:53:28 -0400323 return (mData.mColorAttachments[colorAttachment].isAttached() &&
Jamie Madilld1405e52015-03-05 15:41:39 -0500324 mData.mDrawBufferStates[colorAttachment] != GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comdae24092013-04-13 03:31:31 +0000325}
326
327bool Framebuffer::hasEnabledColorAttachment() const
328{
Jamie Madilld1405e52015-03-05 15:41:39 -0500329 for (size_t colorAttachment = 0; colorAttachment < mData.mColorAttachments.size(); ++colorAttachment)
shannon.woods%transgaming.com@gtempaccount.comdae24092013-04-13 03:31:31 +0000330 {
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700331 if (isEnabledColorAttachment(static_cast<unsigned int>(colorAttachment)))
shannon.woods%transgaming.com@gtempaccount.comdae24092013-04-13 03:31:31 +0000332 {
333 return true;
334 }
335 }
336
337 return false;
338}
339
Corentin Wallez37c39792015-08-20 14:19:46 -0400340size_t Framebuffer::getNumColorBuffers() const
341{
342 return mData.mColorAttachments.size();
343}
344
Jamie Madill0df8fe42015-11-24 16:10:24 -0500345bool Framebuffer::hasDepth() const
346{
347 return (mData.mDepthAttachment.isAttached() && mData.mDepthAttachment.getDepthSize() > 0);
348}
349
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000350bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000351{
Jamie Madill2d06b732015-04-20 12:53:28 -0400352 return (mData.mStencilAttachment.isAttached() && mData.mStencilAttachment.getStencilSize() > 0);
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000353}
354
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000355bool Framebuffer::usingExtendedDrawBuffers() const
356{
Jamie Madilld1405e52015-03-05 15:41:39 -0500357 for (size_t colorAttachment = 1; colorAttachment < mData.mColorAttachments.size(); ++colorAttachment)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000358 {
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700359 if (isEnabledColorAttachment(static_cast<unsigned int>(colorAttachment)))
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000360 {
361 return true;
362 }
363 }
364
365 return false;
366}
367
Geoff Lang748f74e2014-12-01 11:25:34 -0500368GLenum Framebuffer::checkStatus(const gl::Data &data) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000369{
Geoff Lang528ce3c2014-12-01 10:44:07 -0500370 // The default framebuffer *must* always be complete, though it may not be
371 // subject to the same rules as application FBOs. ie, it could have 0x0 size.
372 if (mId == 0)
373 {
374 return GL_FRAMEBUFFER_COMPLETE;
375 }
376
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000377 unsigned int colorbufferSize = 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000378 int samples = -1;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000379 bool missingAttachment = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000380
Jamie Madill2d06b732015-04-20 12:53:28 -0400381 for (const FramebufferAttachment &colorAttachment : mData.mColorAttachments)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000382 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400383 if (colorAttachment.isAttached())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000384 {
Jamie Madill6b120b92015-11-24 13:00:07 -0500385 const Extents &size = colorAttachment.getSize();
386 if (size.width == 0 || size.height == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000387 {
388 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
389 }
daniel@transgaming.com01868132010-08-24 19:21:17 +0000390
Jamie Madill2d06b732015-04-20 12:53:28 -0400391 GLenum internalformat = colorAttachment.getInternalFormat();
Jamie Madill48faf802014-11-06 15:27:22 -0500392 const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400393 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill2d06b732015-04-20 12:53:28 -0400394 if (colorAttachment.type() == GL_TEXTURE)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000395 {
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400396 if (!formatCaps.renderable)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000397 {
Jamie Madill81176782015-11-24 16:10:23 -0500398 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000399 }
400
Geoff Lang5d601382014-07-22 15:14:06 -0400401 if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000402 {
403 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
404 }
Jamie Madill6b120b92015-11-24 13:00:07 -0500405
406 if (colorAttachment.layer() >= size.depth)
407 {
408 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
409 }
Jamie Madill3215b202015-12-15 16:41:39 -0500410
411 // ES3 specifies that cube map texture attachments must be cube complete.
412 // This language is missing from the ES2 spec, but we enforce it here because some
413 // desktop OpenGL drivers also enforce this validation.
414 // TODO(jmadill): Check if OpenGL ES2 drivers enforce cube completeness.
415 const Texture *texture = colorAttachment.getTexture();
416 ASSERT(texture);
417 if (texture->getTarget() == GL_TEXTURE_CUBE_MAP && !texture->isCubeComplete())
418 {
419 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
420 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000421 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400422 else if (colorAttachment.type() == GL_RENDERBUFFER)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000423 {
Geoff Lang5d601382014-07-22 15:14:06 -0400424 if (!formatCaps.renderable || formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400425 {
426 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
427 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000428 }
429
430 if (!missingAttachment)
431 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000432 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
433 // all color attachments have the same number of samples for the FBO to be complete.
Jamie Madill2d06b732015-04-20 12:53:28 -0400434 if (colorAttachment.getSamples() != samples)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000435 {
436 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
437 }
438
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000439 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
440 // in GLES 3.0, there is no such restriction
Jamie Madill48faf802014-11-06 15:27:22 -0500441 if (data.clientVersion < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000442 {
Geoff Lang5d601382014-07-22 15:14:06 -0400443 if (formatInfo.pixelBytes != colorbufferSize)
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000444 {
445 return GL_FRAMEBUFFER_UNSUPPORTED;
446 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000447 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000448 }
449 else
450 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400451 samples = colorAttachment.getSamples();
Geoff Lang5d601382014-07-22 15:14:06 -0400452 colorbufferSize = formatInfo.pixelBytes;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000453 missingAttachment = false;
454 }
455 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000456 }
457
Jamie Madill2d06b732015-04-20 12:53:28 -0400458 const FramebufferAttachment &depthAttachment = mData.mDepthAttachment;
459 if (depthAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000460 {
Jamie Madill6b120b92015-11-24 13:00:07 -0500461 const Extents &size = depthAttachment.getSize();
462 if (size.width == 0 || size.height == 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000463 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000464 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000465 }
466
Jamie Madill2d06b732015-04-20 12:53:28 -0400467 GLenum internalformat = depthAttachment.getInternalFormat();
Jamie Madill48faf802014-11-06 15:27:22 -0500468 const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400469 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill2d06b732015-04-20 12:53:28 -0400470 if (depthAttachment.type() == GL_TEXTURE)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000471 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000472 // depth texture attachments require OES/ANGLE_depth_texture
Jamie Madill48faf802014-11-06 15:27:22 -0500473 if (!data.extensions->depthTextures)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000474 {
475 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
476 }
477
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400478 if (!formatCaps.renderable)
Geoff Langcec35902014-04-16 10:52:36 -0400479 {
Jamie Madill81176782015-11-24 16:10:23 -0500480 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
Geoff Langcec35902014-04-16 10:52:36 -0400481 }
482
Geoff Lang5d601382014-07-22 15:14:06 -0400483 if (formatInfo.depthBits == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000484 {
485 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
486 }
487 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400488 else if (depthAttachment.type() == GL_RENDERBUFFER)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000489 {
Geoff Lang5d601382014-07-22 15:14:06 -0400490 if (!formatCaps.renderable || formatInfo.depthBits == 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400491 {
492 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
493 }
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000494 }
495
496 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000497 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400498 samples = depthAttachment.getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000499 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000500 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400501 else if (samples != depthAttachment.getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000502 {
503 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
504 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000505 }
506
Jamie Madill2d06b732015-04-20 12:53:28 -0400507 const FramebufferAttachment &stencilAttachment = mData.mStencilAttachment;
508 if (stencilAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000509 {
Jamie Madill6b120b92015-11-24 13:00:07 -0500510 const Extents &size = stencilAttachment.getSize();
511 if (size.width == 0 || size.height == 0)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000512 {
513 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
514 }
515
Jamie Madill2d06b732015-04-20 12:53:28 -0400516 GLenum internalformat = stencilAttachment.getInternalFormat();
Jamie Madill48faf802014-11-06 15:27:22 -0500517 const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400518 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill2d06b732015-04-20 12:53:28 -0400519 if (stencilAttachment.type() == GL_TEXTURE)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000520 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000521 // texture stencil attachments come along as part
522 // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
Jamie Madill48faf802014-11-06 15:27:22 -0500523 if (!data.extensions->depthTextures)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000524 {
525 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
526 }
527
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400528 if (!formatCaps.renderable)
Geoff Langcec35902014-04-16 10:52:36 -0400529 {
Jamie Madill81176782015-11-24 16:10:23 -0500530 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
Geoff Langcec35902014-04-16 10:52:36 -0400531 }
532
Geoff Lang5d601382014-07-22 15:14:06 -0400533 if (formatInfo.stencilBits == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000534 {
535 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
536 }
537 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400538 else if (stencilAttachment.type() == GL_RENDERBUFFER)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000539 {
Geoff Lang5d601382014-07-22 15:14:06 -0400540 if (!formatCaps.renderable || formatInfo.stencilBits == 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400541 {
542 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
543 }
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000544 }
545
546 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000547 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400548 samples = stencilAttachment.getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000549 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000550 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400551 else if (samples != stencilAttachment.getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000552 {
553 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
554 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000555 }
556
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000557 // we need to have at least one attachment to be complete
558 if (missingAttachment)
559 {
560 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000561 }
562
Jamie Madillcc86d642015-11-24 13:00:07 -0500563 // In ES 2.0, all color attachments must have the same width and height.
564 // In ES 3.0, there is no such restriction.
565 if (data.clientVersion < 3 && !mData.attachmentsHaveSameDimensions())
566 {
567 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
568 }
569
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500570 syncState();
Jamie Madillcc86d642015-11-24 13:00:07 -0500571 if (!mImpl->checkStatus())
572 {
573 return GL_FRAMEBUFFER_UNSUPPORTED;
574 }
575
576 return GL_FRAMEBUFFER_COMPLETE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000577}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000578
Austin Kinross08332632015-05-05 13:35:47 -0700579Error Framebuffer::discard(size_t count, const GLenum *attachments)
580{
581 return mImpl->discard(count, attachments);
582}
583
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500584Error Framebuffer::invalidate(size_t count, const GLenum *attachments)
Jamie Madill2d96b9e2014-08-29 15:46:47 -0400585{
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500586 return mImpl->invalidate(count, attachments);
Jamie Madill2d96b9e2014-08-29 15:46:47 -0400587}
588
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500589Error Framebuffer::invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area)
Jamie Madill400a4412014-08-29 15:46:45 -0400590{
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500591 return mImpl->invalidateSub(count, attachments, area);
Jamie Madill400a4412014-08-29 15:46:45 -0400592}
593
Jamie Madillc29968b2016-01-20 11:17:23 -0500594Error Framebuffer::clear(const gl::Data &data, GLbitfield mask)
Geoff Langb04dc822014-12-01 12:02:02 -0500595{
Jamie Madillc29968b2016-01-20 11:17:23 -0500596 if (data.state->isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500597 {
598 return gl::Error(GL_NO_ERROR);
599 }
600
Jamie Madillc29968b2016-01-20 11:17:23 -0500601 return mImpl->clear(data, mask);
Geoff Langb04dc822014-12-01 12:02:02 -0500602}
603
Jamie Madillc29968b2016-01-20 11:17:23 -0500604Error Framebuffer::clearBufferfv(const gl::Data &data,
Jamie Madill1b94d432015-08-07 13:23:23 -0400605 GLenum buffer,
606 GLint drawbuffer,
607 const GLfloat *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500608{
Jamie Madillc29968b2016-01-20 11:17:23 -0500609 if (data.state->isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500610 {
611 return gl::Error(GL_NO_ERROR);
612 }
613
Jamie Madillc29968b2016-01-20 11:17:23 -0500614 return mImpl->clearBufferfv(data, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500615}
616
Jamie Madillc29968b2016-01-20 11:17:23 -0500617Error Framebuffer::clearBufferuiv(const gl::Data &data,
Jamie Madill1b94d432015-08-07 13:23:23 -0400618 GLenum buffer,
619 GLint drawbuffer,
620 const GLuint *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500621{
Jamie Madillc29968b2016-01-20 11:17:23 -0500622 if (data.state->isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500623 {
624 return gl::Error(GL_NO_ERROR);
625 }
626
Jamie Madillc29968b2016-01-20 11:17:23 -0500627 return mImpl->clearBufferuiv(data, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500628}
629
Jamie Madillc29968b2016-01-20 11:17:23 -0500630Error Framebuffer::clearBufferiv(const gl::Data &data,
Jamie Madill1b94d432015-08-07 13:23:23 -0400631 GLenum buffer,
632 GLint drawbuffer,
633 const GLint *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500634{
Jamie Madillc29968b2016-01-20 11:17:23 -0500635 if (data.state->isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500636 {
637 return gl::Error(GL_NO_ERROR);
638 }
639
Jamie Madillc29968b2016-01-20 11:17:23 -0500640 return mImpl->clearBufferiv(data, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500641}
642
Jamie Madillc29968b2016-01-20 11:17:23 -0500643Error Framebuffer::clearBufferfi(const gl::Data &data,
Jamie Madill1b94d432015-08-07 13:23:23 -0400644 GLenum buffer,
645 GLint drawbuffer,
646 GLfloat depth,
647 GLint stencil)
Geoff Langb04dc822014-12-01 12:02:02 -0500648{
Jamie Madillc29968b2016-01-20 11:17:23 -0500649 if (data.state->isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500650 {
651 return gl::Error(GL_NO_ERROR);
652 }
653
Jamie Madillc29968b2016-01-20 11:17:23 -0500654 return mImpl->clearBufferfi(data, buffer, drawbuffer, depth, stencil);
Geoff Langb04dc822014-12-01 12:02:02 -0500655}
656
Geoff Langbce529e2014-12-01 12:48:41 -0500657GLenum Framebuffer::getImplementationColorReadFormat() const
658{
659 return mImpl->getImplementationColorReadFormat();
660}
661
662GLenum Framebuffer::getImplementationColorReadType() const
663{
664 return mImpl->getImplementationColorReadType();
665}
666
Jamie Madillc29968b2016-01-20 11:17:23 -0500667Error Framebuffer::readPixels(const State &state,
668 const Rectangle &area,
Jamie Madill1b94d432015-08-07 13:23:23 -0400669 GLenum format,
670 GLenum type,
671 GLvoid *pixels) const
Geoff Langbce529e2014-12-01 12:48:41 -0500672{
Geoff Lang520c4ae2015-05-05 13:12:36 -0400673 Error error = mImpl->readPixels(state, area, format, type, pixels);
674 if (error.isError())
675 {
676 return error;
677 }
678
679 Buffer *unpackBuffer = state.getUnpackState().pixelBuffer.get();
680 if (unpackBuffer)
681 {
682 unpackBuffer->onPixelUnpack();
683 }
684
685 return Error(GL_NO_ERROR);
Geoff Langbce529e2014-12-01 12:48:41 -0500686}
687
Jamie Madillc29968b2016-01-20 11:17:23 -0500688Error Framebuffer::blit(const State &state,
689 const Rectangle &sourceArea,
690 const Rectangle &destArea,
Geoff Lang242468f2015-09-24 14:15:41 -0400691 GLbitfield mask,
692 GLenum filter,
Jamie Madillc29968b2016-01-20 11:17:23 -0500693 const Framebuffer *sourceFramebuffer)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500694{
695 return mImpl->blit(state, sourceArea, destArea, mask, filter, sourceFramebuffer);
696}
697
Jamie Madill48faf802014-11-06 15:27:22 -0500698int Framebuffer::getSamples(const gl::Data &data) const
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000699{
Geoff Lang748f74e2014-12-01 11:25:34 -0500700 if (checkStatus(data) == GL_FRAMEBUFFER_COMPLETE)
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000701 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000702 // for a complete framebuffer, all attachments must have the same sample count
703 // in this case return the first nonzero sample size
Jamie Madill2d06b732015-04-20 12:53:28 -0400704 for (const FramebufferAttachment &colorAttachment : mData.mColorAttachments)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000705 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400706 if (colorAttachment.isAttached())
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000707 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400708 return colorAttachment.getSamples();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000709 }
710 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000711 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000712
713 return 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000714}
715
Jamie Madille261b442014-06-25 12:42:21 -0400716bool Framebuffer::hasValidDepthStencil() const
717{
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400718 return mData.getDepthStencilAttachment() != nullptr;
Jamie Madille261b442014-06-25 12:42:21 -0400719}
720
Jamie Madill2d06b732015-04-20 12:53:28 -0400721void Framebuffer::setAttachment(GLenum type,
722 GLenum binding,
723 const ImageIndex &textureIndex,
724 FramebufferAttachmentObject *resource)
Geoff Langab75a052014-10-15 12:56:37 -0400725{
Jamie Madill2d06b732015-04-20 12:53:28 -0400726 if (binding == GL_DEPTH_STENCIL || binding == GL_DEPTH_STENCIL_ATTACHMENT)
Geoff Langab75a052014-10-15 12:56:37 -0400727 {
Geoff Langab75a052014-10-15 12:56:37 -0400728 // ensure this is a legitimate depth+stencil format
Jamie Madill375c37c2015-07-21 15:14:08 -0400729 FramebufferAttachmentObject *attachmentObj = resource;
730 if (resource)
Geoff Langab75a052014-10-15 12:56:37 -0400731 {
Jamie Madill375c37c2015-07-21 15:14:08 -0400732 FramebufferAttachment::Target target(binding, textureIndex);
733 GLenum internalFormat = resource->getAttachmentInternalFormat(target);
734 const InternalFormat &formatInfo = GetInternalFormatInfo(internalFormat);
735 if (formatInfo.depthBits == 0 || formatInfo.stencilBits == 0)
736 {
737 // Attaching nullptr detaches the current attachment.
738 attachmentObj = nullptr;
739 }
Geoff Langab75a052014-10-15 12:56:37 -0400740 }
Jamie Madill375c37c2015-07-21 15:14:08 -0400741
742 mData.mDepthAttachment.attach(type, binding, textureIndex, attachmentObj);
743 mData.mStencilAttachment.attach(type, binding, textureIndex, attachmentObj);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500744 mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT);
745 mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT);
Geoff Langab75a052014-10-15 12:56:37 -0400746 }
747 else
748 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400749 switch (binding)
750 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500751 case GL_DEPTH:
752 case GL_DEPTH_ATTACHMENT:
753 mData.mDepthAttachment.attach(type, binding, textureIndex, resource);
754 mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT);
Jamie Madill2d06b732015-04-20 12:53:28 -0400755 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500756 case GL_STENCIL:
757 case GL_STENCIL_ATTACHMENT:
758 mData.mStencilAttachment.attach(type, binding, textureIndex, resource);
759 mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT);
Jamie Madill2d06b732015-04-20 12:53:28 -0400760 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500761 case GL_BACK:
762 mData.mColorAttachments[0].attach(type, binding, textureIndex, resource);
763 mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0);
Jamie Madill2d06b732015-04-20 12:53:28 -0400764 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500765 default:
Jamie Madill2d06b732015-04-20 12:53:28 -0400766 {
767 size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
768 ASSERT(colorIndex < mData.mColorAttachments.size());
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400769 mData.mColorAttachments[colorIndex].attach(type, binding, textureIndex, resource);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500770 mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
Jamie Madill2d06b732015-04-20 12:53:28 -0400771 }
772 break;
773 }
Geoff Langab75a052014-10-15 12:56:37 -0400774 }
775}
776
Jamie Madill2d06b732015-04-20 12:53:28 -0400777void Framebuffer::resetAttachment(GLenum binding)
778{
779 setAttachment(GL_NONE, binding, ImageIndex::MakeInvalid(), nullptr);
780}
781
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500782void Framebuffer::syncState() const
783{
784 if (mDirtyBits.any())
785 {
786 mImpl->syncState(mDirtyBits);
787 mDirtyBits.reset();
788 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000789}
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500790
791} // namespace gl