blob: e6881ebff56ab5c634129ded78bfb0df49135b78 [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
Mingyu Hu2d0e5b52019-08-27 13:49:07 -0700143bool CheckAttachmentSampleCounts(const Context *context,
144 GLsizei currAttachmentSamples,
145 GLsizei samples,
146 bool colorAttachment)
147{
148 if (currAttachmentSamples != samples)
149 {
150 if (colorAttachment)
151 {
152 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
153 // all color attachments have the same number of samples for the FBO to be complete.
154 return false;
155 }
156 else
157 {
158 // CHROMIUM_framebuffer_mixed_samples allows a framebuffer to be considered complete
159 // when its depth or stencil samples are a multiple of the number of color samples.
160 if (!context->getExtensions().framebufferMixedSamples)
161 {
162 return false;
163 }
164
165 if ((currAttachmentSamples % std::max(samples, 1)) != 0)
166 {
167 return false;
168 }
169 }
170 }
171 return true;
172}
173
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400174bool CheckAttachmentSampleCompleteness(const Context *context,
175 const FramebufferAttachment &attachment,
176 bool colorAttachment,
177 Optional<int> *samples,
Mingyu Hu2d0e5b52019-08-27 13:49:07 -0700178 Optional<bool> *fixedSampleLocations,
179 Optional<int> *renderToTextureSamples)
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400180{
181 ASSERT(attachment.isAttached());
182
183 if (attachment.type() == GL_TEXTURE)
184 {
185 const Texture *texture = attachment.getTexture();
186 ASSERT(texture);
Mingyu Hu2d0e5b52019-08-27 13:49:07 -0700187 GLenum internalFormat = attachment.getFormat().info->internalFormat;
188 const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
189 if (static_cast<GLuint>(attachment.getSamples()) > formatCaps.getMaxSamples())
190 {
191 return false;
192 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400193
194 const ImageIndex &attachmentImageIndex = attachment.getTextureImageIndex();
Jiawei Shaoa8802472018-05-28 11:17:47 +0800195 bool fixedSampleloc = texture->getAttachmentFixedSampleLocations(attachmentImageIndex);
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400196 if (fixedSampleLocations->valid() && fixedSampleloc != fixedSampleLocations->value())
197 {
198 return false;
199 }
200 else
201 {
202 *fixedSampleLocations = fixedSampleloc;
203 }
204 }
205
Mingyu Hu2d0e5b52019-08-27 13:49:07 -0700206 if (renderToTextureSamples->valid())
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400207 {
Mingyu Hu2d0e5b52019-08-27 13:49:07 -0700208 // Only check against RenderToTextureSamples if they actually exist.
209 if (renderToTextureSamples->value() !=
210 FramebufferAttachment::kDefaultRenderToTextureSamples)
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400211 {
Mingyu Hu2d0e5b52019-08-27 13:49:07 -0700212 if (!CheckAttachmentSampleCounts(context, attachment.getRenderToTextureSamples(),
213 renderToTextureSamples->value(), colorAttachment))
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400214 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400215 return false;
216 }
Mingyu Hu2d0e5b52019-08-27 13:49:07 -0700217 }
218 }
219 else
220 {
221 *renderToTextureSamples = attachment.getRenderToTextureSamples();
222 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400223
Mingyu Hu2d0e5b52019-08-27 13:49:07 -0700224 if (samples->valid())
225 {
226 // RenderToTextureSamples takes precedence if they exist.
227 if (renderToTextureSamples->value() ==
228 FramebufferAttachment::kDefaultRenderToTextureSamples)
229 {
230 if (!CheckAttachmentSampleCounts(context, attachment.getSamples(), samples->value(),
231 colorAttachment))
232 {
233 return false;
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400234 }
235 }
236 }
237 else
238 {
239 *samples = attachment.getSamples();
240 }
241
242 return true;
243}
244
Jamie Madill05b35b22017-10-03 09:01:44 -0400245// Needed to index into the attachment arrays/bitsets.
Jamie Madill682efdc2017-10-03 14:10:29 -0400246static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS) ==
Jamie Madilld4442552018-02-27 22:03:47 -0500247 Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX,
Jamie Madill05b35b22017-10-03 09:01:44 -0400248 "Framebuffer Dirty bit mismatch");
Jamie Madill682efdc2017-10-03 14:10:29 -0400249static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS) ==
Jamie Madilld4442552018-02-27 22:03:47 -0500250 Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT,
Jamie Madill05b35b22017-10-03 09:01:44 -0400251 "Framebuffer Dirty bit mismatch");
Jamie Madill682efdc2017-10-03 14:10:29 -0400252static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS + 1) ==
Jamie Madilld4442552018-02-27 22:03:47 -0500253 Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT,
Jamie Madill05b35b22017-10-03 09:01:44 -0400254 "Framebuffer Dirty bit mismatch");
255
Jamie Madill6f755b22018-10-09 12:48:54 -0400256angle::Result InitAttachment(const Context *context, FramebufferAttachment *attachment)
Jamie Madill05b35b22017-10-03 09:01:44 -0400257{
258 ASSERT(attachment->isAttached());
259 if (attachment->initState() == InitState::MayNeedInit)
260 {
261 ANGLE_TRY(attachment->initializeContents(context));
262 }
Jamie Madill7c985f52018-11-29 18:16:17 -0500263 return angle::Result::Continue;
Jamie Madill05b35b22017-10-03 09:01:44 -0400264}
265
266bool IsColorMaskedOut(const BlendState &blend)
267{
268 return (!blend.colorMaskRed && !blend.colorMaskGreen && !blend.colorMaskBlue &&
269 !blend.colorMaskAlpha);
270}
271
272bool IsDepthMaskedOut(const DepthStencilState &depthStencil)
273{
274 return !depthStencil.depthMask;
275}
276
277bool IsStencilMaskedOut(const DepthStencilState &depthStencil)
278{
279 return ((depthStencil.stencilMask & depthStencil.stencilWritemask) == 0);
280}
281
282bool IsClearBufferMaskedOut(const Context *context, GLenum buffer)
283{
284 switch (buffer)
285 {
286 case GL_COLOR:
Jamie Madillc3dc5d42018-12-30 12:12:04 -0500287 return IsColorMaskedOut(context->getState().getBlendState());
Jamie Madill05b35b22017-10-03 09:01:44 -0400288 case GL_DEPTH:
Jamie Madillc3dc5d42018-12-30 12:12:04 -0500289 return IsDepthMaskedOut(context->getState().getDepthStencilState());
Jamie Madill05b35b22017-10-03 09:01:44 -0400290 case GL_STENCIL:
Jamie Madillc3dc5d42018-12-30 12:12:04 -0500291 return IsStencilMaskedOut(context->getState().getDepthStencilState());
Jamie Madill05b35b22017-10-03 09:01:44 -0400292 case GL_DEPTH_STENCIL:
Jamie Madillc3dc5d42018-12-30 12:12:04 -0500293 return IsDepthMaskedOut(context->getState().getDepthStencilState()) &&
294 IsStencilMaskedOut(context->getState().getDepthStencilState());
Jamie Madill05b35b22017-10-03 09:01:44 -0400295 default:
296 UNREACHABLE();
297 return true;
298 }
299}
300
Jamie Madill362876b2016-06-16 14:46:59 -0400301} // anonymous namespace
Jamie Madilld1405e52015-03-05 15:41:39 -0500302
Jamie Madill6f60d052017-02-22 15:20:11 -0500303// This constructor is only used for default framebuffers.
Jamie Madill48ef11b2016-04-27 15:21:52 -0400304FramebufferState::FramebufferState()
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600305 : mId(Framebuffer::kDefaultDrawFramebufferHandle),
Jamie Madill2274b652018-05-31 10:56:08 -0400306 mLabel(),
Geoff Lang70d0f492015-12-10 17:45:46 -0500307 mColorAttachments(1),
Corentin Walleze7557742017-06-01 13:09:57 -0400308 mDrawBufferStates(1, GL_BACK),
Jamie Madill6f60d052017-02-22 15:20:11 -0500309 mReadBufferState(GL_BACK),
Brandon Jones76746f92017-11-22 11:44:41 -0800310 mDrawBufferTypeMask(),
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800311 mDefaultWidth(0),
312 mDefaultHeight(0),
313 mDefaultSamples(0),
Jamie Madilla02315b2017-02-23 14:14:47 -0500314 mDefaultFixedSampleLocations(GL_FALSE),
Jiawei Shaob1e91382018-05-17 14:33:55 +0800315 mDefaultLayers(0),
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600316 mWebGLDepthStencilConsistent(true),
317 mDefaultFramebufferReadAttachmentInitialized(false)
Corentin Wallez37c39792015-08-20 14:19:46 -0400318{
Geoff Langd90d3882017-03-21 10:49:54 -0400319 ASSERT(mDrawBufferStates.size() > 0);
Jamie Madilla4595b82017-01-11 17:36:34 -0500320 mEnabledDrawBuffers.set(0);
Corentin Wallez37c39792015-08-20 14:19:46 -0400321}
322
Jiacheng Lu2c5d48a2019-08-23 09:28:35 -0600323FramebufferState::FramebufferState(const Caps &caps, FramebufferID id)
Jamie Madill2274b652018-05-31 10:56:08 -0400324 : mId(id),
325 mLabel(),
Geoff Lang70d0f492015-12-10 17:45:46 -0500326 mColorAttachments(caps.maxColorAttachments),
Jamie Madilld1405e52015-03-05 15:41:39 -0500327 mDrawBufferStates(caps.maxDrawBuffers, GL_NONE),
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800328 mReadBufferState(GL_COLOR_ATTACHMENT0_EXT),
Brandon Jones76746f92017-11-22 11:44:41 -0800329 mDrawBufferTypeMask(),
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800330 mDefaultWidth(0),
331 mDefaultHeight(0),
332 mDefaultSamples(0),
Jamie Madilla02315b2017-02-23 14:14:47 -0500333 mDefaultFixedSampleLocations(GL_FALSE),
Jiawei Shaob1e91382018-05-17 14:33:55 +0800334 mDefaultLayers(0),
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600335 mWebGLDepthStencilConsistent(true),
336 mDefaultFramebufferReadAttachmentInitialized(false)
Jamie Madilld1405e52015-03-05 15:41:39 -0500337{
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600338 ASSERT(mId != Framebuffer::kDefaultDrawFramebufferHandle);
Geoff Langa15472a2015-08-11 11:48:03 -0400339 ASSERT(mDrawBufferStates.size() > 0);
Jamie Madilld1405e52015-03-05 15:41:39 -0500340 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
341}
342
Jamie Madillb980c562018-11-27 11:34:27 -0500343FramebufferState::~FramebufferState() {}
Jamie Madilld1405e52015-03-05 15:41:39 -0500344
Jamie Madill48ef11b2016-04-27 15:21:52 -0400345const std::string &FramebufferState::getLabel()
Geoff Lang70d0f492015-12-10 17:45:46 -0500346{
347 return mLabel;
348}
349
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800350const FramebufferAttachment *FramebufferState::getAttachment(const Context *context,
351 GLenum attachment) const
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400352{
353 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
354 {
355 return getColorAttachment(attachment - GL_COLOR_ATTACHMENT0);
356 }
357
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800358 // WebGL1 allows a developer to query for attachment parameters even when "inconsistant" (i.e.
359 // multiple conflicting attachment points) and requires us to return the framebuffer attachment
360 // associated with WebGL.
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400361 switch (attachment)
362 {
363 case GL_COLOR:
364 case GL_BACK:
365 return getColorAttachment(0);
366 case GL_DEPTH:
367 case GL_DEPTH_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800368 if (context->isWebGL1())
369 {
370 return getWebGLDepthAttachment();
371 }
372 else
373 {
374 return getDepthAttachment();
375 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400376 case GL_STENCIL:
377 case GL_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800378 if (context->isWebGL1())
379 {
380 return getWebGLStencilAttachment();
381 }
382 else
383 {
384 return getStencilAttachment();
385 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400386 case GL_DEPTH_STENCIL:
387 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800388 if (context->isWebGL1())
389 {
390 return getWebGLDepthStencilAttachment();
391 }
392 else
393 {
394 return getDepthStencilAttachment();
395 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400396 default:
397 UNREACHABLE();
398 return nullptr;
399 }
400}
401
Jamie Madill05b35b22017-10-03 09:01:44 -0400402size_t FramebufferState::getReadIndex() const
Jamie Madill7147f012015-03-05 15:41:40 -0500403{
Jamie Madill231c7f52017-04-26 13:45:37 -0400404 ASSERT(mReadBufferState == GL_BACK ||
405 (mReadBufferState >= GL_COLOR_ATTACHMENT0 && mReadBufferState <= GL_COLOR_ATTACHMENT15));
406 size_t readIndex = (mReadBufferState == GL_BACK
407 ? 0
408 : static_cast<size_t>(mReadBufferState - GL_COLOR_ATTACHMENT0));
Jamie Madill7147f012015-03-05 15:41:40 -0500409 ASSERT(readIndex < mColorAttachments.size());
Jamie Madill05b35b22017-10-03 09:01:44 -0400410 return readIndex;
411}
412
413const FramebufferAttachment *FramebufferState::getReadAttachment() const
414{
415 if (mReadBufferState == GL_NONE)
416 {
417 return nullptr;
418 }
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600419
Jamie Madill05b35b22017-10-03 09:01:44 -0400420 size_t readIndex = getReadIndex();
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600421 const gl::FramebufferAttachment &framebufferAttachment =
422 isDefault() ? mDefaultFramebufferReadAttachment : mColorAttachments[readIndex];
423
424 return framebufferAttachment.isAttached() ? &framebufferAttachment : nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500425}
426
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500427const FramebufferAttachment *FramebufferState::getFirstNonNullAttachment() const
428{
429 auto *colorAttachment = getFirstColorAttachment();
430 if (colorAttachment)
431 {
432 return colorAttachment;
433 }
434 return getDepthOrStencilAttachment();
435}
436
Jamie Madill48ef11b2016-04-27 15:21:52 -0400437const FramebufferAttachment *FramebufferState::getFirstColorAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500438{
Jamie Madill2d06b732015-04-20 12:53:28 -0400439 for (const FramebufferAttachment &colorAttachment : mColorAttachments)
Jamie Madill7147f012015-03-05 15:41:40 -0500440 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400441 if (colorAttachment.isAttached())
Jamie Madill7147f012015-03-05 15:41:40 -0500442 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400443 return &colorAttachment;
Jamie Madill7147f012015-03-05 15:41:40 -0500444 }
445 }
446
447 return nullptr;
448}
449
Jamie Madill48ef11b2016-04-27 15:21:52 -0400450const FramebufferAttachment *FramebufferState::getDepthOrStencilAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500451{
Jamie Madill2d06b732015-04-20 12:53:28 -0400452 if (mDepthAttachment.isAttached())
453 {
454 return &mDepthAttachment;
455 }
456 if (mStencilAttachment.isAttached())
457 {
458 return &mStencilAttachment;
459 }
460 return nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500461}
462
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500463const FramebufferAttachment *FramebufferState::getStencilOrDepthStencilAttachment() const
464{
465 if (mStencilAttachment.isAttached())
466 {
467 return &mStencilAttachment;
468 }
469 return getDepthStencilAttachment();
470}
471
Jamie Madill48ef11b2016-04-27 15:21:52 -0400472const FramebufferAttachment *FramebufferState::getColorAttachment(size_t colorAttachment) const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400473{
474 ASSERT(colorAttachment < mColorAttachments.size());
Jamie Madill231c7f52017-04-26 13:45:37 -0400475 return mColorAttachments[colorAttachment].isAttached() ? &mColorAttachments[colorAttachment]
476 : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400477}
478
Jamie Madill48ef11b2016-04-27 15:21:52 -0400479const FramebufferAttachment *FramebufferState::getDepthAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400480{
Jamie Madill2d06b732015-04-20 12:53:28 -0400481 return mDepthAttachment.isAttached() ? &mDepthAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400482}
483
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800484const FramebufferAttachment *FramebufferState::getWebGLDepthAttachment() const
485{
486 return mWebGLDepthAttachment.isAttached() ? &mWebGLDepthAttachment : nullptr;
487}
488
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800489const FramebufferAttachment *FramebufferState::getWebGLDepthStencilAttachment() const
490{
491 return mWebGLDepthStencilAttachment.isAttached() ? &mWebGLDepthStencilAttachment : nullptr;
492}
493
Jamie Madill48ef11b2016-04-27 15:21:52 -0400494const FramebufferAttachment *FramebufferState::getStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400495{
Jamie Madill2d06b732015-04-20 12:53:28 -0400496 return mStencilAttachment.isAttached() ? &mStencilAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400497}
498
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800499const FramebufferAttachment *FramebufferState::getWebGLStencilAttachment() const
500{
501 return mWebGLStencilAttachment.isAttached() ? &mWebGLStencilAttachment : nullptr;
502}
503
Jamie Madill48ef11b2016-04-27 15:21:52 -0400504const FramebufferAttachment *FramebufferState::getDepthStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400505{
506 // A valid depth-stencil attachment has the same resource bound to both the
507 // depth and stencil attachment points.
Jamie Madill2d06b732015-04-20 12:53:28 -0400508 if (mDepthAttachment.isAttached() && mStencilAttachment.isAttached() &&
Jamie Madill44f26482016-11-18 12:49:15 -0500509 mDepthAttachment == mStencilAttachment)
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400510 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400511 return &mDepthAttachment;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400512 }
513
514 return nullptr;
515}
516
Jamie Madill48ef11b2016-04-27 15:21:52 -0400517bool FramebufferState::attachmentsHaveSameDimensions() const
Jamie Madillcc86d642015-11-24 13:00:07 -0500518{
519 Optional<Extents> attachmentSize;
520
Jamie Madill231c7f52017-04-26 13:45:37 -0400521 auto hasMismatchedSize = [&attachmentSize](const FramebufferAttachment &attachment) {
Jamie Madillcc86d642015-11-24 13:00:07 -0500522 if (!attachment.isAttached())
523 {
524 return false;
525 }
526
527 if (!attachmentSize.valid())
528 {
529 attachmentSize = attachment.getSize();
530 return false;
531 }
532
Jeff Gilbert8f8edd62017-10-31 14:26:30 -0700533 const auto &prevSize = attachmentSize.value();
534 const auto &curSize = attachment.getSize();
535 return (curSize.width != prevSize.width || curSize.height != prevSize.height);
Jamie Madillcc86d642015-11-24 13:00:07 -0500536 };
537
538 for (const auto &attachment : mColorAttachments)
539 {
540 if (hasMismatchedSize(attachment))
541 {
542 return false;
543 }
544 }
545
546 if (hasMismatchedSize(mDepthAttachment))
547 {
548 return false;
549 }
550
551 return !hasMismatchedSize(mStencilAttachment);
552}
553
Luc Ferron5bdf8bd2018-06-20 09:51:37 -0400554bool FramebufferState::hasSeparateDepthAndStencilAttachments() const
555{
556 // if we have both a depth and stencil buffer, they must refer to the same object
557 // since we only support packed_depth_stencil and not separate depth and stencil
558 return (getDepthAttachment() != nullptr && getStencilAttachment() != nullptr &&
559 getDepthStencilAttachment() == nullptr);
560}
561
Jamie Madilld4442552018-02-27 22:03:47 -0500562const FramebufferAttachment *FramebufferState::getDrawBuffer(size_t drawBufferIdx) const
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400563{
564 ASSERT(drawBufferIdx < mDrawBufferStates.size());
565 if (mDrawBufferStates[drawBufferIdx] != GL_NONE)
566 {
567 // ES3 spec: "If the GL is bound to a draw framebuffer object, the ith buffer listed in bufs
568 // must be COLOR_ATTACHMENTi or NONE"
569 ASSERT(mDrawBufferStates[drawBufferIdx] == GL_COLOR_ATTACHMENT0 + drawBufferIdx ||
570 (drawBufferIdx == 0 && mDrawBufferStates[drawBufferIdx] == GL_BACK));
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800571
572 if (mDrawBufferStates[drawBufferIdx] == GL_BACK)
573 {
574 return getColorAttachment(0);
575 }
576 else
577 {
578 return getColorAttachment(mDrawBufferStates[drawBufferIdx] - GL_COLOR_ATTACHMENT0);
579 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400580 }
581 else
582 {
583 return nullptr;
584 }
585}
586
587size_t FramebufferState::getDrawBufferCount() const
588{
589 return mDrawBufferStates.size();
590}
591
Geoff Langb21e20d2016-07-19 15:35:41 -0400592bool FramebufferState::colorAttachmentsAreUniqueImages() const
593{
594 for (size_t firstAttachmentIdx = 0; firstAttachmentIdx < mColorAttachments.size();
595 firstAttachmentIdx++)
596 {
Jamie Madilld4442552018-02-27 22:03:47 -0500597 const FramebufferAttachment &firstAttachment = mColorAttachments[firstAttachmentIdx];
Geoff Langb21e20d2016-07-19 15:35:41 -0400598 if (!firstAttachment.isAttached())
599 {
600 continue;
601 }
602
603 for (size_t secondAttachmentIdx = firstAttachmentIdx + 1;
604 secondAttachmentIdx < mColorAttachments.size(); secondAttachmentIdx++)
605 {
Jamie Madilld4442552018-02-27 22:03:47 -0500606 const FramebufferAttachment &secondAttachment = mColorAttachments[secondAttachmentIdx];
Geoff Langb21e20d2016-07-19 15:35:41 -0400607 if (!secondAttachment.isAttached())
608 {
609 continue;
610 }
611
612 if (firstAttachment == secondAttachment)
613 {
614 return false;
615 }
616 }
617 }
618
619 return true;
620}
621
Jamie Madill9c335862017-07-18 11:51:38 -0400622bool FramebufferState::hasDepth() const
623{
624 return (mDepthAttachment.isAttached() && mDepthAttachment.getDepthSize() > 0);
625}
626
627bool FramebufferState::hasStencil() const
628{
629 return (mStencilAttachment.isAttached() && mStencilAttachment.getStencilSize() > 0);
630}
631
Mingyu Hu7d64c482019-03-12 14:27:40 -0700632bool FramebufferState::isMultiview() const
Martin Radev5c00d0d2017-08-07 10:06:59 +0300633{
634 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
635 if (attachment == nullptr)
636 {
Mingyu Hu7d64c482019-03-12 14:27:40 -0700637 return false;
Martin Radev5c00d0d2017-08-07 10:06:59 +0300638 }
Mingyu Hu7d64c482019-03-12 14:27:40 -0700639 return attachment->isMultiview();
Martin Radev5c00d0d2017-08-07 10:06:59 +0300640}
641
Martin Radev4e619f52017-08-09 11:50:06 +0300642int FramebufferState::getBaseViewIndex() const
643{
644 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
645 if (attachment == nullptr)
646 {
647 return GL_NONE;
648 }
649 return attachment->getBaseViewIndex();
650}
651
Jamie Madill05b35b22017-10-03 09:01:44 -0400652Box FramebufferState::getDimensions() const
653{
Jonah Ryan-Davis7151fe52019-07-17 15:15:27 -0400654 Extents extents = getExtents();
655 return Box(0, 0, 0, extents.width, extents.height, extents.depth);
656}
657
658Extents FramebufferState::getExtents() const
659{
Jamie Madill05b35b22017-10-03 09:01:44 -0400660 ASSERT(attachmentsHaveSameDimensions());
Tim Van Patten626a7282019-07-08 15:11:59 -0600661 const FramebufferAttachment *first = getFirstNonNullAttachment();
662 if (first)
663 {
664 return first->getSize();
665 }
666 return Extents(getDefaultWidth(), getDefaultHeight(), 0);
Jamie Madill05b35b22017-10-03 09:01:44 -0400667}
668
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600669bool FramebufferState::isDefault() const
670{
671 return mId == Framebuffer::kDefaultDrawFramebufferHandle;
672}
673
Jiacheng Lu2c5d48a2019-08-23 09:28:35 -0600674const FramebufferID Framebuffer::kDefaultDrawFramebufferHandle = {0};
675
676Framebuffer::Framebuffer(const Caps &caps, rx::GLImplFactory *factory, FramebufferID id)
Jamie Madill2274b652018-05-31 10:56:08 -0400677 : mState(caps, id),
Jamie Madill362876b2016-06-16 14:46:59 -0400678 mImpl(factory->createFramebuffer(mState)),
Jamie Madill362876b2016-06-16 14:46:59 -0400679 mCachedStatus(),
680 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
681 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000682{
Corentin Wallez37c39792015-08-20 14:19:46 -0400683 ASSERT(mImpl != nullptr);
Jamie Madill362876b2016-06-16 14:46:59 -0400684 ASSERT(mState.mColorAttachments.size() == static_cast<size_t>(caps.maxColorAttachments));
685
Jamie Madill1e5499d2017-04-05 11:22:16 -0400686 for (uint32_t colorIndex = 0;
687 colorIndex < static_cast<uint32_t>(mState.mColorAttachments.size()); ++colorIndex)
Jamie Madill362876b2016-06-16 14:46:59 -0400688 {
Jamie Madill1e5499d2017-04-05 11:22:16 -0400689 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
Jamie Madill362876b2016-06-16 14:46:59 -0400690 }
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600691 mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
Corentin Wallez37c39792015-08-20 14:19:46 -0400692}
693
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600694Framebuffer::Framebuffer(const Context *context, egl::Surface *surface, egl::Surface *readSurface)
Jamie Madill362876b2016-06-16 14:46:59 -0400695 : mState(),
Geoff Langbf7b95d2018-05-01 16:48:21 -0400696 mImpl(surface->getImplementation()->createDefaultFramebuffer(context, mState)),
Jamie Madill362876b2016-06-16 14:46:59 -0400697 mCachedStatus(GL_FRAMEBUFFER_COMPLETE),
698 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
699 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
Corentin Wallez37c39792015-08-20 14:19:46 -0400700{
Geoff Langda88add2014-12-01 10:22:01 -0500701 ASSERT(mImpl != nullptr);
Jamie Madill6f60d052017-02-22 15:20:11 -0500702
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600703 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
Geoff Langbf7b95d2018-05-01 16:48:21 -0400704 setAttachmentImpl(context, GL_FRAMEBUFFER_DEFAULT, GL_BACK, ImageIndex(), surface,
Jamie Madillcc129372018-04-12 09:13:18 -0400705 FramebufferAttachment::kDefaultNumViews,
Mingyu Hu7e44ec22019-08-26 15:59:48 -0700706 FramebufferAttachment::kDefaultBaseViewIndex, false,
707 FramebufferAttachment::kDefaultRenderToTextureSamples);
Jamie Madill6f60d052017-02-22 15:20:11 -0500708
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600709 setReadSurface(context, readSurface);
710
Jamie Madill6f60d052017-02-22 15:20:11 -0500711 if (surface->getConfig()->depthSize > 0)
712 {
Geoff Langbf7b95d2018-05-01 16:48:21 -0400713 setAttachmentImpl(context, GL_FRAMEBUFFER_DEFAULT, GL_DEPTH, ImageIndex(), surface,
Jamie Madillcc129372018-04-12 09:13:18 -0400714 FramebufferAttachment::kDefaultNumViews,
Mingyu Hu7e44ec22019-08-26 15:59:48 -0700715 FramebufferAttachment::kDefaultBaseViewIndex, false,
716 FramebufferAttachment::kDefaultRenderToTextureSamples);
Jamie Madill6f60d052017-02-22 15:20:11 -0500717 }
718
719 if (surface->getConfig()->stencilSize > 0)
720 {
Geoff Langbf7b95d2018-05-01 16:48:21 -0400721 setAttachmentImpl(context, GL_FRAMEBUFFER_DEFAULT, GL_STENCIL, ImageIndex(), surface,
Jamie Madillcc129372018-04-12 09:13:18 -0400722 FramebufferAttachment::kDefaultNumViews,
Mingyu Hu7e44ec22019-08-26 15:59:48 -0700723 FramebufferAttachment::kDefaultBaseViewIndex, false,
724 FramebufferAttachment::kDefaultRenderToTextureSamples);
Jamie Madill6f60d052017-02-22 15:20:11 -0500725 }
Jamie Madill6e18a232019-01-16 13:27:14 -0500726 SetComponentTypeMask(getDrawbufferWriteType(0), 0, &mState.mDrawBufferTypeMask);
Geoff Langee244c72019-05-06 10:30:18 -0400727
728 // Ensure the backend has a chance to synchronize its content for a new backbuffer.
729 mDirtyBits.set(DIRTY_BIT_COLOR_BUFFER_CONTENTS_0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000730}
731
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600732Framebuffer::Framebuffer(const Context *context,
733 rx::GLImplFactory *factory,
734 egl::Surface *readSurface)
Corentin Wallezccab69d2017-01-27 16:57:15 -0500735 : mState(),
736 mImpl(factory->createFramebuffer(mState)),
Corentin Wallezccab69d2017-01-27 16:57:15 -0500737 mCachedStatus(GL_FRAMEBUFFER_UNDEFINED_OES),
738 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
739 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
740{
Jamie Madill1e5499d2017-04-05 11:22:16 -0400741 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
Jamie Madill6e18a232019-01-16 13:27:14 -0500742 SetComponentTypeMask(getDrawbufferWriteType(0), 0, &mState.mDrawBufferTypeMask);
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600743
744 setReadSurface(context, readSurface);
Corentin Wallezccab69d2017-01-27 16:57:15 -0500745}
746
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000747Framebuffer::~Framebuffer()
748{
Geoff Langda88add2014-12-01 10:22:01 -0500749 SafeDelete(mImpl);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000750}
751
Jamie Madill4928b7c2017-06-20 12:57:39 -0400752void Framebuffer::onDestroy(const Context *context)
Jamie Madill6c1f6712017-02-14 19:08:04 -0500753{
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600754 if (isDefault())
755 {
756 mState.mDefaultFramebufferReadAttachment.detach(context);
757 mState.mDefaultFramebufferReadAttachmentInitialized = false;
758 }
759
Jamie Madill4928b7c2017-06-20 12:57:39 -0400760 for (auto &attachment : mState.mColorAttachments)
761 {
762 attachment.detach(context);
763 }
764 mState.mDepthAttachment.detach(context);
765 mState.mStencilAttachment.detach(context);
766 mState.mWebGLDepthAttachment.detach(context);
767 mState.mWebGLStencilAttachment.detach(context);
768 mState.mWebGLDepthStencilAttachment.detach(context);
769
Jamie Madillc564c072017-06-01 12:45:42 -0400770 mImpl->destroy(context);
Jamie Madill6c1f6712017-02-14 19:08:04 -0500771}
772
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600773void Framebuffer::setReadSurface(const Context *context, egl::Surface *readSurface)
774{
775 // updateAttachment() without mState.mResourceNeedsInit.set()
776 mState.mDefaultFramebufferReadAttachment.attach(
777 context, GL_FRAMEBUFFER_DEFAULT, GL_BACK, ImageIndex(), readSurface,
778 FramebufferAttachment::kDefaultNumViews, FramebufferAttachment::kDefaultBaseViewIndex,
Mingyu Hu7e44ec22019-08-26 15:59:48 -0700779 false, FramebufferAttachment::kDefaultRenderToTextureSamples);
Tim Van Patten56ba54c2019-08-08 13:03:34 -0600780 mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
781}
782
Jamie Madille90d4ee2018-11-28 14:04:00 -0500783void Framebuffer::setLabel(const Context *context, const std::string &label)
Geoff Lang70d0f492015-12-10 17:45:46 -0500784{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400785 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -0500786}
787
788const std::string &Framebuffer::getLabel() const
789{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400790 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -0500791}
792
Jamie Madill2ab08ed2019-08-12 16:20:21 -0400793bool Framebuffer::detachTexture(const Context *context, TextureID textureId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000794{
Jamie Madill2ab08ed2019-08-12 16:20:21 -0400795 return detachResourceById(context, GL_TEXTURE, textureId.value);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000796}
797
Jamie Madill7c7dec02019-08-06 17:44:11 -0400798bool Framebuffer::detachRenderbuffer(const Context *context, RenderbufferID renderbufferId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000799{
Jamie Madill7c7dec02019-08-06 17:44:11 -0400800 return detachResourceById(context, GL_RENDERBUFFER, renderbufferId.value);
Jamie Madilld1405e52015-03-05 15:41:39 -0500801}
Jamie Madille261b442014-06-25 12:42:21 -0400802
Jamie Madill8693bdb2017-09-02 15:32:14 -0400803bool Framebuffer::detachResourceById(const Context *context, GLenum resourceType, GLuint resourceId)
Jamie Madilld1405e52015-03-05 15:41:39 -0500804{
Jamie Madill8693bdb2017-09-02 15:32:14 -0400805 bool found = false;
806
Jamie Madill362876b2016-06-16 14:46:59 -0400807 for (size_t colorIndex = 0; colorIndex < mState.mColorAttachments.size(); ++colorIndex)
Jamie Madilld1405e52015-03-05 15:41:39 -0500808 {
Jamie Madill8693bdb2017-09-02 15:32:14 -0400809 if (detachMatchingAttachment(context, &mState.mColorAttachments[colorIndex], resourceType,
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300810 resourceId))
Jamie Madill8693bdb2017-09-02 15:32:14 -0400811 {
812 found = true;
813 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000814 }
815
Jamie Madilla02315b2017-02-23 14:14:47 -0500816 if (context->isWebGL1())
817 {
818 const std::array<FramebufferAttachment *, 3> attachments = {
819 {&mState.mWebGLDepthStencilAttachment, &mState.mWebGLDepthAttachment,
820 &mState.mWebGLStencilAttachment}};
821 for (FramebufferAttachment *attachment : attachments)
822 {
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300823 if (detachMatchingAttachment(context, attachment, resourceType, resourceId))
Jamie Madilla02315b2017-02-23 14:14:47 -0500824 {
Jamie Madill8693bdb2017-09-02 15:32:14 -0400825 found = true;
Jamie Madilla02315b2017-02-23 14:14:47 -0500826 }
827 }
828 }
829 else
830 {
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300831 if (detachMatchingAttachment(context, &mState.mDepthAttachment, resourceType, resourceId))
Jamie Madill8693bdb2017-09-02 15:32:14 -0400832 {
833 found = true;
834 }
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300835 if (detachMatchingAttachment(context, &mState.mStencilAttachment, resourceType, resourceId))
Jamie Madill8693bdb2017-09-02 15:32:14 -0400836 {
837 found = true;
838 }
Jamie Madilla02315b2017-02-23 14:14:47 -0500839 }
Jamie Madill8693bdb2017-09-02 15:32:14 -0400840
841 return found;
Jamie Madill362876b2016-06-16 14:46:59 -0400842}
843
Jamie Madill8693bdb2017-09-02 15:32:14 -0400844bool Framebuffer::detachMatchingAttachment(const Context *context,
Jamie Madill4928b7c2017-06-20 12:57:39 -0400845 FramebufferAttachment *attachment,
Jamie Madill362876b2016-06-16 14:46:59 -0400846 GLenum matchType,
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300847 GLuint matchId)
Jamie Madill362876b2016-06-16 14:46:59 -0400848{
849 if (attachment->isAttached() && attachment->type() == matchType && attachment->id() == matchId)
850 {
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300851 // We go through resetAttachment to make sure that all the required bookkeeping will be done
852 // such as updating enabled draw buffer state.
853 resetAttachment(context, attachment->getBinding());
Jamie Madill8693bdb2017-09-02 15:32:14 -0400854 return true;
Jamie Madill362876b2016-06-16 14:46:59 -0400855 }
Jamie Madill8693bdb2017-09-02 15:32:14 -0400856
857 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000858}
859
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400860const FramebufferAttachment *Framebuffer::getColorAttachment(size_t colorAttachment) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000861{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400862 return mState.getColorAttachment(colorAttachment);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000863}
864
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400865const FramebufferAttachment *Framebuffer::getDepthAttachment() const
Geoff Lang646559f2013-08-15 11:08:15 -0400866{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400867 return mState.getDepthAttachment();
Geoff Lang646559f2013-08-15 11:08:15 -0400868}
869
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400870const FramebufferAttachment *Framebuffer::getStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400871{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400872 return mState.getStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400873}
874
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400875const FramebufferAttachment *Framebuffer::getDepthStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400876{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400877 return mState.getDepthStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400878}
879
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400880const FramebufferAttachment *Framebuffer::getDepthOrStencilAttachment() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000881{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400882 return mState.getDepthOrStencilAttachment();
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000883}
884
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500885const FramebufferAttachment *Framebuffer::getStencilOrDepthStencilAttachment() const
886{
887 return mState.getStencilOrDepthStencilAttachment();
888}
889
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400890const FramebufferAttachment *Framebuffer::getReadColorAttachment() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000891{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400892 return mState.getReadAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000893}
894
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400895GLenum Framebuffer::getReadColorAttachmentType() const
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000896{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400897 const FramebufferAttachment *readAttachment = mState.getReadAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400898 return (readAttachment != nullptr ? readAttachment->type() : GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000899}
900
Jamie Madill4e71b2b2019-07-08 13:23:38 -0400901const FramebufferAttachment *Framebuffer::getFirstColorAttachment() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000902{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400903 return mState.getFirstColorAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000904}
905
Jamie Madill6dd06ea2017-07-19 13:47:55 -0400906const FramebufferAttachment *Framebuffer::getFirstNonNullAttachment() const
907{
908 return mState.getFirstNonNullAttachment();
909}
910
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800911const FramebufferAttachment *Framebuffer::getAttachment(const Context *context,
912 GLenum attachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000913{
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800914 return mState.getAttachment(context, attachment);
Geoff Lang55ba29c2013-07-11 16:57:53 -0400915}
916
Geoff Langa15472a2015-08-11 11:48:03 -0400917size_t Framebuffer::getDrawbufferStateCount() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000918{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400919 return mState.mDrawBufferStates.size();
Geoff Langa15472a2015-08-11 11:48:03 -0400920}
921
922GLenum Framebuffer::getDrawBufferState(size_t drawBuffer) const
923{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400924 ASSERT(drawBuffer < mState.mDrawBufferStates.size());
925 return mState.mDrawBufferStates[drawBuffer];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000926}
927
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500928const std::vector<GLenum> &Framebuffer::getDrawBufferStates() const
929{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400930 return mState.getDrawBufferStates();
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500931}
932
Geoff Lang164d54e2014-12-01 10:55:33 -0500933void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000934{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400935 auto &drawStates = mState.mDrawBufferStates;
Jamie Madilld1405e52015-03-05 15:41:39 -0500936
937 ASSERT(count <= drawStates.size());
938 std::copy(buffers, buffers + count, drawStates.begin());
939 std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500940 mDirtyBits.set(DIRTY_BIT_DRAW_BUFFERS);
Jamie Madilla4595b82017-01-11 17:36:34 -0500941
942 mState.mEnabledDrawBuffers.reset();
Brandon Jones76746f92017-11-22 11:44:41 -0800943 mState.mDrawBufferTypeMask.reset();
944
Jamie Madilla4595b82017-01-11 17:36:34 -0500945 for (size_t index = 0; index < count; ++index)
946 {
Jamie Madill6e18a232019-01-16 13:27:14 -0500947 SetComponentTypeMask(getDrawbufferWriteType(index), index, &mState.mDrawBufferTypeMask);
Brandon Jones76746f92017-11-22 11:44:41 -0800948
Jamie Madilla4595b82017-01-11 17:36:34 -0500949 if (drawStates[index] != GL_NONE && mState.mColorAttachments[index].isAttached())
950 {
951 mState.mEnabledDrawBuffers.set(index);
952 }
953 }
Geoff Lang9dd95802014-12-01 11:12:59 -0500954}
955
Geoff Langa15472a2015-08-11 11:48:03 -0400956const FramebufferAttachment *Framebuffer::getDrawBuffer(size_t drawBuffer) const
957{
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400958 return mState.getDrawBuffer(drawBuffer);
Geoff Langa15472a2015-08-11 11:48:03 -0400959}
960
Jamie Madill6e18a232019-01-16 13:27:14 -0500961ComponentType Framebuffer::getDrawbufferWriteType(size_t drawBuffer) const
Geoff Lange0cff192017-05-30 13:04:56 -0400962{
963 const FramebufferAttachment *attachment = mState.getDrawBuffer(drawBuffer);
964 if (attachment == nullptr)
965 {
Jamie Madill6e18a232019-01-16 13:27:14 -0500966 return ComponentType::NoType;
Geoff Lange0cff192017-05-30 13:04:56 -0400967 }
968
969 GLenum componentType = attachment->getFormat().info->componentType;
970 switch (componentType)
971 {
972 case GL_INT:
Jamie Madill6e18a232019-01-16 13:27:14 -0500973 return ComponentType::Int;
Geoff Lange0cff192017-05-30 13:04:56 -0400974 case GL_UNSIGNED_INT:
Jamie Madill6e18a232019-01-16 13:27:14 -0500975 return ComponentType::UnsignedInt;
Geoff Lange0cff192017-05-30 13:04:56 -0400976
977 default:
Jamie Madill6e18a232019-01-16 13:27:14 -0500978 return ComponentType::Float;
Geoff Lange0cff192017-05-30 13:04:56 -0400979 }
980}
981
Brandon Jonesc405ae72017-12-06 14:15:03 -0800982ComponentTypeMask Framebuffer::getDrawBufferTypeMask() const
Brandon Jones76746f92017-11-22 11:44:41 -0800983{
984 return mState.mDrawBufferTypeMask;
985}
986
987DrawBufferMask Framebuffer::getDrawBufferMask() const
988{
989 return mState.mEnabledDrawBuffers;
990}
991
Geoff Langa15472a2015-08-11 11:48:03 -0400992bool Framebuffer::hasEnabledDrawBuffer() const
993{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400994 for (size_t drawbufferIdx = 0; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
Geoff Langa15472a2015-08-11 11:48:03 -0400995 {
996 if (getDrawBuffer(drawbufferIdx) != nullptr)
997 {
998 return true;
999 }
1000 }
1001
1002 return false;
1003}
1004
Geoff Lang9dd95802014-12-01 11:12:59 -05001005GLenum Framebuffer::getReadBufferState() const
1006{
Jamie Madill48ef11b2016-04-27 15:21:52 -04001007 return mState.mReadBufferState;
Geoff Lang9dd95802014-12-01 11:12:59 -05001008}
1009
1010void Framebuffer::setReadBuffer(GLenum buffer)
1011{
Jamie Madillb885e572015-02-03 16:16:04 -05001012 ASSERT(buffer == GL_BACK || buffer == GL_NONE ||
1013 (buffer >= GL_COLOR_ATTACHMENT0 &&
Jamie Madill48ef11b2016-04-27 15:21:52 -04001014 (buffer - GL_COLOR_ATTACHMENT0) < mState.mColorAttachments.size()));
1015 mState.mReadBufferState = buffer;
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001016 mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001017}
1018
Jamie Madill4e71b2b2019-07-08 13:23:38 -04001019size_t Framebuffer::getNumColorAttachments() const
Corentin Wallez37c39792015-08-20 14:19:46 -04001020{
Jamie Madill48ef11b2016-04-27 15:21:52 -04001021 return mState.mColorAttachments.size();
Corentin Wallez37c39792015-08-20 14:19:46 -04001022}
1023
Jamie Madill0df8fe42015-11-24 16:10:24 -05001024bool Framebuffer::hasDepth() const
1025{
Jamie Madill9c335862017-07-18 11:51:38 -04001026 return mState.hasDepth();
Jamie Madill0df8fe42015-11-24 16:10:24 -05001027}
1028
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +00001029bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00001030{
Jamie Madill9c335862017-07-18 11:51:38 -04001031 return mState.hasStencil();
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +00001032}
1033
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +00001034bool Framebuffer::usingExtendedDrawBuffers() const
1035{
Jamie Madill48ef11b2016-04-27 15:21:52 -04001036 for (size_t drawbufferIdx = 1; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +00001037 {
Geoff Langa15472a2015-08-11 11:48:03 -04001038 if (getDrawBuffer(drawbufferIdx) != nullptr)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +00001039 {
1040 return true;
1041 }
1042 }
1043
1044 return false;
1045}
1046
Jamie Madill124f78c2019-06-18 11:48:24 -04001047void Framebuffer::invalidateCompletenessCache()
Geoff Lang9aded172017-04-05 11:07:56 -04001048{
Tim Van Patten56ba54c2019-08-08 13:03:34 -06001049 if (!isDefault())
Geoff Lang9aded172017-04-05 11:07:56 -04001050 {
1051 mCachedStatus.reset();
1052 }
Jamie Madill124f78c2019-06-18 11:48:24 -04001053 onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
Geoff Lang9aded172017-04-05 11:07:56 -04001054}
1055
Jamie Madillcc73f242018-08-01 11:34:48 -04001056GLenum Framebuffer::checkStatusImpl(const Context *context)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001057{
Jamie Madillcc73f242018-08-01 11:34:48 -04001058 ASSERT(!isDefault());
1059 ASSERT(hasAnyDirtyBit() || !mCachedStatus.valid());
Geoff Lang528ce3c2014-12-01 10:44:07 -05001060
Jamie Madillcc73f242018-08-01 11:34:48 -04001061 mCachedStatus = checkStatusWithGLFrontEnd(context);
Jamie Madille98b1b52018-03-08 09:47:23 -05001062
Jamie Madillcc73f242018-08-01 11:34:48 -04001063 if (mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE)
1064 {
Jamie Madill67220092019-05-20 11:12:53 -04001065 // We can skip syncState on several back-ends.
1066 if (mImpl->shouldSyncStateBeforeCheckStatus())
Jamie Madille98b1b52018-03-08 09:47:23 -05001067 {
Jamie Madill67220092019-05-20 11:12:53 -04001068 angle::Result err = syncState(context);
1069 if (err != angle::Result::Continue)
1070 {
1071 return 0;
1072 }
Jamie Madillcc73f242018-08-01 11:34:48 -04001073 }
Jamie Madill67220092019-05-20 11:12:53 -04001074
Jamie Madillcc73f242018-08-01 11:34:48 -04001075 if (!mImpl->checkStatus(context))
1076 {
1077 mCachedStatus = GL_FRAMEBUFFER_UNSUPPORTED;
Jamie Madille98b1b52018-03-08 09:47:23 -05001078 }
Jamie Madill362876b2016-06-16 14:46:59 -04001079 }
1080
Jamie Madill427064d2018-04-13 16:20:34 -04001081 return mCachedStatus.value();
Jamie Madill362876b2016-06-16 14:46:59 -04001082}
1083
Jamie Madille98b1b52018-03-08 09:47:23 -05001084GLenum Framebuffer::checkStatusWithGLFrontEnd(const Context *context)
Jamie Madill362876b2016-06-16 14:46:59 -04001085{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001086 const State &state = context->getState();
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001087
Tim Van Patten56ba54c2019-08-08 13:03:34 -06001088 ASSERT(!isDefault());
Jamie Madill362876b2016-06-16 14:46:59 -04001089
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001090 bool hasAttachments = false;
1091 Optional<unsigned int> colorbufferSize;
1092 Optional<int> samples;
Geoff Lang92019432017-11-20 13:09:34 -05001093 Optional<bool> fixedSampleLocations;
JiangYizhou461d9a32017-01-04 16:37:26 +08001094 bool hasRenderbuffer = false;
Mingyu Hu2d0e5b52019-08-27 13:49:07 -07001095 Optional<int> renderToTextureSamples;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001096
Martin Radev9bc9a322017-07-21 14:28:17 +03001097 const FramebufferAttachment *firstAttachment = getFirstNonNullAttachment();
1098
Jiawei Shaoa8802472018-05-28 11:17:47 +08001099 Optional<bool> isLayered;
1100 Optional<TextureType> colorAttachmentsTextureType;
1101
Jamie Madill48ef11b2016-04-27 15:21:52 -04001102 for (const FramebufferAttachment &colorAttachment : mState.mColorAttachments)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001103 {
Jamie Madill2d06b732015-04-20 12:53:28 -04001104 if (colorAttachment.isAttached())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001105 {
Geoff Lang9f10b772017-05-16 15:51:03 -04001106 if (!CheckAttachmentCompleteness(context, colorAttachment))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001107 {
1108 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1109 }
daniel@transgaming.com01868132010-08-24 19:21:17 +00001110
Geoff Lang677bb6f2017-04-05 12:40:40 -04001111 const InternalFormat &format = *colorAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -04001112 if (format.depthBits > 0 || format.stencilBits > 0)
1113 {
1114 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1115 }
1116
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001117 if (!CheckAttachmentSampleCompleteness(context, colorAttachment, true, &samples,
Mingyu Hu2d0e5b52019-08-27 13:49:07 -07001118 &fixedSampleLocations, &renderToTextureSamples))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001119 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001120 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001121 }
1122
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001123 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
1124 // in GLES 3.0, there is no such restriction
1125 if (state.getClientMajorVersion() < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001126 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001127 if (colorbufferSize.valid())
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001128 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001129 if (format.pixelBytes != colorbufferSize.value())
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +00001130 {
1131 return GL_FRAMEBUFFER_UNSUPPORTED;
1132 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001133 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001134 else
1135 {
1136 colorbufferSize = format.pixelBytes;
1137 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001138 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001139
Martin Radev9bc9a322017-07-21 14:28:17 +03001140 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &colorAttachment))
1141 {
Mingyu Hu7d64c482019-03-12 14:27:40 -07001142 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR;
Martin Radev9bc9a322017-07-21 14:28:17 +03001143 }
1144
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001145 hasRenderbuffer = hasRenderbuffer || (colorAttachment.type() == GL_RENDERBUFFER);
Jiawei Shaoa8802472018-05-28 11:17:47 +08001146
1147 if (!hasAttachments)
1148 {
1149 isLayered = colorAttachment.isLayered();
1150 if (isLayered.value())
1151 {
1152 colorAttachmentsTextureType = colorAttachment.getTextureImageIndex().getType();
1153 }
1154 hasAttachments = true;
1155 }
1156 else
1157 {
1158 // [EXT_geometry_shader] section 9.4.1, "Framebuffer Completeness"
1159 // If any framebuffer attachment is layered, all populated attachments
1160 // must be layered. Additionally, all populated color attachments must
1161 // be from textures of the same target. {FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT }
1162 ASSERT(isLayered.valid());
1163 if (isLayered.value() != colorAttachment.isLayered())
1164 {
1165 return GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT;
1166 }
1167 else if (isLayered.value())
1168 {
1169 ASSERT(colorAttachmentsTextureType.valid());
1170 if (colorAttachmentsTextureType.value() !=
1171 colorAttachment.getTextureImageIndex().getType())
1172 {
1173 return GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT;
1174 }
1175 }
1176 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001177 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001178 }
1179
Jamie Madill48ef11b2016-04-27 15:21:52 -04001180 const FramebufferAttachment &depthAttachment = mState.mDepthAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -04001181 if (depthAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001182 {
Geoff Lang9f10b772017-05-16 15:51:03 -04001183 if (!CheckAttachmentCompleteness(context, depthAttachment))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001184 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001185 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001186 }
1187
Geoff Lang677bb6f2017-04-05 12:40:40 -04001188 const InternalFormat &format = *depthAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -04001189 if (format.depthBits == 0)
1190 {
1191 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001192 }
1193
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001194 if (!CheckAttachmentSampleCompleteness(context, depthAttachment, false, &samples,
Mingyu Hu2d0e5b52019-08-27 13:49:07 -07001195 &fixedSampleLocations, &renderToTextureSamples))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001196 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001197 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001198 }
Sami Väisänena797e062016-05-12 15:23:40 +03001199
Martin Radev9bc9a322017-07-21 14:28:17 +03001200 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &depthAttachment))
1201 {
Mingyu Hu7d64c482019-03-12 14:27:40 -07001202 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR;
Martin Radev9bc9a322017-07-21 14:28:17 +03001203 }
1204
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001205 hasRenderbuffer = hasRenderbuffer || (depthAttachment.type() == GL_RENDERBUFFER);
Jiawei Shaoa8802472018-05-28 11:17:47 +08001206
1207 if (!hasAttachments)
1208 {
1209 isLayered = depthAttachment.isLayered();
1210 hasAttachments = true;
1211 }
1212 else
1213 {
1214 // [EXT_geometry_shader] section 9.4.1, "Framebuffer Completeness"
1215 // If any framebuffer attachment is layered, all populated attachments
1216 // must be layered. {FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT }
1217 ASSERT(isLayered.valid());
1218 if (isLayered.value() != depthAttachment.isLayered())
1219 {
1220 return GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT;
1221 }
1222 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001223 }
1224
Jamie Madill48ef11b2016-04-27 15:21:52 -04001225 const FramebufferAttachment &stencilAttachment = mState.mStencilAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -04001226 if (stencilAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001227 {
Geoff Lang9f10b772017-05-16 15:51:03 -04001228 if (!CheckAttachmentCompleteness(context, stencilAttachment))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001229 {
1230 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1231 }
1232
Geoff Lang677bb6f2017-04-05 12:40:40 -04001233 const InternalFormat &format = *stencilAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -04001234 if (format.stencilBits == 0)
1235 {
1236 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001237 }
1238
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001239 if (!CheckAttachmentSampleCompleteness(context, stencilAttachment, false, &samples,
Mingyu Hu2d0e5b52019-08-27 13:49:07 -07001240 &fixedSampleLocations, &renderToTextureSamples))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001241 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001242 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001243 }
Corentin Wallez086d59a2016-04-29 09:06:49 -04001244
Martin Radev9bc9a322017-07-21 14:28:17 +03001245 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &stencilAttachment))
1246 {
Mingyu Hu7d64c482019-03-12 14:27:40 -07001247 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR;
Martin Radev9bc9a322017-07-21 14:28:17 +03001248 }
1249
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001250 hasRenderbuffer = hasRenderbuffer || (stencilAttachment.type() == GL_RENDERBUFFER);
Jiawei Shaoa8802472018-05-28 11:17:47 +08001251
1252 if (!hasAttachments)
1253 {
1254 hasAttachments = true;
1255 }
1256 else
1257 {
1258 // [EXT_geometry_shader] section 9.4.1, "Framebuffer Completeness"
1259 // If any framebuffer attachment is layered, all populated attachments
1260 // must be layered.
1261 // {FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT }
1262 ASSERT(isLayered.valid());
1263 if (isLayered.value() != stencilAttachment.isLayered())
1264 {
1265 return GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT;
1266 }
1267 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001268 }
1269
1270 // Starting from ES 3.0 stencil and depth, if present, should be the same image
1271 if (state.getClientMajorVersion() >= 3 && depthAttachment.isAttached() &&
1272 stencilAttachment.isAttached() && stencilAttachment != depthAttachment)
1273 {
1274 return GL_FRAMEBUFFER_UNSUPPORTED;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001275 }
1276
Jamie Madilla02315b2017-02-23 14:14:47 -05001277 // Special additional validation for WebGL 1 DEPTH/STENCIL/DEPTH_STENCIL.
1278 if (state.isWebGL1())
1279 {
1280 if (!mState.mWebGLDepthStencilConsistent)
1281 {
1282 return GL_FRAMEBUFFER_UNSUPPORTED;
1283 }
1284
1285 if (mState.mWebGLDepthStencilAttachment.isAttached())
1286 {
1287 if (mState.mWebGLDepthStencilAttachment.getDepthSize() == 0 ||
1288 mState.mWebGLDepthStencilAttachment.getStencilSize() == 0)
1289 {
1290 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1291 }
Martin Radev9bc9a322017-07-21 14:28:17 +03001292
1293 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment,
1294 &mState.mWebGLDepthStencilAttachment))
1295 {
Mingyu Hu7d64c482019-03-12 14:27:40 -07001296 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR;
Martin Radev9bc9a322017-07-21 14:28:17 +03001297 }
Jamie Madilla02315b2017-02-23 14:14:47 -05001298 }
1299 else if (mState.mStencilAttachment.isAttached() &&
1300 mState.mStencilAttachment.getDepthSize() > 0)
1301 {
1302 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1303 }
1304 else if (mState.mDepthAttachment.isAttached() &&
1305 mState.mDepthAttachment.getStencilSize() > 0)
1306 {
1307 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1308 }
1309 }
1310
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001311 // ES3.1(section 9.4) requires that if no image is attached to the framebuffer, and either the
1312 // value of the framebuffer's FRAMEBUFFER_DEFAULT_WIDTH or FRAMEBUFFER_DEFAULT_HEIGHT parameters
1313 // is zero, the framebuffer is considered incomplete.
JiangYizhou461d9a32017-01-04 16:37:26 +08001314 GLint defaultWidth = mState.getDefaultWidth();
1315 GLint defaultHeight = mState.getDefaultHeight();
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001316 if (!hasAttachments && (defaultWidth == 0 || defaultHeight == 0))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001317 {
1318 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001319 }
1320
Geoff Langa0e0aeb2017-04-12 15:06:29 -04001321 // In ES 2.0 and WebGL, all color attachments must have the same width and height.
Jamie Madillcc86d642015-11-24 13:00:07 -05001322 // In ES 3.0, there is no such restriction.
Geoff Langa0e0aeb2017-04-12 15:06:29 -04001323 if ((state.getClientMajorVersion() < 3 || state.getExtensions().webglCompatibility) &&
1324 !mState.attachmentsHaveSameDimensions())
Jamie Madillcc86d642015-11-24 13:00:07 -05001325 {
1326 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
1327 }
1328
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001329 // ES3.1(section 9.4) requires that if the attached images are a mix of renderbuffers and
1330 // textures, the value of TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all attached textures.
JiangYizhou461d9a32017-01-04 16:37:26 +08001331 if (fixedSampleLocations.valid() && hasRenderbuffer && !fixedSampleLocations.value())
1332 {
1333 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1334 }
1335
Kenneth Russellce8602a2017-10-03 18:23:08 -07001336 // The WebGL conformance tests implicitly define that all framebuffer
1337 // attachments must be unique. For example, the same level of a texture can
1338 // not be attached to two different color attachments.
1339 if (state.getExtensions().webglCompatibility)
1340 {
1341 if (!mState.colorAttachmentsAreUniqueImages())
1342 {
1343 return GL_FRAMEBUFFER_UNSUPPORTED;
1344 }
1345 }
1346
Jamie Madillcc86d642015-11-24 13:00:07 -05001347 return GL_FRAMEBUFFER_COMPLETE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001348}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001349
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001350angle::Result Framebuffer::discard(const Context *context, size_t count, const GLenum *attachments)
Austin Kinross08332632015-05-05 13:35:47 -07001351{
Jamie Madill05b35b22017-10-03 09:01:44 -04001352 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1353 // can be no-ops, so we should probably do that to ensure consistency.
1354 // TODO(jmadill): WebGL behaviour, and robust resource init behaviour without WebGL.
1355
Jamie Madill4928b7c2017-06-20 12:57:39 -04001356 return mImpl->discard(context, count, attachments);
Austin Kinross08332632015-05-05 13:35:47 -07001357}
1358
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001359angle::Result Framebuffer::invalidate(const Context *context,
1360 size_t count,
1361 const GLenum *attachments)
Jamie Madill2d96b9e2014-08-29 15:46:47 -04001362{
Jamie Madill05b35b22017-10-03 09:01:44 -04001363 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1364 // can be no-ops, so we should probably do that to ensure consistency.
1365 // TODO(jmadill): WebGL behaviour, and robust resource init behaviour without WebGL.
1366
Jamie Madill4928b7c2017-06-20 12:57:39 -04001367 return mImpl->invalidate(context, count, attachments);
Jamie Madill2d96b9e2014-08-29 15:46:47 -04001368}
1369
Jamie Madill05b35b22017-10-03 09:01:44 -04001370bool Framebuffer::partialClearNeedsInit(const Context *context,
1371 bool color,
1372 bool depth,
1373 bool stencil)
1374{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001375 const auto &glState = context->getState();
Jamie Madill05b35b22017-10-03 09:01:44 -04001376
1377 if (!glState.isRobustResourceInitEnabled())
1378 {
1379 return false;
1380 }
1381
1382 // Scissors can affect clearing.
1383 // TODO(jmadill): Check for complete scissor overlap.
1384 if (glState.isScissorTestEnabled())
1385 {
1386 return true;
1387 }
1388
1389 // If colors masked, we must clear before we clear. Do a simple check.
1390 // TODO(jmadill): Filter out unused color channels from the test.
1391 if (color)
1392 {
1393 const auto &blend = glState.getBlendState();
1394 if (!(blend.colorMaskRed && blend.colorMaskGreen && blend.colorMaskBlue &&
1395 blend.colorMaskAlpha))
1396 {
1397 return true;
1398 }
1399 }
1400
1401 const auto &depthStencil = glState.getDepthStencilState();
Yuly Novikov21edf3d2018-07-23 16:44:16 -04001402 if (stencil && (depthStencil.stencilMask != depthStencil.stencilWritemask ||
1403 depthStencil.stencilBackMask != depthStencil.stencilBackWritemask))
Jamie Madill05b35b22017-10-03 09:01:44 -04001404 {
1405 return true;
1406 }
1407
1408 return false;
1409}
1410
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001411angle::Result Framebuffer::invalidateSub(const Context *context,
1412 size_t count,
1413 const GLenum *attachments,
1414 const Rectangle &area)
Jamie Madill400a4412014-08-29 15:46:45 -04001415{
Jamie Madill05b35b22017-10-03 09:01:44 -04001416 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1417 // can be no-ops, so we should probably do that to ensure consistency.
1418 // TODO(jmadill): Make a invalidate no-op in WebGL 2.0.
1419
Jamie Madill4928b7c2017-06-20 12:57:39 -04001420 return mImpl->invalidateSub(context, count, attachments, area);
Jamie Madill400a4412014-08-29 15:46:45 -04001421}
1422
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001423angle::Result Framebuffer::clear(const Context *context, GLbitfield mask)
Geoff Langb04dc822014-12-01 12:02:02 -05001424{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001425 const auto &glState = context->getState();
Jamie Madill05b35b22017-10-03 09:01:44 -04001426 if (glState.isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -05001427 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001428 return angle::Result::Continue;
Jamie Madill984ef412015-11-24 16:10:21 -05001429 }
1430
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -04001431 // Remove clear bits that are ineffective. An effective clear changes at least one fragment. If
1432 // color/depth/stencil masks make the clear ineffective we skip it altogether.
1433
1434 // If all color channels are masked, don't attempt to clear color.
1435 if (context->getState().getBlendState().allChannelsMasked())
1436 {
1437 mask &= ~GL_COLOR_BUFFER_BIT;
1438 }
1439
1440 // If depth write is disabled, don't attempt to clear depth.
1441 if (!context->getState().getDepthStencilState().depthMask)
1442 {
1443 mask &= ~GL_DEPTH_BUFFER_BIT;
1444 }
1445
1446 // If all stencil bits are masked, don't attempt to clear stencil.
1447 if (context->getState().getDepthStencilState().stencilWritemask == 0)
1448 {
1449 mask &= ~GL_STENCIL_BUFFER_BIT;
1450 }
1451
1452 if (mask != 0)
1453 {
1454 ANGLE_TRY(mImpl->clear(context, mask));
1455 }
Jamie Madill05b35b22017-10-03 09:01:44 -04001456
Jamie Madill7c985f52018-11-29 18:16:17 -05001457 return angle::Result::Continue;
Geoff Langb04dc822014-12-01 12:02:02 -05001458}
1459
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001460angle::Result Framebuffer::clearBufferfv(const Context *context,
1461 GLenum buffer,
1462 GLint drawbuffer,
1463 const GLfloat *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001464{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001465 if (context->getState().isRasterizerDiscardEnabled() || IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001466 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001467 return angle::Result::Continue;
Jamie Madill984ef412015-11-24 16:10:21 -05001468 }
1469
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -04001470 if (buffer == GL_DEPTH)
1471 {
1472 // If depth write is disabled, don't attempt to clear depth.
1473 if (!context->getState().getDepthStencilState().depthMask)
1474 {
1475 return angle::Result::Continue;
1476 }
1477 }
1478 else
1479 {
1480 // If all color channels are masked, don't attempt to clear color.
1481 if (context->getState().getBlendState().allChannelsMasked())
1482 {
1483 return angle::Result::Continue;
1484 }
1485 }
1486
Jamie Madill05b35b22017-10-03 09:01:44 -04001487 ANGLE_TRY(mImpl->clearBufferfv(context, buffer, drawbuffer, values));
1488
Jamie Madill7c985f52018-11-29 18:16:17 -05001489 return angle::Result::Continue;
Geoff Langb04dc822014-12-01 12:02:02 -05001490}
1491
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001492angle::Result Framebuffer::clearBufferuiv(const Context *context,
1493 GLenum buffer,
1494 GLint drawbuffer,
1495 const GLuint *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001496{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001497 if (context->getState().isRasterizerDiscardEnabled() || IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001498 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001499 return angle::Result::Continue;
Jamie Madill984ef412015-11-24 16:10:21 -05001500 }
1501
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -04001502 // If all color channels are masked, don't attempt to clear color.
1503 if (context->getState().getBlendState().allChannelsMasked())
1504 {
1505 return angle::Result::Continue;
1506 }
1507
Jamie Madill05b35b22017-10-03 09:01:44 -04001508 ANGLE_TRY(mImpl->clearBufferuiv(context, buffer, drawbuffer, values));
1509
Jamie Madill7c985f52018-11-29 18:16:17 -05001510 return angle::Result::Continue;
Geoff Langb04dc822014-12-01 12:02:02 -05001511}
1512
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001513angle::Result Framebuffer::clearBufferiv(const Context *context,
1514 GLenum buffer,
1515 GLint drawbuffer,
1516 const GLint *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001517{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001518 if (context->getState().isRasterizerDiscardEnabled() || IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001519 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001520 return angle::Result::Continue;
Jamie Madill984ef412015-11-24 16:10:21 -05001521 }
1522
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -04001523 if (buffer == GL_STENCIL)
1524 {
1525 // If all stencil bits are masked, don't attempt to clear stencil.
1526 if (context->getState().getDepthStencilState().stencilWritemask == 0)
1527 {
1528 return angle::Result::Continue;
1529 }
1530 }
1531 else
1532 {
1533 // If all color channels are masked, don't attempt to clear color.
1534 if (context->getState().getBlendState().allChannelsMasked())
1535 {
1536 return angle::Result::Continue;
1537 }
1538 }
1539
Jamie Madill05b35b22017-10-03 09:01:44 -04001540 ANGLE_TRY(mImpl->clearBufferiv(context, buffer, drawbuffer, values));
1541
Jamie Madill7c985f52018-11-29 18:16:17 -05001542 return angle::Result::Continue;
Geoff Langb04dc822014-12-01 12:02:02 -05001543}
1544
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001545angle::Result Framebuffer::clearBufferfi(const Context *context,
1546 GLenum buffer,
1547 GLint drawbuffer,
1548 GLfloat depth,
1549 GLint stencil)
Geoff Langb04dc822014-12-01 12:02:02 -05001550{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001551 if (context->getState().isRasterizerDiscardEnabled() || IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001552 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001553 return angle::Result::Continue;
Jamie Madill984ef412015-11-24 16:10:21 -05001554 }
1555
Shahbaz Youssefif6c937f2019-04-02 17:04:08 -04001556 bool clearDepth = context->getState().getDepthStencilState().depthMask;
1557 bool clearStencil = context->getState().getDepthStencilState().stencilWritemask != 0;
1558
1559 if (clearDepth && clearStencil)
1560 {
1561 ASSERT(buffer == GL_DEPTH_STENCIL);
1562 ANGLE_TRY(mImpl->clearBufferfi(context, GL_DEPTH_STENCIL, drawbuffer, depth, stencil));
1563 }
1564 else if (clearDepth && !clearStencil)
1565 {
1566 ANGLE_TRY(mImpl->clearBufferfv(context, GL_DEPTH, drawbuffer, &depth));
1567 }
1568 else if (!clearDepth && clearStencil)
1569 {
1570 ANGLE_TRY(mImpl->clearBufferiv(context, GL_STENCIL, drawbuffer, &stencil));
1571 }
Jamie Madill05b35b22017-10-03 09:01:44 -04001572
Jamie Madill7c985f52018-11-29 18:16:17 -05001573 return angle::Result::Continue;
Geoff Langb04dc822014-12-01 12:02:02 -05001574}
1575
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001576angle::Result Framebuffer::getImplementationColorReadFormat(const Context *context,
1577 GLenum *formatOut)
Geoff Langbce529e2014-12-01 12:48:41 -05001578{
Jamie Madill690c8eb2018-03-12 15:20:03 -04001579 ANGLE_TRY(syncState(context));
1580 *formatOut = mImpl->getImplementationColorReadFormat(context);
Jamie Madill7c985f52018-11-29 18:16:17 -05001581 return angle::Result::Continue;
Geoff Langbce529e2014-12-01 12:48:41 -05001582}
1583
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001584angle::Result Framebuffer::getImplementationColorReadType(const Context *context, GLenum *typeOut)
Geoff Langbce529e2014-12-01 12:48:41 -05001585{
Jamie Madill690c8eb2018-03-12 15:20:03 -04001586 ANGLE_TRY(syncState(context));
1587 *typeOut = mImpl->getImplementationColorReadType(context);
Jamie Madill7c985f52018-11-29 18:16:17 -05001588 return angle::Result::Continue;
Geoff Langbce529e2014-12-01 12:48:41 -05001589}
1590
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001591angle::Result Framebuffer::readPixels(const Context *context,
1592 const Rectangle &area,
1593 GLenum format,
1594 GLenum type,
1595 void *pixels)
Geoff Langbce529e2014-12-01 12:48:41 -05001596{
Jamie Madill362876b2016-06-16 14:46:59 -04001597 ANGLE_TRY(mImpl->readPixels(context, area, format, type, pixels));
Geoff Lang520c4ae2015-05-05 13:12:36 -04001598
Jamie Madillc3dc5d42018-12-30 12:12:04 -05001599 Buffer *unpackBuffer = context->getState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Lang520c4ae2015-05-05 13:12:36 -04001600 if (unpackBuffer)
1601 {
James Dong020abb82019-07-24 11:33:49 -06001602 unpackBuffer->onDataChanged();
Geoff Lang520c4ae2015-05-05 13:12:36 -04001603 }
1604
Jamie Madill7c985f52018-11-29 18:16:17 -05001605 return angle::Result::Continue;
Geoff Langbce529e2014-12-01 12:48:41 -05001606}
1607
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001608angle::Result Framebuffer::blit(const Context *context,
1609 const Rectangle &sourceArea,
1610 const Rectangle &destArea,
1611 GLbitfield mask,
1612 GLenum filter)
Geoff Lang54bd5a42014-12-01 12:51:04 -05001613{
He Yunchao6be602d2016-12-22 14:33:07 +08001614 GLbitfield blitMask = mask;
1615
1616 // Note that blitting is called against draw framebuffer.
1617 // See the code in gl::Context::blitFramebuffer.
1618 if ((mask & GL_COLOR_BUFFER_BIT) && !hasEnabledDrawBuffer())
1619 {
1620 blitMask &= ~GL_COLOR_BUFFER_BIT;
1621 }
1622
1623 if ((mask & GL_STENCIL_BUFFER_BIT) && mState.getStencilAttachment() == nullptr)
1624 {
1625 blitMask &= ~GL_STENCIL_BUFFER_BIT;
1626 }
1627
1628 if ((mask & GL_DEPTH_BUFFER_BIT) && mState.getDepthAttachment() == nullptr)
1629 {
1630 blitMask &= ~GL_DEPTH_BUFFER_BIT;
1631 }
1632
1633 if (!blitMask)
1634 {
Jamie Madill7c985f52018-11-29 18:16:17 -05001635 return angle::Result::Continue;
He Yunchao6be602d2016-12-22 14:33:07 +08001636 }
1637
1638 return mImpl->blit(context, sourceArea, destArea, blitMask, filter);
Geoff Lang54bd5a42014-12-01 12:51:04 -05001639}
1640
Jamie Madill427064d2018-04-13 16:20:34 -04001641int Framebuffer::getSamples(const Context *context)
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001642{
Mingyu Hu2d0e5b52019-08-27 13:49:07 -07001643 return (isComplete(context) ? getCachedSamples(context, AttachmentSampleType::Emulated) : 0);
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001644}
1645
Mingyu Hu2d0e5b52019-08-27 13:49:07 -07001646int Framebuffer::getResourceSamples(const Context *context)
1647{
1648 return (isComplete(context) ? getCachedSamples(context, AttachmentSampleType::Resource) : 0);
1649}
1650
1651int Framebuffer::getCachedSamples(const Context *context, AttachmentSampleType sampleType) const
Jamie Madill9c335862017-07-18 11:51:38 -04001652{
Jamie Madill5b772312018-03-08 20:28:32 -05001653 ASSERT(mCachedStatus.valid() && mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE);
1654
Jamie Madill9c335862017-07-18 11:51:38 -04001655 // For a complete framebuffer, all attachments must have the same sample count.
1656 // In this case return the first nonzero sample size.
1657 const auto *firstNonNullAttachment = mState.getFirstNonNullAttachment();
1658 if (firstNonNullAttachment)
1659 {
1660 ASSERT(firstNonNullAttachment->isAttached());
Mingyu Hu2d0e5b52019-08-27 13:49:07 -07001661 if (sampleType == AttachmentSampleType::Resource)
1662 {
1663 return firstNonNullAttachment->getResourceSamples();
1664 }
1665 else
1666 {
1667 ASSERT(sampleType == AttachmentSampleType::Emulated);
1668 return firstNonNullAttachment->getSamples();
1669 }
Jamie Madill9c335862017-07-18 11:51:38 -04001670 }
1671
1672 // No attachments found.
1673 return 0;
1674}
1675
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001676angle::Result Framebuffer::getSamplePosition(const Context *context,
1677 size_t index,
1678 GLfloat *xy) const
Corentin Wallezccab69d2017-01-27 16:57:15 -05001679{
Geoff Lang13455072018-05-09 11:24:43 -04001680 ANGLE_TRY(mImpl->getSamplePosition(context, index, xy));
Jamie Madill7c985f52018-11-29 18:16:17 -05001681 return angle::Result::Continue;
Corentin Wallezccab69d2017-01-27 16:57:15 -05001682}
1683
Jamie Madille261b442014-06-25 12:42:21 -04001684bool Framebuffer::hasValidDepthStencil() const
1685{
Jamie Madill48ef11b2016-04-27 15:21:52 -04001686 return mState.getDepthStencilAttachment() != nullptr;
Jamie Madille261b442014-06-25 12:42:21 -04001687}
1688
Jamie Madilla02315b2017-02-23 14:14:47 -05001689void Framebuffer::setAttachment(const Context *context,
1690 GLenum type,
Jamie Madill2d06b732015-04-20 12:53:28 -04001691 GLenum binding,
1692 const ImageIndex &textureIndex,
1693 FramebufferAttachmentObject *resource)
Geoff Langab75a052014-10-15 12:56:37 -04001694{
Martin Radev5dae57b2017-07-14 16:15:55 +03001695 setAttachment(context, type, binding, textureIndex, resource,
1696 FramebufferAttachment::kDefaultNumViews,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001697 FramebufferAttachment::kDefaultBaseViewIndex, false,
1698 FramebufferAttachment::kDefaultRenderToTextureSamples);
Martin Radev5dae57b2017-07-14 16:15:55 +03001699}
1700
Mingyu Hu2d0e5b52019-08-27 13:49:07 -07001701void Framebuffer::setAttachmentMultisample(const Context *context,
1702 GLenum type,
1703 GLenum binding,
1704 const ImageIndex &textureIndex,
1705 FramebufferAttachmentObject *resource,
1706 GLsizei samples)
1707{
1708 setAttachment(context, type, binding, textureIndex, resource,
1709 FramebufferAttachment::kDefaultNumViews,
1710 FramebufferAttachment::kDefaultBaseViewIndex, false, samples);
1711}
1712
Martin Radev5dae57b2017-07-14 16:15:55 +03001713void Framebuffer::setAttachment(const Context *context,
1714 GLenum type,
1715 GLenum binding,
1716 const ImageIndex &textureIndex,
1717 FramebufferAttachmentObject *resource,
1718 GLsizei numViews,
1719 GLuint baseViewIndex,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001720 bool isMultiview,
1721 GLsizei samples)
Martin Radev5dae57b2017-07-14 16:15:55 +03001722{
Jamie Madilla02315b2017-02-23 14:14:47 -05001723 // Context may be null in unit tests.
1724 if (!context || !context->isWebGL1())
1725 {
Martin Radev5dae57b2017-07-14 16:15:55 +03001726 setAttachmentImpl(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001727 isMultiview, samples);
Jamie Madilla02315b2017-02-23 14:14:47 -05001728 return;
1729 }
1730
1731 switch (binding)
1732 {
1733 case GL_DEPTH_STENCIL:
1734 case GL_DEPTH_STENCIL_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001735 mState.mWebGLDepthStencilAttachment.attach(context, type, binding, textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001736 resource, numViews, baseViewIndex,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001737 isMultiview, samples);
Jamie Madilla02315b2017-02-23 14:14:47 -05001738 break;
1739 case GL_DEPTH:
1740 case GL_DEPTH_ATTACHMENT:
Martin Radev5dae57b2017-07-14 16:15:55 +03001741 mState.mWebGLDepthAttachment.attach(context, type, binding, textureIndex, resource,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001742 numViews, baseViewIndex, isMultiview, samples);
Jamie Madilla02315b2017-02-23 14:14:47 -05001743 break;
1744 case GL_STENCIL:
1745 case GL_STENCIL_ATTACHMENT:
Martin Radev5dae57b2017-07-14 16:15:55 +03001746 mState.mWebGLStencilAttachment.attach(context, type, binding, textureIndex, resource,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001747 numViews, baseViewIndex, isMultiview, samples);
Jamie Madilla02315b2017-02-23 14:14:47 -05001748 break;
1749 default:
Martin Radev5dae57b2017-07-14 16:15:55 +03001750 setAttachmentImpl(context, type, binding, textureIndex, resource, numViews,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001751 baseViewIndex, isMultiview, samples);
Jamie Madilla02315b2017-02-23 14:14:47 -05001752 return;
1753 }
1754
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001755 commitWebGL1DepthStencilIfConsistent(context, numViews, baseViewIndex, isMultiview, samples);
Jamie Madilla02315b2017-02-23 14:14:47 -05001756}
1757
Mingyu Hu7d64c482019-03-12 14:27:40 -07001758void Framebuffer::setAttachmentMultiview(const Context *context,
1759 GLenum type,
1760 GLenum binding,
1761 const ImageIndex &textureIndex,
1762 FramebufferAttachmentObject *resource,
1763 GLsizei numViews,
1764 GLint baseViewIndex)
Martin Radev82ef7742017-08-08 17:44:58 +03001765{
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001766 setAttachment(context, type, binding, textureIndex, resource, numViews, baseViewIndex, true,
1767 FramebufferAttachment::kDefaultRenderToTextureSamples);
Martin Radev5dae57b2017-07-14 16:15:55 +03001768}
1769
1770void Framebuffer::commitWebGL1DepthStencilIfConsistent(const Context *context,
1771 GLsizei numViews,
1772 GLuint baseViewIndex,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001773 bool isMultiview,
1774 GLsizei samples)
Jamie Madilla02315b2017-02-23 14:14:47 -05001775{
1776 int count = 0;
1777
1778 std::array<FramebufferAttachment *, 3> attachments = {{&mState.mWebGLDepthStencilAttachment,
1779 &mState.mWebGLDepthAttachment,
1780 &mState.mWebGLStencilAttachment}};
1781 for (FramebufferAttachment *attachment : attachments)
1782 {
1783 if (attachment->isAttached())
1784 {
1785 count++;
1786 }
1787 }
1788
1789 mState.mWebGLDepthStencilConsistent = (count <= 1);
1790 if (!mState.mWebGLDepthStencilConsistent)
1791 {
1792 // Inconsistent.
1793 return;
1794 }
1795
Geoff Lange466c552017-03-17 15:24:12 -04001796 auto getImageIndexIfTextureAttachment = [](const FramebufferAttachment &attachment) {
1797 if (attachment.type() == GL_TEXTURE)
1798 {
1799 return attachment.getTextureImageIndex();
1800 }
1801 else
1802 {
Jamie Madillcc129372018-04-12 09:13:18 -04001803 return ImageIndex();
Geoff Lange466c552017-03-17 15:24:12 -04001804 }
1805 };
1806
Jamie Madilla02315b2017-02-23 14:14:47 -05001807 if (mState.mWebGLDepthAttachment.isAttached())
1808 {
1809 const auto &depth = mState.mWebGLDepthAttachment;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001810 setAttachmentImpl(context, depth.type(), GL_DEPTH_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001811 getImageIndexIfTextureAttachment(depth), depth.getResource(), numViews,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001812 baseViewIndex, isMultiview, samples);
Jamie Madillcc129372018-04-12 09:13:18 -04001813 setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex(), nullptr, numViews,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001814 baseViewIndex, isMultiview, samples);
Jamie Madilla02315b2017-02-23 14:14:47 -05001815 }
1816 else if (mState.mWebGLStencilAttachment.isAttached())
1817 {
1818 const auto &stencil = mState.mWebGLStencilAttachment;
Jamie Madillcc129372018-04-12 09:13:18 -04001819 setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex(), nullptr, numViews,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001820 baseViewIndex, isMultiview, samples);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001821 setAttachmentImpl(context, stencil.type(), GL_STENCIL_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001822 getImageIndexIfTextureAttachment(stencil), stencil.getResource(),
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001823 numViews, baseViewIndex, isMultiview, samples);
Jamie Madilla02315b2017-02-23 14:14:47 -05001824 }
1825 else if (mState.mWebGLDepthStencilAttachment.isAttached())
1826 {
1827 const auto &depthStencil = mState.mWebGLDepthStencilAttachment;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001828 setAttachmentImpl(context, depthStencil.type(), GL_DEPTH_ATTACHMENT,
Geoff Lange466c552017-03-17 15:24:12 -04001829 getImageIndexIfTextureAttachment(depthStencil),
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001830 depthStencil.getResource(), numViews, baseViewIndex, isMultiview,
1831 samples);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001832 setAttachmentImpl(context, depthStencil.type(), GL_STENCIL_ATTACHMENT,
Geoff Lange466c552017-03-17 15:24:12 -04001833 getImageIndexIfTextureAttachment(depthStencil),
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001834 depthStencil.getResource(), numViews, baseViewIndex, isMultiview,
1835 samples);
Jamie Madilla02315b2017-02-23 14:14:47 -05001836 }
1837 else
1838 {
Jamie Madillcc129372018-04-12 09:13:18 -04001839 setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex(), nullptr, numViews,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001840 baseViewIndex, isMultiview, samples);
Jamie Madillcc129372018-04-12 09:13:18 -04001841 setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex(), nullptr, numViews,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001842 baseViewIndex, isMultiview, samples);
Jamie Madilla02315b2017-02-23 14:14:47 -05001843 }
1844}
1845
Jamie Madill4928b7c2017-06-20 12:57:39 -04001846void Framebuffer::setAttachmentImpl(const Context *context,
1847 GLenum type,
Jamie Madilla02315b2017-02-23 14:14:47 -05001848 GLenum binding,
1849 const ImageIndex &textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001850 FramebufferAttachmentObject *resource,
1851 GLsizei numViews,
1852 GLuint baseViewIndex,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001853 bool isMultiview,
1854 GLsizei samples)
Jamie Madilla02315b2017-02-23 14:14:47 -05001855{
Jamie Madilla02315b2017-02-23 14:14:47 -05001856 switch (binding)
1857 {
Jamie Madillb8126692017-04-05 11:22:17 -04001858 case GL_DEPTH_STENCIL:
1859 case GL_DEPTH_STENCIL_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001860 updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
Geoff Lang32d60062019-09-06 10:10:08 -04001861 &mDirtyDepthAttachmentBinding, type, binding, textureIndex, resource,
1862 numViews, baseViewIndex, isMultiview, samples);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001863 updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
Geoff Lang32d60062019-09-06 10:10:08 -04001864 &mDirtyStencilAttachmentBinding, type, binding, textureIndex, resource,
1865 numViews, baseViewIndex, isMultiview, samples);
Jamie Madill42975642017-10-12 12:31:51 -04001866 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001867
Jamie Madilla02315b2017-02-23 14:14:47 -05001868 case GL_DEPTH:
1869 case GL_DEPTH_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001870 updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001871 &mDirtyDepthAttachmentBinding, type, binding, textureIndex, resource,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001872 numViews, baseViewIndex, isMultiview, samples);
Jamie Madill2d06b732015-04-20 12:53:28 -04001873 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001874
Jamie Madilla02315b2017-02-23 14:14:47 -05001875 case GL_STENCIL:
1876 case GL_STENCIL_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001877 updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001878 &mDirtyStencilAttachmentBinding, type, binding, textureIndex, resource,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001879 numViews, baseViewIndex, isMultiview, samples);
Jamie Madilla02315b2017-02-23 14:14:47 -05001880 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001881
Jamie Madilla02315b2017-02-23 14:14:47 -05001882 case GL_BACK:
Geoff Lang8170eab2017-09-21 13:59:04 -04001883 updateAttachment(context, &mState.mColorAttachments[0], DIRTY_BIT_COLOR_ATTACHMENT_0,
1884 &mDirtyColorAttachmentBindings[0], type, binding, textureIndex,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001885 resource, numViews, baseViewIndex, isMultiview, samples);
Jamie Madilla02315b2017-02-23 14:14:47 -05001886 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001887
Jamie Madilla02315b2017-02-23 14:14:47 -05001888 default:
1889 {
1890 size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
1891 ASSERT(colorIndex < mState.mColorAttachments.size());
Jamie Madillb8126692017-04-05 11:22:17 -04001892 size_t dirtyBit = DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001893 updateAttachment(context, &mState.mColorAttachments[colorIndex], dirtyBit,
Jamie Madillb8126692017-04-05 11:22:17 -04001894 &mDirtyColorAttachmentBindings[colorIndex], type, binding,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001895 textureIndex, resource, numViews, baseViewIndex, isMultiview, samples);
Jamie Madilla02315b2017-02-23 14:14:47 -05001896
shrekshaoc87e0052019-02-21 11:40:28 -08001897 if (!resource)
1898 {
shrekshao8413fab2019-04-04 17:13:18 -07001899 mColorAttachmentBits.reset(colorIndex);
shrekshaoc87e0052019-02-21 11:40:28 -08001900 mFloat32ColorAttachmentBits.reset(colorIndex);
1901 }
1902 else
1903 {
shrekshao8413fab2019-04-04 17:13:18 -07001904 mColorAttachmentBits.set(colorIndex);
shrekshaoc87e0052019-02-21 11:40:28 -08001905 updateFloat32ColorAttachmentBits(
1906 colorIndex, resource->getAttachmentFormat(binding, textureIndex).info);
1907 }
1908
Corentin Walleze7557742017-06-01 13:09:57 -04001909 // TODO(jmadill): ASSERT instead of checking the attachment exists in
1910 // formsRenderingFeedbackLoopWith
Jamie Madilla02315b2017-02-23 14:14:47 -05001911 bool enabled = (type != GL_NONE && getDrawBufferState(colorIndex) != GL_NONE);
1912 mState.mEnabledDrawBuffers.set(colorIndex, enabled);
Jamie Madill6e18a232019-01-16 13:27:14 -05001913 SetComponentTypeMask(getDrawbufferWriteType(colorIndex), colorIndex,
1914 &mState.mDrawBufferTypeMask);
Jamie Madill2d06b732015-04-20 12:53:28 -04001915 }
Jamie Madilla02315b2017-02-23 14:14:47 -05001916 break;
Geoff Langab75a052014-10-15 12:56:37 -04001917 }
1918}
1919
Jamie Madill4928b7c2017-06-20 12:57:39 -04001920void Framebuffer::updateAttachment(const Context *context,
1921 FramebufferAttachment *attachment,
Jamie Madillb8126692017-04-05 11:22:17 -04001922 size_t dirtyBit,
Jamie Madilld4442552018-02-27 22:03:47 -05001923 angle::ObserverBinding *onDirtyBinding,
Jamie Madillb8126692017-04-05 11:22:17 -04001924 GLenum type,
1925 GLenum binding,
1926 const ImageIndex &textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001927 FramebufferAttachmentObject *resource,
1928 GLsizei numViews,
1929 GLuint baseViewIndex,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001930 bool isMultiview,
1931 GLsizei samples)
Jamie Madillb8126692017-04-05 11:22:17 -04001932{
Martin Radev5dae57b2017-07-14 16:15:55 +03001933 attachment->attach(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
Mingyu Hu7e44ec22019-08-26 15:59:48 -07001934 isMultiview, samples);
Jamie Madillb8126692017-04-05 11:22:17 -04001935 mDirtyBits.set(dirtyBit);
Jamie Madill05b35b22017-10-03 09:01:44 -04001936 mState.mResourceNeedsInit.set(dirtyBit, attachment->initState() == InitState::MayNeedInit);
Jamie Madill66f0d2c2018-11-30 15:25:36 -05001937 onDirtyBinding->bind(resource);
Jamie Madille98b1b52018-03-08 09:47:23 -05001938
Jamie Madill124f78c2019-06-18 11:48:24 -04001939 invalidateCompletenessCache();
Jamie Madillb8126692017-04-05 11:22:17 -04001940}
1941
Jamie Madilla02315b2017-02-23 14:14:47 -05001942void Framebuffer::resetAttachment(const Context *context, GLenum binding)
Jamie Madill2d06b732015-04-20 12:53:28 -04001943{
Jamie Madillcc129372018-04-12 09:13:18 -04001944 setAttachment(context, GL_NONE, binding, ImageIndex(), nullptr);
Jamie Madill2d06b732015-04-20 12:53:28 -04001945}
1946
Jamie Madill6f755b22018-10-09 12:48:54 -04001947angle::Result Framebuffer::syncState(const Context *context)
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001948{
1949 if (mDirtyBits.any())
1950 {
Jamie Madill888081d2018-02-27 00:24:46 -05001951 mDirtyBitsGuard = mDirtyBits;
Jamie Madill19fa1c62018-03-08 09:47:21 -05001952 ANGLE_TRY(mImpl->syncState(context, mDirtyBits));
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001953 mDirtyBits.reset();
Jamie Madill888081d2018-02-27 00:24:46 -05001954 mDirtyBitsGuard.reset();
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001955 }
Jamie Madill7c985f52018-11-29 18:16:17 -05001956 return angle::Result::Continue;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001957}
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001958
Jamie Madill124f78c2019-06-18 11:48:24 -04001959void Framebuffer::onSubjectStateChange(angle::SubjectIndex index, angle::SubjectMessage message)
Jamie Madill51f40ec2016-06-15 14:06:00 -04001960{
Jamie Madille4faae22019-05-10 08:27:00 -04001961 if (message != angle::SubjectMessage::SubjectChanged)
Jamie Madillf668a4b2018-09-23 17:01:20 -04001962 {
Jamie Madill67220092019-05-20 11:12:53 -04001963 // This can be triggered by SubImage calls for Textures.
1964 if (message == angle::SubjectMessage::ContentsChanged)
1965 {
1966 mDirtyBits.set(DIRTY_BIT_COLOR_BUFFER_CONTENTS_0 + index);
Jamie Madill124f78c2019-06-18 11:48:24 -04001967 onStateChange(angle::SubjectMessage::DirtyBitsFlagged);
Jamie Madill67220092019-05-20 11:12:53 -04001968 return;
1969 }
1970
Jamie Madillf668a4b2018-09-23 17:01:20 -04001971 // This can be triggered by the GL back-end TextureGL class.
Jamie Madille4faae22019-05-10 08:27:00 -04001972 ASSERT(message == angle::SubjectMessage::DirtyBitsFlagged);
Jamie Madillf668a4b2018-09-23 17:01:20 -04001973 return;
1974 }
Jamie Madill55e57f92018-09-18 11:32:43 -04001975
1976 ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(index));
1977 mDirtyBits.set(index);
Jamie Madill888081d2018-02-27 00:24:46 -05001978
Jamie Madill124f78c2019-06-18 11:48:24 -04001979 invalidateCompletenessCache();
Jamie Madill05b35b22017-10-03 09:01:44 -04001980
Jamie Madilld4442552018-02-27 22:03:47 -05001981 FramebufferAttachment *attachment = getAttachmentFromSubjectIndex(index);
1982
Jamie Madill05b35b22017-10-03 09:01:44 -04001983 // Mark the appropriate init flag.
Jamie Madilld4442552018-02-27 22:03:47 -05001984 mState.mResourceNeedsInit.set(index, attachment->initState() == InitState::MayNeedInit);
shrekshaoc87e0052019-02-21 11:40:28 -08001985
1986 // Update mFloat32ColorAttachmentBits Cache
1987 if (index < DIRTY_BIT_COLOR_ATTACHMENT_MAX)
1988 {
1989 ASSERT(index != DIRTY_BIT_DEPTH_ATTACHMENT);
1990 ASSERT(index != DIRTY_BIT_STENCIL_ATTACHMENT);
1991 updateFloat32ColorAttachmentBits(index - DIRTY_BIT_COLOR_ATTACHMENT_0,
1992 attachment->getFormat().info);
1993 }
Jamie Madilld4442552018-02-27 22:03:47 -05001994}
1995
1996FramebufferAttachment *Framebuffer::getAttachmentFromSubjectIndex(angle::SubjectIndex index)
1997{
1998 switch (index)
1999 {
2000 case DIRTY_BIT_DEPTH_ATTACHMENT:
2001 return &mState.mDepthAttachment;
2002 case DIRTY_BIT_STENCIL_ATTACHMENT:
2003 return &mState.mStencilAttachment;
2004 default:
2005 size_t colorIndex = (index - DIRTY_BIT_COLOR_ATTACHMENT_0);
2006 ASSERT(colorIndex < mState.mColorAttachments.size());
2007 return &mState.mColorAttachments[colorIndex];
2008 }
Jamie Madill51f40ec2016-06-15 14:06:00 -04002009}
2010
shrekshao8413fab2019-04-04 17:13:18 -07002011bool Framebuffer::formsRenderingFeedbackLoopWith(const Context *context) const
Jamie Madilla4595b82017-01-11 17:36:34 -05002012{
shrekshao8413fab2019-04-04 17:13:18 -07002013 const State &state = context->getState();
Jamie Madill785e8a02018-10-04 17:42:00 -04002014 const Program *program = state.getProgram();
Jamie Madilla4595b82017-01-11 17:36:34 -05002015
2016 // TODO(jmadill): Default framebuffer feedback loops.
Jiacheng Lu2c5d48a2019-08-23 09:28:35 -06002017 if (mState.isDefault())
Jamie Madilla4595b82017-01-11 17:36:34 -05002018 {
2019 return false;
2020 }
2021
Jamie Madill4e71b2b2019-07-08 13:23:38 -04002022 const FramebufferAttachment *depth = getDepthAttachment();
2023 const FramebufferAttachment *stencil = getStencilAttachment();
shrekshao8413fab2019-04-04 17:13:18 -07002024
2025 const bool checkDepth = depth && depth->type() == GL_TEXTURE;
2026 // Skip the feedback loop check for stencil if depth/stencil point to the same resource.
2027 const bool checkStencil =
2028 (stencil && stencil->type() == GL_TEXTURE) && (!depth || *stencil != *depth);
2029
2030 const gl::ActiveTextureMask &activeTextures = program->getActiveSamplersMask();
2031 const gl::ActiveTexturePointerArray &textures = state.getActiveTexturesCache();
2032
2033 for (size_t textureUnit : activeTextures)
Jamie Madilla4595b82017-01-11 17:36:34 -05002034 {
shrekshao8413fab2019-04-04 17:13:18 -07002035 Texture *texture = textures[textureUnit];
2036
2037 if (texture == nullptr)
Jamie Madilla4595b82017-01-11 17:36:34 -05002038 {
shrekshao8413fab2019-04-04 17:13:18 -07002039 continue;
2040 }
2041
2042 // Depth and stencil attachment form feedback loops
2043 // Regardless of if enabled or masked.
2044 if (checkDepth)
2045 {
Jamie Madillf7034432019-09-21 14:10:35 -04002046 if (texture->getId() == depth->id())
Jamie Madilla4595b82017-01-11 17:36:34 -05002047 {
2048 return true;
2049 }
2050 }
Jamie Madilla4595b82017-01-11 17:36:34 -05002051
shrekshao8413fab2019-04-04 17:13:18 -07002052 if (checkStencil)
Jamie Madill1d37bc52017-02-02 19:59:58 -05002053 {
Jamie Madillf7034432019-09-21 14:10:35 -04002054 if (texture->getId() == stencil->id())
Jamie Madill1d37bc52017-02-02 19:59:58 -05002055 {
Jamie Madill38fe6842018-09-19 07:20:00 -04002056 return true;
Jamie Madill1d37bc52017-02-02 19:59:58 -05002057 }
2058 }
shrekshao8413fab2019-04-04 17:13:18 -07002059
2060 // Check if any color attachment forms a feedback loop.
2061 for (size_t drawIndex : mColorAttachmentBits)
2062 {
2063 const FramebufferAttachment &attachment = mState.mColorAttachments[drawIndex];
2064 ASSERT(attachment.isAttached());
2065
2066 if (attachment.isTextureWithId(texture->id()))
2067 {
2068 // TODO(jmadill): Check for appropriate overlap.
2069 return true;
2070 }
2071 }
Jamie Madill1d37bc52017-02-02 19:59:58 -05002072 }
2073
Jamie Madilla4595b82017-01-11 17:36:34 -05002074 return false;
2075}
2076
Jamie Madillf7034432019-09-21 14:10:35 -04002077bool Framebuffer::formsCopyingFeedbackLoopWith(TextureID copyTextureID,
Jamie Madillfd3dd432017-02-02 19:59:59 -05002078 GLint copyTextureLevel,
2079 GLint copyTextureLayer) const
Jamie Madillf695a3a2017-01-11 17:36:35 -05002080{
Jiacheng Lu2c5d48a2019-08-23 09:28:35 -06002081 if (mState.isDefault())
Jamie Madillf695a3a2017-01-11 17:36:35 -05002082 {
2083 // It seems impossible to form a texture copying feedback loop with the default FBO.
2084 return false;
2085 }
2086
Jamie Madill4e71b2b2019-07-08 13:23:38 -04002087 const FramebufferAttachment *readAttachment = getReadColorAttachment();
Jamie Madillf695a3a2017-01-11 17:36:35 -05002088 ASSERT(readAttachment);
2089
2090 if (readAttachment->isTextureWithId(copyTextureID))
2091 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002092 const auto &imageIndex = readAttachment->getTextureImageIndex();
Jamie Madillcc129372018-04-12 09:13:18 -04002093 if (imageIndex.getLevelIndex() == copyTextureLevel)
Jamie Madillf695a3a2017-01-11 17:36:35 -05002094 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05002095 // Check 3D/Array texture layers.
Jamie Madillcc129372018-04-12 09:13:18 -04002096 return !imageIndex.hasLayer() || copyTextureLayer == ImageIndex::kEntireLevel ||
2097 imageIndex.getLayerIndex() == copyTextureLayer;
Jamie Madillf695a3a2017-01-11 17:36:35 -05002098 }
2099 }
2100 return false;
2101}
2102
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002103GLint Framebuffer::getDefaultWidth() const
2104{
2105 return mState.getDefaultWidth();
2106}
2107
2108GLint Framebuffer::getDefaultHeight() const
2109{
2110 return mState.getDefaultHeight();
2111}
2112
2113GLint Framebuffer::getDefaultSamples() const
2114{
2115 return mState.getDefaultSamples();
2116}
2117
Geoff Lang92019432017-11-20 13:09:34 -05002118bool Framebuffer::getDefaultFixedSampleLocations() const
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002119{
2120 return mState.getDefaultFixedSampleLocations();
2121}
2122
Jiawei Shaob1e91382018-05-17 14:33:55 +08002123GLint Framebuffer::getDefaultLayers() const
2124{
2125 return mState.getDefaultLayers();
2126}
2127
Jamie Madillb983a4b2018-08-01 11:34:51 -04002128void Framebuffer::setDefaultWidth(const Context *context, GLint defaultWidth)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002129{
2130 mState.mDefaultWidth = defaultWidth;
2131 mDirtyBits.set(DIRTY_BIT_DEFAULT_WIDTH);
Jamie Madill124f78c2019-06-18 11:48:24 -04002132 invalidateCompletenessCache();
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002133}
2134
Jamie Madillb983a4b2018-08-01 11:34:51 -04002135void Framebuffer::setDefaultHeight(const Context *context, GLint defaultHeight)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002136{
2137 mState.mDefaultHeight = defaultHeight;
2138 mDirtyBits.set(DIRTY_BIT_DEFAULT_HEIGHT);
Jamie Madill124f78c2019-06-18 11:48:24 -04002139 invalidateCompletenessCache();
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002140}
2141
Jamie Madillb983a4b2018-08-01 11:34:51 -04002142void Framebuffer::setDefaultSamples(const Context *context, GLint defaultSamples)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002143{
2144 mState.mDefaultSamples = defaultSamples;
2145 mDirtyBits.set(DIRTY_BIT_DEFAULT_SAMPLES);
Jamie Madill124f78c2019-06-18 11:48:24 -04002146 invalidateCompletenessCache();
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002147}
2148
Jamie Madillb983a4b2018-08-01 11:34:51 -04002149void Framebuffer::setDefaultFixedSampleLocations(const Context *context,
2150 bool defaultFixedSampleLocations)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002151{
2152 mState.mDefaultFixedSampleLocations = defaultFixedSampleLocations;
2153 mDirtyBits.set(DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS);
Jamie Madill124f78c2019-06-18 11:48:24 -04002154 invalidateCompletenessCache();
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002155}
2156
Jiawei Shaob1e91382018-05-17 14:33:55 +08002157void Framebuffer::setDefaultLayers(GLint defaultLayers)
2158{
2159 mState.mDefaultLayers = defaultLayers;
2160 mDirtyBits.set(DIRTY_BIT_DEFAULT_LAYERS);
2161}
2162
Martin Radev14a26ae2017-07-24 15:56:29 +03002163GLsizei Framebuffer::getNumViews() const
2164{
Martin Radev5c00d0d2017-08-07 10:06:59 +03002165 return mState.getNumViews();
Martin Radev14a26ae2017-07-24 15:56:29 +03002166}
2167
Martin Radev4e619f52017-08-09 11:50:06 +03002168GLint Framebuffer::getBaseViewIndex() const
2169{
2170 return mState.getBaseViewIndex();
2171}
2172
Mingyu Hu7d64c482019-03-12 14:27:40 -07002173bool Framebuffer::isMultiview() const
Martin Radev878c8b12017-07-28 09:51:04 +03002174{
Mingyu Hu7d64c482019-03-12 14:27:40 -07002175 return mState.isMultiview();
Martin Radev878c8b12017-07-28 09:51:04 +03002176}
2177
Olli Etuaho8acb1b62018-07-30 16:20:54 +03002178bool Framebuffer::readDisallowedByMultiview() const
2179{
Mingyu Hu7d64c482019-03-12 14:27:40 -07002180 return (mState.isMultiview() && mState.getNumViews() > 1);
Olli Etuaho8acb1b62018-07-30 16:20:54 +03002181}
2182
Jamie Madill64b7c4f2018-10-19 11:38:04 -04002183angle::Result Framebuffer::ensureClearAttachmentsInitialized(const Context *context,
2184 GLbitfield mask)
Geoff Langd4fff502017-09-22 11:28:28 -04002185{
Jamie Madillc3dc5d42018-12-30 12:12:04 -05002186 const auto &glState = context->getState();
Geoff Langd4fff502017-09-22 11:28:28 -04002187 if (!context->isRobustResourceInitEnabled() || glState.isRasterizerDiscardEnabled())
2188 {
Jamie Madill7c985f52018-11-29 18:16:17 -05002189 return angle::Result::Continue;
Geoff Langd4fff502017-09-22 11:28:28 -04002190 }
2191
Geoff Langa36483f2018-03-09 16:11:21 -05002192 const BlendState &blend = glState.getBlendState();
2193 const DepthStencilState &depthStencil = glState.getDepthStencilState();
Geoff Langd4fff502017-09-22 11:28:28 -04002194
2195 bool color = (mask & GL_COLOR_BUFFER_BIT) != 0 && !IsColorMaskedOut(blend);
2196 bool depth = (mask & GL_DEPTH_BUFFER_BIT) != 0 && !IsDepthMaskedOut(depthStencil);
2197 bool stencil = (mask & GL_STENCIL_BUFFER_BIT) != 0 && !IsStencilMaskedOut(depthStencil);
2198
2199 if (!color && !depth && !stencil)
2200 {
Jamie Madill7c985f52018-11-29 18:16:17 -05002201 return angle::Result::Continue;
Geoff Langd4fff502017-09-22 11:28:28 -04002202 }
2203
2204 if (partialClearNeedsInit(context, color, depth, stencil))
2205 {
2206 ANGLE_TRY(ensureDrawAttachmentsInitialized(context));
2207 }
2208
2209 // If the impl encounters an error during a a full (non-partial) clear, the attachments will
2210 // still be marked initialized. This simplifies design, allowing this method to be called before
2211 // the clear.
2212 markDrawAttachmentsInitialized(color, depth, stencil);
2213
Jamie Madill7c985f52018-11-29 18:16:17 -05002214 return angle::Result::Continue;
Geoff Langd4fff502017-09-22 11:28:28 -04002215}
2216
Jamie Madill64b7c4f2018-10-19 11:38:04 -04002217angle::Result Framebuffer::ensureClearBufferAttachmentsInitialized(const Context *context,
2218 GLenum buffer,
2219 GLint drawbuffer)
Geoff Langd4fff502017-09-22 11:28:28 -04002220{
2221 if (!context->isRobustResourceInitEnabled() ||
Jamie Madillc3dc5d42018-12-30 12:12:04 -05002222 context->getState().isRasterizerDiscardEnabled() || IsClearBufferMaskedOut(context, buffer))
Geoff Langd4fff502017-09-22 11:28:28 -04002223 {
Jamie Madill7c985f52018-11-29 18:16:17 -05002224 return angle::Result::Continue;
Geoff Langd4fff502017-09-22 11:28:28 -04002225 }
2226
2227 if (partialBufferClearNeedsInit(context, buffer))
2228 {
2229 ANGLE_TRY(ensureBufferInitialized(context, buffer, drawbuffer));
2230 }
2231
2232 // If the impl encounters an error during a a full (non-partial) clear, the attachments will
2233 // still be marked initialized. This simplifies design, allowing this method to be called before
2234 // the clear.
2235 markBufferInitialized(buffer, drawbuffer);
2236
Jamie Madill7c985f52018-11-29 18:16:17 -05002237 return angle::Result::Continue;
Geoff Langd4fff502017-09-22 11:28:28 -04002238}
2239
Jamie Madill6f755b22018-10-09 12:48:54 -04002240angle::Result Framebuffer::ensureDrawAttachmentsInitialized(const Context *context)
Jamie Madill05b35b22017-10-03 09:01:44 -04002241{
2242 if (!context->isRobustResourceInitEnabled())
2243 {
Jamie Madill7c985f52018-11-29 18:16:17 -05002244 return angle::Result::Continue;
Jamie Madill05b35b22017-10-03 09:01:44 -04002245 }
2246
2247 // Note: we don't actually filter by the draw attachment enum. Just init everything.
2248 for (size_t bit : mState.mResourceNeedsInit)
2249 {
2250 switch (bit)
2251 {
2252 case DIRTY_BIT_DEPTH_ATTACHMENT:
2253 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2254 break;
2255 case DIRTY_BIT_STENCIL_ATTACHMENT:
2256 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2257 break;
2258 default:
2259 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[bit]));
2260 break;
2261 }
2262 }
2263
2264 mState.mResourceNeedsInit.reset();
Jamie Madill7c985f52018-11-29 18:16:17 -05002265 return angle::Result::Continue;
Jamie Madill05b35b22017-10-03 09:01:44 -04002266}
2267
Jamie Madill0a1eeb82019-05-13 13:53:18 -04002268angle::Result Framebuffer::ensureReadAttachmentsInitialized(const Context *context)
Jamie Madill05b35b22017-10-03 09:01:44 -04002269{
Jamie Madill0a1eeb82019-05-13 13:53:18 -04002270 ASSERT(context->isRobustResourceInitEnabled());
2271
2272 if (mState.mResourceNeedsInit.none())
Jamie Madill05b35b22017-10-03 09:01:44 -04002273 {
Jamie Madill7c985f52018-11-29 18:16:17 -05002274 return angle::Result::Continue;
Jamie Madill05b35b22017-10-03 09:01:44 -04002275 }
2276
Jamie Madill0a1eeb82019-05-13 13:53:18 -04002277 if (mState.mReadBufferState != GL_NONE)
Jamie Madill05b35b22017-10-03 09:01:44 -04002278 {
Tim Van Patten56ba54c2019-08-08 13:03:34 -06002279 if (isDefault())
Jamie Madill05b35b22017-10-03 09:01:44 -04002280 {
Tim Van Patten56ba54c2019-08-08 13:03:34 -06002281 if (!mState.mDefaultFramebufferReadAttachmentInitialized)
2282 {
2283 ANGLE_TRY(InitAttachment(context, &mState.mDefaultFramebufferReadAttachment));
2284 mState.mDefaultFramebufferReadAttachmentInitialized = true;
2285 }
2286 }
2287 else
2288 {
2289 size_t readIndex = mState.getReadIndex();
2290 if (mState.mResourceNeedsInit[readIndex])
2291 {
2292 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[readIndex]));
2293 mState.mResourceNeedsInit.reset(readIndex);
2294 }
Jamie Madill05b35b22017-10-03 09:01:44 -04002295 }
2296 }
2297
Jamie Madill0a1eeb82019-05-13 13:53:18 -04002298 // Conservatively init depth since it can be read by BlitFramebuffer.
2299 if (hasDepth())
Jamie Madill05b35b22017-10-03 09:01:44 -04002300 {
2301 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2302 {
2303 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2304 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2305 }
2306 }
2307
Jamie Madill0a1eeb82019-05-13 13:53:18 -04002308 // Conservatively init stencil since it can be read by BlitFramebuffer.
2309 if (hasStencil())
Jamie Madill05b35b22017-10-03 09:01:44 -04002310 {
2311 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2312 {
2313 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2314 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2315 }
2316 }
2317
Jamie Madill7c985f52018-11-29 18:16:17 -05002318 return angle::Result::Continue;
Jamie Madill05b35b22017-10-03 09:01:44 -04002319}
2320
2321void Framebuffer::markDrawAttachmentsInitialized(bool color, bool depth, bool stencil)
2322{
2323 // Mark attachments as initialized.
2324 if (color)
2325 {
2326 for (auto colorIndex : mState.mEnabledDrawBuffers)
2327 {
2328 auto &colorAttachment = mState.mColorAttachments[colorIndex];
2329 ASSERT(colorAttachment.isAttached());
2330 colorAttachment.setInitState(InitState::Initialized);
2331 mState.mResourceNeedsInit.reset(colorIndex);
2332 }
2333 }
2334
2335 if (depth && mState.mDepthAttachment.isAttached())
2336 {
2337 mState.mDepthAttachment.setInitState(InitState::Initialized);
2338 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2339 }
2340
2341 if (stencil && mState.mStencilAttachment.isAttached())
2342 {
2343 mState.mStencilAttachment.setInitState(InitState::Initialized);
2344 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2345 }
2346}
2347
2348void Framebuffer::markBufferInitialized(GLenum bufferType, GLint bufferIndex)
2349{
2350 switch (bufferType)
2351 {
2352 case GL_COLOR:
2353 {
2354 ASSERT(bufferIndex < static_cast<GLint>(mState.mColorAttachments.size()));
2355 if (mState.mColorAttachments[bufferIndex].isAttached())
2356 {
2357 mState.mColorAttachments[bufferIndex].setInitState(InitState::Initialized);
2358 mState.mResourceNeedsInit.reset(bufferIndex);
2359 }
2360 break;
2361 }
2362 case GL_DEPTH:
2363 {
2364 if (mState.mDepthAttachment.isAttached())
2365 {
2366 mState.mDepthAttachment.setInitState(InitState::Initialized);
2367 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2368 }
2369 break;
2370 }
2371 case GL_STENCIL:
2372 {
2373 if (mState.mStencilAttachment.isAttached())
2374 {
2375 mState.mStencilAttachment.setInitState(InitState::Initialized);
2376 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2377 }
2378 break;
2379 }
2380 case GL_DEPTH_STENCIL:
2381 {
2382 if (mState.mDepthAttachment.isAttached())
2383 {
2384 mState.mDepthAttachment.setInitState(InitState::Initialized);
2385 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2386 }
2387 if (mState.mStencilAttachment.isAttached())
2388 {
2389 mState.mStencilAttachment.setInitState(InitState::Initialized);
2390 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2391 }
2392 break;
2393 }
2394 default:
2395 UNREACHABLE();
2396 break;
2397 }
2398}
2399
2400Box Framebuffer::getDimensions() const
2401{
2402 return mState.getDimensions();
2403}
2404
Jonah Ryan-Davis7151fe52019-07-17 15:15:27 -04002405Extents Framebuffer::getExtents() const
2406{
2407 return mState.getExtents();
2408}
2409
Jamie Madill64b7c4f2018-10-19 11:38:04 -04002410angle::Result Framebuffer::ensureBufferInitialized(const Context *context,
2411 GLenum bufferType,
2412 GLint bufferIndex)
Jamie Madill05b35b22017-10-03 09:01:44 -04002413{
2414 ASSERT(context->isRobustResourceInitEnabled());
2415
2416 if (mState.mResourceNeedsInit.none())
2417 {
Jamie Madill7c985f52018-11-29 18:16:17 -05002418 return angle::Result::Continue;
Jamie Madill05b35b22017-10-03 09:01:44 -04002419 }
2420
2421 switch (bufferType)
2422 {
2423 case GL_COLOR:
2424 {
2425 ASSERT(bufferIndex < static_cast<GLint>(mState.mColorAttachments.size()));
2426 if (mState.mResourceNeedsInit[bufferIndex])
2427 {
2428 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[bufferIndex]));
2429 mState.mResourceNeedsInit.reset(bufferIndex);
2430 }
2431 break;
2432 }
2433 case GL_DEPTH:
2434 {
2435 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2436 {
2437 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2438 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2439 }
2440 break;
2441 }
2442 case GL_STENCIL:
2443 {
2444 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2445 {
2446 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2447 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2448 }
2449 break;
2450 }
2451 case GL_DEPTH_STENCIL:
2452 {
2453 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2454 {
2455 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2456 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2457 }
2458 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2459 {
2460 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2461 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2462 }
2463 break;
2464 }
2465 default:
2466 UNREACHABLE();
2467 break;
2468 }
2469
Jamie Madill7c985f52018-11-29 18:16:17 -05002470 return angle::Result::Continue;
Jamie Madill05b35b22017-10-03 09:01:44 -04002471}
2472
2473bool Framebuffer::partialBufferClearNeedsInit(const Context *context, GLenum bufferType)
2474{
2475 if (!context->isRobustResourceInitEnabled() || mState.mResourceNeedsInit.none())
2476 {
2477 return false;
2478 }
2479
2480 switch (bufferType)
2481 {
2482 case GL_COLOR:
2483 return partialClearNeedsInit(context, true, false, false);
2484 case GL_DEPTH:
2485 return partialClearNeedsInit(context, false, true, false);
2486 case GL_STENCIL:
2487 return partialClearNeedsInit(context, false, false, true);
2488 case GL_DEPTH_STENCIL:
2489 return partialClearNeedsInit(context, false, true, true);
2490 default:
2491 UNREACHABLE();
2492 return false;
2493 }
2494}
Jamie Madill60ec6ea2016-01-22 15:27:19 -05002495} // namespace gl