blob: 4bacd6fed406446057f0aaff17af6d4f306d5d13 [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"
Brandon Jones76746f92017-11-22 11:44:41 -080022#include "libANGLE/angletypes.h"
Jamie Madillc46f45d2015-03-31 13:20:55 -040023#include "libANGLE/formatutils.h"
Jamie Madill8415b5f2016-04-26 13:41:39 -040024#include "libANGLE/renderer/ContextImpl.h"
Geoff Langb5d8f232014-12-04 15:43:01 -050025#include "libANGLE/renderer/FramebufferImpl.h"
Jamie Madill7aea7e02016-05-10 10:39:45 -040026#include "libANGLE/renderer/GLImplFactory.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050027#include "libANGLE/renderer/RenderbufferImpl.h"
Corentin Wallez37c39792015-08-20 14:19:46 -040028#include "libANGLE/renderer/SurfaceImpl.h"
Geoff Lang0b7eef72014-06-12 14:10:47 -040029
Jamie Madill362876b2016-06-16 14:46:59 -040030using namespace angle;
31
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000032namespace gl
33{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000034
Jamie Madilld1405e52015-03-05 15:41:39 -050035namespace
36{
Jamie Madill362876b2016-06-16 14:46:59 -040037
Jamie Madill1e5499d2017-04-05 11:22:16 -040038void BindResourceChannel(OnAttachmentDirtyBinding *binding, FramebufferAttachmentObject *resource)
Jamie Madilld1405e52015-03-05 15:41:39 -050039{
Jamie Madill362876b2016-06-16 14:46:59 -040040 binding->bind(resource ? resource->getDirtyChannel() : nullptr);
Jamie Madilld1405e52015-03-05 15:41:39 -050041}
Jamie Madill362876b2016-06-16 14:46:59 -040042
Martin Radev9bc9a322017-07-21 14:28:17 +030043bool CheckMultiviewStateMatchesForCompleteness(const FramebufferAttachment *firstAttachment,
44 const FramebufferAttachment *secondAttachment)
45{
46 ASSERT(firstAttachment && secondAttachment);
47 ASSERT(firstAttachment->isAttached() && secondAttachment->isAttached());
48
49 if (firstAttachment->getNumViews() != secondAttachment->getNumViews())
50 {
51 return false;
52 }
53 if (firstAttachment->getBaseViewIndex() != secondAttachment->getBaseViewIndex())
54 {
55 return false;
56 }
57 if (firstAttachment->getMultiviewLayout() != secondAttachment->getMultiviewLayout())
58 {
59 return false;
60 }
61 if (firstAttachment->getMultiviewViewportOffsets() !=
62 secondAttachment->getMultiviewViewportOffsets())
63 {
64 return false;
65 }
66 return true;
67}
68
Geoff Lang9f10b772017-05-16 15:51:03 -040069bool CheckAttachmentCompleteness(const Context *context, const FramebufferAttachment &attachment)
70{
71 ASSERT(attachment.isAttached());
72
73 const Extents &size = attachment.getSize();
74 if (size.width == 0 || size.height == 0)
75 {
76 return false;
77 }
78
79 const InternalFormat &format = *attachment.getFormat().info;
80 if (!format.renderSupport(context->getClientVersion(), context->getExtensions()))
81 {
82 return false;
83 }
84
85 if (attachment.type() == GL_TEXTURE)
86 {
87 if (attachment.layer() >= size.depth)
88 {
89 return false;
90 }
91
92 // ES3 specifies that cube map texture attachments must be cube complete.
93 // This language is missing from the ES2 spec, but we enforce it here because some
94 // desktop OpenGL drivers also enforce this validation.
95 // TODO(jmadill): Check if OpenGL ES2 drivers enforce cube completeness.
96 const Texture *texture = attachment.getTexture();
97 ASSERT(texture);
98 if (texture->getTarget() == GL_TEXTURE_CUBE_MAP &&
99 !texture->getTextureState().isCubeComplete())
100 {
101 return false;
102 }
Geoff Lang857c09d2017-05-16 15:55:04 -0400103
104 if (!texture->getImmutableFormat())
105 {
106 GLuint attachmentMipLevel = static_cast<GLuint>(attachment.mipLevel());
107
108 // From the ES 3.0 spec, pg 213:
109 // If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is TEXTURE and the value of
110 // FRAMEBUFFER_ATTACHMENT_OBJECT_NAME does not name an immutable-format texture,
111 // then the value of FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL must be in the
112 // range[levelbase, q], where levelbase is the value of TEXTURE_BASE_LEVEL and q is
113 // the effective maximum texture level defined in the Mipmapping discussion of
114 // section 3.8.10.4.
115 if (attachmentMipLevel < texture->getBaseLevel() ||
116 attachmentMipLevel > texture->getMipmapMaxLevel())
117 {
118 return false;
119 }
120
121 // Form the ES 3.0 spec, pg 213/214:
122 // If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is TEXTURE and the value of
123 // FRAMEBUFFER_ATTACHMENT_OBJECT_NAME does not name an immutable-format texture and
124 // the value of FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL is not levelbase, then the
125 // texture must be mipmap complete, and if FRAMEBUFFER_ATTACHMENT_OBJECT_NAME names
126 // a cubemap texture, the texture must also be cube complete.
127 if (attachmentMipLevel != texture->getBaseLevel() && !texture->isMipmapComplete())
128 {
129 return false;
130 }
131 }
Geoff Lang9f10b772017-05-16 15:51:03 -0400132 }
133
134 return true;
135};
136
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400137bool CheckAttachmentSampleCompleteness(const Context *context,
138 const FramebufferAttachment &attachment,
139 bool colorAttachment,
140 Optional<int> *samples,
Geoff Lang92019432017-11-20 13:09:34 -0500141 Optional<bool> *fixedSampleLocations)
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400142{
143 ASSERT(attachment.isAttached());
144
145 if (attachment.type() == GL_TEXTURE)
146 {
147 const Texture *texture = attachment.getTexture();
148 ASSERT(texture);
149
150 const ImageIndex &attachmentImageIndex = attachment.getTextureImageIndex();
151
152 // ES3.1 (section 9.4) requires that the value of TEXTURE_FIXED_SAMPLE_LOCATIONS should be
153 // the same for all attached textures.
Geoff Lang92019432017-11-20 13:09:34 -0500154 bool fixedSampleloc = texture->getFixedSampleLocations(attachmentImageIndex.type,
155 attachmentImageIndex.mipIndex);
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400156 if (fixedSampleLocations->valid() && fixedSampleloc != fixedSampleLocations->value())
157 {
158 return false;
159 }
160 else
161 {
162 *fixedSampleLocations = fixedSampleloc;
163 }
164 }
165
166 if (samples->valid())
167 {
168 if (attachment.getSamples() != samples->value())
169 {
170 if (colorAttachment)
171 {
172 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
173 // all color attachments have the same number of samples for the FBO to be complete.
174 return false;
175 }
176 else
177 {
178 // CHROMIUM_framebuffer_mixed_samples allows a framebuffer to be considered complete
179 // when its depth or stencil samples are a multiple of the number of color samples.
180 if (!context->getExtensions().framebufferMixedSamples)
181 {
182 return false;
183 }
184
185 if ((attachment.getSamples() % std::max(samples->value(), 1)) != 0)
186 {
187 return false;
188 }
189 }
190 }
191 }
192 else
193 {
194 *samples = attachment.getSamples();
195 }
196
197 return true;
198}
199
Jamie Madill05b35b22017-10-03 09:01:44 -0400200// Needed to index into the attachment arrays/bitsets.
Jamie Madill682efdc2017-10-03 14:10:29 -0400201static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS) ==
Jamie Madill05b35b22017-10-03 09:01:44 -0400202 gl::Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX,
203 "Framebuffer Dirty bit mismatch");
Jamie Madill682efdc2017-10-03 14:10:29 -0400204static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS) ==
Jamie Madill05b35b22017-10-03 09:01:44 -0400205 gl::Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT,
206 "Framebuffer Dirty bit mismatch");
Jamie Madill682efdc2017-10-03 14:10:29 -0400207static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS + 1) ==
Jamie Madill05b35b22017-10-03 09:01:44 -0400208 gl::Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT,
209 "Framebuffer Dirty bit mismatch");
210
211Error InitAttachment(const Context *context, FramebufferAttachment *attachment)
212{
213 ASSERT(attachment->isAttached());
214 if (attachment->initState() == InitState::MayNeedInit)
215 {
216 ANGLE_TRY(attachment->initializeContents(context));
217 }
218 return NoError();
219}
220
221bool IsColorMaskedOut(const BlendState &blend)
222{
223 return (!blend.colorMaskRed && !blend.colorMaskGreen && !blend.colorMaskBlue &&
224 !blend.colorMaskAlpha);
225}
226
227bool IsDepthMaskedOut(const DepthStencilState &depthStencil)
228{
229 return !depthStencil.depthMask;
230}
231
232bool IsStencilMaskedOut(const DepthStencilState &depthStencil)
233{
234 return ((depthStencil.stencilMask & depthStencil.stencilWritemask) == 0);
235}
236
237bool IsClearBufferMaskedOut(const Context *context, GLenum buffer)
238{
239 switch (buffer)
240 {
241 case GL_COLOR:
242 return IsColorMaskedOut(context->getGLState().getBlendState());
243 case GL_DEPTH:
244 return IsDepthMaskedOut(context->getGLState().getDepthStencilState());
245 case GL_STENCIL:
246 return IsStencilMaskedOut(context->getGLState().getDepthStencilState());
247 case GL_DEPTH_STENCIL:
248 return IsDepthMaskedOut(context->getGLState().getDepthStencilState()) &&
249 IsStencilMaskedOut(context->getGLState().getDepthStencilState());
250 default:
251 UNREACHABLE();
252 return true;
253 }
254}
255
Jamie Madill362876b2016-06-16 14:46:59 -0400256} // anonymous namespace
Jamie Madilld1405e52015-03-05 15:41:39 -0500257
Jamie Madill6f60d052017-02-22 15:20:11 -0500258// This constructor is only used for default framebuffers.
Jamie Madill48ef11b2016-04-27 15:21:52 -0400259FramebufferState::FramebufferState()
Geoff Lang70d0f492015-12-10 17:45:46 -0500260 : mLabel(),
261 mColorAttachments(1),
Corentin Walleze7557742017-06-01 13:09:57 -0400262 mDrawBufferStates(1, GL_BACK),
Jamie Madill6f60d052017-02-22 15:20:11 -0500263 mReadBufferState(GL_BACK),
Brandon Jones76746f92017-11-22 11:44:41 -0800264 mDrawBufferTypeMask(),
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800265 mDefaultWidth(0),
266 mDefaultHeight(0),
267 mDefaultSamples(0),
Jamie Madilla02315b2017-02-23 14:14:47 -0500268 mDefaultFixedSampleLocations(GL_FALSE),
269 mWebGLDepthStencilConsistent(true)
Corentin Wallez37c39792015-08-20 14:19:46 -0400270{
Geoff Langd90d3882017-03-21 10:49:54 -0400271 ASSERT(mDrawBufferStates.size() > 0);
Jamie Madilla4595b82017-01-11 17:36:34 -0500272 mEnabledDrawBuffers.set(0);
Corentin Wallez37c39792015-08-20 14:19:46 -0400273}
274
Jamie Madill48ef11b2016-04-27 15:21:52 -0400275FramebufferState::FramebufferState(const Caps &caps)
Geoff Lang70d0f492015-12-10 17:45:46 -0500276 : mLabel(),
277 mColorAttachments(caps.maxColorAttachments),
Jamie Madilld1405e52015-03-05 15:41:39 -0500278 mDrawBufferStates(caps.maxDrawBuffers, GL_NONE),
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800279 mReadBufferState(GL_COLOR_ATTACHMENT0_EXT),
Brandon Jones76746f92017-11-22 11:44:41 -0800280 mDrawBufferTypeMask(),
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800281 mDefaultWidth(0),
282 mDefaultHeight(0),
283 mDefaultSamples(0),
Jamie Madilla02315b2017-02-23 14:14:47 -0500284 mDefaultFixedSampleLocations(GL_FALSE),
285 mWebGLDepthStencilConsistent(true)
Jamie Madilld1405e52015-03-05 15:41:39 -0500286{
Geoff Langa15472a2015-08-11 11:48:03 -0400287 ASSERT(mDrawBufferStates.size() > 0);
Jamie Madilld1405e52015-03-05 15:41:39 -0500288 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
289}
290
Jamie Madill48ef11b2016-04-27 15:21:52 -0400291FramebufferState::~FramebufferState()
Jamie Madilld1405e52015-03-05 15:41:39 -0500292{
Jamie Madilld1405e52015-03-05 15:41:39 -0500293}
294
Jamie Madill48ef11b2016-04-27 15:21:52 -0400295const std::string &FramebufferState::getLabel()
Geoff Lang70d0f492015-12-10 17:45:46 -0500296{
297 return mLabel;
298}
299
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800300const FramebufferAttachment *FramebufferState::getAttachment(const Context *context,
301 GLenum attachment) const
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400302{
303 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
304 {
305 return getColorAttachment(attachment - GL_COLOR_ATTACHMENT0);
306 }
307
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800308 // WebGL1 allows a developer to query for attachment parameters even when "inconsistant" (i.e.
309 // multiple conflicting attachment points) and requires us to return the framebuffer attachment
310 // associated with WebGL.
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400311 switch (attachment)
312 {
313 case GL_COLOR:
314 case GL_BACK:
315 return getColorAttachment(0);
316 case GL_DEPTH:
317 case GL_DEPTH_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800318 if (context->isWebGL1())
319 {
320 return getWebGLDepthAttachment();
321 }
322 else
323 {
324 return getDepthAttachment();
325 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400326 case GL_STENCIL:
327 case GL_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800328 if (context->isWebGL1())
329 {
330 return getWebGLStencilAttachment();
331 }
332 else
333 {
334 return getStencilAttachment();
335 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400336 case GL_DEPTH_STENCIL:
337 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800338 if (context->isWebGL1())
339 {
340 return getWebGLDepthStencilAttachment();
341 }
342 else
343 {
344 return getDepthStencilAttachment();
345 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400346 default:
347 UNREACHABLE();
348 return nullptr;
349 }
350}
351
Jamie Madill05b35b22017-10-03 09:01:44 -0400352size_t FramebufferState::getReadIndex() const
Jamie Madill7147f012015-03-05 15:41:40 -0500353{
Jamie Madill231c7f52017-04-26 13:45:37 -0400354 ASSERT(mReadBufferState == GL_BACK ||
355 (mReadBufferState >= GL_COLOR_ATTACHMENT0 && mReadBufferState <= GL_COLOR_ATTACHMENT15));
356 size_t readIndex = (mReadBufferState == GL_BACK
357 ? 0
358 : static_cast<size_t>(mReadBufferState - GL_COLOR_ATTACHMENT0));
Jamie Madill7147f012015-03-05 15:41:40 -0500359 ASSERT(readIndex < mColorAttachments.size());
Jamie Madill05b35b22017-10-03 09:01:44 -0400360 return readIndex;
361}
362
363const FramebufferAttachment *FramebufferState::getReadAttachment() const
364{
365 if (mReadBufferState == GL_NONE)
366 {
367 return nullptr;
368 }
369 size_t readIndex = getReadIndex();
Jamie Madill2d06b732015-04-20 12:53:28 -0400370 return mColorAttachments[readIndex].isAttached() ? &mColorAttachments[readIndex] : nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500371}
372
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500373const FramebufferAttachment *FramebufferState::getFirstNonNullAttachment() const
374{
375 auto *colorAttachment = getFirstColorAttachment();
376 if (colorAttachment)
377 {
378 return colorAttachment;
379 }
380 return getDepthOrStencilAttachment();
381}
382
Jamie Madill48ef11b2016-04-27 15:21:52 -0400383const FramebufferAttachment *FramebufferState::getFirstColorAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500384{
Jamie Madill2d06b732015-04-20 12:53:28 -0400385 for (const FramebufferAttachment &colorAttachment : mColorAttachments)
Jamie Madill7147f012015-03-05 15:41:40 -0500386 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400387 if (colorAttachment.isAttached())
Jamie Madill7147f012015-03-05 15:41:40 -0500388 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400389 return &colorAttachment;
Jamie Madill7147f012015-03-05 15:41:40 -0500390 }
391 }
392
393 return nullptr;
394}
395
Jamie Madill48ef11b2016-04-27 15:21:52 -0400396const FramebufferAttachment *FramebufferState::getDepthOrStencilAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500397{
Jamie Madill2d06b732015-04-20 12:53:28 -0400398 if (mDepthAttachment.isAttached())
399 {
400 return &mDepthAttachment;
401 }
402 if (mStencilAttachment.isAttached())
403 {
404 return &mStencilAttachment;
405 }
406 return nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500407}
408
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500409const FramebufferAttachment *FramebufferState::getStencilOrDepthStencilAttachment() const
410{
411 if (mStencilAttachment.isAttached())
412 {
413 return &mStencilAttachment;
414 }
415 return getDepthStencilAttachment();
416}
417
Jamie Madill48ef11b2016-04-27 15:21:52 -0400418const FramebufferAttachment *FramebufferState::getColorAttachment(size_t colorAttachment) const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400419{
420 ASSERT(colorAttachment < mColorAttachments.size());
Jamie Madill231c7f52017-04-26 13:45:37 -0400421 return mColorAttachments[colorAttachment].isAttached() ? &mColorAttachments[colorAttachment]
422 : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400423}
424
Jamie Madill48ef11b2016-04-27 15:21:52 -0400425const FramebufferAttachment *FramebufferState::getDepthAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400426{
Jamie Madill2d06b732015-04-20 12:53:28 -0400427 return mDepthAttachment.isAttached() ? &mDepthAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400428}
429
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800430const FramebufferAttachment *FramebufferState::getWebGLDepthAttachment() const
431{
432 return mWebGLDepthAttachment.isAttached() ? &mWebGLDepthAttachment : nullptr;
433}
434
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800435const FramebufferAttachment *FramebufferState::getWebGLDepthStencilAttachment() const
436{
437 return mWebGLDepthStencilAttachment.isAttached() ? &mWebGLDepthStencilAttachment : nullptr;
438}
439
Jamie Madill48ef11b2016-04-27 15:21:52 -0400440const FramebufferAttachment *FramebufferState::getStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400441{
Jamie Madill2d06b732015-04-20 12:53:28 -0400442 return mStencilAttachment.isAttached() ? &mStencilAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400443}
444
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800445const FramebufferAttachment *FramebufferState::getWebGLStencilAttachment() const
446{
447 return mWebGLStencilAttachment.isAttached() ? &mWebGLStencilAttachment : nullptr;
448}
449
Jamie Madill48ef11b2016-04-27 15:21:52 -0400450const FramebufferAttachment *FramebufferState::getDepthStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400451{
452 // A valid depth-stencil attachment has the same resource bound to both the
453 // depth and stencil attachment points.
Jamie Madill2d06b732015-04-20 12:53:28 -0400454 if (mDepthAttachment.isAttached() && mStencilAttachment.isAttached() &&
Jamie Madill44f26482016-11-18 12:49:15 -0500455 mDepthAttachment == mStencilAttachment)
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400456 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400457 return &mDepthAttachment;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400458 }
459
460 return nullptr;
461}
462
Jamie Madill48ef11b2016-04-27 15:21:52 -0400463bool FramebufferState::attachmentsHaveSameDimensions() const
Jamie Madillcc86d642015-11-24 13:00:07 -0500464{
465 Optional<Extents> attachmentSize;
466
Jamie Madill231c7f52017-04-26 13:45:37 -0400467 auto hasMismatchedSize = [&attachmentSize](const FramebufferAttachment &attachment) {
Jamie Madillcc86d642015-11-24 13:00:07 -0500468 if (!attachment.isAttached())
469 {
470 return false;
471 }
472
473 if (!attachmentSize.valid())
474 {
475 attachmentSize = attachment.getSize();
476 return false;
477 }
478
Jeff Gilbert8f8edd62017-10-31 14:26:30 -0700479 const auto &prevSize = attachmentSize.value();
480 const auto &curSize = attachment.getSize();
481 return (curSize.width != prevSize.width || curSize.height != prevSize.height);
Jamie Madillcc86d642015-11-24 13:00:07 -0500482 };
483
484 for (const auto &attachment : mColorAttachments)
485 {
486 if (hasMismatchedSize(attachment))
487 {
488 return false;
489 }
490 }
491
492 if (hasMismatchedSize(mDepthAttachment))
493 {
494 return false;
495 }
496
497 return !hasMismatchedSize(mStencilAttachment);
498}
499
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400500const gl::FramebufferAttachment *FramebufferState::getDrawBuffer(size_t drawBufferIdx) const
501{
502 ASSERT(drawBufferIdx < mDrawBufferStates.size());
503 if (mDrawBufferStates[drawBufferIdx] != GL_NONE)
504 {
505 // ES3 spec: "If the GL is bound to a draw framebuffer object, the ith buffer listed in bufs
506 // must be COLOR_ATTACHMENTi or NONE"
507 ASSERT(mDrawBufferStates[drawBufferIdx] == GL_COLOR_ATTACHMENT0 + drawBufferIdx ||
508 (drawBufferIdx == 0 && mDrawBufferStates[drawBufferIdx] == GL_BACK));
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800509
510 if (mDrawBufferStates[drawBufferIdx] == GL_BACK)
511 {
512 return getColorAttachment(0);
513 }
514 else
515 {
516 return getColorAttachment(mDrawBufferStates[drawBufferIdx] - GL_COLOR_ATTACHMENT0);
517 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400518 }
519 else
520 {
521 return nullptr;
522 }
523}
524
525size_t FramebufferState::getDrawBufferCount() const
526{
527 return mDrawBufferStates.size();
528}
529
Geoff Langb21e20d2016-07-19 15:35:41 -0400530bool FramebufferState::colorAttachmentsAreUniqueImages() const
531{
532 for (size_t firstAttachmentIdx = 0; firstAttachmentIdx < mColorAttachments.size();
533 firstAttachmentIdx++)
534 {
535 const gl::FramebufferAttachment &firstAttachment = mColorAttachments[firstAttachmentIdx];
536 if (!firstAttachment.isAttached())
537 {
538 continue;
539 }
540
541 for (size_t secondAttachmentIdx = firstAttachmentIdx + 1;
542 secondAttachmentIdx < mColorAttachments.size(); secondAttachmentIdx++)
543 {
544 const gl::FramebufferAttachment &secondAttachment =
545 mColorAttachments[secondAttachmentIdx];
546 if (!secondAttachment.isAttached())
547 {
548 continue;
549 }
550
551 if (firstAttachment == secondAttachment)
552 {
553 return false;
554 }
555 }
556 }
557
558 return true;
559}
560
Jamie Madill9c335862017-07-18 11:51:38 -0400561bool FramebufferState::hasDepth() const
562{
563 return (mDepthAttachment.isAttached() && mDepthAttachment.getDepthSize() > 0);
564}
565
566bool FramebufferState::hasStencil() const
567{
568 return (mStencilAttachment.isAttached() && mStencilAttachment.getStencilSize() > 0);
569}
570
Martin Radev5c00d0d2017-08-07 10:06:59 +0300571GLsizei FramebufferState::getNumViews() const
572{
573 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
574 if (attachment == nullptr)
575 {
576 return FramebufferAttachment::kDefaultNumViews;
577 }
578 return attachment->getNumViews();
579}
580
581const std::vector<Offset> *FramebufferState::getViewportOffsets() const
582{
583 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
584 if (attachment == nullptr)
585 {
586 return nullptr;
587 }
588 return &attachment->getMultiviewViewportOffsets();
589}
590
591GLenum FramebufferState::getMultiviewLayout() const
592{
593 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
594 if (attachment == nullptr)
595 {
596 return GL_NONE;
597 }
598 return attachment->getMultiviewLayout();
599}
600
Martin Radev4e619f52017-08-09 11:50:06 +0300601int FramebufferState::getBaseViewIndex() const
602{
603 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
604 if (attachment == nullptr)
605 {
606 return GL_NONE;
607 }
608 return attachment->getBaseViewIndex();
609}
610
Jamie Madill05b35b22017-10-03 09:01:44 -0400611Box FramebufferState::getDimensions() const
612{
613 ASSERT(attachmentsHaveSameDimensions());
614 ASSERT(getFirstNonNullAttachment() != nullptr);
615 Extents extents = getFirstNonNullAttachment()->getSize();
616 return Box(0, 0, 0, extents.width, extents.height, extents.depth);
617}
618
Jamie Madill7aea7e02016-05-10 10:39:45 -0400619Framebuffer::Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id)
Jamie Madill362876b2016-06-16 14:46:59 -0400620 : mState(caps),
621 mImpl(factory->createFramebuffer(mState)),
622 mId(id),
623 mCachedStatus(),
624 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
625 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000626{
Corentin Wallez37c39792015-08-20 14:19:46 -0400627 ASSERT(mId != 0);
628 ASSERT(mImpl != nullptr);
Jamie Madill362876b2016-06-16 14:46:59 -0400629 ASSERT(mState.mColorAttachments.size() == static_cast<size_t>(caps.maxColorAttachments));
630
Jamie Madill1e5499d2017-04-05 11:22:16 -0400631 for (uint32_t colorIndex = 0;
632 colorIndex < static_cast<uint32_t>(mState.mColorAttachments.size()); ++colorIndex)
Jamie Madill362876b2016-06-16 14:46:59 -0400633 {
Jamie Madill1e5499d2017-04-05 11:22:16 -0400634 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
Jamie Madill362876b2016-06-16 14:46:59 -0400635 }
Corentin Wallez37c39792015-08-20 14:19:46 -0400636}
637
Jamie Madill4928b7c2017-06-20 12:57:39 -0400638Framebuffer::Framebuffer(const egl::Display *display, egl::Surface *surface)
Jamie Madill362876b2016-06-16 14:46:59 -0400639 : mState(),
Jamie Madill6f60d052017-02-22 15:20:11 -0500640 mImpl(surface->getImplementation()->createDefaultFramebuffer(mState)),
Jamie Madill362876b2016-06-16 14:46:59 -0400641 mId(0),
642 mCachedStatus(GL_FRAMEBUFFER_COMPLETE),
643 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
644 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
Corentin Wallez37c39792015-08-20 14:19:46 -0400645{
Geoff Langda88add2014-12-01 10:22:01 -0500646 ASSERT(mImpl != nullptr);
Jamie Madill1e5499d2017-04-05 11:22:16 -0400647 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
Jamie Madill6f60d052017-02-22 15:20:11 -0500648
Jamie Madill4928b7c2017-06-20 12:57:39 -0400649 const Context *proxyContext = display->getProxyContext();
650
651 setAttachmentImpl(proxyContext, GL_FRAMEBUFFER_DEFAULT, GL_BACK, gl::ImageIndex::MakeInvalid(),
Martin Radev5dae57b2017-07-14 16:15:55 +0300652 surface, FramebufferAttachment::kDefaultNumViews,
653 FramebufferAttachment::kDefaultBaseViewIndex,
654 FramebufferAttachment::kDefaultMultiviewLayout,
655 FramebufferAttachment::kDefaultViewportOffsets);
Jamie Madill6f60d052017-02-22 15:20:11 -0500656
657 if (surface->getConfig()->depthSize > 0)
658 {
Martin Radev5dae57b2017-07-14 16:15:55 +0300659 setAttachmentImpl(
660 proxyContext, GL_FRAMEBUFFER_DEFAULT, GL_DEPTH, gl::ImageIndex::MakeInvalid(), surface,
661 FramebufferAttachment::kDefaultNumViews, FramebufferAttachment::kDefaultBaseViewIndex,
662 FramebufferAttachment::kDefaultMultiviewLayout,
663 FramebufferAttachment::kDefaultViewportOffsets);
Jamie Madill6f60d052017-02-22 15:20:11 -0500664 }
665
666 if (surface->getConfig()->stencilSize > 0)
667 {
Jamie Madill4928b7c2017-06-20 12:57:39 -0400668 setAttachmentImpl(proxyContext, GL_FRAMEBUFFER_DEFAULT, GL_STENCIL,
Martin Radev5dae57b2017-07-14 16:15:55 +0300669 gl::ImageIndex::MakeInvalid(), surface,
670 FramebufferAttachment::kDefaultNumViews,
671 FramebufferAttachment::kDefaultBaseViewIndex,
672 FramebufferAttachment::kDefaultMultiviewLayout,
673 FramebufferAttachment::kDefaultViewportOffsets);
Jamie Madill6f60d052017-02-22 15:20:11 -0500674 }
Brandon Jones76746f92017-11-22 11:44:41 -0800675 mState.mDrawBufferTypeMask.setIndex(getDrawbufferWriteType(0), 0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000676}
677
Corentin Wallezccab69d2017-01-27 16:57:15 -0500678Framebuffer::Framebuffer(rx::GLImplFactory *factory)
679 : mState(),
680 mImpl(factory->createFramebuffer(mState)),
681 mId(0),
682 mCachedStatus(GL_FRAMEBUFFER_UNDEFINED_OES),
683 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
684 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
685{
Jamie Madill1e5499d2017-04-05 11:22:16 -0400686 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
Brandon Jones76746f92017-11-22 11:44:41 -0800687 mState.mDrawBufferTypeMask.setIndex(getDrawbufferWriteType(0), 0);
Corentin Wallezccab69d2017-01-27 16:57:15 -0500688}
689
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000690Framebuffer::~Framebuffer()
691{
Geoff Langda88add2014-12-01 10:22:01 -0500692 SafeDelete(mImpl);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000693}
694
Jamie Madill4928b7c2017-06-20 12:57:39 -0400695void Framebuffer::onDestroy(const Context *context)
Jamie Madill6c1f6712017-02-14 19:08:04 -0500696{
Jamie Madill4928b7c2017-06-20 12:57:39 -0400697 for (auto &attachment : mState.mColorAttachments)
698 {
699 attachment.detach(context);
700 }
701 mState.mDepthAttachment.detach(context);
702 mState.mStencilAttachment.detach(context);
703 mState.mWebGLDepthAttachment.detach(context);
704 mState.mWebGLStencilAttachment.detach(context);
705 mState.mWebGLDepthStencilAttachment.detach(context);
706
Jamie Madillc564c072017-06-01 12:45:42 -0400707 mImpl->destroy(context);
Jamie Madill6c1f6712017-02-14 19:08:04 -0500708}
709
710void Framebuffer::destroyDefault(const egl::Display *display)
711{
Jamie Madillc564c072017-06-01 12:45:42 -0400712 mImpl->destroyDefault(display);
Jamie Madill6c1f6712017-02-14 19:08:04 -0500713}
714
Geoff Lang70d0f492015-12-10 17:45:46 -0500715void Framebuffer::setLabel(const std::string &label)
716{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400717 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -0500718}
719
720const std::string &Framebuffer::getLabel() const
721{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400722 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -0500723}
724
Jamie Madill8693bdb2017-09-02 15:32:14 -0400725bool Framebuffer::detachTexture(const Context *context, GLuint textureId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000726{
Jamie Madill8693bdb2017-09-02 15:32:14 -0400727 return detachResourceById(context, GL_TEXTURE, textureId);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000728}
729
Jamie Madill8693bdb2017-09-02 15:32:14 -0400730bool Framebuffer::detachRenderbuffer(const Context *context, GLuint renderbufferId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000731{
Jamie Madill8693bdb2017-09-02 15:32:14 -0400732 return detachResourceById(context, GL_RENDERBUFFER, renderbufferId);
Jamie Madilld1405e52015-03-05 15:41:39 -0500733}
Jamie Madille261b442014-06-25 12:42:21 -0400734
Jamie Madill8693bdb2017-09-02 15:32:14 -0400735bool Framebuffer::detachResourceById(const Context *context, GLenum resourceType, GLuint resourceId)
Jamie Madilld1405e52015-03-05 15:41:39 -0500736{
Jamie Madill8693bdb2017-09-02 15:32:14 -0400737 bool found = false;
738
Jamie Madill362876b2016-06-16 14:46:59 -0400739 for (size_t colorIndex = 0; colorIndex < mState.mColorAttachments.size(); ++colorIndex)
Jamie Madilld1405e52015-03-05 15:41:39 -0500740 {
Jamie Madill8693bdb2017-09-02 15:32:14 -0400741 if (detachMatchingAttachment(context, &mState.mColorAttachments[colorIndex], resourceType,
742 resourceId, DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex))
743 {
744 found = true;
745 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000746 }
747
Jamie Madilla02315b2017-02-23 14:14:47 -0500748 if (context->isWebGL1())
749 {
750 const std::array<FramebufferAttachment *, 3> attachments = {
751 {&mState.mWebGLDepthStencilAttachment, &mState.mWebGLDepthAttachment,
752 &mState.mWebGLStencilAttachment}};
753 for (FramebufferAttachment *attachment : attachments)
754 {
755 if (attachment->isAttached() && attachment->type() == resourceType &&
756 attachment->id() == resourceId)
757 {
758 resetAttachment(context, attachment->getBinding());
Jamie Madill8693bdb2017-09-02 15:32:14 -0400759 found = true;
Jamie Madilla02315b2017-02-23 14:14:47 -0500760 }
761 }
762 }
763 else
764 {
Jamie Madill8693bdb2017-09-02 15:32:14 -0400765 if (detachMatchingAttachment(context, &mState.mDepthAttachment, resourceType, resourceId,
766 DIRTY_BIT_DEPTH_ATTACHMENT))
767 {
768 found = true;
769 }
770 if (detachMatchingAttachment(context, &mState.mStencilAttachment, resourceType, resourceId,
771 DIRTY_BIT_STENCIL_ATTACHMENT))
772 {
773 found = true;
774 }
Jamie Madilla02315b2017-02-23 14:14:47 -0500775 }
Jamie Madill8693bdb2017-09-02 15:32:14 -0400776
777 return found;
Jamie Madill362876b2016-06-16 14:46:59 -0400778}
779
Jamie Madill8693bdb2017-09-02 15:32:14 -0400780bool Framebuffer::detachMatchingAttachment(const Context *context,
Jamie Madill4928b7c2017-06-20 12:57:39 -0400781 FramebufferAttachment *attachment,
Jamie Madill362876b2016-06-16 14:46:59 -0400782 GLenum matchType,
783 GLuint matchId,
784 size_t dirtyBit)
785{
786 if (attachment->isAttached() && attachment->type() == matchType && attachment->id() == matchId)
787 {
Jamie Madill4928b7c2017-06-20 12:57:39 -0400788 attachment->detach(context);
Jamie Madill362876b2016-06-16 14:46:59 -0400789 mDirtyBits.set(dirtyBit);
Jamie Madill05b35b22017-10-03 09:01:44 -0400790 mState.mResourceNeedsInit.set(dirtyBit, false);
Jamie Madill8693bdb2017-09-02 15:32:14 -0400791 return true;
Jamie Madill362876b2016-06-16 14:46:59 -0400792 }
Jamie Madill8693bdb2017-09-02 15:32:14 -0400793
794 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000795}
796
Corentin Wallez37c39792015-08-20 14:19:46 -0400797const FramebufferAttachment *Framebuffer::getColorbuffer(size_t colorAttachment) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000798{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400799 return mState.getColorAttachment(colorAttachment);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000800}
801
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400802const FramebufferAttachment *Framebuffer::getDepthbuffer() const
Geoff Lang646559f2013-08-15 11:08:15 -0400803{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400804 return mState.getDepthAttachment();
Geoff Lang646559f2013-08-15 11:08:15 -0400805}
806
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400807const FramebufferAttachment *Framebuffer::getStencilbuffer() const
808{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400809 return mState.getStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400810}
811
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400812const FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
813{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400814 return mState.getDepthStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400815}
816
817const FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000818{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400819 return mState.getDepthOrStencilAttachment();
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000820}
821
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500822const FramebufferAttachment *Framebuffer::getStencilOrDepthStencilAttachment() const
823{
824 return mState.getStencilOrDepthStencilAttachment();
825}
826
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400827const FramebufferAttachment *Framebuffer::getReadColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000828{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400829 return mState.getReadAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000830}
831
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000832GLenum Framebuffer::getReadColorbufferType() const
833{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400834 const FramebufferAttachment *readAttachment = mState.getReadAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400835 return (readAttachment != nullptr ? readAttachment->type() : GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000836}
837
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400838const FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000839{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400840 return mState.getFirstColorAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000841}
842
Jamie Madill6dd06ea2017-07-19 13:47:55 -0400843const FramebufferAttachment *Framebuffer::getFirstNonNullAttachment() const
844{
845 return mState.getFirstNonNullAttachment();
846}
847
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800848const FramebufferAttachment *Framebuffer::getAttachment(const Context *context,
849 GLenum attachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000850{
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800851 return mState.getAttachment(context, attachment);
Geoff Lang55ba29c2013-07-11 16:57:53 -0400852}
853
Geoff Langa15472a2015-08-11 11:48:03 -0400854size_t Framebuffer::getDrawbufferStateCount() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000855{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400856 return mState.mDrawBufferStates.size();
Geoff Langa15472a2015-08-11 11:48:03 -0400857}
858
859GLenum Framebuffer::getDrawBufferState(size_t drawBuffer) const
860{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400861 ASSERT(drawBuffer < mState.mDrawBufferStates.size());
862 return mState.mDrawBufferStates[drawBuffer];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000863}
864
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500865const std::vector<GLenum> &Framebuffer::getDrawBufferStates() const
866{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400867 return mState.getDrawBufferStates();
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500868}
869
Geoff Lang164d54e2014-12-01 10:55:33 -0500870void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000871{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400872 auto &drawStates = mState.mDrawBufferStates;
Jamie Madilld1405e52015-03-05 15:41:39 -0500873
874 ASSERT(count <= drawStates.size());
875 std::copy(buffers, buffers + count, drawStates.begin());
876 std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500877 mDirtyBits.set(DIRTY_BIT_DRAW_BUFFERS);
Jamie Madilla4595b82017-01-11 17:36:34 -0500878
879 mState.mEnabledDrawBuffers.reset();
Brandon Jones76746f92017-11-22 11:44:41 -0800880 mState.mDrawBufferTypeMask.reset();
881
Jamie Madilla4595b82017-01-11 17:36:34 -0500882 for (size_t index = 0; index < count; ++index)
883 {
Brandon Jones76746f92017-11-22 11:44:41 -0800884 mState.mDrawBufferTypeMask.setIndex(getDrawbufferWriteType(index), index);
885
Jamie Madilla4595b82017-01-11 17:36:34 -0500886 if (drawStates[index] != GL_NONE && mState.mColorAttachments[index].isAttached())
887 {
888 mState.mEnabledDrawBuffers.set(index);
889 }
890 }
Geoff Lang9dd95802014-12-01 11:12:59 -0500891}
892
Geoff Langa15472a2015-08-11 11:48:03 -0400893const FramebufferAttachment *Framebuffer::getDrawBuffer(size_t drawBuffer) const
894{
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400895 return mState.getDrawBuffer(drawBuffer);
Geoff Langa15472a2015-08-11 11:48:03 -0400896}
897
Geoff Lange0cff192017-05-30 13:04:56 -0400898GLenum Framebuffer::getDrawbufferWriteType(size_t drawBuffer) const
899{
900 const FramebufferAttachment *attachment = mState.getDrawBuffer(drawBuffer);
901 if (attachment == nullptr)
902 {
903 return GL_NONE;
904 }
905
906 GLenum componentType = attachment->getFormat().info->componentType;
907 switch (componentType)
908 {
909 case GL_INT:
910 case GL_UNSIGNED_INT:
911 return componentType;
912
913 default:
914 return GL_FLOAT;
915 }
916}
917
Brandon Jonesc405ae72017-12-06 14:15:03 -0800918ComponentTypeMask Framebuffer::getDrawBufferTypeMask() const
Brandon Jones76746f92017-11-22 11:44:41 -0800919{
920 return mState.mDrawBufferTypeMask;
921}
922
923DrawBufferMask Framebuffer::getDrawBufferMask() const
924{
925 return mState.mEnabledDrawBuffers;
926}
927
Geoff Langa15472a2015-08-11 11:48:03 -0400928bool Framebuffer::hasEnabledDrawBuffer() const
929{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400930 for (size_t drawbufferIdx = 0; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
Geoff Langa15472a2015-08-11 11:48:03 -0400931 {
932 if (getDrawBuffer(drawbufferIdx) != nullptr)
933 {
934 return true;
935 }
936 }
937
938 return false;
939}
940
Geoff Lang9dd95802014-12-01 11:12:59 -0500941GLenum Framebuffer::getReadBufferState() const
942{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400943 return mState.mReadBufferState;
Geoff Lang9dd95802014-12-01 11:12:59 -0500944}
945
946void Framebuffer::setReadBuffer(GLenum buffer)
947{
Jamie Madillb885e572015-02-03 16:16:04 -0500948 ASSERT(buffer == GL_BACK || buffer == GL_NONE ||
949 (buffer >= GL_COLOR_ATTACHMENT0 &&
Jamie Madill48ef11b2016-04-27 15:21:52 -0400950 (buffer - GL_COLOR_ATTACHMENT0) < mState.mColorAttachments.size()));
951 mState.mReadBufferState = buffer;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500952 mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000953}
954
Corentin Wallez37c39792015-08-20 14:19:46 -0400955size_t Framebuffer::getNumColorBuffers() const
956{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400957 return mState.mColorAttachments.size();
Corentin Wallez37c39792015-08-20 14:19:46 -0400958}
959
Jamie Madill0df8fe42015-11-24 16:10:24 -0500960bool Framebuffer::hasDepth() const
961{
Jamie Madill9c335862017-07-18 11:51:38 -0400962 return mState.hasDepth();
Jamie Madill0df8fe42015-11-24 16:10:24 -0500963}
964
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000965bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000966{
Jamie Madill9c335862017-07-18 11:51:38 -0400967 return mState.hasStencil();
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000968}
969
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000970bool Framebuffer::usingExtendedDrawBuffers() const
971{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400972 for (size_t drawbufferIdx = 1; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000973 {
Geoff Langa15472a2015-08-11 11:48:03 -0400974 if (getDrawBuffer(drawbufferIdx) != nullptr)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000975 {
976 return true;
977 }
978 }
979
980 return false;
981}
982
Geoff Lang9aded172017-04-05 11:07:56 -0400983void Framebuffer::invalidateCompletenessCache()
984{
985 if (mId != 0)
986 {
987 mCachedStatus.reset();
988 }
989}
990
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400991GLenum Framebuffer::checkStatus(const Context *context)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000992{
Corentin Wallezccab69d2017-01-27 16:57:15 -0500993 // The default framebuffer is always complete except when it is surfaceless in which
994 // case it is always unsupported. We return early because the default framebuffer may
995 // not be subject to the same rules as application FBOs. ie, it could have 0x0 size.
Geoff Lang528ce3c2014-12-01 10:44:07 -0500996 if (mId == 0)
997 {
Corentin Wallezccab69d2017-01-27 16:57:15 -0500998 ASSERT(mCachedStatus.valid());
999 ASSERT(mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE ||
1000 mCachedStatus.value() == GL_FRAMEBUFFER_UNDEFINED_OES);
1001 return mCachedStatus.value();
Geoff Lang528ce3c2014-12-01 10:44:07 -05001002 }
1003
Jamie Madill362876b2016-06-16 14:46:59 -04001004 if (hasAnyDirtyBit() || !mCachedStatus.valid())
1005 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001006 mCachedStatus = checkStatusImpl(context);
Jamie Madill362876b2016-06-16 14:46:59 -04001007 }
1008
1009 return mCachedStatus.value();
1010}
1011
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001012GLenum Framebuffer::checkStatusImpl(const Context *context)
Jamie Madill362876b2016-06-16 14:46:59 -04001013{
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001014 const ContextState &state = context->getContextState();
1015
Jamie Madill362876b2016-06-16 14:46:59 -04001016 ASSERT(mId != 0);
1017
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001018 bool hasAttachments = false;
1019 Optional<unsigned int> colorbufferSize;
1020 Optional<int> samples;
Geoff Lang92019432017-11-20 13:09:34 -05001021 Optional<bool> fixedSampleLocations;
JiangYizhou461d9a32017-01-04 16:37:26 +08001022 bool hasRenderbuffer = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001023
Martin Radev9bc9a322017-07-21 14:28:17 +03001024 const FramebufferAttachment *firstAttachment = getFirstNonNullAttachment();
1025
Jamie Madill48ef11b2016-04-27 15:21:52 -04001026 for (const FramebufferAttachment &colorAttachment : mState.mColorAttachments)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001027 {
Jamie Madill2d06b732015-04-20 12:53:28 -04001028 if (colorAttachment.isAttached())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001029 {
Geoff Lang9f10b772017-05-16 15:51:03 -04001030 if (!CheckAttachmentCompleteness(context, colorAttachment))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001031 {
1032 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1033 }
daniel@transgaming.com01868132010-08-24 19:21:17 +00001034
Geoff Lang677bb6f2017-04-05 12:40:40 -04001035 const InternalFormat &format = *colorAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -04001036 if (format.depthBits > 0 || format.stencilBits > 0)
1037 {
1038 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1039 }
1040
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001041 if (!CheckAttachmentSampleCompleteness(context, colorAttachment, true, &samples,
1042 &fixedSampleLocations))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001043 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001044 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001045 }
1046
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001047 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
1048 // in GLES 3.0, there is no such restriction
1049 if (state.getClientMajorVersion() < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001050 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001051 if (colorbufferSize.valid())
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001052 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001053 if (format.pixelBytes != colorbufferSize.value())
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +00001054 {
1055 return GL_FRAMEBUFFER_UNSUPPORTED;
1056 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001057 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001058 else
1059 {
1060 colorbufferSize = format.pixelBytes;
1061 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001062 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001063
Martin Radev9bc9a322017-07-21 14:28:17 +03001064 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &colorAttachment))
1065 {
1066 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
1067 }
1068
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001069 hasRenderbuffer = hasRenderbuffer || (colorAttachment.type() == GL_RENDERBUFFER);
1070 hasAttachments = true;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001071 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001072 }
1073
Jamie Madill48ef11b2016-04-27 15:21:52 -04001074 const FramebufferAttachment &depthAttachment = mState.mDepthAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -04001075 if (depthAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001076 {
Geoff Lang9f10b772017-05-16 15:51:03 -04001077 if (!CheckAttachmentCompleteness(context, depthAttachment))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001078 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001079 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001080 }
1081
Geoff Lang677bb6f2017-04-05 12:40:40 -04001082 const InternalFormat &format = *depthAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -04001083 if (format.depthBits == 0)
1084 {
1085 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001086 }
1087
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001088 if (!CheckAttachmentSampleCompleteness(context, depthAttachment, false, &samples,
1089 &fixedSampleLocations))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001090 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001091 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001092 }
Sami Väisänena797e062016-05-12 15:23:40 +03001093
Martin Radev9bc9a322017-07-21 14:28:17 +03001094 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &depthAttachment))
1095 {
1096 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
1097 }
1098
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001099 hasRenderbuffer = hasRenderbuffer || (depthAttachment.type() == GL_RENDERBUFFER);
1100 hasAttachments = true;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001101 }
1102
Jamie Madill48ef11b2016-04-27 15:21:52 -04001103 const FramebufferAttachment &stencilAttachment = mState.mStencilAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -04001104 if (stencilAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001105 {
Geoff Lang9f10b772017-05-16 15:51:03 -04001106 if (!CheckAttachmentCompleteness(context, stencilAttachment))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001107 {
1108 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1109 }
1110
Geoff Lang677bb6f2017-04-05 12:40:40 -04001111 const InternalFormat &format = *stencilAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -04001112 if (format.stencilBits == 0)
1113 {
1114 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001115 }
1116
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001117 if (!CheckAttachmentSampleCompleteness(context, stencilAttachment, false, &samples,
1118 &fixedSampleLocations))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001119 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001120 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001121 }
Corentin Wallez086d59a2016-04-29 09:06:49 -04001122
Martin Radev9bc9a322017-07-21 14:28:17 +03001123 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &stencilAttachment))
1124 {
1125 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
1126 }
1127
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001128 hasRenderbuffer = hasRenderbuffer || (stencilAttachment.type() == GL_RENDERBUFFER);
1129 hasAttachments = true;
1130 }
1131
1132 // Starting from ES 3.0 stencil and depth, if present, should be the same image
1133 if (state.getClientMajorVersion() >= 3 && depthAttachment.isAttached() &&
1134 stencilAttachment.isAttached() && stencilAttachment != depthAttachment)
1135 {
1136 return GL_FRAMEBUFFER_UNSUPPORTED;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001137 }
1138
Jamie Madilla02315b2017-02-23 14:14:47 -05001139 // Special additional validation for WebGL 1 DEPTH/STENCIL/DEPTH_STENCIL.
1140 if (state.isWebGL1())
1141 {
1142 if (!mState.mWebGLDepthStencilConsistent)
1143 {
1144 return GL_FRAMEBUFFER_UNSUPPORTED;
1145 }
1146
1147 if (mState.mWebGLDepthStencilAttachment.isAttached())
1148 {
1149 if (mState.mWebGLDepthStencilAttachment.getDepthSize() == 0 ||
1150 mState.mWebGLDepthStencilAttachment.getStencilSize() == 0)
1151 {
1152 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1153 }
Martin Radev9bc9a322017-07-21 14:28:17 +03001154
1155 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment,
1156 &mState.mWebGLDepthStencilAttachment))
1157 {
1158 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
1159 }
Jamie Madilla02315b2017-02-23 14:14:47 -05001160 }
1161 else if (mState.mStencilAttachment.isAttached() &&
1162 mState.mStencilAttachment.getDepthSize() > 0)
1163 {
1164 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1165 }
1166 else if (mState.mDepthAttachment.isAttached() &&
1167 mState.mDepthAttachment.getStencilSize() > 0)
1168 {
1169 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1170 }
1171 }
1172
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001173 // ES3.1(section 9.4) requires that if no image is attached to the framebuffer, and either the
1174 // value of the framebuffer's FRAMEBUFFER_DEFAULT_WIDTH or FRAMEBUFFER_DEFAULT_HEIGHT parameters
1175 // is zero, the framebuffer is considered incomplete.
JiangYizhou461d9a32017-01-04 16:37:26 +08001176 GLint defaultWidth = mState.getDefaultWidth();
1177 GLint defaultHeight = mState.getDefaultHeight();
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001178 if (!hasAttachments && (defaultWidth == 0 || defaultHeight == 0))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001179 {
1180 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001181 }
1182
Geoff Langa0e0aeb2017-04-12 15:06:29 -04001183 // In ES 2.0 and WebGL, all color attachments must have the same width and height.
Jamie Madillcc86d642015-11-24 13:00:07 -05001184 // In ES 3.0, there is no such restriction.
Geoff Langa0e0aeb2017-04-12 15:06:29 -04001185 if ((state.getClientMajorVersion() < 3 || state.getExtensions().webglCompatibility) &&
1186 !mState.attachmentsHaveSameDimensions())
Jamie Madillcc86d642015-11-24 13:00:07 -05001187 {
1188 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
1189 }
1190
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001191 // ES3.1(section 9.4) requires that if the attached images are a mix of renderbuffers and
1192 // textures, the value of TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all attached textures.
JiangYizhou461d9a32017-01-04 16:37:26 +08001193 if (fixedSampleLocations.valid() && hasRenderbuffer && !fixedSampleLocations.value())
1194 {
1195 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1196 }
1197
Kenneth Russellce8602a2017-10-03 18:23:08 -07001198 // The WebGL conformance tests implicitly define that all framebuffer
1199 // attachments must be unique. For example, the same level of a texture can
1200 // not be attached to two different color attachments.
1201 if (state.getExtensions().webglCompatibility)
1202 {
1203 if (!mState.colorAttachmentsAreUniqueImages())
1204 {
1205 return GL_FRAMEBUFFER_UNSUPPORTED;
1206 }
1207 }
1208
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001209 syncState(context);
Kenneth Russellce8602a2017-10-03 18:23:08 -07001210 if (!mImpl->checkStatus(context))
Jamie Madillcc86d642015-11-24 13:00:07 -05001211 {
1212 return GL_FRAMEBUFFER_UNSUPPORTED;
1213 }
1214
1215 return GL_FRAMEBUFFER_COMPLETE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001216}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001217
Jamie Madill4928b7c2017-06-20 12:57:39 -04001218Error Framebuffer::discard(const Context *context, size_t count, const GLenum *attachments)
Austin Kinross08332632015-05-05 13:35:47 -07001219{
Jamie Madill05b35b22017-10-03 09:01:44 -04001220 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1221 // can be no-ops, so we should probably do that to ensure consistency.
1222 // TODO(jmadill): WebGL behaviour, and robust resource init behaviour without WebGL.
1223
Jamie Madill4928b7c2017-06-20 12:57:39 -04001224 return mImpl->discard(context, count, attachments);
Austin Kinross08332632015-05-05 13:35:47 -07001225}
1226
Jamie Madill4928b7c2017-06-20 12:57:39 -04001227Error Framebuffer::invalidate(const Context *context, size_t count, const GLenum *attachments)
Jamie Madill2d96b9e2014-08-29 15:46:47 -04001228{
Jamie Madill05b35b22017-10-03 09:01:44 -04001229 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1230 // can be no-ops, so we should probably do that to ensure consistency.
1231 // TODO(jmadill): WebGL behaviour, and robust resource init behaviour without WebGL.
1232
Jamie Madill4928b7c2017-06-20 12:57:39 -04001233 return mImpl->invalidate(context, count, attachments);
Jamie Madill2d96b9e2014-08-29 15:46:47 -04001234}
1235
Jamie Madill05b35b22017-10-03 09:01:44 -04001236bool Framebuffer::partialClearNeedsInit(const Context *context,
1237 bool color,
1238 bool depth,
1239 bool stencil)
1240{
1241 const auto &glState = context->getGLState();
1242
1243 if (!glState.isRobustResourceInitEnabled())
1244 {
1245 return false;
1246 }
1247
1248 // Scissors can affect clearing.
1249 // TODO(jmadill): Check for complete scissor overlap.
1250 if (glState.isScissorTestEnabled())
1251 {
1252 return true;
1253 }
1254
1255 // If colors masked, we must clear before we clear. Do a simple check.
1256 // TODO(jmadill): Filter out unused color channels from the test.
1257 if (color)
1258 {
1259 const auto &blend = glState.getBlendState();
1260 if (!(blend.colorMaskRed && blend.colorMaskGreen && blend.colorMaskBlue &&
1261 blend.colorMaskAlpha))
1262 {
1263 return true;
1264 }
1265 }
1266
1267 const auto &depthStencil = glState.getDepthStencilState();
1268 ASSERT(depthStencil.stencilBackMask == depthStencil.stencilMask);
1269 if (stencil && depthStencil.stencilMask != depthStencil.stencilWritemask)
1270 {
1271 return true;
1272 }
1273
1274 return false;
1275}
1276
Jamie Madill4928b7c2017-06-20 12:57:39 -04001277Error Framebuffer::invalidateSub(const Context *context,
1278 size_t count,
1279 const GLenum *attachments,
1280 const gl::Rectangle &area)
Jamie Madill400a4412014-08-29 15:46:45 -04001281{
Jamie Madill05b35b22017-10-03 09:01:44 -04001282 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1283 // can be no-ops, so we should probably do that to ensure consistency.
1284 // TODO(jmadill): Make a invalidate no-op in WebGL 2.0.
1285
Jamie Madill4928b7c2017-06-20 12:57:39 -04001286 return mImpl->invalidateSub(context, count, attachments, area);
Jamie Madill400a4412014-08-29 15:46:45 -04001287}
1288
Jamie Madillc564c072017-06-01 12:45:42 -04001289Error Framebuffer::clear(const gl::Context *context, GLbitfield mask)
Geoff Langb04dc822014-12-01 12:02:02 -05001290{
Jamie Madill05b35b22017-10-03 09:01:44 -04001291 const auto &glState = context->getGLState();
1292 if (glState.isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -05001293 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001294 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001295 }
1296
Jamie Madill05b35b22017-10-03 09:01:44 -04001297 const auto &blend = glState.getBlendState();
1298 const auto &depthStencil = glState.getDepthStencilState();
1299
1300 bool color = (mask & GL_COLOR_BUFFER_BIT) != 0 && !IsColorMaskedOut(blend);
1301 bool depth = (mask & GL_DEPTH_BUFFER_BIT) != 0 && !IsDepthMaskedOut(depthStencil);
1302 bool stencil = (mask & GL_STENCIL_BUFFER_BIT) != 0 && !IsStencilMaskedOut(depthStencil);
1303
1304 if (partialClearNeedsInit(context, color, depth, stencil))
1305 {
1306 ANGLE_TRY(ensureDrawAttachmentsInitialized(context));
1307 }
1308
1309 ANGLE_TRY(mImpl->clear(context, mask));
1310
1311 if (glState.isRobustResourceInitEnabled())
1312 {
1313 markDrawAttachmentsInitialized(color, depth, stencil);
1314 }
1315
1316 return NoError();
Geoff Langb04dc822014-12-01 12:02:02 -05001317}
1318
Jamie Madillc564c072017-06-01 12:45:42 -04001319Error Framebuffer::clearBufferfv(const gl::Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001320 GLenum buffer,
1321 GLint drawbuffer,
1322 const GLfloat *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001323{
Jamie Madill05b35b22017-10-03 09:01:44 -04001324 if (context->getGLState().isRasterizerDiscardEnabled() ||
1325 IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001326 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001327 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001328 }
1329
Jamie Madill05b35b22017-10-03 09:01:44 -04001330 if (partialBufferClearNeedsInit(context, buffer))
1331 {
1332 ANGLE_TRY(ensureBufferInitialized(context, buffer, drawbuffer));
1333 }
1334
1335 ANGLE_TRY(mImpl->clearBufferfv(context, buffer, drawbuffer, values));
1336
1337 if (context->isRobustResourceInitEnabled())
1338 {
1339 markBufferInitialized(buffer, drawbuffer);
1340 }
1341 return NoError();
Geoff Langb04dc822014-12-01 12:02:02 -05001342}
1343
Jamie Madillc564c072017-06-01 12:45:42 -04001344Error Framebuffer::clearBufferuiv(const gl::Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001345 GLenum buffer,
1346 GLint drawbuffer,
1347 const GLuint *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001348{
Jamie Madill05b35b22017-10-03 09:01:44 -04001349 if (context->getGLState().isRasterizerDiscardEnabled() ||
1350 IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001351 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001352 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001353 }
1354
Jamie Madill05b35b22017-10-03 09:01:44 -04001355 if (partialBufferClearNeedsInit(context, buffer))
1356 {
1357 ANGLE_TRY(ensureBufferInitialized(context, buffer, drawbuffer));
1358 }
1359
1360 ANGLE_TRY(mImpl->clearBufferuiv(context, buffer, drawbuffer, values));
1361
1362 if (context->isRobustResourceInitEnabled())
1363 {
1364 markBufferInitialized(buffer, drawbuffer);
1365 }
1366 return NoError();
Geoff Langb04dc822014-12-01 12:02:02 -05001367}
1368
Jamie Madillc564c072017-06-01 12:45:42 -04001369Error Framebuffer::clearBufferiv(const gl::Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001370 GLenum buffer,
1371 GLint drawbuffer,
1372 const GLint *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001373{
Jamie Madill05b35b22017-10-03 09:01:44 -04001374 if (context->getGLState().isRasterizerDiscardEnabled() ||
1375 IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001376 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001377 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001378 }
1379
Jamie Madill05b35b22017-10-03 09:01:44 -04001380 if (partialBufferClearNeedsInit(context, buffer))
1381 {
1382 ANGLE_TRY(ensureBufferInitialized(context, buffer, drawbuffer));
1383 }
1384
1385 ANGLE_TRY(mImpl->clearBufferiv(context, buffer, drawbuffer, values));
1386
1387 if (context->isRobustResourceInitEnabled())
1388 {
1389 markBufferInitialized(buffer, drawbuffer);
1390 }
1391 return NoError();
Geoff Langb04dc822014-12-01 12:02:02 -05001392}
1393
Jamie Madillc564c072017-06-01 12:45:42 -04001394Error Framebuffer::clearBufferfi(const gl::Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001395 GLenum buffer,
1396 GLint drawbuffer,
1397 GLfloat depth,
1398 GLint stencil)
Geoff Langb04dc822014-12-01 12:02:02 -05001399{
Jamie Madill05b35b22017-10-03 09:01:44 -04001400 if (context->getGLState().isRasterizerDiscardEnabled() ||
1401 IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001402 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001403 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001404 }
1405
Jamie Madill05b35b22017-10-03 09:01:44 -04001406 if (partialBufferClearNeedsInit(context, buffer))
1407 {
1408 ANGLE_TRY(ensureBufferInitialized(context, buffer, drawbuffer));
1409 }
1410
1411 ANGLE_TRY(mImpl->clearBufferfi(context, buffer, drawbuffer, depth, stencil));
1412
1413 if (context->isRobustResourceInitEnabled())
1414 {
1415 markBufferInitialized(buffer, drawbuffer);
1416 }
1417 return NoError();
Geoff Langb04dc822014-12-01 12:02:02 -05001418}
1419
Jamie Madill4928b7c2017-06-20 12:57:39 -04001420GLenum Framebuffer::getImplementationColorReadFormat(const Context *context) const
Geoff Langbce529e2014-12-01 12:48:41 -05001421{
Jamie Madill4928b7c2017-06-20 12:57:39 -04001422 return mImpl->getImplementationColorReadFormat(context);
Geoff Langbce529e2014-12-01 12:48:41 -05001423}
1424
Jamie Madill4928b7c2017-06-20 12:57:39 -04001425GLenum Framebuffer::getImplementationColorReadType(const Context *context) const
Geoff Langbce529e2014-12-01 12:48:41 -05001426{
Jamie Madill4928b7c2017-06-20 12:57:39 -04001427 return mImpl->getImplementationColorReadType(context);
Geoff Langbce529e2014-12-01 12:48:41 -05001428}
1429
Jamie Madillc564c072017-06-01 12:45:42 -04001430Error Framebuffer::readPixels(const gl::Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001431 const Rectangle &area,
Jamie Madill1b94d432015-08-07 13:23:23 -04001432 GLenum format,
1433 GLenum type,
Jamie Madill05b35b22017-10-03 09:01:44 -04001434 void *pixels)
Geoff Langbce529e2014-12-01 12:48:41 -05001435{
Jamie Madill05b35b22017-10-03 09:01:44 -04001436 ANGLE_TRY(ensureReadAttachmentInitialized(context, GL_COLOR_BUFFER_BIT));
Jamie Madill362876b2016-06-16 14:46:59 -04001437 ANGLE_TRY(mImpl->readPixels(context, area, format, type, pixels));
Geoff Lang520c4ae2015-05-05 13:12:36 -04001438
Corentin Wallez336129f2017-10-17 15:55:40 -04001439 Buffer *unpackBuffer = context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack);
Geoff Lang520c4ae2015-05-05 13:12:36 -04001440 if (unpackBuffer)
1441 {
1442 unpackBuffer->onPixelUnpack();
1443 }
1444
Jamie Madill362876b2016-06-16 14:46:59 -04001445 return NoError();
Geoff Langbce529e2014-12-01 12:48:41 -05001446}
1447
Jamie Madillc564c072017-06-01 12:45:42 -04001448Error Framebuffer::blit(const gl::Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001449 const Rectangle &sourceArea,
1450 const Rectangle &destArea,
Geoff Lang242468f2015-09-24 14:15:41 -04001451 GLbitfield mask,
Jamie Madill8415b5f2016-04-26 13:41:39 -04001452 GLenum filter)
Geoff Lang54bd5a42014-12-01 12:51:04 -05001453{
He Yunchao6be602d2016-12-22 14:33:07 +08001454 GLbitfield blitMask = mask;
1455
1456 // Note that blitting is called against draw framebuffer.
1457 // See the code in gl::Context::blitFramebuffer.
1458 if ((mask & GL_COLOR_BUFFER_BIT) && !hasEnabledDrawBuffer())
1459 {
1460 blitMask &= ~GL_COLOR_BUFFER_BIT;
1461 }
1462
1463 if ((mask & GL_STENCIL_BUFFER_BIT) && mState.getStencilAttachment() == nullptr)
1464 {
1465 blitMask &= ~GL_STENCIL_BUFFER_BIT;
1466 }
1467
1468 if ((mask & GL_DEPTH_BUFFER_BIT) && mState.getDepthAttachment() == nullptr)
1469 {
1470 blitMask &= ~GL_DEPTH_BUFFER_BIT;
1471 }
1472
1473 if (!blitMask)
1474 {
1475 return NoError();
1476 }
1477
Jamie Madill05b35b22017-10-03 09:01:44 -04001478 auto *sourceFBO = context->getGLState().getReadFramebuffer();
1479 ANGLE_TRY(sourceFBO->ensureReadAttachmentInitialized(context, blitMask));
1480
1481 // TODO(jmadill): Only clear if not the full FBO dimensions, and only specified bitmask.
1482 ANGLE_TRY(ensureDrawAttachmentsInitialized(context));
1483
He Yunchao6be602d2016-12-22 14:33:07 +08001484 return mImpl->blit(context, sourceArea, destArea, blitMask, filter);
Geoff Lang54bd5a42014-12-01 12:51:04 -05001485}
1486
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001487int Framebuffer::getSamples(const Context *context)
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001488{
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001489 if (complete(context))
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001490 {
Jamie Madill9c335862017-07-18 11:51:38 -04001491 return getCachedSamples(context);
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001492 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001493
1494 return 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001495}
1496
Jamie Madill9c335862017-07-18 11:51:38 -04001497int Framebuffer::getCachedSamples(const Context *context)
1498{
1499 // For a complete framebuffer, all attachments must have the same sample count.
1500 // In this case return the first nonzero sample size.
1501 const auto *firstNonNullAttachment = mState.getFirstNonNullAttachment();
1502 if (firstNonNullAttachment)
1503 {
1504 ASSERT(firstNonNullAttachment->isAttached());
1505 return firstNonNullAttachment->getSamples();
1506 }
1507
1508 // No attachments found.
1509 return 0;
1510}
1511
Corentin Wallezccab69d2017-01-27 16:57:15 -05001512Error Framebuffer::getSamplePosition(size_t index, GLfloat *xy) const
1513{
1514 ANGLE_TRY(mImpl->getSamplePosition(index, xy));
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001515 return NoError();
Corentin Wallezccab69d2017-01-27 16:57:15 -05001516}
1517
Jamie Madille261b442014-06-25 12:42:21 -04001518bool Framebuffer::hasValidDepthStencil() const
1519{
Jamie Madill48ef11b2016-04-27 15:21:52 -04001520 return mState.getDepthStencilAttachment() != nullptr;
Jamie Madille261b442014-06-25 12:42:21 -04001521}
1522
Jamie Madilla02315b2017-02-23 14:14:47 -05001523void Framebuffer::setAttachment(const Context *context,
1524 GLenum type,
Jamie Madill2d06b732015-04-20 12:53:28 -04001525 GLenum binding,
1526 const ImageIndex &textureIndex,
1527 FramebufferAttachmentObject *resource)
Geoff Langab75a052014-10-15 12:56:37 -04001528{
Martin Radev5dae57b2017-07-14 16:15:55 +03001529 setAttachment(context, type, binding, textureIndex, resource,
1530 FramebufferAttachment::kDefaultNumViews,
1531 FramebufferAttachment::kDefaultBaseViewIndex,
1532 FramebufferAttachment::kDefaultMultiviewLayout,
1533 FramebufferAttachment::kDefaultViewportOffsets);
1534}
1535
1536void Framebuffer::setAttachment(const Context *context,
1537 GLenum type,
1538 GLenum binding,
1539 const ImageIndex &textureIndex,
1540 FramebufferAttachmentObject *resource,
1541 GLsizei numViews,
1542 GLuint baseViewIndex,
1543 GLenum multiviewLayout,
1544 const GLint *viewportOffsets)
1545{
Jamie Madilla02315b2017-02-23 14:14:47 -05001546 // Context may be null in unit tests.
1547 if (!context || !context->isWebGL1())
1548 {
Martin Radev5dae57b2017-07-14 16:15:55 +03001549 setAttachmentImpl(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
1550 multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001551 return;
1552 }
1553
1554 switch (binding)
1555 {
1556 case GL_DEPTH_STENCIL:
1557 case GL_DEPTH_STENCIL_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001558 mState.mWebGLDepthStencilAttachment.attach(context, type, binding, textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001559 resource, numViews, baseViewIndex,
1560 multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001561 break;
1562 case GL_DEPTH:
1563 case GL_DEPTH_ATTACHMENT:
Martin Radev5dae57b2017-07-14 16:15:55 +03001564 mState.mWebGLDepthAttachment.attach(context, type, binding, textureIndex, resource,
1565 numViews, baseViewIndex, multiviewLayout,
1566 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001567 break;
1568 case GL_STENCIL:
1569 case GL_STENCIL_ATTACHMENT:
Martin Radev5dae57b2017-07-14 16:15:55 +03001570 mState.mWebGLStencilAttachment.attach(context, type, binding, textureIndex, resource,
1571 numViews, baseViewIndex, multiviewLayout,
1572 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001573 break;
1574 default:
Martin Radev5dae57b2017-07-14 16:15:55 +03001575 setAttachmentImpl(context, type, binding, textureIndex, resource, numViews,
1576 baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001577 return;
1578 }
1579
Martin Radev5dae57b2017-07-14 16:15:55 +03001580 commitWebGL1DepthStencilIfConsistent(context, numViews, baseViewIndex, multiviewLayout,
1581 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001582}
1583
Martin Radev82ef7742017-08-08 17:44:58 +03001584void Framebuffer::setAttachmentMultiviewLayered(const Context *context,
1585 GLenum type,
1586 GLenum binding,
1587 const ImageIndex &textureIndex,
1588 FramebufferAttachmentObject *resource,
1589 GLsizei numViews,
1590 GLint baseViewIndex)
1591{
1592 setAttachment(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
1593 GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE,
1594 FramebufferAttachment::kDefaultViewportOffsets);
1595}
1596
Martin Radev5dae57b2017-07-14 16:15:55 +03001597void Framebuffer::setAttachmentMultiviewSideBySide(const Context *context,
1598 GLenum type,
1599 GLenum binding,
1600 const ImageIndex &textureIndex,
1601 FramebufferAttachmentObject *resource,
1602 GLsizei numViews,
1603 const GLint *viewportOffsets)
1604{
1605 setAttachment(context, type, binding, textureIndex, resource, numViews,
1606 FramebufferAttachment::kDefaultBaseViewIndex,
1607 GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, viewportOffsets);
1608}
1609
1610void Framebuffer::commitWebGL1DepthStencilIfConsistent(const Context *context,
1611 GLsizei numViews,
1612 GLuint baseViewIndex,
1613 GLenum multiviewLayout,
1614 const GLint *viewportOffsets)
Jamie Madilla02315b2017-02-23 14:14:47 -05001615{
1616 int count = 0;
1617
1618 std::array<FramebufferAttachment *, 3> attachments = {{&mState.mWebGLDepthStencilAttachment,
1619 &mState.mWebGLDepthAttachment,
1620 &mState.mWebGLStencilAttachment}};
1621 for (FramebufferAttachment *attachment : attachments)
1622 {
1623 if (attachment->isAttached())
1624 {
1625 count++;
1626 }
1627 }
1628
1629 mState.mWebGLDepthStencilConsistent = (count <= 1);
1630 if (!mState.mWebGLDepthStencilConsistent)
1631 {
1632 // Inconsistent.
1633 return;
1634 }
1635
Geoff Lange466c552017-03-17 15:24:12 -04001636 auto getImageIndexIfTextureAttachment = [](const FramebufferAttachment &attachment) {
1637 if (attachment.type() == GL_TEXTURE)
1638 {
1639 return attachment.getTextureImageIndex();
1640 }
1641 else
1642 {
1643 return ImageIndex::MakeInvalid();
1644 }
1645 };
1646
Jamie Madilla02315b2017-02-23 14:14:47 -05001647 if (mState.mWebGLDepthAttachment.isAttached())
1648 {
1649 const auto &depth = mState.mWebGLDepthAttachment;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001650 setAttachmentImpl(context, depth.type(), GL_DEPTH_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001651 getImageIndexIfTextureAttachment(depth), depth.getResource(), numViews,
1652 baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001653 setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex::MakeInvalid(),
Martin Radev5dae57b2017-07-14 16:15:55 +03001654 nullptr, numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001655 }
1656 else if (mState.mWebGLStencilAttachment.isAttached())
1657 {
1658 const auto &stencil = mState.mWebGLStencilAttachment;
Martin Radev5dae57b2017-07-14 16:15:55 +03001659 setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex::MakeInvalid(), nullptr,
1660 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001661 setAttachmentImpl(context, stencil.type(), GL_STENCIL_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001662 getImageIndexIfTextureAttachment(stencil), stencil.getResource(),
1663 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001664 }
1665 else if (mState.mWebGLDepthStencilAttachment.isAttached())
1666 {
1667 const auto &depthStencil = mState.mWebGLDepthStencilAttachment;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001668 setAttachmentImpl(context, depthStencil.type(), GL_DEPTH_ATTACHMENT,
Geoff Lange466c552017-03-17 15:24:12 -04001669 getImageIndexIfTextureAttachment(depthStencil),
Martin Radev5dae57b2017-07-14 16:15:55 +03001670 depthStencil.getResource(), numViews, baseViewIndex, multiviewLayout,
1671 viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001672 setAttachmentImpl(context, depthStencil.type(), GL_STENCIL_ATTACHMENT,
Geoff Lange466c552017-03-17 15:24:12 -04001673 getImageIndexIfTextureAttachment(depthStencil),
Martin Radev5dae57b2017-07-14 16:15:55 +03001674 depthStencil.getResource(), numViews, baseViewIndex, multiviewLayout,
1675 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001676 }
1677 else
1678 {
Martin Radev5dae57b2017-07-14 16:15:55 +03001679 setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex::MakeInvalid(), nullptr,
1680 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001681 setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex::MakeInvalid(),
Martin Radev5dae57b2017-07-14 16:15:55 +03001682 nullptr, numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001683 }
1684}
1685
Jamie Madill4928b7c2017-06-20 12:57:39 -04001686void Framebuffer::setAttachmentImpl(const Context *context,
1687 GLenum type,
Jamie Madilla02315b2017-02-23 14:14:47 -05001688 GLenum binding,
1689 const ImageIndex &textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001690 FramebufferAttachmentObject *resource,
1691 GLsizei numViews,
1692 GLuint baseViewIndex,
1693 GLenum multiviewLayout,
1694 const GLint *viewportOffsets)
Jamie Madilla02315b2017-02-23 14:14:47 -05001695{
Jamie Madilla02315b2017-02-23 14:14:47 -05001696 switch (binding)
1697 {
Jamie Madillb8126692017-04-05 11:22:17 -04001698 case GL_DEPTH_STENCIL:
1699 case GL_DEPTH_STENCIL_ATTACHMENT:
1700 {
1701 // ensure this is a legitimate depth+stencil format
1702 FramebufferAttachmentObject *attachmentObj = resource;
1703 if (resource)
1704 {
Jamie Madill4fd95d52017-04-05 11:22:18 -04001705 const Format &format = resource->getAttachmentFormat(binding, textureIndex);
Jamie Madillb8126692017-04-05 11:22:17 -04001706 if (format.info->depthBits == 0 || format.info->stencilBits == 0)
1707 {
1708 // Attaching nullptr detaches the current attachment.
1709 attachmentObj = nullptr;
1710 }
1711 }
1712
Jamie Madill4928b7c2017-06-20 12:57:39 -04001713 updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
Jamie Madillb8126692017-04-05 11:22:17 -04001714 &mDirtyDepthAttachmentBinding, type, binding, textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001715 attachmentObj, numViews, baseViewIndex, multiviewLayout,
1716 viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001717 updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
Jamie Madillb8126692017-04-05 11:22:17 -04001718 &mDirtyStencilAttachmentBinding, type, binding, textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001719 attachmentObj, numViews, baseViewIndex, multiviewLayout,
1720 viewportOffsets);
Jamie Madill42975642017-10-12 12:31:51 -04001721 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001722 }
1723
Jamie Madilla02315b2017-02-23 14:14:47 -05001724 case GL_DEPTH:
1725 case GL_DEPTH_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001726 updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001727 &mDirtyDepthAttachmentBinding, type, binding, textureIndex, resource,
1728 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madill2d06b732015-04-20 12:53:28 -04001729 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001730
Jamie Madilla02315b2017-02-23 14:14:47 -05001731 case GL_STENCIL:
1732 case GL_STENCIL_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001733 updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001734 &mDirtyStencilAttachmentBinding, type, binding, textureIndex, resource,
1735 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001736 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001737
Jamie Madilla02315b2017-02-23 14:14:47 -05001738 case GL_BACK:
Geoff Lang8170eab2017-09-21 13:59:04 -04001739 updateAttachment(context, &mState.mColorAttachments[0], DIRTY_BIT_COLOR_ATTACHMENT_0,
1740 &mDirtyColorAttachmentBindings[0], type, binding, textureIndex,
1741 resource, numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001742 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001743
Jamie Madilla02315b2017-02-23 14:14:47 -05001744 default:
1745 {
1746 size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
1747 ASSERT(colorIndex < mState.mColorAttachments.size());
Jamie Madillb8126692017-04-05 11:22:17 -04001748 size_t dirtyBit = DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001749 updateAttachment(context, &mState.mColorAttachments[colorIndex], dirtyBit,
Jamie Madillb8126692017-04-05 11:22:17 -04001750 &mDirtyColorAttachmentBindings[colorIndex], type, binding,
Martin Radev5dae57b2017-07-14 16:15:55 +03001751 textureIndex, resource, numViews, baseViewIndex, multiviewLayout,
1752 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001753
Corentin Walleze7557742017-06-01 13:09:57 -04001754 // TODO(jmadill): ASSERT instead of checking the attachment exists in
1755 // formsRenderingFeedbackLoopWith
Jamie Madilla02315b2017-02-23 14:14:47 -05001756 bool enabled = (type != GL_NONE && getDrawBufferState(colorIndex) != GL_NONE);
1757 mState.mEnabledDrawBuffers.set(colorIndex, enabled);
Brandon Jones76746f92017-11-22 11:44:41 -08001758 mState.mDrawBufferTypeMask.setIndex(getDrawbufferWriteType(colorIndex), colorIndex);
Jamie Madill2d06b732015-04-20 12:53:28 -04001759 }
Jamie Madilla02315b2017-02-23 14:14:47 -05001760 break;
Geoff Langab75a052014-10-15 12:56:37 -04001761 }
Jamie Madill42975642017-10-12 12:31:51 -04001762
1763 mAttachedTextures.reset();
Geoff Langab75a052014-10-15 12:56:37 -04001764}
1765
Jamie Madill4928b7c2017-06-20 12:57:39 -04001766void Framebuffer::updateAttachment(const Context *context,
1767 FramebufferAttachment *attachment,
Jamie Madillb8126692017-04-05 11:22:17 -04001768 size_t dirtyBit,
1769 OnAttachmentDirtyBinding *onDirtyBinding,
1770 GLenum type,
1771 GLenum binding,
1772 const ImageIndex &textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001773 FramebufferAttachmentObject *resource,
1774 GLsizei numViews,
1775 GLuint baseViewIndex,
1776 GLenum multiviewLayout,
1777 const GLint *viewportOffsets)
Jamie Madillb8126692017-04-05 11:22:17 -04001778{
Martin Radev5dae57b2017-07-14 16:15:55 +03001779 attachment->attach(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
1780 multiviewLayout, viewportOffsets);
Jamie Madillb8126692017-04-05 11:22:17 -04001781 mDirtyBits.set(dirtyBit);
Jamie Madill05b35b22017-10-03 09:01:44 -04001782 mState.mResourceNeedsInit.set(dirtyBit, attachment->initState() == InitState::MayNeedInit);
Jamie Madillb8126692017-04-05 11:22:17 -04001783 BindResourceChannel(onDirtyBinding, resource);
1784}
1785
Jamie Madilla02315b2017-02-23 14:14:47 -05001786void Framebuffer::resetAttachment(const Context *context, GLenum binding)
Jamie Madill2d06b732015-04-20 12:53:28 -04001787{
Jamie Madilla02315b2017-02-23 14:14:47 -05001788 setAttachment(context, GL_NONE, binding, ImageIndex::MakeInvalid(), nullptr);
Jamie Madill2d06b732015-04-20 12:53:28 -04001789}
1790
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001791void Framebuffer::syncState(const Context *context)
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001792{
1793 if (mDirtyBits.any())
1794 {
Jamie Madillc564c072017-06-01 12:45:42 -04001795 mImpl->syncState(context, mDirtyBits);
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001796 mDirtyBits.reset();
Corentin Wallezccab69d2017-01-27 16:57:15 -05001797 if (mId != 0)
1798 {
1799 mCachedStatus.reset();
1800 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001801 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001802}
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001803
Jamie Madill05b35b22017-10-03 09:01:44 -04001804void Framebuffer::signal(size_t dirtyBit, InitState state)
Jamie Madill51f40ec2016-06-15 14:06:00 -04001805{
Geoff Lang8170eab2017-09-21 13:59:04 -04001806 // Only reset the cached status if this is not the default framebuffer. The default framebuffer
1807 // will still use this channel to mark itself dirty.
1808 if (mId != 0)
1809 {
1810 // TOOD(jmadill): Make this only update individual attachments to do less work.
1811 mCachedStatus.reset();
1812 }
Jamie Madill05b35b22017-10-03 09:01:44 -04001813
1814 // Mark the appropriate init flag.
1815 mState.mResourceNeedsInit.set(dirtyBit, state == InitState::MayNeedInit);
Jamie Madill51f40ec2016-06-15 14:06:00 -04001816}
1817
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001818bool Framebuffer::complete(const Context *context)
Jamie Madill51f40ec2016-06-15 14:06:00 -04001819{
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001820 return (checkStatus(context) == GL_FRAMEBUFFER_COMPLETE);
1821}
1822
1823bool Framebuffer::cachedComplete() const
1824{
1825 return (mCachedStatus.valid() && mCachedStatus == GL_FRAMEBUFFER_COMPLETE);
Jamie Madill51f40ec2016-06-15 14:06:00 -04001826}
1827
Jamie Madilla4595b82017-01-11 17:36:34 -05001828bool Framebuffer::formsRenderingFeedbackLoopWith(const State &state) const
1829{
1830 const Program *program = state.getProgram();
1831
1832 // TODO(jmadill): Default framebuffer feedback loops.
1833 if (mId == 0)
1834 {
1835 return false;
1836 }
1837
1838 // The bitset will skip inactive draw buffers.
Jamie Madill6de51852017-04-12 09:53:01 -04001839 for (size_t drawIndex : mState.mEnabledDrawBuffers)
Jamie Madilla4595b82017-01-11 17:36:34 -05001840 {
Jamie Madill5aca1932017-07-21 12:22:01 -04001841 const FramebufferAttachment &attachment = mState.mColorAttachments[drawIndex];
1842 ASSERT(attachment.isAttached());
1843 if (attachment.type() == GL_TEXTURE)
Jamie Madilla4595b82017-01-11 17:36:34 -05001844 {
1845 // Validate the feedback loop.
Jamie Madill5aca1932017-07-21 12:22:01 -04001846 if (program->samplesFromTexture(state, attachment.id()))
Jamie Madilla4595b82017-01-11 17:36:34 -05001847 {
1848 return true;
1849 }
1850 }
1851 }
1852
Jamie Madill1d37bc52017-02-02 19:59:58 -05001853 // Validate depth-stencil feedback loop.
1854 const auto &dsState = state.getDepthStencilState();
1855
1856 // We can skip the feedback loop checks if depth/stencil is masked out or disabled.
1857 const FramebufferAttachment *depth = getDepthbuffer();
1858 if (depth && depth->type() == GL_TEXTURE && dsState.depthTest && dsState.depthMask)
1859 {
1860 if (program->samplesFromTexture(state, depth->id()))
1861 {
1862 return true;
1863 }
1864 }
1865
1866 // Note: we assume the front and back masks are the same for WebGL.
1867 const FramebufferAttachment *stencil = getStencilbuffer();
1868 ASSERT(dsState.stencilBackWritemask == dsState.stencilWritemask);
1869 if (stencil && stencil->type() == GL_TEXTURE && dsState.stencilTest &&
1870 dsState.stencilWritemask != 0)
1871 {
1872 // Skip the feedback loop check if depth/stencil point to the same resource.
1873 if (!depth || *stencil != *depth)
1874 {
1875 if (program->samplesFromTexture(state, stencil->id()))
1876 {
1877 return true;
1878 }
1879 }
1880 }
1881
Jamie Madilla4595b82017-01-11 17:36:34 -05001882 return false;
1883}
1884
Jamie Madillfd3dd432017-02-02 19:59:59 -05001885bool Framebuffer::formsCopyingFeedbackLoopWith(GLuint copyTextureID,
1886 GLint copyTextureLevel,
1887 GLint copyTextureLayer) const
Jamie Madillf695a3a2017-01-11 17:36:35 -05001888{
1889 if (mId == 0)
1890 {
1891 // It seems impossible to form a texture copying feedback loop with the default FBO.
1892 return false;
1893 }
1894
1895 const FramebufferAttachment *readAttachment = getReadColorbuffer();
1896 ASSERT(readAttachment);
1897
1898 if (readAttachment->isTextureWithId(copyTextureID))
1899 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05001900 const auto &imageIndex = readAttachment->getTextureImageIndex();
1901 if (imageIndex.mipIndex == copyTextureLevel)
Jamie Madillf695a3a2017-01-11 17:36:35 -05001902 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05001903 // Check 3D/Array texture layers.
1904 return imageIndex.layerIndex == ImageIndex::ENTIRE_LEVEL ||
1905 copyTextureLayer == ImageIndex::ENTIRE_LEVEL ||
1906 imageIndex.layerIndex == copyTextureLayer;
Jamie Madillf695a3a2017-01-11 17:36:35 -05001907 }
1908 }
1909 return false;
1910}
1911
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001912GLint Framebuffer::getDefaultWidth() const
1913{
1914 return mState.getDefaultWidth();
1915}
1916
1917GLint Framebuffer::getDefaultHeight() const
1918{
1919 return mState.getDefaultHeight();
1920}
1921
1922GLint Framebuffer::getDefaultSamples() const
1923{
1924 return mState.getDefaultSamples();
1925}
1926
Geoff Lang92019432017-11-20 13:09:34 -05001927bool Framebuffer::getDefaultFixedSampleLocations() const
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001928{
1929 return mState.getDefaultFixedSampleLocations();
1930}
1931
1932void Framebuffer::setDefaultWidth(GLint defaultWidth)
1933{
1934 mState.mDefaultWidth = defaultWidth;
1935 mDirtyBits.set(DIRTY_BIT_DEFAULT_WIDTH);
1936}
1937
1938void Framebuffer::setDefaultHeight(GLint defaultHeight)
1939{
1940 mState.mDefaultHeight = defaultHeight;
1941 mDirtyBits.set(DIRTY_BIT_DEFAULT_HEIGHT);
1942}
1943
1944void Framebuffer::setDefaultSamples(GLint defaultSamples)
1945{
1946 mState.mDefaultSamples = defaultSamples;
1947 mDirtyBits.set(DIRTY_BIT_DEFAULT_SAMPLES);
1948}
1949
Geoff Lang92019432017-11-20 13:09:34 -05001950void Framebuffer::setDefaultFixedSampleLocations(bool defaultFixedSampleLocations)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001951{
1952 mState.mDefaultFixedSampleLocations = defaultFixedSampleLocations;
1953 mDirtyBits.set(DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS);
1954}
1955
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001956// TODO(jmadill): Remove this kludge.
1957GLenum Framebuffer::checkStatus(const ValidationContext *context)
1958{
1959 return checkStatus(static_cast<const Context *>(context));
1960}
1961
1962int Framebuffer::getSamples(const ValidationContext *context)
1963{
1964 return getSamples(static_cast<const Context *>(context));
1965}
1966
Martin Radev14a26ae2017-07-24 15:56:29 +03001967GLsizei Framebuffer::getNumViews() const
1968{
Martin Radev5c00d0d2017-08-07 10:06:59 +03001969 return mState.getNumViews();
Martin Radev14a26ae2017-07-24 15:56:29 +03001970}
1971
Martin Radev4e619f52017-08-09 11:50:06 +03001972GLint Framebuffer::getBaseViewIndex() const
1973{
1974 return mState.getBaseViewIndex();
1975}
1976
Martin Radev878c8b12017-07-28 09:51:04 +03001977const std::vector<Offset> *Framebuffer::getViewportOffsets() const
1978{
Martin Radev5c00d0d2017-08-07 10:06:59 +03001979 return mState.getViewportOffsets();
Martin Radev878c8b12017-07-28 09:51:04 +03001980}
1981
1982GLenum Framebuffer::getMultiviewLayout() const
1983{
Martin Radev5c00d0d2017-08-07 10:06:59 +03001984 return mState.getMultiviewLayout();
Martin Radev878c8b12017-07-28 09:51:04 +03001985}
1986
Jamie Madill05b35b22017-10-03 09:01:44 -04001987Error Framebuffer::ensureDrawAttachmentsInitialized(const Context *context)
1988{
1989 if (!context->isRobustResourceInitEnabled())
1990 {
1991 return NoError();
1992 }
1993
1994 // Note: we don't actually filter by the draw attachment enum. Just init everything.
1995 for (size_t bit : mState.mResourceNeedsInit)
1996 {
1997 switch (bit)
1998 {
1999 case DIRTY_BIT_DEPTH_ATTACHMENT:
2000 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2001 break;
2002 case DIRTY_BIT_STENCIL_ATTACHMENT:
2003 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2004 break;
2005 default:
2006 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[bit]));
2007 break;
2008 }
2009 }
2010
2011 mState.mResourceNeedsInit.reset();
2012 return NoError();
2013}
2014
2015Error Framebuffer::ensureReadAttachmentInitialized(const Context *context, GLbitfield blitMask)
2016{
2017 if (!context->isRobustResourceInitEnabled() || mState.mResourceNeedsInit.none())
2018 {
2019 return NoError();
2020 }
2021
2022 if ((blitMask & GL_COLOR_BUFFER_BIT) != 0 && mState.mReadBufferState != GL_NONE)
2023 {
2024 size_t readIndex = mState.getReadIndex();
2025 if (mState.mResourceNeedsInit[readIndex])
2026 {
2027 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[readIndex]));
2028 mState.mResourceNeedsInit.reset(readIndex);
2029 }
2030 }
2031
2032 if ((blitMask & GL_DEPTH_BUFFER_BIT) != 0 && hasDepth())
2033 {
2034 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2035 {
2036 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2037 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2038 }
2039 }
2040
2041 if ((blitMask & GL_STENCIL_BUFFER_BIT) != 0 && hasStencil())
2042 {
2043 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2044 {
2045 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2046 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2047 }
2048 }
2049
2050 return NoError();
2051}
2052
2053void Framebuffer::markDrawAttachmentsInitialized(bool color, bool depth, bool stencil)
2054{
2055 // Mark attachments as initialized.
2056 if (color)
2057 {
2058 for (auto colorIndex : mState.mEnabledDrawBuffers)
2059 {
2060 auto &colorAttachment = mState.mColorAttachments[colorIndex];
2061 ASSERT(colorAttachment.isAttached());
2062 colorAttachment.setInitState(InitState::Initialized);
2063 mState.mResourceNeedsInit.reset(colorIndex);
2064 }
2065 }
2066
2067 if (depth && mState.mDepthAttachment.isAttached())
2068 {
2069 mState.mDepthAttachment.setInitState(InitState::Initialized);
2070 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2071 }
2072
2073 if (stencil && mState.mStencilAttachment.isAttached())
2074 {
2075 mState.mStencilAttachment.setInitState(InitState::Initialized);
2076 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2077 }
2078}
2079
2080void Framebuffer::markBufferInitialized(GLenum bufferType, GLint bufferIndex)
2081{
2082 switch (bufferType)
2083 {
2084 case GL_COLOR:
2085 {
2086 ASSERT(bufferIndex < static_cast<GLint>(mState.mColorAttachments.size()));
2087 if (mState.mColorAttachments[bufferIndex].isAttached())
2088 {
2089 mState.mColorAttachments[bufferIndex].setInitState(InitState::Initialized);
2090 mState.mResourceNeedsInit.reset(bufferIndex);
2091 }
2092 break;
2093 }
2094 case GL_DEPTH:
2095 {
2096 if (mState.mDepthAttachment.isAttached())
2097 {
2098 mState.mDepthAttachment.setInitState(InitState::Initialized);
2099 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2100 }
2101 break;
2102 }
2103 case GL_STENCIL:
2104 {
2105 if (mState.mStencilAttachment.isAttached())
2106 {
2107 mState.mStencilAttachment.setInitState(InitState::Initialized);
2108 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2109 }
2110 break;
2111 }
2112 case GL_DEPTH_STENCIL:
2113 {
2114 if (mState.mDepthAttachment.isAttached())
2115 {
2116 mState.mDepthAttachment.setInitState(InitState::Initialized);
2117 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2118 }
2119 if (mState.mStencilAttachment.isAttached())
2120 {
2121 mState.mStencilAttachment.setInitState(InitState::Initialized);
2122 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2123 }
2124 break;
2125 }
2126 default:
2127 UNREACHABLE();
2128 break;
2129 }
2130}
2131
2132Box Framebuffer::getDimensions() const
2133{
2134 return mState.getDimensions();
2135}
2136
2137Error Framebuffer::ensureBufferInitialized(const Context *context,
2138 GLenum bufferType,
2139 GLint bufferIndex)
2140{
2141 ASSERT(context->isRobustResourceInitEnabled());
2142
2143 if (mState.mResourceNeedsInit.none())
2144 {
2145 return NoError();
2146 }
2147
2148 switch (bufferType)
2149 {
2150 case GL_COLOR:
2151 {
2152 ASSERT(bufferIndex < static_cast<GLint>(mState.mColorAttachments.size()));
2153 if (mState.mResourceNeedsInit[bufferIndex])
2154 {
2155 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[bufferIndex]));
2156 mState.mResourceNeedsInit.reset(bufferIndex);
2157 }
2158 break;
2159 }
2160 case GL_DEPTH:
2161 {
2162 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2163 {
2164 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2165 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2166 }
2167 break;
2168 }
2169 case GL_STENCIL:
2170 {
2171 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2172 {
2173 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2174 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2175 }
2176 break;
2177 }
2178 case GL_DEPTH_STENCIL:
2179 {
2180 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2181 {
2182 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2183 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2184 }
2185 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2186 {
2187 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2188 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2189 }
2190 break;
2191 }
2192 default:
2193 UNREACHABLE();
2194 break;
2195 }
2196
2197 return NoError();
2198}
2199
2200bool Framebuffer::partialBufferClearNeedsInit(const Context *context, GLenum bufferType)
2201{
2202 if (!context->isRobustResourceInitEnabled() || mState.mResourceNeedsInit.none())
2203 {
2204 return false;
2205 }
2206
2207 switch (bufferType)
2208 {
2209 case GL_COLOR:
2210 return partialClearNeedsInit(context, true, false, false);
2211 case GL_DEPTH:
2212 return partialClearNeedsInit(context, false, true, false);
2213 case GL_STENCIL:
2214 return partialClearNeedsInit(context, false, false, true);
2215 case GL_DEPTH_STENCIL:
2216 return partialClearNeedsInit(context, false, true, true);
2217 default:
2218 UNREACHABLE();
2219 return false;
2220 }
2221}
2222
Jamie Madill42975642017-10-12 12:31:51 -04002223bool Framebuffer::hasTextureAttachment(const Texture *texture) const
2224{
2225 if (!mAttachedTextures.valid())
2226 {
2227 std::set<const FramebufferAttachmentObject *> attachedTextures;
2228
2229 for (const auto &colorAttachment : mState.mColorAttachments)
2230 {
2231 if (colorAttachment.isAttached() && colorAttachment.type() == GL_TEXTURE)
2232 {
2233 attachedTextures.insert(colorAttachment.getResource());
2234 }
2235 }
2236
2237 if (mState.mDepthAttachment.isAttached() && mState.mDepthAttachment.type() == GL_TEXTURE)
2238 {
2239 attachedTextures.insert(mState.mDepthAttachment.getResource());
2240 }
2241
2242 if (mState.mStencilAttachment.isAttached() &&
2243 mState.mStencilAttachment.type() == GL_TEXTURE)
2244 {
2245 attachedTextures.insert(mState.mStencilAttachment.getResource());
2246 }
2247
2248 mAttachedTextures = std::move(attachedTextures);
2249 }
2250
2251 return (mAttachedTextures.value().count(texture) > 0);
2252}
2253
Jamie Madill60ec6ea2016-01-22 15:27:19 -05002254} // namespace gl