blob: e991bb3250149843cc5381eda2d0875280a30b16 [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 }
Mingyu Hu7d64c482019-03-12 14:27:40 -070052 if (firstAttachment->isMultiview() != secondAttachment->isMultiview())
Martin Radev9bc9a322017-07-21 14:28:17 +030053 {
54 return false;
55 }
56 return true;
57}
58
Geoff Lang9f10b772017-05-16 15:51:03 -040059bool CheckAttachmentCompleteness(const Context *context, const FramebufferAttachment &attachment)
60{
61 ASSERT(attachment.isAttached());
62
63 const Extents &size = attachment.getSize();
64 if (size.width == 0 || size.height == 0)
65 {
66 return false;
67 }
68
Yuly Novikov2eb54072018-08-22 16:41:26 -040069 if (!attachment.isRenderable(context))
Geoff Lang9f10b772017-05-16 15:51:03 -040070 {
71 return false;
72 }
73
74 if (attachment.type() == GL_TEXTURE)
75 {
Jiawei Shaoa8802472018-05-28 11:17:47 +080076 // [EXT_geometry_shader] Section 9.4.1, "Framebuffer Completeness"
77 // If <image> is a three-dimensional texture or a two-dimensional array texture and the
78 // attachment is not layered, the selected layer is less than the depth or layer count,
79 // respectively, of the texture.
80 if (!attachment.isLayered())
Geoff Lang9f10b772017-05-16 15:51:03 -040081 {
Jiawei Shaoa8802472018-05-28 11:17:47 +080082 if (attachment.layer() >= size.depth)
83 {
84 return false;
85 }
86 }
87 // If <image> is a three-dimensional texture or a two-dimensional array texture and the
88 // attachment is layered, the depth or layer count, respectively, of the texture is less
89 // than or equal to the value of MAX_FRAMEBUFFER_LAYERS_EXT.
90 else
91 {
92 if (static_cast<GLuint>(size.depth) >= context->getCaps().maxFramebufferLayers)
93 {
94 return false;
95 }
Geoff Lang9f10b772017-05-16 15:51:03 -040096 }
97
98 // ES3 specifies that cube map texture attachments must be cube complete.
99 // This language is missing from the ES2 spec, but we enforce it here because some
100 // desktop OpenGL drivers also enforce this validation.
101 // TODO(jmadill): Check if OpenGL ES2 drivers enforce cube completeness.
102 const Texture *texture = attachment.getTexture();
103 ASSERT(texture);
Corentin Wallez99d492c2018-02-27 15:17:10 -0500104 if (texture->getType() == TextureType::CubeMap &&
Geoff Lang9f10b772017-05-16 15:51:03 -0400105 !texture->getTextureState().isCubeComplete())
106 {
107 return false;
108 }
Geoff Lang857c09d2017-05-16 15:55:04 -0400109
110 if (!texture->getImmutableFormat())
111 {
112 GLuint attachmentMipLevel = static_cast<GLuint>(attachment.mipLevel());
113
114 // From the ES 3.0 spec, pg 213:
115 // If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is TEXTURE and the value of
116 // FRAMEBUFFER_ATTACHMENT_OBJECT_NAME does not name an immutable-format texture,
117 // then the value of FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL must be in the
118 // range[levelbase, q], where levelbase is the value of TEXTURE_BASE_LEVEL and q is
119 // the effective maximum texture level defined in the Mipmapping discussion of
120 // section 3.8.10.4.
121 if (attachmentMipLevel < texture->getBaseLevel() ||
122 attachmentMipLevel > texture->getMipmapMaxLevel())
123 {
124 return false;
125 }
126
127 // Form the ES 3.0 spec, pg 213/214:
128 // If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is TEXTURE and the value of
129 // FRAMEBUFFER_ATTACHMENT_OBJECT_NAME does not name an immutable-format texture and
130 // the value of FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL is not levelbase, then the
131 // texture must be mipmap complete, and if FRAMEBUFFER_ATTACHMENT_OBJECT_NAME names
132 // a cubemap texture, the texture must also be cube complete.
133 if (attachmentMipLevel != texture->getBaseLevel() && !texture->isMipmapComplete())
134 {
135 return false;
136 }
137 }
Geoff Lang9f10b772017-05-16 15:51:03 -0400138 }
139
140 return true;
Jamie Madillc09ae152019-02-01 14:16:32 -0500141}
Geoff Lang9f10b772017-05-16 15:51:03 -0400142
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400143bool CheckAttachmentSampleCompleteness(const Context *context,
144 const FramebufferAttachment &attachment,
145 bool colorAttachment,
146 Optional<int> *samples,
Geoff Lang92019432017-11-20 13:09:34 -0500147 Optional<bool> *fixedSampleLocations)
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400148{
149 ASSERT(attachment.isAttached());
150
151 if (attachment.type() == GL_TEXTURE)
152 {
153 const Texture *texture = attachment.getTexture();
154 ASSERT(texture);
155
156 const ImageIndex &attachmentImageIndex = attachment.getTextureImageIndex();
Jiawei Shaoa8802472018-05-28 11:17:47 +0800157 bool fixedSampleloc = texture->getAttachmentFixedSampleLocations(attachmentImageIndex);
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400158 if (fixedSampleLocations->valid() && fixedSampleloc != fixedSampleLocations->value())
159 {
160 return false;
161 }
162 else
163 {
164 *fixedSampleLocations = fixedSampleloc;
165 }
166 }
167
168 if (samples->valid())
169 {
170 if (attachment.getSamples() != samples->value())
171 {
172 if (colorAttachment)
173 {
174 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
175 // all color attachments have the same number of samples for the FBO to be complete.
176 return false;
177 }
178 else
179 {
180 // CHROMIUM_framebuffer_mixed_samples allows a framebuffer to be considered complete
181 // when its depth or stencil samples are a multiple of the number of color samples.
182 if (!context->getExtensions().framebufferMixedSamples)
183 {
184 return false;
185 }
186
187 if ((attachment.getSamples() % std::max(samples->value(), 1)) != 0)
188 {
189 return false;
190 }
191 }
192 }
193 }
194 else
195 {
196 *samples = attachment.getSamples();
197 }
198
199 return true;
200}
201
Jamie Madill05b35b22017-10-03 09:01:44 -0400202// Needed to index into the attachment arrays/bitsets.
Jamie Madill682efdc2017-10-03 14:10:29 -0400203static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS) ==
Jamie Madilld4442552018-02-27 22:03:47 -0500204 Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX,
Jamie Madill05b35b22017-10-03 09:01:44 -0400205 "Framebuffer Dirty bit mismatch");
Jamie Madill682efdc2017-10-03 14:10:29 -0400206static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS) ==
Jamie Madilld4442552018-02-27 22:03:47 -0500207 Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT,
Jamie Madill05b35b22017-10-03 09:01:44 -0400208 "Framebuffer Dirty bit mismatch");
Jamie Madill682efdc2017-10-03 14:10:29 -0400209static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS + 1) ==
Jamie Madilld4442552018-02-27 22:03:47 -0500210 Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT,
Jamie Madill05b35b22017-10-03 09:01:44 -0400211 "Framebuffer Dirty bit mismatch");
212
Jamie Madill6f755b22018-10-09 12:48:54 -0400213angle::Result InitAttachment(const Context *context, FramebufferAttachment *attachment)
Jamie Madill05b35b22017-10-03 09:01:44 -0400214{
215 ASSERT(attachment->isAttached());
216 if (attachment->initState() == InitState::MayNeedInit)
217 {
218 ANGLE_TRY(attachment->initializeContents(context));
219 }
Jamie Madill7c985f52018-11-29 18:16:17 -0500220 return angle::Result::Continue;
Jamie Madill05b35b22017-10-03 09:01:44 -0400221}
222
223bool IsColorMaskedOut(const BlendState &blend)
224{
225 return (!blend.colorMaskRed && !blend.colorMaskGreen && !blend.colorMaskBlue &&
226 !blend.colorMaskAlpha);
227}
228
229bool IsDepthMaskedOut(const DepthStencilState &depthStencil)
230{
231 return !depthStencil.depthMask;
232}
233
234bool IsStencilMaskedOut(const DepthStencilState &depthStencil)
235{
236 return ((depthStencil.stencilMask & depthStencil.stencilWritemask) == 0);
237}
238
239bool IsClearBufferMaskedOut(const Context *context, GLenum buffer)
240{
241 switch (buffer)
242 {
243 case GL_COLOR:
Jamie Madillc3dc5d42018-12-30 12:12:04 -0500244 return IsColorMaskedOut(context->getState().getBlendState());
Jamie Madill05b35b22017-10-03 09:01:44 -0400245 case GL_DEPTH:
Jamie Madillc3dc5d42018-12-30 12:12:04 -0500246 return IsDepthMaskedOut(context->getState().getDepthStencilState());
Jamie Madill05b35b22017-10-03 09:01:44 -0400247 case GL_STENCIL:
Jamie Madillc3dc5d42018-12-30 12:12:04 -0500248 return IsStencilMaskedOut(context->getState().getDepthStencilState());
Jamie Madill05b35b22017-10-03 09:01:44 -0400249 case GL_DEPTH_STENCIL:
Jamie Madillc3dc5d42018-12-30 12:12:04 -0500250 return IsDepthMaskedOut(context->getState().getDepthStencilState()) &&
251 IsStencilMaskedOut(context->getState().getDepthStencilState());
Jamie Madill05b35b22017-10-03 09:01:44 -0400252 default:
253 UNREACHABLE();
254 return true;
255 }
256}
257
Jamie Madill362876b2016-06-16 14:46:59 -0400258} // anonymous namespace
Jamie Madilld1405e52015-03-05 15:41:39 -0500259
Jamie Madill6f60d052017-02-22 15:20:11 -0500260// This constructor is only used for default framebuffers.
Jamie Madill48ef11b2016-04-27 15:21:52 -0400261FramebufferState::FramebufferState()
Jamie Madill2274b652018-05-31 10:56:08 -0400262 : mId(0),
263 mLabel(),
Geoff Lang70d0f492015-12-10 17:45:46 -0500264 mColorAttachments(1),
Corentin Walleze7557742017-06-01 13:09:57 -0400265 mDrawBufferStates(1, GL_BACK),
Jamie Madill6f60d052017-02-22 15:20:11 -0500266 mReadBufferState(GL_BACK),
Brandon Jones76746f92017-11-22 11:44:41 -0800267 mDrawBufferTypeMask(),
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800268 mDefaultWidth(0),
269 mDefaultHeight(0),
270 mDefaultSamples(0),
Jamie Madilla02315b2017-02-23 14:14:47 -0500271 mDefaultFixedSampleLocations(GL_FALSE),
Jiawei Shaob1e91382018-05-17 14:33:55 +0800272 mDefaultLayers(0),
Jamie Madilla02315b2017-02-23 14:14:47 -0500273 mWebGLDepthStencilConsistent(true)
Corentin Wallez37c39792015-08-20 14:19:46 -0400274{
Geoff Langd90d3882017-03-21 10:49:54 -0400275 ASSERT(mDrawBufferStates.size() > 0);
Jamie Madilla4595b82017-01-11 17:36:34 -0500276 mEnabledDrawBuffers.set(0);
Corentin Wallez37c39792015-08-20 14:19:46 -0400277}
278
Jamie Madill2274b652018-05-31 10:56:08 -0400279FramebufferState::FramebufferState(const Caps &caps, GLuint id)
280 : mId(id),
281 mLabel(),
Geoff Lang70d0f492015-12-10 17:45:46 -0500282 mColorAttachments(caps.maxColorAttachments),
Jamie Madilld1405e52015-03-05 15:41:39 -0500283 mDrawBufferStates(caps.maxDrawBuffers, GL_NONE),
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800284 mReadBufferState(GL_COLOR_ATTACHMENT0_EXT),
Brandon Jones76746f92017-11-22 11:44:41 -0800285 mDrawBufferTypeMask(),
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800286 mDefaultWidth(0),
287 mDefaultHeight(0),
288 mDefaultSamples(0),
Jamie Madilla02315b2017-02-23 14:14:47 -0500289 mDefaultFixedSampleLocations(GL_FALSE),
Jiawei Shaob1e91382018-05-17 14:33:55 +0800290 mDefaultLayers(0),
Jamie Madilla02315b2017-02-23 14:14:47 -0500291 mWebGLDepthStencilConsistent(true)
Jamie Madilld1405e52015-03-05 15:41:39 -0500292{
Jamie Madill2274b652018-05-31 10:56:08 -0400293 ASSERT(mId != 0);
Geoff Langa15472a2015-08-11 11:48:03 -0400294 ASSERT(mDrawBufferStates.size() > 0);
Jamie Madilld1405e52015-03-05 15:41:39 -0500295 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
296}
297
Jamie Madillb980c562018-11-27 11:34:27 -0500298FramebufferState::~FramebufferState() {}
Jamie Madilld1405e52015-03-05 15:41:39 -0500299
Jamie Madill48ef11b2016-04-27 15:21:52 -0400300const std::string &FramebufferState::getLabel()
Geoff Lang70d0f492015-12-10 17:45:46 -0500301{
302 return mLabel;
303}
304
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800305const FramebufferAttachment *FramebufferState::getAttachment(const Context *context,
306 GLenum attachment) const
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400307{
308 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
309 {
310 return getColorAttachment(attachment - GL_COLOR_ATTACHMENT0);
311 }
312
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800313 // WebGL1 allows a developer to query for attachment parameters even when "inconsistant" (i.e.
314 // multiple conflicting attachment points) and requires us to return the framebuffer attachment
315 // associated with WebGL.
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400316 switch (attachment)
317 {
318 case GL_COLOR:
319 case GL_BACK:
320 return getColorAttachment(0);
321 case GL_DEPTH:
322 case GL_DEPTH_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800323 if (context->isWebGL1())
324 {
325 return getWebGLDepthAttachment();
326 }
327 else
328 {
329 return getDepthAttachment();
330 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400331 case GL_STENCIL:
332 case GL_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800333 if (context->isWebGL1())
334 {
335 return getWebGLStencilAttachment();
336 }
337 else
338 {
339 return getStencilAttachment();
340 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400341 case GL_DEPTH_STENCIL:
342 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800343 if (context->isWebGL1())
344 {
345 return getWebGLDepthStencilAttachment();
346 }
347 else
348 {
349 return getDepthStencilAttachment();
350 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400351 default:
352 UNREACHABLE();
353 return nullptr;
354 }
355}
356
Jamie Madill05b35b22017-10-03 09:01:44 -0400357size_t FramebufferState::getReadIndex() const
Jamie Madill7147f012015-03-05 15:41:40 -0500358{
Jamie Madill231c7f52017-04-26 13:45:37 -0400359 ASSERT(mReadBufferState == GL_BACK ||
360 (mReadBufferState >= GL_COLOR_ATTACHMENT0 && mReadBufferState <= GL_COLOR_ATTACHMENT15));
361 size_t readIndex = (mReadBufferState == GL_BACK
362 ? 0
363 : static_cast<size_t>(mReadBufferState - GL_COLOR_ATTACHMENT0));
Jamie Madill7147f012015-03-05 15:41:40 -0500364 ASSERT(readIndex < mColorAttachments.size());
Jamie Madill05b35b22017-10-03 09:01:44 -0400365 return readIndex;
366}
367
368const FramebufferAttachment *FramebufferState::getReadAttachment() const
369{
370 if (mReadBufferState == GL_NONE)
371 {
372 return nullptr;
373 }
374 size_t readIndex = getReadIndex();
Jamie Madill2d06b732015-04-20 12:53:28 -0400375 return mColorAttachments[readIndex].isAttached() ? &mColorAttachments[readIndex] : nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500376}
377
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500378const FramebufferAttachment *FramebufferState::getFirstNonNullAttachment() const
379{
380 auto *colorAttachment = getFirstColorAttachment();
381 if (colorAttachment)
382 {
383 return colorAttachment;
384 }
385 return getDepthOrStencilAttachment();
386}
387
Jamie Madill48ef11b2016-04-27 15:21:52 -0400388const FramebufferAttachment *FramebufferState::getFirstColorAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500389{
Jamie Madill2d06b732015-04-20 12:53:28 -0400390 for (const FramebufferAttachment &colorAttachment : mColorAttachments)
Jamie Madill7147f012015-03-05 15:41:40 -0500391 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400392 if (colorAttachment.isAttached())
Jamie Madill7147f012015-03-05 15:41:40 -0500393 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400394 return &colorAttachment;
Jamie Madill7147f012015-03-05 15:41:40 -0500395 }
396 }
397
398 return nullptr;
399}
400
Jamie Madill48ef11b2016-04-27 15:21:52 -0400401const FramebufferAttachment *FramebufferState::getDepthOrStencilAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500402{
Jamie Madill2d06b732015-04-20 12:53:28 -0400403 if (mDepthAttachment.isAttached())
404 {
405 return &mDepthAttachment;
406 }
407 if (mStencilAttachment.isAttached())
408 {
409 return &mStencilAttachment;
410 }
411 return nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500412}
413
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500414const FramebufferAttachment *FramebufferState::getStencilOrDepthStencilAttachment() const
415{
416 if (mStencilAttachment.isAttached())
417 {
418 return &mStencilAttachment;
419 }
420 return getDepthStencilAttachment();
421}
422
Jamie Madill48ef11b2016-04-27 15:21:52 -0400423const FramebufferAttachment *FramebufferState::getColorAttachment(size_t colorAttachment) const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400424{
425 ASSERT(colorAttachment < mColorAttachments.size());
Jamie Madill231c7f52017-04-26 13:45:37 -0400426 return mColorAttachments[colorAttachment].isAttached() ? &mColorAttachments[colorAttachment]
427 : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400428}
429
Jamie Madill48ef11b2016-04-27 15:21:52 -0400430const FramebufferAttachment *FramebufferState::getDepthAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400431{
Jamie Madill2d06b732015-04-20 12:53:28 -0400432 return mDepthAttachment.isAttached() ? &mDepthAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400433}
434
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800435const FramebufferAttachment *FramebufferState::getWebGLDepthAttachment() const
436{
437 return mWebGLDepthAttachment.isAttached() ? &mWebGLDepthAttachment : nullptr;
438}
439
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800440const FramebufferAttachment *FramebufferState::getWebGLDepthStencilAttachment() const
441{
442 return mWebGLDepthStencilAttachment.isAttached() ? &mWebGLDepthStencilAttachment : nullptr;
443}
444
Jamie Madill48ef11b2016-04-27 15:21:52 -0400445const FramebufferAttachment *FramebufferState::getStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400446{
Jamie Madill2d06b732015-04-20 12:53:28 -0400447 return mStencilAttachment.isAttached() ? &mStencilAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400448}
449
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800450const FramebufferAttachment *FramebufferState::getWebGLStencilAttachment() const
451{
452 return mWebGLStencilAttachment.isAttached() ? &mWebGLStencilAttachment : nullptr;
453}
454
Jamie Madill48ef11b2016-04-27 15:21:52 -0400455const FramebufferAttachment *FramebufferState::getDepthStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400456{
457 // A valid depth-stencil attachment has the same resource bound to both the
458 // depth and stencil attachment points.
Jamie Madill2d06b732015-04-20 12:53:28 -0400459 if (mDepthAttachment.isAttached() && mStencilAttachment.isAttached() &&
Jamie Madill44f26482016-11-18 12:49:15 -0500460 mDepthAttachment == mStencilAttachment)
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400461 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400462 return &mDepthAttachment;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400463 }
464
465 return nullptr;
466}
467
Jamie Madill48ef11b2016-04-27 15:21:52 -0400468bool FramebufferState::attachmentsHaveSameDimensions() const
Jamie Madillcc86d642015-11-24 13:00:07 -0500469{
470 Optional<Extents> attachmentSize;
471
Jamie Madill231c7f52017-04-26 13:45:37 -0400472 auto hasMismatchedSize = [&attachmentSize](const FramebufferAttachment &attachment) {
Jamie Madillcc86d642015-11-24 13:00:07 -0500473 if (!attachment.isAttached())
474 {
475 return false;
476 }
477
478 if (!attachmentSize.valid())
479 {
480 attachmentSize = attachment.getSize();
481 return false;
482 }
483
Jeff Gilbert8f8edd62017-10-31 14:26:30 -0700484 const auto &prevSize = attachmentSize.value();
485 const auto &curSize = attachment.getSize();
486 return (curSize.width != prevSize.width || curSize.height != prevSize.height);
Jamie Madillcc86d642015-11-24 13:00:07 -0500487 };
488
489 for (const auto &attachment : mColorAttachments)
490 {
491 if (hasMismatchedSize(attachment))
492 {
493 return false;
494 }
495 }
496
497 if (hasMismatchedSize(mDepthAttachment))
498 {
499 return false;
500 }
501
502 return !hasMismatchedSize(mStencilAttachment);
503}
504
Luc Ferron5bdf8bd2018-06-20 09:51:37 -0400505bool FramebufferState::hasSeparateDepthAndStencilAttachments() const
506{
507 // if we have both a depth and stencil buffer, they must refer to the same object
508 // since we only support packed_depth_stencil and not separate depth and stencil
509 return (getDepthAttachment() != nullptr && getStencilAttachment() != nullptr &&
510 getDepthStencilAttachment() == nullptr);
511}
512
Jamie Madilld4442552018-02-27 22:03:47 -0500513const FramebufferAttachment *FramebufferState::getDrawBuffer(size_t drawBufferIdx) const
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400514{
515 ASSERT(drawBufferIdx < mDrawBufferStates.size());
516 if (mDrawBufferStates[drawBufferIdx] != GL_NONE)
517 {
518 // ES3 spec: "If the GL is bound to a draw framebuffer object, the ith buffer listed in bufs
519 // must be COLOR_ATTACHMENTi or NONE"
520 ASSERT(mDrawBufferStates[drawBufferIdx] == GL_COLOR_ATTACHMENT0 + drawBufferIdx ||
521 (drawBufferIdx == 0 && mDrawBufferStates[drawBufferIdx] == GL_BACK));
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800522
523 if (mDrawBufferStates[drawBufferIdx] == GL_BACK)
524 {
525 return getColorAttachment(0);
526 }
527 else
528 {
529 return getColorAttachment(mDrawBufferStates[drawBufferIdx] - GL_COLOR_ATTACHMENT0);
530 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400531 }
532 else
533 {
534 return nullptr;
535 }
536}
537
538size_t FramebufferState::getDrawBufferCount() const
539{
540 return mDrawBufferStates.size();
541}
542
Geoff Langb21e20d2016-07-19 15:35:41 -0400543bool FramebufferState::colorAttachmentsAreUniqueImages() const
544{
545 for (size_t firstAttachmentIdx = 0; firstAttachmentIdx < mColorAttachments.size();
546 firstAttachmentIdx++)
547 {
Jamie Madilld4442552018-02-27 22:03:47 -0500548 const FramebufferAttachment &firstAttachment = mColorAttachments[firstAttachmentIdx];
Geoff Langb21e20d2016-07-19 15:35:41 -0400549 if (!firstAttachment.isAttached())
550 {
551 continue;
552 }
553
554 for (size_t secondAttachmentIdx = firstAttachmentIdx + 1;
555 secondAttachmentIdx < mColorAttachments.size(); secondAttachmentIdx++)
556 {
Jamie Madilld4442552018-02-27 22:03:47 -0500557 const FramebufferAttachment &secondAttachment = mColorAttachments[secondAttachmentIdx];
Geoff Langb21e20d2016-07-19 15:35:41 -0400558 if (!secondAttachment.isAttached())
559 {
560 continue;
561 }
562
563 if (firstAttachment == secondAttachment)
564 {
565 return false;
566 }
567 }
568 }
569
570 return true;
571}
572
Jamie Madill9c335862017-07-18 11:51:38 -0400573bool FramebufferState::hasDepth() const
574{
575 return (mDepthAttachment.isAttached() && mDepthAttachment.getDepthSize() > 0);
576}
577
578bool FramebufferState::hasStencil() const
579{
580 return (mStencilAttachment.isAttached() && mStencilAttachment.getStencilSize() > 0);
581}
582
Mingyu Hu7d64c482019-03-12 14:27:40 -0700583bool FramebufferState::isMultiview() const
Martin Radev5c00d0d2017-08-07 10:06:59 +0300584{
585 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
586 if (attachment == nullptr)
587 {
Mingyu Hu7d64c482019-03-12 14:27:40 -0700588 return false;
Martin Radev5c00d0d2017-08-07 10:06:59 +0300589 }
Mingyu Hu7d64c482019-03-12 14:27:40 -0700590 return attachment->isMultiview();
Martin Radev5c00d0d2017-08-07 10:06:59 +0300591}
592
Martin Radev4e619f52017-08-09 11:50:06 +0300593int FramebufferState::getBaseViewIndex() const
594{
595 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
596 if (attachment == nullptr)
597 {
598 return GL_NONE;
599 }
600 return attachment->getBaseViewIndex();
601}
602
Jamie Madill05b35b22017-10-03 09:01:44 -0400603Box FramebufferState::getDimensions() const
604{
Jonah Ryan-Davis7151fe52019-07-17 15:15:27 -0400605 Extents extents = getExtents();
606 return Box(0, 0, 0, extents.width, extents.height, extents.depth);
607}
608
609Extents FramebufferState::getExtents() const
610{
Jamie Madill05b35b22017-10-03 09:01:44 -0400611 ASSERT(attachmentsHaveSameDimensions());
Tim Van Patten626a7282019-07-08 15:11:59 -0600612 const FramebufferAttachment *first = getFirstNonNullAttachment();
613 if (first)
614 {
615 return first->getSize();
616 }
617 return Extents(getDefaultWidth(), getDefaultHeight(), 0);
Jamie Madill05b35b22017-10-03 09:01:44 -0400618}
619
Jamie Madill7aea7e02016-05-10 10:39:45 -0400620Framebuffer::Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id)
Jamie Madill2274b652018-05-31 10:56:08 -0400621 : mState(caps, id),
Jamie Madill362876b2016-06-16 14:46:59 -0400622 mImpl(factory->createFramebuffer(mState)),
Jamie Madill362876b2016-06-16 14:46:59 -0400623 mCachedStatus(),
624 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
625 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000626{
Corentin Wallez37c39792015-08-20 14:19:46 -0400627 ASSERT(mImpl != nullptr);
Jamie Madill362876b2016-06-16 14:46:59 -0400628 ASSERT(mState.mColorAttachments.size() == static_cast<size_t>(caps.maxColorAttachments));
629
Jamie Madill1e5499d2017-04-05 11:22:16 -0400630 for (uint32_t colorIndex = 0;
631 colorIndex < static_cast<uint32_t>(mState.mColorAttachments.size()); ++colorIndex)
Jamie Madill362876b2016-06-16 14:46:59 -0400632 {
Jamie Madill1e5499d2017-04-05 11:22:16 -0400633 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
Jamie Madill362876b2016-06-16 14:46:59 -0400634 }
Corentin Wallez37c39792015-08-20 14:19:46 -0400635}
636
Geoff Langbf7b95d2018-05-01 16:48:21 -0400637Framebuffer::Framebuffer(const Context *context, egl::Surface *surface)
Jamie Madill362876b2016-06-16 14:46:59 -0400638 : mState(),
Geoff Langbf7b95d2018-05-01 16:48:21 -0400639 mImpl(surface->getImplementation()->createDefaultFramebuffer(context, mState)),
Jamie Madill362876b2016-06-16 14:46:59 -0400640 mCachedStatus(GL_FRAMEBUFFER_COMPLETE),
641 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
642 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
Corentin Wallez37c39792015-08-20 14:19:46 -0400643{
Geoff Langda88add2014-12-01 10:22:01 -0500644 ASSERT(mImpl != nullptr);
Jamie Madill1e5499d2017-04-05 11:22:16 -0400645 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
Jamie Madill6f60d052017-02-22 15:20:11 -0500646
Geoff Langbf7b95d2018-05-01 16:48:21 -0400647 setAttachmentImpl(context, GL_FRAMEBUFFER_DEFAULT, GL_BACK, ImageIndex(), surface,
Jamie Madillcc129372018-04-12 09:13:18 -0400648 FramebufferAttachment::kDefaultNumViews,
Mingyu Hu7d64c482019-03-12 14:27:40 -0700649 FramebufferAttachment::kDefaultBaseViewIndex, false);
Jamie Madill6f60d052017-02-22 15:20:11 -0500650
651 if (surface->getConfig()->depthSize > 0)
652 {
Geoff Langbf7b95d2018-05-01 16:48:21 -0400653 setAttachmentImpl(context, GL_FRAMEBUFFER_DEFAULT, GL_DEPTH, ImageIndex(), surface,
Jamie Madillcc129372018-04-12 09:13:18 -0400654 FramebufferAttachment::kDefaultNumViews,
Mingyu Hu7d64c482019-03-12 14:27:40 -0700655 FramebufferAttachment::kDefaultBaseViewIndex, false);
Jamie Madill6f60d052017-02-22 15:20:11 -0500656 }
657
658 if (surface->getConfig()->stencilSize > 0)
659 {
Geoff Langbf7b95d2018-05-01 16:48:21 -0400660 setAttachmentImpl(context, GL_FRAMEBUFFER_DEFAULT, GL_STENCIL, ImageIndex(), surface,
Jamie Madillcc129372018-04-12 09:13:18 -0400661 FramebufferAttachment::kDefaultNumViews,
Mingyu Hu7d64c482019-03-12 14:27:40 -0700662 FramebufferAttachment::kDefaultBaseViewIndex, false);
Jamie Madill6f60d052017-02-22 15:20:11 -0500663 }
Jamie Madill6e18a232019-01-16 13:27:14 -0500664 SetComponentTypeMask(getDrawbufferWriteType(0), 0, &mState.mDrawBufferTypeMask);
Geoff Langee244c72019-05-06 10:30:18 -0400665
666 // Ensure the backend has a chance to synchronize its content for a new backbuffer.
667 mDirtyBits.set(DIRTY_BIT_COLOR_BUFFER_CONTENTS_0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000668}
669
Corentin Wallezccab69d2017-01-27 16:57:15 -0500670Framebuffer::Framebuffer(rx::GLImplFactory *factory)
671 : mState(),
672 mImpl(factory->createFramebuffer(mState)),
Corentin Wallezccab69d2017-01-27 16:57:15 -0500673 mCachedStatus(GL_FRAMEBUFFER_UNDEFINED_OES),
674 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
675 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
676{
Jamie Madill1e5499d2017-04-05 11:22:16 -0400677 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
Jamie Madill6e18a232019-01-16 13:27:14 -0500678 SetComponentTypeMask(getDrawbufferWriteType(0), 0, &mState.mDrawBufferTypeMask);
Corentin Wallezccab69d2017-01-27 16:57:15 -0500679}
680
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000681Framebuffer::~Framebuffer()
682{
Geoff Langda88add2014-12-01 10:22:01 -0500683 SafeDelete(mImpl);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000684}
685
Jamie Madill4928b7c2017-06-20 12:57:39 -0400686void Framebuffer::onDestroy(const Context *context)
Jamie Madill6c1f6712017-02-14 19:08:04 -0500687{
Jamie Madill4928b7c2017-06-20 12:57:39 -0400688 for (auto &attachment : mState.mColorAttachments)
689 {
690 attachment.detach(context);
691 }
692 mState.mDepthAttachment.detach(context);
693 mState.mStencilAttachment.detach(context);
694 mState.mWebGLDepthAttachment.detach(context);
695 mState.mWebGLStencilAttachment.detach(context);
696 mState.mWebGLDepthStencilAttachment.detach(context);
697
Jamie Madillc564c072017-06-01 12:45:42 -0400698 mImpl->destroy(context);
Jamie Madill6c1f6712017-02-14 19:08:04 -0500699}
700
Jamie Madille90d4ee2018-11-28 14:04:00 -0500701void Framebuffer::setLabel(const Context *context, const std::string &label)
Geoff Lang70d0f492015-12-10 17:45:46 -0500702{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400703 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -0500704}
705
706const std::string &Framebuffer::getLabel() const
707{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400708 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -0500709}
710
Jamie Madill2ab08ed2019-08-12 16:20:21 -0400711bool Framebuffer::detachTexture(const Context *context, TextureID textureId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000712{
Jamie Madill2ab08ed2019-08-12 16:20:21 -0400713 return detachResourceById(context, GL_TEXTURE, textureId.value);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000714}
715
Jamie Madill7c7dec02019-08-06 17:44:11 -0400716bool Framebuffer::detachRenderbuffer(const Context *context, RenderbufferID renderbufferId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000717{
Jamie Madill7c7dec02019-08-06 17:44:11 -0400718 return detachResourceById(context, GL_RENDERBUFFER, renderbufferId.value);
Jamie Madilld1405e52015-03-05 15:41:39 -0500719}
Jamie Madille261b442014-06-25 12:42:21 -0400720
Jamie Madill8693bdb2017-09-02 15:32:14 -0400721bool Framebuffer::detachResourceById(const Context *context, GLenum resourceType, GLuint resourceId)
Jamie Madilld1405e52015-03-05 15:41:39 -0500722{
Jamie Madill8693bdb2017-09-02 15:32:14 -0400723 bool found = false;
724
Jamie Madill362876b2016-06-16 14:46:59 -0400725 for (size_t colorIndex = 0; colorIndex < mState.mColorAttachments.size(); ++colorIndex)
Jamie Madilld1405e52015-03-05 15:41:39 -0500726 {
Jamie Madill8693bdb2017-09-02 15:32:14 -0400727 if (detachMatchingAttachment(context, &mState.mColorAttachments[colorIndex], resourceType,
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300728 resourceId))
Jamie Madill8693bdb2017-09-02 15:32:14 -0400729 {
730 found = true;
731 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000732 }
733
Jamie Madilla02315b2017-02-23 14:14:47 -0500734 if (context->isWebGL1())
735 {
736 const std::array<FramebufferAttachment *, 3> attachments = {
737 {&mState.mWebGLDepthStencilAttachment, &mState.mWebGLDepthAttachment,
738 &mState.mWebGLStencilAttachment}};
739 for (FramebufferAttachment *attachment : attachments)
740 {
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300741 if (detachMatchingAttachment(context, attachment, resourceType, resourceId))
Jamie Madilla02315b2017-02-23 14:14:47 -0500742 {
Jamie Madill8693bdb2017-09-02 15:32:14 -0400743 found = true;
Jamie Madilla02315b2017-02-23 14:14:47 -0500744 }
745 }
746 }
747 else
748 {
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300749 if (detachMatchingAttachment(context, &mState.mDepthAttachment, resourceType, resourceId))
Jamie Madill8693bdb2017-09-02 15:32:14 -0400750 {
751 found = true;
752 }
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300753 if (detachMatchingAttachment(context, &mState.mStencilAttachment, resourceType, resourceId))
Jamie Madill8693bdb2017-09-02 15:32:14 -0400754 {
755 found = true;
756 }
Jamie Madilla02315b2017-02-23 14:14:47 -0500757 }
Jamie Madill8693bdb2017-09-02 15:32:14 -0400758
759 return found;
Jamie Madill362876b2016-06-16 14:46:59 -0400760}
761
Jamie Madill8693bdb2017-09-02 15:32:14 -0400762bool Framebuffer::detachMatchingAttachment(const Context *context,
Jamie Madill4928b7c2017-06-20 12:57:39 -0400763 FramebufferAttachment *attachment,
Jamie Madill362876b2016-06-16 14:46:59 -0400764 GLenum matchType,
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300765 GLuint matchId)
Jamie Madill362876b2016-06-16 14:46:59 -0400766{
767 if (attachment->isAttached() && attachment->type() == matchType && attachment->id() == matchId)
768 {
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300769 // We go through resetAttachment to make sure that all the required bookkeeping will be done
770 // such as updating enabled draw buffer state.
771 resetAttachment(context, attachment->getBinding());
Jamie Madill8693bdb2017-09-02 15:32:14 -0400772 return true;
Jamie Madill362876b2016-06-16 14:46:59 -0400773 }
Jamie Madill8693bdb2017-09-02 15:32:14 -0400774
775 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000776}
777
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400778const FramebufferAttachment *Framebuffer::getColorAttachment(size_t colorAttachment) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000779{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400780 return mState.getColorAttachment(colorAttachment);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000781}
782
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400783const FramebufferAttachment *Framebuffer::getDepthAttachment() const
Geoff Lang646559f2013-08-15 11:08:15 -0400784{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400785 return mState.getDepthAttachment();
Geoff Lang646559f2013-08-15 11:08:15 -0400786}
787
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400788const FramebufferAttachment *Framebuffer::getStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400789{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400790 return mState.getStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400791}
792
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400793const FramebufferAttachment *Framebuffer::getDepthStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400794{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400795 return mState.getDepthStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400796}
797
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400798const FramebufferAttachment *Framebuffer::getDepthOrStencilAttachment() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000799{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400800 return mState.getDepthOrStencilAttachment();
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000801}
802
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500803const FramebufferAttachment *Framebuffer::getStencilOrDepthStencilAttachment() const
804{
805 return mState.getStencilOrDepthStencilAttachment();
806}
807
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400808const FramebufferAttachment *Framebuffer::getReadColorAttachment() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000809{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400810 return mState.getReadAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000811}
812
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400813GLenum Framebuffer::getReadColorAttachmentType() const
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000814{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400815 const FramebufferAttachment *readAttachment = mState.getReadAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400816 return (readAttachment != nullptr ? readAttachment->type() : GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000817}
818
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400819const FramebufferAttachment *Framebuffer::getFirstColorAttachment() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000820{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400821 return mState.getFirstColorAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000822}
823
Jamie Madill6dd06ea2017-07-19 13:47:55 -0400824const FramebufferAttachment *Framebuffer::getFirstNonNullAttachment() const
825{
826 return mState.getFirstNonNullAttachment();
827}
828
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800829const FramebufferAttachment *Framebuffer::getAttachment(const Context *context,
830 GLenum attachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000831{
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800832 return mState.getAttachment(context, attachment);
Geoff Lang55ba29c2013-07-11 16:57:53 -0400833}
834
Geoff Langa15472a2015-08-11 11:48:03 -0400835size_t Framebuffer::getDrawbufferStateCount() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000836{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400837 return mState.mDrawBufferStates.size();
Geoff Langa15472a2015-08-11 11:48:03 -0400838}
839
840GLenum Framebuffer::getDrawBufferState(size_t drawBuffer) const
841{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400842 ASSERT(drawBuffer < mState.mDrawBufferStates.size());
843 return mState.mDrawBufferStates[drawBuffer];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000844}
845
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500846const std::vector<GLenum> &Framebuffer::getDrawBufferStates() const
847{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400848 return mState.getDrawBufferStates();
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500849}
850
Geoff Lang164d54e2014-12-01 10:55:33 -0500851void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000852{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400853 auto &drawStates = mState.mDrawBufferStates;
Jamie Madilld1405e52015-03-05 15:41:39 -0500854
855 ASSERT(count <= drawStates.size());
856 std::copy(buffers, buffers + count, drawStates.begin());
857 std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500858 mDirtyBits.set(DIRTY_BIT_DRAW_BUFFERS);
Jamie Madilla4595b82017-01-11 17:36:34 -0500859
860 mState.mEnabledDrawBuffers.reset();
Brandon Jones76746f92017-11-22 11:44:41 -0800861 mState.mDrawBufferTypeMask.reset();
862
Jamie Madilla4595b82017-01-11 17:36:34 -0500863 for (size_t index = 0; index < count; ++index)
864 {
Jamie Madill6e18a232019-01-16 13:27:14 -0500865 SetComponentTypeMask(getDrawbufferWriteType(index), index, &mState.mDrawBufferTypeMask);
Brandon Jones76746f92017-11-22 11:44:41 -0800866
Jamie Madilla4595b82017-01-11 17:36:34 -0500867 if (drawStates[index] != GL_NONE && mState.mColorAttachments[index].isAttached())
868 {
869 mState.mEnabledDrawBuffers.set(index);
870 }
871 }
Geoff Lang9dd95802014-12-01 11:12:59 -0500872}
873
Geoff Langa15472a2015-08-11 11:48:03 -0400874const FramebufferAttachment *Framebuffer::getDrawBuffer(size_t drawBuffer) const
875{
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400876 return mState.getDrawBuffer(drawBuffer);
Geoff Langa15472a2015-08-11 11:48:03 -0400877}
878
Jamie Madill6e18a232019-01-16 13:27:14 -0500879ComponentType Framebuffer::getDrawbufferWriteType(size_t drawBuffer) const
Geoff Lange0cff192017-05-30 13:04:56 -0400880{
881 const FramebufferAttachment *attachment = mState.getDrawBuffer(drawBuffer);
882 if (attachment == nullptr)
883 {
Jamie Madill6e18a232019-01-16 13:27:14 -0500884 return ComponentType::NoType;
Geoff Lange0cff192017-05-30 13:04:56 -0400885 }
886
887 GLenum componentType = attachment->getFormat().info->componentType;
888 switch (componentType)
889 {
890 case GL_INT:
Jamie Madill6e18a232019-01-16 13:27:14 -0500891 return ComponentType::Int;
Geoff Lange0cff192017-05-30 13:04:56 -0400892 case GL_UNSIGNED_INT:
Jamie Madill6e18a232019-01-16 13:27:14 -0500893 return ComponentType::UnsignedInt;
Geoff Lange0cff192017-05-30 13:04:56 -0400894
895 default:
Jamie Madill6e18a232019-01-16 13:27:14 -0500896 return ComponentType::Float;
Geoff Lange0cff192017-05-30 13:04:56 -0400897 }
898}
899
Brandon Jonesc405ae72017-12-06 14:15:03 -0800900ComponentTypeMask Framebuffer::getDrawBufferTypeMask() const
Brandon Jones76746f92017-11-22 11:44:41 -0800901{
902 return mState.mDrawBufferTypeMask;
903}
904
905DrawBufferMask Framebuffer::getDrawBufferMask() const
906{
907 return mState.mEnabledDrawBuffers;
908}
909
Geoff Langa15472a2015-08-11 11:48:03 -0400910bool Framebuffer::hasEnabledDrawBuffer() const
911{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400912 for (size_t drawbufferIdx = 0; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
Geoff Langa15472a2015-08-11 11:48:03 -0400913 {
914 if (getDrawBuffer(drawbufferIdx) != nullptr)
915 {
916 return true;
917 }
918 }
919
920 return false;
921}
922
Geoff Lang9dd95802014-12-01 11:12:59 -0500923GLenum Framebuffer::getReadBufferState() const
924{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400925 return mState.mReadBufferState;
Geoff Lang9dd95802014-12-01 11:12:59 -0500926}
927
928void Framebuffer::setReadBuffer(GLenum buffer)
929{
Jamie Madillb885e572015-02-03 16:16:04 -0500930 ASSERT(buffer == GL_BACK || buffer == GL_NONE ||
931 (buffer >= GL_COLOR_ATTACHMENT0 &&
Jamie Madill48ef11b2016-04-27 15:21:52 -0400932 (buffer - GL_COLOR_ATTACHMENT0) < mState.mColorAttachments.size()));
933 mState.mReadBufferState = buffer;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500934 mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000935}
936
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400937size_t Framebuffer::getNumColorAttachments() const
Corentin Wallez37c39792015-08-20 14:19:46 -0400938{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400939 return mState.mColorAttachments.size();
Corentin Wallez37c39792015-08-20 14:19:46 -0400940}
941
Jamie Madill0df8fe42015-11-24 16:10:24 -0500942bool Framebuffer::hasDepth() const
943{
Jamie Madill9c335862017-07-18 11:51:38 -0400944 return mState.hasDepth();
Jamie Madill0df8fe42015-11-24 16:10:24 -0500945}
946
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000947bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000948{
Jamie Madill9c335862017-07-18 11:51:38 -0400949 return mState.hasStencil();
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000950}
951
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000952bool Framebuffer::usingExtendedDrawBuffers() const
953{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400954 for (size_t drawbufferIdx = 1; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000955 {
Geoff Langa15472a2015-08-11 11:48:03 -0400956 if (getDrawBuffer(drawbufferIdx) != nullptr)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000957 {
958 return true;
959 }
960 }
961
962 return false;
963}
964
Jamie Madill124f78c2019-06-18 11:48:24 -0400965void Framebuffer::invalidateCompletenessCache()
Geoff Lang9aded172017-04-05 11:07:56 -0400966{
Jamie Madill2274b652018-05-31 10:56:08 -0400967 if (mState.mId != 0)
Geoff Lang9aded172017-04-05 11:07:56 -0400968 {
969 mCachedStatus.reset();
970 }
Jamie Madill124f78c2019-06-18 11:48:24 -0400971 onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
Geoff Lang9aded172017-04-05 11:07:56 -0400972}
973
Jamie Madillcc73f242018-08-01 11:34:48 -0400974GLenum Framebuffer::checkStatusImpl(const Context *context)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000975{
Jamie Madillcc73f242018-08-01 11:34:48 -0400976 ASSERT(!isDefault());
977 ASSERT(hasAnyDirtyBit() || !mCachedStatus.valid());
Geoff Lang528ce3c2014-12-01 10:44:07 -0500978
Jamie Madillcc73f242018-08-01 11:34:48 -0400979 mCachedStatus = checkStatusWithGLFrontEnd(context);
Jamie Madille98b1b52018-03-08 09:47:23 -0500980
Jamie Madillcc73f242018-08-01 11:34:48 -0400981 if (mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE)
982 {
Jamie Madill67220092019-05-20 11:12:53 -0400983 // We can skip syncState on several back-ends.
984 if (mImpl->shouldSyncStateBeforeCheckStatus())
Jamie Madille98b1b52018-03-08 09:47:23 -0500985 {
Jamie Madill67220092019-05-20 11:12:53 -0400986 angle::Result err = syncState(context);
987 if (err != angle::Result::Continue)
988 {
989 return 0;
990 }
Jamie Madillcc73f242018-08-01 11:34:48 -0400991 }
Jamie Madill67220092019-05-20 11:12:53 -0400992
Jamie Madillcc73f242018-08-01 11:34:48 -0400993 if (!mImpl->checkStatus(context))
994 {
995 mCachedStatus = GL_FRAMEBUFFER_UNSUPPORTED;
Jamie Madille98b1b52018-03-08 09:47:23 -0500996 }
Jamie Madill362876b2016-06-16 14:46:59 -0400997 }
998
Jamie Madill427064d2018-04-13 16:20:34 -0400999 return mCachedStatus.value();
Jamie Madill362876b2016-06-16 14:46:59 -04001000}
1001
Jamie Madille98b1b52018-03-08 09:47:23 -05001002GLenum Framebuffer::checkStatusWithGLFrontEnd(const Context *context)
Jamie Madill362876b2016-06-16 14:46:59 -04001003{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001004 const State &state = context->getState();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001005
Jamie Madill2274b652018-05-31 10:56:08 -04001006 ASSERT(mState.mId != 0);
Jamie Madill362876b2016-06-16 14:46:59 -04001007
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001008 bool hasAttachments = false;
1009 Optional<unsigned int> colorbufferSize;
1010 Optional<int> samples;
Geoff Lang92019432017-11-20 13:09:34 -05001011 Optional<bool> fixedSampleLocations;
JiangYizhou461d9a32017-01-04 16:37:26 +08001012 bool hasRenderbuffer = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001013
Martin Radev9bc9a322017-07-21 14:28:17 +03001014 const FramebufferAttachment *firstAttachment = getFirstNonNullAttachment();
1015
Jiawei Shaoa8802472018-05-28 11:17:47 +08001016 Optional<bool> isLayered;
1017 Optional<TextureType> colorAttachmentsTextureType;
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 {
Mingyu Hu7d64c482019-03-12 14:27:40 -07001059 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR;
Martin Radev9bc9a322017-07-21 14:28:17 +03001060 }
1061
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001062 hasRenderbuffer = hasRenderbuffer || (colorAttachment.type() == GL_RENDERBUFFER);
Jiawei Shaoa8802472018-05-28 11:17:47 +08001063
1064 if (!hasAttachments)
1065 {
1066 isLayered = colorAttachment.isLayered();
1067 if (isLayered.value())
1068 {
1069 colorAttachmentsTextureType = colorAttachment.getTextureImageIndex().getType();
1070 }
1071 hasAttachments = true;
1072 }
1073 else
1074 {
1075 // [EXT_geometry_shader] section 9.4.1, "Framebuffer Completeness"
1076 // If any framebuffer attachment is layered, all populated attachments
1077 // must be layered. Additionally, all populated color attachments must
1078 // be from textures of the same target. {FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT }
1079 ASSERT(isLayered.valid());
1080 if (isLayered.value() != colorAttachment.isLayered())
1081 {
1082 return GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT;
1083 }
1084 else if (isLayered.value())
1085 {
1086 ASSERT(colorAttachmentsTextureType.valid());
1087 if (colorAttachmentsTextureType.value() !=
1088 colorAttachment.getTextureImageIndex().getType())
1089 {
1090 return GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT;
1091 }
1092 }
1093 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001094 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001095 }
1096
Jamie Madill48ef11b2016-04-27 15:21:52 -04001097 const FramebufferAttachment &depthAttachment = mState.mDepthAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -04001098 if (depthAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001099 {
Geoff Lang9f10b772017-05-16 15:51:03 -04001100 if (!CheckAttachmentCompleteness(context, depthAttachment))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001101 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001102 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001103 }
1104
Geoff Lang677bb6f2017-04-05 12:40:40 -04001105 const InternalFormat &format = *depthAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -04001106 if (format.depthBits == 0)
1107 {
1108 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001109 }
1110
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001111 if (!CheckAttachmentSampleCompleteness(context, depthAttachment, false, &samples,
1112 &fixedSampleLocations))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001113 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001114 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001115 }
Sami Väisänena797e062016-05-12 15:23:40 +03001116
Martin Radev9bc9a322017-07-21 14:28:17 +03001117 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &depthAttachment))
1118 {
Mingyu Hu7d64c482019-03-12 14:27:40 -07001119 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR;
Martin Radev9bc9a322017-07-21 14:28:17 +03001120 }
1121
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001122 hasRenderbuffer = hasRenderbuffer || (depthAttachment.type() == GL_RENDERBUFFER);
Jiawei Shaoa8802472018-05-28 11:17:47 +08001123
1124 if (!hasAttachments)
1125 {
1126 isLayered = depthAttachment.isLayered();
1127 hasAttachments = true;
1128 }
1129 else
1130 {
1131 // [EXT_geometry_shader] section 9.4.1, "Framebuffer Completeness"
1132 // If any framebuffer attachment is layered, all populated attachments
1133 // must be layered. {FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT }
1134 ASSERT(isLayered.valid());
1135 if (isLayered.value() != depthAttachment.isLayered())
1136 {
1137 return GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT;
1138 }
1139 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001140 }
1141
Jamie Madill48ef11b2016-04-27 15:21:52 -04001142 const FramebufferAttachment &stencilAttachment = mState.mStencilAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -04001143 if (stencilAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001144 {
Geoff Lang9f10b772017-05-16 15:51:03 -04001145 if (!CheckAttachmentCompleteness(context, stencilAttachment))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001146 {
1147 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1148 }
1149
Geoff Lang677bb6f2017-04-05 12:40:40 -04001150 const InternalFormat &format = *stencilAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -04001151 if (format.stencilBits == 0)
1152 {
1153 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001154 }
1155
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001156 if (!CheckAttachmentSampleCompleteness(context, stencilAttachment, false, &samples,
1157 &fixedSampleLocations))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001158 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001159 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001160 }
Corentin Wallez086d59a2016-04-29 09:06:49 -04001161
Martin Radev9bc9a322017-07-21 14:28:17 +03001162 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &stencilAttachment))
1163 {
Mingyu Hu7d64c482019-03-12 14:27:40 -07001164 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR;
Martin Radev9bc9a322017-07-21 14:28:17 +03001165 }
1166
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001167 hasRenderbuffer = hasRenderbuffer || (stencilAttachment.type() == GL_RENDERBUFFER);
Jiawei Shaoa8802472018-05-28 11:17:47 +08001168
1169 if (!hasAttachments)
1170 {
1171 hasAttachments = true;
1172 }
1173 else
1174 {
1175 // [EXT_geometry_shader] section 9.4.1, "Framebuffer Completeness"
1176 // If any framebuffer attachment is layered, all populated attachments
1177 // must be layered.
1178 // {FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT }
1179 ASSERT(isLayered.valid());
1180 if (isLayered.value() != stencilAttachment.isLayered())
1181 {
1182 return GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT;
1183 }
1184 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001185 }
1186
1187 // Starting from ES 3.0 stencil and depth, if present, should be the same image
1188 if (state.getClientMajorVersion() >= 3 && depthAttachment.isAttached() &&
1189 stencilAttachment.isAttached() && stencilAttachment != depthAttachment)
1190 {
1191 return GL_FRAMEBUFFER_UNSUPPORTED;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001192 }
1193
Jamie Madilla02315b2017-02-23 14:14:47 -05001194 // Special additional validation for WebGL 1 DEPTH/STENCIL/DEPTH_STENCIL.
1195 if (state.isWebGL1())
1196 {
1197 if (!mState.mWebGLDepthStencilConsistent)
1198 {
1199 return GL_FRAMEBUFFER_UNSUPPORTED;
1200 }
1201
1202 if (mState.mWebGLDepthStencilAttachment.isAttached())
1203 {
1204 if (mState.mWebGLDepthStencilAttachment.getDepthSize() == 0 ||
1205 mState.mWebGLDepthStencilAttachment.getStencilSize() == 0)
1206 {
1207 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1208 }
Martin Radev9bc9a322017-07-21 14:28:17 +03001209
1210 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment,
1211 &mState.mWebGLDepthStencilAttachment))
1212 {
Mingyu Hu7d64c482019-03-12 14:27:40 -07001213 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR;
Martin Radev9bc9a322017-07-21 14:28:17 +03001214 }
Jamie Madilla02315b2017-02-23 14:14:47 -05001215 }
1216 else if (mState.mStencilAttachment.isAttached() &&
1217 mState.mStencilAttachment.getDepthSize() > 0)
1218 {
1219 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1220 }
1221 else if (mState.mDepthAttachment.isAttached() &&
1222 mState.mDepthAttachment.getStencilSize() > 0)
1223 {
1224 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1225 }
1226 }
1227
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001228 // ES3.1(section 9.4) requires that if no image is attached to the framebuffer, and either the
1229 // value of the framebuffer's FRAMEBUFFER_DEFAULT_WIDTH or FRAMEBUFFER_DEFAULT_HEIGHT parameters
1230 // is zero, the framebuffer is considered incomplete.
JiangYizhou461d9a32017-01-04 16:37:26 +08001231 GLint defaultWidth = mState.getDefaultWidth();
1232 GLint defaultHeight = mState.getDefaultHeight();
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001233 if (!hasAttachments && (defaultWidth == 0 || defaultHeight == 0))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001234 {
1235 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001236 }
1237
Geoff Langa0e0aeb2017-04-12 15:06:29 -04001238 // In ES 2.0 and WebGL, all color attachments must have the same width and height.
Jamie Madillcc86d642015-11-24 13:00:07 -05001239 // In ES 3.0, there is no such restriction.
Geoff Langa0e0aeb2017-04-12 15:06:29 -04001240 if ((state.getClientMajorVersion() < 3 || state.getExtensions().webglCompatibility) &&
1241 !mState.attachmentsHaveSameDimensions())
Jamie Madillcc86d642015-11-24 13:00:07 -05001242 {
1243 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
1244 }
1245
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001246 // ES3.1(section 9.4) requires that if the attached images are a mix of renderbuffers and
1247 // textures, the value of TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all attached textures.
JiangYizhou461d9a32017-01-04 16:37:26 +08001248 if (fixedSampleLocations.valid() && hasRenderbuffer && !fixedSampleLocations.value())
1249 {
1250 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1251 }
1252
Kenneth Russellce8602a2017-10-03 18:23:08 -07001253 // The WebGL conformance tests implicitly define that all framebuffer
1254 // attachments must be unique. For example, the same level of a texture can
1255 // not be attached to two different color attachments.
1256 if (state.getExtensions().webglCompatibility)
1257 {
1258 if (!mState.colorAttachmentsAreUniqueImages())
1259 {
1260 return GL_FRAMEBUFFER_UNSUPPORTED;
1261 }
1262 }
1263
Jamie Madillcc86d642015-11-24 13:00:07 -05001264 return GL_FRAMEBUFFER_COMPLETE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001265}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001266
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001267angle::Result Framebuffer::discard(const Context *context, size_t count, const GLenum *attachments)
Austin Kinross08332632015-05-05 13:35:47 -07001268{
Jamie Madill05b35b22017-10-03 09:01:44 -04001269 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1270 // can be no-ops, so we should probably do that to ensure consistency.
1271 // TODO(jmadill): WebGL behaviour, and robust resource init behaviour without WebGL.
1272
Jamie Madill4928b7c2017-06-20 12:57:39 -04001273 return mImpl->discard(context, count, attachments);
Austin Kinross08332632015-05-05 13:35:47 -07001274}
1275
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001276angle::Result Framebuffer::invalidate(const Context *context,
1277 size_t count,
1278 const GLenum *attachments)
Jamie Madill2d96b9e2014-08-29 15:46:47 -04001279{
Jamie Madill05b35b22017-10-03 09:01:44 -04001280 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1281 // can be no-ops, so we should probably do that to ensure consistency.
1282 // TODO(jmadill): WebGL behaviour, and robust resource init behaviour without WebGL.
1283
Jamie Madill4928b7c2017-06-20 12:57:39 -04001284 return mImpl->invalidate(context, count, attachments);
Jamie Madill2d96b9e2014-08-29 15:46:47 -04001285}
1286
Jamie Madill05b35b22017-10-03 09:01:44 -04001287bool Framebuffer::partialClearNeedsInit(const Context *context,
1288 bool color,
1289 bool depth,
1290 bool stencil)
1291{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001292 const auto &glState = context->getState();
Jamie Madill05b35b22017-10-03 09:01:44 -04001293
1294 if (!glState.isRobustResourceInitEnabled())
1295 {
1296 return false;
1297 }
1298
1299 // Scissors can affect clearing.
1300 // TODO(jmadill): Check for complete scissor overlap.
1301 if (glState.isScissorTestEnabled())
1302 {
1303 return true;
1304 }
1305
1306 // If colors masked, we must clear before we clear. Do a simple check.
1307 // TODO(jmadill): Filter out unused color channels from the test.
1308 if (color)
1309 {
1310 const auto &blend = glState.getBlendState();
1311 if (!(blend.colorMaskRed && blend.colorMaskGreen && blend.colorMaskBlue &&
1312 blend.colorMaskAlpha))
1313 {
1314 return true;
1315 }
1316 }
1317
1318 const auto &depthStencil = glState.getDepthStencilState();
Yuly Novikov21edf3d2018-07-23 16:44:16 -04001319 if (stencil && (depthStencil.stencilMask != depthStencil.stencilWritemask ||
1320 depthStencil.stencilBackMask != depthStencil.stencilBackWritemask))
Jamie Madill05b35b22017-10-03 09:01:44 -04001321 {
1322 return true;
1323 }
1324
1325 return false;
1326}
1327
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001328angle::Result Framebuffer::invalidateSub(const Context *context,
1329 size_t count,
1330 const GLenum *attachments,
1331 const Rectangle &area)
Jamie Madill400a4412014-08-29 15:46:45 -04001332{
Jamie Madill05b35b22017-10-03 09:01:44 -04001333 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1334 // can be no-ops, so we should probably do that to ensure consistency.
1335 // TODO(jmadill): Make a invalidate no-op in WebGL 2.0.
1336
Jamie Madill4928b7c2017-06-20 12:57:39 -04001337 return mImpl->invalidateSub(context, count, attachments, area);
Jamie Madill400a4412014-08-29 15:46:45 -04001338}
1339
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001340angle::Result Framebuffer::clear(const Context *context, GLbitfield mask)
Geoff Langb04dc822014-12-01 12:02:02 -05001341{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001342 const auto &glState = context->getState();
Jamie Madill05b35b22017-10-03 09:01:44 -04001343 if (glState.isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -05001344 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001345 return angle::Result::Continue;
Jamie Madill984ef412015-11-24 16:10:21 -05001346 }
1347
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -04001348 // Remove clear bits that are ineffective. An effective clear changes at least one fragment. If
1349 // color/depth/stencil masks make the clear ineffective we skip it altogether.
1350
1351 // If all color channels are masked, don't attempt to clear color.
1352 if (context->getState().getBlendState().allChannelsMasked())
1353 {
1354 mask &= ~GL_COLOR_BUFFER_BIT;
1355 }
1356
1357 // If depth write is disabled, don't attempt to clear depth.
1358 if (!context->getState().getDepthStencilState().depthMask)
1359 {
1360 mask &= ~GL_DEPTH_BUFFER_BIT;
1361 }
1362
1363 // If all stencil bits are masked, don't attempt to clear stencil.
1364 if (context->getState().getDepthStencilState().stencilWritemask == 0)
1365 {
1366 mask &= ~GL_STENCIL_BUFFER_BIT;
1367 }
1368
1369 if (mask != 0)
1370 {
1371 ANGLE_TRY(mImpl->clear(context, mask));
1372 }
Jamie Madill05b35b22017-10-03 09:01:44 -04001373
Jamie Madill7c985f52018-11-29 18:16:17 -05001374 return angle::Result::Continue;
Geoff Langb04dc822014-12-01 12:02:02 -05001375}
1376
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001377angle::Result Framebuffer::clearBufferfv(const Context *context,
1378 GLenum buffer,
1379 GLint drawbuffer,
1380 const GLfloat *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001381{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001382 if (context->getState().isRasterizerDiscardEnabled() || IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001383 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001384 return angle::Result::Continue;
Jamie Madill984ef412015-11-24 16:10:21 -05001385 }
1386
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -04001387 if (buffer == GL_DEPTH)
1388 {
1389 // If depth write is disabled, don't attempt to clear depth.
1390 if (!context->getState().getDepthStencilState().depthMask)
1391 {
1392 return angle::Result::Continue;
1393 }
1394 }
1395 else
1396 {
1397 // If all color channels are masked, don't attempt to clear color.
1398 if (context->getState().getBlendState().allChannelsMasked())
1399 {
1400 return angle::Result::Continue;
1401 }
1402 }
1403
Jamie Madill05b35b22017-10-03 09:01:44 -04001404 ANGLE_TRY(mImpl->clearBufferfv(context, buffer, drawbuffer, values));
1405
Jamie Madill7c985f52018-11-29 18:16:17 -05001406 return angle::Result::Continue;
Geoff Langb04dc822014-12-01 12:02:02 -05001407}
1408
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001409angle::Result Framebuffer::clearBufferuiv(const Context *context,
1410 GLenum buffer,
1411 GLint drawbuffer,
1412 const GLuint *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001413{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001414 if (context->getState().isRasterizerDiscardEnabled() || IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001415 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001416 return angle::Result::Continue;
Jamie Madill984ef412015-11-24 16:10:21 -05001417 }
1418
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -04001419 // If all color channels are masked, don't attempt to clear color.
1420 if (context->getState().getBlendState().allChannelsMasked())
1421 {
1422 return angle::Result::Continue;
1423 }
1424
Jamie Madill05b35b22017-10-03 09:01:44 -04001425 ANGLE_TRY(mImpl->clearBufferuiv(context, buffer, drawbuffer, values));
1426
Jamie Madill7c985f52018-11-29 18:16:17 -05001427 return angle::Result::Continue;
Geoff Langb04dc822014-12-01 12:02:02 -05001428}
1429
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001430angle::Result Framebuffer::clearBufferiv(const Context *context,
1431 GLenum buffer,
1432 GLint drawbuffer,
1433 const GLint *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001434{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001435 if (context->getState().isRasterizerDiscardEnabled() || IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001436 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001437 return angle::Result::Continue;
Jamie Madill984ef412015-11-24 16:10:21 -05001438 }
1439
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -04001440 if (buffer == GL_STENCIL)
1441 {
1442 // If all stencil bits are masked, don't attempt to clear stencil.
1443 if (context->getState().getDepthStencilState().stencilWritemask == 0)
1444 {
1445 return angle::Result::Continue;
1446 }
1447 }
1448 else
1449 {
1450 // If all color channels are masked, don't attempt to clear color.
1451 if (context->getState().getBlendState().allChannelsMasked())
1452 {
1453 return angle::Result::Continue;
1454 }
1455 }
1456
Jamie Madill05b35b22017-10-03 09:01:44 -04001457 ANGLE_TRY(mImpl->clearBufferiv(context, buffer, drawbuffer, values));
1458
Jamie Madill7c985f52018-11-29 18:16:17 -05001459 return angle::Result::Continue;
Geoff Langb04dc822014-12-01 12:02:02 -05001460}
1461
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001462angle::Result Framebuffer::clearBufferfi(const Context *context,
1463 GLenum buffer,
1464 GLint drawbuffer,
1465 GLfloat depth,
1466 GLint stencil)
Geoff Langb04dc822014-12-01 12:02:02 -05001467{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001468 if (context->getState().isRasterizerDiscardEnabled() || IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001469 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001470 return angle::Result::Continue;
Jamie Madill984ef412015-11-24 16:10:21 -05001471 }
1472
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -04001473 bool clearDepth = context->getState().getDepthStencilState().depthMask;
1474 bool clearStencil = context->getState().getDepthStencilState().stencilWritemask != 0;
1475
1476 if (clearDepth && clearStencil)
1477 {
1478 ASSERT(buffer == GL_DEPTH_STENCIL);
1479 ANGLE_TRY(mImpl->clearBufferfi(context, GL_DEPTH_STENCIL, drawbuffer, depth, stencil));
1480 }
1481 else if (clearDepth && !clearStencil)
1482 {
1483 ANGLE_TRY(mImpl->clearBufferfv(context, GL_DEPTH, drawbuffer, &depth));
1484 }
1485 else if (!clearDepth && clearStencil)
1486 {
1487 ANGLE_TRY(mImpl->clearBufferiv(context, GL_STENCIL, drawbuffer, &stencil));
1488 }
Jamie Madill05b35b22017-10-03 09:01:44 -04001489
Jamie Madill7c985f52018-11-29 18:16:17 -05001490 return angle::Result::Continue;
Geoff Langb04dc822014-12-01 12:02:02 -05001491}
1492
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001493angle::Result Framebuffer::getImplementationColorReadFormat(const Context *context,
1494 GLenum *formatOut)
Geoff Langbce529e2014-12-01 12:48:41 -05001495{
Jamie Madill690c8eb2018-03-12 15:20:03 -04001496 ANGLE_TRY(syncState(context));
1497 *formatOut = mImpl->getImplementationColorReadFormat(context);
Jamie Madill7c985f52018-11-29 18:16:17 -05001498 return angle::Result::Continue;
Geoff Langbce529e2014-12-01 12:48:41 -05001499}
1500
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001501angle::Result Framebuffer::getImplementationColorReadType(const Context *context, GLenum *typeOut)
Geoff Langbce529e2014-12-01 12:48:41 -05001502{
Jamie Madill690c8eb2018-03-12 15:20:03 -04001503 ANGLE_TRY(syncState(context));
1504 *typeOut = mImpl->getImplementationColorReadType(context);
Jamie Madill7c985f52018-11-29 18:16:17 -05001505 return angle::Result::Continue;
Geoff Langbce529e2014-12-01 12:48:41 -05001506}
1507
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001508angle::Result Framebuffer::readPixels(const Context *context,
1509 const Rectangle &area,
1510 GLenum format,
1511 GLenum type,
1512 void *pixels)
Geoff Langbce529e2014-12-01 12:48:41 -05001513{
Jamie Madill362876b2016-06-16 14:46:59 -04001514 ANGLE_TRY(mImpl->readPixels(context, area, format, type, pixels));
Geoff Lang520c4ae2015-05-05 13:12:36 -04001515
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001516 Buffer *unpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Lang520c4ae2015-05-05 13:12:36 -04001517 if (unpackBuffer)
1518 {
James Dong020abb82019-07-24 11:33:49 -06001519 unpackBuffer->onDataChanged();
Geoff Lang520c4ae2015-05-05 13:12:36 -04001520 }
1521
Jamie Madill7c985f52018-11-29 18:16:17 -05001522 return angle::Result::Continue;
Geoff Langbce529e2014-12-01 12:48:41 -05001523}
1524
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001525angle::Result Framebuffer::blit(const Context *context,
1526 const Rectangle &sourceArea,
1527 const Rectangle &destArea,
1528 GLbitfield mask,
1529 GLenum filter)
Geoff Lang54bd5a42014-12-01 12:51:04 -05001530{
He Yunchao6be602d2016-12-22 14:33:07 +08001531 GLbitfield blitMask = mask;
1532
1533 // Note that blitting is called against draw framebuffer.
1534 // See the code in gl::Context::blitFramebuffer.
1535 if ((mask & GL_COLOR_BUFFER_BIT) && !hasEnabledDrawBuffer())
1536 {
1537 blitMask &= ~GL_COLOR_BUFFER_BIT;
1538 }
1539
1540 if ((mask & GL_STENCIL_BUFFER_BIT) && mState.getStencilAttachment() == nullptr)
1541 {
1542 blitMask &= ~GL_STENCIL_BUFFER_BIT;
1543 }
1544
1545 if ((mask & GL_DEPTH_BUFFER_BIT) && mState.getDepthAttachment() == nullptr)
1546 {
1547 blitMask &= ~GL_DEPTH_BUFFER_BIT;
1548 }
1549
1550 if (!blitMask)
1551 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001552 return angle::Result::Continue;
He Yunchao6be602d2016-12-22 14:33:07 +08001553 }
1554
1555 return mImpl->blit(context, sourceArea, destArea, blitMask, filter);
Geoff Lang54bd5a42014-12-01 12:51:04 -05001556}
1557
Luc Ferronbf6dc372018-06-28 15:24:19 -04001558bool Framebuffer::isDefault() const
1559{
1560 return id() == 0;
1561}
1562
Jamie Madill427064d2018-04-13 16:20:34 -04001563int Framebuffer::getSamples(const Context *context)
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001564{
Jamie Madill427064d2018-04-13 16:20:34 -04001565 return (isComplete(context) ? getCachedSamples(context) : 0);
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001566}
1567
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -04001568int Framebuffer::getCachedSamples(const Context *context) const
Jamie Madill9c335862017-07-18 11:51:38 -04001569{
Jamie Madill5b772312018-03-08 20:28:32 -05001570 ASSERT(mCachedStatus.valid() && mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE);
1571
Jamie Madill9c335862017-07-18 11:51:38 -04001572 // For a complete framebuffer, all attachments must have the same sample count.
1573 // In this case return the first nonzero sample size.
1574 const auto *firstNonNullAttachment = mState.getFirstNonNullAttachment();
1575 if (firstNonNullAttachment)
1576 {
1577 ASSERT(firstNonNullAttachment->isAttached());
1578 return firstNonNullAttachment->getSamples();
1579 }
1580
1581 // No attachments found.
1582 return 0;
1583}
1584
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001585angle::Result Framebuffer::getSamplePosition(const Context *context,
1586 size_t index,
1587 GLfloat *xy) const
Corentin Wallezccab69d2017-01-27 16:57:15 -05001588{
Geoff Lang13455072018-05-09 11:24:43 -04001589 ANGLE_TRY(mImpl->getSamplePosition(context, index, xy));
Jamie Madill7c985f52018-11-29 18:16:17 -05001590 return angle::Result::Continue;
Corentin Wallezccab69d2017-01-27 16:57:15 -05001591}
1592
Jamie Madille261b442014-06-25 12:42:21 -04001593bool Framebuffer::hasValidDepthStencil() const
1594{
Jamie Madill48ef11b2016-04-27 15:21:52 -04001595 return mState.getDepthStencilAttachment() != nullptr;
Jamie Madille261b442014-06-25 12:42:21 -04001596}
1597
Jamie Madilla02315b2017-02-23 14:14:47 -05001598void Framebuffer::setAttachment(const Context *context,
1599 GLenum type,
Jamie Madill2d06b732015-04-20 12:53:28 -04001600 GLenum binding,
1601 const ImageIndex &textureIndex,
1602 FramebufferAttachmentObject *resource)
Geoff Langab75a052014-10-15 12:56:37 -04001603{
Martin Radev5dae57b2017-07-14 16:15:55 +03001604 setAttachment(context, type, binding, textureIndex, resource,
1605 FramebufferAttachment::kDefaultNumViews,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001606 FramebufferAttachment::kDefaultBaseViewIndex, false);
Martin Radev5dae57b2017-07-14 16:15:55 +03001607}
1608
1609void Framebuffer::setAttachment(const Context *context,
1610 GLenum type,
1611 GLenum binding,
1612 const ImageIndex &textureIndex,
1613 FramebufferAttachmentObject *resource,
1614 GLsizei numViews,
1615 GLuint baseViewIndex,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001616 bool isMultiview)
Martin Radev5dae57b2017-07-14 16:15:55 +03001617{
Jamie Madilla02315b2017-02-23 14:14:47 -05001618 // Context may be null in unit tests.
1619 if (!context || !context->isWebGL1())
1620 {
Martin Radev5dae57b2017-07-14 16:15:55 +03001621 setAttachmentImpl(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001622 isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001623 return;
1624 }
1625
1626 switch (binding)
1627 {
1628 case GL_DEPTH_STENCIL:
1629 case GL_DEPTH_STENCIL_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001630 mState.mWebGLDepthStencilAttachment.attach(context, type, binding, textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001631 resource, numViews, baseViewIndex,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001632 isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001633 break;
1634 case GL_DEPTH:
1635 case GL_DEPTH_ATTACHMENT:
Martin Radev5dae57b2017-07-14 16:15:55 +03001636 mState.mWebGLDepthAttachment.attach(context, type, binding, textureIndex, resource,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001637 numViews, baseViewIndex, isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001638 break;
1639 case GL_STENCIL:
1640 case GL_STENCIL_ATTACHMENT:
Martin Radev5dae57b2017-07-14 16:15:55 +03001641 mState.mWebGLStencilAttachment.attach(context, type, binding, textureIndex, resource,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001642 numViews, baseViewIndex, isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001643 break;
1644 default:
Martin Radev5dae57b2017-07-14 16:15:55 +03001645 setAttachmentImpl(context, type, binding, textureIndex, resource, numViews,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001646 baseViewIndex, isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001647 return;
1648 }
1649
Mingyu Hu7d64c482019-03-12 14:27:40 -07001650 commitWebGL1DepthStencilIfConsistent(context, numViews, baseViewIndex, isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001651}
1652
Mingyu Hu7d64c482019-03-12 14:27:40 -07001653void Framebuffer::setAttachmentMultiview(const Context *context,
1654 GLenum type,
1655 GLenum binding,
1656 const ImageIndex &textureIndex,
1657 FramebufferAttachmentObject *resource,
1658 GLsizei numViews,
1659 GLint baseViewIndex)
Martin Radev82ef7742017-08-08 17:44:58 +03001660{
Mingyu Hu7d64c482019-03-12 14:27:40 -07001661 setAttachment(context, type, binding, textureIndex, resource, numViews, baseViewIndex, true);
Martin Radev5dae57b2017-07-14 16:15:55 +03001662}
1663
1664void Framebuffer::commitWebGL1DepthStencilIfConsistent(const Context *context,
1665 GLsizei numViews,
1666 GLuint baseViewIndex,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001667 bool isMultiview)
Jamie Madilla02315b2017-02-23 14:14:47 -05001668{
1669 int count = 0;
1670
1671 std::array<FramebufferAttachment *, 3> attachments = {{&mState.mWebGLDepthStencilAttachment,
1672 &mState.mWebGLDepthAttachment,
1673 &mState.mWebGLStencilAttachment}};
1674 for (FramebufferAttachment *attachment : attachments)
1675 {
1676 if (attachment->isAttached())
1677 {
1678 count++;
1679 }
1680 }
1681
1682 mState.mWebGLDepthStencilConsistent = (count <= 1);
1683 if (!mState.mWebGLDepthStencilConsistent)
1684 {
1685 // Inconsistent.
1686 return;
1687 }
1688
Geoff Lange466c552017-03-17 15:24:12 -04001689 auto getImageIndexIfTextureAttachment = [](const FramebufferAttachment &attachment) {
1690 if (attachment.type() == GL_TEXTURE)
1691 {
1692 return attachment.getTextureImageIndex();
1693 }
1694 else
1695 {
Jamie Madillcc129372018-04-12 09:13:18 -04001696 return ImageIndex();
Geoff Lange466c552017-03-17 15:24:12 -04001697 }
1698 };
1699
Jamie Madilla02315b2017-02-23 14:14:47 -05001700 if (mState.mWebGLDepthAttachment.isAttached())
1701 {
1702 const auto &depth = mState.mWebGLDepthAttachment;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001703 setAttachmentImpl(context, depth.type(), GL_DEPTH_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001704 getImageIndexIfTextureAttachment(depth), depth.getResource(), numViews,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001705 baseViewIndex, isMultiview);
Jamie Madillcc129372018-04-12 09:13:18 -04001706 setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex(), nullptr, numViews,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001707 baseViewIndex, isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001708 }
1709 else if (mState.mWebGLStencilAttachment.isAttached())
1710 {
1711 const auto &stencil = mState.mWebGLStencilAttachment;
Jamie Madillcc129372018-04-12 09:13:18 -04001712 setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex(), nullptr, numViews,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001713 baseViewIndex, isMultiview);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001714 setAttachmentImpl(context, stencil.type(), GL_STENCIL_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001715 getImageIndexIfTextureAttachment(stencil), stencil.getResource(),
Mingyu Hu7d64c482019-03-12 14:27:40 -07001716 numViews, baseViewIndex, isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001717 }
1718 else if (mState.mWebGLDepthStencilAttachment.isAttached())
1719 {
1720 const auto &depthStencil = mState.mWebGLDepthStencilAttachment;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001721 setAttachmentImpl(context, depthStencil.type(), GL_DEPTH_ATTACHMENT,
Geoff Lange466c552017-03-17 15:24:12 -04001722 getImageIndexIfTextureAttachment(depthStencil),
Mingyu Hu7d64c482019-03-12 14:27:40 -07001723 depthStencil.getResource(), numViews, baseViewIndex, isMultiview);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001724 setAttachmentImpl(context, depthStencil.type(), GL_STENCIL_ATTACHMENT,
Geoff Lange466c552017-03-17 15:24:12 -04001725 getImageIndexIfTextureAttachment(depthStencil),
Mingyu Hu7d64c482019-03-12 14:27:40 -07001726 depthStencil.getResource(), numViews, baseViewIndex, isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001727 }
1728 else
1729 {
Jamie Madillcc129372018-04-12 09:13:18 -04001730 setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex(), nullptr, numViews,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001731 baseViewIndex, isMultiview);
Jamie Madillcc129372018-04-12 09:13:18 -04001732 setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex(), nullptr, numViews,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001733 baseViewIndex, isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001734 }
1735}
1736
Jamie Madill4928b7c2017-06-20 12:57:39 -04001737void Framebuffer::setAttachmentImpl(const Context *context,
1738 GLenum type,
Jamie Madilla02315b2017-02-23 14:14:47 -05001739 GLenum binding,
1740 const ImageIndex &textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001741 FramebufferAttachmentObject *resource,
1742 GLsizei numViews,
1743 GLuint baseViewIndex,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001744 bool isMultiview)
Jamie Madilla02315b2017-02-23 14:14:47 -05001745{
Jamie Madilla02315b2017-02-23 14:14:47 -05001746 switch (binding)
1747 {
Jamie Madillb8126692017-04-05 11:22:17 -04001748 case GL_DEPTH_STENCIL:
1749 case GL_DEPTH_STENCIL_ATTACHMENT:
1750 {
1751 // ensure this is a legitimate depth+stencil format
1752 FramebufferAttachmentObject *attachmentObj = resource;
1753 if (resource)
1754 {
Jamie Madill4fd95d52017-04-05 11:22:18 -04001755 const Format &format = resource->getAttachmentFormat(binding, textureIndex);
Jamie Madillb8126692017-04-05 11:22:17 -04001756 if (format.info->depthBits == 0 || format.info->stencilBits == 0)
1757 {
1758 // Attaching nullptr detaches the current attachment.
1759 attachmentObj = nullptr;
1760 }
1761 }
1762
Jamie Madill4928b7c2017-06-20 12:57:39 -04001763 updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
Jamie Madillb8126692017-04-05 11:22:17 -04001764 &mDirtyDepthAttachmentBinding, type, binding, textureIndex,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001765 attachmentObj, numViews, baseViewIndex, isMultiview);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001766 updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
Jamie Madillb8126692017-04-05 11:22:17 -04001767 &mDirtyStencilAttachmentBinding, type, binding, textureIndex,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001768 attachmentObj, numViews, baseViewIndex, isMultiview);
Jamie Madill42975642017-10-12 12:31:51 -04001769 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001770 }
1771
Jamie Madilla02315b2017-02-23 14:14:47 -05001772 case GL_DEPTH:
1773 case GL_DEPTH_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001774 updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001775 &mDirtyDepthAttachmentBinding, type, binding, textureIndex, resource,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001776 numViews, baseViewIndex, isMultiview);
Jamie Madill2d06b732015-04-20 12:53:28 -04001777 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001778
Jamie Madilla02315b2017-02-23 14:14:47 -05001779 case GL_STENCIL:
1780 case GL_STENCIL_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001781 updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001782 &mDirtyStencilAttachmentBinding, type, binding, textureIndex, resource,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001783 numViews, baseViewIndex, isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001784 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001785
Jamie Madilla02315b2017-02-23 14:14:47 -05001786 case GL_BACK:
Geoff Lang8170eab2017-09-21 13:59:04 -04001787 updateAttachment(context, &mState.mColorAttachments[0], DIRTY_BIT_COLOR_ATTACHMENT_0,
1788 &mDirtyColorAttachmentBindings[0], type, binding, textureIndex,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001789 resource, numViews, baseViewIndex, isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001790 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001791
Jamie Madilla02315b2017-02-23 14:14:47 -05001792 default:
1793 {
1794 size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
1795 ASSERT(colorIndex < mState.mColorAttachments.size());
Jamie Madillb8126692017-04-05 11:22:17 -04001796 size_t dirtyBit = DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001797 updateAttachment(context, &mState.mColorAttachments[colorIndex], dirtyBit,
Jamie Madillb8126692017-04-05 11:22:17 -04001798 &mDirtyColorAttachmentBindings[colorIndex], type, binding,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001799 textureIndex, resource, numViews, baseViewIndex, isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001800
shrekshaoc87e0052019-02-21 11:40:28 -08001801 if (!resource)
1802 {
shrekshao8413fab2019-04-04 17:13:18 -07001803 mColorAttachmentBits.reset(colorIndex);
shrekshaoc87e0052019-02-21 11:40:28 -08001804 mFloat32ColorAttachmentBits.reset(colorIndex);
1805 }
1806 else
1807 {
shrekshao8413fab2019-04-04 17:13:18 -07001808 mColorAttachmentBits.set(colorIndex);
shrekshaoc87e0052019-02-21 11:40:28 -08001809 updateFloat32ColorAttachmentBits(
1810 colorIndex, resource->getAttachmentFormat(binding, textureIndex).info);
1811 }
1812
Corentin Walleze7557742017-06-01 13:09:57 -04001813 // TODO(jmadill): ASSERT instead of checking the attachment exists in
1814 // formsRenderingFeedbackLoopWith
Jamie Madilla02315b2017-02-23 14:14:47 -05001815 bool enabled = (type != GL_NONE && getDrawBufferState(colorIndex) != GL_NONE);
1816 mState.mEnabledDrawBuffers.set(colorIndex, enabled);
Jamie Madill6e18a232019-01-16 13:27:14 -05001817 SetComponentTypeMask(getDrawbufferWriteType(colorIndex), colorIndex,
1818 &mState.mDrawBufferTypeMask);
Jamie Madill2d06b732015-04-20 12:53:28 -04001819 }
Jamie Madilla02315b2017-02-23 14:14:47 -05001820 break;
Geoff Langab75a052014-10-15 12:56:37 -04001821 }
1822}
1823
Jamie Madill4928b7c2017-06-20 12:57:39 -04001824void Framebuffer::updateAttachment(const Context *context,
1825 FramebufferAttachment *attachment,
Jamie Madillb8126692017-04-05 11:22:17 -04001826 size_t dirtyBit,
Jamie Madilld4442552018-02-27 22:03:47 -05001827 angle::ObserverBinding *onDirtyBinding,
Jamie Madillb8126692017-04-05 11:22:17 -04001828 GLenum type,
1829 GLenum binding,
1830 const ImageIndex &textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001831 FramebufferAttachmentObject *resource,
1832 GLsizei numViews,
1833 GLuint baseViewIndex,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001834 bool isMultiview)
Jamie Madillb8126692017-04-05 11:22:17 -04001835{
Martin Radev5dae57b2017-07-14 16:15:55 +03001836 attachment->attach(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001837 isMultiview);
Jamie Madillb8126692017-04-05 11:22:17 -04001838 mDirtyBits.set(dirtyBit);
Jamie Madill05b35b22017-10-03 09:01:44 -04001839 mState.mResourceNeedsInit.set(dirtyBit, attachment->initState() == InitState::MayNeedInit);
Jamie Madill66f0d2c2018-11-30 15:25:36 -05001840 onDirtyBinding->bind(resource);
Jamie Madille98b1b52018-03-08 09:47:23 -05001841
Jamie Madill124f78c2019-06-18 11:48:24 -04001842 invalidateCompletenessCache();
Jamie Madillb8126692017-04-05 11:22:17 -04001843}
1844
Jamie Madilla02315b2017-02-23 14:14:47 -05001845void Framebuffer::resetAttachment(const Context *context, GLenum binding)
Jamie Madill2d06b732015-04-20 12:53:28 -04001846{
Jamie Madillcc129372018-04-12 09:13:18 -04001847 setAttachment(context, GL_NONE, binding, ImageIndex(), nullptr);
Jamie Madill2d06b732015-04-20 12:53:28 -04001848}
1849
Jamie Madill6f755b22018-10-09 12:48:54 -04001850angle::Result Framebuffer::syncState(const Context *context)
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001851{
1852 if (mDirtyBits.any())
1853 {
Jamie Madill888081d2018-02-27 00:24:46 -05001854 mDirtyBitsGuard = mDirtyBits;
Jamie Madill19fa1c62018-03-08 09:47:21 -05001855 ANGLE_TRY(mImpl->syncState(context, mDirtyBits));
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001856 mDirtyBits.reset();
Jamie Madill888081d2018-02-27 00:24:46 -05001857 mDirtyBitsGuard.reset();
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001858 }
Jamie Madill7c985f52018-11-29 18:16:17 -05001859 return angle::Result::Continue;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001860}
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001861
Jamie Madill124f78c2019-06-18 11:48:24 -04001862void Framebuffer::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
Jamie Madill51f40ec2016-06-15 14:06:00 -04001863{
Jamie Madille4faae22019-05-10 08:27:00 -04001864 if (message != angle::SubjectMessage::SubjectChanged)
Jamie Madillf668a4b2018-09-23 17:01:20 -04001865 {
Jamie Madill67220092019-05-20 11:12:53 -04001866 // This can be triggered by SubImage calls for Textures.
1867 if (message == angle::SubjectMessage::ContentsChanged)
1868 {
1869 mDirtyBits.set(DIRTY_BIT_COLOR_BUFFER_CONTENTS_0 + index);
Jamie Madill124f78c2019-06-18 11:48:24 -04001870 onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
Jamie Madill67220092019-05-20 11:12:53 -04001871 return;
1872 }
1873
Jamie Madillf668a4b2018-09-23 17:01:20 -04001874 // This can be triggered by the GL back-end TextureGL class.
Jamie Madille4faae22019-05-10 08:27:00 -04001875 ASSERT(message == angle::SubjectMessage::DirtyBitsFlagged);
Jamie Madillf668a4b2018-09-23 17:01:20 -04001876 return;
1877 }
Jamie Madill55e57f92018-09-18 11:32:43 -04001878
1879 ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(index));
1880 mDirtyBits.set(index);
Jamie Madill888081d2018-02-27 00:24:46 -05001881
Jamie Madill124f78c2019-06-18 11:48:24 -04001882 invalidateCompletenessCache();
Jamie Madill05b35b22017-10-03 09:01:44 -04001883
Jamie Madilld4442552018-02-27 22:03:47 -05001884 FramebufferAttachment *attachment = getAttachmentFromSubjectIndex(index);
1885
Jamie Madill05b35b22017-10-03 09:01:44 -04001886 // Mark the appropriate init flag.
Jamie Madilld4442552018-02-27 22:03:47 -05001887 mState.mResourceNeedsInit.set(index, attachment->initState() == InitState::MayNeedInit);
shrekshaoc87e0052019-02-21 11:40:28 -08001888
1889 // Update mFloat32ColorAttachmentBits Cache
1890 if (index < DIRTY_BIT_COLOR_ATTACHMENT_MAX)
1891 {
1892 ASSERT(index != DIRTY_BIT_DEPTH_ATTACHMENT);
1893 ASSERT(index != DIRTY_BIT_STENCIL_ATTACHMENT);
1894 updateFloat32ColorAttachmentBits(index - DIRTY_BIT_COLOR_ATTACHMENT_0,
1895 attachment->getFormat().info);
1896 }
Jamie Madilld4442552018-02-27 22:03:47 -05001897}
1898
1899FramebufferAttachment *Framebuffer::getAttachmentFromSubjectIndex(angle::SubjectIndex index)
1900{
1901 switch (index)
1902 {
1903 case DIRTY_BIT_DEPTH_ATTACHMENT:
1904 return &mState.mDepthAttachment;
1905 case DIRTY_BIT_STENCIL_ATTACHMENT:
1906 return &mState.mStencilAttachment;
1907 default:
1908 size_t colorIndex = (index - DIRTY_BIT_COLOR_ATTACHMENT_0);
1909 ASSERT(colorIndex < mState.mColorAttachments.size());
1910 return &mState.mColorAttachments[colorIndex];
1911 }
Jamie Madill51f40ec2016-06-15 14:06:00 -04001912}
1913
shrekshao8413fab2019-04-04 17:13:18 -07001914bool Framebuffer::formsRenderingFeedbackLoopWith(const Context *context) const
Jamie Madilla4595b82017-01-11 17:36:34 -05001915{
shrekshao8413fab2019-04-04 17:13:18 -07001916 const State &state = context->getState();
Jamie Madill785e8a02018-10-04 17:42:00 -04001917 const Program *program = state.getProgram();
Jamie Madilla4595b82017-01-11 17:36:34 -05001918
1919 // TODO(jmadill): Default framebuffer feedback loops.
Jamie Madill2274b652018-05-31 10:56:08 -04001920 if (mState.mId == 0)
Jamie Madilla4595b82017-01-11 17:36:34 -05001921 {
1922 return false;
1923 }
1924
Jamie Madill4e71b2b2019-07-08 13:23:38 -04001925 const FramebufferAttachment *depth = getDepthAttachment();
1926 const FramebufferAttachment *stencil = getStencilAttachment();
shrekshao8413fab2019-04-04 17:13:18 -07001927
1928 const bool checkDepth = depth && depth->type() == GL_TEXTURE;
1929 // Skip the feedback loop check for stencil if depth/stencil point to the same resource.
1930 const bool checkStencil =
1931 (stencil && stencil->type() == GL_TEXTURE) && (!depth || *stencil != *depth);
1932
1933 const gl::ActiveTextureMask &activeTextures = program->getActiveSamplersMask();
1934 const gl::ActiveTexturePointerArray &textures = state.getActiveTexturesCache();
1935
1936 for (size_t textureUnit : activeTextures)
Jamie Madilla4595b82017-01-11 17:36:34 -05001937 {
shrekshao8413fab2019-04-04 17:13:18 -07001938 Texture *texture = textures[textureUnit];
1939
1940 if (texture == nullptr)
Jamie Madilla4595b82017-01-11 17:36:34 -05001941 {
shrekshao8413fab2019-04-04 17:13:18 -07001942 continue;
1943 }
1944
1945 // Depth and stencil attachment form feedback loops
1946 // Regardless of if enabled or masked.
1947 if (checkDepth)
1948 {
1949 if (texture->id() == depth->id())
Jamie Madilla4595b82017-01-11 17:36:34 -05001950 {
1951 return true;
1952 }
1953 }
Jamie Madilla4595b82017-01-11 17:36:34 -05001954
shrekshao8413fab2019-04-04 17:13:18 -07001955 if (checkStencil)
Jamie Madill1d37bc52017-02-02 19:59:58 -05001956 {
shrekshao8413fab2019-04-04 17:13:18 -07001957 if (texture->id() == stencil->id())
Jamie Madill1d37bc52017-02-02 19:59:58 -05001958 {
Jamie Madill38fe6842018-09-19 07:20:00 -04001959 return true;
Jamie Madill1d37bc52017-02-02 19:59:58 -05001960 }
1961 }
shrekshao8413fab2019-04-04 17:13:18 -07001962
1963 // Check if any color attachment forms a feedback loop.
1964 for (size_t drawIndex : mColorAttachmentBits)
1965 {
1966 const FramebufferAttachment &attachment = mState.mColorAttachments[drawIndex];
1967 ASSERT(attachment.isAttached());
1968
1969 if (attachment.isTextureWithId(texture->id()))
1970 {
1971 // TODO(jmadill): Check for appropriate overlap.
1972 return true;
1973 }
1974 }
Jamie Madill1d37bc52017-02-02 19:59:58 -05001975 }
1976
Jamie Madilla4595b82017-01-11 17:36:34 -05001977 return false;
1978}
1979
Jamie Madillfd3dd432017-02-02 19:59:59 -05001980bool Framebuffer::formsCopyingFeedbackLoopWith(GLuint copyTextureID,
1981 GLint copyTextureLevel,
1982 GLint copyTextureLayer) const
Jamie Madillf695a3a2017-01-11 17:36:35 -05001983{
Jamie Madill2274b652018-05-31 10:56:08 -04001984 if (mState.mId == 0)
Jamie Madillf695a3a2017-01-11 17:36:35 -05001985 {
1986 // It seems impossible to form a texture copying feedback loop with the default FBO.
1987 return false;
1988 }
1989
Jamie Madill4e71b2b2019-07-08 13:23:38 -04001990 const FramebufferAttachment *readAttachment = getReadColorAttachment();
Jamie Madillf695a3a2017-01-11 17:36:35 -05001991 ASSERT(readAttachment);
1992
1993 if (readAttachment->isTextureWithId(copyTextureID))
1994 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05001995 const auto &imageIndex = readAttachment->getTextureImageIndex();
Jamie Madillcc129372018-04-12 09:13:18 -04001996 if (imageIndex.getLevelIndex() == copyTextureLevel)
Jamie Madillf695a3a2017-01-11 17:36:35 -05001997 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05001998 // Check 3D/Array texture layers.
Jamie Madillcc129372018-04-12 09:13:18 -04001999 return !imageIndex.hasLayer() || copyTextureLayer == ImageIndex::kEntireLevel ||
2000 imageIndex.getLayerIndex() == copyTextureLayer;
Jamie Madillf695a3a2017-01-11 17:36:35 -05002001 }
2002 }
2003 return false;
2004}
2005
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002006GLint Framebuffer::getDefaultWidth() const
2007{
2008 return mState.getDefaultWidth();
2009}
2010
2011GLint Framebuffer::getDefaultHeight() const
2012{
2013 return mState.getDefaultHeight();
2014}
2015
2016GLint Framebuffer::getDefaultSamples() const
2017{
2018 return mState.getDefaultSamples();
2019}
2020
Geoff Lang92019432017-11-20 13:09:34 -05002021bool Framebuffer::getDefaultFixedSampleLocations() const
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002022{
2023 return mState.getDefaultFixedSampleLocations();
2024}
2025
Jiawei Shaob1e91382018-05-17 14:33:55 +08002026GLint Framebuffer::getDefaultLayers() const
2027{
2028 return mState.getDefaultLayers();
2029}
2030
Jamie Madillb983a4b2018-08-01 11:34:51 -04002031void Framebuffer::setDefaultWidth(const Context *context, GLint defaultWidth)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002032{
2033 mState.mDefaultWidth = defaultWidth;
2034 mDirtyBits.set(DIRTY_BIT_DEFAULT_WIDTH);
Jamie Madill124f78c2019-06-18 11:48:24 -04002035 invalidateCompletenessCache();
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002036}
2037
Jamie Madillb983a4b2018-08-01 11:34:51 -04002038void Framebuffer::setDefaultHeight(const Context *context, GLint defaultHeight)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002039{
2040 mState.mDefaultHeight = defaultHeight;
2041 mDirtyBits.set(DIRTY_BIT_DEFAULT_HEIGHT);
Jamie Madill124f78c2019-06-18 11:48:24 -04002042 invalidateCompletenessCache();
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002043}
2044
Jamie Madillb983a4b2018-08-01 11:34:51 -04002045void Framebuffer::setDefaultSamples(const Context *context, GLint defaultSamples)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002046{
2047 mState.mDefaultSamples = defaultSamples;
2048 mDirtyBits.set(DIRTY_BIT_DEFAULT_SAMPLES);
Jamie Madill124f78c2019-06-18 11:48:24 -04002049 invalidateCompletenessCache();
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002050}
2051
Jamie Madillb983a4b2018-08-01 11:34:51 -04002052void Framebuffer::setDefaultFixedSampleLocations(const Context *context,
2053 bool defaultFixedSampleLocations)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002054{
2055 mState.mDefaultFixedSampleLocations = defaultFixedSampleLocations;
2056 mDirtyBits.set(DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS);
Jamie Madill124f78c2019-06-18 11:48:24 -04002057 invalidateCompletenessCache();
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002058}
2059
Jiawei Shaob1e91382018-05-17 14:33:55 +08002060void Framebuffer::setDefaultLayers(GLint defaultLayers)
2061{
2062 mState.mDefaultLayers = defaultLayers;
2063 mDirtyBits.set(DIRTY_BIT_DEFAULT_LAYERS);
2064}
2065
Martin Radev14a26ae2017-07-24 15:56:29 +03002066GLsizei Framebuffer::getNumViews() const
2067{
Martin Radev5c00d0d2017-08-07 10:06:59 +03002068 return mState.getNumViews();
Martin Radev14a26ae2017-07-24 15:56:29 +03002069}
2070
Martin Radev4e619f52017-08-09 11:50:06 +03002071GLint Framebuffer::getBaseViewIndex() const
2072{
2073 return mState.getBaseViewIndex();
2074}
2075
Mingyu Hu7d64c482019-03-12 14:27:40 -07002076bool Framebuffer::isMultiview() const
Martin Radev878c8b12017-07-28 09:51:04 +03002077{
Mingyu Hu7d64c482019-03-12 14:27:40 -07002078 return mState.isMultiview();
Martin Radev878c8b12017-07-28 09:51:04 +03002079}
2080
Olli Etuaho8acb1b62018-07-30 16:20:54 +03002081bool Framebuffer::readDisallowedByMultiview() const
2082{
Mingyu Hu7d64c482019-03-12 14:27:40 -07002083 return (mState.isMultiview() && mState.getNumViews() > 1);
Olli Etuaho8acb1b62018-07-30 16:20:54 +03002084}
2085
Jamie Madill64b7c4f2018-10-19 11:38:04 -04002086angle::Result Framebuffer::ensureClearAttachmentsInitialized(const Context *context,
2087 GLbitfield mask)
Geoff Langd4fff502017-09-22 11:28:28 -04002088{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05002089 const auto &glState = context->getState();
Geoff Langd4fff502017-09-22 11:28:28 -04002090 if (!context->isRobustResourceInitEnabled() || glState.isRasterizerDiscardEnabled())
2091 {
Jamie Madill7c985f52018-11-29 18:16:17 -05002092 return angle::Result::Continue;
Geoff Langd4fff502017-09-22 11:28:28 -04002093 }
2094
Geoff Langa36483f2018-03-09 16:11:21 -05002095 const BlendState &blend = glState.getBlendState();
2096 const DepthStencilState &depthStencil = glState.getDepthStencilState();
Geoff Langd4fff502017-09-22 11:28:28 -04002097
2098 bool color = (mask & GL_COLOR_BUFFER_BIT) != 0 && !IsColorMaskedOut(blend);
2099 bool depth = (mask & GL_DEPTH_BUFFER_BIT) != 0 && !IsDepthMaskedOut(depthStencil);
2100 bool stencil = (mask & GL_STENCIL_BUFFER_BIT) != 0 && !IsStencilMaskedOut(depthStencil);
2101
2102 if (!color && !depth && !stencil)
2103 {
Jamie Madill7c985f52018-11-29 18:16:17 -05002104 return angle::Result::Continue;
Geoff Langd4fff502017-09-22 11:28:28 -04002105 }
2106
2107 if (partialClearNeedsInit(context, color, depth, stencil))
2108 {
2109 ANGLE_TRY(ensureDrawAttachmentsInitialized(context));
2110 }
2111
2112 // If the impl encounters an error during a a full (non-partial) clear, the attachments will
2113 // still be marked initialized. This simplifies design, allowing this method to be called before
2114 // the clear.
2115 markDrawAttachmentsInitialized(color, depth, stencil);
2116
Jamie Madill7c985f52018-11-29 18:16:17 -05002117 return angle::Result::Continue;
Geoff Langd4fff502017-09-22 11:28:28 -04002118}
2119
Jamie Madill64b7c4f2018-10-19 11:38:04 -04002120angle::Result Framebuffer::ensureClearBufferAttachmentsInitialized(const Context *context,
2121 GLenum buffer,
2122 GLint drawbuffer)
Geoff Langd4fff502017-09-22 11:28:28 -04002123{
2124 if (!context->isRobustResourceInitEnabled() ||
Jamie Madillc3dc5d42018-12-30 12:12:04 -05002125 context->getState().isRasterizerDiscardEnabled() || IsClearBufferMaskedOut(context, buffer))
Geoff Langd4fff502017-09-22 11:28:28 -04002126 {
Jamie Madill7c985f52018-11-29 18:16:17 -05002127 return angle::Result::Continue;
Geoff Langd4fff502017-09-22 11:28:28 -04002128 }
2129
2130 if (partialBufferClearNeedsInit(context, buffer))
2131 {
2132 ANGLE_TRY(ensureBufferInitialized(context, buffer, drawbuffer));
2133 }
2134
2135 // If the impl encounters an error during a a full (non-partial) clear, the attachments will
2136 // still be marked initialized. This simplifies design, allowing this method to be called before
2137 // the clear.
2138 markBufferInitialized(buffer, drawbuffer);
2139
Jamie Madill7c985f52018-11-29 18:16:17 -05002140 return angle::Result::Continue;
Geoff Langd4fff502017-09-22 11:28:28 -04002141}
2142
Jamie Madill6f755b22018-10-09 12:48:54 -04002143angle::Result Framebuffer::ensureDrawAttachmentsInitialized(const Context *context)
Jamie Madill05b35b22017-10-03 09:01:44 -04002144{
2145 if (!context->isRobustResourceInitEnabled())
2146 {
Jamie Madill7c985f52018-11-29 18:16:17 -05002147 return angle::Result::Continue;
Jamie Madill05b35b22017-10-03 09:01:44 -04002148 }
2149
2150 // Note: we don't actually filter by the draw attachment enum. Just init everything.
2151 for (size_t bit : mState.mResourceNeedsInit)
2152 {
2153 switch (bit)
2154 {
2155 case DIRTY_BIT_DEPTH_ATTACHMENT:
2156 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2157 break;
2158 case DIRTY_BIT_STENCIL_ATTACHMENT:
2159 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2160 break;
2161 default:
2162 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[bit]));
2163 break;
2164 }
2165 }
2166
2167 mState.mResourceNeedsInit.reset();
Jamie Madill7c985f52018-11-29 18:16:17 -05002168 return angle::Result::Continue;
Jamie Madill05b35b22017-10-03 09:01:44 -04002169}
2170
Jamie Madill0a1eeb82019-05-13 13:53:18 -04002171angle::Result Framebuffer::ensureReadAttachmentsInitialized(const Context *context)
Jamie Madill05b35b22017-10-03 09:01:44 -04002172{
Jamie Madill0a1eeb82019-05-13 13:53:18 -04002173 ASSERT(context->isRobustResourceInitEnabled());
2174
2175 if (mState.mResourceNeedsInit.none())
Jamie Madill05b35b22017-10-03 09:01:44 -04002176 {
Jamie Madill7c985f52018-11-29 18:16:17 -05002177 return angle::Result::Continue;
Jamie Madill05b35b22017-10-03 09:01:44 -04002178 }
2179
Jamie Madill0a1eeb82019-05-13 13:53:18 -04002180 if (mState.mReadBufferState != GL_NONE)
Jamie Madill05b35b22017-10-03 09:01:44 -04002181 {
2182 size_t readIndex = mState.getReadIndex();
2183 if (mState.mResourceNeedsInit[readIndex])
2184 {
2185 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[readIndex]));
2186 mState.mResourceNeedsInit.reset(readIndex);
2187 }
2188 }
2189
Jamie Madill0a1eeb82019-05-13 13:53:18 -04002190 // Conservatively init depth since it can be read by BlitFramebuffer.
2191 if (hasDepth())
Jamie Madill05b35b22017-10-03 09:01:44 -04002192 {
2193 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2194 {
2195 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2196 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2197 }
2198 }
2199
Jamie Madill0a1eeb82019-05-13 13:53:18 -04002200 // Conservatively init stencil since it can be read by BlitFramebuffer.
2201 if (hasStencil())
Jamie Madill05b35b22017-10-03 09:01:44 -04002202 {
2203 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2204 {
2205 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2206 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2207 }
2208 }
2209
Jamie Madill7c985f52018-11-29 18:16:17 -05002210 return angle::Result::Continue;
Jamie Madill05b35b22017-10-03 09:01:44 -04002211}
2212
2213void Framebuffer::markDrawAttachmentsInitialized(bool color, bool depth, bool stencil)
2214{
2215 // Mark attachments as initialized.
2216 if (color)
2217 {
2218 for (auto colorIndex : mState.mEnabledDrawBuffers)
2219 {
2220 auto &colorAttachment = mState.mColorAttachments[colorIndex];
2221 ASSERT(colorAttachment.isAttached());
2222 colorAttachment.setInitState(InitState::Initialized);
2223 mState.mResourceNeedsInit.reset(colorIndex);
2224 }
2225 }
2226
2227 if (depth && mState.mDepthAttachment.isAttached())
2228 {
2229 mState.mDepthAttachment.setInitState(InitState::Initialized);
2230 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2231 }
2232
2233 if (stencil && mState.mStencilAttachment.isAttached())
2234 {
2235 mState.mStencilAttachment.setInitState(InitState::Initialized);
2236 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2237 }
2238}
2239
2240void Framebuffer::markBufferInitialized(GLenum bufferType, GLint bufferIndex)
2241{
2242 switch (bufferType)
2243 {
2244 case GL_COLOR:
2245 {
2246 ASSERT(bufferIndex < static_cast<GLint>(mState.mColorAttachments.size()));
2247 if (mState.mColorAttachments[bufferIndex].isAttached())
2248 {
2249 mState.mColorAttachments[bufferIndex].setInitState(InitState::Initialized);
2250 mState.mResourceNeedsInit.reset(bufferIndex);
2251 }
2252 break;
2253 }
2254 case GL_DEPTH:
2255 {
2256 if (mState.mDepthAttachment.isAttached())
2257 {
2258 mState.mDepthAttachment.setInitState(InitState::Initialized);
2259 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2260 }
2261 break;
2262 }
2263 case GL_STENCIL:
2264 {
2265 if (mState.mStencilAttachment.isAttached())
2266 {
2267 mState.mStencilAttachment.setInitState(InitState::Initialized);
2268 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2269 }
2270 break;
2271 }
2272 case GL_DEPTH_STENCIL:
2273 {
2274 if (mState.mDepthAttachment.isAttached())
2275 {
2276 mState.mDepthAttachment.setInitState(InitState::Initialized);
2277 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2278 }
2279 if (mState.mStencilAttachment.isAttached())
2280 {
2281 mState.mStencilAttachment.setInitState(InitState::Initialized);
2282 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2283 }
2284 break;
2285 }
2286 default:
2287 UNREACHABLE();
2288 break;
2289 }
2290}
2291
2292Box Framebuffer::getDimensions() const
2293{
2294 return mState.getDimensions();
2295}
2296
Jonah Ryan-Davis7151fe52019-07-17 15:15:27 -04002297Extents Framebuffer::getExtents() const
2298{
2299 return mState.getExtents();
2300}
2301
Jamie Madill64b7c4f2018-10-19 11:38:04 -04002302angle::Result Framebuffer::ensureBufferInitialized(const Context *context,
2303 GLenum bufferType,
2304 GLint bufferIndex)
Jamie Madill05b35b22017-10-03 09:01:44 -04002305{
2306 ASSERT(context->isRobustResourceInitEnabled());
2307
2308 if (mState.mResourceNeedsInit.none())
2309 {
Jamie Madill7c985f52018-11-29 18:16:17 -05002310 return angle::Result::Continue;
Jamie Madill05b35b22017-10-03 09:01:44 -04002311 }
2312
2313 switch (bufferType)
2314 {
2315 case GL_COLOR:
2316 {
2317 ASSERT(bufferIndex < static_cast<GLint>(mState.mColorAttachments.size()));
2318 if (mState.mResourceNeedsInit[bufferIndex])
2319 {
2320 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[bufferIndex]));
2321 mState.mResourceNeedsInit.reset(bufferIndex);
2322 }
2323 break;
2324 }
2325 case GL_DEPTH:
2326 {
2327 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2328 {
2329 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2330 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2331 }
2332 break;
2333 }
2334 case GL_STENCIL:
2335 {
2336 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2337 {
2338 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2339 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2340 }
2341 break;
2342 }
2343 case GL_DEPTH_STENCIL:
2344 {
2345 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2346 {
2347 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2348 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2349 }
2350 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2351 {
2352 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2353 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2354 }
2355 break;
2356 }
2357 default:
2358 UNREACHABLE();
2359 break;
2360 }
2361
Jamie Madill7c985f52018-11-29 18:16:17 -05002362 return angle::Result::Continue;
Jamie Madill05b35b22017-10-03 09:01:44 -04002363}
2364
2365bool Framebuffer::partialBufferClearNeedsInit(const Context *context, GLenum bufferType)
2366{
2367 if (!context->isRobustResourceInitEnabled() || mState.mResourceNeedsInit.none())
2368 {
2369 return false;
2370 }
2371
2372 switch (bufferType)
2373 {
2374 case GL_COLOR:
2375 return partialClearNeedsInit(context, true, false, false);
2376 case GL_DEPTH:
2377 return partialClearNeedsInit(context, false, true, false);
2378 case GL_STENCIL:
2379 return partialClearNeedsInit(context, false, false, true);
2380 case GL_DEPTH_STENCIL:
2381 return partialClearNeedsInit(context, false, true, true);
2382 default:
2383 UNREACHABLE();
2384 return false;
2385 }
2386}
Jamie Madill60ec6ea2016-01-22 15:27:19 -05002387} // namespace gl