blob: 98a6d5374bd3436d33f382b3593854e569fac818 [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 Hu7d64c482019-03-12 14:27:40 -0700663 FramebufferAttachment::kDefaultBaseViewIndex, false);
Jamie Madill6f60d052017-02-22 15:20:11 -0500664
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600665 setReadSurface(context, readSurface);
666
Jamie Madill6f60d052017-02-22 15:20:11 -0500667 if (surface->getConfig()->depthSize > 0)
668 {
Geoff Langbf7b95d2018-05-01 16:48:21 -0400669 setAttachmentImpl(context, GL_FRAMEBUFFER_DEFAULT, GL_DEPTH, ImageIndex(), surface,
Jamie Madillcc129372018-04-12 09:13:18 -0400670 FramebufferAttachment::kDefaultNumViews,
Mingyu Hu7d64c482019-03-12 14:27:40 -0700671 FramebufferAttachment::kDefaultBaseViewIndex, false);
Jamie Madill6f60d052017-02-22 15:20:11 -0500672 }
673
674 if (surface->getConfig()->stencilSize > 0)
675 {
Geoff Langbf7b95d2018-05-01 16:48:21 -0400676 setAttachmentImpl(context, GL_FRAMEBUFFER_DEFAULT, GL_STENCIL, ImageIndex(), surface,
Jamie Madillcc129372018-04-12 09:13:18 -0400677 FramebufferAttachment::kDefaultNumViews,
Mingyu Hu7d64c482019-03-12 14:27:40 -0700678 FramebufferAttachment::kDefaultBaseViewIndex, false);
Jamie Madill6f60d052017-02-22 15:20:11 -0500679 }
Jamie Madill6e18a232019-01-16 13:27:14 -0500680 SetComponentTypeMask(getDrawbufferWriteType(0), 0, &mState.mDrawBufferTypeMask);
Geoff Langee244c72019-05-06 10:30:18 -0400681
682 // Ensure the backend has a chance to synchronize its content for a new backbuffer.
683 mDirtyBits.set(DIRTY_BIT_COLOR_BUFFER_CONTENTS_0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000684}
685
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600686Framebuffer::Framebuffer(const Context *context,
687 rx::GLImplFactory *factory,
688 egl::Surface *readSurface)
Corentin Wallezccab69d2017-01-27 16:57:15 -0500689 : mState(),
690 mImpl(factory->createFramebuffer(mState)),
Corentin Wallezccab69d2017-01-27 16:57:15 -0500691 mCachedStatus(GL_FRAMEBUFFER_UNDEFINED_OES),
692 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
693 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
694{
Jamie Madill1e5499d2017-04-05 11:22:16 -0400695 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
Jamie Madill6e18a232019-01-16 13:27:14 -0500696 SetComponentTypeMask(getDrawbufferWriteType(0), 0, &mState.mDrawBufferTypeMask);
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600697
698 setReadSurface(context, readSurface);
Corentin Wallezccab69d2017-01-27 16:57:15 -0500699}
700
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000701Framebuffer::~Framebuffer()
702{
Geoff Langda88add2014-12-01 10:22:01 -0500703 SafeDelete(mImpl);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000704}
705
Jamie Madill4928b7c2017-06-20 12:57:39 -0400706void Framebuffer::onDestroy(const Context *context)
Jamie Madill6c1f6712017-02-14 19:08:04 -0500707{
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600708 if (isDefault())
709 {
710 mState.mDefaultFramebufferReadAttachment.detach(context);
711 mState.mDefaultFramebufferReadAttachmentInitialized = false;
712 }
713
Jamie Madill4928b7c2017-06-20 12:57:39 -0400714 for (auto &attachment : mState.mColorAttachments)
715 {
716 attachment.detach(context);
717 }
718 mState.mDepthAttachment.detach(context);
719 mState.mStencilAttachment.detach(context);
720 mState.mWebGLDepthAttachment.detach(context);
721 mState.mWebGLStencilAttachment.detach(context);
722 mState.mWebGLDepthStencilAttachment.detach(context);
723
Jamie Madillc564c072017-06-01 12:45:42 -0400724 mImpl->destroy(context);
Jamie Madill6c1f6712017-02-14 19:08:04 -0500725}
726
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600727void Framebuffer::setReadSurface(const Context *context, egl::Surface *readSurface)
728{
729 // updateAttachment() without mState.mResourceNeedsInit.set()
730 mState.mDefaultFramebufferReadAttachment.attach(
731 context, GL_FRAMEBUFFER_DEFAULT, GL_BACK, ImageIndex(), readSurface,
732 FramebufferAttachment::kDefaultNumViews, FramebufferAttachment::kDefaultBaseViewIndex,
733 false);
734 mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
735}
736
Jamie Madille90d4ee2018-11-28 14:04:00 -0500737void Framebuffer::setLabel(const Context *context, const std::string &label)
Geoff Lang70d0f492015-12-10 17:45:46 -0500738{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400739 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -0500740}
741
742const std::string &Framebuffer::getLabel() const
743{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400744 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -0500745}
746
Jamie Madill2ab08ed2019-08-12 16:20:21 -0400747bool Framebuffer::detachTexture(const Context *context, TextureID textureId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000748{
Jamie Madill2ab08ed2019-08-12 16:20:21 -0400749 return detachResourceById(context, GL_TEXTURE, textureId.value);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000750}
751
Jamie Madill7c7dec02019-08-06 17:44:11 -0400752bool Framebuffer::detachRenderbuffer(const Context *context, RenderbufferID renderbufferId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000753{
Jamie Madill7c7dec02019-08-06 17:44:11 -0400754 return detachResourceById(context, GL_RENDERBUFFER, renderbufferId.value);
Jamie Madilld1405e52015-03-05 15:41:39 -0500755}
Jamie Madille261b442014-06-25 12:42:21 -0400756
Jamie Madill8693bdb2017-09-02 15:32:14 -0400757bool Framebuffer::detachResourceById(const Context *context, GLenum resourceType, GLuint resourceId)
Jamie Madilld1405e52015-03-05 15:41:39 -0500758{
Jamie Madill8693bdb2017-09-02 15:32:14 -0400759 bool found = false;
760
Jamie Madill362876b2016-06-16 14:46:59 -0400761 for (size_t colorIndex = 0; colorIndex < mState.mColorAttachments.size(); ++colorIndex)
Jamie Madilld1405e52015-03-05 15:41:39 -0500762 {
Jamie Madill8693bdb2017-09-02 15:32:14 -0400763 if (detachMatchingAttachment(context, &mState.mColorAttachments[colorIndex], resourceType,
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300764 resourceId))
Jamie Madill8693bdb2017-09-02 15:32:14 -0400765 {
766 found = true;
767 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000768 }
769
Jamie Madilla02315b2017-02-23 14:14:47 -0500770 if (context->isWebGL1())
771 {
772 const std::array<FramebufferAttachment *, 3> attachments = {
773 {&mState.mWebGLDepthStencilAttachment, &mState.mWebGLDepthAttachment,
774 &mState.mWebGLStencilAttachment}};
775 for (FramebufferAttachment *attachment : attachments)
776 {
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300777 if (detachMatchingAttachment(context, attachment, resourceType, resourceId))
Jamie Madilla02315b2017-02-23 14:14:47 -0500778 {
Jamie Madill8693bdb2017-09-02 15:32:14 -0400779 found = true;
Jamie Madilla02315b2017-02-23 14:14:47 -0500780 }
781 }
782 }
783 else
784 {
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300785 if (detachMatchingAttachment(context, &mState.mDepthAttachment, resourceType, resourceId))
Jamie Madill8693bdb2017-09-02 15:32:14 -0400786 {
787 found = true;
788 }
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300789 if (detachMatchingAttachment(context, &mState.mStencilAttachment, resourceType, resourceId))
Jamie Madill8693bdb2017-09-02 15:32:14 -0400790 {
791 found = true;
792 }
Jamie Madilla02315b2017-02-23 14:14:47 -0500793 }
Jamie Madill8693bdb2017-09-02 15:32:14 -0400794
795 return found;
Jamie Madill362876b2016-06-16 14:46:59 -0400796}
797
Jamie Madill8693bdb2017-09-02 15:32:14 -0400798bool Framebuffer::detachMatchingAttachment(const Context *context,
Jamie Madill4928b7c2017-06-20 12:57:39 -0400799 FramebufferAttachment *attachment,
Jamie Madill362876b2016-06-16 14:46:59 -0400800 GLenum matchType,
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300801 GLuint matchId)
Jamie Madill362876b2016-06-16 14:46:59 -0400802{
803 if (attachment->isAttached() && attachment->type() == matchType && attachment->id() == matchId)
804 {
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300805 // We go through resetAttachment to make sure that all the required bookkeeping will be done
806 // such as updating enabled draw buffer state.
807 resetAttachment(context, attachment->getBinding());
Jamie Madill8693bdb2017-09-02 15:32:14 -0400808 return true;
Jamie Madill362876b2016-06-16 14:46:59 -0400809 }
Jamie Madill8693bdb2017-09-02 15:32:14 -0400810
811 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000812}
813
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400814const FramebufferAttachment *Framebuffer::getColorAttachment(size_t colorAttachment) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000815{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400816 return mState.getColorAttachment(colorAttachment);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000817}
818
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400819const FramebufferAttachment *Framebuffer::getDepthAttachment() const
Geoff Lang646559f2013-08-15 11:08:15 -0400820{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400821 return mState.getDepthAttachment();
Geoff Lang646559f2013-08-15 11:08:15 -0400822}
823
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400824const FramebufferAttachment *Framebuffer::getStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400825{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400826 return mState.getStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400827}
828
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400829const FramebufferAttachment *Framebuffer::getDepthStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400830{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400831 return mState.getDepthStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400832}
833
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400834const FramebufferAttachment *Framebuffer::getDepthOrStencilAttachment() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000835{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400836 return mState.getDepthOrStencilAttachment();
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000837}
838
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500839const FramebufferAttachment *Framebuffer::getStencilOrDepthStencilAttachment() const
840{
841 return mState.getStencilOrDepthStencilAttachment();
842}
843
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400844const FramebufferAttachment *Framebuffer::getReadColorAttachment() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000845{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400846 return mState.getReadAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000847}
848
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400849GLenum Framebuffer::getReadColorAttachmentType() const
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000850{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400851 const FramebufferAttachment *readAttachment = mState.getReadAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400852 return (readAttachment != nullptr ? readAttachment->type() : GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000853}
854
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400855const FramebufferAttachment *Framebuffer::getFirstColorAttachment() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000856{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400857 return mState.getFirstColorAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000858}
859
Jamie Madill6dd06ea2017-07-19 13:47:55 -0400860const FramebufferAttachment *Framebuffer::getFirstNonNullAttachment() const
861{
862 return mState.getFirstNonNullAttachment();
863}
864
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800865const FramebufferAttachment *Framebuffer::getAttachment(const Context *context,
866 GLenum attachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000867{
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800868 return mState.getAttachment(context, attachment);
Geoff Lang55ba29c2013-07-11 16:57:53 -0400869}
870
Geoff Langa15472a2015-08-11 11:48:03 -0400871size_t Framebuffer::getDrawbufferStateCount() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000872{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400873 return mState.mDrawBufferStates.size();
Geoff Langa15472a2015-08-11 11:48:03 -0400874}
875
876GLenum Framebuffer::getDrawBufferState(size_t drawBuffer) const
877{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400878 ASSERT(drawBuffer < mState.mDrawBufferStates.size());
879 return mState.mDrawBufferStates[drawBuffer];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000880}
881
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500882const std::vector<GLenum> &Framebuffer::getDrawBufferStates() const
883{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400884 return mState.getDrawBufferStates();
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500885}
886
Geoff Lang164d54e2014-12-01 10:55:33 -0500887void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000888{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400889 auto &drawStates = mState.mDrawBufferStates;
Jamie Madilld1405e52015-03-05 15:41:39 -0500890
891 ASSERT(count <= drawStates.size());
892 std::copy(buffers, buffers + count, drawStates.begin());
893 std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500894 mDirtyBits.set(DIRTY_BIT_DRAW_BUFFERS);
Jamie Madilla4595b82017-01-11 17:36:34 -0500895
896 mState.mEnabledDrawBuffers.reset();
Brandon Jones76746f92017-11-22 11:44:41 -0800897 mState.mDrawBufferTypeMask.reset();
898
Jamie Madilla4595b82017-01-11 17:36:34 -0500899 for (size_t index = 0; index < count; ++index)
900 {
Jamie Madill6e18a232019-01-16 13:27:14 -0500901 SetComponentTypeMask(getDrawbufferWriteType(index), index, &mState.mDrawBufferTypeMask);
Brandon Jones76746f92017-11-22 11:44:41 -0800902
Jamie Madilla4595b82017-01-11 17:36:34 -0500903 if (drawStates[index] != GL_NONE && mState.mColorAttachments[index].isAttached())
904 {
905 mState.mEnabledDrawBuffers.set(index);
906 }
907 }
Geoff Lang9dd95802014-12-01 11:12:59 -0500908}
909
Geoff Langa15472a2015-08-11 11:48:03 -0400910const FramebufferAttachment *Framebuffer::getDrawBuffer(size_t drawBuffer) const
911{
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400912 return mState.getDrawBuffer(drawBuffer);
Geoff Langa15472a2015-08-11 11:48:03 -0400913}
914
Jamie Madill6e18a232019-01-16 13:27:14 -0500915ComponentType Framebuffer::getDrawbufferWriteType(size_t drawBuffer) const
Geoff Lange0cff192017-05-30 13:04:56 -0400916{
917 const FramebufferAttachment *attachment = mState.getDrawBuffer(drawBuffer);
918 if (attachment == nullptr)
919 {
Jamie Madill6e18a232019-01-16 13:27:14 -0500920 return ComponentType::NoType;
Geoff Lange0cff192017-05-30 13:04:56 -0400921 }
922
923 GLenum componentType = attachment->getFormat().info->componentType;
924 switch (componentType)
925 {
926 case GL_INT:
Jamie Madill6e18a232019-01-16 13:27:14 -0500927 return ComponentType::Int;
Geoff Lange0cff192017-05-30 13:04:56 -0400928 case GL_UNSIGNED_INT:
Jamie Madill6e18a232019-01-16 13:27:14 -0500929 return ComponentType::UnsignedInt;
Geoff Lange0cff192017-05-30 13:04:56 -0400930
931 default:
Jamie Madill6e18a232019-01-16 13:27:14 -0500932 return ComponentType::Float;
Geoff Lange0cff192017-05-30 13:04:56 -0400933 }
934}
935
Brandon Jonesc405ae72017-12-06 14:15:03 -0800936ComponentTypeMask Framebuffer::getDrawBufferTypeMask() const
Brandon Jones76746f92017-11-22 11:44:41 -0800937{
938 return mState.mDrawBufferTypeMask;
939}
940
941DrawBufferMask Framebuffer::getDrawBufferMask() const
942{
943 return mState.mEnabledDrawBuffers;
944}
945
Geoff Langa15472a2015-08-11 11:48:03 -0400946bool Framebuffer::hasEnabledDrawBuffer() const
947{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400948 for (size_t drawbufferIdx = 0; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
Geoff Langa15472a2015-08-11 11:48:03 -0400949 {
950 if (getDrawBuffer(drawbufferIdx) != nullptr)
951 {
952 return true;
953 }
954 }
955
956 return false;
957}
958
Geoff Lang9dd95802014-12-01 11:12:59 -0500959GLenum Framebuffer::getReadBufferState() const
960{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400961 return mState.mReadBufferState;
Geoff Lang9dd95802014-12-01 11:12:59 -0500962}
963
964void Framebuffer::setReadBuffer(GLenum buffer)
965{
Jamie Madillb885e572015-02-03 16:16:04 -0500966 ASSERT(buffer == GL_BACK || buffer == GL_NONE ||
967 (buffer >= GL_COLOR_ATTACHMENT0 &&
Jamie Madill48ef11b2016-04-27 15:21:52 -0400968 (buffer - GL_COLOR_ATTACHMENT0) < mState.mColorAttachments.size()));
969 mState.mReadBufferState = buffer;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500970 mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000971}
972
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400973size_t Framebuffer::getNumColorAttachments() const
Corentin Wallez37c39792015-08-20 14:19:46 -0400974{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400975 return mState.mColorAttachments.size();
Corentin Wallez37c39792015-08-20 14:19:46 -0400976}
977
Jamie Madill0df8fe42015-11-24 16:10:24 -0500978bool Framebuffer::hasDepth() const
979{
Jamie Madill9c335862017-07-18 11:51:38 -0400980 return mState.hasDepth();
Jamie Madill0df8fe42015-11-24 16:10:24 -0500981}
982
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000983bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000984{
Jamie Madill9c335862017-07-18 11:51:38 -0400985 return mState.hasStencil();
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000986}
987
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000988bool Framebuffer::usingExtendedDrawBuffers() const
989{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400990 for (size_t drawbufferIdx = 1; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000991 {
Geoff Langa15472a2015-08-11 11:48:03 -0400992 if (getDrawBuffer(drawbufferIdx) != nullptr)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000993 {
994 return true;
995 }
996 }
997
998 return false;
999}
1000
Jamie Madill124f78c2019-06-18 11:48:24 -04001001void Framebuffer::invalidateCompletenessCache()
Geoff Lang9aded172017-04-05 11:07:56 -04001002{
Tim Van Patten56ba54c2019-08-08 13:03:34 -06001003 if (!isDefault())
Geoff Lang9aded172017-04-05 11:07:56 -04001004 {
1005 mCachedStatus.reset();
1006 }
Jamie Madill124f78c2019-06-18 11:48:24 -04001007 onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
Geoff Lang9aded172017-04-05 11:07:56 -04001008}
1009
Jamie Madillcc73f242018-08-01 11:34:48 -04001010GLenum Framebuffer::checkStatusImpl(const Context *context)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001011{
Jamie Madillcc73f242018-08-01 11:34:48 -04001012 ASSERT(!isDefault());
1013 ASSERT(hasAnyDirtyBit() || !mCachedStatus.valid());
Geoff Lang528ce3c2014-12-01 10:44:07 -05001014
Jamie Madillcc73f242018-08-01 11:34:48 -04001015 mCachedStatus = checkStatusWithGLFrontEnd(context);
Jamie Madille98b1b52018-03-08 09:47:23 -05001016
Jamie Madillcc73f242018-08-01 11:34:48 -04001017 if (mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE)
1018 {
Jamie Madill67220092019-05-20 11:12:53 -04001019 // We can skip syncState on several back-ends.
1020 if (mImpl->shouldSyncStateBeforeCheckStatus())
Jamie Madille98b1b52018-03-08 09:47:23 -05001021 {
Jamie Madill67220092019-05-20 11:12:53 -04001022 angle::Result err = syncState(context);
1023 if (err != angle::Result::Continue)
1024 {
1025 return 0;
1026 }
Jamie Madillcc73f242018-08-01 11:34:48 -04001027 }
Jamie Madill67220092019-05-20 11:12:53 -04001028
Jamie Madillcc73f242018-08-01 11:34:48 -04001029 if (!mImpl->checkStatus(context))
1030 {
1031 mCachedStatus = GL_FRAMEBUFFER_UNSUPPORTED;
Jamie Madille98b1b52018-03-08 09:47:23 -05001032 }
Jamie Madill362876b2016-06-16 14:46:59 -04001033 }
1034
Jamie Madill427064d2018-04-13 16:20:34 -04001035 return mCachedStatus.value();
Jamie Madill362876b2016-06-16 14:46:59 -04001036}
1037
Jamie Madille98b1b52018-03-08 09:47:23 -05001038GLenum Framebuffer::checkStatusWithGLFrontEnd(const Context *context)
Jamie Madill362876b2016-06-16 14:46:59 -04001039{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001040 const State &state = context->getState();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001041
Tim Van Patten56ba54c2019-08-08 13:03:34 -06001042 ASSERT(!isDefault());
Jamie Madill362876b2016-06-16 14:46:59 -04001043
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001044 bool hasAttachments = false;
1045 Optional<unsigned int> colorbufferSize;
1046 Optional<int> samples;
Geoff Lang92019432017-11-20 13:09:34 -05001047 Optional<bool> fixedSampleLocations;
JiangYizhou461d9a32017-01-04 16:37:26 +08001048 bool hasRenderbuffer = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001049
Martin Radev9bc9a322017-07-21 14:28:17 +03001050 const FramebufferAttachment *firstAttachment = getFirstNonNullAttachment();
1051
Jiawei Shaoa8802472018-05-28 11:17:47 +08001052 Optional<bool> isLayered;
1053 Optional<TextureType> colorAttachmentsTextureType;
1054
Jamie Madill48ef11b2016-04-27 15:21:52 -04001055 for (const FramebufferAttachment &colorAttachment : mState.mColorAttachments)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001056 {
Jamie Madill2d06b732015-04-20 12:53:28 -04001057 if (colorAttachment.isAttached())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001058 {
Geoff Lang9f10b772017-05-16 15:51:03 -04001059 if (!CheckAttachmentCompleteness(context, colorAttachment))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001060 {
1061 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1062 }
daniel@transgaming.com01868132010-08-24 19:21:17 +00001063
Geoff Lang677bb6f2017-04-05 12:40:40 -04001064 const InternalFormat &format = *colorAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -04001065 if (format.depthBits > 0 || format.stencilBits > 0)
1066 {
1067 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1068 }
1069
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001070 if (!CheckAttachmentSampleCompleteness(context, colorAttachment, true, &samples,
1071 &fixedSampleLocations))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001072 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001073 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001074 }
1075
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001076 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
1077 // in GLES 3.0, there is no such restriction
1078 if (state.getClientMajorVersion() < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001079 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001080 if (colorbufferSize.valid())
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001081 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001082 if (format.pixelBytes != colorbufferSize.value())
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +00001083 {
1084 return GL_FRAMEBUFFER_UNSUPPORTED;
1085 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001086 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001087 else
1088 {
1089 colorbufferSize = format.pixelBytes;
1090 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001091 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001092
Martin Radev9bc9a322017-07-21 14:28:17 +03001093 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &colorAttachment))
1094 {
Mingyu Hu7d64c482019-03-12 14:27:40 -07001095 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR;
Martin Radev9bc9a322017-07-21 14:28:17 +03001096 }
1097
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001098 hasRenderbuffer = hasRenderbuffer || (colorAttachment.type() == GL_RENDERBUFFER);
Jiawei Shaoa8802472018-05-28 11:17:47 +08001099
1100 if (!hasAttachments)
1101 {
1102 isLayered = colorAttachment.isLayered();
1103 if (isLayered.value())
1104 {
1105 colorAttachmentsTextureType = colorAttachment.getTextureImageIndex().getType();
1106 }
1107 hasAttachments = true;
1108 }
1109 else
1110 {
1111 // [EXT_geometry_shader] section 9.4.1, "Framebuffer Completeness"
1112 // If any framebuffer attachment is layered, all populated attachments
1113 // must be layered. Additionally, all populated color attachments must
1114 // be from textures of the same target. {FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT }
1115 ASSERT(isLayered.valid());
1116 if (isLayered.value() != colorAttachment.isLayered())
1117 {
1118 return GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT;
1119 }
1120 else if (isLayered.value())
1121 {
1122 ASSERT(colorAttachmentsTextureType.valid());
1123 if (colorAttachmentsTextureType.value() !=
1124 colorAttachment.getTextureImageIndex().getType())
1125 {
1126 return GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT;
1127 }
1128 }
1129 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001130 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001131 }
1132
Jamie Madill48ef11b2016-04-27 15:21:52 -04001133 const FramebufferAttachment &depthAttachment = mState.mDepthAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -04001134 if (depthAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001135 {
Geoff Lang9f10b772017-05-16 15:51:03 -04001136 if (!CheckAttachmentCompleteness(context, depthAttachment))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001137 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001138 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001139 }
1140
Geoff Lang677bb6f2017-04-05 12:40:40 -04001141 const InternalFormat &format = *depthAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -04001142 if (format.depthBits == 0)
1143 {
1144 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001145 }
1146
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001147 if (!CheckAttachmentSampleCompleteness(context, depthAttachment, false, &samples,
1148 &fixedSampleLocations))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001149 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001150 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001151 }
Sami Väisänena797e062016-05-12 15:23:40 +03001152
Martin Radev9bc9a322017-07-21 14:28:17 +03001153 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &depthAttachment))
1154 {
Mingyu Hu7d64c482019-03-12 14:27:40 -07001155 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR;
Martin Radev9bc9a322017-07-21 14:28:17 +03001156 }
1157
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001158 hasRenderbuffer = hasRenderbuffer || (depthAttachment.type() == GL_RENDERBUFFER);
Jiawei Shaoa8802472018-05-28 11:17:47 +08001159
1160 if (!hasAttachments)
1161 {
1162 isLayered = depthAttachment.isLayered();
1163 hasAttachments = true;
1164 }
1165 else
1166 {
1167 // [EXT_geometry_shader] section 9.4.1, "Framebuffer Completeness"
1168 // If any framebuffer attachment is layered, all populated attachments
1169 // must be layered. {FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT }
1170 ASSERT(isLayered.valid());
1171 if (isLayered.value() != depthAttachment.isLayered())
1172 {
1173 return GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT;
1174 }
1175 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001176 }
1177
Jamie Madill48ef11b2016-04-27 15:21:52 -04001178 const FramebufferAttachment &stencilAttachment = mState.mStencilAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -04001179 if (stencilAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001180 {
Geoff Lang9f10b772017-05-16 15:51:03 -04001181 if (!CheckAttachmentCompleteness(context, stencilAttachment))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001182 {
1183 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1184 }
1185
Geoff Lang677bb6f2017-04-05 12:40:40 -04001186 const InternalFormat &format = *stencilAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -04001187 if (format.stencilBits == 0)
1188 {
1189 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001190 }
1191
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001192 if (!CheckAttachmentSampleCompleteness(context, stencilAttachment, false, &samples,
1193 &fixedSampleLocations))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001194 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001195 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001196 }
Corentin Wallez086d59a2016-04-29 09:06:49 -04001197
Martin Radev9bc9a322017-07-21 14:28:17 +03001198 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &stencilAttachment))
1199 {
Mingyu Hu7d64c482019-03-12 14:27:40 -07001200 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR;
Martin Radev9bc9a322017-07-21 14:28:17 +03001201 }
1202
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001203 hasRenderbuffer = hasRenderbuffer || (stencilAttachment.type() == GL_RENDERBUFFER);
Jiawei Shaoa8802472018-05-28 11:17:47 +08001204
1205 if (!hasAttachments)
1206 {
1207 hasAttachments = true;
1208 }
1209 else
1210 {
1211 // [EXT_geometry_shader] section 9.4.1, "Framebuffer Completeness"
1212 // If any framebuffer attachment is layered, all populated attachments
1213 // must be layered.
1214 // {FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT }
1215 ASSERT(isLayered.valid());
1216 if (isLayered.value() != stencilAttachment.isLayered())
1217 {
1218 return GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT;
1219 }
1220 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001221 }
1222
1223 // Starting from ES 3.0 stencil and depth, if present, should be the same image
1224 if (state.getClientMajorVersion() >= 3 && depthAttachment.isAttached() &&
1225 stencilAttachment.isAttached() && stencilAttachment != depthAttachment)
1226 {
1227 return GL_FRAMEBUFFER_UNSUPPORTED;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001228 }
1229
Jamie Madilla02315b2017-02-23 14:14:47 -05001230 // Special additional validation for WebGL 1 DEPTH/STENCIL/DEPTH_STENCIL.
1231 if (state.isWebGL1())
1232 {
1233 if (!mState.mWebGLDepthStencilConsistent)
1234 {
1235 return GL_FRAMEBUFFER_UNSUPPORTED;
1236 }
1237
1238 if (mState.mWebGLDepthStencilAttachment.isAttached())
1239 {
1240 if (mState.mWebGLDepthStencilAttachment.getDepthSize() == 0 ||
1241 mState.mWebGLDepthStencilAttachment.getStencilSize() == 0)
1242 {
1243 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1244 }
Martin Radev9bc9a322017-07-21 14:28:17 +03001245
1246 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment,
1247 &mState.mWebGLDepthStencilAttachment))
1248 {
Mingyu Hu7d64c482019-03-12 14:27:40 -07001249 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR;
Martin Radev9bc9a322017-07-21 14:28:17 +03001250 }
Jamie Madilla02315b2017-02-23 14:14:47 -05001251 }
1252 else if (mState.mStencilAttachment.isAttached() &&
1253 mState.mStencilAttachment.getDepthSize() > 0)
1254 {
1255 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1256 }
1257 else if (mState.mDepthAttachment.isAttached() &&
1258 mState.mDepthAttachment.getStencilSize() > 0)
1259 {
1260 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1261 }
1262 }
1263
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001264 // ES3.1(section 9.4) requires that if no image is attached to the framebuffer, and either the
1265 // value of the framebuffer's FRAMEBUFFER_DEFAULT_WIDTH or FRAMEBUFFER_DEFAULT_HEIGHT parameters
1266 // is zero, the framebuffer is considered incomplete.
JiangYizhou461d9a32017-01-04 16:37:26 +08001267 GLint defaultWidth = mState.getDefaultWidth();
1268 GLint defaultHeight = mState.getDefaultHeight();
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001269 if (!hasAttachments && (defaultWidth == 0 || defaultHeight == 0))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001270 {
1271 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001272 }
1273
Geoff Langa0e0aeb2017-04-12 15:06:29 -04001274 // In ES 2.0 and WebGL, all color attachments must have the same width and height.
Jamie Madillcc86d642015-11-24 13:00:07 -05001275 // In ES 3.0, there is no such restriction.
Geoff Langa0e0aeb2017-04-12 15:06:29 -04001276 if ((state.getClientMajorVersion() < 3 || state.getExtensions().webglCompatibility) &&
1277 !mState.attachmentsHaveSameDimensions())
Jamie Madillcc86d642015-11-24 13:00:07 -05001278 {
1279 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
1280 }
1281
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001282 // ES3.1(section 9.4) requires that if the attached images are a mix of renderbuffers and
1283 // textures, the value of TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all attached textures.
JiangYizhou461d9a32017-01-04 16:37:26 +08001284 if (fixedSampleLocations.valid() && hasRenderbuffer && !fixedSampleLocations.value())
1285 {
1286 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1287 }
1288
Kenneth Russellce8602a2017-10-03 18:23:08 -07001289 // The WebGL conformance tests implicitly define that all framebuffer
1290 // attachments must be unique. For example, the same level of a texture can
1291 // not be attached to two different color attachments.
1292 if (state.getExtensions().webglCompatibility)
1293 {
1294 if (!mState.colorAttachmentsAreUniqueImages())
1295 {
1296 return GL_FRAMEBUFFER_UNSUPPORTED;
1297 }
1298 }
1299
Jamie Madillcc86d642015-11-24 13:00:07 -05001300 return GL_FRAMEBUFFER_COMPLETE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001301}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001302
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001303angle::Result Framebuffer::discard(const Context *context, size_t count, const GLenum *attachments)
Austin Kinross08332632015-05-05 13:35:47 -07001304{
Jamie Madill05b35b22017-10-03 09:01:44 -04001305 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1306 // can be no-ops, so we should probably do that to ensure consistency.
1307 // TODO(jmadill): WebGL behaviour, and robust resource init behaviour without WebGL.
1308
Jamie Madill4928b7c2017-06-20 12:57:39 -04001309 return mImpl->discard(context, count, attachments);
Austin Kinross08332632015-05-05 13:35:47 -07001310}
1311
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001312angle::Result Framebuffer::invalidate(const Context *context,
1313 size_t count,
1314 const GLenum *attachments)
Jamie Madill2d96b9e2014-08-29 15:46:47 -04001315{
Jamie Madill05b35b22017-10-03 09:01:44 -04001316 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1317 // can be no-ops, so we should probably do that to ensure consistency.
1318 // TODO(jmadill): WebGL behaviour, and robust resource init behaviour without WebGL.
1319
Jamie Madill4928b7c2017-06-20 12:57:39 -04001320 return mImpl->invalidate(context, count, attachments);
Jamie Madill2d96b9e2014-08-29 15:46:47 -04001321}
1322
Jamie Madill05b35b22017-10-03 09:01:44 -04001323bool Framebuffer::partialClearNeedsInit(const Context *context,
1324 bool color,
1325 bool depth,
1326 bool stencil)
1327{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001328 const auto &glState = context->getState();
Jamie Madill05b35b22017-10-03 09:01:44 -04001329
1330 if (!glState.isRobustResourceInitEnabled())
1331 {
1332 return false;
1333 }
1334
1335 // Scissors can affect clearing.
1336 // TODO(jmadill): Check for complete scissor overlap.
1337 if (glState.isScissorTestEnabled())
1338 {
1339 return true;
1340 }
1341
1342 // If colors masked, we must clear before we clear. Do a simple check.
1343 // TODO(jmadill): Filter out unused color channels from the test.
1344 if (color)
1345 {
1346 const auto &blend = glState.getBlendState();
1347 if (!(blend.colorMaskRed && blend.colorMaskGreen && blend.colorMaskBlue &&
1348 blend.colorMaskAlpha))
1349 {
1350 return true;
1351 }
1352 }
1353
1354 const auto &depthStencil = glState.getDepthStencilState();
Yuly Novikov21edf3d2018-07-23 16:44:16 -04001355 if (stencil && (depthStencil.stencilMask != depthStencil.stencilWritemask ||
1356 depthStencil.stencilBackMask != depthStencil.stencilBackWritemask))
Jamie Madill05b35b22017-10-03 09:01:44 -04001357 {
1358 return true;
1359 }
1360
1361 return false;
1362}
1363
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001364angle::Result Framebuffer::invalidateSub(const Context *context,
1365 size_t count,
1366 const GLenum *attachments,
1367 const Rectangle &area)
Jamie Madill400a4412014-08-29 15:46:45 -04001368{
Jamie Madill05b35b22017-10-03 09:01:44 -04001369 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1370 // can be no-ops, so we should probably do that to ensure consistency.
1371 // TODO(jmadill): Make a invalidate no-op in WebGL 2.0.
1372
Jamie Madill4928b7c2017-06-20 12:57:39 -04001373 return mImpl->invalidateSub(context, count, attachments, area);
Jamie Madill400a4412014-08-29 15:46:45 -04001374}
1375
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001376angle::Result Framebuffer::clear(const Context *context, GLbitfield mask)
Geoff Langb04dc822014-12-01 12:02:02 -05001377{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001378 const auto &glState = context->getState();
Jamie Madill05b35b22017-10-03 09:01:44 -04001379 if (glState.isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -05001380 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001381 return angle::Result::Continue;
Jamie Madill984ef412015-11-24 16:10:21 -05001382 }
1383
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -04001384 // Remove clear bits that are ineffective. An effective clear changes at least one fragment. If
1385 // color/depth/stencil masks make the clear ineffective we skip it altogether.
1386
1387 // If all color channels are masked, don't attempt to clear color.
1388 if (context->getState().getBlendState().allChannelsMasked())
1389 {
1390 mask &= ~GL_COLOR_BUFFER_BIT;
1391 }
1392
1393 // If depth write is disabled, don't attempt to clear depth.
1394 if (!context->getState().getDepthStencilState().depthMask)
1395 {
1396 mask &= ~GL_DEPTH_BUFFER_BIT;
1397 }
1398
1399 // If all stencil bits are masked, don't attempt to clear stencil.
1400 if (context->getState().getDepthStencilState().stencilWritemask == 0)
1401 {
1402 mask &= ~GL_STENCIL_BUFFER_BIT;
1403 }
1404
1405 if (mask != 0)
1406 {
1407 ANGLE_TRY(mImpl->clear(context, mask));
1408 }
Jamie Madill05b35b22017-10-03 09:01:44 -04001409
Jamie Madill7c985f52018-11-29 18:16:17 -05001410 return angle::Result::Continue;
Geoff Langb04dc822014-12-01 12:02:02 -05001411}
1412
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001413angle::Result Framebuffer::clearBufferfv(const Context *context,
1414 GLenum buffer,
1415 GLint drawbuffer,
1416 const GLfloat *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001417{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001418 if (context->getState().isRasterizerDiscardEnabled() || IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001419 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001420 return angle::Result::Continue;
Jamie Madill984ef412015-11-24 16:10:21 -05001421 }
1422
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -04001423 if (buffer == GL_DEPTH)
1424 {
1425 // If depth write is disabled, don't attempt to clear depth.
1426 if (!context->getState().getDepthStencilState().depthMask)
1427 {
1428 return angle::Result::Continue;
1429 }
1430 }
1431 else
1432 {
1433 // If all color channels are masked, don't attempt to clear color.
1434 if (context->getState().getBlendState().allChannelsMasked())
1435 {
1436 return angle::Result::Continue;
1437 }
1438 }
1439
Jamie Madill05b35b22017-10-03 09:01:44 -04001440 ANGLE_TRY(mImpl->clearBufferfv(context, buffer, drawbuffer, values));
1441
Jamie Madill7c985f52018-11-29 18:16:17 -05001442 return angle::Result::Continue;
Geoff Langb04dc822014-12-01 12:02:02 -05001443}
1444
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001445angle::Result Framebuffer::clearBufferuiv(const Context *context,
1446 GLenum buffer,
1447 GLint drawbuffer,
1448 const GLuint *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001449{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001450 if (context->getState().isRasterizerDiscardEnabled() || IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001451 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001452 return angle::Result::Continue;
Jamie Madill984ef412015-11-24 16:10:21 -05001453 }
1454
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -04001455 // If all color channels are masked, don't attempt to clear color.
1456 if (context->getState().getBlendState().allChannelsMasked())
1457 {
1458 return angle::Result::Continue;
1459 }
1460
Jamie Madill05b35b22017-10-03 09:01:44 -04001461 ANGLE_TRY(mImpl->clearBufferuiv(context, buffer, drawbuffer, values));
1462
Jamie Madill7c985f52018-11-29 18:16:17 -05001463 return angle::Result::Continue;
Geoff Langb04dc822014-12-01 12:02:02 -05001464}
1465
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001466angle::Result Framebuffer::clearBufferiv(const Context *context,
1467 GLenum buffer,
1468 GLint drawbuffer,
1469 const GLint *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001470{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001471 if (context->getState().isRasterizerDiscardEnabled() || IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001472 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001473 return angle::Result::Continue;
Jamie Madill984ef412015-11-24 16:10:21 -05001474 }
1475
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -04001476 if (buffer == GL_STENCIL)
1477 {
1478 // If all stencil bits are masked, don't attempt to clear stencil.
1479 if (context->getState().getDepthStencilState().stencilWritemask == 0)
1480 {
1481 return angle::Result::Continue;
1482 }
1483 }
1484 else
1485 {
1486 // If all color channels are masked, don't attempt to clear color.
1487 if (context->getState().getBlendState().allChannelsMasked())
1488 {
1489 return angle::Result::Continue;
1490 }
1491 }
1492
Jamie Madill05b35b22017-10-03 09:01:44 -04001493 ANGLE_TRY(mImpl->clearBufferiv(context, buffer, drawbuffer, values));
1494
Jamie Madill7c985f52018-11-29 18:16:17 -05001495 return angle::Result::Continue;
Geoff Langb04dc822014-12-01 12:02:02 -05001496}
1497
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001498angle::Result Framebuffer::clearBufferfi(const Context *context,
1499 GLenum buffer,
1500 GLint drawbuffer,
1501 GLfloat depth,
1502 GLint stencil)
Geoff Langb04dc822014-12-01 12:02:02 -05001503{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001504 if (context->getState().isRasterizerDiscardEnabled() || IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001505 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001506 return angle::Result::Continue;
Jamie Madill984ef412015-11-24 16:10:21 -05001507 }
1508
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -04001509 bool clearDepth = context->getState().getDepthStencilState().depthMask;
1510 bool clearStencil = context->getState().getDepthStencilState().stencilWritemask != 0;
1511
1512 if (clearDepth && clearStencil)
1513 {
1514 ASSERT(buffer == GL_DEPTH_STENCIL);
1515 ANGLE_TRY(mImpl->clearBufferfi(context, GL_DEPTH_STENCIL, drawbuffer, depth, stencil));
1516 }
1517 else if (clearDepth && !clearStencil)
1518 {
1519 ANGLE_TRY(mImpl->clearBufferfv(context, GL_DEPTH, drawbuffer, &depth));
1520 }
1521 else if (!clearDepth && clearStencil)
1522 {
1523 ANGLE_TRY(mImpl->clearBufferiv(context, GL_STENCIL, drawbuffer, &stencil));
1524 }
Jamie Madill05b35b22017-10-03 09:01:44 -04001525
Jamie Madill7c985f52018-11-29 18:16:17 -05001526 return angle::Result::Continue;
Geoff Langb04dc822014-12-01 12:02:02 -05001527}
1528
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001529angle::Result Framebuffer::getImplementationColorReadFormat(const Context *context,
1530 GLenum *formatOut)
Geoff Langbce529e2014-12-01 12:48:41 -05001531{
Jamie Madill690c8eb2018-03-12 15:20:03 -04001532 ANGLE_TRY(syncState(context));
1533 *formatOut = mImpl->getImplementationColorReadFormat(context);
Jamie Madill7c985f52018-11-29 18:16:17 -05001534 return angle::Result::Continue;
Geoff Langbce529e2014-12-01 12:48:41 -05001535}
1536
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001537angle::Result Framebuffer::getImplementationColorReadType(const Context *context, GLenum *typeOut)
Geoff Langbce529e2014-12-01 12:48:41 -05001538{
Jamie Madill690c8eb2018-03-12 15:20:03 -04001539 ANGLE_TRY(syncState(context));
1540 *typeOut = mImpl->getImplementationColorReadType(context);
Jamie Madill7c985f52018-11-29 18:16:17 -05001541 return angle::Result::Continue;
Geoff Langbce529e2014-12-01 12:48:41 -05001542}
1543
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001544angle::Result Framebuffer::readPixels(const Context *context,
1545 const Rectangle &area,
1546 GLenum format,
1547 GLenum type,
1548 void *pixels)
Geoff Langbce529e2014-12-01 12:48:41 -05001549{
Jamie Madill362876b2016-06-16 14:46:59 -04001550 ANGLE_TRY(mImpl->readPixels(context, area, format, type, pixels));
Geoff Lang520c4ae2015-05-05 13:12:36 -04001551
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001552 Buffer *unpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Lang520c4ae2015-05-05 13:12:36 -04001553 if (unpackBuffer)
1554 {
James Dong020abb82019-07-24 11:33:49 -06001555 unpackBuffer->onDataChanged();
Geoff Lang520c4ae2015-05-05 13:12:36 -04001556 }
1557
Jamie Madill7c985f52018-11-29 18:16:17 -05001558 return angle::Result::Continue;
Geoff Langbce529e2014-12-01 12:48:41 -05001559}
1560
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001561angle::Result Framebuffer::blit(const Context *context,
1562 const Rectangle &sourceArea,
1563 const Rectangle &destArea,
1564 GLbitfield mask,
1565 GLenum filter)
Geoff Lang54bd5a42014-12-01 12:51:04 -05001566{
He Yunchao6be602d2016-12-22 14:33:07 +08001567 GLbitfield blitMask = mask;
1568
1569 // Note that blitting is called against draw framebuffer.
1570 // See the code in gl::Context::blitFramebuffer.
1571 if ((mask & GL_COLOR_BUFFER_BIT) && !hasEnabledDrawBuffer())
1572 {
1573 blitMask &= ~GL_COLOR_BUFFER_BIT;
1574 }
1575
1576 if ((mask & GL_STENCIL_BUFFER_BIT) && mState.getStencilAttachment() == nullptr)
1577 {
1578 blitMask &= ~GL_STENCIL_BUFFER_BIT;
1579 }
1580
1581 if ((mask & GL_DEPTH_BUFFER_BIT) && mState.getDepthAttachment() == nullptr)
1582 {
1583 blitMask &= ~GL_DEPTH_BUFFER_BIT;
1584 }
1585
1586 if (!blitMask)
1587 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001588 return angle::Result::Continue;
He Yunchao6be602d2016-12-22 14:33:07 +08001589 }
1590
1591 return mImpl->blit(context, sourceArea, destArea, blitMask, filter);
Geoff Lang54bd5a42014-12-01 12:51:04 -05001592}
1593
Jamie Madill427064d2018-04-13 16:20:34 -04001594int Framebuffer::getSamples(const Context *context)
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001595{
Jamie Madill427064d2018-04-13 16:20:34 -04001596 return (isComplete(context) ? getCachedSamples(context) : 0);
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001597}
1598
Shahbaz Youssefif2a1c382019-05-21 16:32:49 -04001599int Framebuffer::getCachedSamples(const Context *context) const
Jamie Madill9c335862017-07-18 11:51:38 -04001600{
Jamie Madill5b772312018-03-08 20:28:32 -05001601 ASSERT(mCachedStatus.valid() && mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE);
1602
Jamie Madill9c335862017-07-18 11:51:38 -04001603 // For a complete framebuffer, all attachments must have the same sample count.
1604 // In this case return the first nonzero sample size.
1605 const auto *firstNonNullAttachment = mState.getFirstNonNullAttachment();
1606 if (firstNonNullAttachment)
1607 {
1608 ASSERT(firstNonNullAttachment->isAttached());
1609 return firstNonNullAttachment->getSamples();
1610 }
1611
1612 // No attachments found.
1613 return 0;
1614}
1615
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001616angle::Result Framebuffer::getSamplePosition(const Context *context,
1617 size_t index,
1618 GLfloat *xy) const
Corentin Wallezccab69d2017-01-27 16:57:15 -05001619{
Geoff Lang13455072018-05-09 11:24:43 -04001620 ANGLE_TRY(mImpl->getSamplePosition(context, index, xy));
Jamie Madill7c985f52018-11-29 18:16:17 -05001621 return angle::Result::Continue;
Corentin Wallezccab69d2017-01-27 16:57:15 -05001622}
1623
Jamie Madille261b442014-06-25 12:42:21 -04001624bool Framebuffer::hasValidDepthStencil() const
1625{
Jamie Madill48ef11b2016-04-27 15:21:52 -04001626 return mState.getDepthStencilAttachment() != nullptr;
Jamie Madille261b442014-06-25 12:42:21 -04001627}
1628
Jamie Madilla02315b2017-02-23 14:14:47 -05001629void Framebuffer::setAttachment(const Context *context,
1630 GLenum type,
Jamie Madill2d06b732015-04-20 12:53:28 -04001631 GLenum binding,
1632 const ImageIndex &textureIndex,
1633 FramebufferAttachmentObject *resource)
Geoff Langab75a052014-10-15 12:56:37 -04001634{
Martin Radev5dae57b2017-07-14 16:15:55 +03001635 setAttachment(context, type, binding, textureIndex, resource,
1636 FramebufferAttachment::kDefaultNumViews,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001637 FramebufferAttachment::kDefaultBaseViewIndex, false);
Martin Radev5dae57b2017-07-14 16:15:55 +03001638}
1639
1640void Framebuffer::setAttachment(const Context *context,
1641 GLenum type,
1642 GLenum binding,
1643 const ImageIndex &textureIndex,
1644 FramebufferAttachmentObject *resource,
1645 GLsizei numViews,
1646 GLuint baseViewIndex,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001647 bool isMultiview)
Martin Radev5dae57b2017-07-14 16:15:55 +03001648{
Jamie Madilla02315b2017-02-23 14:14:47 -05001649 // Context may be null in unit tests.
1650 if (!context || !context->isWebGL1())
1651 {
Martin Radev5dae57b2017-07-14 16:15:55 +03001652 setAttachmentImpl(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001653 isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001654 return;
1655 }
1656
1657 switch (binding)
1658 {
1659 case GL_DEPTH_STENCIL:
1660 case GL_DEPTH_STENCIL_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001661 mState.mWebGLDepthStencilAttachment.attach(context, type, binding, textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001662 resource, numViews, baseViewIndex,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001663 isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001664 break;
1665 case GL_DEPTH:
1666 case GL_DEPTH_ATTACHMENT:
Martin Radev5dae57b2017-07-14 16:15:55 +03001667 mState.mWebGLDepthAttachment.attach(context, type, binding, textureIndex, resource,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001668 numViews, baseViewIndex, isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001669 break;
1670 case GL_STENCIL:
1671 case GL_STENCIL_ATTACHMENT:
Martin Radev5dae57b2017-07-14 16:15:55 +03001672 mState.mWebGLStencilAttachment.attach(context, type, binding, textureIndex, resource,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001673 numViews, baseViewIndex, isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001674 break;
1675 default:
Martin Radev5dae57b2017-07-14 16:15:55 +03001676 setAttachmentImpl(context, type, binding, textureIndex, resource, numViews,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001677 baseViewIndex, isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001678 return;
1679 }
1680
Mingyu Hu7d64c482019-03-12 14:27:40 -07001681 commitWebGL1DepthStencilIfConsistent(context, numViews, baseViewIndex, isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001682}
1683
Mingyu Hu7d64c482019-03-12 14:27:40 -07001684void Framebuffer::setAttachmentMultiview(const Context *context,
1685 GLenum type,
1686 GLenum binding,
1687 const ImageIndex &textureIndex,
1688 FramebufferAttachmentObject *resource,
1689 GLsizei numViews,
1690 GLint baseViewIndex)
Martin Radev82ef7742017-08-08 17:44:58 +03001691{
Mingyu Hu7d64c482019-03-12 14:27:40 -07001692 setAttachment(context, type, binding, textureIndex, resource, numViews, baseViewIndex, true);
Martin Radev5dae57b2017-07-14 16:15:55 +03001693}
1694
1695void Framebuffer::commitWebGL1DepthStencilIfConsistent(const Context *context,
1696 GLsizei numViews,
1697 GLuint baseViewIndex,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001698 bool isMultiview)
Jamie Madilla02315b2017-02-23 14:14:47 -05001699{
1700 int count = 0;
1701
1702 std::array<FramebufferAttachment *, 3> attachments = {{&mState.mWebGLDepthStencilAttachment,
1703 &mState.mWebGLDepthAttachment,
1704 &mState.mWebGLStencilAttachment}};
1705 for (FramebufferAttachment *attachment : attachments)
1706 {
1707 if (attachment->isAttached())
1708 {
1709 count++;
1710 }
1711 }
1712
1713 mState.mWebGLDepthStencilConsistent = (count <= 1);
1714 if (!mState.mWebGLDepthStencilConsistent)
1715 {
1716 // Inconsistent.
1717 return;
1718 }
1719
Geoff Lange466c552017-03-17 15:24:12 -04001720 auto getImageIndexIfTextureAttachment = [](const FramebufferAttachment &attachment) {
1721 if (attachment.type() == GL_TEXTURE)
1722 {
1723 return attachment.getTextureImageIndex();
1724 }
1725 else
1726 {
Jamie Madillcc129372018-04-12 09:13:18 -04001727 return ImageIndex();
Geoff Lange466c552017-03-17 15:24:12 -04001728 }
1729 };
1730
Jamie Madilla02315b2017-02-23 14:14:47 -05001731 if (mState.mWebGLDepthAttachment.isAttached())
1732 {
1733 const auto &depth = mState.mWebGLDepthAttachment;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001734 setAttachmentImpl(context, depth.type(), GL_DEPTH_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001735 getImageIndexIfTextureAttachment(depth), depth.getResource(), numViews,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001736 baseViewIndex, isMultiview);
Jamie Madillcc129372018-04-12 09:13:18 -04001737 setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex(), nullptr, numViews,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001738 baseViewIndex, isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001739 }
1740 else if (mState.mWebGLStencilAttachment.isAttached())
1741 {
1742 const auto &stencil = mState.mWebGLStencilAttachment;
Jamie Madillcc129372018-04-12 09:13:18 -04001743 setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex(), nullptr, numViews,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001744 baseViewIndex, isMultiview);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001745 setAttachmentImpl(context, stencil.type(), GL_STENCIL_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001746 getImageIndexIfTextureAttachment(stencil), stencil.getResource(),
Mingyu Hu7d64c482019-03-12 14:27:40 -07001747 numViews, baseViewIndex, isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001748 }
1749 else if (mState.mWebGLDepthStencilAttachment.isAttached())
1750 {
1751 const auto &depthStencil = mState.mWebGLDepthStencilAttachment;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001752 setAttachmentImpl(context, depthStencil.type(), GL_DEPTH_ATTACHMENT,
Geoff Lange466c552017-03-17 15:24:12 -04001753 getImageIndexIfTextureAttachment(depthStencil),
Mingyu Hu7d64c482019-03-12 14:27:40 -07001754 depthStencil.getResource(), numViews, baseViewIndex, isMultiview);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001755 setAttachmentImpl(context, depthStencil.type(), GL_STENCIL_ATTACHMENT,
Geoff Lange466c552017-03-17 15:24:12 -04001756 getImageIndexIfTextureAttachment(depthStencil),
Mingyu Hu7d64c482019-03-12 14:27:40 -07001757 depthStencil.getResource(), numViews, baseViewIndex, isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001758 }
1759 else
1760 {
Jamie Madillcc129372018-04-12 09:13:18 -04001761 setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex(), nullptr, numViews,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001762 baseViewIndex, isMultiview);
Jamie Madillcc129372018-04-12 09:13:18 -04001763 setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex(), nullptr, numViews,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001764 baseViewIndex, isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001765 }
1766}
1767
Jamie Madill4928b7c2017-06-20 12:57:39 -04001768void Framebuffer::setAttachmentImpl(const Context *context,
1769 GLenum type,
Jamie Madilla02315b2017-02-23 14:14:47 -05001770 GLenum binding,
1771 const ImageIndex &textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001772 FramebufferAttachmentObject *resource,
1773 GLsizei numViews,
1774 GLuint baseViewIndex,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001775 bool isMultiview)
Jamie Madilla02315b2017-02-23 14:14:47 -05001776{
Jamie Madilla02315b2017-02-23 14:14:47 -05001777 switch (binding)
1778 {
Jamie Madillb8126692017-04-05 11:22:17 -04001779 case GL_DEPTH_STENCIL:
1780 case GL_DEPTH_STENCIL_ATTACHMENT:
1781 {
1782 // ensure this is a legitimate depth+stencil format
1783 FramebufferAttachmentObject *attachmentObj = resource;
1784 if (resource)
1785 {
Jamie Madill4fd95d52017-04-05 11:22:18 -04001786 const Format &format = resource->getAttachmentFormat(binding, textureIndex);
Jamie Madillb8126692017-04-05 11:22:17 -04001787 if (format.info->depthBits == 0 || format.info->stencilBits == 0)
1788 {
1789 // Attaching nullptr detaches the current attachment.
1790 attachmentObj = nullptr;
1791 }
1792 }
1793
Jamie Madill4928b7c2017-06-20 12:57:39 -04001794 updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
Jamie Madillb8126692017-04-05 11:22:17 -04001795 &mDirtyDepthAttachmentBinding, type, binding, textureIndex,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001796 attachmentObj, numViews, baseViewIndex, isMultiview);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001797 updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
Jamie Madillb8126692017-04-05 11:22:17 -04001798 &mDirtyStencilAttachmentBinding, type, binding, textureIndex,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001799 attachmentObj, numViews, baseViewIndex, isMultiview);
Jamie Madill42975642017-10-12 12:31:51 -04001800 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001801 }
1802
Jamie Madilla02315b2017-02-23 14:14:47 -05001803 case GL_DEPTH:
1804 case GL_DEPTH_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001805 updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001806 &mDirtyDepthAttachmentBinding, type, binding, textureIndex, resource,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001807 numViews, baseViewIndex, isMultiview);
Jamie Madill2d06b732015-04-20 12:53:28 -04001808 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001809
Jamie Madilla02315b2017-02-23 14:14:47 -05001810 case GL_STENCIL:
1811 case GL_STENCIL_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001812 updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001813 &mDirtyStencilAttachmentBinding, type, binding, textureIndex, resource,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001814 numViews, baseViewIndex, isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001815 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001816
Jamie Madilla02315b2017-02-23 14:14:47 -05001817 case GL_BACK:
Geoff Lang8170eab2017-09-21 13:59:04 -04001818 updateAttachment(context, &mState.mColorAttachments[0], DIRTY_BIT_COLOR_ATTACHMENT_0,
1819 &mDirtyColorAttachmentBindings[0], type, binding, textureIndex,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001820 resource, numViews, baseViewIndex, isMultiview);
Tim Van Patten56ba54c2019-08-08 13:03:34 -06001821
Jamie Madilla02315b2017-02-23 14:14:47 -05001822 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001823
Jamie Madilla02315b2017-02-23 14:14:47 -05001824 default:
1825 {
1826 size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
1827 ASSERT(colorIndex < mState.mColorAttachments.size());
Jamie Madillb8126692017-04-05 11:22:17 -04001828 size_t dirtyBit = DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001829 updateAttachment(context, &mState.mColorAttachments[colorIndex], dirtyBit,
Jamie Madillb8126692017-04-05 11:22:17 -04001830 &mDirtyColorAttachmentBindings[colorIndex], type, binding,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001831 textureIndex, resource, numViews, baseViewIndex, isMultiview);
Jamie Madilla02315b2017-02-23 14:14:47 -05001832
shrekshaoc87e0052019-02-21 11:40:28 -08001833 if (!resource)
1834 {
shrekshao8413fab2019-04-04 17:13:18 -07001835 mColorAttachmentBits.reset(colorIndex);
shrekshaoc87e0052019-02-21 11:40:28 -08001836 mFloat32ColorAttachmentBits.reset(colorIndex);
1837 }
1838 else
1839 {
shrekshao8413fab2019-04-04 17:13:18 -07001840 mColorAttachmentBits.set(colorIndex);
shrekshaoc87e0052019-02-21 11:40:28 -08001841 updateFloat32ColorAttachmentBits(
1842 colorIndex, resource->getAttachmentFormat(binding, textureIndex).info);
1843 }
1844
Corentin Walleze7557742017-06-01 13:09:57 -04001845 // TODO(jmadill): ASSERT instead of checking the attachment exists in
1846 // formsRenderingFeedbackLoopWith
Jamie Madilla02315b2017-02-23 14:14:47 -05001847 bool enabled = (type != GL_NONE && getDrawBufferState(colorIndex) != GL_NONE);
1848 mState.mEnabledDrawBuffers.set(colorIndex, enabled);
Jamie Madill6e18a232019-01-16 13:27:14 -05001849 SetComponentTypeMask(getDrawbufferWriteType(colorIndex), colorIndex,
1850 &mState.mDrawBufferTypeMask);
Jamie Madill2d06b732015-04-20 12:53:28 -04001851 }
Jamie Madilla02315b2017-02-23 14:14:47 -05001852 break;
Geoff Langab75a052014-10-15 12:56:37 -04001853 }
1854}
1855
Jamie Madill4928b7c2017-06-20 12:57:39 -04001856void Framebuffer::updateAttachment(const Context *context,
1857 FramebufferAttachment *attachment,
Jamie Madillb8126692017-04-05 11:22:17 -04001858 size_t dirtyBit,
Jamie Madilld4442552018-02-27 22:03:47 -05001859 angle::ObserverBinding *onDirtyBinding,
Jamie Madillb8126692017-04-05 11:22:17 -04001860 GLenum type,
1861 GLenum binding,
1862 const ImageIndex &textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001863 FramebufferAttachmentObject *resource,
1864 GLsizei numViews,
1865 GLuint baseViewIndex,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001866 bool isMultiview)
Jamie Madillb8126692017-04-05 11:22:17 -04001867{
Martin Radev5dae57b2017-07-14 16:15:55 +03001868 attachment->attach(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
Mingyu Hu7d64c482019-03-12 14:27:40 -07001869 isMultiview);
Jamie Madillb8126692017-04-05 11:22:17 -04001870 mDirtyBits.set(dirtyBit);
Jamie Madill05b35b22017-10-03 09:01:44 -04001871 mState.mResourceNeedsInit.set(dirtyBit, attachment->initState() == InitState::MayNeedInit);
Jamie Madill66f0d2c2018-11-30 15:25:36 -05001872 onDirtyBinding->bind(resource);
Jamie Madille98b1b52018-03-08 09:47:23 -05001873
Jamie Madill124f78c2019-06-18 11:48:24 -04001874 invalidateCompletenessCache();
Jamie Madillb8126692017-04-05 11:22:17 -04001875}
1876
Jamie Madilla02315b2017-02-23 14:14:47 -05001877void Framebuffer::resetAttachment(const Context *context, GLenum binding)
Jamie Madill2d06b732015-04-20 12:53:28 -04001878{
Jamie Madillcc129372018-04-12 09:13:18 -04001879 setAttachment(context, GL_NONE, binding, ImageIndex(), nullptr);
Jamie Madill2d06b732015-04-20 12:53:28 -04001880}
1881
Jamie Madill6f755b22018-10-09 12:48:54 -04001882angle::Result Framebuffer::syncState(const Context *context)
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001883{
1884 if (mDirtyBits.any())
1885 {
Jamie Madill888081d2018-02-27 00:24:46 -05001886 mDirtyBitsGuard = mDirtyBits;
Jamie Madill19fa1c62018-03-08 09:47:21 -05001887 ANGLE_TRY(mImpl->syncState(context, mDirtyBits));
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001888 mDirtyBits.reset();
Jamie Madill888081d2018-02-27 00:24:46 -05001889 mDirtyBitsGuard.reset();
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001890 }
Jamie Madill7c985f52018-11-29 18:16:17 -05001891 return angle::Result::Continue;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001892}
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001893
Jamie Madill124f78c2019-06-18 11:48:24 -04001894void Framebuffer::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
Jamie Madill51f40ec2016-06-15 14:06:00 -04001895{
Jamie Madille4faae22019-05-10 08:27:00 -04001896 if (message != angle::SubjectMessage::SubjectChanged)
Jamie Madillf668a4b2018-09-23 17:01:20 -04001897 {
Jamie Madill67220092019-05-20 11:12:53 -04001898 // This can be triggered by SubImage calls for Textures.
1899 if (message == angle::SubjectMessage::ContentsChanged)
1900 {
1901 mDirtyBits.set(DIRTY_BIT_COLOR_BUFFER_CONTENTS_0 + index);
Jamie Madill124f78c2019-06-18 11:48:24 -04001902 onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
Jamie Madill67220092019-05-20 11:12:53 -04001903 return;
1904 }
1905
Jamie Madillf668a4b2018-09-23 17:01:20 -04001906 // This can be triggered by the GL back-end TextureGL class.
Jamie Madille4faae22019-05-10 08:27:00 -04001907 ASSERT(message == angle::SubjectMessage::DirtyBitsFlagged);
Jamie Madillf668a4b2018-09-23 17:01:20 -04001908 return;
1909 }
Jamie Madill55e57f92018-09-18 11:32:43 -04001910
1911 ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(index));
1912 mDirtyBits.set(index);
Jamie Madill888081d2018-02-27 00:24:46 -05001913
Jamie Madill124f78c2019-06-18 11:48:24 -04001914 invalidateCompletenessCache();
Jamie Madill05b35b22017-10-03 09:01:44 -04001915
Jamie Madilld4442552018-02-27 22:03:47 -05001916 FramebufferAttachment *attachment = getAttachmentFromSubjectIndex(index);
1917
Jamie Madill05b35b22017-10-03 09:01:44 -04001918 // Mark the appropriate init flag.
Jamie Madilld4442552018-02-27 22:03:47 -05001919 mState.mResourceNeedsInit.set(index, attachment->initState() == InitState::MayNeedInit);
shrekshaoc87e0052019-02-21 11:40:28 -08001920
1921 // Update mFloat32ColorAttachmentBits Cache
1922 if (index < DIRTY_BIT_COLOR_ATTACHMENT_MAX)
1923 {
1924 ASSERT(index != DIRTY_BIT_DEPTH_ATTACHMENT);
1925 ASSERT(index != DIRTY_BIT_STENCIL_ATTACHMENT);
1926 updateFloat32ColorAttachmentBits(index - DIRTY_BIT_COLOR_ATTACHMENT_0,
1927 attachment->getFormat().info);
1928 }
Jamie Madilld4442552018-02-27 22:03:47 -05001929}
1930
1931FramebufferAttachment *Framebuffer::getAttachmentFromSubjectIndex(angle::SubjectIndex index)
1932{
1933 switch (index)
1934 {
1935 case DIRTY_BIT_DEPTH_ATTACHMENT:
1936 return &mState.mDepthAttachment;
1937 case DIRTY_BIT_STENCIL_ATTACHMENT:
1938 return &mState.mStencilAttachment;
1939 default:
1940 size_t colorIndex = (index - DIRTY_BIT_COLOR_ATTACHMENT_0);
1941 ASSERT(colorIndex < mState.mColorAttachments.size());
1942 return &mState.mColorAttachments[colorIndex];
1943 }
Jamie Madill51f40ec2016-06-15 14:06:00 -04001944}
1945
shrekshao8413fab2019-04-04 17:13:18 -07001946bool Framebuffer::formsRenderingFeedbackLoopWith(const Context *context) const
Jamie Madilla4595b82017-01-11 17:36:34 -05001947{
shrekshao8413fab2019-04-04 17:13:18 -07001948 const State &state = context->getState();
Jamie Madill785e8a02018-10-04 17:42:00 -04001949 const Program *program = state.getProgram();
Jamie Madilla4595b82017-01-11 17:36:34 -05001950
1951 // TODO(jmadill): Default framebuffer feedback loops.
Jiacheng Lu2c5d48a2019-08-23 09:28:35 -06001952 if (mState.isDefault())
Jamie Madilla4595b82017-01-11 17:36:34 -05001953 {
1954 return false;
1955 }
1956
Jamie Madill4e71b2b2019-07-08 13:23:38 -04001957 const FramebufferAttachment *depth = getDepthAttachment();
1958 const FramebufferAttachment *stencil = getStencilAttachment();
shrekshao8413fab2019-04-04 17:13:18 -07001959
1960 const bool checkDepth = depth && depth->type() == GL_TEXTURE;
1961 // Skip the feedback loop check for stencil if depth/stencil point to the same resource.
1962 const bool checkStencil =
1963 (stencil && stencil->type() == GL_TEXTURE) && (!depth || *stencil != *depth);
1964
1965 const gl::ActiveTextureMask &activeTextures = program->getActiveSamplersMask();
1966 const gl::ActiveTexturePointerArray &textures = state.getActiveTexturesCache();
1967
1968 for (size_t textureUnit : activeTextures)
Jamie Madilla4595b82017-01-11 17:36:34 -05001969 {
shrekshao8413fab2019-04-04 17:13:18 -07001970 Texture *texture = textures[textureUnit];
1971
1972 if (texture == nullptr)
Jamie Madilla4595b82017-01-11 17:36:34 -05001973 {
shrekshao8413fab2019-04-04 17:13:18 -07001974 continue;
1975 }
1976
1977 // Depth and stencil attachment form feedback loops
1978 // Regardless of if enabled or masked.
1979 if (checkDepth)
1980 {
1981 if (texture->id() == depth->id())
Jamie Madilla4595b82017-01-11 17:36:34 -05001982 {
1983 return true;
1984 }
1985 }
Jamie Madilla4595b82017-01-11 17:36:34 -05001986
shrekshao8413fab2019-04-04 17:13:18 -07001987 if (checkStencil)
Jamie Madill1d37bc52017-02-02 19:59:58 -05001988 {
shrekshao8413fab2019-04-04 17:13:18 -07001989 if (texture->id() == stencil->id())
Jamie Madill1d37bc52017-02-02 19:59:58 -05001990 {
Jamie Madill38fe6842018-09-19 07:20:00 -04001991 return true;
Jamie Madill1d37bc52017-02-02 19:59:58 -05001992 }
1993 }
shrekshao8413fab2019-04-04 17:13:18 -07001994
1995 // Check if any color attachment forms a feedback loop.
1996 for (size_t drawIndex : mColorAttachmentBits)
1997 {
1998 const FramebufferAttachment &attachment = mState.mColorAttachments[drawIndex];
1999 ASSERT(attachment.isAttached());
2000
2001 if (attachment.isTextureWithId(texture->id()))
2002 {
2003 // TODO(jmadill): Check for appropriate overlap.
2004 return true;
2005 }
2006 }
Jamie Madill1d37bc52017-02-02 19:59:58 -05002007 }
2008
Jamie Madilla4595b82017-01-11 17:36:34 -05002009 return false;
2010}
2011
Jamie Madillfd3dd432017-02-02 19:59:59 -05002012bool Framebuffer::formsCopyingFeedbackLoopWith(GLuint copyTextureID,
2013 GLint copyTextureLevel,
2014 GLint copyTextureLayer) const
Jamie Madillf695a3a2017-01-11 17:36:35 -05002015{
Jiacheng Lu2c5d48a2019-08-23 09:28:35 -06002016 if (mState.isDefault())
Jamie Madillf695a3a2017-01-11 17:36:35 -05002017 {
2018 // It seems impossible to form a texture copying feedback loop with the default FBO.
2019 return false;
2020 }
2021
Jamie Madill4e71b2b2019-07-08 13:23:38 -04002022 const FramebufferAttachment *readAttachment = getReadColorAttachment();
Jamie Madillf695a3a2017-01-11 17:36:35 -05002023 ASSERT(readAttachment);
2024
2025 if (readAttachment->isTextureWithId(copyTextureID))
2026 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002027 const auto &imageIndex = readAttachment->getTextureImageIndex();
Jamie Madillcc129372018-04-12 09:13:18 -04002028 if (imageIndex.getLevelIndex() == copyTextureLevel)
Jamie Madillf695a3a2017-01-11 17:36:35 -05002029 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002030 // Check 3D/Array texture layers.
Jamie Madillcc129372018-04-12 09:13:18 -04002031 return !imageIndex.hasLayer() || copyTextureLayer == ImageIndex::kEntireLevel ||
2032 imageIndex.getLayerIndex() == copyTextureLayer;
Jamie Madillf695a3a2017-01-11 17:36:35 -05002033 }
2034 }
2035 return false;
2036}
2037
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002038GLint Framebuffer::getDefaultWidth() const
2039{
2040 return mState.getDefaultWidth();
2041}
2042
2043GLint Framebuffer::getDefaultHeight() const
2044{
2045 return mState.getDefaultHeight();
2046}
2047
2048GLint Framebuffer::getDefaultSamples() const
2049{
2050 return mState.getDefaultSamples();
2051}
2052
Geoff Lang92019432017-11-20 13:09:34 -05002053bool Framebuffer::getDefaultFixedSampleLocations() const
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002054{
2055 return mState.getDefaultFixedSampleLocations();
2056}
2057
Jiawei Shaob1e91382018-05-17 14:33:55 +08002058GLint Framebuffer::getDefaultLayers() const
2059{
2060 return mState.getDefaultLayers();
2061}
2062
Jamie Madillb983a4b2018-08-01 11:34:51 -04002063void Framebuffer::setDefaultWidth(const Context *context, GLint defaultWidth)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002064{
2065 mState.mDefaultWidth = defaultWidth;
2066 mDirtyBits.set(DIRTY_BIT_DEFAULT_WIDTH);
Jamie Madill124f78c2019-06-18 11:48:24 -04002067 invalidateCompletenessCache();
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002068}
2069
Jamie Madillb983a4b2018-08-01 11:34:51 -04002070void Framebuffer::setDefaultHeight(const Context *context, GLint defaultHeight)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002071{
2072 mState.mDefaultHeight = defaultHeight;
2073 mDirtyBits.set(DIRTY_BIT_DEFAULT_HEIGHT);
Jamie Madill124f78c2019-06-18 11:48:24 -04002074 invalidateCompletenessCache();
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002075}
2076
Jamie Madillb983a4b2018-08-01 11:34:51 -04002077void Framebuffer::setDefaultSamples(const Context *context, GLint defaultSamples)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002078{
2079 mState.mDefaultSamples = defaultSamples;
2080 mDirtyBits.set(DIRTY_BIT_DEFAULT_SAMPLES);
Jamie Madill124f78c2019-06-18 11:48:24 -04002081 invalidateCompletenessCache();
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002082}
2083
Jamie Madillb983a4b2018-08-01 11:34:51 -04002084void Framebuffer::setDefaultFixedSampleLocations(const Context *context,
2085 bool defaultFixedSampleLocations)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002086{
2087 mState.mDefaultFixedSampleLocations = defaultFixedSampleLocations;
2088 mDirtyBits.set(DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS);
Jamie Madill124f78c2019-06-18 11:48:24 -04002089 invalidateCompletenessCache();
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002090}
2091
Jiawei Shaob1e91382018-05-17 14:33:55 +08002092void Framebuffer::setDefaultLayers(GLint defaultLayers)
2093{
2094 mState.mDefaultLayers = defaultLayers;
2095 mDirtyBits.set(DIRTY_BIT_DEFAULT_LAYERS);
2096}
2097
Martin Radev14a26ae2017-07-24 15:56:29 +03002098GLsizei Framebuffer::getNumViews() const
2099{
Martin Radev5c00d0d2017-08-07 10:06:59 +03002100 return mState.getNumViews();
Martin Radev14a26ae2017-07-24 15:56:29 +03002101}
2102
Martin Radev4e619f52017-08-09 11:50:06 +03002103GLint Framebuffer::getBaseViewIndex() const
2104{
2105 return mState.getBaseViewIndex();
2106}
2107
Mingyu Hu7d64c482019-03-12 14:27:40 -07002108bool Framebuffer::isMultiview() const
Martin Radev878c8b12017-07-28 09:51:04 +03002109{
Mingyu Hu7d64c482019-03-12 14:27:40 -07002110 return mState.isMultiview();
Martin Radev878c8b12017-07-28 09:51:04 +03002111}
2112
Olli Etuaho8acb1b62018-07-30 16:20:54 +03002113bool Framebuffer::readDisallowedByMultiview() const
2114{
Mingyu Hu7d64c482019-03-12 14:27:40 -07002115 return (mState.isMultiview() && mState.getNumViews() > 1);
Olli Etuaho8acb1b62018-07-30 16:20:54 +03002116}
2117
Jamie Madill64b7c4f2018-10-19 11:38:04 -04002118angle::Result Framebuffer::ensureClearAttachmentsInitialized(const Context *context,
2119 GLbitfield mask)
Geoff Langd4fff502017-09-22 11:28:28 -04002120{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05002121 const auto &glState = context->getState();
Geoff Langd4fff502017-09-22 11:28:28 -04002122 if (!context->isRobustResourceInitEnabled() || glState.isRasterizerDiscardEnabled())
2123 {
Jamie Madill7c985f52018-11-29 18:16:17 -05002124 return angle::Result::Continue;
Geoff Langd4fff502017-09-22 11:28:28 -04002125 }
2126
Geoff Langa36483f2018-03-09 16:11:21 -05002127 const BlendState &blend = glState.getBlendState();
2128 const DepthStencilState &depthStencil = glState.getDepthStencilState();
Geoff Langd4fff502017-09-22 11:28:28 -04002129
2130 bool color = (mask & GL_COLOR_BUFFER_BIT) != 0 && !IsColorMaskedOut(blend);
2131 bool depth = (mask & GL_DEPTH_BUFFER_BIT) != 0 && !IsDepthMaskedOut(depthStencil);
2132 bool stencil = (mask & GL_STENCIL_BUFFER_BIT) != 0 && !IsStencilMaskedOut(depthStencil);
2133
2134 if (!color && !depth && !stencil)
2135 {
Jamie Madill7c985f52018-11-29 18:16:17 -05002136 return angle::Result::Continue;
Geoff Langd4fff502017-09-22 11:28:28 -04002137 }
2138
2139 if (partialClearNeedsInit(context, color, depth, stencil))
2140 {
2141 ANGLE_TRY(ensureDrawAttachmentsInitialized(context));
2142 }
2143
2144 // If the impl encounters an error during a a full (non-partial) clear, the attachments will
2145 // still be marked initialized. This simplifies design, allowing this method to be called before
2146 // the clear.
2147 markDrawAttachmentsInitialized(color, depth, stencil);
2148
Jamie Madill7c985f52018-11-29 18:16:17 -05002149 return angle::Result::Continue;
Geoff Langd4fff502017-09-22 11:28:28 -04002150}
2151
Jamie Madill64b7c4f2018-10-19 11:38:04 -04002152angle::Result Framebuffer::ensureClearBufferAttachmentsInitialized(const Context *context,
2153 GLenum buffer,
2154 GLint drawbuffer)
Geoff Langd4fff502017-09-22 11:28:28 -04002155{
2156 if (!context->isRobustResourceInitEnabled() ||
Jamie Madillc3dc5d42018-12-30 12:12:04 -05002157 context->getState().isRasterizerDiscardEnabled() || IsClearBufferMaskedOut(context, buffer))
Geoff Langd4fff502017-09-22 11:28:28 -04002158 {
Jamie Madill7c985f52018-11-29 18:16:17 -05002159 return angle::Result::Continue;
Geoff Langd4fff502017-09-22 11:28:28 -04002160 }
2161
2162 if (partialBufferClearNeedsInit(context, buffer))
2163 {
2164 ANGLE_TRY(ensureBufferInitialized(context, buffer, drawbuffer));
2165 }
2166
2167 // If the impl encounters an error during a a full (non-partial) clear, the attachments will
2168 // still be marked initialized. This simplifies design, allowing this method to be called before
2169 // the clear.
2170 markBufferInitialized(buffer, drawbuffer);
2171
Jamie Madill7c985f52018-11-29 18:16:17 -05002172 return angle::Result::Continue;
Geoff Langd4fff502017-09-22 11:28:28 -04002173}
2174
Jamie Madill6f755b22018-10-09 12:48:54 -04002175angle::Result Framebuffer::ensureDrawAttachmentsInitialized(const Context *context)
Jamie Madill05b35b22017-10-03 09:01:44 -04002176{
2177 if (!context->isRobustResourceInitEnabled())
2178 {
Jamie Madill7c985f52018-11-29 18:16:17 -05002179 return angle::Result::Continue;
Jamie Madill05b35b22017-10-03 09:01:44 -04002180 }
2181
2182 // Note: we don't actually filter by the draw attachment enum. Just init everything.
2183 for (size_t bit : mState.mResourceNeedsInit)
2184 {
2185 switch (bit)
2186 {
2187 case DIRTY_BIT_DEPTH_ATTACHMENT:
2188 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2189 break;
2190 case DIRTY_BIT_STENCIL_ATTACHMENT:
2191 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2192 break;
2193 default:
2194 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[bit]));
2195 break;
2196 }
2197 }
2198
2199 mState.mResourceNeedsInit.reset();
Jamie Madill7c985f52018-11-29 18:16:17 -05002200 return angle::Result::Continue;
Jamie Madill05b35b22017-10-03 09:01:44 -04002201}
2202
Jamie Madill0a1eeb82019-05-13 13:53:18 -04002203angle::Result Framebuffer::ensureReadAttachmentsInitialized(const Context *context)
Jamie Madill05b35b22017-10-03 09:01:44 -04002204{
Jamie Madill0a1eeb82019-05-13 13:53:18 -04002205 ASSERT(context->isRobustResourceInitEnabled());
2206
2207 if (mState.mResourceNeedsInit.none())
Jamie Madill05b35b22017-10-03 09:01:44 -04002208 {
Jamie Madill7c985f52018-11-29 18:16:17 -05002209 return angle::Result::Continue;
Jamie Madill05b35b22017-10-03 09:01:44 -04002210 }
2211
Jamie Madill0a1eeb82019-05-13 13:53:18 -04002212 if (mState.mReadBufferState != GL_NONE)
Jamie Madill05b35b22017-10-03 09:01:44 -04002213 {
Tim Van Patten56ba54c2019-08-08 13:03:34 -06002214 if (isDefault())
Jamie Madill05b35b22017-10-03 09:01:44 -04002215 {
Tim Van Patten56ba54c2019-08-08 13:03:34 -06002216 if (!mState.mDefaultFramebufferReadAttachmentInitialized)
2217 {
2218 ANGLE_TRY(InitAttachment(context, &mState.mDefaultFramebufferReadAttachment));
2219 mState.mDefaultFramebufferReadAttachmentInitialized = true;
2220 }
2221 }
2222 else
2223 {
2224 size_t readIndex = mState.getReadIndex();
2225 if (mState.mResourceNeedsInit[readIndex])
2226 {
2227 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[readIndex]));
2228 mState.mResourceNeedsInit.reset(readIndex);
2229 }
Jamie Madill05b35b22017-10-03 09:01:44 -04002230 }
2231 }
2232
Jamie Madill0a1eeb82019-05-13 13:53:18 -04002233 // Conservatively init depth since it can be read by BlitFramebuffer.
2234 if (hasDepth())
Jamie Madill05b35b22017-10-03 09:01:44 -04002235 {
2236 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2237 {
2238 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2239 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2240 }
2241 }
2242
Jamie Madill0a1eeb82019-05-13 13:53:18 -04002243 // Conservatively init stencil since it can be read by BlitFramebuffer.
2244 if (hasStencil())
Jamie Madill05b35b22017-10-03 09:01:44 -04002245 {
2246 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2247 {
2248 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2249 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2250 }
2251 }
2252
Jamie Madill7c985f52018-11-29 18:16:17 -05002253 return angle::Result::Continue;
Jamie Madill05b35b22017-10-03 09:01:44 -04002254}
2255
2256void Framebuffer::markDrawAttachmentsInitialized(bool color, bool depth, bool stencil)
2257{
2258 // Mark attachments as initialized.
2259 if (color)
2260 {
2261 for (auto colorIndex : mState.mEnabledDrawBuffers)
2262 {
2263 auto &colorAttachment = mState.mColorAttachments[colorIndex];
2264 ASSERT(colorAttachment.isAttached());
2265 colorAttachment.setInitState(InitState::Initialized);
2266 mState.mResourceNeedsInit.reset(colorIndex);
2267 }
2268 }
2269
2270 if (depth && mState.mDepthAttachment.isAttached())
2271 {
2272 mState.mDepthAttachment.setInitState(InitState::Initialized);
2273 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2274 }
2275
2276 if (stencil && mState.mStencilAttachment.isAttached())
2277 {
2278 mState.mStencilAttachment.setInitState(InitState::Initialized);
2279 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2280 }
2281}
2282
2283void Framebuffer::markBufferInitialized(GLenum bufferType, GLint bufferIndex)
2284{
2285 switch (bufferType)
2286 {
2287 case GL_COLOR:
2288 {
2289 ASSERT(bufferIndex < static_cast<GLint>(mState.mColorAttachments.size()));
2290 if (mState.mColorAttachments[bufferIndex].isAttached())
2291 {
2292 mState.mColorAttachments[bufferIndex].setInitState(InitState::Initialized);
2293 mState.mResourceNeedsInit.reset(bufferIndex);
2294 }
2295 break;
2296 }
2297 case GL_DEPTH:
2298 {
2299 if (mState.mDepthAttachment.isAttached())
2300 {
2301 mState.mDepthAttachment.setInitState(InitState::Initialized);
2302 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2303 }
2304 break;
2305 }
2306 case GL_STENCIL:
2307 {
2308 if (mState.mStencilAttachment.isAttached())
2309 {
2310 mState.mStencilAttachment.setInitState(InitState::Initialized);
2311 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2312 }
2313 break;
2314 }
2315 case GL_DEPTH_STENCIL:
2316 {
2317 if (mState.mDepthAttachment.isAttached())
2318 {
2319 mState.mDepthAttachment.setInitState(InitState::Initialized);
2320 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2321 }
2322 if (mState.mStencilAttachment.isAttached())
2323 {
2324 mState.mStencilAttachment.setInitState(InitState::Initialized);
2325 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2326 }
2327 break;
2328 }
2329 default:
2330 UNREACHABLE();
2331 break;
2332 }
2333}
2334
2335Box Framebuffer::getDimensions() const
2336{
2337 return mState.getDimensions();
2338}
2339
Jonah Ryan-Davis7151fe52019-07-17 15:15:27 -04002340Extents Framebuffer::getExtents() const
2341{
2342 return mState.getExtents();
2343}
2344
Jamie Madill64b7c4f2018-10-19 11:38:04 -04002345angle::Result Framebuffer::ensureBufferInitialized(const Context *context,
2346 GLenum bufferType,
2347 GLint bufferIndex)
Jamie Madill05b35b22017-10-03 09:01:44 -04002348{
2349 ASSERT(context->isRobustResourceInitEnabled());
2350
2351 if (mState.mResourceNeedsInit.none())
2352 {
Jamie Madill7c985f52018-11-29 18:16:17 -05002353 return angle::Result::Continue;
Jamie Madill05b35b22017-10-03 09:01:44 -04002354 }
2355
2356 switch (bufferType)
2357 {
2358 case GL_COLOR:
2359 {
2360 ASSERT(bufferIndex < static_cast<GLint>(mState.mColorAttachments.size()));
2361 if (mState.mResourceNeedsInit[bufferIndex])
2362 {
2363 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[bufferIndex]));
2364 mState.mResourceNeedsInit.reset(bufferIndex);
2365 }
2366 break;
2367 }
2368 case GL_DEPTH:
2369 {
2370 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2371 {
2372 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2373 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2374 }
2375 break;
2376 }
2377 case GL_STENCIL:
2378 {
2379 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2380 {
2381 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2382 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2383 }
2384 break;
2385 }
2386 case GL_DEPTH_STENCIL:
2387 {
2388 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2389 {
2390 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2391 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2392 }
2393 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2394 {
2395 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2396 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2397 }
2398 break;
2399 }
2400 default:
2401 UNREACHABLE();
2402 break;
2403 }
2404
Jamie Madill7c985f52018-11-29 18:16:17 -05002405 return angle::Result::Continue;
Jamie Madill05b35b22017-10-03 09:01:44 -04002406}
2407
2408bool Framebuffer::partialBufferClearNeedsInit(const Context *context, GLenum bufferType)
2409{
2410 if (!context->isRobustResourceInitEnabled() || mState.mResourceNeedsInit.none())
2411 {
2412 return false;
2413 }
2414
2415 switch (bufferType)
2416 {
2417 case GL_COLOR:
2418 return partialClearNeedsInit(context, true, false, false);
2419 case GL_DEPTH:
2420 return partialClearNeedsInit(context, false, true, false);
2421 case GL_STENCIL:
2422 return partialClearNeedsInit(context, false, false, true);
2423 case GL_DEPTH_STENCIL:
2424 return partialClearNeedsInit(context, false, true, true);
2425 default:
2426 UNREACHABLE();
2427 return false;
2428 }
2429}
Jamie Madill60ec6ea2016-01-22 15:27:19 -05002430} // namespace gl