blob: 2f0e48dc6c4ae0a1c7d8f7e324ab63c188d1b794 [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 Madill231c7f52017-04-26 13:45:37 -040013#include "common/bitset_utils.h"
Jamie Madillc46f45d2015-03-31 13:20:55 -040014#include "common/utilities.h"
15#include "libANGLE/Config.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050016#include "libANGLE/Context.h"
Jamie Madill6c1f6712017-02-14 19:08:04 -050017#include "libANGLE/Display.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050018#include "libANGLE/FramebufferAttachment.h"
Jamie Madillc46f45d2015-03-31 13:20:55 -040019#include "libANGLE/Renderbuffer.h"
20#include "libANGLE/Surface.h"
21#include "libANGLE/Texture.h"
22#include "libANGLE/formatutils.h"
Jamie Madill8415b5f2016-04-26 13:41:39 -040023#include "libANGLE/renderer/ContextImpl.h"
Geoff Langb5d8f232014-12-04 15:43:01 -050024#include "libANGLE/renderer/FramebufferImpl.h"
Jamie Madill7aea7e02016-05-10 10:39:45 -040025#include "libANGLE/renderer/GLImplFactory.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050026#include "libANGLE/renderer/RenderbufferImpl.h"
Corentin Wallez37c39792015-08-20 14:19:46 -040027#include "libANGLE/renderer/SurfaceImpl.h"
Geoff Lang0b7eef72014-06-12 14:10:47 -040028
Jamie Madill362876b2016-06-16 14:46:59 -040029using namespace angle;
30
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000031namespace gl
32{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000033
Jamie Madilld1405e52015-03-05 15:41:39 -050034namespace
35{
Jamie Madill362876b2016-06-16 14:46:59 -040036
Jamie Madill1e5499d2017-04-05 11:22:16 -040037void BindResourceChannel(OnAttachmentDirtyBinding *binding, FramebufferAttachmentObject *resource)
Jamie Madilld1405e52015-03-05 15:41:39 -050038{
Jamie Madill362876b2016-06-16 14:46:59 -040039 binding->bind(resource ? resource->getDirtyChannel() : nullptr);
Jamie Madilld1405e52015-03-05 15:41:39 -050040}
Jamie Madill362876b2016-06-16 14:46:59 -040041
Geoff Lang9f10b772017-05-16 15:51:03 -040042bool CheckAttachmentCompleteness(const Context *context, const FramebufferAttachment &attachment)
43{
44 ASSERT(attachment.isAttached());
45
46 const Extents &size = attachment.getSize();
47 if (size.width == 0 || size.height == 0)
48 {
49 return false;
50 }
51
52 const InternalFormat &format = *attachment.getFormat().info;
53 if (!format.renderSupport(context->getClientVersion(), context->getExtensions()))
54 {
55 return false;
56 }
57
58 if (attachment.type() == GL_TEXTURE)
59 {
60 if (attachment.layer() >= size.depth)
61 {
62 return false;
63 }
64
65 // ES3 specifies that cube map texture attachments must be cube complete.
66 // This language is missing from the ES2 spec, but we enforce it here because some
67 // desktop OpenGL drivers also enforce this validation.
68 // TODO(jmadill): Check if OpenGL ES2 drivers enforce cube completeness.
69 const Texture *texture = attachment.getTexture();
70 ASSERT(texture);
71 if (texture->getTarget() == GL_TEXTURE_CUBE_MAP &&
72 !texture->getTextureState().isCubeComplete())
73 {
74 return false;
75 }
76 }
77
78 return true;
79};
80
Jamie Madill362876b2016-06-16 14:46:59 -040081} // anonymous namespace
Jamie Madilld1405e52015-03-05 15:41:39 -050082
Jamie Madill6f60d052017-02-22 15:20:11 -050083// This constructor is only used for default framebuffers.
Jamie Madill48ef11b2016-04-27 15:21:52 -040084FramebufferState::FramebufferState()
Geoff Lang70d0f492015-12-10 17:45:46 -050085 : mLabel(),
86 mColorAttachments(1),
Geoff Langd90d3882017-03-21 10:49:54 -040087 mDrawBufferStates(IMPLEMENTATION_MAX_DRAW_BUFFERS, GL_NONE),
Jamie Madill6f60d052017-02-22 15:20:11 -050088 mReadBufferState(GL_BACK),
JiangYizhouf7bbc8a2016-11-16 09:57:22 +080089 mDefaultWidth(0),
90 mDefaultHeight(0),
91 mDefaultSamples(0),
Jamie Madilla02315b2017-02-23 14:14:47 -050092 mDefaultFixedSampleLocations(GL_FALSE),
93 mWebGLDepthStencilConsistent(true)
Corentin Wallez37c39792015-08-20 14:19:46 -040094{
Geoff Langd90d3882017-03-21 10:49:54 -040095 ASSERT(mDrawBufferStates.size() > 0);
96 mDrawBufferStates[0] = GL_BACK;
Jamie Madilla4595b82017-01-11 17:36:34 -050097 mEnabledDrawBuffers.set(0);
Corentin Wallez37c39792015-08-20 14:19:46 -040098}
99
Jamie Madill48ef11b2016-04-27 15:21:52 -0400100FramebufferState::FramebufferState(const Caps &caps)
Geoff Lang70d0f492015-12-10 17:45:46 -0500101 : mLabel(),
102 mColorAttachments(caps.maxColorAttachments),
Jamie Madilld1405e52015-03-05 15:41:39 -0500103 mDrawBufferStates(caps.maxDrawBuffers, GL_NONE),
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800104 mReadBufferState(GL_COLOR_ATTACHMENT0_EXT),
105 mDefaultWidth(0),
106 mDefaultHeight(0),
107 mDefaultSamples(0),
Jamie Madilla02315b2017-02-23 14:14:47 -0500108 mDefaultFixedSampleLocations(GL_FALSE),
109 mWebGLDepthStencilConsistent(true)
Jamie Madilld1405e52015-03-05 15:41:39 -0500110{
Geoff Langa15472a2015-08-11 11:48:03 -0400111 ASSERT(mDrawBufferStates.size() > 0);
Jamie Madilld1405e52015-03-05 15:41:39 -0500112 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
113}
114
Jamie Madill48ef11b2016-04-27 15:21:52 -0400115FramebufferState::~FramebufferState()
Jamie Madilld1405e52015-03-05 15:41:39 -0500116{
Jamie Madilld1405e52015-03-05 15:41:39 -0500117}
118
Jamie Madill48ef11b2016-04-27 15:21:52 -0400119const std::string &FramebufferState::getLabel()
Geoff Lang70d0f492015-12-10 17:45:46 -0500120{
121 return mLabel;
122}
123
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400124const FramebufferAttachment *FramebufferState::getAttachment(GLenum attachment) const
125{
126 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
127 {
128 return getColorAttachment(attachment - GL_COLOR_ATTACHMENT0);
129 }
130
131 switch (attachment)
132 {
133 case GL_COLOR:
134 case GL_BACK:
135 return getColorAttachment(0);
136 case GL_DEPTH:
137 case GL_DEPTH_ATTACHMENT:
138 return getDepthAttachment();
139 case GL_STENCIL:
140 case GL_STENCIL_ATTACHMENT:
141 return getStencilAttachment();
142 case GL_DEPTH_STENCIL:
143 case GL_DEPTH_STENCIL_ATTACHMENT:
144 return getDepthStencilAttachment();
145 default:
146 UNREACHABLE();
147 return nullptr;
148 }
149}
150
Jamie Madill48ef11b2016-04-27 15:21:52 -0400151const FramebufferAttachment *FramebufferState::getReadAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500152{
Antoine Labour2ec65dc2016-11-30 16:28:58 -0800153 if (mReadBufferState == GL_NONE)
154 {
155 return nullptr;
156 }
Jamie Madill231c7f52017-04-26 13:45:37 -0400157 ASSERT(mReadBufferState == GL_BACK ||
158 (mReadBufferState >= GL_COLOR_ATTACHMENT0 && mReadBufferState <= GL_COLOR_ATTACHMENT15));
159 size_t readIndex = (mReadBufferState == GL_BACK
160 ? 0
161 : static_cast<size_t>(mReadBufferState - GL_COLOR_ATTACHMENT0));
Jamie Madill7147f012015-03-05 15:41:40 -0500162 ASSERT(readIndex < mColorAttachments.size());
Jamie Madill2d06b732015-04-20 12:53:28 -0400163 return mColorAttachments[readIndex].isAttached() ? &mColorAttachments[readIndex] : nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500164}
165
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500166const FramebufferAttachment *FramebufferState::getFirstNonNullAttachment() const
167{
168 auto *colorAttachment = getFirstColorAttachment();
169 if (colorAttachment)
170 {
171 return colorAttachment;
172 }
173 return getDepthOrStencilAttachment();
174}
175
Jamie Madill48ef11b2016-04-27 15:21:52 -0400176const FramebufferAttachment *FramebufferState::getFirstColorAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500177{
Jamie Madill2d06b732015-04-20 12:53:28 -0400178 for (const FramebufferAttachment &colorAttachment : mColorAttachments)
Jamie Madill7147f012015-03-05 15:41:40 -0500179 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400180 if (colorAttachment.isAttached())
Jamie Madill7147f012015-03-05 15:41:40 -0500181 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400182 return &colorAttachment;
Jamie Madill7147f012015-03-05 15:41:40 -0500183 }
184 }
185
186 return nullptr;
187}
188
Jamie Madill48ef11b2016-04-27 15:21:52 -0400189const FramebufferAttachment *FramebufferState::getDepthOrStencilAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500190{
Jamie Madill2d06b732015-04-20 12:53:28 -0400191 if (mDepthAttachment.isAttached())
192 {
193 return &mDepthAttachment;
194 }
195 if (mStencilAttachment.isAttached())
196 {
197 return &mStencilAttachment;
198 }
199 return nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500200}
201
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500202const FramebufferAttachment *FramebufferState::getStencilOrDepthStencilAttachment() const
203{
204 if (mStencilAttachment.isAttached())
205 {
206 return &mStencilAttachment;
207 }
208 return getDepthStencilAttachment();
209}
210
Jamie Madill48ef11b2016-04-27 15:21:52 -0400211const FramebufferAttachment *FramebufferState::getColorAttachment(size_t colorAttachment) const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400212{
213 ASSERT(colorAttachment < mColorAttachments.size());
Jamie Madill231c7f52017-04-26 13:45:37 -0400214 return mColorAttachments[colorAttachment].isAttached() ? &mColorAttachments[colorAttachment]
215 : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400216}
217
Jamie Madill48ef11b2016-04-27 15:21:52 -0400218const FramebufferAttachment *FramebufferState::getDepthAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400219{
Jamie Madill2d06b732015-04-20 12:53:28 -0400220 return mDepthAttachment.isAttached() ? &mDepthAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400221}
222
Jamie Madill48ef11b2016-04-27 15:21:52 -0400223const FramebufferAttachment *FramebufferState::getStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400224{
Jamie Madill2d06b732015-04-20 12:53:28 -0400225 return mStencilAttachment.isAttached() ? &mStencilAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400226}
227
Jamie Madill48ef11b2016-04-27 15:21:52 -0400228const FramebufferAttachment *FramebufferState::getDepthStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400229{
230 // A valid depth-stencil attachment has the same resource bound to both the
231 // depth and stencil attachment points.
Jamie Madill2d06b732015-04-20 12:53:28 -0400232 if (mDepthAttachment.isAttached() && mStencilAttachment.isAttached() &&
Jamie Madill44f26482016-11-18 12:49:15 -0500233 mDepthAttachment == mStencilAttachment)
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400234 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400235 return &mDepthAttachment;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400236 }
237
238 return nullptr;
239}
240
Jamie Madill48ef11b2016-04-27 15:21:52 -0400241bool FramebufferState::attachmentsHaveSameDimensions() const
Jamie Madillcc86d642015-11-24 13:00:07 -0500242{
243 Optional<Extents> attachmentSize;
244
Jamie Madill231c7f52017-04-26 13:45:37 -0400245 auto hasMismatchedSize = [&attachmentSize](const FramebufferAttachment &attachment) {
Jamie Madillcc86d642015-11-24 13:00:07 -0500246 if (!attachment.isAttached())
247 {
248 return false;
249 }
250
251 if (!attachmentSize.valid())
252 {
253 attachmentSize = attachment.getSize();
254 return false;
255 }
256
257 return (attachment.getSize() != attachmentSize.value());
258 };
259
260 for (const auto &attachment : mColorAttachments)
261 {
262 if (hasMismatchedSize(attachment))
263 {
264 return false;
265 }
266 }
267
268 if (hasMismatchedSize(mDepthAttachment))
269 {
270 return false;
271 }
272
273 return !hasMismatchedSize(mStencilAttachment);
274}
275
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400276const gl::FramebufferAttachment *FramebufferState::getDrawBuffer(size_t drawBufferIdx) const
277{
278 ASSERT(drawBufferIdx < mDrawBufferStates.size());
279 if (mDrawBufferStates[drawBufferIdx] != GL_NONE)
280 {
281 // ES3 spec: "If the GL is bound to a draw framebuffer object, the ith buffer listed in bufs
282 // must be COLOR_ATTACHMENTi or NONE"
283 ASSERT(mDrawBufferStates[drawBufferIdx] == GL_COLOR_ATTACHMENT0 + drawBufferIdx ||
284 (drawBufferIdx == 0 && mDrawBufferStates[drawBufferIdx] == GL_BACK));
285 return getAttachment(mDrawBufferStates[drawBufferIdx]);
286 }
287 else
288 {
289 return nullptr;
290 }
291}
292
293size_t FramebufferState::getDrawBufferCount() const
294{
295 return mDrawBufferStates.size();
296}
297
Geoff Langb21e20d2016-07-19 15:35:41 -0400298bool FramebufferState::colorAttachmentsAreUniqueImages() const
299{
300 for (size_t firstAttachmentIdx = 0; firstAttachmentIdx < mColorAttachments.size();
301 firstAttachmentIdx++)
302 {
303 const gl::FramebufferAttachment &firstAttachment = mColorAttachments[firstAttachmentIdx];
304 if (!firstAttachment.isAttached())
305 {
306 continue;
307 }
308
309 for (size_t secondAttachmentIdx = firstAttachmentIdx + 1;
310 secondAttachmentIdx < mColorAttachments.size(); secondAttachmentIdx++)
311 {
312 const gl::FramebufferAttachment &secondAttachment =
313 mColorAttachments[secondAttachmentIdx];
314 if (!secondAttachment.isAttached())
315 {
316 continue;
317 }
318
319 if (firstAttachment == secondAttachment)
320 {
321 return false;
322 }
323 }
324 }
325
326 return true;
327}
328
Jamie Madill7aea7e02016-05-10 10:39:45 -0400329Framebuffer::Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id)
Jamie Madill362876b2016-06-16 14:46:59 -0400330 : mState(caps),
331 mImpl(factory->createFramebuffer(mState)),
332 mId(id),
333 mCachedStatus(),
334 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
335 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000336{
Corentin Wallez37c39792015-08-20 14:19:46 -0400337 ASSERT(mId != 0);
338 ASSERT(mImpl != nullptr);
Jamie Madill362876b2016-06-16 14:46:59 -0400339 ASSERT(mState.mColorAttachments.size() == static_cast<size_t>(caps.maxColorAttachments));
340
Jamie Madill1e5499d2017-04-05 11:22:16 -0400341 for (uint32_t colorIndex = 0;
342 colorIndex < static_cast<uint32_t>(mState.mColorAttachments.size()); ++colorIndex)
Jamie Madill362876b2016-06-16 14:46:59 -0400343 {
Jamie Madill1e5499d2017-04-05 11:22:16 -0400344 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
Jamie Madill362876b2016-06-16 14:46:59 -0400345 }
Corentin Wallez37c39792015-08-20 14:19:46 -0400346}
347
Jamie Madill6f60d052017-02-22 15:20:11 -0500348Framebuffer::Framebuffer(egl::Surface *surface)
Jamie Madill362876b2016-06-16 14:46:59 -0400349 : mState(),
Jamie Madill6f60d052017-02-22 15:20:11 -0500350 mImpl(surface->getImplementation()->createDefaultFramebuffer(mState)),
Jamie Madill362876b2016-06-16 14:46:59 -0400351 mId(0),
352 mCachedStatus(GL_FRAMEBUFFER_COMPLETE),
353 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
354 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
Corentin Wallez37c39792015-08-20 14:19:46 -0400355{
Geoff Langda88add2014-12-01 10:22:01 -0500356 ASSERT(mImpl != nullptr);
Jamie Madill1e5499d2017-04-05 11:22:16 -0400357 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
Jamie Madill6f60d052017-02-22 15:20:11 -0500358
Jamie Madilla02315b2017-02-23 14:14:47 -0500359 setAttachmentImpl(GL_FRAMEBUFFER_DEFAULT, GL_BACK, gl::ImageIndex::MakeInvalid(), surface);
Jamie Madill6f60d052017-02-22 15:20:11 -0500360
361 if (surface->getConfig()->depthSize > 0)
362 {
Jamie Madilla02315b2017-02-23 14:14:47 -0500363 setAttachmentImpl(GL_FRAMEBUFFER_DEFAULT, GL_DEPTH, gl::ImageIndex::MakeInvalid(), surface);
Jamie Madill6f60d052017-02-22 15:20:11 -0500364 }
365
366 if (surface->getConfig()->stencilSize > 0)
367 {
Jamie Madilla02315b2017-02-23 14:14:47 -0500368 setAttachmentImpl(GL_FRAMEBUFFER_DEFAULT, GL_STENCIL, gl::ImageIndex::MakeInvalid(),
369 surface);
Jamie Madill6f60d052017-02-22 15:20:11 -0500370 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000371}
372
Corentin Wallezccab69d2017-01-27 16:57:15 -0500373Framebuffer::Framebuffer(rx::GLImplFactory *factory)
374 : mState(),
375 mImpl(factory->createFramebuffer(mState)),
376 mId(0),
377 mCachedStatus(GL_FRAMEBUFFER_UNDEFINED_OES),
378 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
379 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
380{
Jamie Madill1e5499d2017-04-05 11:22:16 -0400381 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
Corentin Wallezccab69d2017-01-27 16:57:15 -0500382}
383
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000384Framebuffer::~Framebuffer()
385{
Geoff Langda88add2014-12-01 10:22:01 -0500386 SafeDelete(mImpl);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000387}
388
Jamie Madill6c1f6712017-02-14 19:08:04 -0500389void Framebuffer::destroy(const Context *context)
390{
391 mImpl->destroy(rx::SafeGetImpl(context));
392}
393
394void Framebuffer::destroyDefault(const egl::Display *display)
395{
396 mImpl->destroyDefault(rx::SafeGetImpl(display));
397}
398
Geoff Lang70d0f492015-12-10 17:45:46 -0500399void Framebuffer::setLabel(const std::string &label)
400{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400401 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -0500402}
403
404const std::string &Framebuffer::getLabel() const
405{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400406 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -0500407}
408
Jamie Madilla02315b2017-02-23 14:14:47 -0500409void Framebuffer::detachTexture(const Context *context, GLuint textureId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000410{
Jamie Madilla02315b2017-02-23 14:14:47 -0500411 detachResourceById(context, GL_TEXTURE, textureId);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000412}
413
Jamie Madilla02315b2017-02-23 14:14:47 -0500414void Framebuffer::detachRenderbuffer(const Context *context, GLuint renderbufferId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000415{
Jamie Madilla02315b2017-02-23 14:14:47 -0500416 detachResourceById(context, GL_RENDERBUFFER, renderbufferId);
Jamie Madilld1405e52015-03-05 15:41:39 -0500417}
Jamie Madille261b442014-06-25 12:42:21 -0400418
Jamie Madilla02315b2017-02-23 14:14:47 -0500419void Framebuffer::detachResourceById(const Context *context, GLenum resourceType, GLuint resourceId)
Jamie Madilld1405e52015-03-05 15:41:39 -0500420{
Jamie Madill362876b2016-06-16 14:46:59 -0400421 for (size_t colorIndex = 0; colorIndex < mState.mColorAttachments.size(); ++colorIndex)
Jamie Madilld1405e52015-03-05 15:41:39 -0500422 {
Jamie Madill362876b2016-06-16 14:46:59 -0400423 detachMatchingAttachment(&mState.mColorAttachments[colorIndex], resourceType, resourceId,
424 DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000425 }
426
Jamie Madilla02315b2017-02-23 14:14:47 -0500427 if (context->isWebGL1())
428 {
429 const std::array<FramebufferAttachment *, 3> attachments = {
430 {&mState.mWebGLDepthStencilAttachment, &mState.mWebGLDepthAttachment,
431 &mState.mWebGLStencilAttachment}};
432 for (FramebufferAttachment *attachment : attachments)
433 {
434 if (attachment->isAttached() && attachment->type() == resourceType &&
435 attachment->id() == resourceId)
436 {
437 resetAttachment(context, attachment->getBinding());
438 }
439 }
440 }
441 else
442 {
443 detachMatchingAttachment(&mState.mDepthAttachment, resourceType, resourceId,
444 DIRTY_BIT_DEPTH_ATTACHMENT);
445 detachMatchingAttachment(&mState.mStencilAttachment, resourceType, resourceId,
446 DIRTY_BIT_STENCIL_ATTACHMENT);
447 }
Jamie Madill362876b2016-06-16 14:46:59 -0400448}
449
450void Framebuffer::detachMatchingAttachment(FramebufferAttachment *attachment,
451 GLenum matchType,
452 GLuint matchId,
453 size_t dirtyBit)
454{
455 if (attachment->isAttached() && attachment->type() == matchType && attachment->id() == matchId)
456 {
457 attachment->detach();
458 mDirtyBits.set(dirtyBit);
459 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000460}
461
Corentin Wallez37c39792015-08-20 14:19:46 -0400462const FramebufferAttachment *Framebuffer::getColorbuffer(size_t colorAttachment) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000463{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400464 return mState.getColorAttachment(colorAttachment);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000465}
466
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400467const FramebufferAttachment *Framebuffer::getDepthbuffer() const
Geoff Lang646559f2013-08-15 11:08:15 -0400468{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400469 return mState.getDepthAttachment();
Geoff Lang646559f2013-08-15 11:08:15 -0400470}
471
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400472const FramebufferAttachment *Framebuffer::getStencilbuffer() const
473{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400474 return mState.getStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400475}
476
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400477const FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
478{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400479 return mState.getDepthStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400480}
481
482const FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000483{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400484 return mState.getDepthOrStencilAttachment();
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000485}
486
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500487const FramebufferAttachment *Framebuffer::getStencilOrDepthStencilAttachment() const
488{
489 return mState.getStencilOrDepthStencilAttachment();
490}
491
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400492const FramebufferAttachment *Framebuffer::getReadColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000493{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400494 return mState.getReadAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000495}
496
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000497GLenum Framebuffer::getReadColorbufferType() const
498{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400499 const FramebufferAttachment *readAttachment = mState.getReadAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400500 return (readAttachment != nullptr ? readAttachment->type() : GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000501}
502
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400503const FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000504{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400505 return mState.getFirstColorAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000506}
507
Jamie Madill2d06b732015-04-20 12:53:28 -0400508const FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000509{
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400510 return mState.getAttachment(attachment);
Geoff Lang55ba29c2013-07-11 16:57:53 -0400511}
512
Geoff Langa15472a2015-08-11 11:48:03 -0400513size_t Framebuffer::getDrawbufferStateCount() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000514{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400515 return mState.mDrawBufferStates.size();
Geoff Langa15472a2015-08-11 11:48:03 -0400516}
517
518GLenum Framebuffer::getDrawBufferState(size_t drawBuffer) const
519{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400520 ASSERT(drawBuffer < mState.mDrawBufferStates.size());
521 return mState.mDrawBufferStates[drawBuffer];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000522}
523
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500524const std::vector<GLenum> &Framebuffer::getDrawBufferStates() const
525{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400526 return mState.getDrawBufferStates();
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500527}
528
Geoff Lang164d54e2014-12-01 10:55:33 -0500529void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000530{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400531 auto &drawStates = mState.mDrawBufferStates;
Jamie Madilld1405e52015-03-05 15:41:39 -0500532
533 ASSERT(count <= drawStates.size());
534 std::copy(buffers, buffers + count, drawStates.begin());
535 std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500536 mDirtyBits.set(DIRTY_BIT_DRAW_BUFFERS);
Jamie Madilla4595b82017-01-11 17:36:34 -0500537
538 mState.mEnabledDrawBuffers.reset();
539 for (size_t index = 0; index < count; ++index)
540 {
541 if (drawStates[index] != GL_NONE && mState.mColorAttachments[index].isAttached())
542 {
543 mState.mEnabledDrawBuffers.set(index);
544 }
545 }
Geoff Lang9dd95802014-12-01 11:12:59 -0500546}
547
Geoff Langa15472a2015-08-11 11:48:03 -0400548const FramebufferAttachment *Framebuffer::getDrawBuffer(size_t drawBuffer) const
549{
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400550 return mState.getDrawBuffer(drawBuffer);
Geoff Langa15472a2015-08-11 11:48:03 -0400551}
552
553bool Framebuffer::hasEnabledDrawBuffer() const
554{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400555 for (size_t drawbufferIdx = 0; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
Geoff Langa15472a2015-08-11 11:48:03 -0400556 {
557 if (getDrawBuffer(drawbufferIdx) != nullptr)
558 {
559 return true;
560 }
561 }
562
563 return false;
564}
565
Geoff Lang9dd95802014-12-01 11:12:59 -0500566GLenum Framebuffer::getReadBufferState() const
567{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400568 return mState.mReadBufferState;
Geoff Lang9dd95802014-12-01 11:12:59 -0500569}
570
571void Framebuffer::setReadBuffer(GLenum buffer)
572{
Jamie Madillb885e572015-02-03 16:16:04 -0500573 ASSERT(buffer == GL_BACK || buffer == GL_NONE ||
574 (buffer >= GL_COLOR_ATTACHMENT0 &&
Jamie Madill48ef11b2016-04-27 15:21:52 -0400575 (buffer - GL_COLOR_ATTACHMENT0) < mState.mColorAttachments.size()));
576 mState.mReadBufferState = buffer;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500577 mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000578}
579
Corentin Wallez37c39792015-08-20 14:19:46 -0400580size_t Framebuffer::getNumColorBuffers() const
581{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400582 return mState.mColorAttachments.size();
Corentin Wallez37c39792015-08-20 14:19:46 -0400583}
584
Jamie Madill0df8fe42015-11-24 16:10:24 -0500585bool Framebuffer::hasDepth() const
586{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400587 return (mState.mDepthAttachment.isAttached() && mState.mDepthAttachment.getDepthSize() > 0);
Jamie Madill0df8fe42015-11-24 16:10:24 -0500588}
589
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000590bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000591{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400592 return (mState.mStencilAttachment.isAttached() &&
593 mState.mStencilAttachment.getStencilSize() > 0);
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000594}
595
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000596bool Framebuffer::usingExtendedDrawBuffers() const
597{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400598 for (size_t drawbufferIdx = 1; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000599 {
Geoff Langa15472a2015-08-11 11:48:03 -0400600 if (getDrawBuffer(drawbufferIdx) != nullptr)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000601 {
602 return true;
603 }
604 }
605
606 return false;
607}
608
Geoff Lang9aded172017-04-05 11:07:56 -0400609void Framebuffer::invalidateCompletenessCache()
610{
611 if (mId != 0)
612 {
613 mCachedStatus.reset();
614 }
615}
616
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400617GLenum Framebuffer::checkStatus(const Context *context)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000618{
Corentin Wallezccab69d2017-01-27 16:57:15 -0500619 // The default framebuffer is always complete except when it is surfaceless in which
620 // case it is always unsupported. We return early because the default framebuffer may
621 // not be subject to the same rules as application FBOs. ie, it could have 0x0 size.
Geoff Lang528ce3c2014-12-01 10:44:07 -0500622 if (mId == 0)
623 {
Corentin Wallezccab69d2017-01-27 16:57:15 -0500624 ASSERT(mCachedStatus.valid());
625 ASSERT(mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE ||
626 mCachedStatus.value() == GL_FRAMEBUFFER_UNDEFINED_OES);
627 return mCachedStatus.value();
Geoff Lang528ce3c2014-12-01 10:44:07 -0500628 }
629
Jamie Madill362876b2016-06-16 14:46:59 -0400630 if (hasAnyDirtyBit() || !mCachedStatus.valid())
631 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400632 mCachedStatus = checkStatusImpl(context);
Jamie Madill362876b2016-06-16 14:46:59 -0400633 }
634
635 return mCachedStatus.value();
636}
637
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400638GLenum Framebuffer::checkStatusImpl(const Context *context)
Jamie Madill362876b2016-06-16 14:46:59 -0400639{
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400640 const ContextState &state = context->getContextState();
641
Jamie Madill362876b2016-06-16 14:46:59 -0400642 ASSERT(mId != 0);
643
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000644 unsigned int colorbufferSize = 0;
Jamie Madill231c7f52017-04-26 13:45:37 -0400645 int samples = -1;
646 bool missingAttachment = true;
JiangYizhou461d9a32017-01-04 16:37:26 +0800647 Optional<GLboolean> fixedSampleLocations;
648 bool hasRenderbuffer = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000649
Jamie Madill48ef11b2016-04-27 15:21:52 -0400650 for (const FramebufferAttachment &colorAttachment : mState.mColorAttachments)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000651 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400652 if (colorAttachment.isAttached())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000653 {
Geoff Lang9f10b772017-05-16 15:51:03 -0400654 if (!CheckAttachmentCompleteness(context, colorAttachment))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000655 {
656 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
657 }
daniel@transgaming.com01868132010-08-24 19:21:17 +0000658
Geoff Lang677bb6f2017-04-05 12:40:40 -0400659 const InternalFormat &format = *colorAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -0400660 if (format.depthBits > 0 || format.stencilBits > 0)
661 {
662 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
663 }
664
Jamie Madill2d06b732015-04-20 12:53:28 -0400665 if (colorAttachment.type() == GL_TEXTURE)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000666 {
JiangYizhou461d9a32017-01-04 16:37:26 +0800667 // ES3.1 (section 9.4) requires that the value of TEXTURE_FIXED_SAMPLE_LOCATIONS
668 // should be the same for all attached textures.
669 GLboolean fixedSampleloc = colorAttachment.getTexture()->getFixedSampleLocations(
670 colorAttachment.getTextureImageIndex().type, 0);
671 if (fixedSampleLocations.valid() && fixedSampleloc != fixedSampleLocations.value())
672 {
673 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
674 }
675 else
676 {
677 fixedSampleLocations = fixedSampleloc;
678 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000679 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400680 else if (colorAttachment.type() == GL_RENDERBUFFER)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000681 {
JiangYizhou461d9a32017-01-04 16:37:26 +0800682 hasRenderbuffer = true;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000683 }
684
685 if (!missingAttachment)
686 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000687 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
688 // all color attachments have the same number of samples for the FBO to be complete.
Jamie Madill2d06b732015-04-20 12:53:28 -0400689 if (colorAttachment.getSamples() != samples)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000690 {
691 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
692 }
693
Jamie Madill231c7f52017-04-26 13:45:37 -0400694 // in GLES 2.0, all color attachments attachments must have the same number of
695 // bitplanes in GLES 3.0, there is no such restriction
Martin Radev1be913c2016-07-11 17:59:16 +0300696 if (state.getClientMajorVersion() < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000697 {
Geoff Lang677bb6f2017-04-05 12:40:40 -0400698 if (format.pixelBytes != colorbufferSize)
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000699 {
700 return GL_FRAMEBUFFER_UNSUPPORTED;
701 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000702 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000703 }
704 else
705 {
JiangYizhou461d9a32017-01-04 16:37:26 +0800706 samples = colorAttachment.getSamples();
Geoff Lang677bb6f2017-04-05 12:40:40 -0400707 colorbufferSize = format.pixelBytes;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000708 missingAttachment = false;
709 }
710 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000711 }
712
Jamie Madill48ef11b2016-04-27 15:21:52 -0400713 const FramebufferAttachment &depthAttachment = mState.mDepthAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -0400714 if (depthAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000715 {
Geoff Lang9f10b772017-05-16 15:51:03 -0400716 if (!CheckAttachmentCompleteness(context, depthAttachment))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000717 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000718 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000719 }
720
Geoff Lang677bb6f2017-04-05 12:40:40 -0400721 const InternalFormat &format = *depthAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -0400722 if (format.depthBits == 0)
723 {
724 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000725 }
726
727 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000728 {
Jamie Madill231c7f52017-04-26 13:45:37 -0400729 samples = depthAttachment.getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000730 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000731 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400732 else if (samples != depthAttachment.getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000733 {
Sami Väisänena797e062016-05-12 15:23:40 +0300734 // CHROMIUM_framebuffer_mixed_samples allows a framebuffer to be
735 // considered complete when its depth or stencil samples are a
736 // multiple of the number of color samples.
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700737 const bool mixedSamples = state.getExtensions().framebufferMixedSamples;
Sami Väisänena797e062016-05-12 15:23:40 +0300738 if (!mixedSamples)
739 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
740
741 const int colorSamples = samples ? samples : 1;
742 const int depthSamples = depthAttachment.getSamples();
743 if ((depthSamples % colorSamples) != 0)
744 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000745 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000746 }
747
Jamie Madill48ef11b2016-04-27 15:21:52 -0400748 const FramebufferAttachment &stencilAttachment = mState.mStencilAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -0400749 if (stencilAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000750 {
Geoff Lang9f10b772017-05-16 15:51:03 -0400751 if (!CheckAttachmentCompleteness(context, stencilAttachment))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000752 {
753 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
754 }
755
Geoff Lang677bb6f2017-04-05 12:40:40 -0400756 const InternalFormat &format = *stencilAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -0400757 if (format.stencilBits == 0)
758 {
759 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000760 }
761
762 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000763 {
Jamie Madill231c7f52017-04-26 13:45:37 -0400764 samples = stencilAttachment.getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000765 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000766 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400767 else if (samples != stencilAttachment.getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000768 {
Sami Väisänena797e062016-05-12 15:23:40 +0300769 // see the comments in depth attachment check.
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700770 const bool mixedSamples = state.getExtensions().framebufferMixedSamples;
Sami Väisänena797e062016-05-12 15:23:40 +0300771 if (!mixedSamples)
772 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
773
774 const int colorSamples = samples ? samples : 1;
775 const int stencilSamples = stencilAttachment.getSamples();
776 if ((stencilSamples % colorSamples) != 0)
777 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000778 }
Corentin Wallez086d59a2016-04-29 09:06:49 -0400779
780 // Starting from ES 3.0 stencil and depth, if present, should be the same image
Martin Radev1be913c2016-07-11 17:59:16 +0300781 if (state.getClientMajorVersion() >= 3 && depthAttachment.isAttached() &&
Corentin Wallez086d59a2016-04-29 09:06:49 -0400782 stencilAttachment != depthAttachment)
783 {
784 return GL_FRAMEBUFFER_UNSUPPORTED;
785 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000786 }
787
Jamie Madilla02315b2017-02-23 14:14:47 -0500788 // Special additional validation for WebGL 1 DEPTH/STENCIL/DEPTH_STENCIL.
789 if (state.isWebGL1())
790 {
791 if (!mState.mWebGLDepthStencilConsistent)
792 {
793 return GL_FRAMEBUFFER_UNSUPPORTED;
794 }
795
796 if (mState.mWebGLDepthStencilAttachment.isAttached())
797 {
798 if (mState.mWebGLDepthStencilAttachment.getDepthSize() == 0 ||
799 mState.mWebGLDepthStencilAttachment.getStencilSize() == 0)
800 {
801 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
802 }
803 }
804 else if (mState.mStencilAttachment.isAttached() &&
805 mState.mStencilAttachment.getDepthSize() > 0)
806 {
807 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
808 }
809 else if (mState.mDepthAttachment.isAttached() &&
810 mState.mDepthAttachment.getStencilSize() > 0)
811 {
812 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
813 }
814 }
815
JiangYizhou461d9a32017-01-04 16:37:26 +0800816 // ES3.1(section 9.4) requires that if no image is attached to the
817 // framebuffer, and either the value of the framebuffer's FRAMEBUFFER_DEFAULT_WIDTH
818 // or FRAMEBUFFER_DEFAULT_HEIGHT parameters is zero, the framebuffer is
819 // considered incomplete.
820 GLint defaultWidth = mState.getDefaultWidth();
821 GLint defaultHeight = mState.getDefaultHeight();
822
823 if (missingAttachment && (defaultWidth == 0 || defaultHeight == 0))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000824 {
825 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000826 }
827
Geoff Langa0e0aeb2017-04-12 15:06:29 -0400828 // In ES 2.0 and WebGL, all color attachments must have the same width and height.
Jamie Madillcc86d642015-11-24 13:00:07 -0500829 // In ES 3.0, there is no such restriction.
Geoff Langa0e0aeb2017-04-12 15:06:29 -0400830 if ((state.getClientMajorVersion() < 3 || state.getExtensions().webglCompatibility) &&
831 !mState.attachmentsHaveSameDimensions())
Jamie Madillcc86d642015-11-24 13:00:07 -0500832 {
833 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
834 }
835
JiangYizhou461d9a32017-01-04 16:37:26 +0800836 // ES3.1(section 9.4) requires that if the attached images are a mix of renderbuffers
837 // and textures, the value of TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all
838 // attached textures.
839 if (fixedSampleLocations.valid() && hasRenderbuffer && !fixedSampleLocations.value())
840 {
841 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
842 }
843
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400844 syncState(context);
Jamie Madillcc86d642015-11-24 13:00:07 -0500845 if (!mImpl->checkStatus())
846 {
847 return GL_FRAMEBUFFER_UNSUPPORTED;
848 }
849
850 return GL_FRAMEBUFFER_COMPLETE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000851}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000852
Austin Kinross08332632015-05-05 13:35:47 -0700853Error Framebuffer::discard(size_t count, const GLenum *attachments)
854{
855 return mImpl->discard(count, attachments);
856}
857
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500858Error Framebuffer::invalidate(size_t count, const GLenum *attachments)
Jamie Madill2d96b9e2014-08-29 15:46:47 -0400859{
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500860 return mImpl->invalidate(count, attachments);
Jamie Madill2d96b9e2014-08-29 15:46:47 -0400861}
862
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500863Error Framebuffer::invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area)
Jamie Madill400a4412014-08-29 15:46:45 -0400864{
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500865 return mImpl->invalidateSub(count, attachments, area);
Jamie Madill400a4412014-08-29 15:46:45 -0400866}
867
Jamie Madill8415b5f2016-04-26 13:41:39 -0400868Error Framebuffer::clear(rx::ContextImpl *context, GLbitfield mask)
Geoff Langb04dc822014-12-01 12:02:02 -0500869{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700870 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500871 {
Jamie Madill362876b2016-06-16 14:46:59 -0400872 return gl::NoError();
Jamie Madill984ef412015-11-24 16:10:21 -0500873 }
874
Jamie Madill8415b5f2016-04-26 13:41:39 -0400875 return mImpl->clear(context, mask);
Geoff Langb04dc822014-12-01 12:02:02 -0500876}
877
Jamie Madill8415b5f2016-04-26 13:41:39 -0400878Error Framebuffer::clearBufferfv(rx::ContextImpl *context,
Jamie Madill1b94d432015-08-07 13:23:23 -0400879 GLenum buffer,
880 GLint drawbuffer,
881 const GLfloat *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500882{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700883 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500884 {
Jamie Madill362876b2016-06-16 14:46:59 -0400885 return gl::NoError();
Jamie Madill984ef412015-11-24 16:10:21 -0500886 }
887
Jamie Madill8415b5f2016-04-26 13:41:39 -0400888 return mImpl->clearBufferfv(context, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500889}
890
Jamie Madill8415b5f2016-04-26 13:41:39 -0400891Error Framebuffer::clearBufferuiv(rx::ContextImpl *context,
Jamie Madill1b94d432015-08-07 13:23:23 -0400892 GLenum buffer,
893 GLint drawbuffer,
894 const GLuint *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500895{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700896 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500897 {
Jamie Madill362876b2016-06-16 14:46:59 -0400898 return gl::NoError();
Jamie Madill984ef412015-11-24 16:10:21 -0500899 }
900
Jamie Madill8415b5f2016-04-26 13:41:39 -0400901 return mImpl->clearBufferuiv(context, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500902}
903
Jamie Madill8415b5f2016-04-26 13:41:39 -0400904Error Framebuffer::clearBufferiv(rx::ContextImpl *context,
Jamie Madill1b94d432015-08-07 13:23:23 -0400905 GLenum buffer,
906 GLint drawbuffer,
907 const GLint *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500908{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700909 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500910 {
Jamie Madill362876b2016-06-16 14:46:59 -0400911 return gl::NoError();
Jamie Madill984ef412015-11-24 16:10:21 -0500912 }
913
Jamie Madill8415b5f2016-04-26 13:41:39 -0400914 return mImpl->clearBufferiv(context, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500915}
916
Jamie Madill8415b5f2016-04-26 13:41:39 -0400917Error Framebuffer::clearBufferfi(rx::ContextImpl *context,
Jamie Madill1b94d432015-08-07 13:23:23 -0400918 GLenum buffer,
919 GLint drawbuffer,
920 GLfloat depth,
921 GLint stencil)
Geoff Langb04dc822014-12-01 12:02:02 -0500922{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700923 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500924 {
Jamie Madill362876b2016-06-16 14:46:59 -0400925 return gl::NoError();
Jamie Madill984ef412015-11-24 16:10:21 -0500926 }
927
Jamie Madill8415b5f2016-04-26 13:41:39 -0400928 return mImpl->clearBufferfi(context, buffer, drawbuffer, depth, stencil);
Geoff Langb04dc822014-12-01 12:02:02 -0500929}
930
Geoff Langbce529e2014-12-01 12:48:41 -0500931GLenum Framebuffer::getImplementationColorReadFormat() const
932{
933 return mImpl->getImplementationColorReadFormat();
934}
935
936GLenum Framebuffer::getImplementationColorReadType() const
937{
938 return mImpl->getImplementationColorReadType();
939}
940
Jamie Madill8415b5f2016-04-26 13:41:39 -0400941Error Framebuffer::readPixels(rx::ContextImpl *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500942 const Rectangle &area,
Jamie Madill1b94d432015-08-07 13:23:23 -0400943 GLenum format,
944 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400945 void *pixels) const
Geoff Langbce529e2014-12-01 12:48:41 -0500946{
Jamie Madill362876b2016-06-16 14:46:59 -0400947 ANGLE_TRY(mImpl->readPixels(context, area, format, type, pixels));
Geoff Lang520c4ae2015-05-05 13:12:36 -0400948
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700949 Buffer *unpackBuffer = context->getGLState().getUnpackState().pixelBuffer.get();
Geoff Lang520c4ae2015-05-05 13:12:36 -0400950 if (unpackBuffer)
951 {
952 unpackBuffer->onPixelUnpack();
953 }
954
Jamie Madill362876b2016-06-16 14:46:59 -0400955 return NoError();
Geoff Langbce529e2014-12-01 12:48:41 -0500956}
957
Jamie Madill8415b5f2016-04-26 13:41:39 -0400958Error Framebuffer::blit(rx::ContextImpl *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500959 const Rectangle &sourceArea,
960 const Rectangle &destArea,
Geoff Lang242468f2015-09-24 14:15:41 -0400961 GLbitfield mask,
Jamie Madill8415b5f2016-04-26 13:41:39 -0400962 GLenum filter)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500963{
He Yunchao6be602d2016-12-22 14:33:07 +0800964 GLbitfield blitMask = mask;
965
966 // Note that blitting is called against draw framebuffer.
967 // See the code in gl::Context::blitFramebuffer.
968 if ((mask & GL_COLOR_BUFFER_BIT) && !hasEnabledDrawBuffer())
969 {
970 blitMask &= ~GL_COLOR_BUFFER_BIT;
971 }
972
973 if ((mask & GL_STENCIL_BUFFER_BIT) && mState.getStencilAttachment() == nullptr)
974 {
975 blitMask &= ~GL_STENCIL_BUFFER_BIT;
976 }
977
978 if ((mask & GL_DEPTH_BUFFER_BIT) && mState.getDepthAttachment() == nullptr)
979 {
980 blitMask &= ~GL_DEPTH_BUFFER_BIT;
981 }
982
983 if (!blitMask)
984 {
985 return NoError();
986 }
987
988 return mImpl->blit(context, sourceArea, destArea, blitMask, filter);
Geoff Lang54bd5a42014-12-01 12:51:04 -0500989}
990
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400991int Framebuffer::getSamples(const Context *context)
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000992{
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400993 if (complete(context))
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000994 {
Jamie Madill362876b2016-06-16 14:46:59 -0400995 // For a complete framebuffer, all attachments must have the same sample count.
996 // In this case return the first nonzero sample size.
997 const auto *firstColorAttachment = mState.getFirstColorAttachment();
998 if (firstColorAttachment)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000999 {
Jamie Madill362876b2016-06-16 14:46:59 -04001000 ASSERT(firstColorAttachment->isAttached());
1001 return firstColorAttachment->getSamples();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001002 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001003 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001004
1005 return 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001006}
1007
Corentin Wallezccab69d2017-01-27 16:57:15 -05001008Error Framebuffer::getSamplePosition(size_t index, GLfloat *xy) const
1009{
1010 ANGLE_TRY(mImpl->getSamplePosition(index, xy));
1011 return gl::NoError();
1012}
1013
Jamie Madille261b442014-06-25 12:42:21 -04001014bool Framebuffer::hasValidDepthStencil() const
1015{
Jamie Madill48ef11b2016-04-27 15:21:52 -04001016 return mState.getDepthStencilAttachment() != nullptr;
Jamie Madille261b442014-06-25 12:42:21 -04001017}
1018
Jamie Madilla02315b2017-02-23 14:14:47 -05001019void Framebuffer::setAttachment(const Context *context,
1020 GLenum type,
Jamie Madill2d06b732015-04-20 12:53:28 -04001021 GLenum binding,
1022 const ImageIndex &textureIndex,
1023 FramebufferAttachmentObject *resource)
Geoff Langab75a052014-10-15 12:56:37 -04001024{
Jamie Madilla02315b2017-02-23 14:14:47 -05001025 // Context may be null in unit tests.
1026 if (!context || !context->isWebGL1())
1027 {
1028 setAttachmentImpl(type, binding, textureIndex, resource);
1029 return;
1030 }
1031
1032 switch (binding)
1033 {
1034 case GL_DEPTH_STENCIL:
1035 case GL_DEPTH_STENCIL_ATTACHMENT:
1036 mState.mWebGLDepthStencilAttachment.attach(type, binding, textureIndex, resource);
1037 break;
1038 case GL_DEPTH:
1039 case GL_DEPTH_ATTACHMENT:
1040 mState.mWebGLDepthAttachment.attach(type, binding, textureIndex, resource);
1041 break;
1042 case GL_STENCIL:
1043 case GL_STENCIL_ATTACHMENT:
1044 mState.mWebGLStencilAttachment.attach(type, binding, textureIndex, resource);
1045 break;
1046 default:
1047 setAttachmentImpl(type, binding, textureIndex, resource);
1048 return;
1049 }
1050
1051 commitWebGL1DepthStencilIfConsistent();
1052}
1053
1054void Framebuffer::commitWebGL1DepthStencilIfConsistent()
1055{
1056 int count = 0;
1057
1058 std::array<FramebufferAttachment *, 3> attachments = {{&mState.mWebGLDepthStencilAttachment,
1059 &mState.mWebGLDepthAttachment,
1060 &mState.mWebGLStencilAttachment}};
1061 for (FramebufferAttachment *attachment : attachments)
1062 {
1063 if (attachment->isAttached())
1064 {
1065 count++;
1066 }
1067 }
1068
1069 mState.mWebGLDepthStencilConsistent = (count <= 1);
1070 if (!mState.mWebGLDepthStencilConsistent)
1071 {
1072 // Inconsistent.
1073 return;
1074 }
1075
Geoff Lange466c552017-03-17 15:24:12 -04001076 auto getImageIndexIfTextureAttachment = [](const FramebufferAttachment &attachment) {
1077 if (attachment.type() == GL_TEXTURE)
1078 {
1079 return attachment.getTextureImageIndex();
1080 }
1081 else
1082 {
1083 return ImageIndex::MakeInvalid();
1084 }
1085 };
1086
Jamie Madilla02315b2017-02-23 14:14:47 -05001087 if (mState.mWebGLDepthAttachment.isAttached())
1088 {
1089 const auto &depth = mState.mWebGLDepthAttachment;
Geoff Lange466c552017-03-17 15:24:12 -04001090 setAttachmentImpl(depth.type(), GL_DEPTH_ATTACHMENT,
1091 getImageIndexIfTextureAttachment(depth), depth.getResource());
Jamie Madilla02315b2017-02-23 14:14:47 -05001092 setAttachmentImpl(GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex::MakeInvalid(), nullptr);
1093 }
1094 else if (mState.mWebGLStencilAttachment.isAttached())
1095 {
1096 const auto &stencil = mState.mWebGLStencilAttachment;
1097 setAttachmentImpl(GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex::MakeInvalid(), nullptr);
Geoff Lange466c552017-03-17 15:24:12 -04001098 setAttachmentImpl(stencil.type(), GL_STENCIL_ATTACHMENT,
1099 getImageIndexIfTextureAttachment(stencil), stencil.getResource());
Jamie Madilla02315b2017-02-23 14:14:47 -05001100 }
1101 else if (mState.mWebGLDepthStencilAttachment.isAttached())
1102 {
1103 const auto &depthStencil = mState.mWebGLDepthStencilAttachment;
Geoff Lange466c552017-03-17 15:24:12 -04001104 setAttachmentImpl(depthStencil.type(), GL_DEPTH_ATTACHMENT,
1105 getImageIndexIfTextureAttachment(depthStencil),
Jamie Madilla02315b2017-02-23 14:14:47 -05001106 depthStencil.getResource());
Geoff Lange466c552017-03-17 15:24:12 -04001107 setAttachmentImpl(depthStencil.type(), GL_STENCIL_ATTACHMENT,
1108 getImageIndexIfTextureAttachment(depthStencil),
Jamie Madilla02315b2017-02-23 14:14:47 -05001109 depthStencil.getResource());
1110 }
1111 else
1112 {
1113 setAttachmentImpl(GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex::MakeInvalid(), nullptr);
1114 setAttachmentImpl(GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex::MakeInvalid(), nullptr);
1115 }
1116}
1117
1118void Framebuffer::setAttachmentImpl(GLenum type,
1119 GLenum binding,
1120 const ImageIndex &textureIndex,
1121 FramebufferAttachmentObject *resource)
1122{
Jamie Madilla02315b2017-02-23 14:14:47 -05001123 switch (binding)
1124 {
Jamie Madillb8126692017-04-05 11:22:17 -04001125 case GL_DEPTH_STENCIL:
1126 case GL_DEPTH_STENCIL_ATTACHMENT:
1127 {
1128 // ensure this is a legitimate depth+stencil format
1129 FramebufferAttachmentObject *attachmentObj = resource;
1130 if (resource)
1131 {
Jamie Madill4fd95d52017-04-05 11:22:18 -04001132 const Format &format = resource->getAttachmentFormat(binding, textureIndex);
Jamie Madillb8126692017-04-05 11:22:17 -04001133 if (format.info->depthBits == 0 || format.info->stencilBits == 0)
1134 {
1135 // Attaching nullptr detaches the current attachment.
1136 attachmentObj = nullptr;
1137 }
1138 }
1139
1140 updateAttachment(&mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
1141 &mDirtyDepthAttachmentBinding, type, binding, textureIndex,
1142 attachmentObj);
1143 updateAttachment(&mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
1144 &mDirtyStencilAttachmentBinding, type, binding, textureIndex,
1145 attachmentObj);
1146 return;
1147 }
1148
Jamie Madilla02315b2017-02-23 14:14:47 -05001149 case GL_DEPTH:
1150 case GL_DEPTH_ATTACHMENT:
Jamie Madillb8126692017-04-05 11:22:17 -04001151 updateAttachment(&mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
1152 &mDirtyDepthAttachmentBinding, type, binding, textureIndex, resource);
Jamie Madill2d06b732015-04-20 12:53:28 -04001153 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001154
Jamie Madilla02315b2017-02-23 14:14:47 -05001155 case GL_STENCIL:
1156 case GL_STENCIL_ATTACHMENT:
Jamie Madillb8126692017-04-05 11:22:17 -04001157 updateAttachment(&mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
1158 &mDirtyStencilAttachmentBinding, type, binding, textureIndex,
1159 resource);
Jamie Madilla02315b2017-02-23 14:14:47 -05001160 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001161
Jamie Madilla02315b2017-02-23 14:14:47 -05001162 case GL_BACK:
1163 mState.mColorAttachments[0].attach(type, binding, textureIndex, resource);
1164 mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0);
1165 // No need for a resource binding for the default FBO, it's always complete.
1166 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001167
Jamie Madilla02315b2017-02-23 14:14:47 -05001168 default:
1169 {
1170 size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
1171 ASSERT(colorIndex < mState.mColorAttachments.size());
Jamie Madillb8126692017-04-05 11:22:17 -04001172 size_t dirtyBit = DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex;
1173 updateAttachment(&mState.mColorAttachments[colorIndex], dirtyBit,
1174 &mDirtyColorAttachmentBindings[colorIndex], type, binding,
1175 textureIndex, resource);
Jamie Madilla02315b2017-02-23 14:14:47 -05001176
1177 bool enabled = (type != GL_NONE && getDrawBufferState(colorIndex) != GL_NONE);
1178 mState.mEnabledDrawBuffers.set(colorIndex, enabled);
Jamie Madill2d06b732015-04-20 12:53:28 -04001179 }
Jamie Madilla02315b2017-02-23 14:14:47 -05001180 break;
Geoff Langab75a052014-10-15 12:56:37 -04001181 }
1182}
1183
Jamie Madillb8126692017-04-05 11:22:17 -04001184void Framebuffer::updateAttachment(FramebufferAttachment *attachment,
1185 size_t dirtyBit,
1186 OnAttachmentDirtyBinding *onDirtyBinding,
1187 GLenum type,
1188 GLenum binding,
1189 const ImageIndex &textureIndex,
1190 FramebufferAttachmentObject *resource)
1191{
1192 attachment->attach(type, binding, textureIndex, resource);
1193 mDirtyBits.set(dirtyBit);
1194 BindResourceChannel(onDirtyBinding, resource);
1195}
1196
Jamie Madilla02315b2017-02-23 14:14:47 -05001197void Framebuffer::resetAttachment(const Context *context, GLenum binding)
Jamie Madill2d06b732015-04-20 12:53:28 -04001198{
Jamie Madilla02315b2017-02-23 14:14:47 -05001199 setAttachment(context, GL_NONE, binding, ImageIndex::MakeInvalid(), nullptr);
Jamie Madill2d06b732015-04-20 12:53:28 -04001200}
1201
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001202void Framebuffer::syncState(const Context *context)
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001203{
1204 if (mDirtyBits.any())
1205 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001206 mImpl->syncState(rx::SafeGetImpl(context), mDirtyBits);
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001207 mDirtyBits.reset();
Corentin Wallezccab69d2017-01-27 16:57:15 -05001208 if (mId != 0)
1209 {
1210 mCachedStatus.reset();
1211 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001212 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001213}
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001214
Jamie Madill1e5499d2017-04-05 11:22:16 -04001215void Framebuffer::signal(uint32_t token)
Jamie Madill51f40ec2016-06-15 14:06:00 -04001216{
Jamie Madill362876b2016-06-16 14:46:59 -04001217 // TOOD(jmadill): Make this only update individual attachments to do less work.
1218 mCachedStatus.reset();
Jamie Madill51f40ec2016-06-15 14:06:00 -04001219}
1220
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001221bool Framebuffer::complete(const Context *context)
Jamie Madill51f40ec2016-06-15 14:06:00 -04001222{
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001223 return (checkStatus(context) == GL_FRAMEBUFFER_COMPLETE);
1224}
1225
1226bool Framebuffer::cachedComplete() const
1227{
1228 return (mCachedStatus.valid() && mCachedStatus == GL_FRAMEBUFFER_COMPLETE);
Jamie Madill51f40ec2016-06-15 14:06:00 -04001229}
1230
Jamie Madilla4595b82017-01-11 17:36:34 -05001231bool Framebuffer::formsRenderingFeedbackLoopWith(const State &state) const
1232{
1233 const Program *program = state.getProgram();
1234
1235 // TODO(jmadill): Default framebuffer feedback loops.
1236 if (mId == 0)
1237 {
1238 return false;
1239 }
1240
1241 // The bitset will skip inactive draw buffers.
Jamie Madill6de51852017-04-12 09:53:01 -04001242 for (size_t drawIndex : mState.mEnabledDrawBuffers)
Jamie Madilla4595b82017-01-11 17:36:34 -05001243 {
1244 const FramebufferAttachment *attachment = getDrawBuffer(drawIndex);
1245 if (attachment && attachment->type() == GL_TEXTURE)
1246 {
1247 // Validate the feedback loop.
1248 if (program->samplesFromTexture(state, attachment->id()))
1249 {
1250 return true;
1251 }
1252 }
1253 }
1254
Jamie Madill1d37bc52017-02-02 19:59:58 -05001255 // Validate depth-stencil feedback loop.
1256 const auto &dsState = state.getDepthStencilState();
1257
1258 // We can skip the feedback loop checks if depth/stencil is masked out or disabled.
1259 const FramebufferAttachment *depth = getDepthbuffer();
1260 if (depth && depth->type() == GL_TEXTURE && dsState.depthTest && dsState.depthMask)
1261 {
1262 if (program->samplesFromTexture(state, depth->id()))
1263 {
1264 return true;
1265 }
1266 }
1267
1268 // Note: we assume the front and back masks are the same for WebGL.
1269 const FramebufferAttachment *stencil = getStencilbuffer();
1270 ASSERT(dsState.stencilBackWritemask == dsState.stencilWritemask);
1271 if (stencil && stencil->type() == GL_TEXTURE && dsState.stencilTest &&
1272 dsState.stencilWritemask != 0)
1273 {
1274 // Skip the feedback loop check if depth/stencil point to the same resource.
1275 if (!depth || *stencil != *depth)
1276 {
1277 if (program->samplesFromTexture(state, stencil->id()))
1278 {
1279 return true;
1280 }
1281 }
1282 }
1283
Jamie Madilla4595b82017-01-11 17:36:34 -05001284 return false;
1285}
1286
Jamie Madillfd3dd432017-02-02 19:59:59 -05001287bool Framebuffer::formsCopyingFeedbackLoopWith(GLuint copyTextureID,
1288 GLint copyTextureLevel,
1289 GLint copyTextureLayer) const
Jamie Madillf695a3a2017-01-11 17:36:35 -05001290{
1291 if (mId == 0)
1292 {
1293 // It seems impossible to form a texture copying feedback loop with the default FBO.
1294 return false;
1295 }
1296
1297 const FramebufferAttachment *readAttachment = getReadColorbuffer();
1298 ASSERT(readAttachment);
1299
1300 if (readAttachment->isTextureWithId(copyTextureID))
1301 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05001302 const auto &imageIndex = readAttachment->getTextureImageIndex();
1303 if (imageIndex.mipIndex == copyTextureLevel)
Jamie Madillf695a3a2017-01-11 17:36:35 -05001304 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05001305 // Check 3D/Array texture layers.
1306 return imageIndex.layerIndex == ImageIndex::ENTIRE_LEVEL ||
1307 copyTextureLayer == ImageIndex::ENTIRE_LEVEL ||
1308 imageIndex.layerIndex == copyTextureLayer;
Jamie Madillf695a3a2017-01-11 17:36:35 -05001309 }
1310 }
1311 return false;
1312}
1313
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001314GLint Framebuffer::getDefaultWidth() const
1315{
1316 return mState.getDefaultWidth();
1317}
1318
1319GLint Framebuffer::getDefaultHeight() const
1320{
1321 return mState.getDefaultHeight();
1322}
1323
1324GLint Framebuffer::getDefaultSamples() const
1325{
1326 return mState.getDefaultSamples();
1327}
1328
1329GLboolean Framebuffer::getDefaultFixedSampleLocations() const
1330{
1331 return mState.getDefaultFixedSampleLocations();
1332}
1333
1334void Framebuffer::setDefaultWidth(GLint defaultWidth)
1335{
1336 mState.mDefaultWidth = defaultWidth;
1337 mDirtyBits.set(DIRTY_BIT_DEFAULT_WIDTH);
1338}
1339
1340void Framebuffer::setDefaultHeight(GLint defaultHeight)
1341{
1342 mState.mDefaultHeight = defaultHeight;
1343 mDirtyBits.set(DIRTY_BIT_DEFAULT_HEIGHT);
1344}
1345
1346void Framebuffer::setDefaultSamples(GLint defaultSamples)
1347{
1348 mState.mDefaultSamples = defaultSamples;
1349 mDirtyBits.set(DIRTY_BIT_DEFAULT_SAMPLES);
1350}
1351
1352void Framebuffer::setDefaultFixedSampleLocations(GLboolean defaultFixedSampleLocations)
1353{
1354 mState.mDefaultFixedSampleLocations = defaultFixedSampleLocations;
1355 mDirtyBits.set(DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS);
1356}
1357
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001358// TODO(jmadill): Remove this kludge.
1359GLenum Framebuffer::checkStatus(const ValidationContext *context)
1360{
1361 return checkStatus(static_cast<const Context *>(context));
1362}
1363
1364int Framebuffer::getSamples(const ValidationContext *context)
1365{
1366 return getSamples(static_cast<const Context *>(context));
1367}
1368
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001369} // namespace gl