blob: 67db701161a2e0dfe2aba5813d2207b49a89e241 [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
308 switch (attachment)
309 {
310 case GL_COLOR:
311 case GL_BACK:
312 return getColorAttachment(0);
313 case GL_DEPTH:
314 case GL_DEPTH_ATTACHMENT:
315 return getDepthAttachment();
316 case GL_STENCIL:
317 case GL_STENCIL_ATTACHMENT:
318 return getStencilAttachment();
319 case GL_DEPTH_STENCIL:
320 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800321 // In WebG1, DEPTH_STENCIL_ATTACHMENT is an alternative attachment point and even when
322 // inconsistant (i.e. multiple conflicting attachment points), it is still permitted to
323 // query the attachment parameters.
324 if (context->isWebGL1())
325 {
326 return getWebGLDepthStencilAttachment();
327 }
328 else
329 {
330 return getDepthStencilAttachment();
331 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400332 default:
333 UNREACHABLE();
334 return nullptr;
335 }
336}
337
Jamie Madill05b35b22017-10-03 09:01:44 -0400338size_t FramebufferState::getReadIndex() const
Jamie Madill7147f012015-03-05 15:41:40 -0500339{
Jamie Madill231c7f52017-04-26 13:45:37 -0400340 ASSERT(mReadBufferState == GL_BACK ||
341 (mReadBufferState >= GL_COLOR_ATTACHMENT0 && mReadBufferState <= GL_COLOR_ATTACHMENT15));
342 size_t readIndex = (mReadBufferState == GL_BACK
343 ? 0
344 : static_cast<size_t>(mReadBufferState - GL_COLOR_ATTACHMENT0));
Jamie Madill7147f012015-03-05 15:41:40 -0500345 ASSERT(readIndex < mColorAttachments.size());
Jamie Madill05b35b22017-10-03 09:01:44 -0400346 return readIndex;
347}
348
349const FramebufferAttachment *FramebufferState::getReadAttachment() const
350{
351 if (mReadBufferState == GL_NONE)
352 {
353 return nullptr;
354 }
355 size_t readIndex = getReadIndex();
Jamie Madill2d06b732015-04-20 12:53:28 -0400356 return mColorAttachments[readIndex].isAttached() ? &mColorAttachments[readIndex] : nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500357}
358
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500359const FramebufferAttachment *FramebufferState::getFirstNonNullAttachment() const
360{
361 auto *colorAttachment = getFirstColorAttachment();
362 if (colorAttachment)
363 {
364 return colorAttachment;
365 }
366 return getDepthOrStencilAttachment();
367}
368
Jamie Madill48ef11b2016-04-27 15:21:52 -0400369const FramebufferAttachment *FramebufferState::getFirstColorAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500370{
Jamie Madill2d06b732015-04-20 12:53:28 -0400371 for (const FramebufferAttachment &colorAttachment : mColorAttachments)
Jamie Madill7147f012015-03-05 15:41:40 -0500372 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400373 if (colorAttachment.isAttached())
Jamie Madill7147f012015-03-05 15:41:40 -0500374 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400375 return &colorAttachment;
Jamie Madill7147f012015-03-05 15:41:40 -0500376 }
377 }
378
379 return nullptr;
380}
381
Jamie Madill48ef11b2016-04-27 15:21:52 -0400382const FramebufferAttachment *FramebufferState::getDepthOrStencilAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500383{
Jamie Madill2d06b732015-04-20 12:53:28 -0400384 if (mDepthAttachment.isAttached())
385 {
386 return &mDepthAttachment;
387 }
388 if (mStencilAttachment.isAttached())
389 {
390 return &mStencilAttachment;
391 }
392 return nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500393}
394
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500395const FramebufferAttachment *FramebufferState::getStencilOrDepthStencilAttachment() const
396{
397 if (mStencilAttachment.isAttached())
398 {
399 return &mStencilAttachment;
400 }
401 return getDepthStencilAttachment();
402}
403
Jamie Madill48ef11b2016-04-27 15:21:52 -0400404const FramebufferAttachment *FramebufferState::getColorAttachment(size_t colorAttachment) const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400405{
406 ASSERT(colorAttachment < mColorAttachments.size());
Jamie Madill231c7f52017-04-26 13:45:37 -0400407 return mColorAttachments[colorAttachment].isAttached() ? &mColorAttachments[colorAttachment]
408 : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400409}
410
Jamie Madill48ef11b2016-04-27 15:21:52 -0400411const FramebufferAttachment *FramebufferState::getDepthAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400412{
Jamie Madill2d06b732015-04-20 12:53:28 -0400413 return mDepthAttachment.isAttached() ? &mDepthAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400414}
415
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800416const FramebufferAttachment *FramebufferState::getWebGLDepthStencilAttachment() const
417{
418 return mWebGLDepthStencilAttachment.isAttached() ? &mWebGLDepthStencilAttachment : nullptr;
419}
420
Jamie Madill48ef11b2016-04-27 15:21:52 -0400421const FramebufferAttachment *FramebufferState::getStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400422{
Jamie Madill2d06b732015-04-20 12:53:28 -0400423 return mStencilAttachment.isAttached() ? &mStencilAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400424}
425
Jamie Madill48ef11b2016-04-27 15:21:52 -0400426const FramebufferAttachment *FramebufferState::getDepthStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400427{
428 // A valid depth-stencil attachment has the same resource bound to both the
429 // depth and stencil attachment points.
Jamie Madill2d06b732015-04-20 12:53:28 -0400430 if (mDepthAttachment.isAttached() && mStencilAttachment.isAttached() &&
Jamie Madill44f26482016-11-18 12:49:15 -0500431 mDepthAttachment == mStencilAttachment)
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400432 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400433 return &mDepthAttachment;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400434 }
435
436 return nullptr;
437}
438
Jamie Madill48ef11b2016-04-27 15:21:52 -0400439bool FramebufferState::attachmentsHaveSameDimensions() const
Jamie Madillcc86d642015-11-24 13:00:07 -0500440{
441 Optional<Extents> attachmentSize;
442
Jamie Madill231c7f52017-04-26 13:45:37 -0400443 auto hasMismatchedSize = [&attachmentSize](const FramebufferAttachment &attachment) {
Jamie Madillcc86d642015-11-24 13:00:07 -0500444 if (!attachment.isAttached())
445 {
446 return false;
447 }
448
449 if (!attachmentSize.valid())
450 {
451 attachmentSize = attachment.getSize();
452 return false;
453 }
454
Jeff Gilbert8f8edd62017-10-31 14:26:30 -0700455 const auto &prevSize = attachmentSize.value();
456 const auto &curSize = attachment.getSize();
457 return (curSize.width != prevSize.width || curSize.height != prevSize.height);
Jamie Madillcc86d642015-11-24 13:00:07 -0500458 };
459
460 for (const auto &attachment : mColorAttachments)
461 {
462 if (hasMismatchedSize(attachment))
463 {
464 return false;
465 }
466 }
467
468 if (hasMismatchedSize(mDepthAttachment))
469 {
470 return false;
471 }
472
473 return !hasMismatchedSize(mStencilAttachment);
474}
475
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400476const gl::FramebufferAttachment *FramebufferState::getDrawBuffer(size_t drawBufferIdx) const
477{
478 ASSERT(drawBufferIdx < mDrawBufferStates.size());
479 if (mDrawBufferStates[drawBufferIdx] != GL_NONE)
480 {
481 // ES3 spec: "If the GL is bound to a draw framebuffer object, the ith buffer listed in bufs
482 // must be COLOR_ATTACHMENTi or NONE"
483 ASSERT(mDrawBufferStates[drawBufferIdx] == GL_COLOR_ATTACHMENT0 + drawBufferIdx ||
484 (drawBufferIdx == 0 && mDrawBufferStates[drawBufferIdx] == GL_BACK));
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800485
486 if (mDrawBufferStates[drawBufferIdx] == GL_BACK)
487 {
488 return getColorAttachment(0);
489 }
490 else
491 {
492 return getColorAttachment(mDrawBufferStates[drawBufferIdx] - GL_COLOR_ATTACHMENT0);
493 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400494 }
495 else
496 {
497 return nullptr;
498 }
499}
500
501size_t FramebufferState::getDrawBufferCount() const
502{
503 return mDrawBufferStates.size();
504}
505
Geoff Langb21e20d2016-07-19 15:35:41 -0400506bool FramebufferState::colorAttachmentsAreUniqueImages() const
507{
508 for (size_t firstAttachmentIdx = 0; firstAttachmentIdx < mColorAttachments.size();
509 firstAttachmentIdx++)
510 {
511 const gl::FramebufferAttachment &firstAttachment = mColorAttachments[firstAttachmentIdx];
512 if (!firstAttachment.isAttached())
513 {
514 continue;
515 }
516
517 for (size_t secondAttachmentIdx = firstAttachmentIdx + 1;
518 secondAttachmentIdx < mColorAttachments.size(); secondAttachmentIdx++)
519 {
520 const gl::FramebufferAttachment &secondAttachment =
521 mColorAttachments[secondAttachmentIdx];
522 if (!secondAttachment.isAttached())
523 {
524 continue;
525 }
526
527 if (firstAttachment == secondAttachment)
528 {
529 return false;
530 }
531 }
532 }
533
534 return true;
535}
536
Jamie Madill9c335862017-07-18 11:51:38 -0400537bool FramebufferState::hasDepth() const
538{
539 return (mDepthAttachment.isAttached() && mDepthAttachment.getDepthSize() > 0);
540}
541
542bool FramebufferState::hasStencil() const
543{
544 return (mStencilAttachment.isAttached() && mStencilAttachment.getStencilSize() > 0);
545}
546
Martin Radev5c00d0d2017-08-07 10:06:59 +0300547GLsizei FramebufferState::getNumViews() const
548{
549 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
550 if (attachment == nullptr)
551 {
552 return FramebufferAttachment::kDefaultNumViews;
553 }
554 return attachment->getNumViews();
555}
556
557const std::vector<Offset> *FramebufferState::getViewportOffsets() const
558{
559 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
560 if (attachment == nullptr)
561 {
562 return nullptr;
563 }
564 return &attachment->getMultiviewViewportOffsets();
565}
566
567GLenum FramebufferState::getMultiviewLayout() const
568{
569 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
570 if (attachment == nullptr)
571 {
572 return GL_NONE;
573 }
574 return attachment->getMultiviewLayout();
575}
576
Martin Radev4e619f52017-08-09 11:50:06 +0300577int FramebufferState::getBaseViewIndex() const
578{
579 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
580 if (attachment == nullptr)
581 {
582 return GL_NONE;
583 }
584 return attachment->getBaseViewIndex();
585}
586
Jamie Madill05b35b22017-10-03 09:01:44 -0400587Box FramebufferState::getDimensions() const
588{
589 ASSERT(attachmentsHaveSameDimensions());
590 ASSERT(getFirstNonNullAttachment() != nullptr);
591 Extents extents = getFirstNonNullAttachment()->getSize();
592 return Box(0, 0, 0, extents.width, extents.height, extents.depth);
593}
594
Jamie Madill7aea7e02016-05-10 10:39:45 -0400595Framebuffer::Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id)
Jamie Madill362876b2016-06-16 14:46:59 -0400596 : mState(caps),
597 mImpl(factory->createFramebuffer(mState)),
598 mId(id),
599 mCachedStatus(),
600 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
601 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000602{
Corentin Wallez37c39792015-08-20 14:19:46 -0400603 ASSERT(mId != 0);
604 ASSERT(mImpl != nullptr);
Jamie Madill362876b2016-06-16 14:46:59 -0400605 ASSERT(mState.mColorAttachments.size() == static_cast<size_t>(caps.maxColorAttachments));
606
Jamie Madill1e5499d2017-04-05 11:22:16 -0400607 for (uint32_t colorIndex = 0;
608 colorIndex < static_cast<uint32_t>(mState.mColorAttachments.size()); ++colorIndex)
Jamie Madill362876b2016-06-16 14:46:59 -0400609 {
Jamie Madill1e5499d2017-04-05 11:22:16 -0400610 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
Jamie Madill362876b2016-06-16 14:46:59 -0400611 }
Corentin Wallez37c39792015-08-20 14:19:46 -0400612}
613
Jamie Madill4928b7c2017-06-20 12:57:39 -0400614Framebuffer::Framebuffer(const egl::Display *display, egl::Surface *surface)
Jamie Madill362876b2016-06-16 14:46:59 -0400615 : mState(),
Jamie Madill6f60d052017-02-22 15:20:11 -0500616 mImpl(surface->getImplementation()->createDefaultFramebuffer(mState)),
Jamie Madill362876b2016-06-16 14:46:59 -0400617 mId(0),
618 mCachedStatus(GL_FRAMEBUFFER_COMPLETE),
619 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
620 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
Corentin Wallez37c39792015-08-20 14:19:46 -0400621{
Geoff Langda88add2014-12-01 10:22:01 -0500622 ASSERT(mImpl != nullptr);
Jamie Madill1e5499d2017-04-05 11:22:16 -0400623 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
Jamie Madill6f60d052017-02-22 15:20:11 -0500624
Jamie Madill4928b7c2017-06-20 12:57:39 -0400625 const Context *proxyContext = display->getProxyContext();
626
627 setAttachmentImpl(proxyContext, GL_FRAMEBUFFER_DEFAULT, GL_BACK, gl::ImageIndex::MakeInvalid(),
Martin Radev5dae57b2017-07-14 16:15:55 +0300628 surface, FramebufferAttachment::kDefaultNumViews,
629 FramebufferAttachment::kDefaultBaseViewIndex,
630 FramebufferAttachment::kDefaultMultiviewLayout,
631 FramebufferAttachment::kDefaultViewportOffsets);
Jamie Madill6f60d052017-02-22 15:20:11 -0500632
633 if (surface->getConfig()->depthSize > 0)
634 {
Martin Radev5dae57b2017-07-14 16:15:55 +0300635 setAttachmentImpl(
636 proxyContext, GL_FRAMEBUFFER_DEFAULT, GL_DEPTH, gl::ImageIndex::MakeInvalid(), surface,
637 FramebufferAttachment::kDefaultNumViews, FramebufferAttachment::kDefaultBaseViewIndex,
638 FramebufferAttachment::kDefaultMultiviewLayout,
639 FramebufferAttachment::kDefaultViewportOffsets);
Jamie Madill6f60d052017-02-22 15:20:11 -0500640 }
641
642 if (surface->getConfig()->stencilSize > 0)
643 {
Jamie Madill4928b7c2017-06-20 12:57:39 -0400644 setAttachmentImpl(proxyContext, GL_FRAMEBUFFER_DEFAULT, GL_STENCIL,
Martin Radev5dae57b2017-07-14 16:15:55 +0300645 gl::ImageIndex::MakeInvalid(), surface,
646 FramebufferAttachment::kDefaultNumViews,
647 FramebufferAttachment::kDefaultBaseViewIndex,
648 FramebufferAttachment::kDefaultMultiviewLayout,
649 FramebufferAttachment::kDefaultViewportOffsets);
Jamie Madill6f60d052017-02-22 15:20:11 -0500650 }
Brandon Jones76746f92017-11-22 11:44:41 -0800651 mState.mDrawBufferTypeMask.setIndex(getDrawbufferWriteType(0), 0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000652}
653
Corentin Wallezccab69d2017-01-27 16:57:15 -0500654Framebuffer::Framebuffer(rx::GLImplFactory *factory)
655 : mState(),
656 mImpl(factory->createFramebuffer(mState)),
657 mId(0),
658 mCachedStatus(GL_FRAMEBUFFER_UNDEFINED_OES),
659 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
660 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
661{
Jamie Madill1e5499d2017-04-05 11:22:16 -0400662 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
Brandon Jones76746f92017-11-22 11:44:41 -0800663 mState.mDrawBufferTypeMask.setIndex(getDrawbufferWriteType(0), 0);
Corentin Wallezccab69d2017-01-27 16:57:15 -0500664}
665
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000666Framebuffer::~Framebuffer()
667{
Geoff Langda88add2014-12-01 10:22:01 -0500668 SafeDelete(mImpl);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000669}
670
Jamie Madill4928b7c2017-06-20 12:57:39 -0400671void Framebuffer::onDestroy(const Context *context)
Jamie Madill6c1f6712017-02-14 19:08:04 -0500672{
Jamie Madill4928b7c2017-06-20 12:57:39 -0400673 for (auto &attachment : mState.mColorAttachments)
674 {
675 attachment.detach(context);
676 }
677 mState.mDepthAttachment.detach(context);
678 mState.mStencilAttachment.detach(context);
679 mState.mWebGLDepthAttachment.detach(context);
680 mState.mWebGLStencilAttachment.detach(context);
681 mState.mWebGLDepthStencilAttachment.detach(context);
682
Jamie Madillc564c072017-06-01 12:45:42 -0400683 mImpl->destroy(context);
Jamie Madill6c1f6712017-02-14 19:08:04 -0500684}
685
686void Framebuffer::destroyDefault(const egl::Display *display)
687{
Jamie Madillc564c072017-06-01 12:45:42 -0400688 mImpl->destroyDefault(display);
Jamie Madill6c1f6712017-02-14 19:08:04 -0500689}
690
Geoff Lang70d0f492015-12-10 17:45:46 -0500691void Framebuffer::setLabel(const std::string &label)
692{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400693 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -0500694}
695
696const std::string &Framebuffer::getLabel() const
697{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400698 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -0500699}
700
Jamie Madill8693bdb2017-09-02 15:32:14 -0400701bool Framebuffer::detachTexture(const Context *context, GLuint textureId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000702{
Jamie Madill8693bdb2017-09-02 15:32:14 -0400703 return detachResourceById(context, GL_TEXTURE, textureId);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000704}
705
Jamie Madill8693bdb2017-09-02 15:32:14 -0400706bool Framebuffer::detachRenderbuffer(const Context *context, GLuint renderbufferId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000707{
Jamie Madill8693bdb2017-09-02 15:32:14 -0400708 return detachResourceById(context, GL_RENDERBUFFER, renderbufferId);
Jamie Madilld1405e52015-03-05 15:41:39 -0500709}
Jamie Madille261b442014-06-25 12:42:21 -0400710
Jamie Madill8693bdb2017-09-02 15:32:14 -0400711bool Framebuffer::detachResourceById(const Context *context, GLenum resourceType, GLuint resourceId)
Jamie Madilld1405e52015-03-05 15:41:39 -0500712{
Jamie Madill8693bdb2017-09-02 15:32:14 -0400713 bool found = false;
714
Jamie Madill362876b2016-06-16 14:46:59 -0400715 for (size_t colorIndex = 0; colorIndex < mState.mColorAttachments.size(); ++colorIndex)
Jamie Madilld1405e52015-03-05 15:41:39 -0500716 {
Jamie Madill8693bdb2017-09-02 15:32:14 -0400717 if (detachMatchingAttachment(context, &mState.mColorAttachments[colorIndex], resourceType,
718 resourceId, DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex))
719 {
720 found = true;
721 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000722 }
723
Jamie Madilla02315b2017-02-23 14:14:47 -0500724 if (context->isWebGL1())
725 {
726 const std::array<FramebufferAttachment *, 3> attachments = {
727 {&mState.mWebGLDepthStencilAttachment, &mState.mWebGLDepthAttachment,
728 &mState.mWebGLStencilAttachment}};
729 for (FramebufferAttachment *attachment : attachments)
730 {
731 if (attachment->isAttached() && attachment->type() == resourceType &&
732 attachment->id() == resourceId)
733 {
734 resetAttachment(context, attachment->getBinding());
Jamie Madill8693bdb2017-09-02 15:32:14 -0400735 found = true;
Jamie Madilla02315b2017-02-23 14:14:47 -0500736 }
737 }
738 }
739 else
740 {
Jamie Madill8693bdb2017-09-02 15:32:14 -0400741 if (detachMatchingAttachment(context, &mState.mDepthAttachment, resourceType, resourceId,
742 DIRTY_BIT_DEPTH_ATTACHMENT))
743 {
744 found = true;
745 }
746 if (detachMatchingAttachment(context, &mState.mStencilAttachment, resourceType, resourceId,
747 DIRTY_BIT_STENCIL_ATTACHMENT))
748 {
749 found = true;
750 }
Jamie Madilla02315b2017-02-23 14:14:47 -0500751 }
Jamie Madill8693bdb2017-09-02 15:32:14 -0400752
753 return found;
Jamie Madill362876b2016-06-16 14:46:59 -0400754}
755
Jamie Madill8693bdb2017-09-02 15:32:14 -0400756bool Framebuffer::detachMatchingAttachment(const Context *context,
Jamie Madill4928b7c2017-06-20 12:57:39 -0400757 FramebufferAttachment *attachment,
Jamie Madill362876b2016-06-16 14:46:59 -0400758 GLenum matchType,
759 GLuint matchId,
760 size_t dirtyBit)
761{
762 if (attachment->isAttached() && attachment->type() == matchType && attachment->id() == matchId)
763 {
Jamie Madill4928b7c2017-06-20 12:57:39 -0400764 attachment->detach(context);
Jamie Madill362876b2016-06-16 14:46:59 -0400765 mDirtyBits.set(dirtyBit);
Jamie Madill05b35b22017-10-03 09:01:44 -0400766 mState.mResourceNeedsInit.set(dirtyBit, false);
Jamie Madill8693bdb2017-09-02 15:32:14 -0400767 return true;
Jamie Madill362876b2016-06-16 14:46:59 -0400768 }
Jamie Madill8693bdb2017-09-02 15:32:14 -0400769
770 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000771}
772
Corentin Wallez37c39792015-08-20 14:19:46 -0400773const FramebufferAttachment *Framebuffer::getColorbuffer(size_t colorAttachment) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000774{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400775 return mState.getColorAttachment(colorAttachment);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000776}
777
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400778const FramebufferAttachment *Framebuffer::getDepthbuffer() const
Geoff Lang646559f2013-08-15 11:08:15 -0400779{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400780 return mState.getDepthAttachment();
Geoff Lang646559f2013-08-15 11:08:15 -0400781}
782
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400783const FramebufferAttachment *Framebuffer::getStencilbuffer() const
784{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400785 return mState.getStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400786}
787
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400788const FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
789{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400790 return mState.getDepthStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400791}
792
793const FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000794{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400795 return mState.getDepthOrStencilAttachment();
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000796}
797
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500798const FramebufferAttachment *Framebuffer::getStencilOrDepthStencilAttachment() const
799{
800 return mState.getStencilOrDepthStencilAttachment();
801}
802
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400803const FramebufferAttachment *Framebuffer::getReadColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000804{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400805 return mState.getReadAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000806}
807
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000808GLenum Framebuffer::getReadColorbufferType() const
809{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400810 const FramebufferAttachment *readAttachment = mState.getReadAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400811 return (readAttachment != nullptr ? readAttachment->type() : GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000812}
813
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400814const FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000815{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400816 return mState.getFirstColorAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000817}
818
Jamie Madill6dd06ea2017-07-19 13:47:55 -0400819const FramebufferAttachment *Framebuffer::getFirstNonNullAttachment() const
820{
821 return mState.getFirstNonNullAttachment();
822}
823
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800824const FramebufferAttachment *Framebuffer::getAttachment(const Context *context,
825 GLenum attachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000826{
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800827 return mState.getAttachment(context, attachment);
Geoff Lang55ba29c2013-07-11 16:57:53 -0400828}
829
Geoff Langa15472a2015-08-11 11:48:03 -0400830size_t Framebuffer::getDrawbufferStateCount() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000831{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400832 return mState.mDrawBufferStates.size();
Geoff Langa15472a2015-08-11 11:48:03 -0400833}
834
835GLenum Framebuffer::getDrawBufferState(size_t drawBuffer) const
836{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400837 ASSERT(drawBuffer < mState.mDrawBufferStates.size());
838 return mState.mDrawBufferStates[drawBuffer];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000839}
840
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500841const std::vector<GLenum> &Framebuffer::getDrawBufferStates() const
842{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400843 return mState.getDrawBufferStates();
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500844}
845
Geoff Lang164d54e2014-12-01 10:55:33 -0500846void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000847{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400848 auto &drawStates = mState.mDrawBufferStates;
Jamie Madilld1405e52015-03-05 15:41:39 -0500849
850 ASSERT(count <= drawStates.size());
851 std::copy(buffers, buffers + count, drawStates.begin());
852 std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500853 mDirtyBits.set(DIRTY_BIT_DRAW_BUFFERS);
Jamie Madilla4595b82017-01-11 17:36:34 -0500854
855 mState.mEnabledDrawBuffers.reset();
Brandon Jones76746f92017-11-22 11:44:41 -0800856 mState.mDrawBufferTypeMask.reset();
857
Jamie Madilla4595b82017-01-11 17:36:34 -0500858 for (size_t index = 0; index < count; ++index)
859 {
Brandon Jones76746f92017-11-22 11:44:41 -0800860 mState.mDrawBufferTypeMask.setIndex(getDrawbufferWriteType(index), index);
861
Jamie Madilla4595b82017-01-11 17:36:34 -0500862 if (drawStates[index] != GL_NONE && mState.mColorAttachments[index].isAttached())
863 {
864 mState.mEnabledDrawBuffers.set(index);
865 }
866 }
Geoff Lang9dd95802014-12-01 11:12:59 -0500867}
868
Geoff Langa15472a2015-08-11 11:48:03 -0400869const FramebufferAttachment *Framebuffer::getDrawBuffer(size_t drawBuffer) const
870{
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400871 return mState.getDrawBuffer(drawBuffer);
Geoff Langa15472a2015-08-11 11:48:03 -0400872}
873
Geoff Lange0cff192017-05-30 13:04:56 -0400874GLenum Framebuffer::getDrawbufferWriteType(size_t drawBuffer) const
875{
876 const FramebufferAttachment *attachment = mState.getDrawBuffer(drawBuffer);
877 if (attachment == nullptr)
878 {
879 return GL_NONE;
880 }
881
882 GLenum componentType = attachment->getFormat().info->componentType;
883 switch (componentType)
884 {
885 case GL_INT:
886 case GL_UNSIGNED_INT:
887 return componentType;
888
889 default:
890 return GL_FLOAT;
891 }
892}
893
Brandon Jones76746f92017-11-22 11:44:41 -0800894DrawBufferTypeMask Framebuffer::getDrawBufferTypeMask() const
895{
896 return mState.mDrawBufferTypeMask;
897}
898
899DrawBufferMask Framebuffer::getDrawBufferMask() const
900{
901 return mState.mEnabledDrawBuffers;
902}
903
Geoff Langa15472a2015-08-11 11:48:03 -0400904bool Framebuffer::hasEnabledDrawBuffer() const
905{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400906 for (size_t drawbufferIdx = 0; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
Geoff Langa15472a2015-08-11 11:48:03 -0400907 {
908 if (getDrawBuffer(drawbufferIdx) != nullptr)
909 {
910 return true;
911 }
912 }
913
914 return false;
915}
916
Geoff Lang9dd95802014-12-01 11:12:59 -0500917GLenum Framebuffer::getReadBufferState() const
918{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400919 return mState.mReadBufferState;
Geoff Lang9dd95802014-12-01 11:12:59 -0500920}
921
922void Framebuffer::setReadBuffer(GLenum buffer)
923{
Jamie Madillb885e572015-02-03 16:16:04 -0500924 ASSERT(buffer == GL_BACK || buffer == GL_NONE ||
925 (buffer >= GL_COLOR_ATTACHMENT0 &&
Jamie Madill48ef11b2016-04-27 15:21:52 -0400926 (buffer - GL_COLOR_ATTACHMENT0) < mState.mColorAttachments.size()));
927 mState.mReadBufferState = buffer;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500928 mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000929}
930
Corentin Wallez37c39792015-08-20 14:19:46 -0400931size_t Framebuffer::getNumColorBuffers() const
932{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400933 return mState.mColorAttachments.size();
Corentin Wallez37c39792015-08-20 14:19:46 -0400934}
935
Jamie Madill0df8fe42015-11-24 16:10:24 -0500936bool Framebuffer::hasDepth() const
937{
Jamie Madill9c335862017-07-18 11:51:38 -0400938 return mState.hasDepth();
Jamie Madill0df8fe42015-11-24 16:10:24 -0500939}
940
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000941bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000942{
Jamie Madill9c335862017-07-18 11:51:38 -0400943 return mState.hasStencil();
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000944}
945
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000946bool Framebuffer::usingExtendedDrawBuffers() const
947{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400948 for (size_t drawbufferIdx = 1; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000949 {
Geoff Langa15472a2015-08-11 11:48:03 -0400950 if (getDrawBuffer(drawbufferIdx) != nullptr)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000951 {
952 return true;
953 }
954 }
955
956 return false;
957}
958
Geoff Lang9aded172017-04-05 11:07:56 -0400959void Framebuffer::invalidateCompletenessCache()
960{
961 if (mId != 0)
962 {
963 mCachedStatus.reset();
964 }
965}
966
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400967GLenum Framebuffer::checkStatus(const Context *context)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000968{
Corentin Wallezccab69d2017-01-27 16:57:15 -0500969 // The default framebuffer is always complete except when it is surfaceless in which
970 // case it is always unsupported. We return early because the default framebuffer may
971 // not be subject to the same rules as application FBOs. ie, it could have 0x0 size.
Geoff Lang528ce3c2014-12-01 10:44:07 -0500972 if (mId == 0)
973 {
Corentin Wallezccab69d2017-01-27 16:57:15 -0500974 ASSERT(mCachedStatus.valid());
975 ASSERT(mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE ||
976 mCachedStatus.value() == GL_FRAMEBUFFER_UNDEFINED_OES);
977 return mCachedStatus.value();
Geoff Lang528ce3c2014-12-01 10:44:07 -0500978 }
979
Jamie Madill362876b2016-06-16 14:46:59 -0400980 if (hasAnyDirtyBit() || !mCachedStatus.valid())
981 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400982 mCachedStatus = checkStatusImpl(context);
Jamie Madill362876b2016-06-16 14:46:59 -0400983 }
984
985 return mCachedStatus.value();
986}
987
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400988GLenum Framebuffer::checkStatusImpl(const Context *context)
Jamie Madill362876b2016-06-16 14:46:59 -0400989{
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400990 const ContextState &state = context->getContextState();
991
Jamie Madill362876b2016-06-16 14:46:59 -0400992 ASSERT(mId != 0);
993
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400994 bool hasAttachments = false;
995 Optional<unsigned int> colorbufferSize;
996 Optional<int> samples;
Geoff Lang92019432017-11-20 13:09:34 -0500997 Optional<bool> fixedSampleLocations;
JiangYizhou461d9a32017-01-04 16:37:26 +0800998 bool hasRenderbuffer = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000999
Martin Radev9bc9a322017-07-21 14:28:17 +03001000 const FramebufferAttachment *firstAttachment = getFirstNonNullAttachment();
1001
Jamie Madill48ef11b2016-04-27 15:21:52 -04001002 for (const FramebufferAttachment &colorAttachment : mState.mColorAttachments)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001003 {
Jamie Madill2d06b732015-04-20 12:53:28 -04001004 if (colorAttachment.isAttached())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001005 {
Geoff Lang9f10b772017-05-16 15:51:03 -04001006 if (!CheckAttachmentCompleteness(context, colorAttachment))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001007 {
1008 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1009 }
daniel@transgaming.com01868132010-08-24 19:21:17 +00001010
Geoff Lang677bb6f2017-04-05 12:40:40 -04001011 const InternalFormat &format = *colorAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -04001012 if (format.depthBits > 0 || format.stencilBits > 0)
1013 {
1014 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1015 }
1016
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001017 if (!CheckAttachmentSampleCompleteness(context, colorAttachment, true, &samples,
1018 &fixedSampleLocations))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001019 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001020 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001021 }
1022
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001023 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
1024 // in GLES 3.0, there is no such restriction
1025 if (state.getClientMajorVersion() < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001026 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001027 if (colorbufferSize.valid())
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001028 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001029 if (format.pixelBytes != colorbufferSize.value())
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +00001030 {
1031 return GL_FRAMEBUFFER_UNSUPPORTED;
1032 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001033 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001034 else
1035 {
1036 colorbufferSize = format.pixelBytes;
1037 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001038 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001039
Martin Radev9bc9a322017-07-21 14:28:17 +03001040 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &colorAttachment))
1041 {
1042 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
1043 }
1044
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001045 hasRenderbuffer = hasRenderbuffer || (colorAttachment.type() == GL_RENDERBUFFER);
1046 hasAttachments = true;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001047 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001048 }
1049
Jamie Madill48ef11b2016-04-27 15:21:52 -04001050 const FramebufferAttachment &depthAttachment = mState.mDepthAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -04001051 if (depthAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001052 {
Geoff Lang9f10b772017-05-16 15:51:03 -04001053 if (!CheckAttachmentCompleteness(context, depthAttachment))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001054 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001055 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001056 }
1057
Geoff Lang677bb6f2017-04-05 12:40:40 -04001058 const InternalFormat &format = *depthAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -04001059 if (format.depthBits == 0)
1060 {
1061 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001062 }
1063
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001064 if (!CheckAttachmentSampleCompleteness(context, depthAttachment, false, &samples,
1065 &fixedSampleLocations))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001066 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001067 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001068 }
Sami Väisänena797e062016-05-12 15:23:40 +03001069
Martin Radev9bc9a322017-07-21 14:28:17 +03001070 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &depthAttachment))
1071 {
1072 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
1073 }
1074
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001075 hasRenderbuffer = hasRenderbuffer || (depthAttachment.type() == GL_RENDERBUFFER);
1076 hasAttachments = true;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001077 }
1078
Jamie Madill48ef11b2016-04-27 15:21:52 -04001079 const FramebufferAttachment &stencilAttachment = mState.mStencilAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -04001080 if (stencilAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001081 {
Geoff Lang9f10b772017-05-16 15:51:03 -04001082 if (!CheckAttachmentCompleteness(context, stencilAttachment))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001083 {
1084 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1085 }
1086
Geoff Lang677bb6f2017-04-05 12:40:40 -04001087 const InternalFormat &format = *stencilAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -04001088 if (format.stencilBits == 0)
1089 {
1090 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001091 }
1092
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001093 if (!CheckAttachmentSampleCompleteness(context, stencilAttachment, false, &samples,
1094 &fixedSampleLocations))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001095 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001096 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001097 }
Corentin Wallez086d59a2016-04-29 09:06:49 -04001098
Martin Radev9bc9a322017-07-21 14:28:17 +03001099 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &stencilAttachment))
1100 {
1101 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
1102 }
1103
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001104 hasRenderbuffer = hasRenderbuffer || (stencilAttachment.type() == GL_RENDERBUFFER);
1105 hasAttachments = true;
1106 }
1107
1108 // Starting from ES 3.0 stencil and depth, if present, should be the same image
1109 if (state.getClientMajorVersion() >= 3 && depthAttachment.isAttached() &&
1110 stencilAttachment.isAttached() && stencilAttachment != depthAttachment)
1111 {
1112 return GL_FRAMEBUFFER_UNSUPPORTED;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001113 }
1114
Jamie Madilla02315b2017-02-23 14:14:47 -05001115 // Special additional validation for WebGL 1 DEPTH/STENCIL/DEPTH_STENCIL.
1116 if (state.isWebGL1())
1117 {
1118 if (!mState.mWebGLDepthStencilConsistent)
1119 {
1120 return GL_FRAMEBUFFER_UNSUPPORTED;
1121 }
1122
1123 if (mState.mWebGLDepthStencilAttachment.isAttached())
1124 {
1125 if (mState.mWebGLDepthStencilAttachment.getDepthSize() == 0 ||
1126 mState.mWebGLDepthStencilAttachment.getStencilSize() == 0)
1127 {
1128 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1129 }
Martin Radev9bc9a322017-07-21 14:28:17 +03001130
1131 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment,
1132 &mState.mWebGLDepthStencilAttachment))
1133 {
1134 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
1135 }
Jamie Madilla02315b2017-02-23 14:14:47 -05001136 }
1137 else if (mState.mStencilAttachment.isAttached() &&
1138 mState.mStencilAttachment.getDepthSize() > 0)
1139 {
1140 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1141 }
1142 else if (mState.mDepthAttachment.isAttached() &&
1143 mState.mDepthAttachment.getStencilSize() > 0)
1144 {
1145 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1146 }
1147 }
1148
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001149 // ES3.1(section 9.4) requires that if no image is attached to the framebuffer, and either the
1150 // value of the framebuffer's FRAMEBUFFER_DEFAULT_WIDTH or FRAMEBUFFER_DEFAULT_HEIGHT parameters
1151 // is zero, the framebuffer is considered incomplete.
JiangYizhou461d9a32017-01-04 16:37:26 +08001152 GLint defaultWidth = mState.getDefaultWidth();
1153 GLint defaultHeight = mState.getDefaultHeight();
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001154 if (!hasAttachments && (defaultWidth == 0 || defaultHeight == 0))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001155 {
1156 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001157 }
1158
Geoff Langa0e0aeb2017-04-12 15:06:29 -04001159 // In ES 2.0 and WebGL, all color attachments must have the same width and height.
Jamie Madillcc86d642015-11-24 13:00:07 -05001160 // In ES 3.0, there is no such restriction.
Geoff Langa0e0aeb2017-04-12 15:06:29 -04001161 if ((state.getClientMajorVersion() < 3 || state.getExtensions().webglCompatibility) &&
1162 !mState.attachmentsHaveSameDimensions())
Jamie Madillcc86d642015-11-24 13:00:07 -05001163 {
1164 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
1165 }
1166
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001167 // ES3.1(section 9.4) requires that if the attached images are a mix of renderbuffers and
1168 // textures, the value of TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all attached textures.
JiangYizhou461d9a32017-01-04 16:37:26 +08001169 if (fixedSampleLocations.valid() && hasRenderbuffer && !fixedSampleLocations.value())
1170 {
1171 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1172 }
1173
Kenneth Russellce8602a2017-10-03 18:23:08 -07001174 // The WebGL conformance tests implicitly define that all framebuffer
1175 // attachments must be unique. For example, the same level of a texture can
1176 // not be attached to two different color attachments.
1177 if (state.getExtensions().webglCompatibility)
1178 {
1179 if (!mState.colorAttachmentsAreUniqueImages())
1180 {
1181 return GL_FRAMEBUFFER_UNSUPPORTED;
1182 }
1183 }
1184
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001185 syncState(context);
Kenneth Russellce8602a2017-10-03 18:23:08 -07001186 if (!mImpl->checkStatus(context))
Jamie Madillcc86d642015-11-24 13:00:07 -05001187 {
1188 return GL_FRAMEBUFFER_UNSUPPORTED;
1189 }
1190
1191 return GL_FRAMEBUFFER_COMPLETE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001192}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001193
Jamie Madill4928b7c2017-06-20 12:57:39 -04001194Error Framebuffer::discard(const Context *context, size_t count, const GLenum *attachments)
Austin Kinross08332632015-05-05 13:35:47 -07001195{
Jamie Madill05b35b22017-10-03 09:01:44 -04001196 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1197 // can be no-ops, so we should probably do that to ensure consistency.
1198 // TODO(jmadill): WebGL behaviour, and robust resource init behaviour without WebGL.
1199
Jamie Madill4928b7c2017-06-20 12:57:39 -04001200 return mImpl->discard(context, count, attachments);
Austin Kinross08332632015-05-05 13:35:47 -07001201}
1202
Jamie Madill4928b7c2017-06-20 12:57:39 -04001203Error Framebuffer::invalidate(const Context *context, size_t count, const GLenum *attachments)
Jamie Madill2d96b9e2014-08-29 15:46:47 -04001204{
Jamie Madill05b35b22017-10-03 09:01:44 -04001205 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1206 // can be no-ops, so we should probably do that to ensure consistency.
1207 // TODO(jmadill): WebGL behaviour, and robust resource init behaviour without WebGL.
1208
Jamie Madill4928b7c2017-06-20 12:57:39 -04001209 return mImpl->invalidate(context, count, attachments);
Jamie Madill2d96b9e2014-08-29 15:46:47 -04001210}
1211
Jamie Madill05b35b22017-10-03 09:01:44 -04001212bool Framebuffer::partialClearNeedsInit(const Context *context,
1213 bool color,
1214 bool depth,
1215 bool stencil)
1216{
1217 const auto &glState = context->getGLState();
1218
1219 if (!glState.isRobustResourceInitEnabled())
1220 {
1221 return false;
1222 }
1223
1224 // Scissors can affect clearing.
1225 // TODO(jmadill): Check for complete scissor overlap.
1226 if (glState.isScissorTestEnabled())
1227 {
1228 return true;
1229 }
1230
1231 // If colors masked, we must clear before we clear. Do a simple check.
1232 // TODO(jmadill): Filter out unused color channels from the test.
1233 if (color)
1234 {
1235 const auto &blend = glState.getBlendState();
1236 if (!(blend.colorMaskRed && blend.colorMaskGreen && blend.colorMaskBlue &&
1237 blend.colorMaskAlpha))
1238 {
1239 return true;
1240 }
1241 }
1242
1243 const auto &depthStencil = glState.getDepthStencilState();
1244 ASSERT(depthStencil.stencilBackMask == depthStencil.stencilMask);
1245 if (stencil && depthStencil.stencilMask != depthStencil.stencilWritemask)
1246 {
1247 return true;
1248 }
1249
1250 return false;
1251}
1252
Jamie Madill4928b7c2017-06-20 12:57:39 -04001253Error Framebuffer::invalidateSub(const Context *context,
1254 size_t count,
1255 const GLenum *attachments,
1256 const gl::Rectangle &area)
Jamie Madill400a4412014-08-29 15:46:45 -04001257{
Jamie Madill05b35b22017-10-03 09:01:44 -04001258 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1259 // can be no-ops, so we should probably do that to ensure consistency.
1260 // TODO(jmadill): Make a invalidate no-op in WebGL 2.0.
1261
Jamie Madill4928b7c2017-06-20 12:57:39 -04001262 return mImpl->invalidateSub(context, count, attachments, area);
Jamie Madill400a4412014-08-29 15:46:45 -04001263}
1264
Jamie Madillc564c072017-06-01 12:45:42 -04001265Error Framebuffer::clear(const gl::Context *context, GLbitfield mask)
Geoff Langb04dc822014-12-01 12:02:02 -05001266{
Jamie Madill05b35b22017-10-03 09:01:44 -04001267 const auto &glState = context->getGLState();
1268 if (glState.isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -05001269 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001270 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001271 }
1272
Jamie Madill05b35b22017-10-03 09:01:44 -04001273 const auto &blend = glState.getBlendState();
1274 const auto &depthStencil = glState.getDepthStencilState();
1275
1276 bool color = (mask & GL_COLOR_BUFFER_BIT) != 0 && !IsColorMaskedOut(blend);
1277 bool depth = (mask & GL_DEPTH_BUFFER_BIT) != 0 && !IsDepthMaskedOut(depthStencil);
1278 bool stencil = (mask & GL_STENCIL_BUFFER_BIT) != 0 && !IsStencilMaskedOut(depthStencil);
1279
1280 if (partialClearNeedsInit(context, color, depth, stencil))
1281 {
1282 ANGLE_TRY(ensureDrawAttachmentsInitialized(context));
1283 }
1284
1285 ANGLE_TRY(mImpl->clear(context, mask));
1286
1287 if (glState.isRobustResourceInitEnabled())
1288 {
1289 markDrawAttachmentsInitialized(color, depth, stencil);
1290 }
1291
1292 return NoError();
Geoff Langb04dc822014-12-01 12:02:02 -05001293}
1294
Jamie Madillc564c072017-06-01 12:45:42 -04001295Error Framebuffer::clearBufferfv(const gl::Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001296 GLenum buffer,
1297 GLint drawbuffer,
1298 const GLfloat *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001299{
Jamie Madill05b35b22017-10-03 09:01:44 -04001300 if (context->getGLState().isRasterizerDiscardEnabled() ||
1301 IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001302 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001303 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001304 }
1305
Jamie Madill05b35b22017-10-03 09:01:44 -04001306 if (partialBufferClearNeedsInit(context, buffer))
1307 {
1308 ANGLE_TRY(ensureBufferInitialized(context, buffer, drawbuffer));
1309 }
1310
1311 ANGLE_TRY(mImpl->clearBufferfv(context, buffer, drawbuffer, values));
1312
1313 if (context->isRobustResourceInitEnabled())
1314 {
1315 markBufferInitialized(buffer, drawbuffer);
1316 }
1317 return NoError();
Geoff Langb04dc822014-12-01 12:02:02 -05001318}
1319
Jamie Madillc564c072017-06-01 12:45:42 -04001320Error Framebuffer::clearBufferuiv(const gl::Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001321 GLenum buffer,
1322 GLint drawbuffer,
1323 const GLuint *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001324{
Jamie Madill05b35b22017-10-03 09:01:44 -04001325 if (context->getGLState().isRasterizerDiscardEnabled() ||
1326 IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001327 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001328 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001329 }
1330
Jamie Madill05b35b22017-10-03 09:01:44 -04001331 if (partialBufferClearNeedsInit(context, buffer))
1332 {
1333 ANGLE_TRY(ensureBufferInitialized(context, buffer, drawbuffer));
1334 }
1335
1336 ANGLE_TRY(mImpl->clearBufferuiv(context, buffer, drawbuffer, values));
1337
1338 if (context->isRobustResourceInitEnabled())
1339 {
1340 markBufferInitialized(buffer, drawbuffer);
1341 }
1342 return NoError();
Geoff Langb04dc822014-12-01 12:02:02 -05001343}
1344
Jamie Madillc564c072017-06-01 12:45:42 -04001345Error Framebuffer::clearBufferiv(const gl::Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001346 GLenum buffer,
1347 GLint drawbuffer,
1348 const GLint *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001349{
Jamie Madill05b35b22017-10-03 09:01:44 -04001350 if (context->getGLState().isRasterizerDiscardEnabled() ||
1351 IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001352 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001353 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001354 }
1355
Jamie Madill05b35b22017-10-03 09:01:44 -04001356 if (partialBufferClearNeedsInit(context, buffer))
1357 {
1358 ANGLE_TRY(ensureBufferInitialized(context, buffer, drawbuffer));
1359 }
1360
1361 ANGLE_TRY(mImpl->clearBufferiv(context, buffer, drawbuffer, values));
1362
1363 if (context->isRobustResourceInitEnabled())
1364 {
1365 markBufferInitialized(buffer, drawbuffer);
1366 }
1367 return NoError();
Geoff Langb04dc822014-12-01 12:02:02 -05001368}
1369
Jamie Madillc564c072017-06-01 12:45:42 -04001370Error Framebuffer::clearBufferfi(const gl::Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001371 GLenum buffer,
1372 GLint drawbuffer,
1373 GLfloat depth,
1374 GLint stencil)
Geoff Langb04dc822014-12-01 12:02:02 -05001375{
Jamie Madill05b35b22017-10-03 09:01:44 -04001376 if (context->getGLState().isRasterizerDiscardEnabled() ||
1377 IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001378 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001379 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001380 }
1381
Jamie Madill05b35b22017-10-03 09:01:44 -04001382 if (partialBufferClearNeedsInit(context, buffer))
1383 {
1384 ANGLE_TRY(ensureBufferInitialized(context, buffer, drawbuffer));
1385 }
1386
1387 ANGLE_TRY(mImpl->clearBufferfi(context, buffer, drawbuffer, depth, stencil));
1388
1389 if (context->isRobustResourceInitEnabled())
1390 {
1391 markBufferInitialized(buffer, drawbuffer);
1392 }
1393 return NoError();
Geoff Langb04dc822014-12-01 12:02:02 -05001394}
1395
Jamie Madill4928b7c2017-06-20 12:57:39 -04001396GLenum Framebuffer::getImplementationColorReadFormat(const Context *context) const
Geoff Langbce529e2014-12-01 12:48:41 -05001397{
Jamie Madill4928b7c2017-06-20 12:57:39 -04001398 return mImpl->getImplementationColorReadFormat(context);
Geoff Langbce529e2014-12-01 12:48:41 -05001399}
1400
Jamie Madill4928b7c2017-06-20 12:57:39 -04001401GLenum Framebuffer::getImplementationColorReadType(const Context *context) const
Geoff Langbce529e2014-12-01 12:48:41 -05001402{
Jamie Madill4928b7c2017-06-20 12:57:39 -04001403 return mImpl->getImplementationColorReadType(context);
Geoff Langbce529e2014-12-01 12:48:41 -05001404}
1405
Jamie Madillc564c072017-06-01 12:45:42 -04001406Error Framebuffer::readPixels(const gl::Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001407 const Rectangle &area,
Jamie Madill1b94d432015-08-07 13:23:23 -04001408 GLenum format,
1409 GLenum type,
Jamie Madill05b35b22017-10-03 09:01:44 -04001410 void *pixels)
Geoff Langbce529e2014-12-01 12:48:41 -05001411{
Jamie Madill05b35b22017-10-03 09:01:44 -04001412 ANGLE_TRY(ensureReadAttachmentInitialized(context, GL_COLOR_BUFFER_BIT));
Jamie Madill362876b2016-06-16 14:46:59 -04001413 ANGLE_TRY(mImpl->readPixels(context, area, format, type, pixels));
Geoff Lang520c4ae2015-05-05 13:12:36 -04001414
Corentin Wallez336129f2017-10-17 15:55:40 -04001415 Buffer *unpackBuffer = context->getGLState().getTargetBuffer(gl::BufferBinding::PixelUnpack);
Geoff Lang520c4ae2015-05-05 13:12:36 -04001416 if (unpackBuffer)
1417 {
1418 unpackBuffer->onPixelUnpack();
1419 }
1420
Jamie Madill362876b2016-06-16 14:46:59 -04001421 return NoError();
Geoff Langbce529e2014-12-01 12:48:41 -05001422}
1423
Jamie Madillc564c072017-06-01 12:45:42 -04001424Error Framebuffer::blit(const gl::Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001425 const Rectangle &sourceArea,
1426 const Rectangle &destArea,
Geoff Lang242468f2015-09-24 14:15:41 -04001427 GLbitfield mask,
Jamie Madill8415b5f2016-04-26 13:41:39 -04001428 GLenum filter)
Geoff Lang54bd5a42014-12-01 12:51:04 -05001429{
He Yunchao6be602d2016-12-22 14:33:07 +08001430 GLbitfield blitMask = mask;
1431
1432 // Note that blitting is called against draw framebuffer.
1433 // See the code in gl::Context::blitFramebuffer.
1434 if ((mask & GL_COLOR_BUFFER_BIT) && !hasEnabledDrawBuffer())
1435 {
1436 blitMask &= ~GL_COLOR_BUFFER_BIT;
1437 }
1438
1439 if ((mask & GL_STENCIL_BUFFER_BIT) && mState.getStencilAttachment() == nullptr)
1440 {
1441 blitMask &= ~GL_STENCIL_BUFFER_BIT;
1442 }
1443
1444 if ((mask & GL_DEPTH_BUFFER_BIT) && mState.getDepthAttachment() == nullptr)
1445 {
1446 blitMask &= ~GL_DEPTH_BUFFER_BIT;
1447 }
1448
1449 if (!blitMask)
1450 {
1451 return NoError();
1452 }
1453
Jamie Madill05b35b22017-10-03 09:01:44 -04001454 auto *sourceFBO = context->getGLState().getReadFramebuffer();
1455 ANGLE_TRY(sourceFBO->ensureReadAttachmentInitialized(context, blitMask));
1456
1457 // TODO(jmadill): Only clear if not the full FBO dimensions, and only specified bitmask.
1458 ANGLE_TRY(ensureDrawAttachmentsInitialized(context));
1459
He Yunchao6be602d2016-12-22 14:33:07 +08001460 return mImpl->blit(context, sourceArea, destArea, blitMask, filter);
Geoff Lang54bd5a42014-12-01 12:51:04 -05001461}
1462
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001463int Framebuffer::getSamples(const Context *context)
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001464{
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001465 if (complete(context))
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001466 {
Jamie Madill9c335862017-07-18 11:51:38 -04001467 return getCachedSamples(context);
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001468 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001469
1470 return 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001471}
1472
Jamie Madill9c335862017-07-18 11:51:38 -04001473int Framebuffer::getCachedSamples(const Context *context)
1474{
1475 // For a complete framebuffer, all attachments must have the same sample count.
1476 // In this case return the first nonzero sample size.
1477 const auto *firstNonNullAttachment = mState.getFirstNonNullAttachment();
1478 if (firstNonNullAttachment)
1479 {
1480 ASSERT(firstNonNullAttachment->isAttached());
1481 return firstNonNullAttachment->getSamples();
1482 }
1483
1484 // No attachments found.
1485 return 0;
1486}
1487
Corentin Wallezccab69d2017-01-27 16:57:15 -05001488Error Framebuffer::getSamplePosition(size_t index, GLfloat *xy) const
1489{
1490 ANGLE_TRY(mImpl->getSamplePosition(index, xy));
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001491 return NoError();
Corentin Wallezccab69d2017-01-27 16:57:15 -05001492}
1493
Jamie Madille261b442014-06-25 12:42:21 -04001494bool Framebuffer::hasValidDepthStencil() const
1495{
Jamie Madill48ef11b2016-04-27 15:21:52 -04001496 return mState.getDepthStencilAttachment() != nullptr;
Jamie Madille261b442014-06-25 12:42:21 -04001497}
1498
Jamie Madilla02315b2017-02-23 14:14:47 -05001499void Framebuffer::setAttachment(const Context *context,
1500 GLenum type,
Jamie Madill2d06b732015-04-20 12:53:28 -04001501 GLenum binding,
1502 const ImageIndex &textureIndex,
1503 FramebufferAttachmentObject *resource)
Geoff Langab75a052014-10-15 12:56:37 -04001504{
Martin Radev5dae57b2017-07-14 16:15:55 +03001505 setAttachment(context, type, binding, textureIndex, resource,
1506 FramebufferAttachment::kDefaultNumViews,
1507 FramebufferAttachment::kDefaultBaseViewIndex,
1508 FramebufferAttachment::kDefaultMultiviewLayout,
1509 FramebufferAttachment::kDefaultViewportOffsets);
1510}
1511
1512void Framebuffer::setAttachment(const Context *context,
1513 GLenum type,
1514 GLenum binding,
1515 const ImageIndex &textureIndex,
1516 FramebufferAttachmentObject *resource,
1517 GLsizei numViews,
1518 GLuint baseViewIndex,
1519 GLenum multiviewLayout,
1520 const GLint *viewportOffsets)
1521{
Jamie Madilla02315b2017-02-23 14:14:47 -05001522 // Context may be null in unit tests.
1523 if (!context || !context->isWebGL1())
1524 {
Martin Radev5dae57b2017-07-14 16:15:55 +03001525 setAttachmentImpl(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
1526 multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001527 return;
1528 }
1529
1530 switch (binding)
1531 {
1532 case GL_DEPTH_STENCIL:
1533 case GL_DEPTH_STENCIL_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001534 mState.mWebGLDepthStencilAttachment.attach(context, type, binding, textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001535 resource, numViews, baseViewIndex,
1536 multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001537 break;
1538 case GL_DEPTH:
1539 case GL_DEPTH_ATTACHMENT:
Martin Radev5dae57b2017-07-14 16:15:55 +03001540 mState.mWebGLDepthAttachment.attach(context, type, binding, textureIndex, resource,
1541 numViews, baseViewIndex, multiviewLayout,
1542 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001543 break;
1544 case GL_STENCIL:
1545 case GL_STENCIL_ATTACHMENT:
Martin Radev5dae57b2017-07-14 16:15:55 +03001546 mState.mWebGLStencilAttachment.attach(context, type, binding, textureIndex, resource,
1547 numViews, baseViewIndex, multiviewLayout,
1548 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001549 break;
1550 default:
Martin Radev5dae57b2017-07-14 16:15:55 +03001551 setAttachmentImpl(context, type, binding, textureIndex, resource, numViews,
1552 baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001553 return;
1554 }
1555
Martin Radev5dae57b2017-07-14 16:15:55 +03001556 commitWebGL1DepthStencilIfConsistent(context, numViews, baseViewIndex, multiviewLayout,
1557 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001558}
1559
Martin Radev82ef7742017-08-08 17:44:58 +03001560void Framebuffer::setAttachmentMultiviewLayered(const Context *context,
1561 GLenum type,
1562 GLenum binding,
1563 const ImageIndex &textureIndex,
1564 FramebufferAttachmentObject *resource,
1565 GLsizei numViews,
1566 GLint baseViewIndex)
1567{
1568 setAttachment(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
1569 GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE,
1570 FramebufferAttachment::kDefaultViewportOffsets);
1571}
1572
Martin Radev5dae57b2017-07-14 16:15:55 +03001573void Framebuffer::setAttachmentMultiviewSideBySide(const Context *context,
1574 GLenum type,
1575 GLenum binding,
1576 const ImageIndex &textureIndex,
1577 FramebufferAttachmentObject *resource,
1578 GLsizei numViews,
1579 const GLint *viewportOffsets)
1580{
1581 setAttachment(context, type, binding, textureIndex, resource, numViews,
1582 FramebufferAttachment::kDefaultBaseViewIndex,
1583 GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, viewportOffsets);
1584}
1585
1586void Framebuffer::commitWebGL1DepthStencilIfConsistent(const Context *context,
1587 GLsizei numViews,
1588 GLuint baseViewIndex,
1589 GLenum multiviewLayout,
1590 const GLint *viewportOffsets)
Jamie Madilla02315b2017-02-23 14:14:47 -05001591{
1592 int count = 0;
1593
1594 std::array<FramebufferAttachment *, 3> attachments = {{&mState.mWebGLDepthStencilAttachment,
1595 &mState.mWebGLDepthAttachment,
1596 &mState.mWebGLStencilAttachment}};
1597 for (FramebufferAttachment *attachment : attachments)
1598 {
1599 if (attachment->isAttached())
1600 {
1601 count++;
1602 }
1603 }
1604
1605 mState.mWebGLDepthStencilConsistent = (count <= 1);
1606 if (!mState.mWebGLDepthStencilConsistent)
1607 {
1608 // Inconsistent.
1609 return;
1610 }
1611
Geoff Lange466c552017-03-17 15:24:12 -04001612 auto getImageIndexIfTextureAttachment = [](const FramebufferAttachment &attachment) {
1613 if (attachment.type() == GL_TEXTURE)
1614 {
1615 return attachment.getTextureImageIndex();
1616 }
1617 else
1618 {
1619 return ImageIndex::MakeInvalid();
1620 }
1621 };
1622
Jamie Madilla02315b2017-02-23 14:14:47 -05001623 if (mState.mWebGLDepthAttachment.isAttached())
1624 {
1625 const auto &depth = mState.mWebGLDepthAttachment;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001626 setAttachmentImpl(context, depth.type(), GL_DEPTH_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001627 getImageIndexIfTextureAttachment(depth), depth.getResource(), numViews,
1628 baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001629 setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex::MakeInvalid(),
Martin Radev5dae57b2017-07-14 16:15:55 +03001630 nullptr, numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001631 }
1632 else if (mState.mWebGLStencilAttachment.isAttached())
1633 {
1634 const auto &stencil = mState.mWebGLStencilAttachment;
Martin Radev5dae57b2017-07-14 16:15:55 +03001635 setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex::MakeInvalid(), nullptr,
1636 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001637 setAttachmentImpl(context, stencil.type(), GL_STENCIL_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001638 getImageIndexIfTextureAttachment(stencil), stencil.getResource(),
1639 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001640 }
1641 else if (mState.mWebGLDepthStencilAttachment.isAttached())
1642 {
1643 const auto &depthStencil = mState.mWebGLDepthStencilAttachment;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001644 setAttachmentImpl(context, depthStencil.type(), GL_DEPTH_ATTACHMENT,
Geoff Lange466c552017-03-17 15:24:12 -04001645 getImageIndexIfTextureAttachment(depthStencil),
Martin Radev5dae57b2017-07-14 16:15:55 +03001646 depthStencil.getResource(), numViews, baseViewIndex, multiviewLayout,
1647 viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001648 setAttachmentImpl(context, depthStencil.type(), GL_STENCIL_ATTACHMENT,
Geoff Lange466c552017-03-17 15:24:12 -04001649 getImageIndexIfTextureAttachment(depthStencil),
Martin Radev5dae57b2017-07-14 16:15:55 +03001650 depthStencil.getResource(), numViews, baseViewIndex, multiviewLayout,
1651 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001652 }
1653 else
1654 {
Martin Radev5dae57b2017-07-14 16:15:55 +03001655 setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex::MakeInvalid(), nullptr,
1656 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001657 setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex::MakeInvalid(),
Martin Radev5dae57b2017-07-14 16:15:55 +03001658 nullptr, numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001659 }
1660}
1661
Jamie Madill4928b7c2017-06-20 12:57:39 -04001662void Framebuffer::setAttachmentImpl(const Context *context,
1663 GLenum type,
Jamie Madilla02315b2017-02-23 14:14:47 -05001664 GLenum binding,
1665 const ImageIndex &textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001666 FramebufferAttachmentObject *resource,
1667 GLsizei numViews,
1668 GLuint baseViewIndex,
1669 GLenum multiviewLayout,
1670 const GLint *viewportOffsets)
Jamie Madilla02315b2017-02-23 14:14:47 -05001671{
Jamie Madilla02315b2017-02-23 14:14:47 -05001672 switch (binding)
1673 {
Jamie Madillb8126692017-04-05 11:22:17 -04001674 case GL_DEPTH_STENCIL:
1675 case GL_DEPTH_STENCIL_ATTACHMENT:
1676 {
1677 // ensure this is a legitimate depth+stencil format
1678 FramebufferAttachmentObject *attachmentObj = resource;
1679 if (resource)
1680 {
Jamie Madill4fd95d52017-04-05 11:22:18 -04001681 const Format &format = resource->getAttachmentFormat(binding, textureIndex);
Jamie Madillb8126692017-04-05 11:22:17 -04001682 if (format.info->depthBits == 0 || format.info->stencilBits == 0)
1683 {
1684 // Attaching nullptr detaches the current attachment.
1685 attachmentObj = nullptr;
1686 }
1687 }
1688
Jamie Madill4928b7c2017-06-20 12:57:39 -04001689 updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
Jamie Madillb8126692017-04-05 11:22:17 -04001690 &mDirtyDepthAttachmentBinding, type, binding, textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001691 attachmentObj, numViews, baseViewIndex, multiviewLayout,
1692 viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001693 updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
Jamie Madillb8126692017-04-05 11:22:17 -04001694 &mDirtyStencilAttachmentBinding, type, binding, textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001695 attachmentObj, numViews, baseViewIndex, multiviewLayout,
1696 viewportOffsets);
Jamie Madill42975642017-10-12 12:31:51 -04001697 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001698 }
1699
Jamie Madilla02315b2017-02-23 14:14:47 -05001700 case GL_DEPTH:
1701 case GL_DEPTH_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001702 updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001703 &mDirtyDepthAttachmentBinding, type, binding, textureIndex, resource,
1704 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madill2d06b732015-04-20 12:53:28 -04001705 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001706
Jamie Madilla02315b2017-02-23 14:14:47 -05001707 case GL_STENCIL:
1708 case GL_STENCIL_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001709 updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001710 &mDirtyStencilAttachmentBinding, type, binding, textureIndex, resource,
1711 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001712 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001713
Jamie Madilla02315b2017-02-23 14:14:47 -05001714 case GL_BACK:
Martin Radev5dae57b2017-07-14 16:15:55 +03001715 mState.mColorAttachments[0].attach(context, type, binding, textureIndex, resource,
1716 numViews, baseViewIndex, multiviewLayout,
1717 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001718 mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0);
1719 // No need for a resource binding for the default FBO, it's always complete.
1720 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001721
Jamie Madilla02315b2017-02-23 14:14:47 -05001722 default:
1723 {
1724 size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
1725 ASSERT(colorIndex < mState.mColorAttachments.size());
Jamie Madillb8126692017-04-05 11:22:17 -04001726 size_t dirtyBit = DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001727 updateAttachment(context, &mState.mColorAttachments[colorIndex], dirtyBit,
Jamie Madillb8126692017-04-05 11:22:17 -04001728 &mDirtyColorAttachmentBindings[colorIndex], type, binding,
Martin Radev5dae57b2017-07-14 16:15:55 +03001729 textureIndex, resource, numViews, baseViewIndex, multiviewLayout,
1730 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001731
Corentin Walleze7557742017-06-01 13:09:57 -04001732 // TODO(jmadill): ASSERT instead of checking the attachment exists in
1733 // formsRenderingFeedbackLoopWith
Jamie Madilla02315b2017-02-23 14:14:47 -05001734 bool enabled = (type != GL_NONE && getDrawBufferState(colorIndex) != GL_NONE);
1735 mState.mEnabledDrawBuffers.set(colorIndex, enabled);
Brandon Jones76746f92017-11-22 11:44:41 -08001736 mState.mDrawBufferTypeMask.setIndex(getDrawbufferWriteType(colorIndex), colorIndex);
Jamie Madill2d06b732015-04-20 12:53:28 -04001737 }
Jamie Madilla02315b2017-02-23 14:14:47 -05001738 break;
Geoff Langab75a052014-10-15 12:56:37 -04001739 }
Jamie Madill42975642017-10-12 12:31:51 -04001740
1741 mAttachedTextures.reset();
Geoff Langab75a052014-10-15 12:56:37 -04001742}
1743
Jamie Madill4928b7c2017-06-20 12:57:39 -04001744void Framebuffer::updateAttachment(const Context *context,
1745 FramebufferAttachment *attachment,
Jamie Madillb8126692017-04-05 11:22:17 -04001746 size_t dirtyBit,
1747 OnAttachmentDirtyBinding *onDirtyBinding,
1748 GLenum type,
1749 GLenum binding,
1750 const ImageIndex &textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001751 FramebufferAttachmentObject *resource,
1752 GLsizei numViews,
1753 GLuint baseViewIndex,
1754 GLenum multiviewLayout,
1755 const GLint *viewportOffsets)
Jamie Madillb8126692017-04-05 11:22:17 -04001756{
Martin Radev5dae57b2017-07-14 16:15:55 +03001757 attachment->attach(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
1758 multiviewLayout, viewportOffsets);
Jamie Madillb8126692017-04-05 11:22:17 -04001759 mDirtyBits.set(dirtyBit);
Jamie Madill05b35b22017-10-03 09:01:44 -04001760 mState.mResourceNeedsInit.set(dirtyBit, attachment->initState() == InitState::MayNeedInit);
Jamie Madillb8126692017-04-05 11:22:17 -04001761 BindResourceChannel(onDirtyBinding, resource);
1762}
1763
Jamie Madilla02315b2017-02-23 14:14:47 -05001764void Framebuffer::resetAttachment(const Context *context, GLenum binding)
Jamie Madill2d06b732015-04-20 12:53:28 -04001765{
Jamie Madilla02315b2017-02-23 14:14:47 -05001766 setAttachment(context, GL_NONE, binding, ImageIndex::MakeInvalid(), nullptr);
Jamie Madill2d06b732015-04-20 12:53:28 -04001767}
1768
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001769void Framebuffer::syncState(const Context *context)
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001770{
1771 if (mDirtyBits.any())
1772 {
Jamie Madillc564c072017-06-01 12:45:42 -04001773 mImpl->syncState(context, mDirtyBits);
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001774 mDirtyBits.reset();
Corentin Wallezccab69d2017-01-27 16:57:15 -05001775 if (mId != 0)
1776 {
1777 mCachedStatus.reset();
1778 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001779 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001780}
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001781
Jamie Madill05b35b22017-10-03 09:01:44 -04001782void Framebuffer::signal(size_t dirtyBit, InitState state)
Jamie Madill51f40ec2016-06-15 14:06:00 -04001783{
Jamie Madill362876b2016-06-16 14:46:59 -04001784 // TOOD(jmadill): Make this only update individual attachments to do less work.
1785 mCachedStatus.reset();
Jamie Madill05b35b22017-10-03 09:01:44 -04001786
1787 // Mark the appropriate init flag.
1788 mState.mResourceNeedsInit.set(dirtyBit, state == InitState::MayNeedInit);
Jamie Madill51f40ec2016-06-15 14:06:00 -04001789}
1790
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001791bool Framebuffer::complete(const Context *context)
Jamie Madill51f40ec2016-06-15 14:06:00 -04001792{
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001793 return (checkStatus(context) == GL_FRAMEBUFFER_COMPLETE);
1794}
1795
1796bool Framebuffer::cachedComplete() const
1797{
1798 return (mCachedStatus.valid() && mCachedStatus == GL_FRAMEBUFFER_COMPLETE);
Jamie Madill51f40ec2016-06-15 14:06:00 -04001799}
1800
Jamie Madilla4595b82017-01-11 17:36:34 -05001801bool Framebuffer::formsRenderingFeedbackLoopWith(const State &state) const
1802{
1803 const Program *program = state.getProgram();
1804
1805 // TODO(jmadill): Default framebuffer feedback loops.
1806 if (mId == 0)
1807 {
1808 return false;
1809 }
1810
1811 // The bitset will skip inactive draw buffers.
Jamie Madill6de51852017-04-12 09:53:01 -04001812 for (size_t drawIndex : mState.mEnabledDrawBuffers)
Jamie Madilla4595b82017-01-11 17:36:34 -05001813 {
Jamie Madill5aca1932017-07-21 12:22:01 -04001814 const FramebufferAttachment &attachment = mState.mColorAttachments[drawIndex];
1815 ASSERT(attachment.isAttached());
1816 if (attachment.type() == GL_TEXTURE)
Jamie Madilla4595b82017-01-11 17:36:34 -05001817 {
1818 // Validate the feedback loop.
Jamie Madill5aca1932017-07-21 12:22:01 -04001819 if (program->samplesFromTexture(state, attachment.id()))
Jamie Madilla4595b82017-01-11 17:36:34 -05001820 {
1821 return true;
1822 }
1823 }
1824 }
1825
Jamie Madill1d37bc52017-02-02 19:59:58 -05001826 // Validate depth-stencil feedback loop.
1827 const auto &dsState = state.getDepthStencilState();
1828
1829 // We can skip the feedback loop checks if depth/stencil is masked out or disabled.
1830 const FramebufferAttachment *depth = getDepthbuffer();
1831 if (depth && depth->type() == GL_TEXTURE && dsState.depthTest && dsState.depthMask)
1832 {
1833 if (program->samplesFromTexture(state, depth->id()))
1834 {
1835 return true;
1836 }
1837 }
1838
1839 // Note: we assume the front and back masks are the same for WebGL.
1840 const FramebufferAttachment *stencil = getStencilbuffer();
1841 ASSERT(dsState.stencilBackWritemask == dsState.stencilWritemask);
1842 if (stencil && stencil->type() == GL_TEXTURE && dsState.stencilTest &&
1843 dsState.stencilWritemask != 0)
1844 {
1845 // Skip the feedback loop check if depth/stencil point to the same resource.
1846 if (!depth || *stencil != *depth)
1847 {
1848 if (program->samplesFromTexture(state, stencil->id()))
1849 {
1850 return true;
1851 }
1852 }
1853 }
1854
Jamie Madilla4595b82017-01-11 17:36:34 -05001855 return false;
1856}
1857
Jamie Madillfd3dd432017-02-02 19:59:59 -05001858bool Framebuffer::formsCopyingFeedbackLoopWith(GLuint copyTextureID,
1859 GLint copyTextureLevel,
1860 GLint copyTextureLayer) const
Jamie Madillf695a3a2017-01-11 17:36:35 -05001861{
1862 if (mId == 0)
1863 {
1864 // It seems impossible to form a texture copying feedback loop with the default FBO.
1865 return false;
1866 }
1867
1868 const FramebufferAttachment *readAttachment = getReadColorbuffer();
1869 ASSERT(readAttachment);
1870
1871 if (readAttachment->isTextureWithId(copyTextureID))
1872 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05001873 const auto &imageIndex = readAttachment->getTextureImageIndex();
1874 if (imageIndex.mipIndex == copyTextureLevel)
Jamie Madillf695a3a2017-01-11 17:36:35 -05001875 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05001876 // Check 3D/Array texture layers.
1877 return imageIndex.layerIndex == ImageIndex::ENTIRE_LEVEL ||
1878 copyTextureLayer == ImageIndex::ENTIRE_LEVEL ||
1879 imageIndex.layerIndex == copyTextureLayer;
Jamie Madillf695a3a2017-01-11 17:36:35 -05001880 }
1881 }
1882 return false;
1883}
1884
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001885GLint Framebuffer::getDefaultWidth() const
1886{
1887 return mState.getDefaultWidth();
1888}
1889
1890GLint Framebuffer::getDefaultHeight() const
1891{
1892 return mState.getDefaultHeight();
1893}
1894
1895GLint Framebuffer::getDefaultSamples() const
1896{
1897 return mState.getDefaultSamples();
1898}
1899
Geoff Lang92019432017-11-20 13:09:34 -05001900bool Framebuffer::getDefaultFixedSampleLocations() const
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001901{
1902 return mState.getDefaultFixedSampleLocations();
1903}
1904
1905void Framebuffer::setDefaultWidth(GLint defaultWidth)
1906{
1907 mState.mDefaultWidth = defaultWidth;
1908 mDirtyBits.set(DIRTY_BIT_DEFAULT_WIDTH);
1909}
1910
1911void Framebuffer::setDefaultHeight(GLint defaultHeight)
1912{
1913 mState.mDefaultHeight = defaultHeight;
1914 mDirtyBits.set(DIRTY_BIT_DEFAULT_HEIGHT);
1915}
1916
1917void Framebuffer::setDefaultSamples(GLint defaultSamples)
1918{
1919 mState.mDefaultSamples = defaultSamples;
1920 mDirtyBits.set(DIRTY_BIT_DEFAULT_SAMPLES);
1921}
1922
Geoff Lang92019432017-11-20 13:09:34 -05001923void Framebuffer::setDefaultFixedSampleLocations(bool defaultFixedSampleLocations)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001924{
1925 mState.mDefaultFixedSampleLocations = defaultFixedSampleLocations;
1926 mDirtyBits.set(DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS);
1927}
1928
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001929// TODO(jmadill): Remove this kludge.
1930GLenum Framebuffer::checkStatus(const ValidationContext *context)
1931{
1932 return checkStatus(static_cast<const Context *>(context));
1933}
1934
1935int Framebuffer::getSamples(const ValidationContext *context)
1936{
1937 return getSamples(static_cast<const Context *>(context));
1938}
1939
Martin Radev14a26ae2017-07-24 15:56:29 +03001940GLsizei Framebuffer::getNumViews() const
1941{
Martin Radev5c00d0d2017-08-07 10:06:59 +03001942 return mState.getNumViews();
Martin Radev14a26ae2017-07-24 15:56:29 +03001943}
1944
Martin Radev4e619f52017-08-09 11:50:06 +03001945GLint Framebuffer::getBaseViewIndex() const
1946{
1947 return mState.getBaseViewIndex();
1948}
1949
Martin Radev878c8b12017-07-28 09:51:04 +03001950const std::vector<Offset> *Framebuffer::getViewportOffsets() const
1951{
Martin Radev5c00d0d2017-08-07 10:06:59 +03001952 return mState.getViewportOffsets();
Martin Radev878c8b12017-07-28 09:51:04 +03001953}
1954
1955GLenum Framebuffer::getMultiviewLayout() const
1956{
Martin Radev5c00d0d2017-08-07 10:06:59 +03001957 return mState.getMultiviewLayout();
Martin Radev878c8b12017-07-28 09:51:04 +03001958}
1959
Jamie Madill05b35b22017-10-03 09:01:44 -04001960Error Framebuffer::ensureDrawAttachmentsInitialized(const Context *context)
1961{
1962 if (!context->isRobustResourceInitEnabled())
1963 {
1964 return NoError();
1965 }
1966
1967 // Note: we don't actually filter by the draw attachment enum. Just init everything.
1968 for (size_t bit : mState.mResourceNeedsInit)
1969 {
1970 switch (bit)
1971 {
1972 case DIRTY_BIT_DEPTH_ATTACHMENT:
1973 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
1974 break;
1975 case DIRTY_BIT_STENCIL_ATTACHMENT:
1976 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
1977 break;
1978 default:
1979 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[bit]));
1980 break;
1981 }
1982 }
1983
1984 mState.mResourceNeedsInit.reset();
1985 return NoError();
1986}
1987
1988Error Framebuffer::ensureReadAttachmentInitialized(const Context *context, GLbitfield blitMask)
1989{
1990 if (!context->isRobustResourceInitEnabled() || mState.mResourceNeedsInit.none())
1991 {
1992 return NoError();
1993 }
1994
1995 if ((blitMask & GL_COLOR_BUFFER_BIT) != 0 && mState.mReadBufferState != GL_NONE)
1996 {
1997 size_t readIndex = mState.getReadIndex();
1998 if (mState.mResourceNeedsInit[readIndex])
1999 {
2000 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[readIndex]));
2001 mState.mResourceNeedsInit.reset(readIndex);
2002 }
2003 }
2004
2005 if ((blitMask & GL_DEPTH_BUFFER_BIT) != 0 && hasDepth())
2006 {
2007 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2008 {
2009 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2010 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2011 }
2012 }
2013
2014 if ((blitMask & GL_STENCIL_BUFFER_BIT) != 0 && hasStencil())
2015 {
2016 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2017 {
2018 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2019 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2020 }
2021 }
2022
2023 return NoError();
2024}
2025
2026void Framebuffer::markDrawAttachmentsInitialized(bool color, bool depth, bool stencil)
2027{
2028 // Mark attachments as initialized.
2029 if (color)
2030 {
2031 for (auto colorIndex : mState.mEnabledDrawBuffers)
2032 {
2033 auto &colorAttachment = mState.mColorAttachments[colorIndex];
2034 ASSERT(colorAttachment.isAttached());
2035 colorAttachment.setInitState(InitState::Initialized);
2036 mState.mResourceNeedsInit.reset(colorIndex);
2037 }
2038 }
2039
2040 if (depth && mState.mDepthAttachment.isAttached())
2041 {
2042 mState.mDepthAttachment.setInitState(InitState::Initialized);
2043 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2044 }
2045
2046 if (stencil && mState.mStencilAttachment.isAttached())
2047 {
2048 mState.mStencilAttachment.setInitState(InitState::Initialized);
2049 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2050 }
2051}
2052
2053void Framebuffer::markBufferInitialized(GLenum bufferType, GLint bufferIndex)
2054{
2055 switch (bufferType)
2056 {
2057 case GL_COLOR:
2058 {
2059 ASSERT(bufferIndex < static_cast<GLint>(mState.mColorAttachments.size()));
2060 if (mState.mColorAttachments[bufferIndex].isAttached())
2061 {
2062 mState.mColorAttachments[bufferIndex].setInitState(InitState::Initialized);
2063 mState.mResourceNeedsInit.reset(bufferIndex);
2064 }
2065 break;
2066 }
2067 case GL_DEPTH:
2068 {
2069 if (mState.mDepthAttachment.isAttached())
2070 {
2071 mState.mDepthAttachment.setInitState(InitState::Initialized);
2072 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2073 }
2074 break;
2075 }
2076 case GL_STENCIL:
2077 {
2078 if (mState.mStencilAttachment.isAttached())
2079 {
2080 mState.mStencilAttachment.setInitState(InitState::Initialized);
2081 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2082 }
2083 break;
2084 }
2085 case GL_DEPTH_STENCIL:
2086 {
2087 if (mState.mDepthAttachment.isAttached())
2088 {
2089 mState.mDepthAttachment.setInitState(InitState::Initialized);
2090 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2091 }
2092 if (mState.mStencilAttachment.isAttached())
2093 {
2094 mState.mStencilAttachment.setInitState(InitState::Initialized);
2095 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2096 }
2097 break;
2098 }
2099 default:
2100 UNREACHABLE();
2101 break;
2102 }
2103}
2104
2105Box Framebuffer::getDimensions() const
2106{
2107 return mState.getDimensions();
2108}
2109
2110Error Framebuffer::ensureBufferInitialized(const Context *context,
2111 GLenum bufferType,
2112 GLint bufferIndex)
2113{
2114 ASSERT(context->isRobustResourceInitEnabled());
2115
2116 if (mState.mResourceNeedsInit.none())
2117 {
2118 return NoError();
2119 }
2120
2121 switch (bufferType)
2122 {
2123 case GL_COLOR:
2124 {
2125 ASSERT(bufferIndex < static_cast<GLint>(mState.mColorAttachments.size()));
2126 if (mState.mResourceNeedsInit[bufferIndex])
2127 {
2128 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[bufferIndex]));
2129 mState.mResourceNeedsInit.reset(bufferIndex);
2130 }
2131 break;
2132 }
2133 case GL_DEPTH:
2134 {
2135 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2136 {
2137 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2138 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2139 }
2140 break;
2141 }
2142 case GL_STENCIL:
2143 {
2144 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2145 {
2146 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2147 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2148 }
2149 break;
2150 }
2151 case GL_DEPTH_STENCIL:
2152 {
2153 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2154 {
2155 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2156 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2157 }
2158 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2159 {
2160 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2161 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2162 }
2163 break;
2164 }
2165 default:
2166 UNREACHABLE();
2167 break;
2168 }
2169
2170 return NoError();
2171}
2172
2173bool Framebuffer::partialBufferClearNeedsInit(const Context *context, GLenum bufferType)
2174{
2175 if (!context->isRobustResourceInitEnabled() || mState.mResourceNeedsInit.none())
2176 {
2177 return false;
2178 }
2179
2180 switch (bufferType)
2181 {
2182 case GL_COLOR:
2183 return partialClearNeedsInit(context, true, false, false);
2184 case GL_DEPTH:
2185 return partialClearNeedsInit(context, false, true, false);
2186 case GL_STENCIL:
2187 return partialClearNeedsInit(context, false, false, true);
2188 case GL_DEPTH_STENCIL:
2189 return partialClearNeedsInit(context, false, true, true);
2190 default:
2191 UNREACHABLE();
2192 return false;
2193 }
2194}
2195
Jamie Madill42975642017-10-12 12:31:51 -04002196bool Framebuffer::hasTextureAttachment(const Texture *texture) const
2197{
2198 if (!mAttachedTextures.valid())
2199 {
2200 std::set<const FramebufferAttachmentObject *> attachedTextures;
2201
2202 for (const auto &colorAttachment : mState.mColorAttachments)
2203 {
2204 if (colorAttachment.isAttached() && colorAttachment.type() == GL_TEXTURE)
2205 {
2206 attachedTextures.insert(colorAttachment.getResource());
2207 }
2208 }
2209
2210 if (mState.mDepthAttachment.isAttached() && mState.mDepthAttachment.type() == GL_TEXTURE)
2211 {
2212 attachedTextures.insert(mState.mDepthAttachment.getResource());
2213 }
2214
2215 if (mState.mStencilAttachment.isAttached() &&
2216 mState.mStencilAttachment.type() == GL_TEXTURE)
2217 {
2218 attachedTextures.insert(mState.mStencilAttachment.getResource());
2219 }
2220
2221 mAttachedTextures = std::move(attachedTextures);
2222 }
2223
2224 return (mAttachedTextures.value().count(texture) > 0);
2225}
2226
Jamie Madill60ec6ea2016-01-22 15:27:19 -05002227} // namespace gl