blob: c388d1eea43780a970c14478a14f7b8571fb35f8 [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 Lang66988742015-12-22 19:39:19 +000043 : mColorAttachments(1),
Corentin Wallez37c39792015-08-20 14:19:46 -040044 mDrawBufferStates(1, GL_NONE),
45 mReadBufferState(GL_COLOR_ATTACHMENT0_EXT)
46{
47 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
48}
49
Jamie Madilld1405e52015-03-05 15:41:39 -050050Framebuffer::Data::Data(const Caps &caps)
Geoff Lang66988742015-12-22 19:39:19 +000051 : mColorAttachments(caps.maxColorAttachments),
Jamie Madilld1405e52015-03-05 15:41:39 -050052 mDrawBufferStates(caps.maxDrawBuffers, GL_NONE),
53 mReadBufferState(GL_COLOR_ATTACHMENT0_EXT)
54{
55 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
56}
57
58Framebuffer::Data::~Data()
59{
Jamie Madilld1405e52015-03-05 15:41:39 -050060}
61
Jamie Madillb6bda4a2015-04-20 12:53:26 -040062const FramebufferAttachment *Framebuffer::Data::getReadAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -050063{
64 ASSERT(mReadBufferState == GL_BACK || (mReadBufferState >= GL_COLOR_ATTACHMENT0 && mReadBufferState <= GL_COLOR_ATTACHMENT15));
65 size_t readIndex = (mReadBufferState == GL_BACK ? 0 : static_cast<size_t>(mReadBufferState - GL_COLOR_ATTACHMENT0));
66 ASSERT(readIndex < mColorAttachments.size());
Jamie Madill2d06b732015-04-20 12:53:28 -040067 return mColorAttachments[readIndex].isAttached() ? &mColorAttachments[readIndex] : nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -050068}
69
Jamie Madillb6bda4a2015-04-20 12:53:26 -040070const FramebufferAttachment *Framebuffer::Data::getFirstColorAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -050071{
Jamie Madill2d06b732015-04-20 12:53:28 -040072 for (const FramebufferAttachment &colorAttachment : mColorAttachments)
Jamie Madill7147f012015-03-05 15:41:40 -050073 {
Jamie Madill2d06b732015-04-20 12:53:28 -040074 if (colorAttachment.isAttached())
Jamie Madill7147f012015-03-05 15:41:40 -050075 {
Jamie Madill2d06b732015-04-20 12:53:28 -040076 return &colorAttachment;
Jamie Madill7147f012015-03-05 15:41:40 -050077 }
78 }
79
80 return nullptr;
81}
82
Jamie Madillb6bda4a2015-04-20 12:53:26 -040083const FramebufferAttachment *Framebuffer::Data::getDepthOrStencilAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -050084{
Jamie Madill2d06b732015-04-20 12:53:28 -040085 if (mDepthAttachment.isAttached())
86 {
87 return &mDepthAttachment;
88 }
89 if (mStencilAttachment.isAttached())
90 {
91 return &mStencilAttachment;
92 }
93 return nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -050094}
95
Corentin Wallez37c39792015-08-20 14:19:46 -040096const FramebufferAttachment *Framebuffer::Data::getColorAttachment(size_t colorAttachment) const
Jamie Madillb6bda4a2015-04-20 12:53:26 -040097{
98 ASSERT(colorAttachment < mColorAttachments.size());
Jamie Madill2d06b732015-04-20 12:53:28 -040099 return mColorAttachments[colorAttachment].isAttached() ?
100 &mColorAttachments[colorAttachment] :
101 nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400102}
103
Jamie Madille3ef7152015-04-28 16:55:17 +0000104const FramebufferAttachment *Framebuffer::Data::getDepthAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400105{
Jamie Madill2d06b732015-04-20 12:53:28 -0400106 return mDepthAttachment.isAttached() ? &mDepthAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400107}
108
Jamie Madille3ef7152015-04-28 16:55:17 +0000109const FramebufferAttachment *Framebuffer::Data::getStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400110{
Jamie Madill2d06b732015-04-20 12:53:28 -0400111 return mStencilAttachment.isAttached() ? &mStencilAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400112}
113
Jamie Madille3ef7152015-04-28 16:55:17 +0000114const FramebufferAttachment *Framebuffer::Data::getDepthStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400115{
116 // A valid depth-stencil attachment has the same resource bound to both the
117 // depth and stencil attachment points.
Jamie Madill2d06b732015-04-20 12:53:28 -0400118 if (mDepthAttachment.isAttached() && mStencilAttachment.isAttached() &&
119 mDepthAttachment.type() == mStencilAttachment.type() &&
120 mDepthAttachment.id() == mStencilAttachment.id())
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400121 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400122 return &mDepthAttachment;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400123 }
124
125 return nullptr;
126}
127
Jamie Madillcc86d642015-11-24 13:00:07 -0500128bool Framebuffer::Data::attachmentsHaveSameDimensions() const
129{
130 Optional<Extents> attachmentSize;
131
132 auto hasMismatchedSize = [&attachmentSize](const FramebufferAttachment &attachment)
133 {
134 if (!attachment.isAttached())
135 {
136 return false;
137 }
138
139 if (!attachmentSize.valid())
140 {
141 attachmentSize = attachment.getSize();
142 return false;
143 }
144
145 return (attachment.getSize() != attachmentSize.value());
146 };
147
148 for (const auto &attachment : mColorAttachments)
149 {
150 if (hasMismatchedSize(attachment))
151 {
152 return false;
153 }
154 }
155
156 if (hasMismatchedSize(mDepthAttachment))
157 {
158 return false;
159 }
160
161 return !hasMismatchedSize(mStencilAttachment);
162}
163
Jamie Madill48115b62015-03-16 10:46:57 -0400164Framebuffer::Framebuffer(const Caps &caps, rx::ImplFactory *factory, GLuint id)
Corentin Wallez37c39792015-08-20 14:19:46 -0400165 : mData(caps), mImpl(factory->createFramebuffer(mData)), mId(id)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000166{
Corentin Wallez37c39792015-08-20 14:19:46 -0400167 ASSERT(mId != 0);
168 ASSERT(mImpl != nullptr);
169}
170
171Framebuffer::Framebuffer(rx::SurfaceImpl *surface)
172 : mData(), mImpl(surface->createDefaultFramebuffer(mData)), mId(0)
173{
Geoff Langda88add2014-12-01 10:22:01 -0500174 ASSERT(mImpl != nullptr);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000175}
176
177Framebuffer::~Framebuffer()
178{
Geoff Langda88add2014-12-01 10:22:01 -0500179 SafeDelete(mImpl);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000180}
181
Jamie Madille261b442014-06-25 12:42:21 -0400182void Framebuffer::detachTexture(GLuint textureId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000183{
Jamie Madilld1405e52015-03-05 15:41:39 -0500184 detachResourceById(GL_TEXTURE, textureId);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000185}
186
Jamie Madille261b442014-06-25 12:42:21 -0400187void Framebuffer::detachRenderbuffer(GLuint renderbufferId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000188{
Jamie Madilld1405e52015-03-05 15:41:39 -0500189 detachResourceById(GL_RENDERBUFFER, renderbufferId);
190}
Jamie Madille261b442014-06-25 12:42:21 -0400191
Jamie Madilld1405e52015-03-05 15:41:39 -0500192void Framebuffer::detachResourceById(GLenum resourceType, GLuint resourceId)
193{
194 for (auto &colorAttachment : mData.mColorAttachments)
195 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400196 DetachMatchingAttachment(&colorAttachment, resourceType, resourceId);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000197 }
198
Jamie Madill2d06b732015-04-20 12:53:28 -0400199 DetachMatchingAttachment(&mData.mDepthAttachment, resourceType, resourceId);
200 DetachMatchingAttachment(&mData.mStencilAttachment, resourceType, resourceId);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000201}
202
Corentin Wallez37c39792015-08-20 14:19:46 -0400203const FramebufferAttachment *Framebuffer::getColorbuffer(size_t colorAttachment) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000204{
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400205 return mData.getColorAttachment(colorAttachment);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000206}
207
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400208const FramebufferAttachment *Framebuffer::getDepthbuffer() const
Geoff Lang646559f2013-08-15 11:08:15 -0400209{
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400210 return mData.getDepthAttachment();
Geoff Lang646559f2013-08-15 11:08:15 -0400211}
212
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400213const FramebufferAttachment *Framebuffer::getStencilbuffer() const
214{
215 return mData.getStencilAttachment();
216}
217
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400218const FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
219{
220 return mData.getDepthStencilAttachment();
221}
222
223const FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000224{
Jamie Madill7147f012015-03-05 15:41:40 -0500225 return mData.getDepthOrStencilAttachment();
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000226}
227
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400228const FramebufferAttachment *Framebuffer::getReadColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000229{
Jamie Madill7147f012015-03-05 15:41:40 -0500230 return mData.getReadAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000231}
232
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000233GLenum Framebuffer::getReadColorbufferType() const
234{
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400235 const FramebufferAttachment *readAttachment = mData.getReadAttachment();
236 return (readAttachment != nullptr ? readAttachment->type() : GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000237}
238
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400239const FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000240{
Jamie Madill7147f012015-03-05 15:41:40 -0500241 return mData.getFirstColorAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000242}
243
Jamie Madill2d06b732015-04-20 12:53:28 -0400244const FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000245{
Jamie Madille92a3542014-07-03 10:38:58 -0400246 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
247 {
Jamie Madille3ef7152015-04-28 16:55:17 +0000248 return mData.getColorAttachment(attachment - GL_COLOR_ATTACHMENT0);
Jamie Madille92a3542014-07-03 10:38:58 -0400249 }
250 else
251 {
252 switch (attachment)
253 {
Geoff Lang528ce3c2014-12-01 10:44:07 -0500254 case GL_COLOR:
255 case GL_BACK:
Jamie Madille3ef7152015-04-28 16:55:17 +0000256 return mData.getColorAttachment(0);
Geoff Lang528ce3c2014-12-01 10:44:07 -0500257 case GL_DEPTH:
Jamie Madille92a3542014-07-03 10:38:58 -0400258 case GL_DEPTH_ATTACHMENT:
Jamie Madille3ef7152015-04-28 16:55:17 +0000259 return mData.getDepthAttachment();
Geoff Lang528ce3c2014-12-01 10:44:07 -0500260 case GL_STENCIL:
Jamie Madille92a3542014-07-03 10:38:58 -0400261 case GL_STENCIL_ATTACHMENT:
Jamie Madille3ef7152015-04-28 16:55:17 +0000262 return mData.getStencilAttachment();
Geoff Lang528ce3c2014-12-01 10:44:07 -0500263 case GL_DEPTH_STENCIL:
Jamie Madille92a3542014-07-03 10:38:58 -0400264 case GL_DEPTH_STENCIL_ATTACHMENT:
265 return getDepthStencilBuffer();
266 default:
267 UNREACHABLE();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400268 return nullptr;
Jamie Madille92a3542014-07-03 10:38:58 -0400269 }
270 }
Geoff Lang55ba29c2013-07-11 16:57:53 -0400271}
272
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000273GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const
274{
Jamie Madilld1405e52015-03-05 15:41:39 -0500275 ASSERT(colorAttachment < mData.mDrawBufferStates.size());
276 return mData.mDrawBufferStates[colorAttachment];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000277}
278
Geoff Lang164d54e2014-12-01 10:55:33 -0500279void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000280{
Jamie Madilld1405e52015-03-05 15:41:39 -0500281 auto &drawStates = mData.mDrawBufferStates;
282
283 ASSERT(count <= drawStates.size());
284 std::copy(buffers, buffers + count, drawStates.begin());
285 std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE);
Geoff Lang9dd95802014-12-01 11:12:59 -0500286 mImpl->setDrawBuffers(count, buffers);
287}
288
289GLenum Framebuffer::getReadBufferState() const
290{
Jamie Madilld1405e52015-03-05 15:41:39 -0500291 return mData.mReadBufferState;
Geoff Lang9dd95802014-12-01 11:12:59 -0500292}
293
294void Framebuffer::setReadBuffer(GLenum buffer)
295{
Jamie Madillb885e572015-02-03 16:16:04 -0500296 ASSERT(buffer == GL_BACK || buffer == GL_NONE ||
297 (buffer >= GL_COLOR_ATTACHMENT0 &&
Jamie Madilld1405e52015-03-05 15:41:39 -0500298 (buffer - GL_COLOR_ATTACHMENT0) < mData.mColorAttachments.size()));
299 mData.mReadBufferState = buffer;
Geoff Lang9dd95802014-12-01 11:12:59 -0500300 mImpl->setReadBuffer(buffer);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000301}
302
Corentin Wallez37c39792015-08-20 14:19:46 -0400303bool Framebuffer::isEnabledColorAttachment(size_t colorAttachment) const
shannon.woods%transgaming.com@gtempaccount.comdae24092013-04-13 03:31:31 +0000304{
Jamie Madilld1405e52015-03-05 15:41:39 -0500305 ASSERT(colorAttachment < mData.mColorAttachments.size());
Jamie Madill2d06b732015-04-20 12:53:28 -0400306 return (mData.mColorAttachments[colorAttachment].isAttached() &&
Jamie Madilld1405e52015-03-05 15:41:39 -0500307 mData.mDrawBufferStates[colorAttachment] != GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comdae24092013-04-13 03:31:31 +0000308}
309
310bool Framebuffer::hasEnabledColorAttachment() const
311{
Jamie Madilld1405e52015-03-05 15:41:39 -0500312 for (size_t colorAttachment = 0; colorAttachment < mData.mColorAttachments.size(); ++colorAttachment)
shannon.woods%transgaming.com@gtempaccount.comdae24092013-04-13 03:31:31 +0000313 {
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700314 if (isEnabledColorAttachment(static_cast<unsigned int>(colorAttachment)))
shannon.woods%transgaming.com@gtempaccount.comdae24092013-04-13 03:31:31 +0000315 {
316 return true;
317 }
318 }
319
320 return false;
321}
322
Corentin Wallez37c39792015-08-20 14:19:46 -0400323size_t Framebuffer::getNumColorBuffers() const
324{
325 return mData.mColorAttachments.size();
326}
327
Jamie Madill0df8fe42015-11-24 16:10:24 -0500328bool Framebuffer::hasDepth() const
329{
330 return (mData.mDepthAttachment.isAttached() && mData.mDepthAttachment.getDepthSize() > 0);
331}
332
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000333bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000334{
Jamie Madill2d06b732015-04-20 12:53:28 -0400335 return (mData.mStencilAttachment.isAttached() && mData.mStencilAttachment.getStencilSize() > 0);
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000336}
337
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000338bool Framebuffer::usingExtendedDrawBuffers() const
339{
Jamie Madilld1405e52015-03-05 15:41:39 -0500340 for (size_t colorAttachment = 1; colorAttachment < mData.mColorAttachments.size(); ++colorAttachment)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000341 {
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700342 if (isEnabledColorAttachment(static_cast<unsigned int>(colorAttachment)))
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000343 {
344 return true;
345 }
346 }
347
348 return false;
349}
350
Geoff Lang748f74e2014-12-01 11:25:34 -0500351GLenum Framebuffer::checkStatus(const gl::Data &data) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000352{
Geoff Lang528ce3c2014-12-01 10:44:07 -0500353 // The default framebuffer *must* always be complete, though it may not be
354 // subject to the same rules as application FBOs. ie, it could have 0x0 size.
355 if (mId == 0)
356 {
357 return GL_FRAMEBUFFER_COMPLETE;
358 }
359
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000360 unsigned int colorbufferSize = 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000361 int samples = -1;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000362 bool missingAttachment = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000363
Jamie Madill2d06b732015-04-20 12:53:28 -0400364 for (const FramebufferAttachment &colorAttachment : mData.mColorAttachments)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000365 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400366 if (colorAttachment.isAttached())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000367 {
Jamie Madill6b120b92015-11-24 13:00:07 -0500368 const Extents &size = colorAttachment.getSize();
369 if (size.width == 0 || size.height == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000370 {
371 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
372 }
daniel@transgaming.com01868132010-08-24 19:21:17 +0000373
Jamie Madill2d06b732015-04-20 12:53:28 -0400374 GLenum internalformat = colorAttachment.getInternalFormat();
Jamie Madill48faf802014-11-06 15:27:22 -0500375 const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400376 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill2d06b732015-04-20 12:53:28 -0400377 if (colorAttachment.type() == GL_TEXTURE)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000378 {
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400379 if (!formatCaps.renderable)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000380 {
Jamie Madill81176782015-11-24 16:10:23 -0500381 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000382 }
383
Geoff Lang5d601382014-07-22 15:14:06 -0400384 if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000385 {
386 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
387 }
Jamie Madill6b120b92015-11-24 13:00:07 -0500388
389 if (colorAttachment.layer() >= size.depth)
390 {
391 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
392 }
Jamie Madill3215b202015-12-15 16:41:39 -0500393
394 // ES3 specifies that cube map texture attachments must be cube complete.
395 // This language is missing from the ES2 spec, but we enforce it here because some
396 // desktop OpenGL drivers also enforce this validation.
397 // TODO(jmadill): Check if OpenGL ES2 drivers enforce cube completeness.
398 const Texture *texture = colorAttachment.getTexture();
399 ASSERT(texture);
400 if (texture->getTarget() == GL_TEXTURE_CUBE_MAP && !texture->isCubeComplete())
401 {
402 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
403 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000404 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400405 else if (colorAttachment.type() == GL_RENDERBUFFER)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000406 {
Geoff Lang5d601382014-07-22 15:14:06 -0400407 if (!formatCaps.renderable || formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400408 {
409 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
410 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000411 }
412
413 if (!missingAttachment)
414 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000415 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
416 // all color attachments have the same number of samples for the FBO to be complete.
Jamie Madill2d06b732015-04-20 12:53:28 -0400417 if (colorAttachment.getSamples() != samples)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000418 {
419 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
420 }
421
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000422 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
423 // in GLES 3.0, there is no such restriction
Jamie Madill48faf802014-11-06 15:27:22 -0500424 if (data.clientVersion < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000425 {
Geoff Lang5d601382014-07-22 15:14:06 -0400426 if (formatInfo.pixelBytes != colorbufferSize)
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000427 {
428 return GL_FRAMEBUFFER_UNSUPPORTED;
429 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000430 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000431 }
432 else
433 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400434 samples = colorAttachment.getSamples();
Geoff Lang5d601382014-07-22 15:14:06 -0400435 colorbufferSize = formatInfo.pixelBytes;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000436 missingAttachment = false;
437 }
438 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000439 }
440
Jamie Madill2d06b732015-04-20 12:53:28 -0400441 const FramebufferAttachment &depthAttachment = mData.mDepthAttachment;
442 if (depthAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000443 {
Jamie Madill6b120b92015-11-24 13:00:07 -0500444 const Extents &size = depthAttachment.getSize();
445 if (size.width == 0 || size.height == 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000446 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000447 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000448 }
449
Jamie Madill2d06b732015-04-20 12:53:28 -0400450 GLenum internalformat = depthAttachment.getInternalFormat();
Jamie Madill48faf802014-11-06 15:27:22 -0500451 const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400452 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill2d06b732015-04-20 12:53:28 -0400453 if (depthAttachment.type() == GL_TEXTURE)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000454 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000455 // depth texture attachments require OES/ANGLE_depth_texture
Jamie Madill48faf802014-11-06 15:27:22 -0500456 if (!data.extensions->depthTextures)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000457 {
458 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
459 }
460
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400461 if (!formatCaps.renderable)
Geoff Langcec35902014-04-16 10:52:36 -0400462 {
Jamie Madill81176782015-11-24 16:10:23 -0500463 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
Geoff Langcec35902014-04-16 10:52:36 -0400464 }
465
Geoff Lang5d601382014-07-22 15:14:06 -0400466 if (formatInfo.depthBits == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000467 {
468 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
469 }
470 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400471 else if (depthAttachment.type() == GL_RENDERBUFFER)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000472 {
Geoff Lang5d601382014-07-22 15:14:06 -0400473 if (!formatCaps.renderable || formatInfo.depthBits == 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400474 {
475 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
476 }
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000477 }
478
479 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000480 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400481 samples = depthAttachment.getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000482 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000483 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400484 else if (samples != depthAttachment.getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000485 {
486 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
487 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000488 }
489
Jamie Madill2d06b732015-04-20 12:53:28 -0400490 const FramebufferAttachment &stencilAttachment = mData.mStencilAttachment;
491 if (stencilAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000492 {
Jamie Madill6b120b92015-11-24 13:00:07 -0500493 const Extents &size = stencilAttachment.getSize();
494 if (size.width == 0 || size.height == 0)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000495 {
496 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
497 }
498
Jamie Madill2d06b732015-04-20 12:53:28 -0400499 GLenum internalformat = stencilAttachment.getInternalFormat();
Jamie Madill48faf802014-11-06 15:27:22 -0500500 const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400501 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill2d06b732015-04-20 12:53:28 -0400502 if (stencilAttachment.type() == GL_TEXTURE)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000503 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000504 // texture stencil attachments come along as part
505 // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
Jamie Madill48faf802014-11-06 15:27:22 -0500506 if (!data.extensions->depthTextures)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000507 {
508 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
509 }
510
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400511 if (!formatCaps.renderable)
Geoff Langcec35902014-04-16 10:52:36 -0400512 {
Jamie Madill81176782015-11-24 16:10:23 -0500513 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
Geoff Langcec35902014-04-16 10:52:36 -0400514 }
515
Geoff Lang5d601382014-07-22 15:14:06 -0400516 if (formatInfo.stencilBits == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000517 {
518 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
519 }
520 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400521 else if (stencilAttachment.type() == GL_RENDERBUFFER)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000522 {
Geoff Lang5d601382014-07-22 15:14:06 -0400523 if (!formatCaps.renderable || formatInfo.stencilBits == 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400524 {
525 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
526 }
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000527 }
528
529 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000530 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400531 samples = stencilAttachment.getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000532 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000533 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400534 else if (samples != stencilAttachment.getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000535 {
536 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
537 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000538 }
539
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000540 // we need to have at least one attachment to be complete
541 if (missingAttachment)
542 {
543 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000544 }
545
Jamie Madillcc86d642015-11-24 13:00:07 -0500546 // In ES 2.0, all color attachments must have the same width and height.
547 // In ES 3.0, there is no such restriction.
548 if (data.clientVersion < 3 && !mData.attachmentsHaveSameDimensions())
549 {
550 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
551 }
552
553 if (!mImpl->checkStatus())
554 {
555 return GL_FRAMEBUFFER_UNSUPPORTED;
556 }
557
558 return GL_FRAMEBUFFER_COMPLETE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000559}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000560
Austin Kinross08332632015-05-05 13:35:47 -0700561Error Framebuffer::discard(size_t count, const GLenum *attachments)
562{
563 return mImpl->discard(count, attachments);
564}
565
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500566Error Framebuffer::invalidate(size_t count, const GLenum *attachments)
Jamie Madill2d96b9e2014-08-29 15:46:47 -0400567{
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500568 return mImpl->invalidate(count, attachments);
Jamie Madill2d96b9e2014-08-29 15:46:47 -0400569}
570
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500571Error Framebuffer::invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area)
Jamie Madill400a4412014-08-29 15:46:45 -0400572{
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500573 return mImpl->invalidateSub(count, attachments, area);
Jamie Madill400a4412014-08-29 15:46:45 -0400574}
575
Jamie Madill1b94d432015-08-07 13:23:23 -0400576Error Framebuffer::clear(Context *context, GLbitfield mask)
Geoff Langb04dc822014-12-01 12:02:02 -0500577{
Jamie Madill984ef412015-11-24 16:10:21 -0500578 if (context->getState().isRasterizerDiscardEnabled())
579 {
580 return gl::Error(GL_NO_ERROR);
581 }
582
Jamie Madill1b94d432015-08-07 13:23:23 -0400583 // Sync the clear state
584 context->syncRendererState(context->getState().clearStateBitMask());
585
586 return mImpl->clear(context->getData(), mask);
Geoff Langb04dc822014-12-01 12:02:02 -0500587}
588
Jamie Madill1b94d432015-08-07 13:23:23 -0400589Error Framebuffer::clearBufferfv(Context *context,
590 GLenum buffer,
591 GLint drawbuffer,
592 const GLfloat *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500593{
Jamie Madill984ef412015-11-24 16:10:21 -0500594 if (context->getState().isRasterizerDiscardEnabled())
595 {
596 return gl::Error(GL_NO_ERROR);
597 }
598
Jamie Madill1b94d432015-08-07 13:23:23 -0400599 // Sync the clear state
600 context->syncRendererState(context->getState().clearStateBitMask());
Dian Xiang40281592015-11-19 18:24:44 -0800601 return mImpl->clearBufferfv(context->getData(), buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500602}
603
Jamie Madill1b94d432015-08-07 13:23:23 -0400604Error Framebuffer::clearBufferuiv(Context *context,
605 GLenum buffer,
606 GLint drawbuffer,
607 const GLuint *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500608{
Jamie Madill984ef412015-11-24 16:10:21 -0500609 if (context->getState().isRasterizerDiscardEnabled())
610 {
611 return gl::Error(GL_NO_ERROR);
612 }
613
Jamie Madill1b94d432015-08-07 13:23:23 -0400614 // Sync the clear state
615 context->syncRendererState(context->getState().clearStateBitMask());
616
Dian Xiang40281592015-11-19 18:24:44 -0800617 return mImpl->clearBufferuiv(context->getData(), buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500618}
619
Jamie Madill1b94d432015-08-07 13:23:23 -0400620Error Framebuffer::clearBufferiv(Context *context,
621 GLenum buffer,
622 GLint drawbuffer,
623 const GLint *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500624{
Jamie Madill984ef412015-11-24 16:10:21 -0500625 if (context->getState().isRasterizerDiscardEnabled())
626 {
627 return gl::Error(GL_NO_ERROR);
628 }
629
Jamie Madill1b94d432015-08-07 13:23:23 -0400630 // Sync the clear state
631 context->syncRendererState(context->getState().clearStateBitMask());
632
Dian Xiang40281592015-11-19 18:24:44 -0800633 return mImpl->clearBufferiv(context->getData(), buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500634}
635
Jamie Madill1b94d432015-08-07 13:23:23 -0400636Error Framebuffer::clearBufferfi(Context *context,
637 GLenum buffer,
638 GLint drawbuffer,
639 GLfloat depth,
640 GLint stencil)
Geoff Langb04dc822014-12-01 12:02:02 -0500641{
Jamie Madill984ef412015-11-24 16:10:21 -0500642 if (context->getState().isRasterizerDiscardEnabled())
643 {
644 return gl::Error(GL_NO_ERROR);
645 }
646
Jamie Madill1b94d432015-08-07 13:23:23 -0400647 // Sync the clear state
648 context->syncRendererState(context->getState().clearStateBitMask());
649
Dian Xiang40281592015-11-19 18:24:44 -0800650 return mImpl->clearBufferfi(context->getData(), buffer, drawbuffer, depth, stencil);
Geoff Langb04dc822014-12-01 12:02:02 -0500651}
652
Geoff Langbce529e2014-12-01 12:48:41 -0500653GLenum Framebuffer::getImplementationColorReadFormat() const
654{
655 return mImpl->getImplementationColorReadFormat();
656}
657
658GLenum Framebuffer::getImplementationColorReadType() const
659{
660 return mImpl->getImplementationColorReadType();
661}
662
Jamie Madill1b94d432015-08-07 13:23:23 -0400663Error Framebuffer::readPixels(Context *context,
664 const gl::Rectangle &area,
665 GLenum format,
666 GLenum type,
667 GLvoid *pixels) const
Geoff Langbce529e2014-12-01 12:48:41 -0500668{
Jamie Madill1b94d432015-08-07 13:23:23 -0400669 const State &state = context->getState();
670
671 // Sync pack state
672 context->syncRendererState(state.packStateBitMask());
673
Geoff Lang520c4ae2015-05-05 13:12:36 -0400674 Error error = mImpl->readPixels(state, area, format, type, pixels);
675 if (error.isError())
676 {
677 return error;
678 }
679
680 Buffer *unpackBuffer = state.getUnpackState().pixelBuffer.get();
681 if (unpackBuffer)
682 {
683 unpackBuffer->onPixelUnpack();
684 }
685
686 return Error(GL_NO_ERROR);
Geoff Langbce529e2014-12-01 12:48:41 -0500687}
688
Geoff Lang242468f2015-09-24 14:15:41 -0400689Error Framebuffer::blit(Context *context,
690 const gl::Rectangle &sourceArea,
691 const gl::Rectangle &destArea,
692 GLbitfield mask,
693 GLenum filter,
694 const gl::Framebuffer *sourceFramebuffer)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500695{
Geoff Lang242468f2015-09-24 14:15:41 -0400696 // Sync blit state
697 const State &state = context->getState();
698 context->syncRendererState(state.blitStateBitMask());
699
Geoff Lang54bd5a42014-12-01 12:51:04 -0500700 return mImpl->blit(state, sourceArea, destArea, mask, filter, sourceFramebuffer);
701}
702
Jamie Madill48faf802014-11-06 15:27:22 -0500703int Framebuffer::getSamples(const gl::Data &data) const
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000704{
Geoff Lang748f74e2014-12-01 11:25:34 -0500705 if (checkStatus(data) == GL_FRAMEBUFFER_COMPLETE)
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000706 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000707 // for a complete framebuffer, all attachments must have the same sample count
708 // in this case return the first nonzero sample size
Jamie Madill2d06b732015-04-20 12:53:28 -0400709 for (const FramebufferAttachment &colorAttachment : mData.mColorAttachments)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000710 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400711 if (colorAttachment.isAttached())
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000712 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400713 return colorAttachment.getSamples();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000714 }
715 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000716 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000717
718 return 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000719}
720
Jamie Madille261b442014-06-25 12:42:21 -0400721bool Framebuffer::hasValidDepthStencil() const
722{
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400723 return mData.getDepthStencilAttachment() != nullptr;
Jamie Madille261b442014-06-25 12:42:21 -0400724}
725
Jamie Madill2d06b732015-04-20 12:53:28 -0400726void Framebuffer::setAttachment(GLenum type,
727 GLenum binding,
728 const ImageIndex &textureIndex,
729 FramebufferAttachmentObject *resource)
Geoff Langab75a052014-10-15 12:56:37 -0400730{
Jamie Madill2d06b732015-04-20 12:53:28 -0400731 if (binding == GL_DEPTH_STENCIL || binding == GL_DEPTH_STENCIL_ATTACHMENT)
Geoff Langab75a052014-10-15 12:56:37 -0400732 {
Geoff Langab75a052014-10-15 12:56:37 -0400733 // ensure this is a legitimate depth+stencil format
Jamie Madill375c37c2015-07-21 15:14:08 -0400734 FramebufferAttachmentObject *attachmentObj = resource;
735 if (resource)
Geoff Langab75a052014-10-15 12:56:37 -0400736 {
Jamie Madill375c37c2015-07-21 15:14:08 -0400737 FramebufferAttachment::Target target(binding, textureIndex);
738 GLenum internalFormat = resource->getAttachmentInternalFormat(target);
739 const InternalFormat &formatInfo = GetInternalFormatInfo(internalFormat);
740 if (formatInfo.depthBits == 0 || formatInfo.stencilBits == 0)
741 {
742 // Attaching nullptr detaches the current attachment.
743 attachmentObj = nullptr;
744 }
Geoff Langab75a052014-10-15 12:56:37 -0400745 }
Jamie Madill375c37c2015-07-21 15:14:08 -0400746
747 mData.mDepthAttachment.attach(type, binding, textureIndex, attachmentObj);
748 mData.mStencilAttachment.attach(type, binding, textureIndex, attachmentObj);
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400749 mImpl->onUpdateDepthStencilAttachment();
Geoff Langab75a052014-10-15 12:56:37 -0400750 }
751 else
752 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400753 switch (binding)
754 {
755 case GL_DEPTH:
756 case GL_DEPTH_ATTACHMENT:
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400757 mData.mDepthAttachment.attach(type, binding, textureIndex, resource);
758 mImpl->onUpdateDepthAttachment();
Jamie Madill2d06b732015-04-20 12:53:28 -0400759 break;
760 case GL_STENCIL:
761 case GL_STENCIL_ATTACHMENT:
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400762 mData.mStencilAttachment.attach(type, binding, textureIndex, resource);
763 mImpl->onUpdateStencilAttachment();
Jamie Madill2d06b732015-04-20 12:53:28 -0400764 break;
765 case GL_BACK:
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400766 mData.mColorAttachments[0].attach(type, binding, textureIndex, resource);
767 mImpl->onUpdateColorAttachment(0);
Jamie Madill2d06b732015-04-20 12:53:28 -0400768 break;
769 default:
770 {
771 size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
772 ASSERT(colorIndex < mData.mColorAttachments.size());
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400773 mData.mColorAttachments[colorIndex].attach(type, binding, textureIndex, resource);
774 mImpl->onUpdateColorAttachment(colorIndex);
Jamie Madill2d06b732015-04-20 12:53:28 -0400775 }
776 break;
777 }
Geoff Langab75a052014-10-15 12:56:37 -0400778 }
779}
780
Jamie Madill2d06b732015-04-20 12:53:28 -0400781void Framebuffer::resetAttachment(GLenum binding)
782{
783 setAttachment(GL_NONE, binding, ImageIndex::MakeInvalid(), nullptr);
784}
785
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000786}