blob: 7fa5a3a775271b8873d987abadc4243d9c00b36d [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
Jiacheng Lu2c5d48a2019-08-23 09:28:35 -0600280FramebufferState::FramebufferState(const Caps &caps, FramebufferID id)
Jamie Madill2274b652018-05-31 10:56:08 -0400281 : 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
Jiacheng Lu2c5d48a2019-08-23 09:28:35 -0600631const FramebufferID Framebuffer::kDefaultDrawFramebufferHandle = {0};
632
633Framebuffer::Framebuffer(const Caps &caps, rx::GLImplFactory *factory, FramebufferID id)
Jamie Madill2274b652018-05-31 10:56:08 -0400634 : mState(caps, id),
Jamie Madill362876b2016-06-16 14:46:59 -0400635 mImpl(factory->createFramebuffer(mState)),
Jamie Madill362876b2016-06-16 14:46:59 -0400636 mCachedStatus(),
637 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
638 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000639{
Corentin Wallez37c39792015-08-20 14:19:46 -0400640 ASSERT(mImpl != nullptr);
Jamie Madill362876b2016-06-16 14:46:59 -0400641 ASSERT(mState.mColorAttachments.size() == static_cast<size_t>(caps.maxColorAttachments));
642
Jamie Madill1e5499d2017-04-05 11:22:16 -0400643 for (uint32_t colorIndex = 0;
644 colorIndex < static_cast<uint32_t>(mState.mColorAttachments.size()); ++colorIndex)
Jamie Madill362876b2016-06-16 14:46:59 -0400645 {
Jamie Madill1e5499d2017-04-05 11:22:16 -0400646 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
Jamie Madill362876b2016-06-16 14:46:59 -0400647 }
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600648 mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
Corentin Wallez37c39792015-08-20 14:19:46 -0400649}
650
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600651Framebuffer::Framebuffer(const Context *context, egl::Surface *surface, egl::Surface *readSurface)
Jamie Madill362876b2016-06-16 14:46:59 -0400652 : mState(),
Geoff Langbf7b95d2018-05-01 16:48:21 -0400653 mImpl(surface->getImplementation()->createDefaultFramebuffer(context, mState)),
Jamie Madill362876b2016-06-16 14:46:59 -0400654 mCachedStatus(GL_FRAMEBUFFER_COMPLETE),
655 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
656 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
Corentin Wallez37c39792015-08-20 14:19:46 -0400657{
Geoff Langda88add2014-12-01 10:22:01 -0500658 ASSERT(mImpl != nullptr);
Jamie Madill6f60d052017-02-22 15:20:11 -0500659
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600660 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
Geoff Langbf7b95d2018-05-01 16:48:21 -0400661 setAttachmentImpl(context, GL_FRAMEBUFFER_DEFAULT, GL_BACK, ImageIndex(), surface,
Jamie Madillcc129372018-04-12 09:13:18 -0400662 FramebufferAttachment::kDefaultNumViews,
Mingyu Hu7e44ec22019-08-26 15:59:48 -0700663 FramebufferAttachment::kDefaultBaseViewIndex, false,
664 FramebufferAttachment::kDefaultRenderToTextureSamples);
Jamie Madill6f60d052017-02-22 15:20:11 -0500665
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600666 setReadSurface(context, readSurface);
667
Jamie Madill6f60d052017-02-22 15:20:11 -0500668 if (surface->getConfig()->depthSize > 0)
669 {
Geoff Langbf7b95d2018-05-01 16:48:21 -0400670 setAttachmentImpl(context, GL_FRAMEBUFFER_DEFAULT, GL_DEPTH, ImageIndex(), surface,
Jamie Madillcc129372018-04-12 09:13:18 -0400671 FramebufferAttachment::kDefaultNumViews,
Mingyu Hu7e44ec22019-08-26 15:59:48 -0700672 FramebufferAttachment::kDefaultBaseViewIndex, false,
673 FramebufferAttachment::kDefaultRenderToTextureSamples);
Jamie Madill6f60d052017-02-22 15:20:11 -0500674 }
675
676 if (surface->getConfig()->stencilSize > 0)
677 {
Geoff Langbf7b95d2018-05-01 16:48:21 -0400678 setAttachmentImpl(context, GL_FRAMEBUFFER_DEFAULT, GL_STENCIL, ImageIndex(), surface,
Jamie Madillcc129372018-04-12 09:13:18 -0400679 FramebufferAttachment::kDefaultNumViews,
Mingyu Hu7e44ec22019-08-26 15:59:48 -0700680 FramebufferAttachment::kDefaultBaseViewIndex, false,
681 FramebufferAttachment::kDefaultRenderToTextureSamples);
Jamie Madill6f60d052017-02-22 15:20:11 -0500682 }
Jamie Madill6e18a232019-01-16 13:27:14 -0500683 SetComponentTypeMask(getDrawbufferWriteType(0), 0, &mState.mDrawBufferTypeMask);
Geoff Langee244c72019-05-06 10:30:18 -0400684
685 // Ensure the backend has a chance to synchronize its content for a new backbuffer.
686 mDirtyBits.set(DIRTY_BIT_COLOR_BUFFER_CONTENTS_0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000687}
688
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600689Framebuffer::Framebuffer(const Context *context,
690 rx::GLImplFactory *factory,
691 egl::Surface *readSurface)
Corentin Wallezccab69d2017-01-27 16:57:15 -0500692 : mState(),
693 mImpl(factory->createFramebuffer(mState)),
Corentin Wallezccab69d2017-01-27 16:57:15 -0500694 mCachedStatus(GL_FRAMEBUFFER_UNDEFINED_OES),
695 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
696 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
697{
Jamie Madill1e5499d2017-04-05 11:22:16 -0400698 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
Jamie Madill6e18a232019-01-16 13:27:14 -0500699 SetComponentTypeMask(getDrawbufferWriteType(0), 0, &mState.mDrawBufferTypeMask);
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600700
701 setReadSurface(context, readSurface);
Corentin Wallezccab69d2017-01-27 16:57:15 -0500702}
703
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000704Framebuffer::~Framebuffer()
705{
Geoff Langda88add2014-12-01 10:22:01 -0500706 SafeDelete(mImpl);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000707}
708
Jamie Madill4928b7c2017-06-20 12:57:39 -0400709void Framebuffer::onDestroy(const Context *context)
Jamie Madill6c1f6712017-02-14 19:08:04 -0500710{
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600711 if (isDefault())
712 {
713 mState.mDefaultFramebufferReadAttachment.detach(context);
714 mState.mDefaultFramebufferReadAttachmentInitialized = false;
715 }
716
Jamie Madill4928b7c2017-06-20 12:57:39 -0400717 for (auto &attachment : mState.mColorAttachments)
718 {
719 attachment.detach(context);
720 }
721 mState.mDepthAttachment.detach(context);
722 mState.mStencilAttachment.detach(context);
723 mState.mWebGLDepthAttachment.detach(context);
724 mState.mWebGLStencilAttachment.detach(context);
725 mState.mWebGLDepthStencilAttachment.detach(context);
726
Jamie Madillc564c072017-06-01 12:45:42 -0400727 mImpl->destroy(context);
Jamie Madill6c1f6712017-02-14 19:08:04 -0500728}
729
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600730void Framebuffer::setReadSurface(const Context *context, egl::Surface *readSurface)
731{
732 // updateAttachment() without mState.mResourceNeedsInit.set()
733 mState.mDefaultFramebufferReadAttachment.attach(
734 context, GL_FRAMEBUFFER_DEFAULT, GL_BACK, ImageIndex(), readSurface,
735 FramebufferAttachment::kDefaultNumViews, FramebufferAttachment::kDefaultBaseViewIndex,
Mingyu Hu7e44ec22019-08-26 15:59:48 -0700736 false, FramebufferAttachment::kDefaultRenderToTextureSamples);
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600737 mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
738}
739
Jamie Madille90d4ee2018-11-28 14:04:00 -0500740void Framebuffer::setLabel(const Context *context, const std::string &label)
Geoff Lang70d0f492015-12-10 17:45:46 -0500741{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400742 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -0500743}
744
745const std::string &Framebuffer::getLabel() const
746{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400747 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -0500748}
749
Jamie Madill2ab08ed2019-08-12 16:20:21 -0400750bool Framebuffer::detachTexture(const Context *context, TextureID textureId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000751{
Jamie Madill2ab08ed2019-08-12 16:20:21 -0400752 return detachResourceById(context, GL_TEXTURE, textureId.value);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000753}
754
Jamie Madill7c7dec02019-08-06 17:44:11 -0400755bool Framebuffer::detachRenderbuffer(const Context *context, RenderbufferID renderbufferId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000756{
Jamie Madill7c7dec02019-08-06 17:44:11 -0400757 return detachResourceById(context, GL_RENDERBUFFER, renderbufferId.value);
Jamie Madilld1405e52015-03-05 15:41:39 -0500758}
Jamie Madille261b442014-06-25 12:42:21 -0400759
Jamie Madill8693bdb2017-09-02 15:32:14 -0400760bool Framebuffer::detachResourceById(const Context *context, GLenum resourceType, GLuint resourceId)
Jamie Madilld1405e52015-03-05 15:41:39 -0500761{
Jamie Madill8693bdb2017-09-02 15:32:14 -0400762 bool found = false;
763
Jamie Madill362876b2016-06-16 14:46:59 -0400764 for (size_t colorIndex = 0; colorIndex < mState.mColorAttachments.size(); ++colorIndex)
Jamie Madilld1405e52015-03-05 15:41:39 -0500765 {
Jamie Madill8693bdb2017-09-02 15:32:14 -0400766 if (detachMatchingAttachment(context, &mState.mColorAttachments[colorIndex], resourceType,
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300767 resourceId))
Jamie Madill8693bdb2017-09-02 15:32:14 -0400768 {
769 found = true;
770 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000771 }
772
Jamie Madilla02315b2017-02-23 14:14:47 -0500773 if (context->isWebGL1())
774 {
775 const std::array<FramebufferAttachment *, 3> attachments = {
776 {&mState.mWebGLDepthStencilAttachment, &mState.mWebGLDepthAttachment,
777 &mState.mWebGLStencilAttachment}};
778 for (FramebufferAttachment *attachment : attachments)
779 {
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300780 if (detachMatchingAttachment(context, attachment, resourceType, resourceId))
Jamie Madilla02315b2017-02-23 14:14:47 -0500781 {
Jamie Madill8693bdb2017-09-02 15:32:14 -0400782 found = true;
Jamie Madilla02315b2017-02-23 14:14:47 -0500783 }
784 }
785 }
786 else
787 {
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300788 if (detachMatchingAttachment(context, &mState.mDepthAttachment, resourceType, resourceId))
Jamie Madill8693bdb2017-09-02 15:32:14 -0400789 {
790 found = true;
791 }
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300792 if (detachMatchingAttachment(context, &mState.mStencilAttachment, resourceType, resourceId))
Jamie Madill8693bdb2017-09-02 15:32:14 -0400793 {
794 found = true;
795 }
Jamie Madilla02315b2017-02-23 14:14:47 -0500796 }
Jamie Madill8693bdb2017-09-02 15:32:14 -0400797
798 return found;
Jamie Madill362876b2016-06-16 14:46:59 -0400799}
800
Jamie Madill8693bdb2017-09-02 15:32:14 -0400801bool Framebuffer::detachMatchingAttachment(const Context *context,
Jamie Madill4928b7c2017-06-20 12:57:39 -0400802 FramebufferAttachment *attachment,
Jamie Madill362876b2016-06-16 14:46:59 -0400803 GLenum matchType,
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300804 GLuint matchId)
Jamie Madill362876b2016-06-16 14:46:59 -0400805{
806 if (attachment->isAttached() && attachment->type() == matchType && attachment->id() == matchId)
807 {
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300808 // We go through resetAttachment to make sure that all the required bookkeeping will be done
809 // such as updating enabled draw buffer state.
810 resetAttachment(context, attachment->getBinding());
Jamie Madill8693bdb2017-09-02 15:32:14 -0400811 return true;
Jamie Madill362876b2016-06-16 14:46:59 -0400812 }
Jamie Madill8693bdb2017-09-02 15:32:14 -0400813
814 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000815}
816
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400817const FramebufferAttachment *Framebuffer::getColorAttachment(size_t colorAttachment) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000818{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400819 return mState.getColorAttachment(colorAttachment);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000820}
821
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400822const FramebufferAttachment *Framebuffer::getDepthAttachment() const
Geoff Lang646559f2013-08-15 11:08:15 -0400823{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400824 return mState.getDepthAttachment();
Geoff Lang646559f2013-08-15 11:08:15 -0400825}
826
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400827const FramebufferAttachment *Framebuffer::getStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400828{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400829 return mState.getStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400830}
831
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400832const FramebufferAttachment *Framebuffer::getDepthStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400833{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400834 return mState.getDepthStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400835}
836
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400837const FramebufferAttachment *Framebuffer::getDepthOrStencilAttachment() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000838{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400839 return mState.getDepthOrStencilAttachment();
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000840}
841
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500842const FramebufferAttachment *Framebuffer::getStencilOrDepthStencilAttachment() const
843{
844 return mState.getStencilOrDepthStencilAttachment();
845}
846
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400847const FramebufferAttachment *Framebuffer::getReadColorAttachment() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000848{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400849 return mState.getReadAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000850}
851
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400852GLenum Framebuffer::getReadColorAttachmentType() const
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000853{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400854 const FramebufferAttachment *readAttachment = mState.getReadAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400855 return (readAttachment != nullptr ? readAttachment->type() : GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000856}
857
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400858const FramebufferAttachment *Framebuffer::getFirstColorAttachment() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000859{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400860 return mState.getFirstColorAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000861}
862
Jamie Madill6dd06ea2017-07-19 13:47:55 -0400863const FramebufferAttachment *Framebuffer::getFirstNonNullAttachment() const
864{
865 return mState.getFirstNonNullAttachment();
866}
867
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800868const FramebufferAttachment *Framebuffer::getAttachment(const Context *context,
869 GLenum attachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000870{
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800871 return mState.getAttachment(context, attachment);
Geoff Lang55ba29c2013-07-11 16:57:53 -0400872}
873
Geoff Langa15472a2015-08-11 11:48:03 -0400874size_t Framebuffer::getDrawbufferStateCount() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000875{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400876 return mState.mDrawBufferStates.size();
Geoff Langa15472a2015-08-11 11:48:03 -0400877}
878
879GLenum Framebuffer::getDrawBufferState(size_t drawBuffer) const
880{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400881 ASSERT(drawBuffer < mState.mDrawBufferStates.size());
882 return mState.mDrawBufferStates[drawBuffer];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000883}
884
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500885const std::vector<GLenum> &Framebuffer::getDrawBufferStates() const
886{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400887 return mState.getDrawBufferStates();
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500888}
889
Geoff Lang164d54e2014-12-01 10:55:33 -0500890void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000891{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400892 auto &drawStates = mState.mDrawBufferStates;
Jamie Madilld1405e52015-03-05 15:41:39 -0500893
894 ASSERT(count <= drawStates.size());
895 std::copy(buffers, buffers + count, drawStates.begin());
896 std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500897 mDirtyBits.set(DIRTY_BIT_DRAW_BUFFERS);
Jamie Madilla4595b82017-01-11 17:36:34 -0500898
899 mState.mEnabledDrawBuffers.reset();
Brandon Jones76746f92017-11-22 11:44:41 -0800900 mState.mDrawBufferTypeMask.reset();
901
Jamie Madilla4595b82017-01-11 17:36:34 -0500902 for (size_t index = 0; index < count; ++index)
903 {
Jamie Madill6e18a232019-01-16 13:27:14 -0500904 SetComponentTypeMask(getDrawbufferWriteType(index), index, &mState.mDrawBufferTypeMask);
Brandon Jones76746f92017-11-22 11:44:41 -0800905
Jamie Madilla4595b82017-01-11 17:36:34 -0500906 if (drawStates[index] != GL_NONE && mState.mColorAttachments[index].isAttached())
907 {
908 mState.mEnabledDrawBuffers.set(index);
909 }
910 }
Geoff Lang9dd95802014-12-01 11:12:59 -0500911}
912
Geoff Langa15472a2015-08-11 11:48:03 -0400913const FramebufferAttachment *Framebuffer::getDrawBuffer(size_t drawBuffer) const
914{
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400915 return mState.getDrawBuffer(drawBuffer);
Geoff Langa15472a2015-08-11 11:48:03 -0400916}
917
Jamie Madill6e18a232019-01-16 13:27:14 -0500918ComponentType Framebuffer::getDrawbufferWriteType(size_t drawBuffer) const
Geoff Lange0cff192017-05-30 13:04:56 -0400919{
920 const FramebufferAttachment *attachment = mState.getDrawBuffer(drawBuffer);
921 if (attachment == nullptr)
922 {
Jamie Madill6e18a232019-01-16 13:27:14 -0500923 return ComponentType::NoType;
Geoff Lange0cff192017-05-30 13:04:56 -0400924 }
925
926 GLenum componentType = attachment->getFormat().info->componentType;
927 switch (componentType)
928 {
929 case GL_INT:
Jamie Madill6e18a232019-01-16 13:27:14 -0500930 return ComponentType::Int;
Geoff Lange0cff192017-05-30 13:04:56 -0400931 case GL_UNSIGNED_INT:
Jamie Madill6e18a232019-01-16 13:27:14 -0500932 return ComponentType::UnsignedInt;
Geoff Lange0cff192017-05-30 13:04:56 -0400933
934 default:
Jamie Madill6e18a232019-01-16 13:27:14 -0500935 return ComponentType::Float;
Geoff Lange0cff192017-05-30 13:04:56 -0400936 }
937}
938
Brandon Jonesc405ae72017-12-06 14:15:03 -0800939ComponentTypeMask Framebuffer::getDrawBufferTypeMask() const
Brandon Jones76746f92017-11-22 11:44:41 -0800940{
941 return mState.mDrawBufferTypeMask;
942}
943
944DrawBufferMask Framebuffer::getDrawBufferMask() const
945{
946 return mState.mEnabledDrawBuffers;
947}
948
Geoff Langa15472a2015-08-11 11:48:03 -0400949bool Framebuffer::hasEnabledDrawBuffer() const
950{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400951 for (size_t drawbufferIdx = 0; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
Geoff Langa15472a2015-08-11 11:48:03 -0400952 {
953 if (getDrawBuffer(drawbufferIdx) != nullptr)
954 {
955 return true;
956 }
957 }
958
959 return false;
960}
961
Geoff Lang9dd95802014-12-01 11:12:59 -0500962GLenum Framebuffer::getReadBufferState() const
963{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400964 return mState.mReadBufferState;
Geoff Lang9dd95802014-12-01 11:12:59 -0500965}
966
967void Framebuffer::setReadBuffer(GLenum buffer)
968{
Jamie Madillb885e572015-02-03 16:16:04 -0500969 ASSERT(buffer == GL_BACK || buffer == GL_NONE ||
970 (buffer >= GL_COLOR_ATTACHMENT0 &&
Jamie Madill48ef11b2016-04-27 15:21:52 -0400971 (buffer - GL_COLOR_ATTACHMENT0) < mState.mColorAttachments.size()));
972 mState.mReadBufferState = buffer;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500973 mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000974}
975
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400976size_t Framebuffer::getNumColorAttachments() const
Corentin Wallez37c39792015-08-20 14:19:46 -0400977{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400978 return mState.mColorAttachments.size();
Corentin Wallez37c39792015-08-20 14:19:46 -0400979}
980
Jamie Madill0df8fe42015-11-24 16:10:24 -0500981bool Framebuffer::hasDepth() const
982{
Jamie Madill9c335862017-07-18 11:51:38 -0400983 return mState.hasDepth();
Jamie Madill0df8fe42015-11-24 16:10:24 -0500984}
985
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000986bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000987{
Jamie Madill9c335862017-07-18 11:51:38 -0400988 return mState.hasStencil();
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000989}
990
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000991bool Framebuffer::usingExtendedDrawBuffers() const
992{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400993 for (size_t drawbufferIdx = 1; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000994 {
Geoff Langa15472a2015-08-11 11:48:03 -0400995 if (getDrawBuffer(drawbufferIdx) != nullptr)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000996 {
997 return true;
998 }
999 }
1000
1001 return false;
1002}
1003
Jamie Madill124f78c2019-06-18 11:48:24 -04001004void Framebuffer::invalidateCompletenessCache()
Geoff Lang9aded172017-04-05 11:07:56 -04001005{
Tim Van Patten56ba54c2019-08-08 13:03:34 -06001006 if (!isDefault())
Geoff Lang9aded172017-04-05 11:07:56 -04001007 {
1008 mCachedStatus.reset();
1009 }
Jamie Madill124f78c2019-06-18 11:48:24 -04001010 onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
Geoff Lang9aded172017-04-05 11:07:56 -04001011}
1012
Jamie Madillcc73f242018-08-01 11:34:48 -04001013GLenum Framebuffer::checkStatusImpl(const Context *context)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001014{
Jamie Madillcc73f242018-08-01 11:34:48 -04001015 ASSERT(!isDefault());
1016 ASSERT(hasAnyDirtyBit() || !mCachedStatus.valid());
Geoff Lang528ce3c2014-12-01 10:44:07 -05001017
Jamie Madillcc73f242018-08-01 11:34:48 -04001018 mCachedStatus = checkStatusWithGLFrontEnd(context);
Jamie Madille98b1b52018-03-08 09:47:23 -05001019
Jamie Madillcc73f242018-08-01 11:34:48 -04001020 if (mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE)
1021 {
Jamie Madill67220092019-05-20 11:12:53 -04001022 // We can skip syncState on several back-ends.
1023 if (mImpl->shouldSyncStateBeforeCheckStatus())
Jamie Madille98b1b52018-03-08 09:47:23 -05001024 {
Jamie Madill67220092019-05-20 11:12:53 -04001025 angle::Result err = syncState(context);
1026 if (err != angle::Result::Continue)
1027 {
1028 return 0;
1029 }
Jamie Madillcc73f242018-08-01 11:34:48 -04001030 }
Jamie Madill67220092019-05-20 11:12:53 -04001031
Jamie Madillcc73f242018-08-01 11:34:48 -04001032 if (!mImpl->checkStatus(context))
1033 {
1034 mCachedStatus = GL_FRAMEBUFFER_UNSUPPORTED;
Jamie Madille98b1b52018-03-08 09:47:23 -05001035 }
Jamie Madill362876b2016-06-16 14:46:59 -04001036 }
1037
Jamie Madill427064d2018-04-13 16:20:34 -04001038 return mCachedStatus.value();
Jamie Madill362876b2016-06-16 14:46:59 -04001039}
1040
Jamie Madille98b1b52018-03-08 09:47:23 -05001041GLenum Framebuffer::checkStatusWithGLFrontEnd(const Context *context)
Jamie Madill362876b2016-06-16 14:46:59 -04001042{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001043 const State &state = context->getState();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001044
Tim Van Patten56ba54c2019-08-08 13:03:34 -06001045 ASSERT(!isDefault());
Jamie Madill362876b2016-06-16 14:46:59 -04001046
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001047 bool hasAttachments = false;
1048 Optional<unsigned int> colorbufferSize;
1049 Optional<int> samples;
Geoff Lang92019432017-11-20 13:09:34 -05001050 Optional<bool> fixedSampleLocations;
JiangYizhou461d9a32017-01-04 16:37:26 +08001051 bool hasRenderbuffer = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001052
Martin Radev9bc9a322017-07-21 14:28:17 +03001053 const FramebufferAttachment *firstAttachment = getFirstNonNullAttachment();
1054
Jiawei Shaoa8802472018-05-28 11:17:47 +08001055 Optional<bool> isLayered;
1056 Optional<TextureType> colorAttachmentsTextureType;
1057
Jamie Madill48ef11b2016-04-27 15:21:52 -04001058 for (const FramebufferAttachment &colorAttachment : mState.mColorAttachments)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001059 {
Jamie Madill2d06b732015-04-20 12:53:28 -04001060 if (colorAttachment.isAttached())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001061 {
Geoff Lang9f10b772017-05-16 15:51:03 -04001062 if (!CheckAttachmentCompleteness(context, colorAttachment))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001063 {
1064 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1065 }
daniel@transgaming.com01868132010-08-24 19:21:17 +00001066
Geoff Lang677bb6f2017-04-05 12:40:40 -04001067 const InternalFormat &format = *colorAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -04001068 if (format.depthBits > 0 || format.stencilBits > 0)
1069 {
1070 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1071 }
1072
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001073 if (!CheckAttachmentSampleCompleteness(context, colorAttachment, true, &samples,
1074 &fixedSampleLocations))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001075 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001076 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001077 }
1078
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001079 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
1080 // in GLES 3.0, there is no such restriction
1081 if (state.getClientMajorVersion() < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001082 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001083 if (colorbufferSize.valid())
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001084 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001085 if (format.pixelBytes != colorbufferSize.value())
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +00001086 {
1087 return GL_FRAMEBUFFER_UNSUPPORTED;
1088 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001089 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001090 else
1091 {
1092 colorbufferSize = format.pixelBytes;
1093 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001094 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001095
Martin Radev9bc9a322017-07-21 14:28:17 +03001096 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &colorAttachment))
1097 {
Mingyu Hu7d64c482019-03-12 14:27:40 -07001098 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR;
Martin Radev9bc9a322017-07-21 14:28:17 +03001099 }
1100
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001101 hasRenderbuffer = hasRenderbuffer || (colorAttachment.type() == GL_RENDERBUFFER);
Jiawei Shaoa8802472018-05-28 11:17:47 +08001102
1103 if (!hasAttachments)
1104 {
1105 isLayered = colorAttachment.isLayered();
1106 if (isLayered.value())
1107 {
1108 colorAttachmentsTextureType = colorAttachment.getTextureImageIndex().getType();
1109 }
1110 hasAttachments = true;
1111 }
1112 else
1113 {
1114 // [EXT_geometry_shader] section 9.4.1, "Framebuffer Completeness"
1115 // If any framebuffer attachment is layered, all populated attachments
1116 // must be layered. Additionally, all populated color attachments must
1117 // be from textures of the same target. {FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT }
1118 ASSERT(isLayered.valid());
1119 if (isLayered.value() != colorAttachment.isLayered())
1120 {
1121 return GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT;
1122 }
1123 else if (isLayered.value())
1124 {
1125 ASSERT(colorAttachmentsTextureType.valid());
1126 if (colorAttachmentsTextureType.value() !=
1127 colorAttachment.getTextureImageIndex().getType())
1128 {
1129 return GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT;
1130 }
1131 }
1132 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001133 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001134 }
1135
Jamie Madill48ef11b2016-04-27 15:21:52 -04001136 const FramebufferAttachment &depthAttachment = mState.mDepthAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -04001137 if (depthAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001138 {
Geoff Lang9f10b772017-05-16 15:51:03 -04001139 if (!CheckAttachmentCompleteness(context, depthAttachment))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001140 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001141 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001142 }
1143
Geoff Lang677bb6f2017-04-05 12:40:40 -04001144 const InternalFormat &format = *depthAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -04001145 if (format.depthBits == 0)
1146 {
1147 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001148 }
1149
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001150 if (!CheckAttachmentSampleCompleteness(context, depthAttachment, false, &samples,
1151 &fixedSampleLocations))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001152 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001153 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001154 }
Sami Väisänena797e062016-05-12 15:23:40 +03001155
Martin Radev9bc9a322017-07-21 14:28:17 +03001156 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &depthAttachment))
1157 {
Mingyu Hu7d64c482019-03-12 14:27:40 -07001158 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR;
Martin Radev9bc9a322017-07-21 14:28:17 +03001159 }
1160
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001161 hasRenderbuffer = hasRenderbuffer || (depthAttachment.type() == GL_RENDERBUFFER);
Jiawei Shaoa8802472018-05-28 11:17:47 +08001162
1163 if (!hasAttachments)
1164 {
1165 isLayered = depthAttachment.isLayered();
1166 hasAttachments = true;
1167 }
1168 else
1169 {
1170 // [EXT_geometry_shader] section 9.4.1, "Framebuffer Completeness"
1171 // If any framebuffer attachment is layered, all populated attachments
1172 // must be layered. {FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT }
1173 ASSERT(isLayered.valid());
1174 if (isLayered.value() != depthAttachment.isLayered())
1175 {
1176 return GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT;
1177 }
1178 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001179 }
1180
Jamie Madill48ef11b2016-04-27 15:21:52 -04001181 const FramebufferAttachment &stencilAttachment = mState.mStencilAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -04001182 if (stencilAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001183 {
Geoff Lang9f10b772017-05-16 15:51:03 -04001184 if (!CheckAttachmentCompleteness(context, stencilAttachment))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001185 {
1186 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1187 }
1188
Geoff Lang677bb6f2017-04-05 12:40:40 -04001189 const InternalFormat &format = *stencilAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -04001190 if (format.stencilBits == 0)
1191 {
1192 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001193 }
1194
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001195 if (!CheckAttachmentSampleCompleteness(context, stencilAttachment, false, &samples,
1196 &fixedSampleLocations))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001197 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001198 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001199 }
Corentin Wallez086d59a2016-04-29 09:06:49 -04001200
Martin Radev9bc9a322017-07-21 14:28:17 +03001201 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &stencilAttachment))
1202 {
Mingyu Hu7d64c482019-03-12 14:27:40 -07001203 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR;
Martin Radev9bc9a322017-07-21 14:28:17 +03001204 }
1205
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001206 hasRenderbuffer = hasRenderbuffer || (stencilAttachment.type() == GL_RENDERBUFFER);
Jiawei Shaoa8802472018-05-28 11:17:47 +08001207
1208 if (!hasAttachments)
1209 {
1210 hasAttachments = true;
1211 }
1212 else
1213 {
1214 // [EXT_geometry_shader] section 9.4.1, "Framebuffer Completeness"
1215 // If any framebuffer attachment is layered, all populated attachments
1216 // must be layered.
1217 // {FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT }
1218 ASSERT(isLayered.valid());
1219 if (isLayered.value() != stencilAttachment.isLayered())
1220 {
1221 return GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT;
1222 }
1223 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001224 }
1225
1226 // Starting from ES 3.0 stencil and depth, if present, should be the same image
1227 if (state.getClientMajorVersion() >= 3 && depthAttachment.isAttached() &&
1228 stencilAttachment.isAttached() && stencilAttachment != depthAttachment)
1229 {
1230 return GL_FRAMEBUFFER_UNSUPPORTED;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001231 }
1232
Jamie Madilla02315b2017-02-23 14:14:47 -05001233 // Special additional validation for WebGL 1 DEPTH/STENCIL/DEPTH_STENCIL.
1234 if (state.isWebGL1())
1235 {
1236 if (!mState.mWebGLDepthStencilConsistent)
1237 {
1238 return GL_FRAMEBUFFER_UNSUPPORTED;
1239 }
1240
1241 if (mState.mWebGLDepthStencilAttachment.isAttached())
1242 {
1243 if (mState.mWebGLDepthStencilAttachment.getDepthSize() == 0 ||
1244 mState.mWebGLDepthStencilAttachment.getStencilSize() == 0)
1245 {
1246 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1247 }
Martin Radev9bc9a322017-07-21 14:28:17 +03001248
1249 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment,
1250 &mState.mWebGLDepthStencilAttachment))
1251 {
Mingyu Hu7d64c482019-03-12 14:27:40 -07001252 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR;
Martin Radev9bc9a322017-07-21 14:28:17 +03001253 }
Jamie Madilla02315b2017-02-23 14:14:47 -05001254 }
1255 else if (mState.mStencilAttachment.isAttached() &&
1256 mState.mStencilAttachment.getDepthSize() > 0)
1257 {
1258 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1259 }
1260 else if (mState.mDepthAttachment.isAttached() &&
1261 mState.mDepthAttachment.getStencilSize() > 0)
1262 {
1263 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1264 }
1265 }
1266
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001267 // ES3.1(section 9.4) requires that if no image is attached to the framebuffer, and either the
1268 // value of the framebuffer's FRAMEBUFFER_DEFAULT_WIDTH or FRAMEBUFFER_DEFAULT_HEIGHT parameters
1269 // is zero, the framebuffer is considered incomplete.
JiangYizhou461d9a32017-01-04 16:37:26 +08001270 GLint defaultWidth = mState.getDefaultWidth();
1271 GLint defaultHeight = mState.getDefaultHeight();
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001272 if (!hasAttachments && (defaultWidth == 0 || defaultHeight == 0))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001273 {
1274 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001275 }
1276
Geoff Langa0e0aeb2017-04-12 15:06:29 -04001277 // In ES 2.0 and WebGL, all color attachments must have the same width and height.
Jamie Madillcc86d642015-11-24 13:00:07 -05001278 // In ES 3.0, there is no such restriction.
Geoff Langa0e0aeb2017-04-12 15:06:29 -04001279 if ((state.getClientMajorVersion() < 3 || state.getExtensions().webglCompatibility) &&
1280 !mState.attachmentsHaveSameDimensions())
Jamie Madillcc86d642015-11-24 13:00:07 -05001281 {
1282 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
1283 }
1284
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001285 // ES3.1(section 9.4) requires that if the attached images are a mix of renderbuffers and
1286 // textures, the value of TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all attached textures.
JiangYizhou461d9a32017-01-04 16:37:26 +08001287 if (fixedSampleLocations.valid() && hasRenderbuffer && !fixedSampleLocations.value())
1288 {
1289 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1290 }
1291
Kenneth Russellce8602a2017-10-03 18:23:08 -07001292 // The WebGL conformance tests implicitly define that all framebuffer
1293 // attachments must be unique. For example, the same level of a texture can
1294 // not be attached to two different color attachments.
1295 if (state.getExtensions().webglCompatibility)
1296 {
1297 if (!mState.colorAttachmentsAreUniqueImages())
1298 {
1299 return GL_FRAMEBUFFER_UNSUPPORTED;
1300 }
1301 }
1302
Jamie Madillcc86d642015-11-24 13:00:07 -05001303 return GL_FRAMEBUFFER_COMPLETE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001304}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001305
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001306angle::Result Framebuffer::discard(const Context *context, size_t count, const GLenum *attachments)
Austin Kinross08332632015-05-05 13:35:47 -07001307{
Jamie Madill05b35b22017-10-03 09:01:44 -04001308 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1309 // can be no-ops, so we should probably do that to ensure consistency.
1310 // TODO(jmadill): WebGL behaviour, and robust resource init behaviour without WebGL.
1311
Jamie Madill4928b7c2017-06-20 12:57:39 -04001312 return mImpl->discard(context, count, attachments);
Austin Kinross08332632015-05-05 13:35:47 -07001313}
1314
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001315angle::Result Framebuffer::invalidate(const Context *context,
1316 size_t count,
1317 const GLenum *attachments)
Jamie Madill2d96b9e2014-08-29 15:46:47 -04001318{
Jamie Madill05b35b22017-10-03 09:01:44 -04001319 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1320 // can be no-ops, so we should probably do that to ensure consistency.
1321 // TODO(jmadill): WebGL behaviour, and robust resource init behaviour without WebGL.
1322
Jamie Madill4928b7c2017-06-20 12:57:39 -04001323 return mImpl->invalidate(context, count, attachments);
Jamie Madill2d96b9e2014-08-29 15:46:47 -04001324}
1325
Jamie Madill05b35b22017-10-03 09:01:44 -04001326bool Framebuffer::partialClearNeedsInit(const Context *context,
1327 bool color,
1328 bool depth,
1329 bool stencil)
1330{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001331 const auto &glState = context->getState();
Jamie Madill05b35b22017-10-03 09:01:44 -04001332
1333 if (!glState.isRobustResourceInitEnabled())
1334 {
1335 return false;
1336 }
1337
1338 // Scissors can affect clearing.
1339 // TODO(jmadill): Check for complete scissor overlap.
1340 if (glState.isScissorTestEnabled())
1341 {
1342 return true;
1343 }
1344
1345 // If colors masked, we must clear before we clear. Do a simple check.
1346 // TODO(jmadill): Filter out unused color channels from the test.
1347 if (color)
1348 {
1349 const auto &blend = glState.getBlendState();
1350 if (!(blend.colorMaskRed && blend.colorMaskGreen && blend.colorMaskBlue &&
1351 blend.colorMaskAlpha))
1352 {
1353 return true;
1354 }
1355 }
1356
1357 const auto &depthStencil = glState.getDepthStencilState();
Yuly Novikov21edf3d2018-07-23 16:44:16 -04001358 if (stencil && (depthStencil.stencilMask != depthStencil.stencilWritemask ||
1359 depthStencil.stencilBackMask != depthStencil.stencilBackWritemask))
Jamie Madill05b35b22017-10-03 09:01:44 -04001360 {
1361 return true;
1362 }
1363
1364 return false;
1365}
1366
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001367angle::Result Framebuffer::invalidateSub(const Context *context,
1368 size_t count,
1369 const GLenum *attachments,
1370 const Rectangle &area)
Jamie Madill400a4412014-08-29 15:46:45 -04001371{
Jamie Madill05b35b22017-10-03 09:01:44 -04001372 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1373 // can be no-ops, so we should probably do that to ensure consistency.
1374 // TODO(jmadill): Make a invalidate no-op in WebGL 2.0.
1375
Jamie Madill4928b7c2017-06-20 12:57:39 -04001376 return mImpl->invalidateSub(context, count, attachments, area);
Jamie Madill400a4412014-08-29 15:46:45 -04001377}
1378
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001379angle::Result Framebuffer::clear(const Context *context, GLbitfield mask)
Geoff Langb04dc822014-12-01 12:02:02 -05001380{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001381 const auto &glState = context->getState();
Jamie Madill05b35b22017-10-03 09:01:44 -04001382 if (glState.isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -05001383 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001384 return angle::Result::Continue;
Jamie Madill984ef412015-11-24 16:10:21 -05001385 }
1386
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -04001387 // Remove clear bits that are ineffective. An effective clear changes at least one fragment. If
1388 // color/depth/stencil masks make the clear ineffective we skip it altogether.
1389
1390 // If all color channels are masked, don't attempt to clear color.
1391 if (context->getState().getBlendState().allChannelsMasked())
1392 {
1393 mask &= ~GL_COLOR_BUFFER_BIT;
1394 }
1395
1396 // If depth write is disabled, don't attempt to clear depth.
1397 if (!context->getState().getDepthStencilState().depthMask)
1398 {
1399 mask &= ~GL_DEPTH_BUFFER_BIT;
1400 }
1401
1402 // If all stencil bits are masked, don't attempt to clear stencil.
1403 if (context->getState().getDepthStencilState().stencilWritemask == 0)
1404 {
1405 mask &= ~GL_STENCIL_BUFFER_BIT;
1406 }
1407
1408 if (mask != 0)
1409 {
1410 ANGLE_TRY(mImpl->clear(context, mask));
1411 }
Jamie Madill05b35b22017-10-03 09:01:44 -04001412
Jamie Madill7c985f52018-11-29 18:16:17 -05001413 return angle::Result::Continue;
Geoff Langb04dc822014-12-01 12:02:02 -05001414}
1415
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001416angle::Result Framebuffer::clearBufferfv(const Context *context,
1417 GLenum buffer,
1418 GLint drawbuffer,
1419 const GLfloat *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001420{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001421 if (context->getState().isRasterizerDiscardEnabled() || IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001422 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001423 return angle::Result::Continue;
Jamie Madill984ef412015-11-24 16:10:21 -05001424 }
1425
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -04001426 if (buffer == GL_DEPTH)
1427 {
1428 // If depth write is disabled, don't attempt to clear depth.
1429 if (!context->getState().getDepthStencilState().depthMask)
1430 {
1431 return angle::Result::Continue;
1432 }
1433 }
1434 else
1435 {
1436 // If all color channels are masked, don't attempt to clear color.
1437 if (context->getState().getBlendState().allChannelsMasked())
1438 {
1439 return angle::Result::Continue;
1440 }
1441 }
1442
Jamie Madill05b35b22017-10-03 09:01:44 -04001443 ANGLE_TRY(mImpl->clearBufferfv(context, buffer, drawbuffer, values));
1444
Jamie Madill7c985f52018-11-29 18:16:17 -05001445 return angle::Result::Continue;
Geoff Langb04dc822014-12-01 12:02:02 -05001446}
1447
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001448angle::Result Framebuffer::clearBufferuiv(const Context *context,
1449 GLenum buffer,
1450 GLint drawbuffer,
1451 const GLuint *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001452{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001453 if (context->getState().isRasterizerDiscardEnabled() || IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001454 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001455 return angle::Result::Continue;
Jamie Madill984ef412015-11-24 16:10:21 -05001456 }
1457
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -04001458 // If all color channels are masked, don't attempt to clear color.
1459 if (context->getState().getBlendState().allChannelsMasked())
1460 {
1461 return angle::Result::Continue;
1462 }
1463
Jamie Madill05b35b22017-10-03 09:01:44 -04001464 ANGLE_TRY(mImpl->clearBufferuiv(context, buffer, drawbuffer, values));
1465
Jamie Madill7c985f52018-11-29 18:16:17 -05001466 return angle::Result::Continue;
Geoff Langb04dc822014-12-01 12:02:02 -05001467}
1468
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001469angle::Result Framebuffer::clearBufferiv(const Context *context,
1470 GLenum buffer,
1471 GLint drawbuffer,
1472 const GLint *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001473{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001474 if (context->getState().isRasterizerDiscardEnabled() || IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001475 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001476 return angle::Result::Continue;
Jamie Madill984ef412015-11-24 16:10:21 -05001477 }
1478
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -04001479 if (buffer == GL_STENCIL)
1480 {
1481 // If all stencil bits are masked, don't attempt to clear stencil.
1482 if (context->getState().getDepthStencilState().stencilWritemask == 0)
1483 {
1484 return angle::Result::Continue;
1485 }
1486 }
1487 else
1488 {
1489 // If all color channels are masked, don't attempt to clear color.
1490 if (context->getState().getBlendState().allChannelsMasked())
1491 {
1492 return angle::Result::Continue;
1493 }
1494 }
1495
Jamie Madill05b35b22017-10-03 09:01:44 -04001496 ANGLE_TRY(mImpl->clearBufferiv(context, buffer, drawbuffer, values));
1497
Jamie Madill7c985f52018-11-29 18:16:17 -05001498 return angle::Result::Continue;
Geoff Langb04dc822014-12-01 12:02:02 -05001499}
1500
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001501angle::Result Framebuffer::clearBufferfi(const Context *context,
1502 GLenum buffer,
1503 GLint drawbuffer,
1504 GLfloat depth,
1505 GLint stencil)
Geoff Langb04dc822014-12-01 12:02:02 -05001506{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001507 if (context->getState().isRasterizerDiscardEnabled() || IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001508 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001509 return angle::Result::Continue;
Jamie Madill984ef412015-11-24 16:10:21 -05001510 }
1511
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -04001512 bool clearDepth = context->getState().getDepthStencilState().depthMask;
1513 bool clearStencil = context->getState().getDepthStencilState().stencilWritemask != 0;
1514
1515 if (clearDepth && clearStencil)
1516 {
1517 ASSERT(buffer == GL_DEPTH_STENCIL);
1518 ANGLE_TRY(mImpl->clearBufferfi(context, GL_DEPTH_STENCIL, drawbuffer, depth, stencil));
1519 }
1520 else if (clearDepth && !clearStencil)
1521 {
1522 ANGLE_TRY(mImpl->clearBufferfv(context, GL_DEPTH, drawbuffer, &depth));
1523 }
1524 else if (!clearDepth && clearStencil)
1525 {
1526 ANGLE_TRY(mImpl->clearBufferiv(context, GL_STENCIL, drawbuffer, &stencil));
1527 }
Jamie Madill05b35b22017-10-03 09:01:44 -04001528
Jamie Madill7c985f52018-11-29 18:16:17 -05001529 return angle::Result::Continue;
Geoff Langb04dc822014-12-01 12:02:02 -05001530}
1531
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001532angle::Result Framebuffer::getImplementationColorReadFormat(const Context *context,
1533 GLenum *formatOut)
Geoff Langbce529e2014-12-01 12:48:41 -05001534{
Jamie Madill690c8eb2018-03-12 15:20:03 -04001535 ANGLE_TRY(syncState(context));
1536 *formatOut = mImpl->getImplementationColorReadFormat(context);
Jamie Madill7c985f52018-11-29 18:16:17 -05001537 return angle::Result::Continue;
Geoff Langbce529e2014-12-01 12:48:41 -05001538}
1539
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001540angle::Result Framebuffer::getImplementationColorReadType(const Context *context, GLenum *typeOut)
Geoff Langbce529e2014-12-01 12:48:41 -05001541{
Jamie Madill690c8eb2018-03-12 15:20:03 -04001542 ANGLE_TRY(syncState(context));
1543 *typeOut = mImpl->getImplementationColorReadType(context);
Jamie Madill7c985f52018-11-29 18:16:17 -05001544 return angle::Result::Continue;
Geoff Langbce529e2014-12-01 12:48:41 -05001545}
1546
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001547angle::Result Framebuffer::readPixels(const Context *context,
1548 const Rectangle &area,
1549 GLenum format,
1550 GLenum type,
1551 void *pixels)
Geoff Langbce529e2014-12-01 12:48:41 -05001552{
Jamie Madill362876b2016-06-16 14:46:59 -04001553 ANGLE_TRY(mImpl->readPixels(context, area, format, type, pixels));
Geoff Lang520c4ae2015-05-05 13:12:36 -04001554
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001555 Buffer *unpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Lang520c4ae2015-05-05 13:12:36 -04001556 if (unpackBuffer)
1557 {
James Dong020abb82019-07-24 11:33:49 -06001558 unpackBuffer->onDataChanged();
Geoff Lang520c4ae2015-05-05 13:12:36 -04001559 }
1560
Jamie Madill7c985f52018-11-29 18:16:17 -05001561 return angle::Result::Continue;
Geoff Langbce529e2014-12-01 12:48:41 -05001562}
1563
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001564angle::Result Framebuffer::blit(const Context *context,
1565 const Rectangle &sourceArea,
1566 const Rectangle &destArea,
1567 GLbitfield mask,
1568 GLenum filter)
Geoff Lang54bd5a42014-12-01 12:51:04 -05001569{
He Yunchao6be602d2016-12-22 14:33:07 +08001570 GLbitfield blitMask = mask;
1571
1572 // Note that blitting is called against draw framebuffer.
1573 // See the code in gl::Context::blitFramebuffer.
1574 if ((mask & GL_COLOR_BUFFER_BIT) && !hasEnabledDrawBuffer())
1575 {
1576 blitMask &= ~GL_COLOR_BUFFER_BIT;
1577 }
1578
1579 if ((mask & GL_STENCIL_BUFFER_BIT) && mState.getStencilAttachment() == nullptr)
1580 {
1581 blitMask &= ~GL_STENCIL_BUFFER_BIT;
1582 }
1583
1584 if ((mask & GL_DEPTH_BUFFER_BIT) && mState.getDepthAttachment() == nullptr)
1585 {
1586 blitMask &= ~GL_DEPTH_BUFFER_BIT;
1587 }
1588
1589 if (!blitMask)
1590 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001591 return angle::Result::Continue;
He Yunchao6be602d2016-12-22 14:33:07 +08001592 }
1593
1594 return mImpl->blit(context, sourceArea, destArea, blitMask, filter);
Geoff Lang54bd5a42014-12-01 12:51:04 -05001595}
1596
Jamie Madill427064d2018-04-13 16:20:34 -04001597int Framebuffer::getSamples(const Context *context)
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001598{
Jamie Madill427064d2018-04-13 16:20:34 -04001599 return (isComplete(context) ? getCachedSamples(context) : 0);
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001600}
1601
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -04001602int Framebuffer::getCachedSamples(const Context *context) const
Jamie Madill9c335862017-07-18 11:51:38 -04001603{
Jamie Madill5b772312018-03-08 20:28:32 -05001604 ASSERT(mCachedStatus.valid() && mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE);
1605
Jamie Madill9c335862017-07-18 11:51:38 -04001606 // For a complete framebuffer, all attachments must have the same sample count.
1607 // In this case return the first nonzero sample size.
1608 const auto *firstNonNullAttachment = mState.getFirstNonNullAttachment();
1609 if (firstNonNullAttachment)
1610 {
1611 ASSERT(firstNonNullAttachment->isAttached());
1612 return firstNonNullAttachment->getSamples();
1613 }
1614
1615 // No attachments found.
1616 return 0;
1617}
1618
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001619angle::Result Framebuffer::getSamplePosition(const Context *context,
1620 size_t index,
1621 GLfloat *xy) const
Corentin Wallezccab69d2017-01-27 16:57:15 -05001622{
Geoff Lang13455072018-05-09 11:24:43 -04001623 ANGLE_TRY(mImpl->getSamplePosition(context, index, xy));
Jamie Madill7c985f52018-11-29 18:16:17 -05001624 return angle::Result::Continue;
Corentin Wallezccab69d2017-01-27 16:57:15 -05001625}
1626
Jamie Madille261b442014-06-25 12:42:21 -04001627bool Framebuffer::hasValidDepthStencil() const
1628{
Jamie Madill48ef11b2016-04-27 15:21:52 -04001629 return mState.getDepthStencilAttachment() != nullptr;
Jamie Madille261b442014-06-25 12:42:21 -04001630}
1631
Jamie Madilla02315b2017-02-23 14:14:47 -05001632void Framebuffer::setAttachment(const Context *context,
1633 GLenum type,
Jamie Madill2d06b732015-04-20 12:53:28 -04001634 GLenum binding,
1635 const ImageIndex &textureIndex,
1636 FramebufferAttachmentObject *resource)
Geoff Langab75a052014-10-15 12:56:37 -04001637{
Martin Radev5dae57b2017-07-14 16:15:55 +03001638 setAttachment(context, type, binding, textureIndex, resource,
1639 FramebufferAttachment::kDefaultNumViews,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001640 FramebufferAttachment::kDefaultBaseViewIndex, false,
1641 FramebufferAttachment::kDefaultRenderToTextureSamples);
Martin Radev5dae57b2017-07-14 16:15:55 +03001642}
1643
1644void Framebuffer::setAttachment(const Context *context,
1645 GLenum type,
1646 GLenum binding,
1647 const ImageIndex &textureIndex,
1648 FramebufferAttachmentObject *resource,
1649 GLsizei numViews,
1650 GLuint baseViewIndex,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001651 bool isMultiview,
1652 GLsizei samples)
Martin Radev5dae57b2017-07-14 16:15:55 +03001653{
Jamie Madilla02315b2017-02-23 14:14:47 -05001654 // Context may be null in unit tests.
1655 if (!context || !context->isWebGL1())
1656 {
Martin Radev5dae57b2017-07-14 16:15:55 +03001657 setAttachmentImpl(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001658 isMultiview, samples);
Jamie Madilla02315b2017-02-23 14:14:47 -05001659 return;
1660 }
1661
1662 switch (binding)
1663 {
1664 case GL_DEPTH_STENCIL:
1665 case GL_DEPTH_STENCIL_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001666 mState.mWebGLDepthStencilAttachment.attach(context, type, binding, textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001667 resource, numViews, baseViewIndex,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001668 isMultiview, samples);
Jamie Madilla02315b2017-02-23 14:14:47 -05001669 break;
1670 case GL_DEPTH:
1671 case GL_DEPTH_ATTACHMENT:
Martin Radev5dae57b2017-07-14 16:15:55 +03001672 mState.mWebGLDepthAttachment.attach(context, type, binding, textureIndex, resource,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001673 numViews, baseViewIndex, isMultiview, samples);
Jamie Madilla02315b2017-02-23 14:14:47 -05001674 break;
1675 case GL_STENCIL:
1676 case GL_STENCIL_ATTACHMENT:
Martin Radev5dae57b2017-07-14 16:15:55 +03001677 mState.mWebGLStencilAttachment.attach(context, type, binding, textureIndex, resource,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001678 numViews, baseViewIndex, isMultiview, samples);
Jamie Madilla02315b2017-02-23 14:14:47 -05001679 break;
1680 default:
Martin Radev5dae57b2017-07-14 16:15:55 +03001681 setAttachmentImpl(context, type, binding, textureIndex, resource, numViews,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001682 baseViewIndex, isMultiview, samples);
Jamie Madilla02315b2017-02-23 14:14:47 -05001683 return;
1684 }
1685
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001686 commitWebGL1DepthStencilIfConsistent(context, numViews, baseViewIndex, isMultiview, samples);
Jamie Madilla02315b2017-02-23 14:14:47 -05001687}
1688
Mingyu Hu7d64c482019-03-12 14:27:40 -07001689void Framebuffer::setAttachmentMultiview(const Context *context,
1690 GLenum type,
1691 GLenum binding,
1692 const ImageIndex &textureIndex,
1693 FramebufferAttachmentObject *resource,
1694 GLsizei numViews,
1695 GLint baseViewIndex)
Martin Radev82ef7742017-08-08 17:44:58 +03001696{
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001697 setAttachment(context, type, binding, textureIndex, resource, numViews, baseViewIndex, true,
1698 FramebufferAttachment::kDefaultRenderToTextureSamples);
Martin Radev5dae57b2017-07-14 16:15:55 +03001699}
1700
1701void Framebuffer::commitWebGL1DepthStencilIfConsistent(const Context *context,
1702 GLsizei numViews,
1703 GLuint baseViewIndex,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001704 bool isMultiview,
1705 GLsizei samples)
Jamie Madilla02315b2017-02-23 14:14:47 -05001706{
1707 int count = 0;
1708
1709 std::array<FramebufferAttachment *, 3> attachments = {{&mState.mWebGLDepthStencilAttachment,
1710 &mState.mWebGLDepthAttachment,
1711 &mState.mWebGLStencilAttachment}};
1712 for (FramebufferAttachment *attachment : attachments)
1713 {
1714 if (attachment->isAttached())
1715 {
1716 count++;
1717 }
1718 }
1719
1720 mState.mWebGLDepthStencilConsistent = (count <= 1);
1721 if (!mState.mWebGLDepthStencilConsistent)
1722 {
1723 // Inconsistent.
1724 return;
1725 }
1726
Geoff Lange466c552017-03-17 15:24:12 -04001727 auto getImageIndexIfTextureAttachment = [](const FramebufferAttachment &attachment) {
1728 if (attachment.type() == GL_TEXTURE)
1729 {
1730 return attachment.getTextureImageIndex();
1731 }
1732 else
1733 {
Jamie Madillcc129372018-04-12 09:13:18 -04001734 return ImageIndex();
Geoff Lange466c552017-03-17 15:24:12 -04001735 }
1736 };
1737
Jamie Madilla02315b2017-02-23 14:14:47 -05001738 if (mState.mWebGLDepthAttachment.isAttached())
1739 {
1740 const auto &depth = mState.mWebGLDepthAttachment;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001741 setAttachmentImpl(context, depth.type(), GL_DEPTH_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001742 getImageIndexIfTextureAttachment(depth), depth.getResource(), numViews,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001743 baseViewIndex, isMultiview, samples);
Jamie Madillcc129372018-04-12 09:13:18 -04001744 setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex(), nullptr, numViews,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001745 baseViewIndex, isMultiview, samples);
Jamie Madilla02315b2017-02-23 14:14:47 -05001746 }
1747 else if (mState.mWebGLStencilAttachment.isAttached())
1748 {
1749 const auto &stencil = mState.mWebGLStencilAttachment;
Jamie Madillcc129372018-04-12 09:13:18 -04001750 setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex(), nullptr, numViews,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001751 baseViewIndex, isMultiview, samples);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001752 setAttachmentImpl(context, stencil.type(), GL_STENCIL_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001753 getImageIndexIfTextureAttachment(stencil), stencil.getResource(),
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001754 numViews, baseViewIndex, isMultiview, samples);
Jamie Madilla02315b2017-02-23 14:14:47 -05001755 }
1756 else if (mState.mWebGLDepthStencilAttachment.isAttached())
1757 {
1758 const auto &depthStencil = mState.mWebGLDepthStencilAttachment;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001759 setAttachmentImpl(context, depthStencil.type(), GL_DEPTH_ATTACHMENT,
Geoff Lange466c552017-03-17 15:24:12 -04001760 getImageIndexIfTextureAttachment(depthStencil),
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001761 depthStencil.getResource(), numViews, baseViewIndex, isMultiview,
1762 samples);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001763 setAttachmentImpl(context, depthStencil.type(), GL_STENCIL_ATTACHMENT,
Geoff Lange466c552017-03-17 15:24:12 -04001764 getImageIndexIfTextureAttachment(depthStencil),
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001765 depthStencil.getResource(), numViews, baseViewIndex, isMultiview,
1766 samples);
Jamie Madilla02315b2017-02-23 14:14:47 -05001767 }
1768 else
1769 {
Jamie Madillcc129372018-04-12 09:13:18 -04001770 setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex(), nullptr, numViews,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001771 baseViewIndex, isMultiview, samples);
Jamie Madillcc129372018-04-12 09:13:18 -04001772 setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex(), nullptr, numViews,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001773 baseViewIndex, isMultiview, samples);
Jamie Madilla02315b2017-02-23 14:14:47 -05001774 }
1775}
1776
Jamie Madill4928b7c2017-06-20 12:57:39 -04001777void Framebuffer::setAttachmentImpl(const Context *context,
1778 GLenum type,
Jamie Madilla02315b2017-02-23 14:14:47 -05001779 GLenum binding,
1780 const ImageIndex &textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001781 FramebufferAttachmentObject *resource,
1782 GLsizei numViews,
1783 GLuint baseViewIndex,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001784 bool isMultiview,
1785 GLsizei samples)
Jamie Madilla02315b2017-02-23 14:14:47 -05001786{
Jamie Madilla02315b2017-02-23 14:14:47 -05001787 switch (binding)
1788 {
Jamie Madillb8126692017-04-05 11:22:17 -04001789 case GL_DEPTH_STENCIL:
1790 case GL_DEPTH_STENCIL_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001791 updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
Geoff Lang32d60062019-09-06 10:10:08 -04001792 &mDirtyDepthAttachmentBinding, type, binding, textureIndex, resource,
1793 numViews, baseViewIndex, isMultiview, samples);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001794 updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
Geoff Lang32d60062019-09-06 10:10:08 -04001795 &mDirtyStencilAttachmentBinding, type, binding, textureIndex, resource,
1796 numViews, baseViewIndex, isMultiview, samples);
Jamie Madill42975642017-10-12 12:31:51 -04001797 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001798
Jamie Madilla02315b2017-02-23 14:14:47 -05001799 case GL_DEPTH:
1800 case GL_DEPTH_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001801 updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001802 &mDirtyDepthAttachmentBinding, type, binding, textureIndex, resource,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001803 numViews, baseViewIndex, isMultiview, samples);
Jamie Madill2d06b732015-04-20 12:53:28 -04001804 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001805
Jamie Madilla02315b2017-02-23 14:14:47 -05001806 case GL_STENCIL:
1807 case GL_STENCIL_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001808 updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001809 &mDirtyStencilAttachmentBinding, type, binding, textureIndex, resource,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001810 numViews, baseViewIndex, isMultiview, samples);
Jamie Madilla02315b2017-02-23 14:14:47 -05001811 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001812
Jamie Madilla02315b2017-02-23 14:14:47 -05001813 case GL_BACK:
Geoff Lang8170eab2017-09-21 13:59:04 -04001814 updateAttachment(context, &mState.mColorAttachments[0], DIRTY_BIT_COLOR_ATTACHMENT_0,
1815 &mDirtyColorAttachmentBindings[0], type, binding, textureIndex,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001816 resource, numViews, baseViewIndex, isMultiview, samples);
Jamie Madilla02315b2017-02-23 14:14:47 -05001817 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001818
Jamie Madilla02315b2017-02-23 14:14:47 -05001819 default:
1820 {
1821 size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
1822 ASSERT(colorIndex < mState.mColorAttachments.size());
Jamie Madillb8126692017-04-05 11:22:17 -04001823 size_t dirtyBit = DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001824 updateAttachment(context, &mState.mColorAttachments[colorIndex], dirtyBit,
Jamie Madillb8126692017-04-05 11:22:17 -04001825 &mDirtyColorAttachmentBindings[colorIndex], type, binding,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001826 textureIndex, resource, numViews, baseViewIndex, isMultiview, samples);
Jamie Madilla02315b2017-02-23 14:14:47 -05001827
shrekshaoc87e0052019-02-21 11:40:28 -08001828 if (!resource)
1829 {
shrekshao8413fab2019-04-04 17:13:18 -07001830 mColorAttachmentBits.reset(colorIndex);
shrekshaoc87e0052019-02-21 11:40:28 -08001831 mFloat32ColorAttachmentBits.reset(colorIndex);
1832 }
1833 else
1834 {
shrekshao8413fab2019-04-04 17:13:18 -07001835 mColorAttachmentBits.set(colorIndex);
shrekshaoc87e0052019-02-21 11:40:28 -08001836 updateFloat32ColorAttachmentBits(
1837 colorIndex, resource->getAttachmentFormat(binding, textureIndex).info);
1838 }
1839
Corentin Walleze7557742017-06-01 13:09:57 -04001840 // TODO(jmadill): ASSERT instead of checking the attachment exists in
1841 // formsRenderingFeedbackLoopWith
Jamie Madilla02315b2017-02-23 14:14:47 -05001842 bool enabled = (type != GL_NONE && getDrawBufferState(colorIndex) != GL_NONE);
1843 mState.mEnabledDrawBuffers.set(colorIndex, enabled);
Jamie Madill6e18a232019-01-16 13:27:14 -05001844 SetComponentTypeMask(getDrawbufferWriteType(colorIndex), colorIndex,
1845 &mState.mDrawBufferTypeMask);
Jamie Madill2d06b732015-04-20 12:53:28 -04001846 }
Jamie Madilla02315b2017-02-23 14:14:47 -05001847 break;
Geoff Langab75a052014-10-15 12:56:37 -04001848 }
1849}
1850
Jamie Madill4928b7c2017-06-20 12:57:39 -04001851void Framebuffer::updateAttachment(const Context *context,
1852 FramebufferAttachment *attachment,
Jamie Madillb8126692017-04-05 11:22:17 -04001853 size_t dirtyBit,
Jamie Madilld4442552018-02-27 22:03:47 -05001854 angle::ObserverBinding *onDirtyBinding,
Jamie Madillb8126692017-04-05 11:22:17 -04001855 GLenum type,
1856 GLenum binding,
1857 const ImageIndex &textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001858 FramebufferAttachmentObject *resource,
1859 GLsizei numViews,
1860 GLuint baseViewIndex,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001861 bool isMultiview,
1862 GLsizei samples)
Jamie Madillb8126692017-04-05 11:22:17 -04001863{
Martin Radev5dae57b2017-07-14 16:15:55 +03001864 attachment->attach(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001865 isMultiview, samples);
Jamie Madillb8126692017-04-05 11:22:17 -04001866 mDirtyBits.set(dirtyBit);
Jamie Madill05b35b22017-10-03 09:01:44 -04001867 mState.mResourceNeedsInit.set(dirtyBit, attachment->initState() == InitState::MayNeedInit);
Jamie Madill66f0d2c2018-11-30 15:25:36 -05001868 onDirtyBinding->bind(resource);
Jamie Madille98b1b52018-03-08 09:47:23 -05001869
Jamie Madill124f78c2019-06-18 11:48:24 -04001870 invalidateCompletenessCache();
Jamie Madillb8126692017-04-05 11:22:17 -04001871}
1872
Jamie Madilla02315b2017-02-23 14:14:47 -05001873void Framebuffer::resetAttachment(const Context *context, GLenum binding)
Jamie Madill2d06b732015-04-20 12:53:28 -04001874{
Jamie Madillcc129372018-04-12 09:13:18 -04001875 setAttachment(context, GL_NONE, binding, ImageIndex(), nullptr);
Jamie Madill2d06b732015-04-20 12:53:28 -04001876}
1877
Jamie Madill6f755b22018-10-09 12:48:54 -04001878angle::Result Framebuffer::syncState(const Context *context)
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001879{
1880 if (mDirtyBits.any())
1881 {
Jamie Madill888081d2018-02-27 00:24:46 -05001882 mDirtyBitsGuard = mDirtyBits;
Jamie Madill19fa1c62018-03-08 09:47:21 -05001883 ANGLE_TRY(mImpl->syncState(context, mDirtyBits));
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001884 mDirtyBits.reset();
Jamie Madill888081d2018-02-27 00:24:46 -05001885 mDirtyBitsGuard.reset();
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001886 }
Jamie Madill7c985f52018-11-29 18:16:17 -05001887 return angle::Result::Continue;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001888}
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001889
Jamie Madill124f78c2019-06-18 11:48:24 -04001890void Framebuffer::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
Jamie Madill51f40ec2016-06-15 14:06:00 -04001891{
Jamie Madille4faae22019-05-10 08:27:00 -04001892 if (message != angle::SubjectMessage::SubjectChanged)
Jamie Madillf668a4b2018-09-23 17:01:20 -04001893 {
Jamie Madill67220092019-05-20 11:12:53 -04001894 // This can be triggered by SubImage calls for Textures.
1895 if (message == angle::SubjectMessage::ContentsChanged)
1896 {
1897 mDirtyBits.set(DIRTY_BIT_COLOR_BUFFER_CONTENTS_0 + index);
Jamie Madill124f78c2019-06-18 11:48:24 -04001898 onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
Jamie Madill67220092019-05-20 11:12:53 -04001899 return;
1900 }
1901
Jamie Madillf668a4b2018-09-23 17:01:20 -04001902 // This can be triggered by the GL back-end TextureGL class.
Jamie Madille4faae22019-05-10 08:27:00 -04001903 ASSERT(message == angle::SubjectMessage::DirtyBitsFlagged);
Jamie Madillf668a4b2018-09-23 17:01:20 -04001904 return;
1905 }
Jamie Madill55e57f92018-09-18 11:32:43 -04001906
1907 ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(index));
1908 mDirtyBits.set(index);
Jamie Madill888081d2018-02-27 00:24:46 -05001909
Jamie Madill124f78c2019-06-18 11:48:24 -04001910 invalidateCompletenessCache();
Jamie Madill05b35b22017-10-03 09:01:44 -04001911
Jamie Madilld4442552018-02-27 22:03:47 -05001912 FramebufferAttachment *attachment = getAttachmentFromSubjectIndex(index);
1913
Jamie Madill05b35b22017-10-03 09:01:44 -04001914 // Mark the appropriate init flag.
Jamie Madilld4442552018-02-27 22:03:47 -05001915 mState.mResourceNeedsInit.set(index, attachment->initState() == InitState::MayNeedInit);
shrekshaoc87e0052019-02-21 11:40:28 -08001916
1917 // Update mFloat32ColorAttachmentBits Cache
1918 if (index < DIRTY_BIT_COLOR_ATTACHMENT_MAX)
1919 {
1920 ASSERT(index != DIRTY_BIT_DEPTH_ATTACHMENT);
1921 ASSERT(index != DIRTY_BIT_STENCIL_ATTACHMENT);
1922 updateFloat32ColorAttachmentBits(index - DIRTY_BIT_COLOR_ATTACHMENT_0,
1923 attachment->getFormat().info);
1924 }
Jamie Madilld4442552018-02-27 22:03:47 -05001925}
1926
1927FramebufferAttachment *Framebuffer::getAttachmentFromSubjectIndex(angle::SubjectIndex index)
1928{
1929 switch (index)
1930 {
1931 case DIRTY_BIT_DEPTH_ATTACHMENT:
1932 return &mState.mDepthAttachment;
1933 case DIRTY_BIT_STENCIL_ATTACHMENT:
1934 return &mState.mStencilAttachment;
1935 default:
1936 size_t colorIndex = (index - DIRTY_BIT_COLOR_ATTACHMENT_0);
1937 ASSERT(colorIndex < mState.mColorAttachments.size());
1938 return &mState.mColorAttachments[colorIndex];
1939 }
Jamie Madill51f40ec2016-06-15 14:06:00 -04001940}
1941
shrekshao8413fab2019-04-04 17:13:18 -07001942bool Framebuffer::formsRenderingFeedbackLoopWith(const Context *context) const
Jamie Madilla4595b82017-01-11 17:36:34 -05001943{
shrekshao8413fab2019-04-04 17:13:18 -07001944 const State &state = context->getState();
Jamie Madill785e8a02018-10-04 17:42:00 -04001945 const Program *program = state.getProgram();
Jamie Madilla4595b82017-01-11 17:36:34 -05001946
1947 // TODO(jmadill): Default framebuffer feedback loops.
Jiacheng Lu2c5d48a2019-08-23 09:28:35 -06001948 if (mState.isDefault())
Jamie Madilla4595b82017-01-11 17:36:34 -05001949 {
1950 return false;
1951 }
1952
Jamie Madill4e71b2b2019-07-08 13:23:38 -04001953 const FramebufferAttachment *depth = getDepthAttachment();
1954 const FramebufferAttachment *stencil = getStencilAttachment();
shrekshao8413fab2019-04-04 17:13:18 -07001955
1956 const bool checkDepth = depth && depth->type() == GL_TEXTURE;
1957 // Skip the feedback loop check for stencil if depth/stencil point to the same resource.
1958 const bool checkStencil =
1959 (stencil && stencil->type() == GL_TEXTURE) && (!depth || *stencil != *depth);
1960
1961 const gl::ActiveTextureMask &activeTextures = program->getActiveSamplersMask();
1962 const gl::ActiveTexturePointerArray &textures = state.getActiveTexturesCache();
1963
1964 for (size_t textureUnit : activeTextures)
Jamie Madilla4595b82017-01-11 17:36:34 -05001965 {
shrekshao8413fab2019-04-04 17:13:18 -07001966 Texture *texture = textures[textureUnit];
1967
1968 if (texture == nullptr)
Jamie Madilla4595b82017-01-11 17:36:34 -05001969 {
shrekshao8413fab2019-04-04 17:13:18 -07001970 continue;
1971 }
1972
1973 // Depth and stencil attachment form feedback loops
1974 // Regardless of if enabled or masked.
1975 if (checkDepth)
1976 {
Jamie Madillf7034432019-09-21 14:10:35 -04001977 if (texture->getId() == depth->id())
Jamie Madilla4595b82017-01-11 17:36:34 -05001978 {
1979 return true;
1980 }
1981 }
Jamie Madilla4595b82017-01-11 17:36:34 -05001982
shrekshao8413fab2019-04-04 17:13:18 -07001983 if (checkStencil)
Jamie Madill1d37bc52017-02-02 19:59:58 -05001984 {
Jamie Madillf7034432019-09-21 14:10:35 -04001985 if (texture->getId() == stencil->id())
Jamie Madill1d37bc52017-02-02 19:59:58 -05001986 {
Jamie Madill38fe6842018-09-19 07:20:00 -04001987 return true;
Jamie Madill1d37bc52017-02-02 19:59:58 -05001988 }
1989 }
shrekshao8413fab2019-04-04 17:13:18 -07001990
1991 // Check if any color attachment forms a feedback loop.
1992 for (size_t drawIndex : mColorAttachmentBits)
1993 {
1994 const FramebufferAttachment &attachment = mState.mColorAttachments[drawIndex];
1995 ASSERT(attachment.isAttached());
1996
1997 if (attachment.isTextureWithId(texture->id()))
1998 {
1999 // TODO(jmadill): Check for appropriate overlap.
2000 return true;
2001 }
2002 }
Jamie Madill1d37bc52017-02-02 19:59:58 -05002003 }
2004
Jamie Madilla4595b82017-01-11 17:36:34 -05002005 return false;
2006}
2007
Jamie Madillf7034432019-09-21 14:10:35 -04002008bool Framebuffer::formsCopyingFeedbackLoopWith(TextureID copyTextureID,
Jamie Madillfd3dd432017-02-02 19:59:59 -05002009 GLint copyTextureLevel,
2010 GLint copyTextureLayer) const
Jamie Madillf695a3a2017-01-11 17:36:35 -05002011{
Jiacheng Lu2c5d48a2019-08-23 09:28:35 -06002012 if (mState.isDefault())
Jamie Madillf695a3a2017-01-11 17:36:35 -05002013 {
2014 // It seems impossible to form a texture copying feedback loop with the default FBO.
2015 return false;
2016 }
2017
Jamie Madill4e71b2b2019-07-08 13:23:38 -04002018 const FramebufferAttachment *readAttachment = getReadColorAttachment();
Jamie Madillf695a3a2017-01-11 17:36:35 -05002019 ASSERT(readAttachment);
2020
2021 if (readAttachment->isTextureWithId(copyTextureID))
2022 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002023 const auto &imageIndex = readAttachment->getTextureImageIndex();
Jamie Madillcc129372018-04-12 09:13:18 -04002024 if (imageIndex.getLevelIndex() == copyTextureLevel)
Jamie Madillf695a3a2017-01-11 17:36:35 -05002025 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002026 // Check 3D/Array texture layers.
Jamie Madillcc129372018-04-12 09:13:18 -04002027 return !imageIndex.hasLayer() || copyTextureLayer == ImageIndex::kEntireLevel ||
2028 imageIndex.getLayerIndex() == copyTextureLayer;
Jamie Madillf695a3a2017-01-11 17:36:35 -05002029 }
2030 }
2031 return false;
2032}
2033
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002034GLint Framebuffer::getDefaultWidth() const
2035{
2036 return mState.getDefaultWidth();
2037}
2038
2039GLint Framebuffer::getDefaultHeight() const
2040{
2041 return mState.getDefaultHeight();
2042}
2043
2044GLint Framebuffer::getDefaultSamples() const
2045{
2046 return mState.getDefaultSamples();
2047}
2048
Geoff Lang92019432017-11-20 13:09:34 -05002049bool Framebuffer::getDefaultFixedSampleLocations() const
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002050{
2051 return mState.getDefaultFixedSampleLocations();
2052}
2053
Jiawei Shaob1e91382018-05-17 14:33:55 +08002054GLint Framebuffer::getDefaultLayers() const
2055{
2056 return mState.getDefaultLayers();
2057}
2058
Jamie Madillb983a4b2018-08-01 11:34:51 -04002059void Framebuffer::setDefaultWidth(const Context *context, GLint defaultWidth)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002060{
2061 mState.mDefaultWidth = defaultWidth;
2062 mDirtyBits.set(DIRTY_BIT_DEFAULT_WIDTH);
Jamie Madill124f78c2019-06-18 11:48:24 -04002063 invalidateCompletenessCache();
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002064}
2065
Jamie Madillb983a4b2018-08-01 11:34:51 -04002066void Framebuffer::setDefaultHeight(const Context *context, GLint defaultHeight)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002067{
2068 mState.mDefaultHeight = defaultHeight;
2069 mDirtyBits.set(DIRTY_BIT_DEFAULT_HEIGHT);
Jamie Madill124f78c2019-06-18 11:48:24 -04002070 invalidateCompletenessCache();
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002071}
2072
Jamie Madillb983a4b2018-08-01 11:34:51 -04002073void Framebuffer::setDefaultSamples(const Context *context, GLint defaultSamples)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002074{
2075 mState.mDefaultSamples = defaultSamples;
2076 mDirtyBits.set(DIRTY_BIT_DEFAULT_SAMPLES);
Jamie Madill124f78c2019-06-18 11:48:24 -04002077 invalidateCompletenessCache();
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002078}
2079
Jamie Madillb983a4b2018-08-01 11:34:51 -04002080void Framebuffer::setDefaultFixedSampleLocations(const Context *context,
2081 bool defaultFixedSampleLocations)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002082{
2083 mState.mDefaultFixedSampleLocations = defaultFixedSampleLocations;
2084 mDirtyBits.set(DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS);
Jamie Madill124f78c2019-06-18 11:48:24 -04002085 invalidateCompletenessCache();
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002086}
2087
Jiawei Shaob1e91382018-05-17 14:33:55 +08002088void Framebuffer::setDefaultLayers(GLint defaultLayers)
2089{
2090 mState.mDefaultLayers = defaultLayers;
2091 mDirtyBits.set(DIRTY_BIT_DEFAULT_LAYERS);
2092}
2093
Martin Radev14a26ae2017-07-24 15:56:29 +03002094GLsizei Framebuffer::getNumViews() const
2095{
Martin Radev5c00d0d2017-08-07 10:06:59 +03002096 return mState.getNumViews();
Martin Radev14a26ae2017-07-24 15:56:29 +03002097}
2098
Martin Radev4e619f52017-08-09 11:50:06 +03002099GLint Framebuffer::getBaseViewIndex() const
2100{
2101 return mState.getBaseViewIndex();
2102}
2103
Mingyu Hu7d64c482019-03-12 14:27:40 -07002104bool Framebuffer::isMultiview() const
Martin Radev878c8b12017-07-28 09:51:04 +03002105{
Mingyu Hu7d64c482019-03-12 14:27:40 -07002106 return mState.isMultiview();
Martin Radev878c8b12017-07-28 09:51:04 +03002107}
2108
Olli Etuaho8acb1b62018-07-30 16:20:54 +03002109bool Framebuffer::readDisallowedByMultiview() const
2110{
Mingyu Hu7d64c482019-03-12 14:27:40 -07002111 return (mState.isMultiview() && mState.getNumViews() > 1);
Olli Etuaho8acb1b62018-07-30 16:20:54 +03002112}
2113
Jamie Madill64b7c4f2018-10-19 11:38:04 -04002114angle::Result Framebuffer::ensureClearAttachmentsInitialized(const Context *context,
2115 GLbitfield mask)
Geoff Langd4fff502017-09-22 11:28:28 -04002116{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05002117 const auto &glState = context->getState();
Geoff Langd4fff502017-09-22 11:28:28 -04002118 if (!context->isRobustResourceInitEnabled() || glState.isRasterizerDiscardEnabled())
2119 {
Jamie Madill7c985f52018-11-29 18:16:17 -05002120 return angle::Result::Continue;
Geoff Langd4fff502017-09-22 11:28:28 -04002121 }
2122
Geoff Langa36483f2018-03-09 16:11:21 -05002123 const BlendState &blend = glState.getBlendState();
2124 const DepthStencilState &depthStencil = glState.getDepthStencilState();
Geoff Langd4fff502017-09-22 11:28:28 -04002125
2126 bool color = (mask & GL_COLOR_BUFFER_BIT) != 0 && !IsColorMaskedOut(blend);
2127 bool depth = (mask & GL_DEPTH_BUFFER_BIT) != 0 && !IsDepthMaskedOut(depthStencil);
2128 bool stencil = (mask & GL_STENCIL_BUFFER_BIT) != 0 && !IsStencilMaskedOut(depthStencil);
2129
2130 if (!color && !depth && !stencil)
2131 {
Jamie Madill7c985f52018-11-29 18:16:17 -05002132 return angle::Result::Continue;
Geoff Langd4fff502017-09-22 11:28:28 -04002133 }
2134
2135 if (partialClearNeedsInit(context, color, depth, stencil))
2136 {
2137 ANGLE_TRY(ensureDrawAttachmentsInitialized(context));
2138 }
2139
2140 // If the impl encounters an error during a a full (non-partial) clear, the attachments will
2141 // still be marked initialized. This simplifies design, allowing this method to be called before
2142 // the clear.
2143 markDrawAttachmentsInitialized(color, depth, stencil);
2144
Jamie Madill7c985f52018-11-29 18:16:17 -05002145 return angle::Result::Continue;
Geoff Langd4fff502017-09-22 11:28:28 -04002146}
2147
Jamie Madill64b7c4f2018-10-19 11:38:04 -04002148angle::Result Framebuffer::ensureClearBufferAttachmentsInitialized(const Context *context,
2149 GLenum buffer,
2150 GLint drawbuffer)
Geoff Langd4fff502017-09-22 11:28:28 -04002151{
2152 if (!context->isRobustResourceInitEnabled() ||
Jamie Madillc3dc5d42018-12-30 12:12:04 -05002153 context->getState().isRasterizerDiscardEnabled() || IsClearBufferMaskedOut(context, buffer))
Geoff Langd4fff502017-09-22 11:28:28 -04002154 {
Jamie Madill7c985f52018-11-29 18:16:17 -05002155 return angle::Result::Continue;
Geoff Langd4fff502017-09-22 11:28:28 -04002156 }
2157
2158 if (partialBufferClearNeedsInit(context, buffer))
2159 {
2160 ANGLE_TRY(ensureBufferInitialized(context, buffer, drawbuffer));
2161 }
2162
2163 // If the impl encounters an error during a a full (non-partial) clear, the attachments will
2164 // still be marked initialized. This simplifies design, allowing this method to be called before
2165 // the clear.
2166 markBufferInitialized(buffer, drawbuffer);
2167
Jamie Madill7c985f52018-11-29 18:16:17 -05002168 return angle::Result::Continue;
Geoff Langd4fff502017-09-22 11:28:28 -04002169}
2170
Jamie Madill6f755b22018-10-09 12:48:54 -04002171angle::Result Framebuffer::ensureDrawAttachmentsInitialized(const Context *context)
Jamie Madill05b35b22017-10-03 09:01:44 -04002172{
2173 if (!context->isRobustResourceInitEnabled())
2174 {
Jamie Madill7c985f52018-11-29 18:16:17 -05002175 return angle::Result::Continue;
Jamie Madill05b35b22017-10-03 09:01:44 -04002176 }
2177
2178 // Note: we don't actually filter by the draw attachment enum. Just init everything.
2179 for (size_t bit : mState.mResourceNeedsInit)
2180 {
2181 switch (bit)
2182 {
2183 case DIRTY_BIT_DEPTH_ATTACHMENT:
2184 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2185 break;
2186 case DIRTY_BIT_STENCIL_ATTACHMENT:
2187 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2188 break;
2189 default:
2190 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[bit]));
2191 break;
2192 }
2193 }
2194
2195 mState.mResourceNeedsInit.reset();
Jamie Madill7c985f52018-11-29 18:16:17 -05002196 return angle::Result::Continue;
Jamie Madill05b35b22017-10-03 09:01:44 -04002197}
2198
Jamie Madill0a1eeb82019-05-13 13:53:18 -04002199angle::Result Framebuffer::ensureReadAttachmentsInitialized(const Context *context)
Jamie Madill05b35b22017-10-03 09:01:44 -04002200{
Jamie Madill0a1eeb82019-05-13 13:53:18 -04002201 ASSERT(context->isRobustResourceInitEnabled());
2202
2203 if (mState.mResourceNeedsInit.none())
Jamie Madill05b35b22017-10-03 09:01:44 -04002204 {
Jamie Madill7c985f52018-11-29 18:16:17 -05002205 return angle::Result::Continue;
Jamie Madill05b35b22017-10-03 09:01:44 -04002206 }
2207
Jamie Madill0a1eeb82019-05-13 13:53:18 -04002208 if (mState.mReadBufferState != GL_NONE)
Jamie Madill05b35b22017-10-03 09:01:44 -04002209 {
Tim Van Patten56ba54c2019-08-08 13:03:34 -06002210 if (isDefault())
Jamie Madill05b35b22017-10-03 09:01:44 -04002211 {
Tim Van Patten56ba54c2019-08-08 13:03:34 -06002212 if (!mState.mDefaultFramebufferReadAttachmentInitialized)
2213 {
2214 ANGLE_TRY(InitAttachment(context, &mState.mDefaultFramebufferReadAttachment));
2215 mState.mDefaultFramebufferReadAttachmentInitialized = true;
2216 }
2217 }
2218 else
2219 {
2220 size_t readIndex = mState.getReadIndex();
2221 if (mState.mResourceNeedsInit[readIndex])
2222 {
2223 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[readIndex]));
2224 mState.mResourceNeedsInit.reset(readIndex);
2225 }
Jamie Madill05b35b22017-10-03 09:01:44 -04002226 }
2227 }
2228
Jamie Madill0a1eeb82019-05-13 13:53:18 -04002229 // Conservatively init depth since it can be read by BlitFramebuffer.
2230 if (hasDepth())
Jamie Madill05b35b22017-10-03 09:01:44 -04002231 {
2232 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2233 {
2234 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2235 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2236 }
2237 }
2238
Jamie Madill0a1eeb82019-05-13 13:53:18 -04002239 // Conservatively init stencil since it can be read by BlitFramebuffer.
2240 if (hasStencil())
Jamie Madill05b35b22017-10-03 09:01:44 -04002241 {
2242 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2243 {
2244 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2245 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2246 }
2247 }
2248
Jamie Madill7c985f52018-11-29 18:16:17 -05002249 return angle::Result::Continue;
Jamie Madill05b35b22017-10-03 09:01:44 -04002250}
2251
2252void Framebuffer::markDrawAttachmentsInitialized(bool color, bool depth, bool stencil)
2253{
2254 // Mark attachments as initialized.
2255 if (color)
2256 {
2257 for (auto colorIndex : mState.mEnabledDrawBuffers)
2258 {
2259 auto &colorAttachment = mState.mColorAttachments[colorIndex];
2260 ASSERT(colorAttachment.isAttached());
2261 colorAttachment.setInitState(InitState::Initialized);
2262 mState.mResourceNeedsInit.reset(colorIndex);
2263 }
2264 }
2265
2266 if (depth && mState.mDepthAttachment.isAttached())
2267 {
2268 mState.mDepthAttachment.setInitState(InitState::Initialized);
2269 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2270 }
2271
2272 if (stencil && mState.mStencilAttachment.isAttached())
2273 {
2274 mState.mStencilAttachment.setInitState(InitState::Initialized);
2275 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2276 }
2277}
2278
2279void Framebuffer::markBufferInitialized(GLenum bufferType, GLint bufferIndex)
2280{
2281 switch (bufferType)
2282 {
2283 case GL_COLOR:
2284 {
2285 ASSERT(bufferIndex < static_cast<GLint>(mState.mColorAttachments.size()));
2286 if (mState.mColorAttachments[bufferIndex].isAttached())
2287 {
2288 mState.mColorAttachments[bufferIndex].setInitState(InitState::Initialized);
2289 mState.mResourceNeedsInit.reset(bufferIndex);
2290 }
2291 break;
2292 }
2293 case GL_DEPTH:
2294 {
2295 if (mState.mDepthAttachment.isAttached())
2296 {
2297 mState.mDepthAttachment.setInitState(InitState::Initialized);
2298 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2299 }
2300 break;
2301 }
2302 case GL_STENCIL:
2303 {
2304 if (mState.mStencilAttachment.isAttached())
2305 {
2306 mState.mStencilAttachment.setInitState(InitState::Initialized);
2307 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2308 }
2309 break;
2310 }
2311 case GL_DEPTH_STENCIL:
2312 {
2313 if (mState.mDepthAttachment.isAttached())
2314 {
2315 mState.mDepthAttachment.setInitState(InitState::Initialized);
2316 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2317 }
2318 if (mState.mStencilAttachment.isAttached())
2319 {
2320 mState.mStencilAttachment.setInitState(InitState::Initialized);
2321 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2322 }
2323 break;
2324 }
2325 default:
2326 UNREACHABLE();
2327 break;
2328 }
2329}
2330
2331Box Framebuffer::getDimensions() const
2332{
2333 return mState.getDimensions();
2334}
2335
Jonah Ryan-Davis7151fe52019-07-17 15:15:27 -04002336Extents Framebuffer::getExtents() const
2337{
2338 return mState.getExtents();
2339}
2340
Jamie Madill64b7c4f2018-10-19 11:38:04 -04002341angle::Result Framebuffer::ensureBufferInitialized(const Context *context,
2342 GLenum bufferType,
2343 GLint bufferIndex)
Jamie Madill05b35b22017-10-03 09:01:44 -04002344{
2345 ASSERT(context->isRobustResourceInitEnabled());
2346
2347 if (mState.mResourceNeedsInit.none())
2348 {
Jamie Madill7c985f52018-11-29 18:16:17 -05002349 return angle::Result::Continue;
Jamie Madill05b35b22017-10-03 09:01:44 -04002350 }
2351
2352 switch (bufferType)
2353 {
2354 case GL_COLOR:
2355 {
2356 ASSERT(bufferIndex < static_cast<GLint>(mState.mColorAttachments.size()));
2357 if (mState.mResourceNeedsInit[bufferIndex])
2358 {
2359 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[bufferIndex]));
2360 mState.mResourceNeedsInit.reset(bufferIndex);
2361 }
2362 break;
2363 }
2364 case GL_DEPTH:
2365 {
2366 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2367 {
2368 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2369 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2370 }
2371 break;
2372 }
2373 case GL_STENCIL:
2374 {
2375 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2376 {
2377 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2378 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2379 }
2380 break;
2381 }
2382 case GL_DEPTH_STENCIL:
2383 {
2384 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2385 {
2386 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2387 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2388 }
2389 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2390 {
2391 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2392 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2393 }
2394 break;
2395 }
2396 default:
2397 UNREACHABLE();
2398 break;
2399 }
2400
Jamie Madill7c985f52018-11-29 18:16:17 -05002401 return angle::Result::Continue;
Jamie Madill05b35b22017-10-03 09:01:44 -04002402}
2403
2404bool Framebuffer::partialBufferClearNeedsInit(const Context *context, GLenum bufferType)
2405{
2406 if (!context->isRobustResourceInitEnabled() || mState.mResourceNeedsInit.none())
2407 {
2408 return false;
2409 }
2410
2411 switch (bufferType)
2412 {
2413 case GL_COLOR:
2414 return partialClearNeedsInit(context, true, false, false);
2415 case GL_DEPTH:
2416 return partialClearNeedsInit(context, false, true, false);
2417 case GL_STENCIL:
2418 return partialClearNeedsInit(context, false, false, true);
2419 case GL_DEPTH_STENCIL:
2420 return partialClearNeedsInit(context, false, true, true);
2421 default:
2422 UNREACHABLE();
2423 return false;
2424 }
2425}
Jamie Madill60ec6ea2016-01-22 15:27:19 -05002426} // namespace gl