blob: f56e177777786178ddf600794ce7f51f2d855e93 [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
Stuart Morgan9d737962019-08-14 12:25:12 -07002// Copyright 2002 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()
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600262 : mId(Framebuffer::kDefaultDrawFramebufferHandle),
Jamie Madill2274b652018-05-31 10:56:08 -0400263 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),
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600273 mWebGLDepthStencilConsistent(true),
274 mDefaultFramebufferReadAttachmentInitialized(false)
Corentin Wallez37c39792015-08-20 14:19:46 -0400275{
Geoff Langd90d3882017-03-21 10:49:54 -0400276 ASSERT(mDrawBufferStates.size() > 0);
Jamie Madilla4595b82017-01-11 17:36:34 -0500277 mEnabledDrawBuffers.set(0);
Corentin Wallez37c39792015-08-20 14:19:46 -0400278}
279
Jamie Madill2274b652018-05-31 10:56:08 -0400280FramebufferState::FramebufferState(const Caps &caps, GLuint id)
281 : mId(id),
282 mLabel(),
Geoff Lang70d0f492015-12-10 17:45:46 -0500283 mColorAttachments(caps.maxColorAttachments),
Jamie Madilld1405e52015-03-05 15:41:39 -0500284 mDrawBufferStates(caps.maxDrawBuffers, GL_NONE),
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800285 mReadBufferState(GL_COLOR_ATTACHMENT0_EXT),
Brandon Jones76746f92017-11-22 11:44:41 -0800286 mDrawBufferTypeMask(),
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800287 mDefaultWidth(0),
288 mDefaultHeight(0),
289 mDefaultSamples(0),
Jamie Madilla02315b2017-02-23 14:14:47 -0500290 mDefaultFixedSampleLocations(GL_FALSE),
Jiawei Shaob1e91382018-05-17 14:33:55 +0800291 mDefaultLayers(0),
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600292 mWebGLDepthStencilConsistent(true),
293 mDefaultFramebufferReadAttachmentInitialized(false)
Jamie Madilld1405e52015-03-05 15:41:39 -0500294{
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600295 ASSERT(mId != Framebuffer::kDefaultDrawFramebufferHandle);
Geoff Langa15472a2015-08-11 11:48:03 -0400296 ASSERT(mDrawBufferStates.size() > 0);
Jamie Madilld1405e52015-03-05 15:41:39 -0500297 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
298}
299
Jamie Madillb980c562018-11-27 11:34:27 -0500300FramebufferState::~FramebufferState() {}
Jamie Madilld1405e52015-03-05 15:41:39 -0500301
Jamie Madill48ef11b2016-04-27 15:21:52 -0400302const std::string &FramebufferState::getLabel()
Geoff Lang70d0f492015-12-10 17:45:46 -0500303{
304 return mLabel;
305}
306
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800307const FramebufferAttachment *FramebufferState::getAttachment(const Context *context,
308 GLenum attachment) const
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400309{
310 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
311 {
312 return getColorAttachment(attachment - GL_COLOR_ATTACHMENT0);
313 }
314
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800315 // WebGL1 allows a developer to query for attachment parameters even when "inconsistant" (i.e.
316 // multiple conflicting attachment points) and requires us to return the framebuffer attachment
317 // associated with WebGL.
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400318 switch (attachment)
319 {
320 case GL_COLOR:
321 case GL_BACK:
322 return getColorAttachment(0);
323 case GL_DEPTH:
324 case GL_DEPTH_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800325 if (context->isWebGL1())
326 {
327 return getWebGLDepthAttachment();
328 }
329 else
330 {
331 return getDepthAttachment();
332 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400333 case GL_STENCIL:
334 case GL_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800335 if (context->isWebGL1())
336 {
337 return getWebGLStencilAttachment();
338 }
339 else
340 {
341 return getStencilAttachment();
342 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400343 case GL_DEPTH_STENCIL:
344 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800345 if (context->isWebGL1())
346 {
347 return getWebGLDepthStencilAttachment();
348 }
349 else
350 {
351 return getDepthStencilAttachment();
352 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400353 default:
354 UNREACHABLE();
355 return nullptr;
356 }
357}
358
Jamie Madill05b35b22017-10-03 09:01:44 -0400359size_t FramebufferState::getReadIndex() const
Jamie Madill7147f012015-03-05 15:41:40 -0500360{
Jamie Madill231c7f52017-04-26 13:45:37 -0400361 ASSERT(mReadBufferState == GL_BACK ||
362 (mReadBufferState >= GL_COLOR_ATTACHMENT0 && mReadBufferState <= GL_COLOR_ATTACHMENT15));
363 size_t readIndex = (mReadBufferState == GL_BACK
364 ? 0
365 : static_cast<size_t>(mReadBufferState - GL_COLOR_ATTACHMENT0));
Jamie Madill7147f012015-03-05 15:41:40 -0500366 ASSERT(readIndex < mColorAttachments.size());
Jamie Madill05b35b22017-10-03 09:01:44 -0400367 return readIndex;
368}
369
370const FramebufferAttachment *FramebufferState::getReadAttachment() const
371{
372 if (mReadBufferState == GL_NONE)
373 {
374 return nullptr;
375 }
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600376
Jamie Madill05b35b22017-10-03 09:01:44 -0400377 size_t readIndex = getReadIndex();
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600378 const gl::FramebufferAttachment &framebufferAttachment =
379 isDefault() ? mDefaultFramebufferReadAttachment : mColorAttachments[readIndex];
380
381 return framebufferAttachment.isAttached() ? &framebufferAttachment : nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500382}
383
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500384const FramebufferAttachment *FramebufferState::getFirstNonNullAttachment() const
385{
386 auto *colorAttachment = getFirstColorAttachment();
387 if (colorAttachment)
388 {
389 return colorAttachment;
390 }
391 return getDepthOrStencilAttachment();
392}
393
Jamie Madill48ef11b2016-04-27 15:21:52 -0400394const FramebufferAttachment *FramebufferState::getFirstColorAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500395{
Jamie Madill2d06b732015-04-20 12:53:28 -0400396 for (const FramebufferAttachment &colorAttachment : mColorAttachments)
Jamie Madill7147f012015-03-05 15:41:40 -0500397 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400398 if (colorAttachment.isAttached())
Jamie Madill7147f012015-03-05 15:41:40 -0500399 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400400 return &colorAttachment;
Jamie Madill7147f012015-03-05 15:41:40 -0500401 }
402 }
403
404 return nullptr;
405}
406
Jamie Madill48ef11b2016-04-27 15:21:52 -0400407const FramebufferAttachment *FramebufferState::getDepthOrStencilAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500408{
Jamie Madill2d06b732015-04-20 12:53:28 -0400409 if (mDepthAttachment.isAttached())
410 {
411 return &mDepthAttachment;
412 }
413 if (mStencilAttachment.isAttached())
414 {
415 return &mStencilAttachment;
416 }
417 return nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500418}
419
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500420const FramebufferAttachment *FramebufferState::getStencilOrDepthStencilAttachment() const
421{
422 if (mStencilAttachment.isAttached())
423 {
424 return &mStencilAttachment;
425 }
426 return getDepthStencilAttachment();
427}
428
Jamie Madill48ef11b2016-04-27 15:21:52 -0400429const FramebufferAttachment *FramebufferState::getColorAttachment(size_t colorAttachment) const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400430{
431 ASSERT(colorAttachment < mColorAttachments.size());
Jamie Madill231c7f52017-04-26 13:45:37 -0400432 return mColorAttachments[colorAttachment].isAttached() ? &mColorAttachments[colorAttachment]
433 : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400434}
435
Jamie Madill48ef11b2016-04-27 15:21:52 -0400436const FramebufferAttachment *FramebufferState::getDepthAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400437{
Jamie Madill2d06b732015-04-20 12:53:28 -0400438 return mDepthAttachment.isAttached() ? &mDepthAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400439}
440
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800441const FramebufferAttachment *FramebufferState::getWebGLDepthAttachment() const
442{
443 return mWebGLDepthAttachment.isAttached() ? &mWebGLDepthAttachment : nullptr;
444}
445
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800446const FramebufferAttachment *FramebufferState::getWebGLDepthStencilAttachment() const
447{
448 return mWebGLDepthStencilAttachment.isAttached() ? &mWebGLDepthStencilAttachment : nullptr;
449}
450
Jamie Madill48ef11b2016-04-27 15:21:52 -0400451const FramebufferAttachment *FramebufferState::getStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400452{
Jamie Madill2d06b732015-04-20 12:53:28 -0400453 return mStencilAttachment.isAttached() ? &mStencilAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400454}
455
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800456const FramebufferAttachment *FramebufferState::getWebGLStencilAttachment() const
457{
458 return mWebGLStencilAttachment.isAttached() ? &mWebGLStencilAttachment : nullptr;
459}
460
Jamie Madill48ef11b2016-04-27 15:21:52 -0400461const FramebufferAttachment *FramebufferState::getDepthStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400462{
463 // A valid depth-stencil attachment has the same resource bound to both the
464 // depth and stencil attachment points.
Jamie Madill2d06b732015-04-20 12:53:28 -0400465 if (mDepthAttachment.isAttached() && mStencilAttachment.isAttached() &&
Jamie Madill44f26482016-11-18 12:49:15 -0500466 mDepthAttachment == mStencilAttachment)
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400467 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400468 return &mDepthAttachment;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400469 }
470
471 return nullptr;
472}
473
Jamie Madill48ef11b2016-04-27 15:21:52 -0400474bool FramebufferState::attachmentsHaveSameDimensions() const
Jamie Madillcc86d642015-11-24 13:00:07 -0500475{
476 Optional<Extents> attachmentSize;
477
Jamie Madill231c7f52017-04-26 13:45:37 -0400478 auto hasMismatchedSize = [&attachmentSize](const FramebufferAttachment &attachment) {
Jamie Madillcc86d642015-11-24 13:00:07 -0500479 if (!attachment.isAttached())
480 {
481 return false;
482 }
483
484 if (!attachmentSize.valid())
485 {
486 attachmentSize = attachment.getSize();
487 return false;
488 }
489
Jeff Gilbert8f8edd62017-10-31 14:26:30 -0700490 const auto &prevSize = attachmentSize.value();
491 const auto &curSize = attachment.getSize();
492 return (curSize.width != prevSize.width || curSize.height != prevSize.height);
Jamie Madillcc86d642015-11-24 13:00:07 -0500493 };
494
495 for (const auto &attachment : mColorAttachments)
496 {
497 if (hasMismatchedSize(attachment))
498 {
499 return false;
500 }
501 }
502
503 if (hasMismatchedSize(mDepthAttachment))
504 {
505 return false;
506 }
507
508 return !hasMismatchedSize(mStencilAttachment);
509}
510
Luc Ferron5bdf8bd2018-06-20 09:51:37 -0400511bool FramebufferState::hasSeparateDepthAndStencilAttachments() const
512{
513 // if we have both a depth and stencil buffer, they must refer to the same object
514 // since we only support packed_depth_stencil and not separate depth and stencil
515 return (getDepthAttachment() != nullptr && getStencilAttachment() != nullptr &&
516 getDepthStencilAttachment() == nullptr);
517}
518
Jamie Madilld4442552018-02-27 22:03:47 -0500519const FramebufferAttachment *FramebufferState::getDrawBuffer(size_t drawBufferIdx) const
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400520{
521 ASSERT(drawBufferIdx < mDrawBufferStates.size());
522 if (mDrawBufferStates[drawBufferIdx] != GL_NONE)
523 {
524 // ES3 spec: "If the GL is bound to a draw framebuffer object, the ith buffer listed in bufs
525 // must be COLOR_ATTACHMENTi or NONE"
526 ASSERT(mDrawBufferStates[drawBufferIdx] == GL_COLOR_ATTACHMENT0 + drawBufferIdx ||
527 (drawBufferIdx == 0 && mDrawBufferStates[drawBufferIdx] == GL_BACK));
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800528
529 if (mDrawBufferStates[drawBufferIdx] == GL_BACK)
530 {
531 return getColorAttachment(0);
532 }
533 else
534 {
535 return getColorAttachment(mDrawBufferStates[drawBufferIdx] - GL_COLOR_ATTACHMENT0);
536 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400537 }
538 else
539 {
540 return nullptr;
541 }
542}
543
544size_t FramebufferState::getDrawBufferCount() const
545{
546 return mDrawBufferStates.size();
547}
548
Geoff Langb21e20d2016-07-19 15:35:41 -0400549bool FramebufferState::colorAttachmentsAreUniqueImages() const
550{
551 for (size_t firstAttachmentIdx = 0; firstAttachmentIdx < mColorAttachments.size();
552 firstAttachmentIdx++)
553 {
Jamie Madilld4442552018-02-27 22:03:47 -0500554 const FramebufferAttachment &firstAttachment = mColorAttachments[firstAttachmentIdx];
Geoff Langb21e20d2016-07-19 15:35:41 -0400555 if (!firstAttachment.isAttached())
556 {
557 continue;
558 }
559
560 for (size_t secondAttachmentIdx = firstAttachmentIdx + 1;
561 secondAttachmentIdx < mColorAttachments.size(); secondAttachmentIdx++)
562 {
Jamie Madilld4442552018-02-27 22:03:47 -0500563 const FramebufferAttachment &secondAttachment = mColorAttachments[secondAttachmentIdx];
Geoff Langb21e20d2016-07-19 15:35:41 -0400564 if (!secondAttachment.isAttached())
565 {
566 continue;
567 }
568
569 if (firstAttachment == secondAttachment)
570 {
571 return false;
572 }
573 }
574 }
575
576 return true;
577}
578
Jamie Madill9c335862017-07-18 11:51:38 -0400579bool FramebufferState::hasDepth() const
580{
581 return (mDepthAttachment.isAttached() && mDepthAttachment.getDepthSize() > 0);
582}
583
584bool FramebufferState::hasStencil() const
585{
586 return (mStencilAttachment.isAttached() && mStencilAttachment.getStencilSize() > 0);
587}
588
Mingyu Hu7d64c482019-03-12 14:27:40 -0700589bool FramebufferState::isMultiview() const
Martin Radev5c00d0d2017-08-07 10:06:59 +0300590{
591 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
592 if (attachment == nullptr)
593 {
Mingyu Hu7d64c482019-03-12 14:27:40 -0700594 return false;
Martin Radev5c00d0d2017-08-07 10:06:59 +0300595 }
Mingyu Hu7d64c482019-03-12 14:27:40 -0700596 return attachment->isMultiview();
Martin Radev5c00d0d2017-08-07 10:06:59 +0300597}
598
Martin Radev4e619f52017-08-09 11:50:06 +0300599int FramebufferState::getBaseViewIndex() const
600{
601 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
602 if (attachment == nullptr)
603 {
604 return GL_NONE;
605 }
606 return attachment->getBaseViewIndex();
607}
608
Jamie Madill05b35b22017-10-03 09:01:44 -0400609Box FramebufferState::getDimensions() const
610{
Jonah Ryan-Davis7151fe52019-07-17 15:15:27 -0400611 Extents extents = getExtents();
612 return Box(0, 0, 0, extents.width, extents.height, extents.depth);
613}
614
615Extents FramebufferState::getExtents() const
616{
Jamie Madill05b35b22017-10-03 09:01:44 -0400617 ASSERT(attachmentsHaveSameDimensions());
Tim Van Patten626a7282019-07-08 15:11:59 -0600618 const FramebufferAttachment *first = getFirstNonNullAttachment();
619 if (first)
620 {
621 return first->getSize();
622 }
623 return Extents(getDefaultWidth(), getDefaultHeight(), 0);
Jamie Madill05b35b22017-10-03 09:01:44 -0400624}
625
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600626bool FramebufferState::isDefault() const
627{
628 return mId == Framebuffer::kDefaultDrawFramebufferHandle;
629}
630
Jamie Madill7aea7e02016-05-10 10:39:45 -0400631Framebuffer::Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id)
Jamie Madill2274b652018-05-31 10:56:08 -0400632 : mState(caps, id),
Jamie Madill362876b2016-06-16 14:46:59 -0400633 mImpl(factory->createFramebuffer(mState)),
Jamie Madill362876b2016-06-16 14:46:59 -0400634 mCachedStatus(),
635 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
636 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000637{
Corentin Wallez37c39792015-08-20 14:19:46 -0400638 ASSERT(mImpl != nullptr);
Jamie Madill362876b2016-06-16 14:46:59 -0400639 ASSERT(mState.mColorAttachments.size() == static_cast<size_t>(caps.maxColorAttachments));
640
Jamie Madill1e5499d2017-04-05 11:22:16 -0400641 for (uint32_t colorIndex = 0;
642 colorIndex < static_cast<uint32_t>(mState.mColorAttachments.size()); ++colorIndex)
Jamie Madill362876b2016-06-16 14:46:59 -0400643 {
Jamie Madill1e5499d2017-04-05 11:22:16 -0400644 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
Jamie Madill362876b2016-06-16 14:46:59 -0400645 }
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600646 mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
Corentin Wallez37c39792015-08-20 14:19:46 -0400647}
648
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600649Framebuffer::Framebuffer(const Context *context, egl::Surface *surface, egl::Surface *readSurface)
Jamie Madill362876b2016-06-16 14:46:59 -0400650 : mState(),
Geoff Langbf7b95d2018-05-01 16:48:21 -0400651 mImpl(surface->getImplementation()->createDefaultFramebuffer(context, mState)),
Jamie Madill362876b2016-06-16 14:46:59 -0400652 mCachedStatus(GL_FRAMEBUFFER_COMPLETE),
653 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
654 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
Corentin Wallez37c39792015-08-20 14:19:46 -0400655{
Geoff Langda88add2014-12-01 10:22:01 -0500656 ASSERT(mImpl != nullptr);
Jamie Madill6f60d052017-02-22 15:20:11 -0500657
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600658 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
Geoff Langbf7b95d2018-05-01 16:48:21 -0400659 setAttachmentImpl(context, GL_FRAMEBUFFER_DEFAULT, GL_BACK, ImageIndex(), surface,
Jamie Madillcc129372018-04-12 09:13:18 -0400660 FramebufferAttachment::kDefaultNumViews,
Mingyu Hu7d64c482019-03-12 14:27:40 -0700661 FramebufferAttachment::kDefaultBaseViewIndex, false);
Jamie Madill6f60d052017-02-22 15:20:11 -0500662
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600663 setReadSurface(context, readSurface);
664
Jamie Madill6f60d052017-02-22 15:20:11 -0500665 if (surface->getConfig()->depthSize > 0)
666 {
Geoff Langbf7b95d2018-05-01 16:48:21 -0400667 setAttachmentImpl(context, GL_FRAMEBUFFER_DEFAULT, GL_DEPTH, ImageIndex(), surface,
Jamie Madillcc129372018-04-12 09:13:18 -0400668 FramebufferAttachment::kDefaultNumViews,
Mingyu Hu7d64c482019-03-12 14:27:40 -0700669 FramebufferAttachment::kDefaultBaseViewIndex, false);
Jamie Madill6f60d052017-02-22 15:20:11 -0500670 }
671
672 if (surface->getConfig()->stencilSize > 0)
673 {
Geoff Langbf7b95d2018-05-01 16:48:21 -0400674 setAttachmentImpl(context, GL_FRAMEBUFFER_DEFAULT, GL_STENCIL, ImageIndex(), surface,
Jamie Madillcc129372018-04-12 09:13:18 -0400675 FramebufferAttachment::kDefaultNumViews,
Mingyu Hu7d64c482019-03-12 14:27:40 -0700676 FramebufferAttachment::kDefaultBaseViewIndex, false);
Jamie Madill6f60d052017-02-22 15:20:11 -0500677 }
Jamie Madill6e18a232019-01-16 13:27:14 -0500678 SetComponentTypeMask(getDrawbufferWriteType(0), 0, &mState.mDrawBufferTypeMask);
Geoff Langee244c72019-05-06 10:30:18 -0400679
680 // Ensure the backend has a chance to synchronize its content for a new backbuffer.
681 mDirtyBits.set(DIRTY_BIT_COLOR_BUFFER_CONTENTS_0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000682}
683
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600684Framebuffer::Framebuffer(const Context *context,
685 rx::GLImplFactory *factory,
686 egl::Surface *readSurface)
Corentin Wallezccab69d2017-01-27 16:57:15 -0500687 : mState(),
688 mImpl(factory->createFramebuffer(mState)),
Corentin Wallezccab69d2017-01-27 16:57:15 -0500689 mCachedStatus(GL_FRAMEBUFFER_UNDEFINED_OES),
690 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
691 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
692{
Jamie Madill1e5499d2017-04-05 11:22:16 -0400693 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
Jamie Madill6e18a232019-01-16 13:27:14 -0500694 SetComponentTypeMask(getDrawbufferWriteType(0), 0, &mState.mDrawBufferTypeMask);
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600695
696 setReadSurface(context, readSurface);
Corentin Wallezccab69d2017-01-27 16:57:15 -0500697}
698
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000699Framebuffer::~Framebuffer()
700{
Geoff Langda88add2014-12-01 10:22:01 -0500701 SafeDelete(mImpl);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000702}
703
Jamie Madill4928b7c2017-06-20 12:57:39 -0400704void Framebuffer::onDestroy(const Context *context)
Jamie Madill6c1f6712017-02-14 19:08:04 -0500705{
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600706 if (isDefault())
707 {
708 mState.mDefaultFramebufferReadAttachment.detach(context);
709 mState.mDefaultFramebufferReadAttachmentInitialized = false;
710 }
711
Jamie Madill4928b7c2017-06-20 12:57:39 -0400712 for (auto &attachment : mState.mColorAttachments)
713 {
714 attachment.detach(context);
715 }
716 mState.mDepthAttachment.detach(context);
717 mState.mStencilAttachment.detach(context);
718 mState.mWebGLDepthAttachment.detach(context);
719 mState.mWebGLStencilAttachment.detach(context);
720 mState.mWebGLDepthStencilAttachment.detach(context);
721
Jamie Madillc564c072017-06-01 12:45:42 -0400722 mImpl->destroy(context);
Jamie Madill6c1f6712017-02-14 19:08:04 -0500723}
724
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600725void Framebuffer::setReadSurface(const Context *context, egl::Surface *readSurface)
726{
727 // updateAttachment() without mState.mResourceNeedsInit.set()
728 mState.mDefaultFramebufferReadAttachment.attach(
729 context, GL_FRAMEBUFFER_DEFAULT, GL_BACK, ImageIndex(), readSurface,
730 FramebufferAttachment::kDefaultNumViews, FramebufferAttachment::kDefaultBaseViewIndex,
731 false);
732 mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
733}
734
Jamie Madille90d4ee2018-11-28 14:04:00 -0500735void Framebuffer::setLabel(const Context *context, const std::string &label)
Geoff Lang70d0f492015-12-10 17:45:46 -0500736{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400737 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -0500738}
739
740const std::string &Framebuffer::getLabel() const
741{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400742 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -0500743}
744
Jamie Madill2ab08ed2019-08-12 16:20:21 -0400745bool Framebuffer::detachTexture(const Context *context, TextureID textureId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000746{
Jamie Madill2ab08ed2019-08-12 16:20:21 -0400747 return detachResourceById(context, GL_TEXTURE, textureId.value);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000748}
749
Jamie Madill7c7dec02019-08-06 17:44:11 -0400750bool Framebuffer::detachRenderbuffer(const Context *context, RenderbufferID renderbufferId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000751{
Jamie Madill7c7dec02019-08-06 17:44:11 -0400752 return detachResourceById(context, GL_RENDERBUFFER, renderbufferId.value);
Jamie Madilld1405e52015-03-05 15:41:39 -0500753}
Jamie Madille261b442014-06-25 12:42:21 -0400754
Jamie Madill8693bdb2017-09-02 15:32:14 -0400755bool Framebuffer::detachResourceById(const Context *context, GLenum resourceType, GLuint resourceId)
Jamie Madilld1405e52015-03-05 15:41:39 -0500756{
Jamie Madill8693bdb2017-09-02 15:32:14 -0400757 bool found = false;
758
Jamie Madill362876b2016-06-16 14:46:59 -0400759 for (size_t colorIndex = 0; colorIndex < mState.mColorAttachments.size(); ++colorIndex)
Jamie Madilld1405e52015-03-05 15:41:39 -0500760 {
Jamie Madill8693bdb2017-09-02 15:32:14 -0400761 if (detachMatchingAttachment(context, &mState.mColorAttachments[colorIndex], resourceType,
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300762 resourceId))
Jamie Madill8693bdb2017-09-02 15:32:14 -0400763 {
764 found = true;
765 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000766 }
767
Jamie Madilla02315b2017-02-23 14:14:47 -0500768 if (context->isWebGL1())
769 {
770 const std::array<FramebufferAttachment *, 3> attachments = {
771 {&mState.mWebGLDepthStencilAttachment, &mState.mWebGLDepthAttachment,
772 &mState.mWebGLStencilAttachment}};
773 for (FramebufferAttachment *attachment : attachments)
774 {
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300775 if (detachMatchingAttachment(context, attachment, resourceType, resourceId))
Jamie Madilla02315b2017-02-23 14:14:47 -0500776 {
Jamie Madill8693bdb2017-09-02 15:32:14 -0400777 found = true;
Jamie Madilla02315b2017-02-23 14:14:47 -0500778 }
779 }
780 }
781 else
782 {
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300783 if (detachMatchingAttachment(context, &mState.mDepthAttachment, resourceType, resourceId))
Jamie Madill8693bdb2017-09-02 15:32:14 -0400784 {
785 found = true;
786 }
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300787 if (detachMatchingAttachment(context, &mState.mStencilAttachment, resourceType, resourceId))
Jamie Madill8693bdb2017-09-02 15:32:14 -0400788 {
789 found = true;
790 }
Jamie Madilla02315b2017-02-23 14:14:47 -0500791 }
Jamie Madill8693bdb2017-09-02 15:32:14 -0400792
793 return found;
Jamie Madill362876b2016-06-16 14:46:59 -0400794}
795
Jamie Madill8693bdb2017-09-02 15:32:14 -0400796bool Framebuffer::detachMatchingAttachment(const Context *context,
Jamie Madill4928b7c2017-06-20 12:57:39 -0400797 FramebufferAttachment *attachment,
Jamie Madill362876b2016-06-16 14:46:59 -0400798 GLenum matchType,
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300799 GLuint matchId)
Jamie Madill362876b2016-06-16 14:46:59 -0400800{
801 if (attachment->isAttached() && attachment->type() == matchType && attachment->id() == matchId)
802 {
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300803 // We go through resetAttachment to make sure that all the required bookkeeping will be done
804 // such as updating enabled draw buffer state.
805 resetAttachment(context, attachment->getBinding());
Jamie Madill8693bdb2017-09-02 15:32:14 -0400806 return true;
Jamie Madill362876b2016-06-16 14:46:59 -0400807 }
Jamie Madill8693bdb2017-09-02 15:32:14 -0400808
809 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000810}
811
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400812const FramebufferAttachment *Framebuffer::getColorAttachment(size_t colorAttachment) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000813{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400814 return mState.getColorAttachment(colorAttachment);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000815}
816
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400817const FramebufferAttachment *Framebuffer::getDepthAttachment() const
Geoff Lang646559f2013-08-15 11:08:15 -0400818{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400819 return mState.getDepthAttachment();
Geoff Lang646559f2013-08-15 11:08:15 -0400820}
821
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400822const FramebufferAttachment *Framebuffer::getStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400823{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400824 return mState.getStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400825}
826
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400827const FramebufferAttachment *Framebuffer::getDepthStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400828{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400829 return mState.getDepthStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400830}
831
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400832const FramebufferAttachment *Framebuffer::getDepthOrStencilAttachment() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000833{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400834 return mState.getDepthOrStencilAttachment();
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000835}
836
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500837const FramebufferAttachment *Framebuffer::getStencilOrDepthStencilAttachment() const
838{
839 return mState.getStencilOrDepthStencilAttachment();
840}
841
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400842const FramebufferAttachment *Framebuffer::getReadColorAttachment() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000843{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400844 return mState.getReadAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000845}
846
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400847GLenum Framebuffer::getReadColorAttachmentType() const
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000848{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400849 const FramebufferAttachment *readAttachment = mState.getReadAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400850 return (readAttachment != nullptr ? readAttachment->type() : GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000851}
852
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400853const FramebufferAttachment *Framebuffer::getFirstColorAttachment() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000854{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400855 return mState.getFirstColorAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000856}
857
Jamie Madill6dd06ea2017-07-19 13:47:55 -0400858const FramebufferAttachment *Framebuffer::getFirstNonNullAttachment() const
859{
860 return mState.getFirstNonNullAttachment();
861}
862
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800863const FramebufferAttachment *Framebuffer::getAttachment(const Context *context,
864 GLenum attachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000865{
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800866 return mState.getAttachment(context, attachment);
Geoff Lang55ba29c2013-07-11 16:57:53 -0400867}
868
Geoff Langa15472a2015-08-11 11:48:03 -0400869size_t Framebuffer::getDrawbufferStateCount() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000870{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400871 return mState.mDrawBufferStates.size();
Geoff Langa15472a2015-08-11 11:48:03 -0400872}
873
874GLenum Framebuffer::getDrawBufferState(size_t drawBuffer) const
875{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400876 ASSERT(drawBuffer < mState.mDrawBufferStates.size());
877 return mState.mDrawBufferStates[drawBuffer];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000878}
879
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500880const std::vector<GLenum> &Framebuffer::getDrawBufferStates() const
881{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400882 return mState.getDrawBufferStates();
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500883}
884
Geoff Lang164d54e2014-12-01 10:55:33 -0500885void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000886{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400887 auto &drawStates = mState.mDrawBufferStates;
Jamie Madilld1405e52015-03-05 15:41:39 -0500888
889 ASSERT(count <= drawStates.size());
890 std::copy(buffers, buffers + count, drawStates.begin());
891 std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500892 mDirtyBits.set(DIRTY_BIT_DRAW_BUFFERS);
Jamie Madilla4595b82017-01-11 17:36:34 -0500893
894 mState.mEnabledDrawBuffers.reset();
Brandon Jones76746f92017-11-22 11:44:41 -0800895 mState.mDrawBufferTypeMask.reset();
896
Jamie Madilla4595b82017-01-11 17:36:34 -0500897 for (size_t index = 0; index < count; ++index)
898 {
Jamie Madill6e18a232019-01-16 13:27:14 -0500899 SetComponentTypeMask(getDrawbufferWriteType(index), index, &mState.mDrawBufferTypeMask);
Brandon Jones76746f92017-11-22 11:44:41 -0800900
Jamie Madilla4595b82017-01-11 17:36:34 -0500901 if (drawStates[index] != GL_NONE && mState.mColorAttachments[index].isAttached())
902 {
903 mState.mEnabledDrawBuffers.set(index);
904 }
905 }
Geoff Lang9dd95802014-12-01 11:12:59 -0500906}
907
Geoff Langa15472a2015-08-11 11:48:03 -0400908const FramebufferAttachment *Framebuffer::getDrawBuffer(size_t drawBuffer) const
909{
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400910 return mState.getDrawBuffer(drawBuffer);
Geoff Langa15472a2015-08-11 11:48:03 -0400911}
912
Jamie Madill6e18a232019-01-16 13:27:14 -0500913ComponentType Framebuffer::getDrawbufferWriteType(size_t drawBuffer) const
Geoff Lange0cff192017-05-30 13:04:56 -0400914{
915 const FramebufferAttachment *attachment = mState.getDrawBuffer(drawBuffer);
916 if (attachment == nullptr)
917 {
Jamie Madill6e18a232019-01-16 13:27:14 -0500918 return ComponentType::NoType;
Geoff Lange0cff192017-05-30 13:04:56 -0400919 }
920
921 GLenum componentType = attachment->getFormat().info->componentType;
922 switch (componentType)
923 {
924 case GL_INT:
Jamie Madill6e18a232019-01-16 13:27:14 -0500925 return ComponentType::Int;
Geoff Lange0cff192017-05-30 13:04:56 -0400926 case GL_UNSIGNED_INT:
Jamie Madill6e18a232019-01-16 13:27:14 -0500927 return ComponentType::UnsignedInt;
Geoff Lange0cff192017-05-30 13:04:56 -0400928
929 default:
Jamie Madill6e18a232019-01-16 13:27:14 -0500930 return ComponentType::Float;
Geoff Lange0cff192017-05-30 13:04:56 -0400931 }
932}
933
Brandon Jonesc405ae72017-12-06 14:15:03 -0800934ComponentTypeMask Framebuffer::getDrawBufferTypeMask() const
Brandon Jones76746f92017-11-22 11:44:41 -0800935{
936 return mState.mDrawBufferTypeMask;
937}
938
939DrawBufferMask Framebuffer::getDrawBufferMask() const
940{
941 return mState.mEnabledDrawBuffers;
942}
943
Geoff Langa15472a2015-08-11 11:48:03 -0400944bool Framebuffer::hasEnabledDrawBuffer() const
945{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400946 for (size_t drawbufferIdx = 0; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
Geoff Langa15472a2015-08-11 11:48:03 -0400947 {
948 if (getDrawBuffer(drawbufferIdx) != nullptr)
949 {
950 return true;
951 }
952 }
953
954 return false;
955}
956
Geoff Lang9dd95802014-12-01 11:12:59 -0500957GLenum Framebuffer::getReadBufferState() const
958{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400959 return mState.mReadBufferState;
Geoff Lang9dd95802014-12-01 11:12:59 -0500960}
961
962void Framebuffer::setReadBuffer(GLenum buffer)
963{
Jamie Madillb885e572015-02-03 16:16:04 -0500964 ASSERT(buffer == GL_BACK || buffer == GL_NONE ||
965 (buffer >= GL_COLOR_ATTACHMENT0 &&
Jamie Madill48ef11b2016-04-27 15:21:52 -0400966 (buffer - GL_COLOR_ATTACHMENT0) < mState.mColorAttachments.size()));
967 mState.mReadBufferState = buffer;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500968 mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000969}
970
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400971size_t Framebuffer::getNumColorAttachments() const
Corentin Wallez37c39792015-08-20 14:19:46 -0400972{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400973 return mState.mColorAttachments.size();
Corentin Wallez37c39792015-08-20 14:19:46 -0400974}
975
Jamie Madill0df8fe42015-11-24 16:10:24 -0500976bool Framebuffer::hasDepth() const
977{
Jamie Madill9c335862017-07-18 11:51:38 -0400978 return mState.hasDepth();
Jamie Madill0df8fe42015-11-24 16:10:24 -0500979}
980
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000981bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000982{
Jamie Madill9c335862017-07-18 11:51:38 -0400983 return mState.hasStencil();
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000984}
985
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000986bool Framebuffer::usingExtendedDrawBuffers() const
987{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400988 for (size_t drawbufferIdx = 1; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000989 {
Geoff Langa15472a2015-08-11 11:48:03 -0400990 if (getDrawBuffer(drawbufferIdx) != nullptr)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000991 {
992 return true;
993 }
994 }
995
996 return false;
997}
998
Jamie Madill124f78c2019-06-18 11:48:24 -0400999void Framebuffer::invalidateCompletenessCache()
Geoff Lang9aded172017-04-05 11:07:56 -04001000{
Tim Van Patten56ba54c2019-08-08 13:03:34 -06001001 if (!isDefault())
Geoff Lang9aded172017-04-05 11:07:56 -04001002 {
1003 mCachedStatus.reset();
1004 }
Jamie Madill124f78c2019-06-18 11:48:24 -04001005 onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
Geoff Lang9aded172017-04-05 11:07:56 -04001006}
1007
Jamie Madillcc73f242018-08-01 11:34:48 -04001008GLenum Framebuffer::checkStatusImpl(const Context *context)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001009{
Jamie Madillcc73f242018-08-01 11:34:48 -04001010 ASSERT(!isDefault());
1011 ASSERT(hasAnyDirtyBit() || !mCachedStatus.valid());
Geoff Lang528ce3c2014-12-01 10:44:07 -05001012
Jamie Madillcc73f242018-08-01 11:34:48 -04001013 mCachedStatus = checkStatusWithGLFrontEnd(context);
Jamie Madille98b1b52018-03-08 09:47:23 -05001014
Jamie Madillcc73f242018-08-01 11:34:48 -04001015 if (mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE)
1016 {
Jamie Madill67220092019-05-20 11:12:53 -04001017 // We can skip syncState on several back-ends.
1018 if (mImpl->shouldSyncStateBeforeCheckStatus())
Jamie Madille98b1b52018-03-08 09:47:23 -05001019 {
Jamie Madill67220092019-05-20 11:12:53 -04001020 angle::Result err = syncState(context);
1021 if (err != angle::Result::Continue)
1022 {
1023 return 0;
1024 }
Jamie Madillcc73f242018-08-01 11:34:48 -04001025 }
Jamie Madill67220092019-05-20 11:12:53 -04001026
Jamie Madillcc73f242018-08-01 11:34:48 -04001027 if (!mImpl->checkStatus(context))
1028 {
1029 mCachedStatus = GL_FRAMEBUFFER_UNSUPPORTED;
Jamie Madille98b1b52018-03-08 09:47:23 -05001030 }
Jamie Madill362876b2016-06-16 14:46:59 -04001031 }
1032
Jamie Madill427064d2018-04-13 16:20:34 -04001033 return mCachedStatus.value();
Jamie Madill362876b2016-06-16 14:46:59 -04001034}
1035
Jamie Madille98b1b52018-03-08 09:47:23 -05001036GLenum Framebuffer::checkStatusWithGLFrontEnd(const Context *context)
Jamie Madill362876b2016-06-16 14:46:59 -04001037{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001038 const State &state = context->getState();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001039
Tim Van Patten56ba54c2019-08-08 13:03:34 -06001040 ASSERT(!isDefault());
Jamie Madill362876b2016-06-16 14:46:59 -04001041
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001042 bool hasAttachments = false;
1043 Optional<unsigned int> colorbufferSize;
1044 Optional<int> samples;
Geoff Lang92019432017-11-20 13:09:34 -05001045 Optional<bool> fixedSampleLocations;
JiangYizhou461d9a32017-01-04 16:37:26 +08001046 bool hasRenderbuffer = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001047
Martin Radev9bc9a322017-07-21 14:28:17 +03001048 const FramebufferAttachment *firstAttachment = getFirstNonNullAttachment();
1049
Jiawei Shaoa8802472018-05-28 11:17:47 +08001050 Optional<bool> isLayered;
1051 Optional<TextureType> colorAttachmentsTextureType;
1052
Jamie Madill48ef11b2016-04-27 15:21:52 -04001053 for (const FramebufferAttachment &colorAttachment : mState.mColorAttachments)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001054 {
Jamie Madill2d06b732015-04-20 12:53:28 -04001055 if (colorAttachment.isAttached())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001056 {
Geoff Lang9f10b772017-05-16 15:51:03 -04001057 if (!CheckAttachmentCompleteness(context, colorAttachment))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001058 {
1059 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1060 }
daniel@transgaming.com01868132010-08-24 19:21:17 +00001061
Geoff Lang677bb6f2017-04-05 12:40:40 -04001062 const InternalFormat &format = *colorAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -04001063 if (format.depthBits > 0 || format.stencilBits > 0)
1064 {
1065 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1066 }
1067
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001068 if (!CheckAttachmentSampleCompleteness(context, colorAttachment, true, &samples,
1069 &fixedSampleLocations))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001070 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001071 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001072 }
1073
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001074 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
1075 // in GLES 3.0, there is no such restriction
1076 if (state.getClientMajorVersion() < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001077 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001078 if (colorbufferSize.valid())
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001079 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001080 if (format.pixelBytes != colorbufferSize.value())
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +00001081 {
1082 return GL_FRAMEBUFFER_UNSUPPORTED;
1083 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001084 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001085 else
1086 {
1087 colorbufferSize = format.pixelBytes;
1088 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001089 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001090
Martin Radev9bc9a322017-07-21 14:28:17 +03001091 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &colorAttachment))
1092 {
Mingyu Hu7d64c482019-03-12 14:27:40 -07001093 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR;
Martin Radev9bc9a322017-07-21 14:28:17 +03001094 }
1095
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001096 hasRenderbuffer = hasRenderbuffer || (colorAttachment.type() == GL_RENDERBUFFER);
Jiawei Shaoa8802472018-05-28 11:17:47 +08001097
1098 if (!hasAttachments)
1099 {
1100 isLayered = colorAttachment.isLayered();
1101 if (isLayered.value())
1102 {
1103 colorAttachmentsTextureType = colorAttachment.getTextureImageIndex().getType();
1104 }
1105 hasAttachments = true;
1106 }
1107 else
1108 {
1109 // [EXT_geometry_shader] section 9.4.1, "Framebuffer Completeness"
1110 // If any framebuffer attachment is layered, all populated attachments
1111 // must be layered. Additionally, all populated color attachments must
1112 // be from textures of the same target. {FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT }
1113 ASSERT(isLayered.valid());
1114 if (isLayered.value() != colorAttachment.isLayered())
1115 {
1116 return GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT;
1117 }
1118 else if (isLayered.value())
1119 {
1120 ASSERT(colorAttachmentsTextureType.valid());
1121 if (colorAttachmentsTextureType.value() !=
1122 colorAttachment.getTextureImageIndex().getType())
1123 {
1124 return GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT;
1125 }
1126 }
1127 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001128 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001129 }
1130
Jamie Madill48ef11b2016-04-27 15:21:52 -04001131 const FramebufferAttachment &depthAttachment = mState.mDepthAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -04001132 if (depthAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001133 {
Geoff Lang9f10b772017-05-16 15:51:03 -04001134 if (!CheckAttachmentCompleteness(context, depthAttachment))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001135 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001136 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001137 }
1138
Geoff Lang677bb6f2017-04-05 12:40:40 -04001139 const InternalFormat &format = *depthAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -04001140 if (format.depthBits == 0)
1141 {
1142 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001143 }
1144
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001145 if (!CheckAttachmentSampleCompleteness(context, depthAttachment, false, &samples,
1146 &fixedSampleLocations))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001147 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001148 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001149 }
Sami Väisänena797e062016-05-12 15:23:40 +03001150
Martin Radev9bc9a322017-07-21 14:28:17 +03001151 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &depthAttachment))
1152 {
Mingyu Hu7d64c482019-03-12 14:27:40 -07001153 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR;
Martin Radev9bc9a322017-07-21 14:28:17 +03001154 }
1155
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001156 hasRenderbuffer = hasRenderbuffer || (depthAttachment.type() == GL_RENDERBUFFER);
Jiawei Shaoa8802472018-05-28 11:17:47 +08001157
1158 if (!hasAttachments)
1159 {
1160 isLayered = depthAttachment.isLayered();
1161 hasAttachments = true;
1162 }
1163 else
1164 {
1165 // [EXT_geometry_shader] section 9.4.1, "Framebuffer Completeness"
1166 // If any framebuffer attachment is layered, all populated attachments
1167 // must be layered. {FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT }
1168 ASSERT(isLayered.valid());
1169 if (isLayered.value() != depthAttachment.isLayered())
1170 {
1171 return GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT;
1172 }
1173 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001174 }
1175
Jamie Madill48ef11b2016-04-27 15:21:52 -04001176 const FramebufferAttachment &stencilAttachment = mState.mStencilAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -04001177 if (stencilAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001178 {
Geoff Lang9f10b772017-05-16 15:51:03 -04001179 if (!CheckAttachmentCompleteness(context, stencilAttachment))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001180 {
1181 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1182 }
1183
Geoff Lang677bb6f2017-04-05 12:40:40 -04001184 const InternalFormat &format = *stencilAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -04001185 if (format.stencilBits == 0)
1186 {
1187 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001188 }
1189
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001190 if (!CheckAttachmentSampleCompleteness(context, stencilAttachment, false, &samples,
1191 &fixedSampleLocations))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001192 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001193 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001194 }
Corentin Wallez086d59a2016-04-29 09:06:49 -04001195
Martin Radev9bc9a322017-07-21 14:28:17 +03001196 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &stencilAttachment))
1197 {
Mingyu Hu7d64c482019-03-12 14:27:40 -07001198 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR;
Martin Radev9bc9a322017-07-21 14:28:17 +03001199 }
1200
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001201 hasRenderbuffer = hasRenderbuffer || (stencilAttachment.type() == GL_RENDERBUFFER);
Jiawei Shaoa8802472018-05-28 11:17:47 +08001202
1203 if (!hasAttachments)
1204 {
1205 hasAttachments = true;
1206 }
1207 else
1208 {
1209 // [EXT_geometry_shader] section 9.4.1, "Framebuffer Completeness"
1210 // If any framebuffer attachment is layered, all populated attachments
1211 // must be layered.
1212 // {FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT }
1213 ASSERT(isLayered.valid());
1214 if (isLayered.value() != stencilAttachment.isLayered())
1215 {
1216 return GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT;
1217 }
1218 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001219 }
1220
1221 // Starting from ES 3.0 stencil and depth, if present, should be the same image
1222 if (state.getClientMajorVersion() >= 3 && depthAttachment.isAttached() &&
1223 stencilAttachment.isAttached() && stencilAttachment != depthAttachment)
1224 {
1225 return GL_FRAMEBUFFER_UNSUPPORTED;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001226 }
1227
Jamie Madilla02315b2017-02-23 14:14:47 -05001228 // Special additional validation for WebGL 1 DEPTH/STENCIL/DEPTH_STENCIL.
1229 if (state.isWebGL1())
1230 {
1231 if (!mState.mWebGLDepthStencilConsistent)
1232 {
1233 return GL_FRAMEBUFFER_UNSUPPORTED;
1234 }
1235
1236 if (mState.mWebGLDepthStencilAttachment.isAttached())
1237 {
1238 if (mState.mWebGLDepthStencilAttachment.getDepthSize() == 0 ||
1239 mState.mWebGLDepthStencilAttachment.getStencilSize() == 0)
1240 {
1241 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1242 }
Martin Radev9bc9a322017-07-21 14:28:17 +03001243
1244 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment,
1245 &mState.mWebGLDepthStencilAttachment))
1246 {
Mingyu Hu7d64c482019-03-12 14:27:40 -07001247 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR;
Martin Radev9bc9a322017-07-21 14:28:17 +03001248 }
Jamie Madilla02315b2017-02-23 14:14:47 -05001249 }
1250 else if (mState.mStencilAttachment.isAttached() &&
1251 mState.mStencilAttachment.getDepthSize() > 0)
1252 {
1253 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1254 }
1255 else if (mState.mDepthAttachment.isAttached() &&
1256 mState.mDepthAttachment.getStencilSize() > 0)
1257 {
1258 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1259 }
1260 }
1261
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001262 // ES3.1(section 9.4) requires that if no image is attached to the framebuffer, and either the
1263 // value of the framebuffer's FRAMEBUFFER_DEFAULT_WIDTH or FRAMEBUFFER_DEFAULT_HEIGHT parameters
1264 // is zero, the framebuffer is considered incomplete.
JiangYizhou461d9a32017-01-04 16:37:26 +08001265 GLint defaultWidth = mState.getDefaultWidth();
1266 GLint defaultHeight = mState.getDefaultHeight();
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001267 if (!hasAttachments && (defaultWidth == 0 || defaultHeight == 0))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001268 {
1269 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001270 }
1271
Geoff Langa0e0aeb2017-04-12 15:06:29 -04001272 // In ES 2.0 and WebGL, all color attachments must have the same width and height.
Jamie Madillcc86d642015-11-24 13:00:07 -05001273 // In ES 3.0, there is no such restriction.
Geoff Langa0e0aeb2017-04-12 15:06:29 -04001274 if ((state.getClientMajorVersion() < 3 || state.getExtensions().webglCompatibility) &&
1275 !mState.attachmentsHaveSameDimensions())
Jamie Madillcc86d642015-11-24 13:00:07 -05001276 {
1277 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
1278 }
1279
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001280 // ES3.1(section 9.4) requires that if the attached images are a mix of renderbuffers and
1281 // textures, the value of TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all attached textures.
JiangYizhou461d9a32017-01-04 16:37:26 +08001282 if (fixedSampleLocations.valid() && hasRenderbuffer && !fixedSampleLocations.value())
1283 {
1284 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1285 }
1286
Kenneth Russellce8602a2017-10-03 18:23:08 -07001287 // The WebGL conformance tests implicitly define that all framebuffer
1288 // attachments must be unique. For example, the same level of a texture can
1289 // not be attached to two different color attachments.
1290 if (state.getExtensions().webglCompatibility)
1291 {
1292 if (!mState.colorAttachmentsAreUniqueImages())
1293 {
1294 return GL_FRAMEBUFFER_UNSUPPORTED;
1295 }
1296 }
1297
Jamie Madillcc86d642015-11-24 13:00:07 -05001298 return GL_FRAMEBUFFER_COMPLETE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001299}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001300
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001301angle::Result Framebuffer::discard(const Context *context, size_t count, const GLenum *attachments)
Austin Kinross08332632015-05-05 13:35:47 -07001302{
Jamie Madill05b35b22017-10-03 09:01:44 -04001303 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1304 // can be no-ops, so we should probably do that to ensure consistency.
1305 // TODO(jmadill): WebGL behaviour, and robust resource init behaviour without WebGL.
1306
Jamie Madill4928b7c2017-06-20 12:57:39 -04001307 return mImpl->discard(context, count, attachments);
Austin Kinross08332632015-05-05 13:35:47 -07001308}
1309
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001310angle::Result Framebuffer::invalidate(const Context *context,
1311 size_t count,
1312 const GLenum *attachments)
Jamie Madill2d96b9e2014-08-29 15:46:47 -04001313{
Jamie Madill05b35b22017-10-03 09:01:44 -04001314 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1315 // can be no-ops, so we should probably do that to ensure consistency.
1316 // TODO(jmadill): WebGL behaviour, and robust resource init behaviour without WebGL.
1317
Jamie Madill4928b7c2017-06-20 12:57:39 -04001318 return mImpl->invalidate(context, count, attachments);
Jamie Madill2d96b9e2014-08-29 15:46:47 -04001319}
1320
Jamie Madill05b35b22017-10-03 09:01:44 -04001321bool Framebuffer::partialClearNeedsInit(const Context *context,
1322 bool color,
1323 bool depth,
1324 bool stencil)
1325{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001326 const auto &glState = context->getState();
Jamie Madill05b35b22017-10-03 09:01:44 -04001327
1328 if (!glState.isRobustResourceInitEnabled())
1329 {
1330 return false;
1331 }
1332
1333 // Scissors can affect clearing.
1334 // TODO(jmadill): Check for complete scissor overlap.
1335 if (glState.isScissorTestEnabled())
1336 {
1337 return true;
1338 }
1339
1340 // If colors masked, we must clear before we clear. Do a simple check.
1341 // TODO(jmadill): Filter out unused color channels from the test.
1342 if (color)
1343 {
1344 const auto &blend = glState.getBlendState();
1345 if (!(blend.colorMaskRed && blend.colorMaskGreen && blend.colorMaskBlue &&
1346 blend.colorMaskAlpha))
1347 {
1348 return true;
1349 }
1350 }
1351
1352 const auto &depthStencil = glState.getDepthStencilState();
Yuly Novikov21edf3d2018-07-23 16:44:16 -04001353 if (stencil && (depthStencil.stencilMask != depthStencil.stencilWritemask ||
1354 depthStencil.stencilBackMask != depthStencil.stencilBackWritemask))
Jamie Madill05b35b22017-10-03 09:01:44 -04001355 {
1356 return true;
1357 }
1358
1359 return false;
1360}
1361
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001362angle::Result Framebuffer::invalidateSub(const Context *context,
1363 size_t count,
1364 const GLenum *attachments,
1365 const Rectangle &area)
Jamie Madill400a4412014-08-29 15:46:45 -04001366{
Jamie Madill05b35b22017-10-03 09:01:44 -04001367 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1368 // can be no-ops, so we should probably do that to ensure consistency.
1369 // TODO(jmadill): Make a invalidate no-op in WebGL 2.0.
1370
Jamie Madill4928b7c2017-06-20 12:57:39 -04001371 return mImpl->invalidateSub(context, count, attachments, area);
Jamie Madill400a4412014-08-29 15:46:45 -04001372}
1373
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001374angle::Result Framebuffer::clear(const Context *context, GLbitfield mask)
Geoff Langb04dc822014-12-01 12:02:02 -05001375{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001376 const auto &glState = context->getState();
Jamie Madill05b35b22017-10-03 09:01:44 -04001377 if (glState.isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -05001378 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001379 return angle::Result::Continue;
Jamie Madill984ef412015-11-24 16:10:21 -05001380 }
1381
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -04001382 // Remove clear bits that are ineffective. An effective clear changes at least one fragment. If
1383 // color/depth/stencil masks make the clear ineffective we skip it altogether.
1384
1385 // If all color channels are masked, don't attempt to clear color.
1386 if (context->getState().getBlendState().allChannelsMasked())
1387 {
1388 mask &= ~GL_COLOR_BUFFER_BIT;
1389 }
1390
1391 // If depth write is disabled, don't attempt to clear depth.
1392 if (!context->getState().getDepthStencilState().depthMask)
1393 {
1394 mask &= ~GL_DEPTH_BUFFER_BIT;
1395 }
1396
1397 // If all stencil bits are masked, don't attempt to clear stencil.
1398 if (context->getState().getDepthStencilState().stencilWritemask == 0)
1399 {
1400 mask &= ~GL_STENCIL_BUFFER_BIT;
1401 }
1402
1403 if (mask != 0)
1404 {
1405 ANGLE_TRY(mImpl->clear(context, mask));
1406 }
Jamie Madill05b35b22017-10-03 09:01:44 -04001407
Jamie Madill7c985f52018-11-29 18:16:17 -05001408 return angle::Result::Continue;
Geoff Langb04dc822014-12-01 12:02:02 -05001409}
1410
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001411angle::Result Framebuffer::clearBufferfv(const Context *context,
1412 GLenum buffer,
1413 GLint drawbuffer,
1414 const GLfloat *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001415{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001416 if (context->getState().isRasterizerDiscardEnabled() || IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001417 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001418 return angle::Result::Continue;
Jamie Madill984ef412015-11-24 16:10:21 -05001419 }
1420
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -04001421 if (buffer == GL_DEPTH)
1422 {
1423 // If depth write is disabled, don't attempt to clear depth.
1424 if (!context->getState().getDepthStencilState().depthMask)
1425 {
1426 return angle::Result::Continue;
1427 }
1428 }
1429 else
1430 {
1431 // If all color channels are masked, don't attempt to clear color.
1432 if (context->getState().getBlendState().allChannelsMasked())
1433 {
1434 return angle::Result::Continue;
1435 }
1436 }
1437
Jamie Madill05b35b22017-10-03 09:01:44 -04001438 ANGLE_TRY(mImpl->clearBufferfv(context, buffer, drawbuffer, values));
1439
Jamie Madill7c985f52018-11-29 18:16:17 -05001440 return angle::Result::Continue;
Geoff Langb04dc822014-12-01 12:02:02 -05001441}
1442
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001443angle::Result Framebuffer::clearBufferuiv(const Context *context,
1444 GLenum buffer,
1445 GLint drawbuffer,
1446 const GLuint *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001447{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001448 if (context->getState().isRasterizerDiscardEnabled() || IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001449 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001450 return angle::Result::Continue;
Jamie Madill984ef412015-11-24 16:10:21 -05001451 }
1452
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -04001453 // If all color channels are masked, don't attempt to clear color.
1454 if (context->getState().getBlendState().allChannelsMasked())
1455 {
1456 return angle::Result::Continue;
1457 }
1458
Jamie Madill05b35b22017-10-03 09:01:44 -04001459 ANGLE_TRY(mImpl->clearBufferuiv(context, buffer, drawbuffer, values));
1460
Jamie Madill7c985f52018-11-29 18:16:17 -05001461 return angle::Result::Continue;
Geoff Langb04dc822014-12-01 12:02:02 -05001462}
1463
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001464angle::Result Framebuffer::clearBufferiv(const Context *context,
1465 GLenum buffer,
1466 GLint drawbuffer,
1467 const GLint *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001468{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001469 if (context->getState().isRasterizerDiscardEnabled() || IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001470 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001471 return angle::Result::Continue;
Jamie Madill984ef412015-11-24 16:10:21 -05001472 }
1473
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -04001474 if (buffer == GL_STENCIL)
1475 {
1476 // If all stencil bits are masked, don't attempt to clear stencil.
1477 if (context->getState().getDepthStencilState().stencilWritemask == 0)
1478 {
1479 return angle::Result::Continue;
1480 }
1481 }
1482 else
1483 {
1484 // If all color channels are masked, don't attempt to clear color.
1485 if (context->getState().getBlendState().allChannelsMasked())
1486 {
1487 return angle::Result::Continue;
1488 }
1489 }
1490
Jamie Madill05b35b22017-10-03 09:01:44 -04001491 ANGLE_TRY(mImpl->clearBufferiv(context, buffer, drawbuffer, values));
1492
Jamie Madill7c985f52018-11-29 18:16:17 -05001493 return angle::Result::Continue;
Geoff Langb04dc822014-12-01 12:02:02 -05001494}
1495
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001496angle::Result Framebuffer::clearBufferfi(const Context *context,
1497 GLenum buffer,
1498 GLint drawbuffer,
1499 GLfloat depth,
1500 GLint stencil)
Geoff Langb04dc822014-12-01 12:02:02 -05001501{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001502 if (context->getState().isRasterizerDiscardEnabled() || IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001503 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001504 return angle::Result::Continue;
Jamie Madill984ef412015-11-24 16:10:21 -05001505 }
1506
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -04001507 bool clearDepth = context->getState().getDepthStencilState().depthMask;
1508 bool clearStencil = context->getState().getDepthStencilState().stencilWritemask != 0;
1509
1510 if (clearDepth && clearStencil)
1511 {
1512 ASSERT(buffer == GL_DEPTH_STENCIL);
1513 ANGLE_TRY(mImpl->clearBufferfi(context, GL_DEPTH_STENCIL, drawbuffer, depth, stencil));
1514 }
1515 else if (clearDepth && !clearStencil)
1516 {
1517 ANGLE_TRY(mImpl->clearBufferfv(context, GL_DEPTH, drawbuffer, &depth));
1518 }
1519 else if (!clearDepth && clearStencil)
1520 {
1521 ANGLE_TRY(mImpl->clearBufferiv(context, GL_STENCIL, drawbuffer, &stencil));
1522 }
Jamie Madill05b35b22017-10-03 09:01:44 -04001523
Jamie Madill7c985f52018-11-29 18:16:17 -05001524 return angle::Result::Continue;
Geoff Langb04dc822014-12-01 12:02:02 -05001525}
1526
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001527angle::Result Framebuffer::getImplementationColorReadFormat(const Context *context,
1528 GLenum *formatOut)
Geoff Langbce529e2014-12-01 12:48:41 -05001529{
Jamie Madill690c8eb2018-03-12 15:20:03 -04001530 ANGLE_TRY(syncState(context));
1531 *formatOut = mImpl->getImplementationColorReadFormat(context);
Jamie Madill7c985f52018-11-29 18:16:17 -05001532 return angle::Result::Continue;
Geoff Langbce529e2014-12-01 12:48:41 -05001533}
1534
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001535angle::Result Framebuffer::getImplementationColorReadType(const Context *context, GLenum *typeOut)
Geoff Langbce529e2014-12-01 12:48:41 -05001536{
Jamie Madill690c8eb2018-03-12 15:20:03 -04001537 ANGLE_TRY(syncState(context));
1538 *typeOut = mImpl->getImplementationColorReadType(context);
Jamie Madill7c985f52018-11-29 18:16:17 -05001539 return angle::Result::Continue;
Geoff Langbce529e2014-12-01 12:48:41 -05001540}
1541
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001542angle::Result Framebuffer::readPixels(const Context *context,
1543 const Rectangle &area,
1544 GLenum format,
1545 GLenum type,
1546 void *pixels)
Geoff Langbce529e2014-12-01 12:48:41 -05001547{
Jamie Madill362876b2016-06-16 14:46:59 -04001548 ANGLE_TRY(mImpl->readPixels(context, area, format, type, pixels));
Geoff Lang520c4ae2015-05-05 13:12:36 -04001549
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001550 Buffer *unpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Lang520c4ae2015-05-05 13:12:36 -04001551 if (unpackBuffer)
1552 {
James Dong020abb82019-07-24 11:33:49 -06001553 unpackBuffer->onDataChanged();
Geoff Lang520c4ae2015-05-05 13:12:36 -04001554 }
1555
Jamie Madill7c985f52018-11-29 18:16:17 -05001556 return angle::Result::Continue;
Geoff Langbce529e2014-12-01 12:48:41 -05001557}
1558
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001559angle::Result Framebuffer::blit(const Context *context,
1560 const Rectangle &sourceArea,
1561 const Rectangle &destArea,
1562 GLbitfield mask,
1563 GLenum filter)
Geoff Lang54bd5a42014-12-01 12:51:04 -05001564{
He Yunchao6be602d2016-12-22 14:33:07 +08001565 GLbitfield blitMask = mask;
1566
1567 // Note that blitting is called against draw framebuffer.
1568 // See the code in gl::Context::blitFramebuffer.
1569 if ((mask & GL_COLOR_BUFFER_BIT) && !hasEnabledDrawBuffer())
1570 {
1571 blitMask &= ~GL_COLOR_BUFFER_BIT;
1572 }
1573
1574 if ((mask & GL_STENCIL_BUFFER_BIT) && mState.getStencilAttachment() == nullptr)
1575 {
1576 blitMask &= ~GL_STENCIL_BUFFER_BIT;
1577 }
1578
1579 if ((mask & GL_DEPTH_BUFFER_BIT) && mState.getDepthAttachment() == nullptr)
1580 {
1581 blitMask &= ~GL_DEPTH_BUFFER_BIT;
1582 }
1583
1584 if (!blitMask)
1585 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001586 return angle::Result::Continue;
He Yunchao6be602d2016-12-22 14:33:07 +08001587 }
1588
1589 return mImpl->blit(context, sourceArea, destArea, blitMask, filter);
Geoff Lang54bd5a42014-12-01 12:51:04 -05001590}
1591
Jamie Madill427064d2018-04-13 16:20:34 -04001592int Framebuffer::getSamples(const Context *context)
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001593{
Jamie Madill427064d2018-04-13 16:20:34 -04001594 return (isComplete(context) ? getCachedSamples(context) : 0);
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001595}
1596
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -04001597int Framebuffer::getCachedSamples(const Context *context) const
Jamie Madill9c335862017-07-18 11:51:38 -04001598{
Jamie Madill5b772312018-03-08 20:28:32 -05001599 ASSERT(mCachedStatus.valid() && mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE);
1600
Jamie Madill9c335862017-07-18 11:51:38 -04001601 // For a complete framebuffer, all attachments must have the same sample count.
1602 // In this case return the first nonzero sample size.
1603 const auto *firstNonNullAttachment = mState.getFirstNonNullAttachment();
1604 if (firstNonNullAttachment)
1605 {
1606 ASSERT(firstNonNullAttachment->isAttached());
1607 return firstNonNullAttachment->getSamples();
1608 }
1609
1610 // No attachments found.
1611 return 0;
1612}
1613
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001614angle::Result Framebuffer::getSamplePosition(const Context *context,
1615 size_t index,
1616 GLfloat *xy) const
Corentin Wallezccab69d2017-01-27 16:57:15 -05001617{
Geoff Lang13455072018-05-09 11:24:43 -04001618 ANGLE_TRY(mImpl->getSamplePosition(context, index, xy));
Jamie Madill7c985f52018-11-29 18:16:17 -05001619 return angle::Result::Continue;
Corentin Wallezccab69d2017-01-27 16:57:15 -05001620}
1621
Jamie Madille261b442014-06-25 12:42:21 -04001622bool Framebuffer::hasValidDepthStencil() const
1623{
Jamie Madill48ef11b2016-04-27 15:21:52 -04001624 return mState.getDepthStencilAttachment() != nullptr;
Jamie Madille261b442014-06-25 12:42:21 -04001625}
1626
Jamie Madilla02315b2017-02-23 14:14:47 -05001627void Framebuffer::setAttachment(const Context *context,
1628 GLenum type,
Jamie Madill2d06b732015-04-20 12:53:28 -04001629 GLenum binding,
1630 const ImageIndex &textureIndex,
1631 FramebufferAttachmentObject *resource)
Geoff Langab75a052014-10-15 12:56:37 -04001632{
Martin Radev5dae57b2017-07-14 16:15:55 +03001633 setAttachment(context, type, binding, textureIndex, resource,
1634 FramebufferAttachment::kDefaultNumViews,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001635 FramebufferAttachment::kDefaultBaseViewIndex, false);
Martin Radev5dae57b2017-07-14 16:15:55 +03001636}
1637
1638void Framebuffer::setAttachment(const Context *context,
1639 GLenum type,
1640 GLenum binding,
1641 const ImageIndex &textureIndex,
1642 FramebufferAttachmentObject *resource,
1643 GLsizei numViews,
1644 GLuint baseViewIndex,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001645 bool isMultiview)
Martin Radev5dae57b2017-07-14 16:15:55 +03001646{
Jamie Madilla02315b2017-02-23 14:14:47 -05001647 // Context may be null in unit tests.
1648 if (!context || !context->isWebGL1())
1649 {
Martin Radev5dae57b2017-07-14 16:15:55 +03001650 setAttachmentImpl(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001651 isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001652 return;
1653 }
1654
1655 switch (binding)
1656 {
1657 case GL_DEPTH_STENCIL:
1658 case GL_DEPTH_STENCIL_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001659 mState.mWebGLDepthStencilAttachment.attach(context, type, binding, textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001660 resource, numViews, baseViewIndex,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001661 isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001662 break;
1663 case GL_DEPTH:
1664 case GL_DEPTH_ATTACHMENT:
Martin Radev5dae57b2017-07-14 16:15:55 +03001665 mState.mWebGLDepthAttachment.attach(context, type, binding, textureIndex, resource,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001666 numViews, baseViewIndex, isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001667 break;
1668 case GL_STENCIL:
1669 case GL_STENCIL_ATTACHMENT:
Martin Radev5dae57b2017-07-14 16:15:55 +03001670 mState.mWebGLStencilAttachment.attach(context, type, binding, textureIndex, resource,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001671 numViews, baseViewIndex, isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001672 break;
1673 default:
Martin Radev5dae57b2017-07-14 16:15:55 +03001674 setAttachmentImpl(context, type, binding, textureIndex, resource, numViews,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001675 baseViewIndex, isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001676 return;
1677 }
1678
Mingyu Hu7d64c482019-03-12 14:27:40 -07001679 commitWebGL1DepthStencilIfConsistent(context, numViews, baseViewIndex, isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001680}
1681
Mingyu Hu7d64c482019-03-12 14:27:40 -07001682void Framebuffer::setAttachmentMultiview(const Context *context,
1683 GLenum type,
1684 GLenum binding,
1685 const ImageIndex &textureIndex,
1686 FramebufferAttachmentObject *resource,
1687 GLsizei numViews,
1688 GLint baseViewIndex)
Martin Radev82ef7742017-08-08 17:44:58 +03001689{
Mingyu Hu7d64c482019-03-12 14:27:40 -07001690 setAttachment(context, type, binding, textureIndex, resource, numViews, baseViewIndex, true);
Martin Radev5dae57b2017-07-14 16:15:55 +03001691}
1692
1693void Framebuffer::commitWebGL1DepthStencilIfConsistent(const Context *context,
1694 GLsizei numViews,
1695 GLuint baseViewIndex,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001696 bool isMultiview)
Jamie Madilla02315b2017-02-23 14:14:47 -05001697{
1698 int count = 0;
1699
1700 std::array<FramebufferAttachment *, 3> attachments = {{&mState.mWebGLDepthStencilAttachment,
1701 &mState.mWebGLDepthAttachment,
1702 &mState.mWebGLStencilAttachment}};
1703 for (FramebufferAttachment *attachment : attachments)
1704 {
1705 if (attachment->isAttached())
1706 {
1707 count++;
1708 }
1709 }
1710
1711 mState.mWebGLDepthStencilConsistent = (count <= 1);
1712 if (!mState.mWebGLDepthStencilConsistent)
1713 {
1714 // Inconsistent.
1715 return;
1716 }
1717
Geoff Lange466c552017-03-17 15:24:12 -04001718 auto getImageIndexIfTextureAttachment = [](const FramebufferAttachment &attachment) {
1719 if (attachment.type() == GL_TEXTURE)
1720 {
1721 return attachment.getTextureImageIndex();
1722 }
1723 else
1724 {
Jamie Madillcc129372018-04-12 09:13:18 -04001725 return ImageIndex();
Geoff Lange466c552017-03-17 15:24:12 -04001726 }
1727 };
1728
Jamie Madilla02315b2017-02-23 14:14:47 -05001729 if (mState.mWebGLDepthAttachment.isAttached())
1730 {
1731 const auto &depth = mState.mWebGLDepthAttachment;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001732 setAttachmentImpl(context, depth.type(), GL_DEPTH_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001733 getImageIndexIfTextureAttachment(depth), depth.getResource(), numViews,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001734 baseViewIndex, isMultiview);
Jamie Madillcc129372018-04-12 09:13:18 -04001735 setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex(), nullptr, numViews,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001736 baseViewIndex, isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001737 }
1738 else if (mState.mWebGLStencilAttachment.isAttached())
1739 {
1740 const auto &stencil = mState.mWebGLStencilAttachment;
Jamie Madillcc129372018-04-12 09:13:18 -04001741 setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex(), nullptr, numViews,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001742 baseViewIndex, isMultiview);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001743 setAttachmentImpl(context, stencil.type(), GL_STENCIL_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001744 getImageIndexIfTextureAttachment(stencil), stencil.getResource(),
Mingyu Hu7d64c482019-03-12 14:27:40 -07001745 numViews, baseViewIndex, isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001746 }
1747 else if (mState.mWebGLDepthStencilAttachment.isAttached())
1748 {
1749 const auto &depthStencil = mState.mWebGLDepthStencilAttachment;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001750 setAttachmentImpl(context, depthStencil.type(), GL_DEPTH_ATTACHMENT,
Geoff Lange466c552017-03-17 15:24:12 -04001751 getImageIndexIfTextureAttachment(depthStencil),
Mingyu Hu7d64c482019-03-12 14:27:40 -07001752 depthStencil.getResource(), numViews, baseViewIndex, isMultiview);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001753 setAttachmentImpl(context, depthStencil.type(), GL_STENCIL_ATTACHMENT,
Geoff Lange466c552017-03-17 15:24:12 -04001754 getImageIndexIfTextureAttachment(depthStencil),
Mingyu Hu7d64c482019-03-12 14:27:40 -07001755 depthStencil.getResource(), numViews, baseViewIndex, isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001756 }
1757 else
1758 {
Jamie Madillcc129372018-04-12 09:13:18 -04001759 setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex(), nullptr, numViews,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001760 baseViewIndex, isMultiview);
Jamie Madillcc129372018-04-12 09:13:18 -04001761 setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex(), nullptr, numViews,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001762 baseViewIndex, isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001763 }
1764}
1765
Jamie Madill4928b7c2017-06-20 12:57:39 -04001766void Framebuffer::setAttachmentImpl(const Context *context,
1767 GLenum type,
Jamie Madilla02315b2017-02-23 14:14:47 -05001768 GLenum binding,
1769 const ImageIndex &textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001770 FramebufferAttachmentObject *resource,
1771 GLsizei numViews,
1772 GLuint baseViewIndex,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001773 bool isMultiview)
Jamie Madilla02315b2017-02-23 14:14:47 -05001774{
Jamie Madilla02315b2017-02-23 14:14:47 -05001775 switch (binding)
1776 {
Jamie Madillb8126692017-04-05 11:22:17 -04001777 case GL_DEPTH_STENCIL:
1778 case GL_DEPTH_STENCIL_ATTACHMENT:
1779 {
1780 // ensure this is a legitimate depth+stencil format
1781 FramebufferAttachmentObject *attachmentObj = resource;
1782 if (resource)
1783 {
Jamie Madill4fd95d52017-04-05 11:22:18 -04001784 const Format &format = resource->getAttachmentFormat(binding, textureIndex);
Jamie Madillb8126692017-04-05 11:22:17 -04001785 if (format.info->depthBits == 0 || format.info->stencilBits == 0)
1786 {
1787 // Attaching nullptr detaches the current attachment.
1788 attachmentObj = nullptr;
1789 }
1790 }
1791
Jamie Madill4928b7c2017-06-20 12:57:39 -04001792 updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
Jamie Madillb8126692017-04-05 11:22:17 -04001793 &mDirtyDepthAttachmentBinding, type, binding, textureIndex,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001794 attachmentObj, numViews, baseViewIndex, isMultiview);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001795 updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
Jamie Madillb8126692017-04-05 11:22:17 -04001796 &mDirtyStencilAttachmentBinding, type, binding, textureIndex,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001797 attachmentObj, numViews, baseViewIndex, isMultiview);
Jamie Madill42975642017-10-12 12:31:51 -04001798 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001799 }
1800
Jamie Madilla02315b2017-02-23 14:14:47 -05001801 case GL_DEPTH:
1802 case GL_DEPTH_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001803 updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001804 &mDirtyDepthAttachmentBinding, type, binding, textureIndex, resource,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001805 numViews, baseViewIndex, isMultiview);
Jamie Madill2d06b732015-04-20 12:53:28 -04001806 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001807
Jamie Madilla02315b2017-02-23 14:14:47 -05001808 case GL_STENCIL:
1809 case GL_STENCIL_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001810 updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001811 &mDirtyStencilAttachmentBinding, type, binding, textureIndex, resource,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001812 numViews, baseViewIndex, isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001813 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001814
Jamie Madilla02315b2017-02-23 14:14:47 -05001815 case GL_BACK:
Geoff Lang8170eab2017-09-21 13:59:04 -04001816 updateAttachment(context, &mState.mColorAttachments[0], DIRTY_BIT_COLOR_ATTACHMENT_0,
1817 &mDirtyColorAttachmentBindings[0], type, binding, textureIndex,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001818 resource, numViews, baseViewIndex, isMultiview);
Tim Van Patten56ba54c2019-08-08 13:03:34 -06001819
Jamie Madilla02315b2017-02-23 14:14:47 -05001820 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001821
Jamie Madilla02315b2017-02-23 14:14:47 -05001822 default:
1823 {
1824 size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
1825 ASSERT(colorIndex < mState.mColorAttachments.size());
Jamie Madillb8126692017-04-05 11:22:17 -04001826 size_t dirtyBit = DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001827 updateAttachment(context, &mState.mColorAttachments[colorIndex], dirtyBit,
Jamie Madillb8126692017-04-05 11:22:17 -04001828 &mDirtyColorAttachmentBindings[colorIndex], type, binding,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001829 textureIndex, resource, numViews, baseViewIndex, isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001830
shrekshaoc87e0052019-02-21 11:40:28 -08001831 if (!resource)
1832 {
shrekshao8413fab2019-04-04 17:13:18 -07001833 mColorAttachmentBits.reset(colorIndex);
shrekshaoc87e0052019-02-21 11:40:28 -08001834 mFloat32ColorAttachmentBits.reset(colorIndex);
1835 }
1836 else
1837 {
shrekshao8413fab2019-04-04 17:13:18 -07001838 mColorAttachmentBits.set(colorIndex);
shrekshaoc87e0052019-02-21 11:40:28 -08001839 updateFloat32ColorAttachmentBits(
1840 colorIndex, resource->getAttachmentFormat(binding, textureIndex).info);
1841 }
1842
Corentin Walleze7557742017-06-01 13:09:57 -04001843 // TODO(jmadill): ASSERT instead of checking the attachment exists in
1844 // formsRenderingFeedbackLoopWith
Jamie Madilla02315b2017-02-23 14:14:47 -05001845 bool enabled = (type != GL_NONE && getDrawBufferState(colorIndex) != GL_NONE);
1846 mState.mEnabledDrawBuffers.set(colorIndex, enabled);
Jamie Madill6e18a232019-01-16 13:27:14 -05001847 SetComponentTypeMask(getDrawbufferWriteType(colorIndex), colorIndex,
1848 &mState.mDrawBufferTypeMask);
Jamie Madill2d06b732015-04-20 12:53:28 -04001849 }
Jamie Madilla02315b2017-02-23 14:14:47 -05001850 break;
Geoff Langab75a052014-10-15 12:56:37 -04001851 }
1852}
1853
Jamie Madill4928b7c2017-06-20 12:57:39 -04001854void Framebuffer::updateAttachment(const Context *context,
1855 FramebufferAttachment *attachment,
Jamie Madillb8126692017-04-05 11:22:17 -04001856 size_t dirtyBit,
Jamie Madilld4442552018-02-27 22:03:47 -05001857 angle::ObserverBinding *onDirtyBinding,
Jamie Madillb8126692017-04-05 11:22:17 -04001858 GLenum type,
1859 GLenum binding,
1860 const ImageIndex &textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001861 FramebufferAttachmentObject *resource,
1862 GLsizei numViews,
1863 GLuint baseViewIndex,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001864 bool isMultiview)
Jamie Madillb8126692017-04-05 11:22:17 -04001865{
Martin Radev5dae57b2017-07-14 16:15:55 +03001866 attachment->attach(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001867 isMultiview);
Jamie Madillb8126692017-04-05 11:22:17 -04001868 mDirtyBits.set(dirtyBit);
Jamie Madill05b35b22017-10-03 09:01:44 -04001869 mState.mResourceNeedsInit.set(dirtyBit, attachment->initState() == InitState::MayNeedInit);
Jamie Madill66f0d2c2018-11-30 15:25:36 -05001870 onDirtyBinding->bind(resource);
Jamie Madille98b1b52018-03-08 09:47:23 -05001871
Jamie Madill124f78c2019-06-18 11:48:24 -04001872 invalidateCompletenessCache();
Jamie Madillb8126692017-04-05 11:22:17 -04001873}
1874
Jamie Madilla02315b2017-02-23 14:14:47 -05001875void Framebuffer::resetAttachment(const Context *context, GLenum binding)
Jamie Madill2d06b732015-04-20 12:53:28 -04001876{
Jamie Madillcc129372018-04-12 09:13:18 -04001877 setAttachment(context, GL_NONE, binding, ImageIndex(), nullptr);
Jamie Madill2d06b732015-04-20 12:53:28 -04001878}
1879
Jamie Madill6f755b22018-10-09 12:48:54 -04001880angle::Result Framebuffer::syncState(const Context *context)
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001881{
1882 if (mDirtyBits.any())
1883 {
Jamie Madill888081d2018-02-27 00:24:46 -05001884 mDirtyBitsGuard = mDirtyBits;
Jamie Madill19fa1c62018-03-08 09:47:21 -05001885 ANGLE_TRY(mImpl->syncState(context, mDirtyBits));
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001886 mDirtyBits.reset();
Jamie Madill888081d2018-02-27 00:24:46 -05001887 mDirtyBitsGuard.reset();
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001888 }
Jamie Madill7c985f52018-11-29 18:16:17 -05001889 return angle::Result::Continue;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001890}
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001891
Jamie Madill124f78c2019-06-18 11:48:24 -04001892void Framebuffer::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
Jamie Madill51f40ec2016-06-15 14:06:00 -04001893{
Jamie Madille4faae22019-05-10 08:27:00 -04001894 if (message != angle::SubjectMessage::SubjectChanged)
Jamie Madillf668a4b2018-09-23 17:01:20 -04001895 {
Jamie Madill67220092019-05-20 11:12:53 -04001896 // This can be triggered by SubImage calls for Textures.
1897 if (message == angle::SubjectMessage::ContentsChanged)
1898 {
1899 mDirtyBits.set(DIRTY_BIT_COLOR_BUFFER_CONTENTS_0 + index);
Jamie Madill124f78c2019-06-18 11:48:24 -04001900 onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
Jamie Madill67220092019-05-20 11:12:53 -04001901 return;
1902 }
1903
Jamie Madillf668a4b2018-09-23 17:01:20 -04001904 // This can be triggered by the GL back-end TextureGL class.
Jamie Madille4faae22019-05-10 08:27:00 -04001905 ASSERT(message == angle::SubjectMessage::DirtyBitsFlagged);
Jamie Madillf668a4b2018-09-23 17:01:20 -04001906 return;
1907 }
Jamie Madill55e57f92018-09-18 11:32:43 -04001908
1909 ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(index));
1910 mDirtyBits.set(index);
Jamie Madill888081d2018-02-27 00:24:46 -05001911
Jamie Madill124f78c2019-06-18 11:48:24 -04001912 invalidateCompletenessCache();
Jamie Madill05b35b22017-10-03 09:01:44 -04001913
Jamie Madilld4442552018-02-27 22:03:47 -05001914 FramebufferAttachment *attachment = getAttachmentFromSubjectIndex(index);
1915
Jamie Madill05b35b22017-10-03 09:01:44 -04001916 // Mark the appropriate init flag.
Jamie Madilld4442552018-02-27 22:03:47 -05001917 mState.mResourceNeedsInit.set(index, attachment->initState() == InitState::MayNeedInit);
shrekshaoc87e0052019-02-21 11:40:28 -08001918
1919 // Update mFloat32ColorAttachmentBits Cache
1920 if (index < DIRTY_BIT_COLOR_ATTACHMENT_MAX)
1921 {
1922 ASSERT(index != DIRTY_BIT_DEPTH_ATTACHMENT);
1923 ASSERT(index != DIRTY_BIT_STENCIL_ATTACHMENT);
1924 updateFloat32ColorAttachmentBits(index - DIRTY_BIT_COLOR_ATTACHMENT_0,
1925 attachment->getFormat().info);
1926 }
Jamie Madilld4442552018-02-27 22:03:47 -05001927}
1928
1929FramebufferAttachment *Framebuffer::getAttachmentFromSubjectIndex(angle::SubjectIndex index)
1930{
1931 switch (index)
1932 {
1933 case DIRTY_BIT_DEPTH_ATTACHMENT:
1934 return &mState.mDepthAttachment;
1935 case DIRTY_BIT_STENCIL_ATTACHMENT:
1936 return &mState.mStencilAttachment;
1937 default:
1938 size_t colorIndex = (index - DIRTY_BIT_COLOR_ATTACHMENT_0);
1939 ASSERT(colorIndex < mState.mColorAttachments.size());
1940 return &mState.mColorAttachments[colorIndex];
1941 }
Jamie Madill51f40ec2016-06-15 14:06:00 -04001942}
1943
shrekshao8413fab2019-04-04 17:13:18 -07001944bool Framebuffer::formsRenderingFeedbackLoopWith(const Context *context) const
Jamie Madilla4595b82017-01-11 17:36:34 -05001945{
shrekshao8413fab2019-04-04 17:13:18 -07001946 const State &state = context->getState();
Jamie Madill785e8a02018-10-04 17:42:00 -04001947 const Program *program = state.getProgram();
Jamie Madilla4595b82017-01-11 17:36:34 -05001948
1949 // TODO(jmadill): Default framebuffer feedback loops.
Jamie Madill2274b652018-05-31 10:56:08 -04001950 if (mState.mId == 0)
Jamie Madilla4595b82017-01-11 17:36:34 -05001951 {
1952 return false;
1953 }
1954
Jamie Madill4e71b2b2019-07-08 13:23:38 -04001955 const FramebufferAttachment *depth = getDepthAttachment();
1956 const FramebufferAttachment *stencil = getStencilAttachment();
shrekshao8413fab2019-04-04 17:13:18 -07001957
1958 const bool checkDepth = depth && depth->type() == GL_TEXTURE;
1959 // Skip the feedback loop check for stencil if depth/stencil point to the same resource.
1960 const bool checkStencil =
1961 (stencil && stencil->type() == GL_TEXTURE) && (!depth || *stencil != *depth);
1962
1963 const gl::ActiveTextureMask &activeTextures = program->getActiveSamplersMask();
1964 const gl::ActiveTexturePointerArray &textures = state.getActiveTexturesCache();
1965
1966 for (size_t textureUnit : activeTextures)
Jamie Madilla4595b82017-01-11 17:36:34 -05001967 {
shrekshao8413fab2019-04-04 17:13:18 -07001968 Texture *texture = textures[textureUnit];
1969
1970 if (texture == nullptr)
Jamie Madilla4595b82017-01-11 17:36:34 -05001971 {
shrekshao8413fab2019-04-04 17:13:18 -07001972 continue;
1973 }
1974
1975 // Depth and stencil attachment form feedback loops
1976 // Regardless of if enabled or masked.
1977 if (checkDepth)
1978 {
1979 if (texture->id() == depth->id())
Jamie Madilla4595b82017-01-11 17:36:34 -05001980 {
1981 return true;
1982 }
1983 }
Jamie Madilla4595b82017-01-11 17:36:34 -05001984
shrekshao8413fab2019-04-04 17:13:18 -07001985 if (checkStencil)
Jamie Madill1d37bc52017-02-02 19:59:58 -05001986 {
shrekshao8413fab2019-04-04 17:13:18 -07001987 if (texture->id() == stencil->id())
Jamie Madill1d37bc52017-02-02 19:59:58 -05001988 {
Jamie Madill38fe6842018-09-19 07:20:00 -04001989 return true;
Jamie Madill1d37bc52017-02-02 19:59:58 -05001990 }
1991 }
shrekshao8413fab2019-04-04 17:13:18 -07001992
1993 // Check if any color attachment forms a feedback loop.
1994 for (size_t drawIndex : mColorAttachmentBits)
1995 {
1996 const FramebufferAttachment &attachment = mState.mColorAttachments[drawIndex];
1997 ASSERT(attachment.isAttached());
1998
1999 if (attachment.isTextureWithId(texture->id()))
2000 {
2001 // TODO(jmadill): Check for appropriate overlap.
2002 return true;
2003 }
2004 }
Jamie Madill1d37bc52017-02-02 19:59:58 -05002005 }
2006
Jamie Madilla4595b82017-01-11 17:36:34 -05002007 return false;
2008}
2009
Jamie Madillfd3dd432017-02-02 19:59:59 -05002010bool Framebuffer::formsCopyingFeedbackLoopWith(GLuint copyTextureID,
2011 GLint copyTextureLevel,
2012 GLint copyTextureLayer) const
Jamie Madillf695a3a2017-01-11 17:36:35 -05002013{
Jamie Madill2274b652018-05-31 10:56:08 -04002014 if (mState.mId == 0)
Jamie Madillf695a3a2017-01-11 17:36:35 -05002015 {
2016 // It seems impossible to form a texture copying feedback loop with the default FBO.
2017 return false;
2018 }
2019
Jamie Madill4e71b2b2019-07-08 13:23:38 -04002020 const FramebufferAttachment *readAttachment = getReadColorAttachment();
Jamie Madillf695a3a2017-01-11 17:36:35 -05002021 ASSERT(readAttachment);
2022
2023 if (readAttachment->isTextureWithId(copyTextureID))
2024 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002025 const auto &imageIndex = readAttachment->getTextureImageIndex();
Jamie Madillcc129372018-04-12 09:13:18 -04002026 if (imageIndex.getLevelIndex() == copyTextureLevel)
Jamie Madillf695a3a2017-01-11 17:36:35 -05002027 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002028 // Check 3D/Array texture layers.
Jamie Madillcc129372018-04-12 09:13:18 -04002029 return !imageIndex.hasLayer() || copyTextureLayer == ImageIndex::kEntireLevel ||
2030 imageIndex.getLayerIndex() == copyTextureLayer;
Jamie Madillf695a3a2017-01-11 17:36:35 -05002031 }
2032 }
2033 return false;
2034}
2035
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002036GLint Framebuffer::getDefaultWidth() const
2037{
2038 return mState.getDefaultWidth();
2039}
2040
2041GLint Framebuffer::getDefaultHeight() const
2042{
2043 return mState.getDefaultHeight();
2044}
2045
2046GLint Framebuffer::getDefaultSamples() const
2047{
2048 return mState.getDefaultSamples();
2049}
2050
Geoff Lang92019432017-11-20 13:09:34 -05002051bool Framebuffer::getDefaultFixedSampleLocations() const
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002052{
2053 return mState.getDefaultFixedSampleLocations();
2054}
2055
Jiawei Shaob1e91382018-05-17 14:33:55 +08002056GLint Framebuffer::getDefaultLayers() const
2057{
2058 return mState.getDefaultLayers();
2059}
2060
Jamie Madillb983a4b2018-08-01 11:34:51 -04002061void Framebuffer::setDefaultWidth(const Context *context, GLint defaultWidth)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002062{
2063 mState.mDefaultWidth = defaultWidth;
2064 mDirtyBits.set(DIRTY_BIT_DEFAULT_WIDTH);
Jamie Madill124f78c2019-06-18 11:48:24 -04002065 invalidateCompletenessCache();
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002066}
2067
Jamie Madillb983a4b2018-08-01 11:34:51 -04002068void Framebuffer::setDefaultHeight(const Context *context, GLint defaultHeight)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002069{
2070 mState.mDefaultHeight = defaultHeight;
2071 mDirtyBits.set(DIRTY_BIT_DEFAULT_HEIGHT);
Jamie Madill124f78c2019-06-18 11:48:24 -04002072 invalidateCompletenessCache();
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002073}
2074
Jamie Madillb983a4b2018-08-01 11:34:51 -04002075void Framebuffer::setDefaultSamples(const Context *context, GLint defaultSamples)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002076{
2077 mState.mDefaultSamples = defaultSamples;
2078 mDirtyBits.set(DIRTY_BIT_DEFAULT_SAMPLES);
Jamie Madill124f78c2019-06-18 11:48:24 -04002079 invalidateCompletenessCache();
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002080}
2081
Jamie Madillb983a4b2018-08-01 11:34:51 -04002082void Framebuffer::setDefaultFixedSampleLocations(const Context *context,
2083 bool defaultFixedSampleLocations)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002084{
2085 mState.mDefaultFixedSampleLocations = defaultFixedSampleLocations;
2086 mDirtyBits.set(DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS);
Jamie Madill124f78c2019-06-18 11:48:24 -04002087 invalidateCompletenessCache();
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002088}
2089
Jiawei Shaob1e91382018-05-17 14:33:55 +08002090void Framebuffer::setDefaultLayers(GLint defaultLayers)
2091{
2092 mState.mDefaultLayers = defaultLayers;
2093 mDirtyBits.set(DIRTY_BIT_DEFAULT_LAYERS);
2094}
2095
Martin Radev14a26ae2017-07-24 15:56:29 +03002096GLsizei Framebuffer::getNumViews() const
2097{
Martin Radev5c00d0d2017-08-07 10:06:59 +03002098 return mState.getNumViews();
Martin Radev14a26ae2017-07-24 15:56:29 +03002099}
2100
Martin Radev4e619f52017-08-09 11:50:06 +03002101GLint Framebuffer::getBaseViewIndex() const
2102{
2103 return mState.getBaseViewIndex();
2104}
2105
Mingyu Hu7d64c482019-03-12 14:27:40 -07002106bool Framebuffer::isMultiview() const
Martin Radev878c8b12017-07-28 09:51:04 +03002107{
Mingyu Hu7d64c482019-03-12 14:27:40 -07002108 return mState.isMultiview();
Martin Radev878c8b12017-07-28 09:51:04 +03002109}
2110
Olli Etuaho8acb1b62018-07-30 16:20:54 +03002111bool Framebuffer::readDisallowedByMultiview() const
2112{
Mingyu Hu7d64c482019-03-12 14:27:40 -07002113 return (mState.isMultiview() && mState.getNumViews() > 1);
Olli Etuaho8acb1b62018-07-30 16:20:54 +03002114}
2115
Jamie Madill64b7c4f2018-10-19 11:38:04 -04002116angle::Result Framebuffer::ensureClearAttachmentsInitialized(const Context *context,
2117 GLbitfield mask)
Geoff Langd4fff502017-09-22 11:28:28 -04002118{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05002119 const auto &glState = context->getState();
Geoff Langd4fff502017-09-22 11:28:28 -04002120 if (!context->isRobustResourceInitEnabled() || glState.isRasterizerDiscardEnabled())
2121 {
Jamie Madill7c985f52018-11-29 18:16:17 -05002122 return angle::Result::Continue;
Geoff Langd4fff502017-09-22 11:28:28 -04002123 }
2124
Geoff Langa36483f2018-03-09 16:11:21 -05002125 const BlendState &blend = glState.getBlendState();
2126 const DepthStencilState &depthStencil = glState.getDepthStencilState();
Geoff Langd4fff502017-09-22 11:28:28 -04002127
2128 bool color = (mask & GL_COLOR_BUFFER_BIT) != 0 && !IsColorMaskedOut(blend);
2129 bool depth = (mask & GL_DEPTH_BUFFER_BIT) != 0 && !IsDepthMaskedOut(depthStencil);
2130 bool stencil = (mask & GL_STENCIL_BUFFER_BIT) != 0 && !IsStencilMaskedOut(depthStencil);
2131
2132 if (!color && !depth && !stencil)
2133 {
Jamie Madill7c985f52018-11-29 18:16:17 -05002134 return angle::Result::Continue;
Geoff Langd4fff502017-09-22 11:28:28 -04002135 }
2136
2137 if (partialClearNeedsInit(context, color, depth, stencil))
2138 {
2139 ANGLE_TRY(ensureDrawAttachmentsInitialized(context));
2140 }
2141
2142 // If the impl encounters an error during a a full (non-partial) clear, the attachments will
2143 // still be marked initialized. This simplifies design, allowing this method to be called before
2144 // the clear.
2145 markDrawAttachmentsInitialized(color, depth, stencil);
2146
Jamie Madill7c985f52018-11-29 18:16:17 -05002147 return angle::Result::Continue;
Geoff Langd4fff502017-09-22 11:28:28 -04002148}
2149
Jamie Madill64b7c4f2018-10-19 11:38:04 -04002150angle::Result Framebuffer::ensureClearBufferAttachmentsInitialized(const Context *context,
2151 GLenum buffer,
2152 GLint drawbuffer)
Geoff Langd4fff502017-09-22 11:28:28 -04002153{
2154 if (!context->isRobustResourceInitEnabled() ||
Jamie Madillc3dc5d42018-12-30 12:12:04 -05002155 context->getState().isRasterizerDiscardEnabled() || IsClearBufferMaskedOut(context, buffer))
Geoff Langd4fff502017-09-22 11:28:28 -04002156 {
Jamie Madill7c985f52018-11-29 18:16:17 -05002157 return angle::Result::Continue;
Geoff Langd4fff502017-09-22 11:28:28 -04002158 }
2159
2160 if (partialBufferClearNeedsInit(context, buffer))
2161 {
2162 ANGLE_TRY(ensureBufferInitialized(context, buffer, drawbuffer));
2163 }
2164
2165 // If the impl encounters an error during a a full (non-partial) clear, the attachments will
2166 // still be marked initialized. This simplifies design, allowing this method to be called before
2167 // the clear.
2168 markBufferInitialized(buffer, drawbuffer);
2169
Jamie Madill7c985f52018-11-29 18:16:17 -05002170 return angle::Result::Continue;
Geoff Langd4fff502017-09-22 11:28:28 -04002171}
2172
Jamie Madill6f755b22018-10-09 12:48:54 -04002173angle::Result Framebuffer::ensureDrawAttachmentsInitialized(const Context *context)
Jamie Madill05b35b22017-10-03 09:01:44 -04002174{
2175 if (!context->isRobustResourceInitEnabled())
2176 {
Jamie Madill7c985f52018-11-29 18:16:17 -05002177 return angle::Result::Continue;
Jamie Madill05b35b22017-10-03 09:01:44 -04002178 }
2179
2180 // Note: we don't actually filter by the draw attachment enum. Just init everything.
2181 for (size_t bit : mState.mResourceNeedsInit)
2182 {
2183 switch (bit)
2184 {
2185 case DIRTY_BIT_DEPTH_ATTACHMENT:
2186 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2187 break;
2188 case DIRTY_BIT_STENCIL_ATTACHMENT:
2189 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2190 break;
2191 default:
2192 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[bit]));
2193 break;
2194 }
2195 }
2196
2197 mState.mResourceNeedsInit.reset();
Jamie Madill7c985f52018-11-29 18:16:17 -05002198 return angle::Result::Continue;
Jamie Madill05b35b22017-10-03 09:01:44 -04002199}
2200
Jamie Madill0a1eeb82019-05-13 13:53:18 -04002201angle::Result Framebuffer::ensureReadAttachmentsInitialized(const Context *context)
Jamie Madill05b35b22017-10-03 09:01:44 -04002202{
Jamie Madill0a1eeb82019-05-13 13:53:18 -04002203 ASSERT(context->isRobustResourceInitEnabled());
2204
2205 if (mState.mResourceNeedsInit.none())
Jamie Madill05b35b22017-10-03 09:01:44 -04002206 {
Jamie Madill7c985f52018-11-29 18:16:17 -05002207 return angle::Result::Continue;
Jamie Madill05b35b22017-10-03 09:01:44 -04002208 }
2209
Jamie Madill0a1eeb82019-05-13 13:53:18 -04002210 if (mState.mReadBufferState != GL_NONE)
Jamie Madill05b35b22017-10-03 09:01:44 -04002211 {
Tim Van Patten56ba54c2019-08-08 13:03:34 -06002212 if (isDefault())
Jamie Madill05b35b22017-10-03 09:01:44 -04002213 {
Tim Van Patten56ba54c2019-08-08 13:03:34 -06002214 if (!mState.mDefaultFramebufferReadAttachmentInitialized)
2215 {
2216 ANGLE_TRY(InitAttachment(context, &mState.mDefaultFramebufferReadAttachment));
2217 mState.mDefaultFramebufferReadAttachmentInitialized = true;
2218 }
2219 }
2220 else
2221 {
2222 size_t readIndex = mState.getReadIndex();
2223 if (mState.mResourceNeedsInit[readIndex])
2224 {
2225 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[readIndex]));
2226 mState.mResourceNeedsInit.reset(readIndex);
2227 }
Jamie Madill05b35b22017-10-03 09:01:44 -04002228 }
2229 }
2230
Jamie Madill0a1eeb82019-05-13 13:53:18 -04002231 // Conservatively init depth since it can be read by BlitFramebuffer.
2232 if (hasDepth())
Jamie Madill05b35b22017-10-03 09:01:44 -04002233 {
2234 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2235 {
2236 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2237 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2238 }
2239 }
2240
Jamie Madill0a1eeb82019-05-13 13:53:18 -04002241 // Conservatively init stencil since it can be read by BlitFramebuffer.
2242 if (hasStencil())
Jamie Madill05b35b22017-10-03 09:01:44 -04002243 {
2244 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2245 {
2246 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2247 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2248 }
2249 }
2250
Jamie Madill7c985f52018-11-29 18:16:17 -05002251 return angle::Result::Continue;
Jamie Madill05b35b22017-10-03 09:01:44 -04002252}
2253
2254void Framebuffer::markDrawAttachmentsInitialized(bool color, bool depth, bool stencil)
2255{
2256 // Mark attachments as initialized.
2257 if (color)
2258 {
2259 for (auto colorIndex : mState.mEnabledDrawBuffers)
2260 {
2261 auto &colorAttachment = mState.mColorAttachments[colorIndex];
2262 ASSERT(colorAttachment.isAttached());
2263 colorAttachment.setInitState(InitState::Initialized);
2264 mState.mResourceNeedsInit.reset(colorIndex);
2265 }
2266 }
2267
2268 if (depth && mState.mDepthAttachment.isAttached())
2269 {
2270 mState.mDepthAttachment.setInitState(InitState::Initialized);
2271 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2272 }
2273
2274 if (stencil && mState.mStencilAttachment.isAttached())
2275 {
2276 mState.mStencilAttachment.setInitState(InitState::Initialized);
2277 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2278 }
2279}
2280
2281void Framebuffer::markBufferInitialized(GLenum bufferType, GLint bufferIndex)
2282{
2283 switch (bufferType)
2284 {
2285 case GL_COLOR:
2286 {
2287 ASSERT(bufferIndex < static_cast<GLint>(mState.mColorAttachments.size()));
2288 if (mState.mColorAttachments[bufferIndex].isAttached())
2289 {
2290 mState.mColorAttachments[bufferIndex].setInitState(InitState::Initialized);
2291 mState.mResourceNeedsInit.reset(bufferIndex);
2292 }
2293 break;
2294 }
2295 case GL_DEPTH:
2296 {
2297 if (mState.mDepthAttachment.isAttached())
2298 {
2299 mState.mDepthAttachment.setInitState(InitState::Initialized);
2300 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2301 }
2302 break;
2303 }
2304 case GL_STENCIL:
2305 {
2306 if (mState.mStencilAttachment.isAttached())
2307 {
2308 mState.mStencilAttachment.setInitState(InitState::Initialized);
2309 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2310 }
2311 break;
2312 }
2313 case GL_DEPTH_STENCIL:
2314 {
2315 if (mState.mDepthAttachment.isAttached())
2316 {
2317 mState.mDepthAttachment.setInitState(InitState::Initialized);
2318 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2319 }
2320 if (mState.mStencilAttachment.isAttached())
2321 {
2322 mState.mStencilAttachment.setInitState(InitState::Initialized);
2323 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2324 }
2325 break;
2326 }
2327 default:
2328 UNREACHABLE();
2329 break;
2330 }
2331}
2332
2333Box Framebuffer::getDimensions() const
2334{
2335 return mState.getDimensions();
2336}
2337
Jonah Ryan-Davis7151fe52019-07-17 15:15:27 -04002338Extents Framebuffer::getExtents() const
2339{
2340 return mState.getExtents();
2341}
2342
Jamie Madill64b7c4f2018-10-19 11:38:04 -04002343angle::Result Framebuffer::ensureBufferInitialized(const Context *context,
2344 GLenum bufferType,
2345 GLint bufferIndex)
Jamie Madill05b35b22017-10-03 09:01:44 -04002346{
2347 ASSERT(context->isRobustResourceInitEnabled());
2348
2349 if (mState.mResourceNeedsInit.none())
2350 {
Jamie Madill7c985f52018-11-29 18:16:17 -05002351 return angle::Result::Continue;
Jamie Madill05b35b22017-10-03 09:01:44 -04002352 }
2353
2354 switch (bufferType)
2355 {
2356 case GL_COLOR:
2357 {
2358 ASSERT(bufferIndex < static_cast<GLint>(mState.mColorAttachments.size()));
2359 if (mState.mResourceNeedsInit[bufferIndex])
2360 {
2361 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[bufferIndex]));
2362 mState.mResourceNeedsInit.reset(bufferIndex);
2363 }
2364 break;
2365 }
2366 case GL_DEPTH:
2367 {
2368 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2369 {
2370 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2371 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2372 }
2373 break;
2374 }
2375 case GL_STENCIL:
2376 {
2377 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2378 {
2379 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2380 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2381 }
2382 break;
2383 }
2384 case GL_DEPTH_STENCIL:
2385 {
2386 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2387 {
2388 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2389 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2390 }
2391 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2392 {
2393 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2394 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2395 }
2396 break;
2397 }
2398 default:
2399 UNREACHABLE();
2400 break;
2401 }
2402
Jamie Madill7c985f52018-11-29 18:16:17 -05002403 return angle::Result::Continue;
Jamie Madill05b35b22017-10-03 09:01:44 -04002404}
2405
2406bool Framebuffer::partialBufferClearNeedsInit(const Context *context, GLenum bufferType)
2407{
2408 if (!context->isRobustResourceInitEnabled() || mState.mResourceNeedsInit.none())
2409 {
2410 return false;
2411 }
2412
2413 switch (bufferType)
2414 {
2415 case GL_COLOR:
2416 return partialClearNeedsInit(context, true, false, false);
2417 case GL_DEPTH:
2418 return partialClearNeedsInit(context, false, true, false);
2419 case GL_STENCIL:
2420 return partialClearNeedsInit(context, false, false, true);
2421 case GL_DEPTH_STENCIL:
2422 return partialClearNeedsInit(context, false, true, true);
2423 default:
2424 UNREACHABLE();
2425 return false;
2426 }
2427}
Jamie Madill60ec6ea2016-01-22 15:27:19 -05002428} // namespace gl