blob: a50253d93310dc372fcc89c66d0c6fd195ef2e9f [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// Framebuffer.cpp: Implements the gl::Framebuffer class. Implements GL framebuffer
8// objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105.
9
Geoff Lang2b5420c2014-11-19 14:20:15 -050010#include "libANGLE/Framebuffer.h"
Jamie Madillc46f45d2015-03-31 13:20:55 -040011
Jamie Madillcc86d642015-11-24 13:00:07 -050012#include "common/Optional.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040013#include "common/bitset_utils.h"
Jamie Madillc46f45d2015-03-31 13:20:55 -040014#include "common/utilities.h"
15#include "libANGLE/Config.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050016#include "libANGLE/Context.h"
Jamie Madill6c1f6712017-02-14 19:08:04 -050017#include "libANGLE/Display.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050018#include "libANGLE/FramebufferAttachment.h"
Jamie Madillc46f45d2015-03-31 13:20:55 -040019#include "libANGLE/Renderbuffer.h"
20#include "libANGLE/Surface.h"
21#include "libANGLE/Texture.h"
Brandon Jones76746f92017-11-22 11:44:41 -080022#include "libANGLE/angletypes.h"
Jamie Madillc46f45d2015-03-31 13:20:55 -040023#include "libANGLE/formatutils.h"
Jamie Madill8415b5f2016-04-26 13:41:39 -040024#include "libANGLE/renderer/ContextImpl.h"
Geoff Langb5d8f232014-12-04 15:43:01 -050025#include "libANGLE/renderer/FramebufferImpl.h"
Jamie Madill7aea7e02016-05-10 10:39:45 -040026#include "libANGLE/renderer/GLImplFactory.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050027#include "libANGLE/renderer/RenderbufferImpl.h"
Corentin Wallez37c39792015-08-20 14:19:46 -040028#include "libANGLE/renderer/SurfaceImpl.h"
Geoff Lang0b7eef72014-06-12 14:10:47 -040029
Jamie Madill362876b2016-06-16 14:46:59 -040030using namespace angle;
31
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000032namespace gl
33{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000034
Jamie Madilld1405e52015-03-05 15:41:39 -050035namespace
36{
Jamie Madill362876b2016-06-16 14:46:59 -040037
Martin Radev9bc9a322017-07-21 14:28:17 +030038bool CheckMultiviewStateMatchesForCompleteness(const FramebufferAttachment *firstAttachment,
39 const FramebufferAttachment *secondAttachment)
40{
41 ASSERT(firstAttachment && secondAttachment);
42 ASSERT(firstAttachment->isAttached() && secondAttachment->isAttached());
43
44 if (firstAttachment->getNumViews() != secondAttachment->getNumViews())
45 {
46 return false;
47 }
48 if (firstAttachment->getBaseViewIndex() != secondAttachment->getBaseViewIndex())
49 {
50 return false;
51 }
52 if (firstAttachment->getMultiviewLayout() != secondAttachment->getMultiviewLayout())
53 {
54 return false;
55 }
56 if (firstAttachment->getMultiviewViewportOffsets() !=
57 secondAttachment->getMultiviewViewportOffsets())
58 {
59 return false;
60 }
61 return true;
62}
63
Geoff Lang9f10b772017-05-16 15:51:03 -040064bool CheckAttachmentCompleteness(const Context *context, const FramebufferAttachment &attachment)
65{
66 ASSERT(attachment.isAttached());
67
68 const Extents &size = attachment.getSize();
69 if (size.width == 0 || size.height == 0)
70 {
71 return false;
72 }
73
74 const InternalFormat &format = *attachment.getFormat().info;
75 if (!format.renderSupport(context->getClientVersion(), context->getExtensions()))
76 {
77 return false;
78 }
79
80 if (attachment.type() == GL_TEXTURE)
81 {
82 if (attachment.layer() >= size.depth)
83 {
84 return false;
85 }
86
87 // ES3 specifies that cube map texture attachments must be cube complete.
88 // This language is missing from the ES2 spec, but we enforce it here because some
89 // desktop OpenGL drivers also enforce this validation.
90 // TODO(jmadill): Check if OpenGL ES2 drivers enforce cube completeness.
91 const Texture *texture = attachment.getTexture();
92 ASSERT(texture);
Corentin Wallez99d492c2018-02-27 15:17:10 -050093 if (texture->getType() == TextureType::CubeMap &&
Geoff Lang9f10b772017-05-16 15:51:03 -040094 !texture->getTextureState().isCubeComplete())
95 {
96 return false;
97 }
Geoff Lang857c09d2017-05-16 15:55:04 -040098
99 if (!texture->getImmutableFormat())
100 {
101 GLuint attachmentMipLevel = static_cast<GLuint>(attachment.mipLevel());
102
103 // From the ES 3.0 spec, pg 213:
104 // If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is TEXTURE and the value of
105 // FRAMEBUFFER_ATTACHMENT_OBJECT_NAME does not name an immutable-format texture,
106 // then the value of FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL must be in the
107 // range[levelbase, q], where levelbase is the value of TEXTURE_BASE_LEVEL and q is
108 // the effective maximum texture level defined in the Mipmapping discussion of
109 // section 3.8.10.4.
110 if (attachmentMipLevel < texture->getBaseLevel() ||
111 attachmentMipLevel > texture->getMipmapMaxLevel())
112 {
113 return false;
114 }
115
116 // Form the ES 3.0 spec, pg 213/214:
117 // If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is TEXTURE and the value of
118 // FRAMEBUFFER_ATTACHMENT_OBJECT_NAME does not name an immutable-format texture and
119 // the value of FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL is not levelbase, then the
120 // texture must be mipmap complete, and if FRAMEBUFFER_ATTACHMENT_OBJECT_NAME names
121 // a cubemap texture, the texture must also be cube complete.
122 if (attachmentMipLevel != texture->getBaseLevel() && !texture->isMipmapComplete())
123 {
124 return false;
125 }
126 }
Geoff Lang9f10b772017-05-16 15:51:03 -0400127 }
128
129 return true;
130};
131
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400132bool CheckAttachmentSampleCompleteness(const Context *context,
133 const FramebufferAttachment &attachment,
134 bool colorAttachment,
135 Optional<int> *samples,
Geoff Lang92019432017-11-20 13:09:34 -0500136 Optional<bool> *fixedSampleLocations)
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400137{
138 ASSERT(attachment.isAttached());
139
140 if (attachment.type() == GL_TEXTURE)
141 {
142 const Texture *texture = attachment.getTexture();
143 ASSERT(texture);
144
145 const ImageIndex &attachmentImageIndex = attachment.getTextureImageIndex();
146
147 // ES3.1 (section 9.4) requires that the value of TEXTURE_FIXED_SAMPLE_LOCATIONS should be
148 // the same for all attached textures.
Jamie Madillcc129372018-04-12 09:13:18 -0400149 bool fixedSampleloc = texture->getFixedSampleLocations(
150 attachmentImageIndex.getTarget(), attachmentImageIndex.getLevelIndex());
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400151 if (fixedSampleLocations->valid() && fixedSampleloc != fixedSampleLocations->value())
152 {
153 return false;
154 }
155 else
156 {
157 *fixedSampleLocations = fixedSampleloc;
158 }
159 }
160
161 if (samples->valid())
162 {
163 if (attachment.getSamples() != samples->value())
164 {
165 if (colorAttachment)
166 {
167 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
168 // all color attachments have the same number of samples for the FBO to be complete.
169 return false;
170 }
171 else
172 {
173 // CHROMIUM_framebuffer_mixed_samples allows a framebuffer to be considered complete
174 // when its depth or stencil samples are a multiple of the number of color samples.
175 if (!context->getExtensions().framebufferMixedSamples)
176 {
177 return false;
178 }
179
180 if ((attachment.getSamples() % std::max(samples->value(), 1)) != 0)
181 {
182 return false;
183 }
184 }
185 }
186 }
187 else
188 {
189 *samples = attachment.getSamples();
190 }
191
192 return true;
193}
194
Jamie Madill05b35b22017-10-03 09:01:44 -0400195// Needed to index into the attachment arrays/bitsets.
Jamie Madill682efdc2017-10-03 14:10:29 -0400196static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS) ==
Jamie Madilld4442552018-02-27 22:03:47 -0500197 Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX,
Jamie Madill05b35b22017-10-03 09:01:44 -0400198 "Framebuffer Dirty bit mismatch");
Jamie Madill682efdc2017-10-03 14:10:29 -0400199static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS) ==
Jamie Madilld4442552018-02-27 22:03:47 -0500200 Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT,
Jamie Madill05b35b22017-10-03 09:01:44 -0400201 "Framebuffer Dirty bit mismatch");
Jamie Madill682efdc2017-10-03 14:10:29 -0400202static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS + 1) ==
Jamie Madilld4442552018-02-27 22:03:47 -0500203 Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT,
Jamie Madill05b35b22017-10-03 09:01:44 -0400204 "Framebuffer Dirty bit mismatch");
205
206Error InitAttachment(const Context *context, FramebufferAttachment *attachment)
207{
208 ASSERT(attachment->isAttached());
209 if (attachment->initState() == InitState::MayNeedInit)
210 {
211 ANGLE_TRY(attachment->initializeContents(context));
212 }
213 return NoError();
214}
215
216bool IsColorMaskedOut(const BlendState &blend)
217{
218 return (!blend.colorMaskRed && !blend.colorMaskGreen && !blend.colorMaskBlue &&
219 !blend.colorMaskAlpha);
220}
221
222bool IsDepthMaskedOut(const DepthStencilState &depthStencil)
223{
224 return !depthStencil.depthMask;
225}
226
227bool IsStencilMaskedOut(const DepthStencilState &depthStencil)
228{
229 return ((depthStencil.stencilMask & depthStencil.stencilWritemask) == 0);
230}
231
232bool IsClearBufferMaskedOut(const Context *context, GLenum buffer)
233{
234 switch (buffer)
235 {
236 case GL_COLOR:
237 return IsColorMaskedOut(context->getGLState().getBlendState());
238 case GL_DEPTH:
239 return IsDepthMaskedOut(context->getGLState().getDepthStencilState());
240 case GL_STENCIL:
241 return IsStencilMaskedOut(context->getGLState().getDepthStencilState());
242 case GL_DEPTH_STENCIL:
243 return IsDepthMaskedOut(context->getGLState().getDepthStencilState()) &&
244 IsStencilMaskedOut(context->getGLState().getDepthStencilState());
245 default:
246 UNREACHABLE();
247 return true;
248 }
249}
250
Jamie Madill362876b2016-06-16 14:46:59 -0400251} // anonymous namespace
Jamie Madilld1405e52015-03-05 15:41:39 -0500252
Jamie Madill6f60d052017-02-22 15:20:11 -0500253// This constructor is only used for default framebuffers.
Jamie Madill48ef11b2016-04-27 15:21:52 -0400254FramebufferState::FramebufferState()
Jamie Madill2274b652018-05-31 10:56:08 -0400255 : mId(0),
256 mLabel(),
Geoff Lang70d0f492015-12-10 17:45:46 -0500257 mColorAttachments(1),
Corentin Walleze7557742017-06-01 13:09:57 -0400258 mDrawBufferStates(1, GL_BACK),
Jamie Madill6f60d052017-02-22 15:20:11 -0500259 mReadBufferState(GL_BACK),
Brandon Jones76746f92017-11-22 11:44:41 -0800260 mDrawBufferTypeMask(),
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800261 mDefaultWidth(0),
262 mDefaultHeight(0),
263 mDefaultSamples(0),
Jamie Madilla02315b2017-02-23 14:14:47 -0500264 mDefaultFixedSampleLocations(GL_FALSE),
Jiawei Shaob1e91382018-05-17 14:33:55 +0800265 mDefaultLayers(0),
Jamie Madilla02315b2017-02-23 14:14:47 -0500266 mWebGLDepthStencilConsistent(true)
Corentin Wallez37c39792015-08-20 14:19:46 -0400267{
Geoff Langd90d3882017-03-21 10:49:54 -0400268 ASSERT(mDrawBufferStates.size() > 0);
Jamie Madilla4595b82017-01-11 17:36:34 -0500269 mEnabledDrawBuffers.set(0);
Corentin Wallez37c39792015-08-20 14:19:46 -0400270}
271
Jamie Madill2274b652018-05-31 10:56:08 -0400272FramebufferState::FramebufferState(const Caps &caps, GLuint id)
273 : mId(id),
274 mLabel(),
Geoff Lang70d0f492015-12-10 17:45:46 -0500275 mColorAttachments(caps.maxColorAttachments),
Jamie Madilld1405e52015-03-05 15:41:39 -0500276 mDrawBufferStates(caps.maxDrawBuffers, GL_NONE),
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800277 mReadBufferState(GL_COLOR_ATTACHMENT0_EXT),
Brandon Jones76746f92017-11-22 11:44:41 -0800278 mDrawBufferTypeMask(),
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800279 mDefaultWidth(0),
280 mDefaultHeight(0),
281 mDefaultSamples(0),
Jamie Madilla02315b2017-02-23 14:14:47 -0500282 mDefaultFixedSampleLocations(GL_FALSE),
Jiawei Shaob1e91382018-05-17 14:33:55 +0800283 mDefaultLayers(0),
Jamie Madilla02315b2017-02-23 14:14:47 -0500284 mWebGLDepthStencilConsistent(true)
Jamie Madilld1405e52015-03-05 15:41:39 -0500285{
Jamie Madill2274b652018-05-31 10:56:08 -0400286 ASSERT(mId != 0);
Geoff Langa15472a2015-08-11 11:48:03 -0400287 ASSERT(mDrawBufferStates.size() > 0);
Jamie Madilld1405e52015-03-05 15:41:39 -0500288 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
289}
290
Jamie Madill48ef11b2016-04-27 15:21:52 -0400291FramebufferState::~FramebufferState()
Jamie Madilld1405e52015-03-05 15:41:39 -0500292{
Jamie Madilld1405e52015-03-05 15:41:39 -0500293}
294
Jamie Madill48ef11b2016-04-27 15:21:52 -0400295const std::string &FramebufferState::getLabel()
Geoff Lang70d0f492015-12-10 17:45:46 -0500296{
297 return mLabel;
298}
299
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800300const FramebufferAttachment *FramebufferState::getAttachment(const Context *context,
301 GLenum attachment) const
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400302{
303 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
304 {
305 return getColorAttachment(attachment - GL_COLOR_ATTACHMENT0);
306 }
307
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800308 // WebGL1 allows a developer to query for attachment parameters even when "inconsistant" (i.e.
309 // multiple conflicting attachment points) and requires us to return the framebuffer attachment
310 // associated with WebGL.
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400311 switch (attachment)
312 {
313 case GL_COLOR:
314 case GL_BACK:
315 return getColorAttachment(0);
316 case GL_DEPTH:
317 case GL_DEPTH_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800318 if (context->isWebGL1())
319 {
320 return getWebGLDepthAttachment();
321 }
322 else
323 {
324 return getDepthAttachment();
325 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400326 case GL_STENCIL:
327 case GL_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800328 if (context->isWebGL1())
329 {
330 return getWebGLStencilAttachment();
331 }
332 else
333 {
334 return getStencilAttachment();
335 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400336 case GL_DEPTH_STENCIL:
337 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800338 if (context->isWebGL1())
339 {
340 return getWebGLDepthStencilAttachment();
341 }
342 else
343 {
344 return getDepthStencilAttachment();
345 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400346 default:
347 UNREACHABLE();
348 return nullptr;
349 }
350}
351
Jamie Madill05b35b22017-10-03 09:01:44 -0400352size_t FramebufferState::getReadIndex() const
Jamie Madill7147f012015-03-05 15:41:40 -0500353{
Jamie Madill231c7f52017-04-26 13:45:37 -0400354 ASSERT(mReadBufferState == GL_BACK ||
355 (mReadBufferState >= GL_COLOR_ATTACHMENT0 && mReadBufferState <= GL_COLOR_ATTACHMENT15));
356 size_t readIndex = (mReadBufferState == GL_BACK
357 ? 0
358 : static_cast<size_t>(mReadBufferState - GL_COLOR_ATTACHMENT0));
Jamie Madill7147f012015-03-05 15:41:40 -0500359 ASSERT(readIndex < mColorAttachments.size());
Jamie Madill05b35b22017-10-03 09:01:44 -0400360 return readIndex;
361}
362
363const FramebufferAttachment *FramebufferState::getReadAttachment() const
364{
365 if (mReadBufferState == GL_NONE)
366 {
367 return nullptr;
368 }
369 size_t readIndex = getReadIndex();
Jamie Madill2d06b732015-04-20 12:53:28 -0400370 return mColorAttachments[readIndex].isAttached() ? &mColorAttachments[readIndex] : nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500371}
372
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500373const FramebufferAttachment *FramebufferState::getFirstNonNullAttachment() const
374{
375 auto *colorAttachment = getFirstColorAttachment();
376 if (colorAttachment)
377 {
378 return colorAttachment;
379 }
380 return getDepthOrStencilAttachment();
381}
382
Jamie Madill48ef11b2016-04-27 15:21:52 -0400383const FramebufferAttachment *FramebufferState::getFirstColorAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500384{
Jamie Madill2d06b732015-04-20 12:53:28 -0400385 for (const FramebufferAttachment &colorAttachment : mColorAttachments)
Jamie Madill7147f012015-03-05 15:41:40 -0500386 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400387 if (colorAttachment.isAttached())
Jamie Madill7147f012015-03-05 15:41:40 -0500388 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400389 return &colorAttachment;
Jamie Madill7147f012015-03-05 15:41:40 -0500390 }
391 }
392
393 return nullptr;
394}
395
Jamie Madill48ef11b2016-04-27 15:21:52 -0400396const FramebufferAttachment *FramebufferState::getDepthOrStencilAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500397{
Jamie Madill2d06b732015-04-20 12:53:28 -0400398 if (mDepthAttachment.isAttached())
399 {
400 return &mDepthAttachment;
401 }
402 if (mStencilAttachment.isAttached())
403 {
404 return &mStencilAttachment;
405 }
406 return nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500407}
408
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500409const FramebufferAttachment *FramebufferState::getStencilOrDepthStencilAttachment() const
410{
411 if (mStencilAttachment.isAttached())
412 {
413 return &mStencilAttachment;
414 }
415 return getDepthStencilAttachment();
416}
417
Jamie Madill48ef11b2016-04-27 15:21:52 -0400418const FramebufferAttachment *FramebufferState::getColorAttachment(size_t colorAttachment) const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400419{
420 ASSERT(colorAttachment < mColorAttachments.size());
Jamie Madill231c7f52017-04-26 13:45:37 -0400421 return mColorAttachments[colorAttachment].isAttached() ? &mColorAttachments[colorAttachment]
422 : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400423}
424
Jamie Madill48ef11b2016-04-27 15:21:52 -0400425const FramebufferAttachment *FramebufferState::getDepthAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400426{
Jamie Madill2d06b732015-04-20 12:53:28 -0400427 return mDepthAttachment.isAttached() ? &mDepthAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400428}
429
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800430const FramebufferAttachment *FramebufferState::getWebGLDepthAttachment() const
431{
432 return mWebGLDepthAttachment.isAttached() ? &mWebGLDepthAttachment : nullptr;
433}
434
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800435const FramebufferAttachment *FramebufferState::getWebGLDepthStencilAttachment() const
436{
437 return mWebGLDepthStencilAttachment.isAttached() ? &mWebGLDepthStencilAttachment : nullptr;
438}
439
Jamie Madill48ef11b2016-04-27 15:21:52 -0400440const FramebufferAttachment *FramebufferState::getStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400441{
Jamie Madill2d06b732015-04-20 12:53:28 -0400442 return mStencilAttachment.isAttached() ? &mStencilAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400443}
444
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800445const FramebufferAttachment *FramebufferState::getWebGLStencilAttachment() const
446{
447 return mWebGLStencilAttachment.isAttached() ? &mWebGLStencilAttachment : nullptr;
448}
449
Jamie Madill48ef11b2016-04-27 15:21:52 -0400450const FramebufferAttachment *FramebufferState::getDepthStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400451{
452 // A valid depth-stencil attachment has the same resource bound to both the
453 // depth and stencil attachment points.
Jamie Madill2d06b732015-04-20 12:53:28 -0400454 if (mDepthAttachment.isAttached() && mStencilAttachment.isAttached() &&
Jamie Madill44f26482016-11-18 12:49:15 -0500455 mDepthAttachment == mStencilAttachment)
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400456 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400457 return &mDepthAttachment;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400458 }
459
460 return nullptr;
461}
462
Jamie Madill48ef11b2016-04-27 15:21:52 -0400463bool FramebufferState::attachmentsHaveSameDimensions() const
Jamie Madillcc86d642015-11-24 13:00:07 -0500464{
465 Optional<Extents> attachmentSize;
466
Jamie Madill231c7f52017-04-26 13:45:37 -0400467 auto hasMismatchedSize = [&attachmentSize](const FramebufferAttachment &attachment) {
Jamie Madillcc86d642015-11-24 13:00:07 -0500468 if (!attachment.isAttached())
469 {
470 return false;
471 }
472
473 if (!attachmentSize.valid())
474 {
475 attachmentSize = attachment.getSize();
476 return false;
477 }
478
Jeff Gilbert8f8edd62017-10-31 14:26:30 -0700479 const auto &prevSize = attachmentSize.value();
480 const auto &curSize = attachment.getSize();
481 return (curSize.width != prevSize.width || curSize.height != prevSize.height);
Jamie Madillcc86d642015-11-24 13:00:07 -0500482 };
483
484 for (const auto &attachment : mColorAttachments)
485 {
486 if (hasMismatchedSize(attachment))
487 {
488 return false;
489 }
490 }
491
492 if (hasMismatchedSize(mDepthAttachment))
493 {
494 return false;
495 }
496
497 return !hasMismatchedSize(mStencilAttachment);
498}
499
Jamie Madilld4442552018-02-27 22:03:47 -0500500const FramebufferAttachment *FramebufferState::getDrawBuffer(size_t drawBufferIdx) const
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400501{
502 ASSERT(drawBufferIdx < mDrawBufferStates.size());
503 if (mDrawBufferStates[drawBufferIdx] != GL_NONE)
504 {
505 // ES3 spec: "If the GL is bound to a draw framebuffer object, the ith buffer listed in bufs
506 // must be COLOR_ATTACHMENTi or NONE"
507 ASSERT(mDrawBufferStates[drawBufferIdx] == GL_COLOR_ATTACHMENT0 + drawBufferIdx ||
508 (drawBufferIdx == 0 && mDrawBufferStates[drawBufferIdx] == GL_BACK));
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800509
510 if (mDrawBufferStates[drawBufferIdx] == GL_BACK)
511 {
512 return getColorAttachment(0);
513 }
514 else
515 {
516 return getColorAttachment(mDrawBufferStates[drawBufferIdx] - GL_COLOR_ATTACHMENT0);
517 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400518 }
519 else
520 {
521 return nullptr;
522 }
523}
524
525size_t FramebufferState::getDrawBufferCount() const
526{
527 return mDrawBufferStates.size();
528}
529
Geoff Langb21e20d2016-07-19 15:35:41 -0400530bool FramebufferState::colorAttachmentsAreUniqueImages() const
531{
532 for (size_t firstAttachmentIdx = 0; firstAttachmentIdx < mColorAttachments.size();
533 firstAttachmentIdx++)
534 {
Jamie Madilld4442552018-02-27 22:03:47 -0500535 const FramebufferAttachment &firstAttachment = mColorAttachments[firstAttachmentIdx];
Geoff Langb21e20d2016-07-19 15:35:41 -0400536 if (!firstAttachment.isAttached())
537 {
538 continue;
539 }
540
541 for (size_t secondAttachmentIdx = firstAttachmentIdx + 1;
542 secondAttachmentIdx < mColorAttachments.size(); secondAttachmentIdx++)
543 {
Jamie Madilld4442552018-02-27 22:03:47 -0500544 const FramebufferAttachment &secondAttachment = mColorAttachments[secondAttachmentIdx];
Geoff Langb21e20d2016-07-19 15:35:41 -0400545 if (!secondAttachment.isAttached())
546 {
547 continue;
548 }
549
550 if (firstAttachment == secondAttachment)
551 {
552 return false;
553 }
554 }
555 }
556
557 return true;
558}
559
Jamie Madill9c335862017-07-18 11:51:38 -0400560bool FramebufferState::hasDepth() const
561{
562 return (mDepthAttachment.isAttached() && mDepthAttachment.getDepthSize() > 0);
563}
564
565bool FramebufferState::hasStencil() const
566{
567 return (mStencilAttachment.isAttached() && mStencilAttachment.getStencilSize() > 0);
568}
569
Martin Radev5c00d0d2017-08-07 10:06:59 +0300570GLsizei FramebufferState::getNumViews() const
571{
572 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
573 if (attachment == nullptr)
574 {
575 return FramebufferAttachment::kDefaultNumViews;
576 }
577 return attachment->getNumViews();
578}
579
580const std::vector<Offset> *FramebufferState::getViewportOffsets() const
581{
582 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
583 if (attachment == nullptr)
584 {
585 return nullptr;
586 }
587 return &attachment->getMultiviewViewportOffsets();
588}
589
590GLenum FramebufferState::getMultiviewLayout() const
591{
592 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
593 if (attachment == nullptr)
594 {
595 return GL_NONE;
596 }
597 return attachment->getMultiviewLayout();
598}
599
Martin Radev4e619f52017-08-09 11:50:06 +0300600int FramebufferState::getBaseViewIndex() const
601{
602 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
603 if (attachment == nullptr)
604 {
605 return GL_NONE;
606 }
607 return attachment->getBaseViewIndex();
608}
609
Jamie Madill05b35b22017-10-03 09:01:44 -0400610Box FramebufferState::getDimensions() const
611{
612 ASSERT(attachmentsHaveSameDimensions());
613 ASSERT(getFirstNonNullAttachment() != nullptr);
614 Extents extents = getFirstNonNullAttachment()->getSize();
615 return Box(0, 0, 0, extents.width, extents.height, extents.depth);
616}
617
Jamie Madill7aea7e02016-05-10 10:39:45 -0400618Framebuffer::Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id)
Jamie Madill2274b652018-05-31 10:56:08 -0400619 : mState(caps, id),
Jamie Madill362876b2016-06-16 14:46:59 -0400620 mImpl(factory->createFramebuffer(mState)),
Jamie Madill362876b2016-06-16 14:46:59 -0400621 mCachedStatus(),
622 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
623 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000624{
Corentin Wallez37c39792015-08-20 14:19:46 -0400625 ASSERT(mImpl != nullptr);
Jamie Madill362876b2016-06-16 14:46:59 -0400626 ASSERT(mState.mColorAttachments.size() == static_cast<size_t>(caps.maxColorAttachments));
627
Jamie Madill1e5499d2017-04-05 11:22:16 -0400628 for (uint32_t colorIndex = 0;
629 colorIndex < static_cast<uint32_t>(mState.mColorAttachments.size()); ++colorIndex)
Jamie Madill362876b2016-06-16 14:46:59 -0400630 {
Jamie Madill1e5499d2017-04-05 11:22:16 -0400631 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
Jamie Madill362876b2016-06-16 14:46:59 -0400632 }
Corentin Wallez37c39792015-08-20 14:19:46 -0400633}
634
Jamie Madill4928b7c2017-06-20 12:57:39 -0400635Framebuffer::Framebuffer(const egl::Display *display, egl::Surface *surface)
Jamie Madill362876b2016-06-16 14:46:59 -0400636 : mState(),
Jamie Madill6f60d052017-02-22 15:20:11 -0500637 mImpl(surface->getImplementation()->createDefaultFramebuffer(mState)),
Jamie Madill362876b2016-06-16 14:46:59 -0400638 mCachedStatus(GL_FRAMEBUFFER_COMPLETE),
639 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
640 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
Corentin Wallez37c39792015-08-20 14:19:46 -0400641{
Geoff Langda88add2014-12-01 10:22:01 -0500642 ASSERT(mImpl != nullptr);
Jamie Madill1e5499d2017-04-05 11:22:16 -0400643 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
Jamie Madill6f60d052017-02-22 15:20:11 -0500644
Jamie Madill4928b7c2017-06-20 12:57:39 -0400645 const Context *proxyContext = display->getProxyContext();
646
Jamie Madillcc129372018-04-12 09:13:18 -0400647 setAttachmentImpl(proxyContext, GL_FRAMEBUFFER_DEFAULT, GL_BACK, ImageIndex(), surface,
648 FramebufferAttachment::kDefaultNumViews,
Martin Radev5dae57b2017-07-14 16:15:55 +0300649 FramebufferAttachment::kDefaultBaseViewIndex,
650 FramebufferAttachment::kDefaultMultiviewLayout,
651 FramebufferAttachment::kDefaultViewportOffsets);
Jamie Madill6f60d052017-02-22 15:20:11 -0500652
653 if (surface->getConfig()->depthSize > 0)
654 {
Jamie Madillcc129372018-04-12 09:13:18 -0400655 setAttachmentImpl(proxyContext, GL_FRAMEBUFFER_DEFAULT, GL_DEPTH, ImageIndex(), surface,
656 FramebufferAttachment::kDefaultNumViews,
Jamie Madilld4442552018-02-27 22:03:47 -0500657 FramebufferAttachment::kDefaultBaseViewIndex,
658 FramebufferAttachment::kDefaultMultiviewLayout,
659 FramebufferAttachment::kDefaultViewportOffsets);
Jamie Madill6f60d052017-02-22 15:20:11 -0500660 }
661
662 if (surface->getConfig()->stencilSize > 0)
663 {
Jamie Madillcc129372018-04-12 09:13:18 -0400664 setAttachmentImpl(proxyContext, GL_FRAMEBUFFER_DEFAULT, GL_STENCIL, ImageIndex(), surface,
665 FramebufferAttachment::kDefaultNumViews,
666 FramebufferAttachment::kDefaultBaseViewIndex,
667 FramebufferAttachment::kDefaultMultiviewLayout,
668 FramebufferAttachment::kDefaultViewportOffsets);
Jamie Madill6f60d052017-02-22 15:20:11 -0500669 }
Brandon Jones76746f92017-11-22 11:44:41 -0800670 mState.mDrawBufferTypeMask.setIndex(getDrawbufferWriteType(0), 0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000671}
672
Corentin Wallezccab69d2017-01-27 16:57:15 -0500673Framebuffer::Framebuffer(rx::GLImplFactory *factory)
674 : mState(),
675 mImpl(factory->createFramebuffer(mState)),
Corentin Wallezccab69d2017-01-27 16:57:15 -0500676 mCachedStatus(GL_FRAMEBUFFER_UNDEFINED_OES),
677 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
678 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
679{
Jamie Madill1e5499d2017-04-05 11:22:16 -0400680 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
Brandon Jones76746f92017-11-22 11:44:41 -0800681 mState.mDrawBufferTypeMask.setIndex(getDrawbufferWriteType(0), 0);
Corentin Wallezccab69d2017-01-27 16:57:15 -0500682}
683
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000684Framebuffer::~Framebuffer()
685{
Geoff Langda88add2014-12-01 10:22:01 -0500686 SafeDelete(mImpl);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000687}
688
Jamie Madill4928b7c2017-06-20 12:57:39 -0400689void Framebuffer::onDestroy(const Context *context)
Jamie Madill6c1f6712017-02-14 19:08:04 -0500690{
Jamie Madill4928b7c2017-06-20 12:57:39 -0400691 for (auto &attachment : mState.mColorAttachments)
692 {
693 attachment.detach(context);
694 }
695 mState.mDepthAttachment.detach(context);
696 mState.mStencilAttachment.detach(context);
697 mState.mWebGLDepthAttachment.detach(context);
698 mState.mWebGLStencilAttachment.detach(context);
699 mState.mWebGLDepthStencilAttachment.detach(context);
700
Jamie Madillc564c072017-06-01 12:45:42 -0400701 mImpl->destroy(context);
Jamie Madill6c1f6712017-02-14 19:08:04 -0500702}
703
Geoff Lang70d0f492015-12-10 17:45:46 -0500704void Framebuffer::setLabel(const std::string &label)
705{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400706 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -0500707}
708
709const std::string &Framebuffer::getLabel() const
710{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400711 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -0500712}
713
Jamie Madill8693bdb2017-09-02 15:32:14 -0400714bool Framebuffer::detachTexture(const Context *context, GLuint textureId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000715{
Jamie Madill8693bdb2017-09-02 15:32:14 -0400716 return detachResourceById(context, GL_TEXTURE, textureId);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000717}
718
Jamie Madill8693bdb2017-09-02 15:32:14 -0400719bool Framebuffer::detachRenderbuffer(const Context *context, GLuint renderbufferId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000720{
Jamie Madill8693bdb2017-09-02 15:32:14 -0400721 return detachResourceById(context, GL_RENDERBUFFER, renderbufferId);
Jamie Madilld1405e52015-03-05 15:41:39 -0500722}
Jamie Madille261b442014-06-25 12:42:21 -0400723
Jamie Madill8693bdb2017-09-02 15:32:14 -0400724bool Framebuffer::detachResourceById(const Context *context, GLenum resourceType, GLuint resourceId)
Jamie Madilld1405e52015-03-05 15:41:39 -0500725{
Jamie Madill8693bdb2017-09-02 15:32:14 -0400726 bool found = false;
727
Jamie Madill362876b2016-06-16 14:46:59 -0400728 for (size_t colorIndex = 0; colorIndex < mState.mColorAttachments.size(); ++colorIndex)
Jamie Madilld1405e52015-03-05 15:41:39 -0500729 {
Jamie Madill8693bdb2017-09-02 15:32:14 -0400730 if (detachMatchingAttachment(context, &mState.mColorAttachments[colorIndex], resourceType,
731 resourceId, DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex))
732 {
733 found = true;
734 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000735 }
736
Jamie Madilla02315b2017-02-23 14:14:47 -0500737 if (context->isWebGL1())
738 {
739 const std::array<FramebufferAttachment *, 3> attachments = {
740 {&mState.mWebGLDepthStencilAttachment, &mState.mWebGLDepthAttachment,
741 &mState.mWebGLStencilAttachment}};
742 for (FramebufferAttachment *attachment : attachments)
743 {
744 if (attachment->isAttached() && attachment->type() == resourceType &&
745 attachment->id() == resourceId)
746 {
747 resetAttachment(context, attachment->getBinding());
Jamie Madill8693bdb2017-09-02 15:32:14 -0400748 found = true;
Jamie Madilla02315b2017-02-23 14:14:47 -0500749 }
750 }
751 }
752 else
753 {
Jamie Madill8693bdb2017-09-02 15:32:14 -0400754 if (detachMatchingAttachment(context, &mState.mDepthAttachment, resourceType, resourceId,
755 DIRTY_BIT_DEPTH_ATTACHMENT))
756 {
757 found = true;
758 }
759 if (detachMatchingAttachment(context, &mState.mStencilAttachment, resourceType, resourceId,
760 DIRTY_BIT_STENCIL_ATTACHMENT))
761 {
762 found = true;
763 }
Jamie Madilla02315b2017-02-23 14:14:47 -0500764 }
Jamie Madill8693bdb2017-09-02 15:32:14 -0400765
766 return found;
Jamie Madill362876b2016-06-16 14:46:59 -0400767}
768
Jamie Madill8693bdb2017-09-02 15:32:14 -0400769bool Framebuffer::detachMatchingAttachment(const Context *context,
Jamie Madill4928b7c2017-06-20 12:57:39 -0400770 FramebufferAttachment *attachment,
Jamie Madill362876b2016-06-16 14:46:59 -0400771 GLenum matchType,
772 GLuint matchId,
773 size_t dirtyBit)
774{
775 if (attachment->isAttached() && attachment->type() == matchType && attachment->id() == matchId)
776 {
Jamie Madill4928b7c2017-06-20 12:57:39 -0400777 attachment->detach(context);
Jamie Madill362876b2016-06-16 14:46:59 -0400778 mDirtyBits.set(dirtyBit);
Jamie Madill05b35b22017-10-03 09:01:44 -0400779 mState.mResourceNeedsInit.set(dirtyBit, false);
Jamie Madill8693bdb2017-09-02 15:32:14 -0400780 return true;
Jamie Madill362876b2016-06-16 14:46:59 -0400781 }
Jamie Madill8693bdb2017-09-02 15:32:14 -0400782
783 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000784}
785
Corentin Wallez37c39792015-08-20 14:19:46 -0400786const FramebufferAttachment *Framebuffer::getColorbuffer(size_t colorAttachment) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000787{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400788 return mState.getColorAttachment(colorAttachment);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000789}
790
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400791const FramebufferAttachment *Framebuffer::getDepthbuffer() const
Geoff Lang646559f2013-08-15 11:08:15 -0400792{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400793 return mState.getDepthAttachment();
Geoff Lang646559f2013-08-15 11:08:15 -0400794}
795
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400796const FramebufferAttachment *Framebuffer::getStencilbuffer() const
797{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400798 return mState.getStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400799}
800
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400801const FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
802{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400803 return mState.getDepthStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400804}
805
806const FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000807{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400808 return mState.getDepthOrStencilAttachment();
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000809}
810
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500811const FramebufferAttachment *Framebuffer::getStencilOrDepthStencilAttachment() const
812{
813 return mState.getStencilOrDepthStencilAttachment();
814}
815
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400816const FramebufferAttachment *Framebuffer::getReadColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000817{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400818 return mState.getReadAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000819}
820
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000821GLenum Framebuffer::getReadColorbufferType() const
822{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400823 const FramebufferAttachment *readAttachment = mState.getReadAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400824 return (readAttachment != nullptr ? readAttachment->type() : GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000825}
826
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400827const FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000828{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400829 return mState.getFirstColorAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000830}
831
Jamie Madill6dd06ea2017-07-19 13:47:55 -0400832const FramebufferAttachment *Framebuffer::getFirstNonNullAttachment() const
833{
834 return mState.getFirstNonNullAttachment();
835}
836
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800837const FramebufferAttachment *Framebuffer::getAttachment(const Context *context,
838 GLenum attachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000839{
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800840 return mState.getAttachment(context, attachment);
Geoff Lang55ba29c2013-07-11 16:57:53 -0400841}
842
Geoff Langa15472a2015-08-11 11:48:03 -0400843size_t Framebuffer::getDrawbufferStateCount() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000844{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400845 return mState.mDrawBufferStates.size();
Geoff Langa15472a2015-08-11 11:48:03 -0400846}
847
848GLenum Framebuffer::getDrawBufferState(size_t drawBuffer) const
849{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400850 ASSERT(drawBuffer < mState.mDrawBufferStates.size());
851 return mState.mDrawBufferStates[drawBuffer];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000852}
853
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500854const std::vector<GLenum> &Framebuffer::getDrawBufferStates() const
855{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400856 return mState.getDrawBufferStates();
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500857}
858
Geoff Lang164d54e2014-12-01 10:55:33 -0500859void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000860{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400861 auto &drawStates = mState.mDrawBufferStates;
Jamie Madilld1405e52015-03-05 15:41:39 -0500862
863 ASSERT(count <= drawStates.size());
864 std::copy(buffers, buffers + count, drawStates.begin());
865 std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500866 mDirtyBits.set(DIRTY_BIT_DRAW_BUFFERS);
Jamie Madilla4595b82017-01-11 17:36:34 -0500867
868 mState.mEnabledDrawBuffers.reset();
Brandon Jones76746f92017-11-22 11:44:41 -0800869 mState.mDrawBufferTypeMask.reset();
870
Jamie Madilla4595b82017-01-11 17:36:34 -0500871 for (size_t index = 0; index < count; ++index)
872 {
Brandon Jones76746f92017-11-22 11:44:41 -0800873 mState.mDrawBufferTypeMask.setIndex(getDrawbufferWriteType(index), index);
874
Jamie Madilla4595b82017-01-11 17:36:34 -0500875 if (drawStates[index] != GL_NONE && mState.mColorAttachments[index].isAttached())
876 {
877 mState.mEnabledDrawBuffers.set(index);
878 }
879 }
Geoff Lang9dd95802014-12-01 11:12:59 -0500880}
881
Geoff Langa15472a2015-08-11 11:48:03 -0400882const FramebufferAttachment *Framebuffer::getDrawBuffer(size_t drawBuffer) const
883{
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400884 return mState.getDrawBuffer(drawBuffer);
Geoff Langa15472a2015-08-11 11:48:03 -0400885}
886
Geoff Lange0cff192017-05-30 13:04:56 -0400887GLenum Framebuffer::getDrawbufferWriteType(size_t drawBuffer) const
888{
889 const FramebufferAttachment *attachment = mState.getDrawBuffer(drawBuffer);
890 if (attachment == nullptr)
891 {
892 return GL_NONE;
893 }
894
895 GLenum componentType = attachment->getFormat().info->componentType;
896 switch (componentType)
897 {
898 case GL_INT:
899 case GL_UNSIGNED_INT:
900 return componentType;
901
902 default:
903 return GL_FLOAT;
904 }
905}
906
Brandon Jonesc405ae72017-12-06 14:15:03 -0800907ComponentTypeMask Framebuffer::getDrawBufferTypeMask() const
Brandon Jones76746f92017-11-22 11:44:41 -0800908{
909 return mState.mDrawBufferTypeMask;
910}
911
912DrawBufferMask Framebuffer::getDrawBufferMask() const
913{
914 return mState.mEnabledDrawBuffers;
915}
916
Geoff Langa15472a2015-08-11 11:48:03 -0400917bool Framebuffer::hasEnabledDrawBuffer() const
918{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400919 for (size_t drawbufferIdx = 0; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
Geoff Langa15472a2015-08-11 11:48:03 -0400920 {
921 if (getDrawBuffer(drawbufferIdx) != nullptr)
922 {
923 return true;
924 }
925 }
926
927 return false;
928}
929
Geoff Lang9dd95802014-12-01 11:12:59 -0500930GLenum Framebuffer::getReadBufferState() const
931{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400932 return mState.mReadBufferState;
Geoff Lang9dd95802014-12-01 11:12:59 -0500933}
934
935void Framebuffer::setReadBuffer(GLenum buffer)
936{
Jamie Madillb885e572015-02-03 16:16:04 -0500937 ASSERT(buffer == GL_BACK || buffer == GL_NONE ||
938 (buffer >= GL_COLOR_ATTACHMENT0 &&
Jamie Madill48ef11b2016-04-27 15:21:52 -0400939 (buffer - GL_COLOR_ATTACHMENT0) < mState.mColorAttachments.size()));
940 mState.mReadBufferState = buffer;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500941 mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000942}
943
Corentin Wallez37c39792015-08-20 14:19:46 -0400944size_t Framebuffer::getNumColorBuffers() const
945{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400946 return mState.mColorAttachments.size();
Corentin Wallez37c39792015-08-20 14:19:46 -0400947}
948
Jamie Madill0df8fe42015-11-24 16:10:24 -0500949bool Framebuffer::hasDepth() const
950{
Jamie Madill9c335862017-07-18 11:51:38 -0400951 return mState.hasDepth();
Jamie Madill0df8fe42015-11-24 16:10:24 -0500952}
953
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000954bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000955{
Jamie Madill9c335862017-07-18 11:51:38 -0400956 return mState.hasStencil();
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000957}
958
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000959bool Framebuffer::usingExtendedDrawBuffers() const
960{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400961 for (size_t drawbufferIdx = 1; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000962 {
Geoff Langa15472a2015-08-11 11:48:03 -0400963 if (getDrawBuffer(drawbufferIdx) != nullptr)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000964 {
965 return true;
966 }
967 }
968
969 return false;
970}
971
Geoff Lang9aded172017-04-05 11:07:56 -0400972void Framebuffer::invalidateCompletenessCache()
973{
Jamie Madill2274b652018-05-31 10:56:08 -0400974 if (mState.mId != 0)
Geoff Lang9aded172017-04-05 11:07:56 -0400975 {
976 mCachedStatus.reset();
977 }
978}
979
Jamie Madill427064d2018-04-13 16:20:34 -0400980GLenum Framebuffer::checkStatus(const Context *context)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000981{
Corentin Wallezccab69d2017-01-27 16:57:15 -0500982 // The default framebuffer is always complete except when it is surfaceless in which
983 // case it is always unsupported. We return early because the default framebuffer may
984 // not be subject to the same rules as application FBOs. ie, it could have 0x0 size.
Jamie Madill2274b652018-05-31 10:56:08 -0400985 if (mState.mId == 0)
Geoff Lang528ce3c2014-12-01 10:44:07 -0500986 {
Corentin Wallezccab69d2017-01-27 16:57:15 -0500987 ASSERT(mCachedStatus.valid());
988 ASSERT(mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE ||
989 mCachedStatus.value() == GL_FRAMEBUFFER_UNDEFINED_OES);
Jamie Madill427064d2018-04-13 16:20:34 -0400990 return mCachedStatus.value();
Geoff Lang528ce3c2014-12-01 10:44:07 -0500991 }
992
Jamie Madill362876b2016-06-16 14:46:59 -0400993 if (hasAnyDirtyBit() || !mCachedStatus.valid())
994 {
Jamie Madille98b1b52018-03-08 09:47:23 -0500995 mCachedStatus = checkStatusWithGLFrontEnd(context);
996
997 if (mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE)
998 {
Jamie Madill427064d2018-04-13 16:20:34 -0400999 Error err = syncState(context);
1000 if (err.isError())
1001 {
1002 context->handleError(err);
1003 return GetDefaultReturnValue<EntryPoint::CheckFramebufferStatus, GLenum>();
1004 }
Jamie Madille98b1b52018-03-08 09:47:23 -05001005 if (!mImpl->checkStatus(context))
1006 {
1007 mCachedStatus = GL_FRAMEBUFFER_UNSUPPORTED;
1008 }
1009 }
Jamie Madill362876b2016-06-16 14:46:59 -04001010 }
1011
Jamie Madill427064d2018-04-13 16:20:34 -04001012 return mCachedStatus.value();
Jamie Madill362876b2016-06-16 14:46:59 -04001013}
1014
Jamie Madille98b1b52018-03-08 09:47:23 -05001015GLenum Framebuffer::checkStatusWithGLFrontEnd(const Context *context)
Jamie Madill362876b2016-06-16 14:46:59 -04001016{
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001017 const ContextState &state = context->getContextState();
1018
Jamie Madill2274b652018-05-31 10:56:08 -04001019 ASSERT(mState.mId != 0);
Jamie Madill362876b2016-06-16 14:46:59 -04001020
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001021 bool hasAttachments = false;
1022 Optional<unsigned int> colorbufferSize;
1023 Optional<int> samples;
Geoff Lang92019432017-11-20 13:09:34 -05001024 Optional<bool> fixedSampleLocations;
JiangYizhou461d9a32017-01-04 16:37:26 +08001025 bool hasRenderbuffer = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001026
Martin Radev9bc9a322017-07-21 14:28:17 +03001027 const FramebufferAttachment *firstAttachment = getFirstNonNullAttachment();
1028
Jamie Madill48ef11b2016-04-27 15:21:52 -04001029 for (const FramebufferAttachment &colorAttachment : mState.mColorAttachments)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001030 {
Jamie Madill2d06b732015-04-20 12:53:28 -04001031 if (colorAttachment.isAttached())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001032 {
Geoff Lang9f10b772017-05-16 15:51:03 -04001033 if (!CheckAttachmentCompleteness(context, colorAttachment))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001034 {
1035 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1036 }
daniel@transgaming.com01868132010-08-24 19:21:17 +00001037
Geoff Lang677bb6f2017-04-05 12:40:40 -04001038 const InternalFormat &format = *colorAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -04001039 if (format.depthBits > 0 || format.stencilBits > 0)
1040 {
1041 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1042 }
1043
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001044 if (!CheckAttachmentSampleCompleteness(context, colorAttachment, true, &samples,
1045 &fixedSampleLocations))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001046 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001047 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001048 }
1049
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001050 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
1051 // in GLES 3.0, there is no such restriction
1052 if (state.getClientMajorVersion() < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001053 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001054 if (colorbufferSize.valid())
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001055 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001056 if (format.pixelBytes != colorbufferSize.value())
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +00001057 {
1058 return GL_FRAMEBUFFER_UNSUPPORTED;
1059 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001060 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001061 else
1062 {
1063 colorbufferSize = format.pixelBytes;
1064 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001065 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001066
Martin Radev9bc9a322017-07-21 14:28:17 +03001067 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &colorAttachment))
1068 {
1069 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
1070 }
1071
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001072 hasRenderbuffer = hasRenderbuffer || (colorAttachment.type() == GL_RENDERBUFFER);
1073 hasAttachments = true;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001074 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001075 }
1076
Jamie Madill48ef11b2016-04-27 15:21:52 -04001077 const FramebufferAttachment &depthAttachment = mState.mDepthAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -04001078 if (depthAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001079 {
Geoff Lang9f10b772017-05-16 15:51:03 -04001080 if (!CheckAttachmentCompleteness(context, depthAttachment))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001081 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001082 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001083 }
1084
Geoff Lang677bb6f2017-04-05 12:40:40 -04001085 const InternalFormat &format = *depthAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -04001086 if (format.depthBits == 0)
1087 {
1088 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001089 }
1090
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001091 if (!CheckAttachmentSampleCompleteness(context, depthAttachment, false, &samples,
1092 &fixedSampleLocations))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001093 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001094 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001095 }
Sami Väisänena797e062016-05-12 15:23:40 +03001096
Martin Radev9bc9a322017-07-21 14:28:17 +03001097 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &depthAttachment))
1098 {
1099 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
1100 }
1101
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001102 hasRenderbuffer = hasRenderbuffer || (depthAttachment.type() == GL_RENDERBUFFER);
1103 hasAttachments = true;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001104 }
1105
Jamie Madill48ef11b2016-04-27 15:21:52 -04001106 const FramebufferAttachment &stencilAttachment = mState.mStencilAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -04001107 if (stencilAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001108 {
Geoff Lang9f10b772017-05-16 15:51:03 -04001109 if (!CheckAttachmentCompleteness(context, stencilAttachment))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001110 {
1111 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1112 }
1113
Geoff Lang677bb6f2017-04-05 12:40:40 -04001114 const InternalFormat &format = *stencilAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -04001115 if (format.stencilBits == 0)
1116 {
1117 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001118 }
1119
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001120 if (!CheckAttachmentSampleCompleteness(context, stencilAttachment, false, &samples,
1121 &fixedSampleLocations))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001122 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001123 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001124 }
Corentin Wallez086d59a2016-04-29 09:06:49 -04001125
Martin Radev9bc9a322017-07-21 14:28:17 +03001126 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &stencilAttachment))
1127 {
1128 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
1129 }
1130
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001131 hasRenderbuffer = hasRenderbuffer || (stencilAttachment.type() == GL_RENDERBUFFER);
1132 hasAttachments = true;
1133 }
1134
1135 // Starting from ES 3.0 stencil and depth, if present, should be the same image
1136 if (state.getClientMajorVersion() >= 3 && depthAttachment.isAttached() &&
1137 stencilAttachment.isAttached() && stencilAttachment != depthAttachment)
1138 {
1139 return GL_FRAMEBUFFER_UNSUPPORTED;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001140 }
1141
Jamie Madilla02315b2017-02-23 14:14:47 -05001142 // Special additional validation for WebGL 1 DEPTH/STENCIL/DEPTH_STENCIL.
1143 if (state.isWebGL1())
1144 {
1145 if (!mState.mWebGLDepthStencilConsistent)
1146 {
1147 return GL_FRAMEBUFFER_UNSUPPORTED;
1148 }
1149
1150 if (mState.mWebGLDepthStencilAttachment.isAttached())
1151 {
1152 if (mState.mWebGLDepthStencilAttachment.getDepthSize() == 0 ||
1153 mState.mWebGLDepthStencilAttachment.getStencilSize() == 0)
1154 {
1155 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1156 }
Martin Radev9bc9a322017-07-21 14:28:17 +03001157
1158 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment,
1159 &mState.mWebGLDepthStencilAttachment))
1160 {
1161 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
1162 }
Jamie Madilla02315b2017-02-23 14:14:47 -05001163 }
1164 else if (mState.mStencilAttachment.isAttached() &&
1165 mState.mStencilAttachment.getDepthSize() > 0)
1166 {
1167 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1168 }
1169 else if (mState.mDepthAttachment.isAttached() &&
1170 mState.mDepthAttachment.getStencilSize() > 0)
1171 {
1172 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1173 }
1174 }
1175
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001176 // ES3.1(section 9.4) requires that if no image is attached to the framebuffer, and either the
1177 // value of the framebuffer's FRAMEBUFFER_DEFAULT_WIDTH or FRAMEBUFFER_DEFAULT_HEIGHT parameters
1178 // is zero, the framebuffer is considered incomplete.
JiangYizhou461d9a32017-01-04 16:37:26 +08001179 GLint defaultWidth = mState.getDefaultWidth();
1180 GLint defaultHeight = mState.getDefaultHeight();
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001181 if (!hasAttachments && (defaultWidth == 0 || defaultHeight == 0))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001182 {
1183 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001184 }
1185
Geoff Langa0e0aeb2017-04-12 15:06:29 -04001186 // In ES 2.0 and WebGL, all color attachments must have the same width and height.
Jamie Madillcc86d642015-11-24 13:00:07 -05001187 // In ES 3.0, there is no such restriction.
Geoff Langa0e0aeb2017-04-12 15:06:29 -04001188 if ((state.getClientMajorVersion() < 3 || state.getExtensions().webglCompatibility) &&
1189 !mState.attachmentsHaveSameDimensions())
Jamie Madillcc86d642015-11-24 13:00:07 -05001190 {
1191 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
1192 }
1193
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001194 // ES3.1(section 9.4) requires that if the attached images are a mix of renderbuffers and
1195 // textures, the value of TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all attached textures.
JiangYizhou461d9a32017-01-04 16:37:26 +08001196 if (fixedSampleLocations.valid() && hasRenderbuffer && !fixedSampleLocations.value())
1197 {
1198 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1199 }
1200
Kenneth Russellce8602a2017-10-03 18:23:08 -07001201 // The WebGL conformance tests implicitly define that all framebuffer
1202 // attachments must be unique. For example, the same level of a texture can
1203 // not be attached to two different color attachments.
1204 if (state.getExtensions().webglCompatibility)
1205 {
1206 if (!mState.colorAttachmentsAreUniqueImages())
1207 {
1208 return GL_FRAMEBUFFER_UNSUPPORTED;
1209 }
1210 }
1211
Jamie Madillcc86d642015-11-24 13:00:07 -05001212 return GL_FRAMEBUFFER_COMPLETE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001213}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001214
Jamie Madill4928b7c2017-06-20 12:57:39 -04001215Error Framebuffer::discard(const Context *context, size_t count, const GLenum *attachments)
Austin Kinross08332632015-05-05 13:35:47 -07001216{
Jamie Madill05b35b22017-10-03 09:01:44 -04001217 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1218 // can be no-ops, so we should probably do that to ensure consistency.
1219 // TODO(jmadill): WebGL behaviour, and robust resource init behaviour without WebGL.
1220
Jamie Madill4928b7c2017-06-20 12:57:39 -04001221 return mImpl->discard(context, count, attachments);
Austin Kinross08332632015-05-05 13:35:47 -07001222}
1223
Jamie Madill4928b7c2017-06-20 12:57:39 -04001224Error Framebuffer::invalidate(const Context *context, size_t count, const GLenum *attachments)
Jamie Madill2d96b9e2014-08-29 15:46:47 -04001225{
Jamie Madill05b35b22017-10-03 09:01:44 -04001226 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1227 // can be no-ops, so we should probably do that to ensure consistency.
1228 // TODO(jmadill): WebGL behaviour, and robust resource init behaviour without WebGL.
1229
Jamie Madill4928b7c2017-06-20 12:57:39 -04001230 return mImpl->invalidate(context, count, attachments);
Jamie Madill2d96b9e2014-08-29 15:46:47 -04001231}
1232
Jamie Madill05b35b22017-10-03 09:01:44 -04001233bool Framebuffer::partialClearNeedsInit(const Context *context,
1234 bool color,
1235 bool depth,
1236 bool stencil)
1237{
1238 const auto &glState = context->getGLState();
1239
1240 if (!glState.isRobustResourceInitEnabled())
1241 {
1242 return false;
1243 }
1244
1245 // Scissors can affect clearing.
1246 // TODO(jmadill): Check for complete scissor overlap.
1247 if (glState.isScissorTestEnabled())
1248 {
1249 return true;
1250 }
1251
1252 // If colors masked, we must clear before we clear. Do a simple check.
1253 // TODO(jmadill): Filter out unused color channels from the test.
1254 if (color)
1255 {
1256 const auto &blend = glState.getBlendState();
1257 if (!(blend.colorMaskRed && blend.colorMaskGreen && blend.colorMaskBlue &&
1258 blend.colorMaskAlpha))
1259 {
1260 return true;
1261 }
1262 }
1263
1264 const auto &depthStencil = glState.getDepthStencilState();
1265 ASSERT(depthStencil.stencilBackMask == depthStencil.stencilMask);
1266 if (stencil && depthStencil.stencilMask != depthStencil.stencilWritemask)
1267 {
1268 return true;
1269 }
1270
1271 return false;
1272}
1273
Jamie Madill4928b7c2017-06-20 12:57:39 -04001274Error Framebuffer::invalidateSub(const Context *context,
1275 size_t count,
1276 const GLenum *attachments,
Jamie Madilld4442552018-02-27 22:03:47 -05001277 const Rectangle &area)
Jamie Madill400a4412014-08-29 15:46:45 -04001278{
Jamie Madill05b35b22017-10-03 09:01:44 -04001279 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1280 // can be no-ops, so we should probably do that to ensure consistency.
1281 // TODO(jmadill): Make a invalidate no-op in WebGL 2.0.
1282
Jamie Madill4928b7c2017-06-20 12:57:39 -04001283 return mImpl->invalidateSub(context, count, attachments, area);
Jamie Madill400a4412014-08-29 15:46:45 -04001284}
1285
Jamie Madilld4442552018-02-27 22:03:47 -05001286Error Framebuffer::clear(const Context *context, GLbitfield mask)
Geoff Langb04dc822014-12-01 12:02:02 -05001287{
Jamie Madill05b35b22017-10-03 09:01:44 -04001288 const auto &glState = context->getGLState();
1289 if (glState.isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -05001290 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001291 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001292 }
1293
Jamie Madill05b35b22017-10-03 09:01:44 -04001294 ANGLE_TRY(mImpl->clear(context, mask));
1295
Jamie Madill05b35b22017-10-03 09:01:44 -04001296 return NoError();
Geoff Langb04dc822014-12-01 12:02:02 -05001297}
1298
Jamie Madilld4442552018-02-27 22:03:47 -05001299Error Framebuffer::clearBufferfv(const Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001300 GLenum buffer,
1301 GLint drawbuffer,
1302 const GLfloat *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001303{
Jamie Madill05b35b22017-10-03 09:01:44 -04001304 if (context->getGLState().isRasterizerDiscardEnabled() ||
1305 IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001306 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001307 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001308 }
1309
Jamie Madill05b35b22017-10-03 09:01:44 -04001310 ANGLE_TRY(mImpl->clearBufferfv(context, buffer, drawbuffer, values));
1311
Jamie Madill05b35b22017-10-03 09:01:44 -04001312 return NoError();
Geoff Langb04dc822014-12-01 12:02:02 -05001313}
1314
Jamie Madilld4442552018-02-27 22:03:47 -05001315Error Framebuffer::clearBufferuiv(const Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001316 GLenum buffer,
1317 GLint drawbuffer,
1318 const GLuint *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001319{
Jamie Madill05b35b22017-10-03 09:01:44 -04001320 if (context->getGLState().isRasterizerDiscardEnabled() ||
1321 IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001322 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001323 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001324 }
1325
Jamie Madill05b35b22017-10-03 09:01:44 -04001326 ANGLE_TRY(mImpl->clearBufferuiv(context, buffer, drawbuffer, values));
1327
Jamie Madill05b35b22017-10-03 09:01:44 -04001328 return NoError();
Geoff Langb04dc822014-12-01 12:02:02 -05001329}
1330
Jamie Madilld4442552018-02-27 22:03:47 -05001331Error Framebuffer::clearBufferiv(const Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001332 GLenum buffer,
1333 GLint drawbuffer,
1334 const GLint *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001335{
Jamie Madill05b35b22017-10-03 09:01:44 -04001336 if (context->getGLState().isRasterizerDiscardEnabled() ||
1337 IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001338 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001339 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001340 }
1341
Jamie Madill05b35b22017-10-03 09:01:44 -04001342 ANGLE_TRY(mImpl->clearBufferiv(context, buffer, drawbuffer, values));
1343
Jamie Madill05b35b22017-10-03 09:01:44 -04001344 return NoError();
Geoff Langb04dc822014-12-01 12:02:02 -05001345}
1346
Jamie Madilld4442552018-02-27 22:03:47 -05001347Error Framebuffer::clearBufferfi(const Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001348 GLenum buffer,
1349 GLint drawbuffer,
1350 GLfloat depth,
1351 GLint stencil)
Geoff Langb04dc822014-12-01 12:02:02 -05001352{
Jamie Madill05b35b22017-10-03 09:01:44 -04001353 if (context->getGLState().isRasterizerDiscardEnabled() ||
1354 IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001355 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001356 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001357 }
1358
Jamie Madill05b35b22017-10-03 09:01:44 -04001359 ANGLE_TRY(mImpl->clearBufferfi(context, buffer, drawbuffer, depth, stencil));
1360
Jamie Madill05b35b22017-10-03 09:01:44 -04001361 return NoError();
Geoff Langb04dc822014-12-01 12:02:02 -05001362}
1363
Jamie Madill690c8eb2018-03-12 15:20:03 -04001364Error Framebuffer::getImplementationColorReadFormat(const Context *context, GLenum *formatOut)
Geoff Langbce529e2014-12-01 12:48:41 -05001365{
Jamie Madill690c8eb2018-03-12 15:20:03 -04001366 ANGLE_TRY(syncState(context));
1367 *formatOut = mImpl->getImplementationColorReadFormat(context);
1368 return NoError();
Geoff Langbce529e2014-12-01 12:48:41 -05001369}
1370
Jamie Madill690c8eb2018-03-12 15:20:03 -04001371Error Framebuffer::getImplementationColorReadType(const Context *context, GLenum *typeOut)
Geoff Langbce529e2014-12-01 12:48:41 -05001372{
Jamie Madill690c8eb2018-03-12 15:20:03 -04001373 ANGLE_TRY(syncState(context));
1374 *typeOut = mImpl->getImplementationColorReadType(context);
1375 return NoError();
Geoff Langbce529e2014-12-01 12:48:41 -05001376}
1377
Jamie Madilld4442552018-02-27 22:03:47 -05001378Error Framebuffer::readPixels(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001379 const Rectangle &area,
Jamie Madill1b94d432015-08-07 13:23:23 -04001380 GLenum format,
1381 GLenum type,
Jamie Madill05b35b22017-10-03 09:01:44 -04001382 void *pixels)
Geoff Langbce529e2014-12-01 12:48:41 -05001383{
Jamie Madill05b35b22017-10-03 09:01:44 -04001384 ANGLE_TRY(ensureReadAttachmentInitialized(context, GL_COLOR_BUFFER_BIT));
Jamie Madill362876b2016-06-16 14:46:59 -04001385 ANGLE_TRY(mImpl->readPixels(context, area, format, type, pixels));
Geoff Lang520c4ae2015-05-05 13:12:36 -04001386
Jamie Madilld4442552018-02-27 22:03:47 -05001387 Buffer *unpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Lang520c4ae2015-05-05 13:12:36 -04001388 if (unpackBuffer)
1389 {
Jamie Madill09463932018-04-04 05:26:59 -04001390 unpackBuffer->onPixelPack(context);
Geoff Lang520c4ae2015-05-05 13:12:36 -04001391 }
1392
Jamie Madill362876b2016-06-16 14:46:59 -04001393 return NoError();
Geoff Langbce529e2014-12-01 12:48:41 -05001394}
1395
Jamie Madilld4442552018-02-27 22:03:47 -05001396Error Framebuffer::blit(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001397 const Rectangle &sourceArea,
1398 const Rectangle &destArea,
Geoff Lang242468f2015-09-24 14:15:41 -04001399 GLbitfield mask,
Jamie Madill8415b5f2016-04-26 13:41:39 -04001400 GLenum filter)
Geoff Lang54bd5a42014-12-01 12:51:04 -05001401{
He Yunchao6be602d2016-12-22 14:33:07 +08001402 GLbitfield blitMask = mask;
1403
1404 // Note that blitting is called against draw framebuffer.
1405 // See the code in gl::Context::blitFramebuffer.
1406 if ((mask & GL_COLOR_BUFFER_BIT) && !hasEnabledDrawBuffer())
1407 {
1408 blitMask &= ~GL_COLOR_BUFFER_BIT;
1409 }
1410
1411 if ((mask & GL_STENCIL_BUFFER_BIT) && mState.getStencilAttachment() == nullptr)
1412 {
1413 blitMask &= ~GL_STENCIL_BUFFER_BIT;
1414 }
1415
1416 if ((mask & GL_DEPTH_BUFFER_BIT) && mState.getDepthAttachment() == nullptr)
1417 {
1418 blitMask &= ~GL_DEPTH_BUFFER_BIT;
1419 }
1420
1421 if (!blitMask)
1422 {
1423 return NoError();
1424 }
1425
Jamie Madill05b35b22017-10-03 09:01:44 -04001426 auto *sourceFBO = context->getGLState().getReadFramebuffer();
1427 ANGLE_TRY(sourceFBO->ensureReadAttachmentInitialized(context, blitMask));
1428
1429 // TODO(jmadill): Only clear if not the full FBO dimensions, and only specified bitmask.
1430 ANGLE_TRY(ensureDrawAttachmentsInitialized(context));
1431
He Yunchao6be602d2016-12-22 14:33:07 +08001432 return mImpl->blit(context, sourceArea, destArea, blitMask, filter);
Geoff Lang54bd5a42014-12-01 12:51:04 -05001433}
1434
Jamie Madill427064d2018-04-13 16:20:34 -04001435int Framebuffer::getSamples(const Context *context)
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001436{
Jamie Madill427064d2018-04-13 16:20:34 -04001437 return (isComplete(context) ? getCachedSamples(context) : 0);
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001438}
1439
Jamie Madill9c335862017-07-18 11:51:38 -04001440int Framebuffer::getCachedSamples(const Context *context)
1441{
Jamie Madill5b772312018-03-08 20:28:32 -05001442 ASSERT(mCachedStatus.valid() && mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE);
1443
Jamie Madill9c335862017-07-18 11:51:38 -04001444 // For a complete framebuffer, all attachments must have the same sample count.
1445 // In this case return the first nonzero sample size.
1446 const auto *firstNonNullAttachment = mState.getFirstNonNullAttachment();
1447 if (firstNonNullAttachment)
1448 {
1449 ASSERT(firstNonNullAttachment->isAttached());
1450 return firstNonNullAttachment->getSamples();
1451 }
1452
1453 // No attachments found.
1454 return 0;
1455}
1456
Geoff Lang13455072018-05-09 11:24:43 -04001457Error Framebuffer::getSamplePosition(const Context *context, size_t index, GLfloat *xy) const
Corentin Wallezccab69d2017-01-27 16:57:15 -05001458{
Geoff Lang13455072018-05-09 11:24:43 -04001459 ANGLE_TRY(mImpl->getSamplePosition(context, index, xy));
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001460 return NoError();
Corentin Wallezccab69d2017-01-27 16:57:15 -05001461}
1462
Jamie Madille261b442014-06-25 12:42:21 -04001463bool Framebuffer::hasValidDepthStencil() const
1464{
Jamie Madill48ef11b2016-04-27 15:21:52 -04001465 return mState.getDepthStencilAttachment() != nullptr;
Jamie Madille261b442014-06-25 12:42:21 -04001466}
1467
Jamie Madilla02315b2017-02-23 14:14:47 -05001468void Framebuffer::setAttachment(const Context *context,
1469 GLenum type,
Jamie Madill2d06b732015-04-20 12:53:28 -04001470 GLenum binding,
1471 const ImageIndex &textureIndex,
1472 FramebufferAttachmentObject *resource)
Geoff Langab75a052014-10-15 12:56:37 -04001473{
Martin Radev5dae57b2017-07-14 16:15:55 +03001474 setAttachment(context, type, binding, textureIndex, resource,
1475 FramebufferAttachment::kDefaultNumViews,
1476 FramebufferAttachment::kDefaultBaseViewIndex,
1477 FramebufferAttachment::kDefaultMultiviewLayout,
1478 FramebufferAttachment::kDefaultViewportOffsets);
1479}
1480
1481void Framebuffer::setAttachment(const Context *context,
1482 GLenum type,
1483 GLenum binding,
1484 const ImageIndex &textureIndex,
1485 FramebufferAttachmentObject *resource,
1486 GLsizei numViews,
1487 GLuint baseViewIndex,
1488 GLenum multiviewLayout,
1489 const GLint *viewportOffsets)
1490{
Jamie Madilla02315b2017-02-23 14:14:47 -05001491 // Context may be null in unit tests.
1492 if (!context || !context->isWebGL1())
1493 {
Martin Radev5dae57b2017-07-14 16:15:55 +03001494 setAttachmentImpl(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
1495 multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001496 return;
1497 }
1498
1499 switch (binding)
1500 {
1501 case GL_DEPTH_STENCIL:
1502 case GL_DEPTH_STENCIL_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001503 mState.mWebGLDepthStencilAttachment.attach(context, type, binding, textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001504 resource, numViews, baseViewIndex,
1505 multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001506 break;
1507 case GL_DEPTH:
1508 case GL_DEPTH_ATTACHMENT:
Martin Radev5dae57b2017-07-14 16:15:55 +03001509 mState.mWebGLDepthAttachment.attach(context, type, binding, textureIndex, resource,
1510 numViews, baseViewIndex, multiviewLayout,
1511 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001512 break;
1513 case GL_STENCIL:
1514 case GL_STENCIL_ATTACHMENT:
Martin Radev5dae57b2017-07-14 16:15:55 +03001515 mState.mWebGLStencilAttachment.attach(context, type, binding, textureIndex, resource,
1516 numViews, baseViewIndex, multiviewLayout,
1517 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001518 break;
1519 default:
Martin Radev5dae57b2017-07-14 16:15:55 +03001520 setAttachmentImpl(context, type, binding, textureIndex, resource, numViews,
1521 baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001522 return;
1523 }
1524
Martin Radev5dae57b2017-07-14 16:15:55 +03001525 commitWebGL1DepthStencilIfConsistent(context, numViews, baseViewIndex, multiviewLayout,
1526 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001527}
1528
Martin Radev82ef7742017-08-08 17:44:58 +03001529void Framebuffer::setAttachmentMultiviewLayered(const Context *context,
1530 GLenum type,
1531 GLenum binding,
1532 const ImageIndex &textureIndex,
1533 FramebufferAttachmentObject *resource,
1534 GLsizei numViews,
1535 GLint baseViewIndex)
1536{
1537 setAttachment(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
1538 GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE,
1539 FramebufferAttachment::kDefaultViewportOffsets);
1540}
1541
Martin Radev5dae57b2017-07-14 16:15:55 +03001542void Framebuffer::setAttachmentMultiviewSideBySide(const Context *context,
1543 GLenum type,
1544 GLenum binding,
1545 const ImageIndex &textureIndex,
1546 FramebufferAttachmentObject *resource,
1547 GLsizei numViews,
1548 const GLint *viewportOffsets)
1549{
1550 setAttachment(context, type, binding, textureIndex, resource, numViews,
1551 FramebufferAttachment::kDefaultBaseViewIndex,
1552 GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, viewportOffsets);
1553}
1554
1555void Framebuffer::commitWebGL1DepthStencilIfConsistent(const Context *context,
1556 GLsizei numViews,
1557 GLuint baseViewIndex,
1558 GLenum multiviewLayout,
1559 const GLint *viewportOffsets)
Jamie Madilla02315b2017-02-23 14:14:47 -05001560{
1561 int count = 0;
1562
1563 std::array<FramebufferAttachment *, 3> attachments = {{&mState.mWebGLDepthStencilAttachment,
1564 &mState.mWebGLDepthAttachment,
1565 &mState.mWebGLStencilAttachment}};
1566 for (FramebufferAttachment *attachment : attachments)
1567 {
1568 if (attachment->isAttached())
1569 {
1570 count++;
1571 }
1572 }
1573
1574 mState.mWebGLDepthStencilConsistent = (count <= 1);
1575 if (!mState.mWebGLDepthStencilConsistent)
1576 {
1577 // Inconsistent.
1578 return;
1579 }
1580
Geoff Lange466c552017-03-17 15:24:12 -04001581 auto getImageIndexIfTextureAttachment = [](const FramebufferAttachment &attachment) {
1582 if (attachment.type() == GL_TEXTURE)
1583 {
1584 return attachment.getTextureImageIndex();
1585 }
1586 else
1587 {
Jamie Madillcc129372018-04-12 09:13:18 -04001588 return ImageIndex();
Geoff Lange466c552017-03-17 15:24:12 -04001589 }
1590 };
1591
Jamie Madilla02315b2017-02-23 14:14:47 -05001592 if (mState.mWebGLDepthAttachment.isAttached())
1593 {
1594 const auto &depth = mState.mWebGLDepthAttachment;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001595 setAttachmentImpl(context, depth.type(), GL_DEPTH_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001596 getImageIndexIfTextureAttachment(depth), depth.getResource(), numViews,
1597 baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madillcc129372018-04-12 09:13:18 -04001598 setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex(), nullptr, numViews,
1599 baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001600 }
1601 else if (mState.mWebGLStencilAttachment.isAttached())
1602 {
1603 const auto &stencil = mState.mWebGLStencilAttachment;
Jamie Madillcc129372018-04-12 09:13:18 -04001604 setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex(), nullptr, numViews,
1605 baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001606 setAttachmentImpl(context, stencil.type(), GL_STENCIL_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001607 getImageIndexIfTextureAttachment(stencil), stencil.getResource(),
1608 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001609 }
1610 else if (mState.mWebGLDepthStencilAttachment.isAttached())
1611 {
1612 const auto &depthStencil = mState.mWebGLDepthStencilAttachment;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001613 setAttachmentImpl(context, depthStencil.type(), GL_DEPTH_ATTACHMENT,
Geoff Lange466c552017-03-17 15:24:12 -04001614 getImageIndexIfTextureAttachment(depthStencil),
Martin Radev5dae57b2017-07-14 16:15:55 +03001615 depthStencil.getResource(), numViews, baseViewIndex, multiviewLayout,
1616 viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001617 setAttachmentImpl(context, depthStencil.type(), GL_STENCIL_ATTACHMENT,
Geoff Lange466c552017-03-17 15:24:12 -04001618 getImageIndexIfTextureAttachment(depthStencil),
Martin Radev5dae57b2017-07-14 16:15:55 +03001619 depthStencil.getResource(), numViews, baseViewIndex, multiviewLayout,
1620 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001621 }
1622 else
1623 {
Jamie Madillcc129372018-04-12 09:13:18 -04001624 setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex(), nullptr, numViews,
1625 baseViewIndex, multiviewLayout, viewportOffsets);
1626 setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex(), nullptr, numViews,
1627 baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001628 }
1629}
1630
Jamie Madill4928b7c2017-06-20 12:57:39 -04001631void Framebuffer::setAttachmentImpl(const Context *context,
1632 GLenum type,
Jamie Madilla02315b2017-02-23 14:14:47 -05001633 GLenum binding,
1634 const ImageIndex &textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001635 FramebufferAttachmentObject *resource,
1636 GLsizei numViews,
1637 GLuint baseViewIndex,
1638 GLenum multiviewLayout,
1639 const GLint *viewportOffsets)
Jamie Madilla02315b2017-02-23 14:14:47 -05001640{
Jamie Madilla02315b2017-02-23 14:14:47 -05001641 switch (binding)
1642 {
Jamie Madillb8126692017-04-05 11:22:17 -04001643 case GL_DEPTH_STENCIL:
1644 case GL_DEPTH_STENCIL_ATTACHMENT:
1645 {
1646 // ensure this is a legitimate depth+stencil format
1647 FramebufferAttachmentObject *attachmentObj = resource;
1648 if (resource)
1649 {
Jamie Madill4fd95d52017-04-05 11:22:18 -04001650 const Format &format = resource->getAttachmentFormat(binding, textureIndex);
Jamie Madillb8126692017-04-05 11:22:17 -04001651 if (format.info->depthBits == 0 || format.info->stencilBits == 0)
1652 {
1653 // Attaching nullptr detaches the current attachment.
1654 attachmentObj = nullptr;
1655 }
1656 }
1657
Jamie Madill4928b7c2017-06-20 12:57:39 -04001658 updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
Jamie Madillb8126692017-04-05 11:22:17 -04001659 &mDirtyDepthAttachmentBinding, type, binding, textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001660 attachmentObj, numViews, baseViewIndex, multiviewLayout,
1661 viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001662 updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
Jamie Madillb8126692017-04-05 11:22:17 -04001663 &mDirtyStencilAttachmentBinding, type, binding, textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001664 attachmentObj, numViews, baseViewIndex, multiviewLayout,
1665 viewportOffsets);
Jamie Madill42975642017-10-12 12:31:51 -04001666 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001667 }
1668
Jamie Madilla02315b2017-02-23 14:14:47 -05001669 case GL_DEPTH:
1670 case GL_DEPTH_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001671 updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001672 &mDirtyDepthAttachmentBinding, type, binding, textureIndex, resource,
1673 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madill2d06b732015-04-20 12:53:28 -04001674 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001675
Jamie Madilla02315b2017-02-23 14:14:47 -05001676 case GL_STENCIL:
1677 case GL_STENCIL_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001678 updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001679 &mDirtyStencilAttachmentBinding, type, binding, textureIndex, resource,
1680 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001681 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001682
Jamie Madilla02315b2017-02-23 14:14:47 -05001683 case GL_BACK:
Geoff Lang8170eab2017-09-21 13:59:04 -04001684 updateAttachment(context, &mState.mColorAttachments[0], DIRTY_BIT_COLOR_ATTACHMENT_0,
1685 &mDirtyColorAttachmentBindings[0], type, binding, textureIndex,
1686 resource, numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001687 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001688
Jamie Madilla02315b2017-02-23 14:14:47 -05001689 default:
1690 {
1691 size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
1692 ASSERT(colorIndex < mState.mColorAttachments.size());
Jamie Madillb8126692017-04-05 11:22:17 -04001693 size_t dirtyBit = DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001694 updateAttachment(context, &mState.mColorAttachments[colorIndex], dirtyBit,
Jamie Madillb8126692017-04-05 11:22:17 -04001695 &mDirtyColorAttachmentBindings[colorIndex], type, binding,
Martin Radev5dae57b2017-07-14 16:15:55 +03001696 textureIndex, resource, numViews, baseViewIndex, multiviewLayout,
1697 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001698
Corentin Walleze7557742017-06-01 13:09:57 -04001699 // TODO(jmadill): ASSERT instead of checking the attachment exists in
1700 // formsRenderingFeedbackLoopWith
Jamie Madilla02315b2017-02-23 14:14:47 -05001701 bool enabled = (type != GL_NONE && getDrawBufferState(colorIndex) != GL_NONE);
1702 mState.mEnabledDrawBuffers.set(colorIndex, enabled);
Brandon Jones76746f92017-11-22 11:44:41 -08001703 mState.mDrawBufferTypeMask.setIndex(getDrawbufferWriteType(colorIndex), colorIndex);
Jamie Madill2d06b732015-04-20 12:53:28 -04001704 }
Jamie Madilla02315b2017-02-23 14:14:47 -05001705 break;
Geoff Langab75a052014-10-15 12:56:37 -04001706 }
Jamie Madill42975642017-10-12 12:31:51 -04001707
1708 mAttachedTextures.reset();
Geoff Langab75a052014-10-15 12:56:37 -04001709}
1710
Jamie Madill4928b7c2017-06-20 12:57:39 -04001711void Framebuffer::updateAttachment(const Context *context,
1712 FramebufferAttachment *attachment,
Jamie Madillb8126692017-04-05 11:22:17 -04001713 size_t dirtyBit,
Jamie Madilld4442552018-02-27 22:03:47 -05001714 angle::ObserverBinding *onDirtyBinding,
Jamie Madillb8126692017-04-05 11:22:17 -04001715 GLenum type,
1716 GLenum binding,
1717 const ImageIndex &textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001718 FramebufferAttachmentObject *resource,
1719 GLsizei numViews,
1720 GLuint baseViewIndex,
1721 GLenum multiviewLayout,
1722 const GLint *viewportOffsets)
Jamie Madillb8126692017-04-05 11:22:17 -04001723{
Martin Radev5dae57b2017-07-14 16:15:55 +03001724 attachment->attach(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
1725 multiviewLayout, viewportOffsets);
Jamie Madillb8126692017-04-05 11:22:17 -04001726 mDirtyBits.set(dirtyBit);
Jamie Madill05b35b22017-10-03 09:01:44 -04001727 mState.mResourceNeedsInit.set(dirtyBit, attachment->initState() == InitState::MayNeedInit);
Jamie Madill888081d2018-02-27 00:24:46 -05001728 onDirtyBinding->bind(resource ? resource->getSubject() : nullptr);
Jamie Madille98b1b52018-03-08 09:47:23 -05001729
1730 invalidateCompletenessCache();
Jamie Madillb8126692017-04-05 11:22:17 -04001731}
1732
Jamie Madilla02315b2017-02-23 14:14:47 -05001733void Framebuffer::resetAttachment(const Context *context, GLenum binding)
Jamie Madill2d06b732015-04-20 12:53:28 -04001734{
Jamie Madillcc129372018-04-12 09:13:18 -04001735 setAttachment(context, GL_NONE, binding, ImageIndex(), nullptr);
Jamie Madill2d06b732015-04-20 12:53:28 -04001736}
1737
Jamie Madill19fa1c62018-03-08 09:47:21 -05001738Error Framebuffer::syncState(const Context *context)
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001739{
1740 if (mDirtyBits.any())
1741 {
Jamie Madill888081d2018-02-27 00:24:46 -05001742 mDirtyBitsGuard = mDirtyBits;
Jamie Madill19fa1c62018-03-08 09:47:21 -05001743 ANGLE_TRY(mImpl->syncState(context, mDirtyBits));
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001744 mDirtyBits.reset();
Jamie Madill888081d2018-02-27 00:24:46 -05001745 mDirtyBitsGuard.reset();
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001746 }
Jamie Madill19fa1c62018-03-08 09:47:21 -05001747 return NoError();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001748}
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001749
Jamie Madilld4442552018-02-27 22:03:47 -05001750void Framebuffer::onSubjectStateChange(const Context *context,
1751 angle::SubjectIndex index,
1752 angle::SubjectMessage message)
Jamie Madill51f40ec2016-06-15 14:06:00 -04001753{
Jamie Madill888081d2018-02-27 00:24:46 -05001754 if (message == angle::SubjectMessage::DEPENDENT_DIRTY_BITS)
1755 {
1756 ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(index));
1757 mDirtyBits.set(index);
1758 context->getGLState().setFramebufferDirty(this);
1759 return;
1760 }
1761
Geoff Lang8170eab2017-09-21 13:59:04 -04001762 // Only reset the cached status if this is not the default framebuffer. The default framebuffer
1763 // will still use this channel to mark itself dirty.
Jamie Madill2274b652018-05-31 10:56:08 -04001764 if (mState.mId != 0)
Geoff Lang8170eab2017-09-21 13:59:04 -04001765 {
1766 // TOOD(jmadill): Make this only update individual attachments to do less work.
1767 mCachedStatus.reset();
1768 }
Jamie Madill05b35b22017-10-03 09:01:44 -04001769
Jamie Madilld4442552018-02-27 22:03:47 -05001770 FramebufferAttachment *attachment = getAttachmentFromSubjectIndex(index);
1771
Jamie Madill05b35b22017-10-03 09:01:44 -04001772 // Mark the appropriate init flag.
Jamie Madilld4442552018-02-27 22:03:47 -05001773 mState.mResourceNeedsInit.set(index, attachment->initState() == InitState::MayNeedInit);
1774}
1775
1776FramebufferAttachment *Framebuffer::getAttachmentFromSubjectIndex(angle::SubjectIndex index)
1777{
1778 switch (index)
1779 {
1780 case DIRTY_BIT_DEPTH_ATTACHMENT:
1781 return &mState.mDepthAttachment;
1782 case DIRTY_BIT_STENCIL_ATTACHMENT:
1783 return &mState.mStencilAttachment;
1784 default:
1785 size_t colorIndex = (index - DIRTY_BIT_COLOR_ATTACHMENT_0);
1786 ASSERT(colorIndex < mState.mColorAttachments.size());
1787 return &mState.mColorAttachments[colorIndex];
1788 }
Jamie Madill51f40ec2016-06-15 14:06:00 -04001789}
1790
Jamie Madill427064d2018-04-13 16:20:34 -04001791bool Framebuffer::isComplete(const Context *context)
Jamie Madill51f40ec2016-06-15 14:06:00 -04001792{
Jamie Madill427064d2018-04-13 16:20:34 -04001793 return (checkStatus(context) == GL_FRAMEBUFFER_COMPLETE);
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001794}
1795
Jamie Madilla4595b82017-01-11 17:36:34 -05001796bool Framebuffer::formsRenderingFeedbackLoopWith(const State &state) const
1797{
1798 const Program *program = state.getProgram();
1799
1800 // TODO(jmadill): Default framebuffer feedback loops.
Jamie Madill2274b652018-05-31 10:56:08 -04001801 if (mState.mId == 0)
Jamie Madilla4595b82017-01-11 17:36:34 -05001802 {
1803 return false;
1804 }
1805
1806 // The bitset will skip inactive draw buffers.
Jamie Madill6de51852017-04-12 09:53:01 -04001807 for (size_t drawIndex : mState.mEnabledDrawBuffers)
Jamie Madilla4595b82017-01-11 17:36:34 -05001808 {
Jamie Madill5aca1932017-07-21 12:22:01 -04001809 const FramebufferAttachment &attachment = mState.mColorAttachments[drawIndex];
1810 ASSERT(attachment.isAttached());
1811 if (attachment.type() == GL_TEXTURE)
Jamie Madilla4595b82017-01-11 17:36:34 -05001812 {
1813 // Validate the feedback loop.
Jamie Madill5aca1932017-07-21 12:22:01 -04001814 if (program->samplesFromTexture(state, attachment.id()))
Jamie Madilla4595b82017-01-11 17:36:34 -05001815 {
1816 return true;
1817 }
1818 }
1819 }
1820
Jamie Madill1d37bc52017-02-02 19:59:58 -05001821 // Validate depth-stencil feedback loop.
1822 const auto &dsState = state.getDepthStencilState();
1823
1824 // We can skip the feedback loop checks if depth/stencil is masked out or disabled.
1825 const FramebufferAttachment *depth = getDepthbuffer();
1826 if (depth && depth->type() == GL_TEXTURE && dsState.depthTest && dsState.depthMask)
1827 {
1828 if (program->samplesFromTexture(state, depth->id()))
1829 {
1830 return true;
1831 }
1832 }
1833
Jamie Madill1d37bc52017-02-02 19:59:58 -05001834 const FramebufferAttachment *stencil = getStencilbuffer();
Ken Russellb9f92502018-01-27 19:00:26 -08001835 if (dsState.stencilTest && stencil)
Jamie Madill1d37bc52017-02-02 19:59:58 -05001836 {
Ken Russellb9f92502018-01-27 19:00:26 -08001837 GLuint stencilSize = stencil->getStencilSize();
1838 ASSERT(stencilSize <= 8);
1839 GLuint maxStencilValue = (1 << stencilSize) - 1;
1840 // We assume the front and back masks are the same for WebGL.
1841 ASSERT((dsState.stencilBackWritemask & maxStencilValue) ==
1842 (dsState.stencilWritemask & maxStencilValue));
1843 if (stencil->type() == GL_TEXTURE && dsState.stencilWritemask != 0)
Jamie Madill1d37bc52017-02-02 19:59:58 -05001844 {
Ken Russellb9f92502018-01-27 19:00:26 -08001845 // Skip the feedback loop check if depth/stencil point to the same resource.
1846 if (!depth || *stencil != *depth)
Jamie Madill1d37bc52017-02-02 19:59:58 -05001847 {
Ken Russellb9f92502018-01-27 19:00:26 -08001848 if (program->samplesFromTexture(state, stencil->id()))
1849 {
1850 return true;
1851 }
Jamie Madill1d37bc52017-02-02 19:59:58 -05001852 }
1853 }
1854 }
1855
Jamie Madilla4595b82017-01-11 17:36:34 -05001856 return false;
1857}
1858
Jamie Madillfd3dd432017-02-02 19:59:59 -05001859bool Framebuffer::formsCopyingFeedbackLoopWith(GLuint copyTextureID,
1860 GLint copyTextureLevel,
1861 GLint copyTextureLayer) const
Jamie Madillf695a3a2017-01-11 17:36:35 -05001862{
Jamie Madill2274b652018-05-31 10:56:08 -04001863 if (mState.mId == 0)
Jamie Madillf695a3a2017-01-11 17:36:35 -05001864 {
1865 // It seems impossible to form a texture copying feedback loop with the default FBO.
1866 return false;
1867 }
1868
1869 const FramebufferAttachment *readAttachment = getReadColorbuffer();
1870 ASSERT(readAttachment);
1871
1872 if (readAttachment->isTextureWithId(copyTextureID))
1873 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05001874 const auto &imageIndex = readAttachment->getTextureImageIndex();
Jamie Madillcc129372018-04-12 09:13:18 -04001875 if (imageIndex.getLevelIndex() == copyTextureLevel)
Jamie Madillf695a3a2017-01-11 17:36:35 -05001876 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05001877 // Check 3D/Array texture layers.
Jamie Madillcc129372018-04-12 09:13:18 -04001878 return !imageIndex.hasLayer() || copyTextureLayer == ImageIndex::kEntireLevel ||
1879 imageIndex.getLayerIndex() == copyTextureLayer;
Jamie Madillf695a3a2017-01-11 17:36:35 -05001880 }
1881 }
1882 return false;
1883}
1884
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001885GLint Framebuffer::getDefaultWidth() const
1886{
1887 return mState.getDefaultWidth();
1888}
1889
1890GLint Framebuffer::getDefaultHeight() const
1891{
1892 return mState.getDefaultHeight();
1893}
1894
1895GLint Framebuffer::getDefaultSamples() const
1896{
1897 return mState.getDefaultSamples();
1898}
1899
Geoff Lang92019432017-11-20 13:09:34 -05001900bool Framebuffer::getDefaultFixedSampleLocations() const
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001901{
1902 return mState.getDefaultFixedSampleLocations();
1903}
1904
Jiawei Shaob1e91382018-05-17 14:33:55 +08001905GLint Framebuffer::getDefaultLayers() const
1906{
1907 return mState.getDefaultLayers();
1908}
1909
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001910void Framebuffer::setDefaultWidth(GLint defaultWidth)
1911{
1912 mState.mDefaultWidth = defaultWidth;
1913 mDirtyBits.set(DIRTY_BIT_DEFAULT_WIDTH);
Jamie Madille98b1b52018-03-08 09:47:23 -05001914 invalidateCompletenessCache();
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001915}
1916
1917void Framebuffer::setDefaultHeight(GLint defaultHeight)
1918{
1919 mState.mDefaultHeight = defaultHeight;
1920 mDirtyBits.set(DIRTY_BIT_DEFAULT_HEIGHT);
Jamie Madille98b1b52018-03-08 09:47:23 -05001921 invalidateCompletenessCache();
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001922}
1923
1924void Framebuffer::setDefaultSamples(GLint defaultSamples)
1925{
1926 mState.mDefaultSamples = defaultSamples;
1927 mDirtyBits.set(DIRTY_BIT_DEFAULT_SAMPLES);
Jamie Madille98b1b52018-03-08 09:47:23 -05001928 invalidateCompletenessCache();
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001929}
1930
Geoff Lang92019432017-11-20 13:09:34 -05001931void Framebuffer::setDefaultFixedSampleLocations(bool defaultFixedSampleLocations)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001932{
1933 mState.mDefaultFixedSampleLocations = defaultFixedSampleLocations;
1934 mDirtyBits.set(DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS);
Jamie Madille98b1b52018-03-08 09:47:23 -05001935 invalidateCompletenessCache();
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001936}
1937
Jiawei Shaob1e91382018-05-17 14:33:55 +08001938void Framebuffer::setDefaultLayers(GLint defaultLayers)
1939{
1940 mState.mDefaultLayers = defaultLayers;
1941 mDirtyBits.set(DIRTY_BIT_DEFAULT_LAYERS);
1942}
1943
Martin Radev14a26ae2017-07-24 15:56:29 +03001944GLsizei Framebuffer::getNumViews() const
1945{
Martin Radev5c00d0d2017-08-07 10:06:59 +03001946 return mState.getNumViews();
Martin Radev14a26ae2017-07-24 15:56:29 +03001947}
1948
Martin Radev4e619f52017-08-09 11:50:06 +03001949GLint Framebuffer::getBaseViewIndex() const
1950{
1951 return mState.getBaseViewIndex();
1952}
1953
Martin Radev878c8b12017-07-28 09:51:04 +03001954const std::vector<Offset> *Framebuffer::getViewportOffsets() const
1955{
Martin Radev5c00d0d2017-08-07 10:06:59 +03001956 return mState.getViewportOffsets();
Martin Radev878c8b12017-07-28 09:51:04 +03001957}
1958
1959GLenum Framebuffer::getMultiviewLayout() const
1960{
Martin Radev5c00d0d2017-08-07 10:06:59 +03001961 return mState.getMultiviewLayout();
Martin Radev878c8b12017-07-28 09:51:04 +03001962}
1963
Geoff Langd4fff502017-09-22 11:28:28 -04001964Error Framebuffer::ensureClearAttachmentsInitialized(const Context *context, GLbitfield mask)
1965{
1966 const auto &glState = context->getGLState();
1967 if (!context->isRobustResourceInitEnabled() || glState.isRasterizerDiscardEnabled())
1968 {
1969 return NoError();
1970 }
1971
Geoff Langa36483f2018-03-09 16:11:21 -05001972 const BlendState &blend = glState.getBlendState();
1973 const DepthStencilState &depthStencil = glState.getDepthStencilState();
Geoff Langd4fff502017-09-22 11:28:28 -04001974
1975 bool color = (mask & GL_COLOR_BUFFER_BIT) != 0 && !IsColorMaskedOut(blend);
1976 bool depth = (mask & GL_DEPTH_BUFFER_BIT) != 0 && !IsDepthMaskedOut(depthStencil);
1977 bool stencil = (mask & GL_STENCIL_BUFFER_BIT) != 0 && !IsStencilMaskedOut(depthStencil);
1978
1979 if (!color && !depth && !stencil)
1980 {
1981 return NoError();
1982 }
1983
1984 if (partialClearNeedsInit(context, color, depth, stencil))
1985 {
1986 ANGLE_TRY(ensureDrawAttachmentsInitialized(context));
1987 }
1988
1989 // If the impl encounters an error during a a full (non-partial) clear, the attachments will
1990 // still be marked initialized. This simplifies design, allowing this method to be called before
1991 // the clear.
1992 markDrawAttachmentsInitialized(color, depth, stencil);
1993
1994 return NoError();
1995}
1996
1997Error Framebuffer::ensureClearBufferAttachmentsInitialized(const Context *context,
1998 GLenum buffer,
1999 GLint drawbuffer)
2000{
2001 if (!context->isRobustResourceInitEnabled() ||
2002 context->getGLState().isRasterizerDiscardEnabled() ||
2003 IsClearBufferMaskedOut(context, buffer))
2004 {
2005 return NoError();
2006 }
2007
2008 if (partialBufferClearNeedsInit(context, buffer))
2009 {
2010 ANGLE_TRY(ensureBufferInitialized(context, buffer, drawbuffer));
2011 }
2012
2013 // If the impl encounters an error during a a full (non-partial) clear, the attachments will
2014 // still be marked initialized. This simplifies design, allowing this method to be called before
2015 // the clear.
2016 markBufferInitialized(buffer, drawbuffer);
2017
2018 return NoError();
2019}
2020
Jamie Madill05b35b22017-10-03 09:01:44 -04002021Error Framebuffer::ensureDrawAttachmentsInitialized(const Context *context)
2022{
2023 if (!context->isRobustResourceInitEnabled())
2024 {
2025 return NoError();
2026 }
2027
2028 // Note: we don't actually filter by the draw attachment enum. Just init everything.
2029 for (size_t bit : mState.mResourceNeedsInit)
2030 {
2031 switch (bit)
2032 {
2033 case DIRTY_BIT_DEPTH_ATTACHMENT:
2034 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2035 break;
2036 case DIRTY_BIT_STENCIL_ATTACHMENT:
2037 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2038 break;
2039 default:
2040 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[bit]));
2041 break;
2042 }
2043 }
2044
2045 mState.mResourceNeedsInit.reset();
2046 return NoError();
2047}
2048
2049Error Framebuffer::ensureReadAttachmentInitialized(const Context *context, GLbitfield blitMask)
2050{
2051 if (!context->isRobustResourceInitEnabled() || mState.mResourceNeedsInit.none())
2052 {
2053 return NoError();
2054 }
2055
2056 if ((blitMask & GL_COLOR_BUFFER_BIT) != 0 && mState.mReadBufferState != GL_NONE)
2057 {
2058 size_t readIndex = mState.getReadIndex();
2059 if (mState.mResourceNeedsInit[readIndex])
2060 {
2061 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[readIndex]));
2062 mState.mResourceNeedsInit.reset(readIndex);
2063 }
2064 }
2065
2066 if ((blitMask & GL_DEPTH_BUFFER_BIT) != 0 && hasDepth())
2067 {
2068 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2069 {
2070 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2071 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2072 }
2073 }
2074
2075 if ((blitMask & GL_STENCIL_BUFFER_BIT) != 0 && hasStencil())
2076 {
2077 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2078 {
2079 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2080 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2081 }
2082 }
2083
2084 return NoError();
2085}
2086
2087void Framebuffer::markDrawAttachmentsInitialized(bool color, bool depth, bool stencil)
2088{
2089 // Mark attachments as initialized.
2090 if (color)
2091 {
2092 for (auto colorIndex : mState.mEnabledDrawBuffers)
2093 {
2094 auto &colorAttachment = mState.mColorAttachments[colorIndex];
2095 ASSERT(colorAttachment.isAttached());
2096 colorAttachment.setInitState(InitState::Initialized);
2097 mState.mResourceNeedsInit.reset(colorIndex);
2098 }
2099 }
2100
2101 if (depth && mState.mDepthAttachment.isAttached())
2102 {
2103 mState.mDepthAttachment.setInitState(InitState::Initialized);
2104 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2105 }
2106
2107 if (stencil && mState.mStencilAttachment.isAttached())
2108 {
2109 mState.mStencilAttachment.setInitState(InitState::Initialized);
2110 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2111 }
2112}
2113
2114void Framebuffer::markBufferInitialized(GLenum bufferType, GLint bufferIndex)
2115{
2116 switch (bufferType)
2117 {
2118 case GL_COLOR:
2119 {
2120 ASSERT(bufferIndex < static_cast<GLint>(mState.mColorAttachments.size()));
2121 if (mState.mColorAttachments[bufferIndex].isAttached())
2122 {
2123 mState.mColorAttachments[bufferIndex].setInitState(InitState::Initialized);
2124 mState.mResourceNeedsInit.reset(bufferIndex);
2125 }
2126 break;
2127 }
2128 case GL_DEPTH:
2129 {
2130 if (mState.mDepthAttachment.isAttached())
2131 {
2132 mState.mDepthAttachment.setInitState(InitState::Initialized);
2133 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2134 }
2135 break;
2136 }
2137 case GL_STENCIL:
2138 {
2139 if (mState.mStencilAttachment.isAttached())
2140 {
2141 mState.mStencilAttachment.setInitState(InitState::Initialized);
2142 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2143 }
2144 break;
2145 }
2146 case GL_DEPTH_STENCIL:
2147 {
2148 if (mState.mDepthAttachment.isAttached())
2149 {
2150 mState.mDepthAttachment.setInitState(InitState::Initialized);
2151 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2152 }
2153 if (mState.mStencilAttachment.isAttached())
2154 {
2155 mState.mStencilAttachment.setInitState(InitState::Initialized);
2156 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2157 }
2158 break;
2159 }
2160 default:
2161 UNREACHABLE();
2162 break;
2163 }
2164}
2165
2166Box Framebuffer::getDimensions() const
2167{
2168 return mState.getDimensions();
2169}
2170
2171Error Framebuffer::ensureBufferInitialized(const Context *context,
2172 GLenum bufferType,
2173 GLint bufferIndex)
2174{
2175 ASSERT(context->isRobustResourceInitEnabled());
2176
2177 if (mState.mResourceNeedsInit.none())
2178 {
2179 return NoError();
2180 }
2181
2182 switch (bufferType)
2183 {
2184 case GL_COLOR:
2185 {
2186 ASSERT(bufferIndex < static_cast<GLint>(mState.mColorAttachments.size()));
2187 if (mState.mResourceNeedsInit[bufferIndex])
2188 {
2189 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[bufferIndex]));
2190 mState.mResourceNeedsInit.reset(bufferIndex);
2191 }
2192 break;
2193 }
2194 case GL_DEPTH:
2195 {
2196 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2197 {
2198 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2199 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2200 }
2201 break;
2202 }
2203 case GL_STENCIL:
2204 {
2205 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2206 {
2207 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2208 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2209 }
2210 break;
2211 }
2212 case GL_DEPTH_STENCIL:
2213 {
2214 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2215 {
2216 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2217 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2218 }
2219 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2220 {
2221 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2222 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2223 }
2224 break;
2225 }
2226 default:
2227 UNREACHABLE();
2228 break;
2229 }
2230
2231 return NoError();
2232}
2233
2234bool Framebuffer::partialBufferClearNeedsInit(const Context *context, GLenum bufferType)
2235{
2236 if (!context->isRobustResourceInitEnabled() || mState.mResourceNeedsInit.none())
2237 {
2238 return false;
2239 }
2240
2241 switch (bufferType)
2242 {
2243 case GL_COLOR:
2244 return partialClearNeedsInit(context, true, false, false);
2245 case GL_DEPTH:
2246 return partialClearNeedsInit(context, false, true, false);
2247 case GL_STENCIL:
2248 return partialClearNeedsInit(context, false, false, true);
2249 case GL_DEPTH_STENCIL:
2250 return partialClearNeedsInit(context, false, true, true);
2251 default:
2252 UNREACHABLE();
2253 return false;
2254 }
2255}
2256
Jamie Madill42975642017-10-12 12:31:51 -04002257bool Framebuffer::hasTextureAttachment(const Texture *texture) const
2258{
2259 if (!mAttachedTextures.valid())
2260 {
2261 std::set<const FramebufferAttachmentObject *> attachedTextures;
2262
2263 for (const auto &colorAttachment : mState.mColorAttachments)
2264 {
2265 if (colorAttachment.isAttached() && colorAttachment.type() == GL_TEXTURE)
2266 {
2267 attachedTextures.insert(colorAttachment.getResource());
2268 }
2269 }
2270
2271 if (mState.mDepthAttachment.isAttached() && mState.mDepthAttachment.type() == GL_TEXTURE)
2272 {
2273 attachedTextures.insert(mState.mDepthAttachment.getResource());
2274 }
2275
2276 if (mState.mStencilAttachment.isAttached() &&
2277 mState.mStencilAttachment.type() == GL_TEXTURE)
2278 {
2279 attachedTextures.insert(mState.mStencilAttachment.getResource());
2280 }
2281
2282 mAttachedTextures = std::move(attachedTextures);
2283 }
2284
2285 return (mAttachedTextures.value().count(texture) > 0);
2286}
2287
Jamie Madill60ec6ea2016-01-22 15:27:19 -05002288} // namespace gl