blob: d2291102eeca2faa5bf78e70c82adc73efd5c3b1 [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
Martin Radev9bc9a322017-07-21 14:28:17 +030038bool CheckMultiviewStateMatchesForCompleteness(const FramebufferAttachment *firstAttachment,
39 const FramebufferAttachment *secondAttachment)
40{
41 ASSERT(firstAttachment && secondAttachment);
42 ASSERT(firstAttachment->isAttached() && secondAttachment->isAttached());
43
44 if (firstAttachment->getNumViews() != secondAttachment->getNumViews())
45 {
46 return false;
47 }
48 if (firstAttachment->getBaseViewIndex() != secondAttachment->getBaseViewIndex())
49 {
50 return false;
51 }
52 if (firstAttachment->getMultiviewLayout() != secondAttachment->getMultiviewLayout())
53 {
54 return false;
55 }
56 if (firstAttachment->getMultiviewViewportOffsets() !=
57 secondAttachment->getMultiviewViewportOffsets())
58 {
59 return false;
60 }
61 return true;
62}
63
Geoff Lang9f10b772017-05-16 15:51:03 -040064bool CheckAttachmentCompleteness(const Context *context, const FramebufferAttachment &attachment)
65{
66 ASSERT(attachment.isAttached());
67
68 const Extents &size = attachment.getSize();
69 if (size.width == 0 || size.height == 0)
70 {
71 return false;
72 }
73
74 const InternalFormat &format = *attachment.getFormat().info;
75 if (!format.renderSupport(context->getClientVersion(), context->getExtensions()))
76 {
77 return false;
78 }
79
80 if (attachment.type() == GL_TEXTURE)
81 {
82 if (attachment.layer() >= size.depth)
83 {
84 return false;
85 }
86
87 // ES3 specifies that cube map texture attachments must be cube complete.
88 // This language is missing from the ES2 spec, but we enforce it here because some
89 // desktop OpenGL drivers also enforce this validation.
90 // TODO(jmadill): Check if OpenGL ES2 drivers enforce cube completeness.
91 const Texture *texture = attachment.getTexture();
92 ASSERT(texture);
Corentin Wallez99d492c2018-02-27 15:17:10 -050093 if (texture->getType() == TextureType::CubeMap &&
Geoff Lang9f10b772017-05-16 15:51:03 -040094 !texture->getTextureState().isCubeComplete())
95 {
96 return false;
97 }
Geoff Lang857c09d2017-05-16 15:55:04 -040098
99 if (!texture->getImmutableFormat())
100 {
101 GLuint attachmentMipLevel = static_cast<GLuint>(attachment.mipLevel());
102
103 // From the ES 3.0 spec, pg 213:
104 // If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is TEXTURE and the value of
105 // FRAMEBUFFER_ATTACHMENT_OBJECT_NAME does not name an immutable-format texture,
106 // then the value of FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL must be in the
107 // range[levelbase, q], where levelbase is the value of TEXTURE_BASE_LEVEL and q is
108 // the effective maximum texture level defined in the Mipmapping discussion of
109 // section 3.8.10.4.
110 if (attachmentMipLevel < texture->getBaseLevel() ||
111 attachmentMipLevel > texture->getMipmapMaxLevel())
112 {
113 return false;
114 }
115
116 // Form the ES 3.0 spec, pg 213/214:
117 // If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is TEXTURE and the value of
118 // FRAMEBUFFER_ATTACHMENT_OBJECT_NAME does not name an immutable-format texture and
119 // the value of FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL is not levelbase, then the
120 // texture must be mipmap complete, and if FRAMEBUFFER_ATTACHMENT_OBJECT_NAME names
121 // a cubemap texture, the texture must also be cube complete.
122 if (attachmentMipLevel != texture->getBaseLevel() && !texture->isMipmapComplete())
123 {
124 return false;
125 }
126 }
Geoff Lang9f10b772017-05-16 15:51:03 -0400127 }
128
129 return true;
130};
131
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400132bool CheckAttachmentSampleCompleteness(const Context *context,
133 const FramebufferAttachment &attachment,
134 bool colorAttachment,
135 Optional<int> *samples,
Geoff Lang92019432017-11-20 13:09:34 -0500136 Optional<bool> *fixedSampleLocations)
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400137{
138 ASSERT(attachment.isAttached());
139
140 if (attachment.type() == GL_TEXTURE)
141 {
142 const Texture *texture = attachment.getTexture();
143 ASSERT(texture);
144
145 const ImageIndex &attachmentImageIndex = attachment.getTextureImageIndex();
146
147 // ES3.1 (section 9.4) requires that the value of TEXTURE_FIXED_SAMPLE_LOCATIONS should be
148 // the same for all attached textures.
Geoff Langb52fac02018-02-21 15:45:35 -0500149 bool fixedSampleloc = texture->getFixedSampleLocations(attachmentImageIndex.target,
Geoff Lang92019432017-11-20 13:09:34 -0500150 attachmentImageIndex.mipIndex);
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400151 if (fixedSampleLocations->valid() && fixedSampleloc != fixedSampleLocations->value())
152 {
153 return false;
154 }
155 else
156 {
157 *fixedSampleLocations = fixedSampleloc;
158 }
159 }
160
161 if (samples->valid())
162 {
163 if (attachment.getSamples() != samples->value())
164 {
165 if (colorAttachment)
166 {
167 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
168 // all color attachments have the same number of samples for the FBO to be complete.
169 return false;
170 }
171 else
172 {
173 // CHROMIUM_framebuffer_mixed_samples allows a framebuffer to be considered complete
174 // when its depth or stencil samples are a multiple of the number of color samples.
175 if (!context->getExtensions().framebufferMixedSamples)
176 {
177 return false;
178 }
179
180 if ((attachment.getSamples() % std::max(samples->value(), 1)) != 0)
181 {
182 return false;
183 }
184 }
185 }
186 }
187 else
188 {
189 *samples = attachment.getSamples();
190 }
191
192 return true;
193}
194
Jamie Madill05b35b22017-10-03 09:01:44 -0400195// Needed to index into the attachment arrays/bitsets.
Jamie Madill682efdc2017-10-03 14:10:29 -0400196static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS) ==
Jamie Madilld4442552018-02-27 22:03:47 -0500197 Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX,
Jamie Madill05b35b22017-10-03 09:01:44 -0400198 "Framebuffer Dirty bit mismatch");
Jamie Madill682efdc2017-10-03 14:10:29 -0400199static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS) ==
Jamie Madilld4442552018-02-27 22:03:47 -0500200 Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT,
Jamie Madill05b35b22017-10-03 09:01:44 -0400201 "Framebuffer Dirty bit mismatch");
Jamie Madill682efdc2017-10-03 14:10:29 -0400202static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS + 1) ==
Jamie Madilld4442552018-02-27 22:03:47 -0500203 Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT,
Jamie Madill05b35b22017-10-03 09:01:44 -0400204 "Framebuffer Dirty bit mismatch");
205
206Error InitAttachment(const Context *context, FramebufferAttachment *attachment)
207{
208 ASSERT(attachment->isAttached());
209 if (attachment->initState() == InitState::MayNeedInit)
210 {
211 ANGLE_TRY(attachment->initializeContents(context));
212 }
213 return NoError();
214}
215
216bool IsColorMaskedOut(const BlendState &blend)
217{
218 return (!blend.colorMaskRed && !blend.colorMaskGreen && !blend.colorMaskBlue &&
219 !blend.colorMaskAlpha);
220}
221
222bool IsDepthMaskedOut(const DepthStencilState &depthStencil)
223{
224 return !depthStencil.depthMask;
225}
226
227bool IsStencilMaskedOut(const DepthStencilState &depthStencil)
228{
229 return ((depthStencil.stencilMask & depthStencil.stencilWritemask) == 0);
230}
231
232bool IsClearBufferMaskedOut(const Context *context, GLenum buffer)
233{
234 switch (buffer)
235 {
236 case GL_COLOR:
237 return IsColorMaskedOut(context->getGLState().getBlendState());
238 case GL_DEPTH:
239 return IsDepthMaskedOut(context->getGLState().getDepthStencilState());
240 case GL_STENCIL:
241 return IsStencilMaskedOut(context->getGLState().getDepthStencilState());
242 case GL_DEPTH_STENCIL:
243 return IsDepthMaskedOut(context->getGLState().getDepthStencilState()) &&
244 IsStencilMaskedOut(context->getGLState().getDepthStencilState());
245 default:
246 UNREACHABLE();
247 return true;
248 }
249}
250
Jamie Madill362876b2016-06-16 14:46:59 -0400251} // anonymous namespace
Jamie Madilld1405e52015-03-05 15:41:39 -0500252
Jamie Madill6f60d052017-02-22 15:20:11 -0500253// This constructor is only used for default framebuffers.
Jamie Madill48ef11b2016-04-27 15:21:52 -0400254FramebufferState::FramebufferState()
Geoff Lang70d0f492015-12-10 17:45:46 -0500255 : mLabel(),
256 mColorAttachments(1),
Corentin Walleze7557742017-06-01 13:09:57 -0400257 mDrawBufferStates(1, GL_BACK),
Jamie Madill6f60d052017-02-22 15:20:11 -0500258 mReadBufferState(GL_BACK),
Brandon Jones76746f92017-11-22 11:44:41 -0800259 mDrawBufferTypeMask(),
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800260 mDefaultWidth(0),
261 mDefaultHeight(0),
262 mDefaultSamples(0),
Jamie Madilla02315b2017-02-23 14:14:47 -0500263 mDefaultFixedSampleLocations(GL_FALSE),
264 mWebGLDepthStencilConsistent(true)
Corentin Wallez37c39792015-08-20 14:19:46 -0400265{
Geoff Langd90d3882017-03-21 10:49:54 -0400266 ASSERT(mDrawBufferStates.size() > 0);
Jamie Madilla4595b82017-01-11 17:36:34 -0500267 mEnabledDrawBuffers.set(0);
Corentin Wallez37c39792015-08-20 14:19:46 -0400268}
269
Jamie Madill48ef11b2016-04-27 15:21:52 -0400270FramebufferState::FramebufferState(const Caps &caps)
Geoff Lang70d0f492015-12-10 17:45:46 -0500271 : mLabel(),
272 mColorAttachments(caps.maxColorAttachments),
Jamie Madilld1405e52015-03-05 15:41:39 -0500273 mDrawBufferStates(caps.maxDrawBuffers, GL_NONE),
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800274 mReadBufferState(GL_COLOR_ATTACHMENT0_EXT),
Brandon Jones76746f92017-11-22 11:44:41 -0800275 mDrawBufferTypeMask(),
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800276 mDefaultWidth(0),
277 mDefaultHeight(0),
278 mDefaultSamples(0),
Jamie Madilla02315b2017-02-23 14:14:47 -0500279 mDefaultFixedSampleLocations(GL_FALSE),
280 mWebGLDepthStencilConsistent(true)
Jamie Madilld1405e52015-03-05 15:41:39 -0500281{
Geoff Langa15472a2015-08-11 11:48:03 -0400282 ASSERT(mDrawBufferStates.size() > 0);
Jamie Madilld1405e52015-03-05 15:41:39 -0500283 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
284}
285
Jamie Madill48ef11b2016-04-27 15:21:52 -0400286FramebufferState::~FramebufferState()
Jamie Madilld1405e52015-03-05 15:41:39 -0500287{
Jamie Madilld1405e52015-03-05 15:41:39 -0500288}
289
Jamie Madill48ef11b2016-04-27 15:21:52 -0400290const std::string &FramebufferState::getLabel()
Geoff Lang70d0f492015-12-10 17:45:46 -0500291{
292 return mLabel;
293}
294
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800295const FramebufferAttachment *FramebufferState::getAttachment(const Context *context,
296 GLenum attachment) const
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400297{
298 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
299 {
300 return getColorAttachment(attachment - GL_COLOR_ATTACHMENT0);
301 }
302
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800303 // WebGL1 allows a developer to query for attachment parameters even when "inconsistant" (i.e.
304 // multiple conflicting attachment points) and requires us to return the framebuffer attachment
305 // associated with WebGL.
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400306 switch (attachment)
307 {
308 case GL_COLOR:
309 case GL_BACK:
310 return getColorAttachment(0);
311 case GL_DEPTH:
312 case GL_DEPTH_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800313 if (context->isWebGL1())
314 {
315 return getWebGLDepthAttachment();
316 }
317 else
318 {
319 return getDepthAttachment();
320 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400321 case GL_STENCIL:
322 case GL_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800323 if (context->isWebGL1())
324 {
325 return getWebGLStencilAttachment();
326 }
327 else
328 {
329 return getStencilAttachment();
330 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400331 case GL_DEPTH_STENCIL:
332 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800333 if (context->isWebGL1())
334 {
335 return getWebGLDepthStencilAttachment();
336 }
337 else
338 {
339 return getDepthStencilAttachment();
340 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400341 default:
342 UNREACHABLE();
343 return nullptr;
344 }
345}
346
Jamie Madill05b35b22017-10-03 09:01:44 -0400347size_t FramebufferState::getReadIndex() const
Jamie Madill7147f012015-03-05 15:41:40 -0500348{
Jamie Madill231c7f52017-04-26 13:45:37 -0400349 ASSERT(mReadBufferState == GL_BACK ||
350 (mReadBufferState >= GL_COLOR_ATTACHMENT0 && mReadBufferState <= GL_COLOR_ATTACHMENT15));
351 size_t readIndex = (mReadBufferState == GL_BACK
352 ? 0
353 : static_cast<size_t>(mReadBufferState - GL_COLOR_ATTACHMENT0));
Jamie Madill7147f012015-03-05 15:41:40 -0500354 ASSERT(readIndex < mColorAttachments.size());
Jamie Madill05b35b22017-10-03 09:01:44 -0400355 return readIndex;
356}
357
358const FramebufferAttachment *FramebufferState::getReadAttachment() const
359{
360 if (mReadBufferState == GL_NONE)
361 {
362 return nullptr;
363 }
364 size_t readIndex = getReadIndex();
Jamie Madill2d06b732015-04-20 12:53:28 -0400365 return mColorAttachments[readIndex].isAttached() ? &mColorAttachments[readIndex] : nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500366}
367
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500368const FramebufferAttachment *FramebufferState::getFirstNonNullAttachment() const
369{
370 auto *colorAttachment = getFirstColorAttachment();
371 if (colorAttachment)
372 {
373 return colorAttachment;
374 }
375 return getDepthOrStencilAttachment();
376}
377
Jamie Madill48ef11b2016-04-27 15:21:52 -0400378const FramebufferAttachment *FramebufferState::getFirstColorAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500379{
Jamie Madill2d06b732015-04-20 12:53:28 -0400380 for (const FramebufferAttachment &colorAttachment : mColorAttachments)
Jamie Madill7147f012015-03-05 15:41:40 -0500381 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400382 if (colorAttachment.isAttached())
Jamie Madill7147f012015-03-05 15:41:40 -0500383 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400384 return &colorAttachment;
Jamie Madill7147f012015-03-05 15:41:40 -0500385 }
386 }
387
388 return nullptr;
389}
390
Jamie Madill48ef11b2016-04-27 15:21:52 -0400391const FramebufferAttachment *FramebufferState::getDepthOrStencilAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500392{
Jamie Madill2d06b732015-04-20 12:53:28 -0400393 if (mDepthAttachment.isAttached())
394 {
395 return &mDepthAttachment;
396 }
397 if (mStencilAttachment.isAttached())
398 {
399 return &mStencilAttachment;
400 }
401 return nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500402}
403
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500404const FramebufferAttachment *FramebufferState::getStencilOrDepthStencilAttachment() const
405{
406 if (mStencilAttachment.isAttached())
407 {
408 return &mStencilAttachment;
409 }
410 return getDepthStencilAttachment();
411}
412
Jamie Madill48ef11b2016-04-27 15:21:52 -0400413const FramebufferAttachment *FramebufferState::getColorAttachment(size_t colorAttachment) const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400414{
415 ASSERT(colorAttachment < mColorAttachments.size());
Jamie Madill231c7f52017-04-26 13:45:37 -0400416 return mColorAttachments[colorAttachment].isAttached() ? &mColorAttachments[colorAttachment]
417 : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400418}
419
Jamie Madill48ef11b2016-04-27 15:21:52 -0400420const FramebufferAttachment *FramebufferState::getDepthAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400421{
Jamie Madill2d06b732015-04-20 12:53:28 -0400422 return mDepthAttachment.isAttached() ? &mDepthAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400423}
424
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800425const FramebufferAttachment *FramebufferState::getWebGLDepthAttachment() const
426{
427 return mWebGLDepthAttachment.isAttached() ? &mWebGLDepthAttachment : nullptr;
428}
429
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800430const FramebufferAttachment *FramebufferState::getWebGLDepthStencilAttachment() const
431{
432 return mWebGLDepthStencilAttachment.isAttached() ? &mWebGLDepthStencilAttachment : nullptr;
433}
434
Jamie Madill48ef11b2016-04-27 15:21:52 -0400435const FramebufferAttachment *FramebufferState::getStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400436{
Jamie Madill2d06b732015-04-20 12:53:28 -0400437 return mStencilAttachment.isAttached() ? &mStencilAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400438}
439
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800440const FramebufferAttachment *FramebufferState::getWebGLStencilAttachment() const
441{
442 return mWebGLStencilAttachment.isAttached() ? &mWebGLStencilAttachment : nullptr;
443}
444
Jamie Madill48ef11b2016-04-27 15:21:52 -0400445const FramebufferAttachment *FramebufferState::getDepthStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400446{
447 // A valid depth-stencil attachment has the same resource bound to both the
448 // depth and stencil attachment points.
Jamie Madill2d06b732015-04-20 12:53:28 -0400449 if (mDepthAttachment.isAttached() && mStencilAttachment.isAttached() &&
Jamie Madill44f26482016-11-18 12:49:15 -0500450 mDepthAttachment == mStencilAttachment)
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400451 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400452 return &mDepthAttachment;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400453 }
454
455 return nullptr;
456}
457
Jamie Madill48ef11b2016-04-27 15:21:52 -0400458bool FramebufferState::attachmentsHaveSameDimensions() const
Jamie Madillcc86d642015-11-24 13:00:07 -0500459{
460 Optional<Extents> attachmentSize;
461
Jamie Madill231c7f52017-04-26 13:45:37 -0400462 auto hasMismatchedSize = [&attachmentSize](const FramebufferAttachment &attachment) {
Jamie Madillcc86d642015-11-24 13:00:07 -0500463 if (!attachment.isAttached())
464 {
465 return false;
466 }
467
468 if (!attachmentSize.valid())
469 {
470 attachmentSize = attachment.getSize();
471 return false;
472 }
473
Jeff Gilbert8f8edd62017-10-31 14:26:30 -0700474 const auto &prevSize = attachmentSize.value();
475 const auto &curSize = attachment.getSize();
476 return (curSize.width != prevSize.width || curSize.height != prevSize.height);
Jamie Madillcc86d642015-11-24 13:00:07 -0500477 };
478
479 for (const auto &attachment : mColorAttachments)
480 {
481 if (hasMismatchedSize(attachment))
482 {
483 return false;
484 }
485 }
486
487 if (hasMismatchedSize(mDepthAttachment))
488 {
489 return false;
490 }
491
492 return !hasMismatchedSize(mStencilAttachment);
493}
494
Jamie Madilld4442552018-02-27 22:03:47 -0500495const FramebufferAttachment *FramebufferState::getDrawBuffer(size_t drawBufferIdx) const
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400496{
497 ASSERT(drawBufferIdx < mDrawBufferStates.size());
498 if (mDrawBufferStates[drawBufferIdx] != GL_NONE)
499 {
500 // ES3 spec: "If the GL is bound to a draw framebuffer object, the ith buffer listed in bufs
501 // must be COLOR_ATTACHMENTi or NONE"
502 ASSERT(mDrawBufferStates[drawBufferIdx] == GL_COLOR_ATTACHMENT0 + drawBufferIdx ||
503 (drawBufferIdx == 0 && mDrawBufferStates[drawBufferIdx] == GL_BACK));
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800504
505 if (mDrawBufferStates[drawBufferIdx] == GL_BACK)
506 {
507 return getColorAttachment(0);
508 }
509 else
510 {
511 return getColorAttachment(mDrawBufferStates[drawBufferIdx] - GL_COLOR_ATTACHMENT0);
512 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400513 }
514 else
515 {
516 return nullptr;
517 }
518}
519
520size_t FramebufferState::getDrawBufferCount() const
521{
522 return mDrawBufferStates.size();
523}
524
Geoff Langb21e20d2016-07-19 15:35:41 -0400525bool FramebufferState::colorAttachmentsAreUniqueImages() const
526{
527 for (size_t firstAttachmentIdx = 0; firstAttachmentIdx < mColorAttachments.size();
528 firstAttachmentIdx++)
529 {
Jamie Madilld4442552018-02-27 22:03:47 -0500530 const FramebufferAttachment &firstAttachment = mColorAttachments[firstAttachmentIdx];
Geoff Langb21e20d2016-07-19 15:35:41 -0400531 if (!firstAttachment.isAttached())
532 {
533 continue;
534 }
535
536 for (size_t secondAttachmentIdx = firstAttachmentIdx + 1;
537 secondAttachmentIdx < mColorAttachments.size(); secondAttachmentIdx++)
538 {
Jamie Madilld4442552018-02-27 22:03:47 -0500539 const FramebufferAttachment &secondAttachment = mColorAttachments[secondAttachmentIdx];
Geoff Langb21e20d2016-07-19 15:35:41 -0400540 if (!secondAttachment.isAttached())
541 {
542 continue;
543 }
544
545 if (firstAttachment == secondAttachment)
546 {
547 return false;
548 }
549 }
550 }
551
552 return true;
553}
554
Jamie Madill9c335862017-07-18 11:51:38 -0400555bool FramebufferState::hasDepth() const
556{
557 return (mDepthAttachment.isAttached() && mDepthAttachment.getDepthSize() > 0);
558}
559
560bool FramebufferState::hasStencil() const
561{
562 return (mStencilAttachment.isAttached() && mStencilAttachment.getStencilSize() > 0);
563}
564
Martin Radev5c00d0d2017-08-07 10:06:59 +0300565GLsizei FramebufferState::getNumViews() const
566{
567 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
568 if (attachment == nullptr)
569 {
570 return FramebufferAttachment::kDefaultNumViews;
571 }
572 return attachment->getNumViews();
573}
574
575const std::vector<Offset> *FramebufferState::getViewportOffsets() const
576{
577 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
578 if (attachment == nullptr)
579 {
580 return nullptr;
581 }
582 return &attachment->getMultiviewViewportOffsets();
583}
584
585GLenum FramebufferState::getMultiviewLayout() const
586{
587 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
588 if (attachment == nullptr)
589 {
590 return GL_NONE;
591 }
592 return attachment->getMultiviewLayout();
593}
594
Martin Radev4e619f52017-08-09 11:50:06 +0300595int FramebufferState::getBaseViewIndex() const
596{
597 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
598 if (attachment == nullptr)
599 {
600 return GL_NONE;
601 }
602 return attachment->getBaseViewIndex();
603}
604
Jamie Madill05b35b22017-10-03 09:01:44 -0400605Box FramebufferState::getDimensions() const
606{
607 ASSERT(attachmentsHaveSameDimensions());
608 ASSERT(getFirstNonNullAttachment() != nullptr);
609 Extents extents = getFirstNonNullAttachment()->getSize();
610 return Box(0, 0, 0, extents.width, extents.height, extents.depth);
611}
612
Jamie Madill7aea7e02016-05-10 10:39:45 -0400613Framebuffer::Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id)
Jamie Madill362876b2016-06-16 14:46:59 -0400614 : mState(caps),
615 mImpl(factory->createFramebuffer(mState)),
616 mId(id),
617 mCachedStatus(),
618 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
619 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000620{
Corentin Wallez37c39792015-08-20 14:19:46 -0400621 ASSERT(mId != 0);
622 ASSERT(mImpl != nullptr);
Jamie Madill362876b2016-06-16 14:46:59 -0400623 ASSERT(mState.mColorAttachments.size() == static_cast<size_t>(caps.maxColorAttachments));
624
Jamie Madill1e5499d2017-04-05 11:22:16 -0400625 for (uint32_t colorIndex = 0;
626 colorIndex < static_cast<uint32_t>(mState.mColorAttachments.size()); ++colorIndex)
Jamie Madill362876b2016-06-16 14:46:59 -0400627 {
Jamie Madill1e5499d2017-04-05 11:22:16 -0400628 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
Jamie Madill362876b2016-06-16 14:46:59 -0400629 }
Corentin Wallez37c39792015-08-20 14:19:46 -0400630}
631
Jamie Madill4928b7c2017-06-20 12:57:39 -0400632Framebuffer::Framebuffer(const egl::Display *display, egl::Surface *surface)
Jamie Madill362876b2016-06-16 14:46:59 -0400633 : mState(),
Jamie Madill6f60d052017-02-22 15:20:11 -0500634 mImpl(surface->getImplementation()->createDefaultFramebuffer(mState)),
Jamie Madill362876b2016-06-16 14:46:59 -0400635 mId(0),
636 mCachedStatus(GL_FRAMEBUFFER_COMPLETE),
637 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
638 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
Corentin Wallez37c39792015-08-20 14:19:46 -0400639{
Geoff Langda88add2014-12-01 10:22:01 -0500640 ASSERT(mImpl != nullptr);
Jamie Madill1e5499d2017-04-05 11:22:16 -0400641 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
Jamie Madill6f60d052017-02-22 15:20:11 -0500642
Jamie Madill4928b7c2017-06-20 12:57:39 -0400643 const Context *proxyContext = display->getProxyContext();
644
Jamie Madilld4442552018-02-27 22:03:47 -0500645 setAttachmentImpl(proxyContext, GL_FRAMEBUFFER_DEFAULT, GL_BACK, ImageIndex::MakeInvalid(),
Martin Radev5dae57b2017-07-14 16:15:55 +0300646 surface, FramebufferAttachment::kDefaultNumViews,
647 FramebufferAttachment::kDefaultBaseViewIndex,
648 FramebufferAttachment::kDefaultMultiviewLayout,
649 FramebufferAttachment::kDefaultViewportOffsets);
Jamie Madill6f60d052017-02-22 15:20:11 -0500650
651 if (surface->getConfig()->depthSize > 0)
652 {
Jamie Madilld4442552018-02-27 22:03:47 -0500653 setAttachmentImpl(proxyContext, GL_FRAMEBUFFER_DEFAULT, GL_DEPTH, ImageIndex::MakeInvalid(),
654 surface, FramebufferAttachment::kDefaultNumViews,
655 FramebufferAttachment::kDefaultBaseViewIndex,
656 FramebufferAttachment::kDefaultMultiviewLayout,
657 FramebufferAttachment::kDefaultViewportOffsets);
Jamie Madill6f60d052017-02-22 15:20:11 -0500658 }
659
660 if (surface->getConfig()->stencilSize > 0)
661 {
Jamie Madilld4442552018-02-27 22:03:47 -0500662 setAttachmentImpl(
663 proxyContext, GL_FRAMEBUFFER_DEFAULT, GL_STENCIL, ImageIndex::MakeInvalid(), surface,
664 FramebufferAttachment::kDefaultNumViews, FramebufferAttachment::kDefaultBaseViewIndex,
665 FramebufferAttachment::kDefaultMultiviewLayout,
666 FramebufferAttachment::kDefaultViewportOffsets);
Jamie Madill6f60d052017-02-22 15:20:11 -0500667 }
Brandon Jones76746f92017-11-22 11:44:41 -0800668 mState.mDrawBufferTypeMask.setIndex(getDrawbufferWriteType(0), 0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000669}
670
Corentin Wallezccab69d2017-01-27 16:57:15 -0500671Framebuffer::Framebuffer(rx::GLImplFactory *factory)
672 : mState(),
673 mImpl(factory->createFramebuffer(mState)),
674 mId(0),
675 mCachedStatus(GL_FRAMEBUFFER_UNDEFINED_OES),
676 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
677 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
678{
Jamie Madill1e5499d2017-04-05 11:22:16 -0400679 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
Brandon Jones76746f92017-11-22 11:44:41 -0800680 mState.mDrawBufferTypeMask.setIndex(getDrawbufferWriteType(0), 0);
Corentin Wallezccab69d2017-01-27 16:57:15 -0500681}
682
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000683Framebuffer::~Framebuffer()
684{
Geoff Langda88add2014-12-01 10:22:01 -0500685 SafeDelete(mImpl);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000686}
687
Jamie Madill4928b7c2017-06-20 12:57:39 -0400688void Framebuffer::onDestroy(const Context *context)
Jamie Madill6c1f6712017-02-14 19:08:04 -0500689{
Jamie Madill4928b7c2017-06-20 12:57:39 -0400690 for (auto &attachment : mState.mColorAttachments)
691 {
692 attachment.detach(context);
693 }
694 mState.mDepthAttachment.detach(context);
695 mState.mStencilAttachment.detach(context);
696 mState.mWebGLDepthAttachment.detach(context);
697 mState.mWebGLStencilAttachment.detach(context);
698 mState.mWebGLDepthStencilAttachment.detach(context);
699
Jamie Madillc564c072017-06-01 12:45:42 -0400700 mImpl->destroy(context);
Jamie Madill6c1f6712017-02-14 19:08:04 -0500701}
702
703void Framebuffer::destroyDefault(const egl::Display *display)
704{
Jamie Madillc564c072017-06-01 12:45:42 -0400705 mImpl->destroyDefault(display);
Jamie Madill6c1f6712017-02-14 19:08:04 -0500706}
707
Geoff Lang70d0f492015-12-10 17:45:46 -0500708void Framebuffer::setLabel(const std::string &label)
709{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400710 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -0500711}
712
713const std::string &Framebuffer::getLabel() const
714{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400715 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -0500716}
717
Jamie Madill8693bdb2017-09-02 15:32:14 -0400718bool Framebuffer::detachTexture(const Context *context, GLuint textureId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000719{
Jamie Madill8693bdb2017-09-02 15:32:14 -0400720 return detachResourceById(context, GL_TEXTURE, textureId);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000721}
722
Jamie Madill8693bdb2017-09-02 15:32:14 -0400723bool Framebuffer::detachRenderbuffer(const Context *context, GLuint renderbufferId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000724{
Jamie Madill8693bdb2017-09-02 15:32:14 -0400725 return detachResourceById(context, GL_RENDERBUFFER, renderbufferId);
Jamie Madilld1405e52015-03-05 15:41:39 -0500726}
Jamie Madille261b442014-06-25 12:42:21 -0400727
Jamie Madill8693bdb2017-09-02 15:32:14 -0400728bool Framebuffer::detachResourceById(const Context *context, GLenum resourceType, GLuint resourceId)
Jamie Madilld1405e52015-03-05 15:41:39 -0500729{
Jamie Madill8693bdb2017-09-02 15:32:14 -0400730 bool found = false;
731
Jamie Madill362876b2016-06-16 14:46:59 -0400732 for (size_t colorIndex = 0; colorIndex < mState.mColorAttachments.size(); ++colorIndex)
Jamie Madilld1405e52015-03-05 15:41:39 -0500733 {
Jamie Madill8693bdb2017-09-02 15:32:14 -0400734 if (detachMatchingAttachment(context, &mState.mColorAttachments[colorIndex], resourceType,
735 resourceId, DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex))
736 {
737 found = true;
738 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000739 }
740
Jamie Madilla02315b2017-02-23 14:14:47 -0500741 if (context->isWebGL1())
742 {
743 const std::array<FramebufferAttachment *, 3> attachments = {
744 {&mState.mWebGLDepthStencilAttachment, &mState.mWebGLDepthAttachment,
745 &mState.mWebGLStencilAttachment}};
746 for (FramebufferAttachment *attachment : attachments)
747 {
748 if (attachment->isAttached() && attachment->type() == resourceType &&
749 attachment->id() == resourceId)
750 {
751 resetAttachment(context, attachment->getBinding());
Jamie Madill8693bdb2017-09-02 15:32:14 -0400752 found = true;
Jamie Madilla02315b2017-02-23 14:14:47 -0500753 }
754 }
755 }
756 else
757 {
Jamie Madill8693bdb2017-09-02 15:32:14 -0400758 if (detachMatchingAttachment(context, &mState.mDepthAttachment, resourceType, resourceId,
759 DIRTY_BIT_DEPTH_ATTACHMENT))
760 {
761 found = true;
762 }
763 if (detachMatchingAttachment(context, &mState.mStencilAttachment, resourceType, resourceId,
764 DIRTY_BIT_STENCIL_ATTACHMENT))
765 {
766 found = true;
767 }
Jamie Madilla02315b2017-02-23 14:14:47 -0500768 }
Jamie Madill8693bdb2017-09-02 15:32:14 -0400769
770 return found;
Jamie Madill362876b2016-06-16 14:46:59 -0400771}
772
Jamie Madill8693bdb2017-09-02 15:32:14 -0400773bool Framebuffer::detachMatchingAttachment(const Context *context,
Jamie Madill4928b7c2017-06-20 12:57:39 -0400774 FramebufferAttachment *attachment,
Jamie Madill362876b2016-06-16 14:46:59 -0400775 GLenum matchType,
776 GLuint matchId,
777 size_t dirtyBit)
778{
779 if (attachment->isAttached() && attachment->type() == matchType && attachment->id() == matchId)
780 {
Jamie Madill4928b7c2017-06-20 12:57:39 -0400781 attachment->detach(context);
Jamie Madill362876b2016-06-16 14:46:59 -0400782 mDirtyBits.set(dirtyBit);
Jamie Madill05b35b22017-10-03 09:01:44 -0400783 mState.mResourceNeedsInit.set(dirtyBit, false);
Jamie Madill8693bdb2017-09-02 15:32:14 -0400784 return true;
Jamie Madill362876b2016-06-16 14:46:59 -0400785 }
Jamie Madill8693bdb2017-09-02 15:32:14 -0400786
787 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000788}
789
Corentin Wallez37c39792015-08-20 14:19:46 -0400790const FramebufferAttachment *Framebuffer::getColorbuffer(size_t colorAttachment) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000791{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400792 return mState.getColorAttachment(colorAttachment);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000793}
794
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400795const FramebufferAttachment *Framebuffer::getDepthbuffer() const
Geoff Lang646559f2013-08-15 11:08:15 -0400796{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400797 return mState.getDepthAttachment();
Geoff Lang646559f2013-08-15 11:08:15 -0400798}
799
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400800const FramebufferAttachment *Framebuffer::getStencilbuffer() const
801{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400802 return mState.getStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400803}
804
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400805const FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
806{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400807 return mState.getDepthStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400808}
809
810const FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000811{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400812 return mState.getDepthOrStencilAttachment();
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000813}
814
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500815const FramebufferAttachment *Framebuffer::getStencilOrDepthStencilAttachment() const
816{
817 return mState.getStencilOrDepthStencilAttachment();
818}
819
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400820const FramebufferAttachment *Framebuffer::getReadColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000821{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400822 return mState.getReadAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000823}
824
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000825GLenum Framebuffer::getReadColorbufferType() const
826{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400827 const FramebufferAttachment *readAttachment = mState.getReadAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400828 return (readAttachment != nullptr ? readAttachment->type() : GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000829}
830
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400831const FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000832{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400833 return mState.getFirstColorAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000834}
835
Jamie Madill6dd06ea2017-07-19 13:47:55 -0400836const FramebufferAttachment *Framebuffer::getFirstNonNullAttachment() const
837{
838 return mState.getFirstNonNullAttachment();
839}
840
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800841const FramebufferAttachment *Framebuffer::getAttachment(const Context *context,
842 GLenum attachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000843{
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800844 return mState.getAttachment(context, attachment);
Geoff Lang55ba29c2013-07-11 16:57:53 -0400845}
846
Geoff Langa15472a2015-08-11 11:48:03 -0400847size_t Framebuffer::getDrawbufferStateCount() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000848{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400849 return mState.mDrawBufferStates.size();
Geoff Langa15472a2015-08-11 11:48:03 -0400850}
851
852GLenum Framebuffer::getDrawBufferState(size_t drawBuffer) const
853{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400854 ASSERT(drawBuffer < mState.mDrawBufferStates.size());
855 return mState.mDrawBufferStates[drawBuffer];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000856}
857
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500858const std::vector<GLenum> &Framebuffer::getDrawBufferStates() const
859{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400860 return mState.getDrawBufferStates();
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500861}
862
Geoff Lang164d54e2014-12-01 10:55:33 -0500863void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000864{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400865 auto &drawStates = mState.mDrawBufferStates;
Jamie Madilld1405e52015-03-05 15:41:39 -0500866
867 ASSERT(count <= drawStates.size());
868 std::copy(buffers, buffers + count, drawStates.begin());
869 std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500870 mDirtyBits.set(DIRTY_BIT_DRAW_BUFFERS);
Jamie Madilla4595b82017-01-11 17:36:34 -0500871
872 mState.mEnabledDrawBuffers.reset();
Brandon Jones76746f92017-11-22 11:44:41 -0800873 mState.mDrawBufferTypeMask.reset();
874
Jamie Madilla4595b82017-01-11 17:36:34 -0500875 for (size_t index = 0; index < count; ++index)
876 {
Brandon Jones76746f92017-11-22 11:44:41 -0800877 mState.mDrawBufferTypeMask.setIndex(getDrawbufferWriteType(index), index);
878
Jamie Madilla4595b82017-01-11 17:36:34 -0500879 if (drawStates[index] != GL_NONE && mState.mColorAttachments[index].isAttached())
880 {
881 mState.mEnabledDrawBuffers.set(index);
882 }
883 }
Geoff Lang9dd95802014-12-01 11:12:59 -0500884}
885
Geoff Langa15472a2015-08-11 11:48:03 -0400886const FramebufferAttachment *Framebuffer::getDrawBuffer(size_t drawBuffer) const
887{
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400888 return mState.getDrawBuffer(drawBuffer);
Geoff Langa15472a2015-08-11 11:48:03 -0400889}
890
Geoff Lange0cff192017-05-30 13:04:56 -0400891GLenum Framebuffer::getDrawbufferWriteType(size_t drawBuffer) const
892{
893 const FramebufferAttachment *attachment = mState.getDrawBuffer(drawBuffer);
894 if (attachment == nullptr)
895 {
896 return GL_NONE;
897 }
898
899 GLenum componentType = attachment->getFormat().info->componentType;
900 switch (componentType)
901 {
902 case GL_INT:
903 case GL_UNSIGNED_INT:
904 return componentType;
905
906 default:
907 return GL_FLOAT;
908 }
909}
910
Brandon Jonesc405ae72017-12-06 14:15:03 -0800911ComponentTypeMask Framebuffer::getDrawBufferTypeMask() const
Brandon Jones76746f92017-11-22 11:44:41 -0800912{
913 return mState.mDrawBufferTypeMask;
914}
915
916DrawBufferMask Framebuffer::getDrawBufferMask() const
917{
918 return mState.mEnabledDrawBuffers;
919}
920
Geoff Langa15472a2015-08-11 11:48:03 -0400921bool Framebuffer::hasEnabledDrawBuffer() const
922{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400923 for (size_t drawbufferIdx = 0; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
Geoff Langa15472a2015-08-11 11:48:03 -0400924 {
925 if (getDrawBuffer(drawbufferIdx) != nullptr)
926 {
927 return true;
928 }
929 }
930
931 return false;
932}
933
Geoff Lang9dd95802014-12-01 11:12:59 -0500934GLenum Framebuffer::getReadBufferState() const
935{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400936 return mState.mReadBufferState;
Geoff Lang9dd95802014-12-01 11:12:59 -0500937}
938
939void Framebuffer::setReadBuffer(GLenum buffer)
940{
Jamie Madillb885e572015-02-03 16:16:04 -0500941 ASSERT(buffer == GL_BACK || buffer == GL_NONE ||
942 (buffer >= GL_COLOR_ATTACHMENT0 &&
Jamie Madill48ef11b2016-04-27 15:21:52 -0400943 (buffer - GL_COLOR_ATTACHMENT0) < mState.mColorAttachments.size()));
944 mState.mReadBufferState = buffer;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500945 mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000946}
947
Corentin Wallez37c39792015-08-20 14:19:46 -0400948size_t Framebuffer::getNumColorBuffers() const
949{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400950 return mState.mColorAttachments.size();
Corentin Wallez37c39792015-08-20 14:19:46 -0400951}
952
Jamie Madill0df8fe42015-11-24 16:10:24 -0500953bool Framebuffer::hasDepth() const
954{
Jamie Madill9c335862017-07-18 11:51:38 -0400955 return mState.hasDepth();
Jamie Madill0df8fe42015-11-24 16:10:24 -0500956}
957
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000958bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000959{
Jamie Madill9c335862017-07-18 11:51:38 -0400960 return mState.hasStencil();
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000961}
962
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000963bool Framebuffer::usingExtendedDrawBuffers() const
964{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400965 for (size_t drawbufferIdx = 1; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000966 {
Geoff Langa15472a2015-08-11 11:48:03 -0400967 if (getDrawBuffer(drawbufferIdx) != nullptr)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000968 {
969 return true;
970 }
971 }
972
973 return false;
974}
975
Geoff Lang9aded172017-04-05 11:07:56 -0400976void Framebuffer::invalidateCompletenessCache()
977{
978 if (mId != 0)
979 {
980 mCachedStatus.reset();
981 }
982}
983
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400984GLenum Framebuffer::checkStatus(const Context *context)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000985{
Corentin Wallezccab69d2017-01-27 16:57:15 -0500986 // The default framebuffer is always complete except when it is surfaceless in which
987 // case it is always unsupported. We return early because the default framebuffer may
988 // not be subject to the same rules as application FBOs. ie, it could have 0x0 size.
Geoff Lang528ce3c2014-12-01 10:44:07 -0500989 if (mId == 0)
990 {
Corentin Wallezccab69d2017-01-27 16:57:15 -0500991 ASSERT(mCachedStatus.valid());
992 ASSERT(mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE ||
993 mCachedStatus.value() == GL_FRAMEBUFFER_UNDEFINED_OES);
994 return mCachedStatus.value();
Geoff Lang528ce3c2014-12-01 10:44:07 -0500995 }
996
Jamie Madill362876b2016-06-16 14:46:59 -0400997 if (hasAnyDirtyBit() || !mCachedStatus.valid())
998 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400999 mCachedStatus = checkStatusImpl(context);
Jamie Madill362876b2016-06-16 14:46:59 -04001000 }
1001
1002 return mCachedStatus.value();
1003}
1004
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001005GLenum Framebuffer::checkStatusImpl(const Context *context)
Jamie Madill362876b2016-06-16 14:46:59 -04001006{
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001007 const ContextState &state = context->getContextState();
1008
Jamie Madill362876b2016-06-16 14:46:59 -04001009 ASSERT(mId != 0);
1010
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001011 bool hasAttachments = false;
1012 Optional<unsigned int> colorbufferSize;
1013 Optional<int> samples;
Geoff Lang92019432017-11-20 13:09:34 -05001014 Optional<bool> fixedSampleLocations;
JiangYizhou461d9a32017-01-04 16:37:26 +08001015 bool hasRenderbuffer = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001016
Martin Radev9bc9a322017-07-21 14:28:17 +03001017 const FramebufferAttachment *firstAttachment = getFirstNonNullAttachment();
1018
Jamie Madill48ef11b2016-04-27 15:21:52 -04001019 for (const FramebufferAttachment &colorAttachment : mState.mColorAttachments)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001020 {
Jamie Madill2d06b732015-04-20 12:53:28 -04001021 if (colorAttachment.isAttached())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001022 {
Geoff Lang9f10b772017-05-16 15:51:03 -04001023 if (!CheckAttachmentCompleteness(context, colorAttachment))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001024 {
1025 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1026 }
daniel@transgaming.com01868132010-08-24 19:21:17 +00001027
Geoff Lang677bb6f2017-04-05 12:40:40 -04001028 const InternalFormat &format = *colorAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -04001029 if (format.depthBits > 0 || format.stencilBits > 0)
1030 {
1031 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1032 }
1033
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001034 if (!CheckAttachmentSampleCompleteness(context, colorAttachment, true, &samples,
1035 &fixedSampleLocations))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001036 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001037 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001038 }
1039
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001040 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
1041 // in GLES 3.0, there is no such restriction
1042 if (state.getClientMajorVersion() < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001043 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001044 if (colorbufferSize.valid())
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001045 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001046 if (format.pixelBytes != colorbufferSize.value())
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +00001047 {
1048 return GL_FRAMEBUFFER_UNSUPPORTED;
1049 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001050 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001051 else
1052 {
1053 colorbufferSize = format.pixelBytes;
1054 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001055 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001056
Martin Radev9bc9a322017-07-21 14:28:17 +03001057 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &colorAttachment))
1058 {
1059 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
1060 }
1061
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001062 hasRenderbuffer = hasRenderbuffer || (colorAttachment.type() == GL_RENDERBUFFER);
1063 hasAttachments = true;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001064 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001065 }
1066
Jamie Madill48ef11b2016-04-27 15:21:52 -04001067 const FramebufferAttachment &depthAttachment = mState.mDepthAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -04001068 if (depthAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001069 {
Geoff Lang9f10b772017-05-16 15:51:03 -04001070 if (!CheckAttachmentCompleteness(context, depthAttachment))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001071 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001072 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001073 }
1074
Geoff Lang677bb6f2017-04-05 12:40:40 -04001075 const InternalFormat &format = *depthAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -04001076 if (format.depthBits == 0)
1077 {
1078 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001079 }
1080
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001081 if (!CheckAttachmentSampleCompleteness(context, depthAttachment, false, &samples,
1082 &fixedSampleLocations))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001083 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001084 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001085 }
Sami Väisänena797e062016-05-12 15:23:40 +03001086
Martin Radev9bc9a322017-07-21 14:28:17 +03001087 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &depthAttachment))
1088 {
1089 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
1090 }
1091
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001092 hasRenderbuffer = hasRenderbuffer || (depthAttachment.type() == GL_RENDERBUFFER);
1093 hasAttachments = true;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001094 }
1095
Jamie Madill48ef11b2016-04-27 15:21:52 -04001096 const FramebufferAttachment &stencilAttachment = mState.mStencilAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -04001097 if (stencilAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001098 {
Geoff Lang9f10b772017-05-16 15:51:03 -04001099 if (!CheckAttachmentCompleteness(context, stencilAttachment))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001100 {
1101 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1102 }
1103
Geoff Lang677bb6f2017-04-05 12:40:40 -04001104 const InternalFormat &format = *stencilAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -04001105 if (format.stencilBits == 0)
1106 {
1107 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001108 }
1109
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001110 if (!CheckAttachmentSampleCompleteness(context, stencilAttachment, false, &samples,
1111 &fixedSampleLocations))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001112 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001113 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001114 }
Corentin Wallez086d59a2016-04-29 09:06:49 -04001115
Martin Radev9bc9a322017-07-21 14:28:17 +03001116 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &stencilAttachment))
1117 {
1118 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
1119 }
1120
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001121 hasRenderbuffer = hasRenderbuffer || (stencilAttachment.type() == GL_RENDERBUFFER);
1122 hasAttachments = true;
1123 }
1124
1125 // Starting from ES 3.0 stencil and depth, if present, should be the same image
1126 if (state.getClientMajorVersion() >= 3 && depthAttachment.isAttached() &&
1127 stencilAttachment.isAttached() && stencilAttachment != depthAttachment)
1128 {
1129 return GL_FRAMEBUFFER_UNSUPPORTED;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001130 }
1131
Jamie Madilla02315b2017-02-23 14:14:47 -05001132 // Special additional validation for WebGL 1 DEPTH/STENCIL/DEPTH_STENCIL.
1133 if (state.isWebGL1())
1134 {
1135 if (!mState.mWebGLDepthStencilConsistent)
1136 {
1137 return GL_FRAMEBUFFER_UNSUPPORTED;
1138 }
1139
1140 if (mState.mWebGLDepthStencilAttachment.isAttached())
1141 {
1142 if (mState.mWebGLDepthStencilAttachment.getDepthSize() == 0 ||
1143 mState.mWebGLDepthStencilAttachment.getStencilSize() == 0)
1144 {
1145 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1146 }
Martin Radev9bc9a322017-07-21 14:28:17 +03001147
1148 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment,
1149 &mState.mWebGLDepthStencilAttachment))
1150 {
1151 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
1152 }
Jamie Madilla02315b2017-02-23 14:14:47 -05001153 }
1154 else if (mState.mStencilAttachment.isAttached() &&
1155 mState.mStencilAttachment.getDepthSize() > 0)
1156 {
1157 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1158 }
1159 else if (mState.mDepthAttachment.isAttached() &&
1160 mState.mDepthAttachment.getStencilSize() > 0)
1161 {
1162 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1163 }
1164 }
1165
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001166 // ES3.1(section 9.4) requires that if no image is attached to the framebuffer, and either the
1167 // value of the framebuffer's FRAMEBUFFER_DEFAULT_WIDTH or FRAMEBUFFER_DEFAULT_HEIGHT parameters
1168 // is zero, the framebuffer is considered incomplete.
JiangYizhou461d9a32017-01-04 16:37:26 +08001169 GLint defaultWidth = mState.getDefaultWidth();
1170 GLint defaultHeight = mState.getDefaultHeight();
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001171 if (!hasAttachments && (defaultWidth == 0 || defaultHeight == 0))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001172 {
1173 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001174 }
1175
Geoff Langa0e0aeb2017-04-12 15:06:29 -04001176 // In ES 2.0 and WebGL, all color attachments must have the same width and height.
Jamie Madillcc86d642015-11-24 13:00:07 -05001177 // In ES 3.0, there is no such restriction.
Geoff Langa0e0aeb2017-04-12 15:06:29 -04001178 if ((state.getClientMajorVersion() < 3 || state.getExtensions().webglCompatibility) &&
1179 !mState.attachmentsHaveSameDimensions())
Jamie Madillcc86d642015-11-24 13:00:07 -05001180 {
1181 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
1182 }
1183
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001184 // ES3.1(section 9.4) requires that if the attached images are a mix of renderbuffers and
1185 // textures, the value of TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all attached textures.
JiangYizhou461d9a32017-01-04 16:37:26 +08001186 if (fixedSampleLocations.valid() && hasRenderbuffer && !fixedSampleLocations.value())
1187 {
1188 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1189 }
1190
Kenneth Russellce8602a2017-10-03 18:23:08 -07001191 // The WebGL conformance tests implicitly define that all framebuffer
1192 // attachments must be unique. For example, the same level of a texture can
1193 // not be attached to two different color attachments.
1194 if (state.getExtensions().webglCompatibility)
1195 {
1196 if (!mState.colorAttachmentsAreUniqueImages())
1197 {
1198 return GL_FRAMEBUFFER_UNSUPPORTED;
1199 }
1200 }
1201
Jamie Madill19fa1c62018-03-08 09:47:21 -05001202 // TODO(jmadill): Don't swallow an error here. http://anglebug.com/2372
1203 ANGLE_SWALLOW_ERR(syncState(context));
Kenneth Russellce8602a2017-10-03 18:23:08 -07001204 if (!mImpl->checkStatus(context))
Jamie Madillcc86d642015-11-24 13:00:07 -05001205 {
1206 return GL_FRAMEBUFFER_UNSUPPORTED;
1207 }
1208
1209 return GL_FRAMEBUFFER_COMPLETE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001210}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001211
Jamie Madill4928b7c2017-06-20 12:57:39 -04001212Error Framebuffer::discard(const Context *context, size_t count, const GLenum *attachments)
Austin Kinross08332632015-05-05 13:35:47 -07001213{
Jamie Madill05b35b22017-10-03 09:01:44 -04001214 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1215 // can be no-ops, so we should probably do that to ensure consistency.
1216 // TODO(jmadill): WebGL behaviour, and robust resource init behaviour without WebGL.
1217
Jamie Madill4928b7c2017-06-20 12:57:39 -04001218 return mImpl->discard(context, count, attachments);
Austin Kinross08332632015-05-05 13:35:47 -07001219}
1220
Jamie Madill4928b7c2017-06-20 12:57:39 -04001221Error Framebuffer::invalidate(const Context *context, size_t count, const GLenum *attachments)
Jamie Madill2d96b9e2014-08-29 15:46:47 -04001222{
Jamie Madill05b35b22017-10-03 09:01:44 -04001223 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1224 // can be no-ops, so we should probably do that to ensure consistency.
1225 // TODO(jmadill): WebGL behaviour, and robust resource init behaviour without WebGL.
1226
Jamie Madill4928b7c2017-06-20 12:57:39 -04001227 return mImpl->invalidate(context, count, attachments);
Jamie Madill2d96b9e2014-08-29 15:46:47 -04001228}
1229
Jamie Madill05b35b22017-10-03 09:01:44 -04001230bool Framebuffer::partialClearNeedsInit(const Context *context,
1231 bool color,
1232 bool depth,
1233 bool stencil)
1234{
1235 const auto &glState = context->getGLState();
1236
1237 if (!glState.isRobustResourceInitEnabled())
1238 {
1239 return false;
1240 }
1241
1242 // Scissors can affect clearing.
1243 // TODO(jmadill): Check for complete scissor overlap.
1244 if (glState.isScissorTestEnabled())
1245 {
1246 return true;
1247 }
1248
1249 // If colors masked, we must clear before we clear. Do a simple check.
1250 // TODO(jmadill): Filter out unused color channels from the test.
1251 if (color)
1252 {
1253 const auto &blend = glState.getBlendState();
1254 if (!(blend.colorMaskRed && blend.colorMaskGreen && blend.colorMaskBlue &&
1255 blend.colorMaskAlpha))
1256 {
1257 return true;
1258 }
1259 }
1260
1261 const auto &depthStencil = glState.getDepthStencilState();
1262 ASSERT(depthStencil.stencilBackMask == depthStencil.stencilMask);
1263 if (stencil && depthStencil.stencilMask != depthStencil.stencilWritemask)
1264 {
1265 return true;
1266 }
1267
1268 return false;
1269}
1270
Jamie Madill4928b7c2017-06-20 12:57:39 -04001271Error Framebuffer::invalidateSub(const Context *context,
1272 size_t count,
1273 const GLenum *attachments,
Jamie Madilld4442552018-02-27 22:03:47 -05001274 const Rectangle &area)
Jamie Madill400a4412014-08-29 15:46:45 -04001275{
Jamie Madill05b35b22017-10-03 09:01:44 -04001276 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1277 // can be no-ops, so we should probably do that to ensure consistency.
1278 // TODO(jmadill): Make a invalidate no-op in WebGL 2.0.
1279
Jamie Madill4928b7c2017-06-20 12:57:39 -04001280 return mImpl->invalidateSub(context, count, attachments, area);
Jamie Madill400a4412014-08-29 15:46:45 -04001281}
1282
Jamie Madilld4442552018-02-27 22:03:47 -05001283Error Framebuffer::clear(const Context *context, GLbitfield mask)
Geoff Langb04dc822014-12-01 12:02:02 -05001284{
Jamie Madill05b35b22017-10-03 09:01:44 -04001285 const auto &glState = context->getGLState();
1286 if (glState.isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -05001287 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001288 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001289 }
1290
Jamie Madill05b35b22017-10-03 09:01:44 -04001291 ANGLE_TRY(mImpl->clear(context, mask));
1292
Jamie Madill05b35b22017-10-03 09:01:44 -04001293 return NoError();
Geoff Langb04dc822014-12-01 12:02:02 -05001294}
1295
Jamie Madilld4442552018-02-27 22:03:47 -05001296Error Framebuffer::clearBufferfv(const Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001297 GLenum buffer,
1298 GLint drawbuffer,
1299 const GLfloat *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001300{
Jamie Madill05b35b22017-10-03 09:01:44 -04001301 if (context->getGLState().isRasterizerDiscardEnabled() ||
1302 IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001303 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001304 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001305 }
1306
Jamie Madill05b35b22017-10-03 09:01:44 -04001307 ANGLE_TRY(mImpl->clearBufferfv(context, buffer, drawbuffer, values));
1308
Jamie Madill05b35b22017-10-03 09:01:44 -04001309 return NoError();
Geoff Langb04dc822014-12-01 12:02:02 -05001310}
1311
Jamie Madilld4442552018-02-27 22:03:47 -05001312Error Framebuffer::clearBufferuiv(const Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001313 GLenum buffer,
1314 GLint drawbuffer,
1315 const GLuint *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001316{
Jamie Madill05b35b22017-10-03 09:01:44 -04001317 if (context->getGLState().isRasterizerDiscardEnabled() ||
1318 IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001319 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001320 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001321 }
1322
Jamie Madill05b35b22017-10-03 09:01:44 -04001323 ANGLE_TRY(mImpl->clearBufferuiv(context, buffer, drawbuffer, values));
1324
Jamie Madill05b35b22017-10-03 09:01:44 -04001325 return NoError();
Geoff Langb04dc822014-12-01 12:02:02 -05001326}
1327
Jamie Madilld4442552018-02-27 22:03:47 -05001328Error Framebuffer::clearBufferiv(const Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001329 GLenum buffer,
1330 GLint drawbuffer,
1331 const GLint *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001332{
Jamie Madill05b35b22017-10-03 09:01:44 -04001333 if (context->getGLState().isRasterizerDiscardEnabled() ||
1334 IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001335 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001336 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001337 }
1338
Jamie Madill05b35b22017-10-03 09:01:44 -04001339 ANGLE_TRY(mImpl->clearBufferiv(context, buffer, drawbuffer, values));
1340
Jamie Madill05b35b22017-10-03 09:01:44 -04001341 return NoError();
Geoff Langb04dc822014-12-01 12:02:02 -05001342}
1343
Jamie Madilld4442552018-02-27 22:03:47 -05001344Error Framebuffer::clearBufferfi(const Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001345 GLenum buffer,
1346 GLint drawbuffer,
1347 GLfloat depth,
1348 GLint stencil)
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 ANGLE_TRY(mImpl->clearBufferfi(context, buffer, drawbuffer, depth, stencil));
1357
Jamie Madill05b35b22017-10-03 09:01:44 -04001358 return NoError();
Geoff Langb04dc822014-12-01 12:02:02 -05001359}
1360
Jamie Madill4928b7c2017-06-20 12:57:39 -04001361GLenum Framebuffer::getImplementationColorReadFormat(const Context *context) const
Geoff Langbce529e2014-12-01 12:48:41 -05001362{
Jamie Madill4928b7c2017-06-20 12:57:39 -04001363 return mImpl->getImplementationColorReadFormat(context);
Geoff Langbce529e2014-12-01 12:48:41 -05001364}
1365
Jamie Madill4928b7c2017-06-20 12:57:39 -04001366GLenum Framebuffer::getImplementationColorReadType(const Context *context) const
Geoff Langbce529e2014-12-01 12:48:41 -05001367{
Jamie Madill4928b7c2017-06-20 12:57:39 -04001368 return mImpl->getImplementationColorReadType(context);
Geoff Langbce529e2014-12-01 12:48:41 -05001369}
1370
Jamie Madilld4442552018-02-27 22:03:47 -05001371Error Framebuffer::readPixels(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001372 const Rectangle &area,
Jamie Madill1b94d432015-08-07 13:23:23 -04001373 GLenum format,
1374 GLenum type,
Jamie Madill05b35b22017-10-03 09:01:44 -04001375 void *pixels)
Geoff Langbce529e2014-12-01 12:48:41 -05001376{
Jamie Madill05b35b22017-10-03 09:01:44 -04001377 ANGLE_TRY(ensureReadAttachmentInitialized(context, GL_COLOR_BUFFER_BIT));
Jamie Madill362876b2016-06-16 14:46:59 -04001378 ANGLE_TRY(mImpl->readPixels(context, area, format, type, pixels));
Geoff Lang520c4ae2015-05-05 13:12:36 -04001379
Jamie Madilld4442552018-02-27 22:03:47 -05001380 Buffer *unpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Lang520c4ae2015-05-05 13:12:36 -04001381 if (unpackBuffer)
1382 {
1383 unpackBuffer->onPixelUnpack();
1384 }
1385
Jamie Madill362876b2016-06-16 14:46:59 -04001386 return NoError();
Geoff Langbce529e2014-12-01 12:48:41 -05001387}
1388
Jamie Madilld4442552018-02-27 22:03:47 -05001389Error Framebuffer::blit(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001390 const Rectangle &sourceArea,
1391 const Rectangle &destArea,
Geoff Lang242468f2015-09-24 14:15:41 -04001392 GLbitfield mask,
Jamie Madill8415b5f2016-04-26 13:41:39 -04001393 GLenum filter)
Geoff Lang54bd5a42014-12-01 12:51:04 -05001394{
He Yunchao6be602d2016-12-22 14:33:07 +08001395 GLbitfield blitMask = mask;
1396
1397 // Note that blitting is called against draw framebuffer.
1398 // See the code in gl::Context::blitFramebuffer.
1399 if ((mask & GL_COLOR_BUFFER_BIT) && !hasEnabledDrawBuffer())
1400 {
1401 blitMask &= ~GL_COLOR_BUFFER_BIT;
1402 }
1403
1404 if ((mask & GL_STENCIL_BUFFER_BIT) && mState.getStencilAttachment() == nullptr)
1405 {
1406 blitMask &= ~GL_STENCIL_BUFFER_BIT;
1407 }
1408
1409 if ((mask & GL_DEPTH_BUFFER_BIT) && mState.getDepthAttachment() == nullptr)
1410 {
1411 blitMask &= ~GL_DEPTH_BUFFER_BIT;
1412 }
1413
1414 if (!blitMask)
1415 {
1416 return NoError();
1417 }
1418
Jamie Madill05b35b22017-10-03 09:01:44 -04001419 auto *sourceFBO = context->getGLState().getReadFramebuffer();
1420 ANGLE_TRY(sourceFBO->ensureReadAttachmentInitialized(context, blitMask));
1421
1422 // TODO(jmadill): Only clear if not the full FBO dimensions, and only specified bitmask.
1423 ANGLE_TRY(ensureDrawAttachmentsInitialized(context));
1424
He Yunchao6be602d2016-12-22 14:33:07 +08001425 return mImpl->blit(context, sourceArea, destArea, blitMask, filter);
Geoff Lang54bd5a42014-12-01 12:51:04 -05001426}
1427
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001428int Framebuffer::getSamples(const Context *context)
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001429{
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001430 if (complete(context))
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001431 {
Jamie Madill9c335862017-07-18 11:51:38 -04001432 return getCachedSamples(context);
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001433 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001434
1435 return 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001436}
1437
Jamie Madill9c335862017-07-18 11:51:38 -04001438int Framebuffer::getCachedSamples(const Context *context)
1439{
1440 // For a complete framebuffer, all attachments must have the same sample count.
1441 // In this case return the first nonzero sample size.
1442 const auto *firstNonNullAttachment = mState.getFirstNonNullAttachment();
1443 if (firstNonNullAttachment)
1444 {
1445 ASSERT(firstNonNullAttachment->isAttached());
1446 return firstNonNullAttachment->getSamples();
1447 }
1448
1449 // No attachments found.
1450 return 0;
1451}
1452
Corentin Wallezccab69d2017-01-27 16:57:15 -05001453Error Framebuffer::getSamplePosition(size_t index, GLfloat *xy) const
1454{
1455 ANGLE_TRY(mImpl->getSamplePosition(index, xy));
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001456 return NoError();
Corentin Wallezccab69d2017-01-27 16:57:15 -05001457}
1458
Jamie Madille261b442014-06-25 12:42:21 -04001459bool Framebuffer::hasValidDepthStencil() const
1460{
Jamie Madill48ef11b2016-04-27 15:21:52 -04001461 return mState.getDepthStencilAttachment() != nullptr;
Jamie Madille261b442014-06-25 12:42:21 -04001462}
1463
Jamie Madilla02315b2017-02-23 14:14:47 -05001464void Framebuffer::setAttachment(const Context *context,
1465 GLenum type,
Jamie Madill2d06b732015-04-20 12:53:28 -04001466 GLenum binding,
1467 const ImageIndex &textureIndex,
1468 FramebufferAttachmentObject *resource)
Geoff Langab75a052014-10-15 12:56:37 -04001469{
Martin Radev5dae57b2017-07-14 16:15:55 +03001470 setAttachment(context, type, binding, textureIndex, resource,
1471 FramebufferAttachment::kDefaultNumViews,
1472 FramebufferAttachment::kDefaultBaseViewIndex,
1473 FramebufferAttachment::kDefaultMultiviewLayout,
1474 FramebufferAttachment::kDefaultViewportOffsets);
1475}
1476
1477void Framebuffer::setAttachment(const Context *context,
1478 GLenum type,
1479 GLenum binding,
1480 const ImageIndex &textureIndex,
1481 FramebufferAttachmentObject *resource,
1482 GLsizei numViews,
1483 GLuint baseViewIndex,
1484 GLenum multiviewLayout,
1485 const GLint *viewportOffsets)
1486{
Jamie Madilla02315b2017-02-23 14:14:47 -05001487 // Context may be null in unit tests.
1488 if (!context || !context->isWebGL1())
1489 {
Martin Radev5dae57b2017-07-14 16:15:55 +03001490 setAttachmentImpl(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
1491 multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001492 return;
1493 }
1494
1495 switch (binding)
1496 {
1497 case GL_DEPTH_STENCIL:
1498 case GL_DEPTH_STENCIL_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001499 mState.mWebGLDepthStencilAttachment.attach(context, type, binding, textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001500 resource, numViews, baseViewIndex,
1501 multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001502 break;
1503 case GL_DEPTH:
1504 case GL_DEPTH_ATTACHMENT:
Martin Radev5dae57b2017-07-14 16:15:55 +03001505 mState.mWebGLDepthAttachment.attach(context, type, binding, textureIndex, resource,
1506 numViews, baseViewIndex, multiviewLayout,
1507 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001508 break;
1509 case GL_STENCIL:
1510 case GL_STENCIL_ATTACHMENT:
Martin Radev5dae57b2017-07-14 16:15:55 +03001511 mState.mWebGLStencilAttachment.attach(context, type, binding, textureIndex, resource,
1512 numViews, baseViewIndex, multiviewLayout,
1513 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001514 break;
1515 default:
Martin Radev5dae57b2017-07-14 16:15:55 +03001516 setAttachmentImpl(context, type, binding, textureIndex, resource, numViews,
1517 baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001518 return;
1519 }
1520
Martin Radev5dae57b2017-07-14 16:15:55 +03001521 commitWebGL1DepthStencilIfConsistent(context, numViews, baseViewIndex, multiviewLayout,
1522 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001523}
1524
Martin Radev82ef7742017-08-08 17:44:58 +03001525void Framebuffer::setAttachmentMultiviewLayered(const Context *context,
1526 GLenum type,
1527 GLenum binding,
1528 const ImageIndex &textureIndex,
1529 FramebufferAttachmentObject *resource,
1530 GLsizei numViews,
1531 GLint baseViewIndex)
1532{
1533 setAttachment(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
1534 GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE,
1535 FramebufferAttachment::kDefaultViewportOffsets);
1536}
1537
Martin Radev5dae57b2017-07-14 16:15:55 +03001538void Framebuffer::setAttachmentMultiviewSideBySide(const Context *context,
1539 GLenum type,
1540 GLenum binding,
1541 const ImageIndex &textureIndex,
1542 FramebufferAttachmentObject *resource,
1543 GLsizei numViews,
1544 const GLint *viewportOffsets)
1545{
1546 setAttachment(context, type, binding, textureIndex, resource, numViews,
1547 FramebufferAttachment::kDefaultBaseViewIndex,
1548 GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, viewportOffsets);
1549}
1550
1551void Framebuffer::commitWebGL1DepthStencilIfConsistent(const Context *context,
1552 GLsizei numViews,
1553 GLuint baseViewIndex,
1554 GLenum multiviewLayout,
1555 const GLint *viewportOffsets)
Jamie Madilla02315b2017-02-23 14:14:47 -05001556{
1557 int count = 0;
1558
1559 std::array<FramebufferAttachment *, 3> attachments = {{&mState.mWebGLDepthStencilAttachment,
1560 &mState.mWebGLDepthAttachment,
1561 &mState.mWebGLStencilAttachment}};
1562 for (FramebufferAttachment *attachment : attachments)
1563 {
1564 if (attachment->isAttached())
1565 {
1566 count++;
1567 }
1568 }
1569
1570 mState.mWebGLDepthStencilConsistent = (count <= 1);
1571 if (!mState.mWebGLDepthStencilConsistent)
1572 {
1573 // Inconsistent.
1574 return;
1575 }
1576
Geoff Lange466c552017-03-17 15:24:12 -04001577 auto getImageIndexIfTextureAttachment = [](const FramebufferAttachment &attachment) {
1578 if (attachment.type() == GL_TEXTURE)
1579 {
1580 return attachment.getTextureImageIndex();
1581 }
1582 else
1583 {
1584 return ImageIndex::MakeInvalid();
1585 }
1586 };
1587
Jamie Madilla02315b2017-02-23 14:14:47 -05001588 if (mState.mWebGLDepthAttachment.isAttached())
1589 {
1590 const auto &depth = mState.mWebGLDepthAttachment;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001591 setAttachmentImpl(context, depth.type(), GL_DEPTH_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001592 getImageIndexIfTextureAttachment(depth), depth.getResource(), numViews,
1593 baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001594 setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex::MakeInvalid(),
Martin Radev5dae57b2017-07-14 16:15:55 +03001595 nullptr, numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001596 }
1597 else if (mState.mWebGLStencilAttachment.isAttached())
1598 {
1599 const auto &stencil = mState.mWebGLStencilAttachment;
Martin Radev5dae57b2017-07-14 16:15:55 +03001600 setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex::MakeInvalid(), nullptr,
1601 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001602 setAttachmentImpl(context, stencil.type(), GL_STENCIL_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001603 getImageIndexIfTextureAttachment(stencil), stencil.getResource(),
1604 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001605 }
1606 else if (mState.mWebGLDepthStencilAttachment.isAttached())
1607 {
1608 const auto &depthStencil = mState.mWebGLDepthStencilAttachment;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001609 setAttachmentImpl(context, depthStencil.type(), GL_DEPTH_ATTACHMENT,
Geoff Lange466c552017-03-17 15:24:12 -04001610 getImageIndexIfTextureAttachment(depthStencil),
Martin Radev5dae57b2017-07-14 16:15:55 +03001611 depthStencil.getResource(), numViews, baseViewIndex, multiviewLayout,
1612 viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001613 setAttachmentImpl(context, depthStencil.type(), GL_STENCIL_ATTACHMENT,
Geoff Lange466c552017-03-17 15:24:12 -04001614 getImageIndexIfTextureAttachment(depthStencil),
Martin Radev5dae57b2017-07-14 16:15:55 +03001615 depthStencil.getResource(), numViews, baseViewIndex, multiviewLayout,
1616 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001617 }
1618 else
1619 {
Martin Radev5dae57b2017-07-14 16:15:55 +03001620 setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex::MakeInvalid(), nullptr,
1621 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001622 setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex::MakeInvalid(),
Martin Radev5dae57b2017-07-14 16:15:55 +03001623 nullptr, numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001624 }
1625}
1626
Jamie Madill4928b7c2017-06-20 12:57:39 -04001627void Framebuffer::setAttachmentImpl(const Context *context,
1628 GLenum type,
Jamie Madilla02315b2017-02-23 14:14:47 -05001629 GLenum binding,
1630 const ImageIndex &textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001631 FramebufferAttachmentObject *resource,
1632 GLsizei numViews,
1633 GLuint baseViewIndex,
1634 GLenum multiviewLayout,
1635 const GLint *viewportOffsets)
Jamie Madilla02315b2017-02-23 14:14:47 -05001636{
Jamie Madilla02315b2017-02-23 14:14:47 -05001637 switch (binding)
1638 {
Jamie Madillb8126692017-04-05 11:22:17 -04001639 case GL_DEPTH_STENCIL:
1640 case GL_DEPTH_STENCIL_ATTACHMENT:
1641 {
1642 // ensure this is a legitimate depth+stencil format
1643 FramebufferAttachmentObject *attachmentObj = resource;
1644 if (resource)
1645 {
Jamie Madill4fd95d52017-04-05 11:22:18 -04001646 const Format &format = resource->getAttachmentFormat(binding, textureIndex);
Jamie Madillb8126692017-04-05 11:22:17 -04001647 if (format.info->depthBits == 0 || format.info->stencilBits == 0)
1648 {
1649 // Attaching nullptr detaches the current attachment.
1650 attachmentObj = nullptr;
1651 }
1652 }
1653
Jamie Madill4928b7c2017-06-20 12:57:39 -04001654 updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
Jamie Madillb8126692017-04-05 11:22:17 -04001655 &mDirtyDepthAttachmentBinding, type, binding, textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001656 attachmentObj, numViews, baseViewIndex, multiviewLayout,
1657 viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001658 updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
Jamie Madillb8126692017-04-05 11:22:17 -04001659 &mDirtyStencilAttachmentBinding, type, binding, textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001660 attachmentObj, numViews, baseViewIndex, multiviewLayout,
1661 viewportOffsets);
Jamie Madill42975642017-10-12 12:31:51 -04001662 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001663 }
1664
Jamie Madilla02315b2017-02-23 14:14:47 -05001665 case GL_DEPTH:
1666 case GL_DEPTH_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001667 updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001668 &mDirtyDepthAttachmentBinding, type, binding, textureIndex, resource,
1669 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madill2d06b732015-04-20 12:53:28 -04001670 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001671
Jamie Madilla02315b2017-02-23 14:14:47 -05001672 case GL_STENCIL:
1673 case GL_STENCIL_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001674 updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001675 &mDirtyStencilAttachmentBinding, type, binding, textureIndex, resource,
1676 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001677 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001678
Jamie Madilla02315b2017-02-23 14:14:47 -05001679 case GL_BACK:
Geoff Lang8170eab2017-09-21 13:59:04 -04001680 updateAttachment(context, &mState.mColorAttachments[0], DIRTY_BIT_COLOR_ATTACHMENT_0,
1681 &mDirtyColorAttachmentBindings[0], type, binding, textureIndex,
1682 resource, numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001683 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001684
Jamie Madilla02315b2017-02-23 14:14:47 -05001685 default:
1686 {
1687 size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
1688 ASSERT(colorIndex < mState.mColorAttachments.size());
Jamie Madillb8126692017-04-05 11:22:17 -04001689 size_t dirtyBit = DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001690 updateAttachment(context, &mState.mColorAttachments[colorIndex], dirtyBit,
Jamie Madillb8126692017-04-05 11:22:17 -04001691 &mDirtyColorAttachmentBindings[colorIndex], type, binding,
Martin Radev5dae57b2017-07-14 16:15:55 +03001692 textureIndex, resource, numViews, baseViewIndex, multiviewLayout,
1693 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001694
Corentin Walleze7557742017-06-01 13:09:57 -04001695 // TODO(jmadill): ASSERT instead of checking the attachment exists in
1696 // formsRenderingFeedbackLoopWith
Jamie Madilla02315b2017-02-23 14:14:47 -05001697 bool enabled = (type != GL_NONE && getDrawBufferState(colorIndex) != GL_NONE);
1698 mState.mEnabledDrawBuffers.set(colorIndex, enabled);
Brandon Jones76746f92017-11-22 11:44:41 -08001699 mState.mDrawBufferTypeMask.setIndex(getDrawbufferWriteType(colorIndex), colorIndex);
Jamie Madill2d06b732015-04-20 12:53:28 -04001700 }
Jamie Madilla02315b2017-02-23 14:14:47 -05001701 break;
Geoff Langab75a052014-10-15 12:56:37 -04001702 }
Jamie Madill42975642017-10-12 12:31:51 -04001703
1704 mAttachedTextures.reset();
Geoff Langab75a052014-10-15 12:56:37 -04001705}
1706
Jamie Madill4928b7c2017-06-20 12:57:39 -04001707void Framebuffer::updateAttachment(const Context *context,
1708 FramebufferAttachment *attachment,
Jamie Madillb8126692017-04-05 11:22:17 -04001709 size_t dirtyBit,
Jamie Madilld4442552018-02-27 22:03:47 -05001710 angle::ObserverBinding *onDirtyBinding,
Jamie Madillb8126692017-04-05 11:22:17 -04001711 GLenum type,
1712 GLenum binding,
1713 const ImageIndex &textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001714 FramebufferAttachmentObject *resource,
1715 GLsizei numViews,
1716 GLuint baseViewIndex,
1717 GLenum multiviewLayout,
1718 const GLint *viewportOffsets)
Jamie Madillb8126692017-04-05 11:22:17 -04001719{
Martin Radev5dae57b2017-07-14 16:15:55 +03001720 attachment->attach(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
1721 multiviewLayout, viewportOffsets);
Jamie Madillb8126692017-04-05 11:22:17 -04001722 mDirtyBits.set(dirtyBit);
Jamie Madill05b35b22017-10-03 09:01:44 -04001723 mState.mResourceNeedsInit.set(dirtyBit, attachment->initState() == InitState::MayNeedInit);
Jamie Madill888081d2018-02-27 00:24:46 -05001724 onDirtyBinding->bind(resource ? resource->getSubject() : nullptr);
Jamie Madillb8126692017-04-05 11:22:17 -04001725}
1726
Jamie Madilla02315b2017-02-23 14:14:47 -05001727void Framebuffer::resetAttachment(const Context *context, GLenum binding)
Jamie Madill2d06b732015-04-20 12:53:28 -04001728{
Jamie Madilla02315b2017-02-23 14:14:47 -05001729 setAttachment(context, GL_NONE, binding, ImageIndex::MakeInvalid(), nullptr);
Jamie Madill2d06b732015-04-20 12:53:28 -04001730}
1731
Jamie Madill19fa1c62018-03-08 09:47:21 -05001732Error Framebuffer::syncState(const Context *context)
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001733{
1734 if (mDirtyBits.any())
1735 {
Jamie Madill888081d2018-02-27 00:24:46 -05001736 mDirtyBitsGuard = mDirtyBits;
Jamie Madill19fa1c62018-03-08 09:47:21 -05001737 ANGLE_TRY(mImpl->syncState(context, mDirtyBits));
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001738 mDirtyBits.reset();
Corentin Wallezccab69d2017-01-27 16:57:15 -05001739 if (mId != 0)
1740 {
1741 mCachedStatus.reset();
1742 }
Jamie Madill888081d2018-02-27 00:24:46 -05001743 mDirtyBitsGuard.reset();
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001744 }
Jamie Madill19fa1c62018-03-08 09:47:21 -05001745 return NoError();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001746}
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001747
Jamie Madilld4442552018-02-27 22:03:47 -05001748void Framebuffer::onSubjectStateChange(const Context *context,
1749 angle::SubjectIndex index,
1750 angle::SubjectMessage message)
Jamie Madill51f40ec2016-06-15 14:06:00 -04001751{
Jamie Madill888081d2018-02-27 00:24:46 -05001752 if (message == angle::SubjectMessage::DEPENDENT_DIRTY_BITS)
1753 {
1754 ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(index));
1755 mDirtyBits.set(index);
1756 context->getGLState().setFramebufferDirty(this);
1757 return;
1758 }
1759
Geoff Lang8170eab2017-09-21 13:59:04 -04001760 // Only reset the cached status if this is not the default framebuffer. The default framebuffer
1761 // will still use this channel to mark itself dirty.
1762 if (mId != 0)
1763 {
1764 // TOOD(jmadill): Make this only update individual attachments to do less work.
1765 mCachedStatus.reset();
1766 }
Jamie Madill05b35b22017-10-03 09:01:44 -04001767
Jamie Madilld4442552018-02-27 22:03:47 -05001768 FramebufferAttachment *attachment = getAttachmentFromSubjectIndex(index);
1769
Jamie Madill05b35b22017-10-03 09:01:44 -04001770 // Mark the appropriate init flag.
Jamie Madilld4442552018-02-27 22:03:47 -05001771 mState.mResourceNeedsInit.set(index, attachment->initState() == InitState::MayNeedInit);
1772}
1773
1774FramebufferAttachment *Framebuffer::getAttachmentFromSubjectIndex(angle::SubjectIndex index)
1775{
1776 switch (index)
1777 {
1778 case DIRTY_BIT_DEPTH_ATTACHMENT:
1779 return &mState.mDepthAttachment;
1780 case DIRTY_BIT_STENCIL_ATTACHMENT:
1781 return &mState.mStencilAttachment;
1782 default:
1783 size_t colorIndex = (index - DIRTY_BIT_COLOR_ATTACHMENT_0);
1784 ASSERT(colorIndex < mState.mColorAttachments.size());
1785 return &mState.mColorAttachments[colorIndex];
1786 }
Jamie Madill51f40ec2016-06-15 14:06:00 -04001787}
1788
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001789bool Framebuffer::complete(const Context *context)
Jamie Madill51f40ec2016-06-15 14:06:00 -04001790{
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001791 return (checkStatus(context) == GL_FRAMEBUFFER_COMPLETE);
1792}
1793
1794bool Framebuffer::cachedComplete() const
1795{
1796 return (mCachedStatus.valid() && mCachedStatus == GL_FRAMEBUFFER_COMPLETE);
Jamie Madill51f40ec2016-06-15 14:06:00 -04001797}
1798
Jamie Madilla4595b82017-01-11 17:36:34 -05001799bool Framebuffer::formsRenderingFeedbackLoopWith(const State &state) const
1800{
1801 const Program *program = state.getProgram();
1802
1803 // TODO(jmadill): Default framebuffer feedback loops.
1804 if (mId == 0)
1805 {
1806 return false;
1807 }
1808
1809 // The bitset will skip inactive draw buffers.
Jamie Madill6de51852017-04-12 09:53:01 -04001810 for (size_t drawIndex : mState.mEnabledDrawBuffers)
Jamie Madilla4595b82017-01-11 17:36:34 -05001811 {
Jamie Madill5aca1932017-07-21 12:22:01 -04001812 const FramebufferAttachment &attachment = mState.mColorAttachments[drawIndex];
1813 ASSERT(attachment.isAttached());
1814 if (attachment.type() == GL_TEXTURE)
Jamie Madilla4595b82017-01-11 17:36:34 -05001815 {
1816 // Validate the feedback loop.
Jamie Madill5aca1932017-07-21 12:22:01 -04001817 if (program->samplesFromTexture(state, attachment.id()))
Jamie Madilla4595b82017-01-11 17:36:34 -05001818 {
1819 return true;
1820 }
1821 }
1822 }
1823
Jamie Madill1d37bc52017-02-02 19:59:58 -05001824 // Validate depth-stencil feedback loop.
1825 const auto &dsState = state.getDepthStencilState();
1826
1827 // We can skip the feedback loop checks if depth/stencil is masked out or disabled.
1828 const FramebufferAttachment *depth = getDepthbuffer();
1829 if (depth && depth->type() == GL_TEXTURE && dsState.depthTest && dsState.depthMask)
1830 {
1831 if (program->samplesFromTexture(state, depth->id()))
1832 {
1833 return true;
1834 }
1835 }
1836
1837 // Note: we assume the front and back masks are the same for WebGL.
1838 const FramebufferAttachment *stencil = getStencilbuffer();
1839 ASSERT(dsState.stencilBackWritemask == dsState.stencilWritemask);
1840 if (stencil && stencil->type() == GL_TEXTURE && dsState.stencilTest &&
1841 dsState.stencilWritemask != 0)
1842 {
1843 // Skip the feedback loop check if depth/stencil point to the same resource.
1844 if (!depth || *stencil != *depth)
1845 {
1846 if (program->samplesFromTexture(state, stencil->id()))
1847 {
1848 return true;
1849 }
1850 }
1851 }
1852
Jamie Madilla4595b82017-01-11 17:36:34 -05001853 return false;
1854}
1855
Jamie Madillfd3dd432017-02-02 19:59:59 -05001856bool Framebuffer::formsCopyingFeedbackLoopWith(GLuint copyTextureID,
1857 GLint copyTextureLevel,
1858 GLint copyTextureLayer) const
Jamie Madillf695a3a2017-01-11 17:36:35 -05001859{
1860 if (mId == 0)
1861 {
1862 // It seems impossible to form a texture copying feedback loop with the default FBO.
1863 return false;
1864 }
1865
1866 const FramebufferAttachment *readAttachment = getReadColorbuffer();
1867 ASSERT(readAttachment);
1868
1869 if (readAttachment->isTextureWithId(copyTextureID))
1870 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05001871 const auto &imageIndex = readAttachment->getTextureImageIndex();
1872 if (imageIndex.mipIndex == copyTextureLevel)
Jamie Madillf695a3a2017-01-11 17:36:35 -05001873 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05001874 // Check 3D/Array texture layers.
1875 return imageIndex.layerIndex == ImageIndex::ENTIRE_LEVEL ||
1876 copyTextureLayer == ImageIndex::ENTIRE_LEVEL ||
1877 imageIndex.layerIndex == copyTextureLayer;
Jamie Madillf695a3a2017-01-11 17:36:35 -05001878 }
1879 }
1880 return false;
1881}
1882
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001883GLint Framebuffer::getDefaultWidth() const
1884{
1885 return mState.getDefaultWidth();
1886}
1887
1888GLint Framebuffer::getDefaultHeight() const
1889{
1890 return mState.getDefaultHeight();
1891}
1892
1893GLint Framebuffer::getDefaultSamples() const
1894{
1895 return mState.getDefaultSamples();
1896}
1897
Geoff Lang92019432017-11-20 13:09:34 -05001898bool Framebuffer::getDefaultFixedSampleLocations() const
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001899{
1900 return mState.getDefaultFixedSampleLocations();
1901}
1902
1903void Framebuffer::setDefaultWidth(GLint defaultWidth)
1904{
1905 mState.mDefaultWidth = defaultWidth;
1906 mDirtyBits.set(DIRTY_BIT_DEFAULT_WIDTH);
1907}
1908
1909void Framebuffer::setDefaultHeight(GLint defaultHeight)
1910{
1911 mState.mDefaultHeight = defaultHeight;
1912 mDirtyBits.set(DIRTY_BIT_DEFAULT_HEIGHT);
1913}
1914
1915void Framebuffer::setDefaultSamples(GLint defaultSamples)
1916{
1917 mState.mDefaultSamples = defaultSamples;
1918 mDirtyBits.set(DIRTY_BIT_DEFAULT_SAMPLES);
1919}
1920
Geoff Lang92019432017-11-20 13:09:34 -05001921void Framebuffer::setDefaultFixedSampleLocations(bool defaultFixedSampleLocations)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001922{
1923 mState.mDefaultFixedSampleLocations = defaultFixedSampleLocations;
1924 mDirtyBits.set(DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS);
1925}
1926
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001927// TODO(jmadill): Remove this kludge.
1928GLenum Framebuffer::checkStatus(const ValidationContext *context)
1929{
1930 return checkStatus(static_cast<const Context *>(context));
1931}
1932
1933int Framebuffer::getSamples(const ValidationContext *context)
1934{
1935 return getSamples(static_cast<const Context *>(context));
1936}
1937
Martin Radev14a26ae2017-07-24 15:56:29 +03001938GLsizei Framebuffer::getNumViews() const
1939{
Martin Radev5c00d0d2017-08-07 10:06:59 +03001940 return mState.getNumViews();
Martin Radev14a26ae2017-07-24 15:56:29 +03001941}
1942
Martin Radev4e619f52017-08-09 11:50:06 +03001943GLint Framebuffer::getBaseViewIndex() const
1944{
1945 return mState.getBaseViewIndex();
1946}
1947
Martin Radev878c8b12017-07-28 09:51:04 +03001948const std::vector<Offset> *Framebuffer::getViewportOffsets() const
1949{
Martin Radev5c00d0d2017-08-07 10:06:59 +03001950 return mState.getViewportOffsets();
Martin Radev878c8b12017-07-28 09:51:04 +03001951}
1952
1953GLenum Framebuffer::getMultiviewLayout() const
1954{
Martin Radev5c00d0d2017-08-07 10:06:59 +03001955 return mState.getMultiviewLayout();
Martin Radev878c8b12017-07-28 09:51:04 +03001956}
1957
Geoff Langd4fff502017-09-22 11:28:28 -04001958Error Framebuffer::ensureClearAttachmentsInitialized(const Context *context, GLbitfield mask)
1959{
1960 const auto &glState = context->getGLState();
1961 if (!context->isRobustResourceInitEnabled() || glState.isRasterizerDiscardEnabled())
1962 {
1963 return NoError();
1964 }
1965
1966 const auto &blend = glState.getBlendState();
1967 const auto &depthStencil = glState.getDepthStencilState();
1968
1969 bool color = (mask & GL_COLOR_BUFFER_BIT) != 0 && !IsColorMaskedOut(blend);
1970 bool depth = (mask & GL_DEPTH_BUFFER_BIT) != 0 && !IsDepthMaskedOut(depthStencil);
1971 bool stencil = (mask & GL_STENCIL_BUFFER_BIT) != 0 && !IsStencilMaskedOut(depthStencil);
1972
1973 if (!color && !depth && !stencil)
1974 {
1975 return NoError();
1976 }
1977
1978 if (partialClearNeedsInit(context, color, depth, stencil))
1979 {
1980 ANGLE_TRY(ensureDrawAttachmentsInitialized(context));
1981 }
1982
1983 // If the impl encounters an error during a a full (non-partial) clear, the attachments will
1984 // still be marked initialized. This simplifies design, allowing this method to be called before
1985 // the clear.
1986 markDrawAttachmentsInitialized(color, depth, stencil);
1987
1988 return NoError();
1989}
1990
1991Error Framebuffer::ensureClearBufferAttachmentsInitialized(const Context *context,
1992 GLenum buffer,
1993 GLint drawbuffer)
1994{
1995 if (!context->isRobustResourceInitEnabled() ||
1996 context->getGLState().isRasterizerDiscardEnabled() ||
1997 IsClearBufferMaskedOut(context, buffer))
1998 {
1999 return NoError();
2000 }
2001
2002 if (partialBufferClearNeedsInit(context, buffer))
2003 {
2004 ANGLE_TRY(ensureBufferInitialized(context, buffer, drawbuffer));
2005 }
2006
2007 // If the impl encounters an error during a a full (non-partial) clear, the attachments will
2008 // still be marked initialized. This simplifies design, allowing this method to be called before
2009 // the clear.
2010 markBufferInitialized(buffer, drawbuffer);
2011
2012 return NoError();
2013}
2014
Jamie Madill05b35b22017-10-03 09:01:44 -04002015Error Framebuffer::ensureDrawAttachmentsInitialized(const Context *context)
2016{
2017 if (!context->isRobustResourceInitEnabled())
2018 {
2019 return NoError();
2020 }
2021
2022 // Note: we don't actually filter by the draw attachment enum. Just init everything.
2023 for (size_t bit : mState.mResourceNeedsInit)
2024 {
2025 switch (bit)
2026 {
2027 case DIRTY_BIT_DEPTH_ATTACHMENT:
2028 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2029 break;
2030 case DIRTY_BIT_STENCIL_ATTACHMENT:
2031 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2032 break;
2033 default:
2034 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[bit]));
2035 break;
2036 }
2037 }
2038
2039 mState.mResourceNeedsInit.reset();
2040 return NoError();
2041}
2042
2043Error Framebuffer::ensureReadAttachmentInitialized(const Context *context, GLbitfield blitMask)
2044{
2045 if (!context->isRobustResourceInitEnabled() || mState.mResourceNeedsInit.none())
2046 {
2047 return NoError();
2048 }
2049
2050 if ((blitMask & GL_COLOR_BUFFER_BIT) != 0 && mState.mReadBufferState != GL_NONE)
2051 {
2052 size_t readIndex = mState.getReadIndex();
2053 if (mState.mResourceNeedsInit[readIndex])
2054 {
2055 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[readIndex]));
2056 mState.mResourceNeedsInit.reset(readIndex);
2057 }
2058 }
2059
2060 if ((blitMask & GL_DEPTH_BUFFER_BIT) != 0 && hasDepth())
2061 {
2062 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2063 {
2064 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2065 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2066 }
2067 }
2068
2069 if ((blitMask & GL_STENCIL_BUFFER_BIT) != 0 && hasStencil())
2070 {
2071 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2072 {
2073 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2074 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2075 }
2076 }
2077
2078 return NoError();
2079}
2080
2081void Framebuffer::markDrawAttachmentsInitialized(bool color, bool depth, bool stencil)
2082{
2083 // Mark attachments as initialized.
2084 if (color)
2085 {
2086 for (auto colorIndex : mState.mEnabledDrawBuffers)
2087 {
2088 auto &colorAttachment = mState.mColorAttachments[colorIndex];
2089 ASSERT(colorAttachment.isAttached());
2090 colorAttachment.setInitState(InitState::Initialized);
2091 mState.mResourceNeedsInit.reset(colorIndex);
2092 }
2093 }
2094
2095 if (depth && mState.mDepthAttachment.isAttached())
2096 {
2097 mState.mDepthAttachment.setInitState(InitState::Initialized);
2098 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2099 }
2100
2101 if (stencil && mState.mStencilAttachment.isAttached())
2102 {
2103 mState.mStencilAttachment.setInitState(InitState::Initialized);
2104 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2105 }
2106}
2107
2108void Framebuffer::markBufferInitialized(GLenum bufferType, GLint bufferIndex)
2109{
2110 switch (bufferType)
2111 {
2112 case GL_COLOR:
2113 {
2114 ASSERT(bufferIndex < static_cast<GLint>(mState.mColorAttachments.size()));
2115 if (mState.mColorAttachments[bufferIndex].isAttached())
2116 {
2117 mState.mColorAttachments[bufferIndex].setInitState(InitState::Initialized);
2118 mState.mResourceNeedsInit.reset(bufferIndex);
2119 }
2120 break;
2121 }
2122 case GL_DEPTH:
2123 {
2124 if (mState.mDepthAttachment.isAttached())
2125 {
2126 mState.mDepthAttachment.setInitState(InitState::Initialized);
2127 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2128 }
2129 break;
2130 }
2131 case GL_STENCIL:
2132 {
2133 if (mState.mStencilAttachment.isAttached())
2134 {
2135 mState.mStencilAttachment.setInitState(InitState::Initialized);
2136 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2137 }
2138 break;
2139 }
2140 case GL_DEPTH_STENCIL:
2141 {
2142 if (mState.mDepthAttachment.isAttached())
2143 {
2144 mState.mDepthAttachment.setInitState(InitState::Initialized);
2145 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2146 }
2147 if (mState.mStencilAttachment.isAttached())
2148 {
2149 mState.mStencilAttachment.setInitState(InitState::Initialized);
2150 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2151 }
2152 break;
2153 }
2154 default:
2155 UNREACHABLE();
2156 break;
2157 }
2158}
2159
2160Box Framebuffer::getDimensions() const
2161{
2162 return mState.getDimensions();
2163}
2164
2165Error Framebuffer::ensureBufferInitialized(const Context *context,
2166 GLenum bufferType,
2167 GLint bufferIndex)
2168{
2169 ASSERT(context->isRobustResourceInitEnabled());
2170
2171 if (mState.mResourceNeedsInit.none())
2172 {
2173 return NoError();
2174 }
2175
2176 switch (bufferType)
2177 {
2178 case GL_COLOR:
2179 {
2180 ASSERT(bufferIndex < static_cast<GLint>(mState.mColorAttachments.size()));
2181 if (mState.mResourceNeedsInit[bufferIndex])
2182 {
2183 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[bufferIndex]));
2184 mState.mResourceNeedsInit.reset(bufferIndex);
2185 }
2186 break;
2187 }
2188 case GL_DEPTH:
2189 {
2190 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2191 {
2192 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2193 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2194 }
2195 break;
2196 }
2197 case GL_STENCIL:
2198 {
2199 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2200 {
2201 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2202 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2203 }
2204 break;
2205 }
2206 case GL_DEPTH_STENCIL:
2207 {
2208 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2209 {
2210 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2211 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2212 }
2213 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2214 {
2215 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2216 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2217 }
2218 break;
2219 }
2220 default:
2221 UNREACHABLE();
2222 break;
2223 }
2224
2225 return NoError();
2226}
2227
2228bool Framebuffer::partialBufferClearNeedsInit(const Context *context, GLenum bufferType)
2229{
2230 if (!context->isRobustResourceInitEnabled() || mState.mResourceNeedsInit.none())
2231 {
2232 return false;
2233 }
2234
2235 switch (bufferType)
2236 {
2237 case GL_COLOR:
2238 return partialClearNeedsInit(context, true, false, false);
2239 case GL_DEPTH:
2240 return partialClearNeedsInit(context, false, true, false);
2241 case GL_STENCIL:
2242 return partialClearNeedsInit(context, false, false, true);
2243 case GL_DEPTH_STENCIL:
2244 return partialClearNeedsInit(context, false, true, true);
2245 default:
2246 UNREACHABLE();
2247 return false;
2248 }
2249}
2250
Jamie Madill42975642017-10-12 12:31:51 -04002251bool Framebuffer::hasTextureAttachment(const Texture *texture) const
2252{
2253 if (!mAttachedTextures.valid())
2254 {
2255 std::set<const FramebufferAttachmentObject *> attachedTextures;
2256
2257 for (const auto &colorAttachment : mState.mColorAttachments)
2258 {
2259 if (colorAttachment.isAttached() && colorAttachment.type() == GL_TEXTURE)
2260 {
2261 attachedTextures.insert(colorAttachment.getResource());
2262 }
2263 }
2264
2265 if (mState.mDepthAttachment.isAttached() && mState.mDepthAttachment.type() == GL_TEXTURE)
2266 {
2267 attachedTextures.insert(mState.mDepthAttachment.getResource());
2268 }
2269
2270 if (mState.mStencilAttachment.isAttached() &&
2271 mState.mStencilAttachment.type() == GL_TEXTURE)
2272 {
2273 attachedTextures.insert(mState.mStencilAttachment.getResource());
2274 }
2275
2276 mAttachedTextures = std::move(attachedTextures);
2277 }
2278
2279 return (mAttachedTextures.value().count(texture) > 0);
2280}
2281
Jamie Madill60ec6ea2016-01-22 15:27:19 -05002282} // namespace gl