blob: a233c3da14c0c06a276918326aac349e11608817 [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;
Yuly Novikovf15f8862018-06-04 18:59:41 -040075 if (attachment.type() == GL_RENDERBUFFER &&
76 !format.renderbufferSupport(context->getClientVersion(), context->getExtensions()))
77 {
78 return false;
79 }
80 if (attachment.type() == GL_TEXTURE &&
81 !format.textureAttachmentSupport(context->getClientVersion(), context->getExtensions()))
Geoff Lang9f10b772017-05-16 15:51:03 -040082 {
83 return false;
84 }
85
86 if (attachment.type() == GL_TEXTURE)
87 {
88 if (attachment.layer() >= size.depth)
89 {
90 return false;
91 }
92
93 // ES3 specifies that cube map texture attachments must be cube complete.
94 // This language is missing from the ES2 spec, but we enforce it here because some
95 // desktop OpenGL drivers also enforce this validation.
96 // TODO(jmadill): Check if OpenGL ES2 drivers enforce cube completeness.
97 const Texture *texture = attachment.getTexture();
98 ASSERT(texture);
Corentin Wallez99d492c2018-02-27 15:17:10 -050099 if (texture->getType() == TextureType::CubeMap &&
Geoff Lang9f10b772017-05-16 15:51:03 -0400100 !texture->getTextureState().isCubeComplete())
101 {
102 return false;
103 }
Geoff Lang857c09d2017-05-16 15:55:04 -0400104
105 if (!texture->getImmutableFormat())
106 {
107 GLuint attachmentMipLevel = static_cast<GLuint>(attachment.mipLevel());
108
109 // From the ES 3.0 spec, pg 213:
110 // If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is TEXTURE and the value of
111 // FRAMEBUFFER_ATTACHMENT_OBJECT_NAME does not name an immutable-format texture,
112 // then the value of FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL must be in the
113 // range[levelbase, q], where levelbase is the value of TEXTURE_BASE_LEVEL and q is
114 // the effective maximum texture level defined in the Mipmapping discussion of
115 // section 3.8.10.4.
116 if (attachmentMipLevel < texture->getBaseLevel() ||
117 attachmentMipLevel > texture->getMipmapMaxLevel())
118 {
119 return false;
120 }
121
122 // Form the ES 3.0 spec, pg 213/214:
123 // If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is TEXTURE and the value of
124 // FRAMEBUFFER_ATTACHMENT_OBJECT_NAME does not name an immutable-format texture and
125 // the value of FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL is not levelbase, then the
126 // texture must be mipmap complete, and if FRAMEBUFFER_ATTACHMENT_OBJECT_NAME names
127 // a cubemap texture, the texture must also be cube complete.
128 if (attachmentMipLevel != texture->getBaseLevel() && !texture->isMipmapComplete())
129 {
130 return false;
131 }
132 }
Geoff Lang9f10b772017-05-16 15:51:03 -0400133 }
134
135 return true;
136};
137
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400138bool CheckAttachmentSampleCompleteness(const Context *context,
139 const FramebufferAttachment &attachment,
140 bool colorAttachment,
141 Optional<int> *samples,
Geoff Lang92019432017-11-20 13:09:34 -0500142 Optional<bool> *fixedSampleLocations)
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400143{
144 ASSERT(attachment.isAttached());
145
146 if (attachment.type() == GL_TEXTURE)
147 {
148 const Texture *texture = attachment.getTexture();
149 ASSERT(texture);
150
151 const ImageIndex &attachmentImageIndex = attachment.getTextureImageIndex();
152
153 // ES3.1 (section 9.4) requires that the value of TEXTURE_FIXED_SAMPLE_LOCATIONS should be
154 // the same for all attached textures.
Jamie Madillcc129372018-04-12 09:13:18 -0400155 bool fixedSampleloc = texture->getFixedSampleLocations(
156 attachmentImageIndex.getTarget(), attachmentImageIndex.getLevelIndex());
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400157 if (fixedSampleLocations->valid() && fixedSampleloc != fixedSampleLocations->value())
158 {
159 return false;
160 }
161 else
162 {
163 *fixedSampleLocations = fixedSampleloc;
164 }
165 }
166
167 if (samples->valid())
168 {
169 if (attachment.getSamples() != samples->value())
170 {
171 if (colorAttachment)
172 {
173 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
174 // all color attachments have the same number of samples for the FBO to be complete.
175 return false;
176 }
177 else
178 {
179 // CHROMIUM_framebuffer_mixed_samples allows a framebuffer to be considered complete
180 // when its depth or stencil samples are a multiple of the number of color samples.
181 if (!context->getExtensions().framebufferMixedSamples)
182 {
183 return false;
184 }
185
186 if ((attachment.getSamples() % std::max(samples->value(), 1)) != 0)
187 {
188 return false;
189 }
190 }
191 }
192 }
193 else
194 {
195 *samples = attachment.getSamples();
196 }
197
198 return true;
199}
200
Jamie Madill05b35b22017-10-03 09:01:44 -0400201// Needed to index into the attachment arrays/bitsets.
Jamie Madill682efdc2017-10-03 14:10:29 -0400202static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS) ==
Jamie Madilld4442552018-02-27 22:03:47 -0500203 Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX,
Jamie Madill05b35b22017-10-03 09:01:44 -0400204 "Framebuffer Dirty bit mismatch");
Jamie Madill682efdc2017-10-03 14:10:29 -0400205static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS) ==
Jamie Madilld4442552018-02-27 22:03:47 -0500206 Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT,
Jamie Madill05b35b22017-10-03 09:01:44 -0400207 "Framebuffer Dirty bit mismatch");
Jamie Madill682efdc2017-10-03 14:10:29 -0400208static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS + 1) ==
Jamie Madilld4442552018-02-27 22:03:47 -0500209 Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT,
Jamie Madill05b35b22017-10-03 09:01:44 -0400210 "Framebuffer Dirty bit mismatch");
211
212Error InitAttachment(const Context *context, FramebufferAttachment *attachment)
213{
214 ASSERT(attachment->isAttached());
215 if (attachment->initState() == InitState::MayNeedInit)
216 {
217 ANGLE_TRY(attachment->initializeContents(context));
218 }
219 return NoError();
220}
221
222bool IsColorMaskedOut(const BlendState &blend)
223{
224 return (!blend.colorMaskRed && !blend.colorMaskGreen && !blend.colorMaskBlue &&
225 !blend.colorMaskAlpha);
226}
227
228bool IsDepthMaskedOut(const DepthStencilState &depthStencil)
229{
230 return !depthStencil.depthMask;
231}
232
233bool IsStencilMaskedOut(const DepthStencilState &depthStencil)
234{
235 return ((depthStencil.stencilMask & depthStencil.stencilWritemask) == 0);
236}
237
238bool IsClearBufferMaskedOut(const Context *context, GLenum buffer)
239{
240 switch (buffer)
241 {
242 case GL_COLOR:
243 return IsColorMaskedOut(context->getGLState().getBlendState());
244 case GL_DEPTH:
245 return IsDepthMaskedOut(context->getGLState().getDepthStencilState());
246 case GL_STENCIL:
247 return IsStencilMaskedOut(context->getGLState().getDepthStencilState());
248 case GL_DEPTH_STENCIL:
249 return IsDepthMaskedOut(context->getGLState().getDepthStencilState()) &&
250 IsStencilMaskedOut(context->getGLState().getDepthStencilState());
251 default:
252 UNREACHABLE();
253 return true;
254 }
255}
256
Jamie Madill362876b2016-06-16 14:46:59 -0400257} // anonymous namespace
Jamie Madilld1405e52015-03-05 15:41:39 -0500258
Jamie Madill6f60d052017-02-22 15:20:11 -0500259// This constructor is only used for default framebuffers.
Jamie Madill48ef11b2016-04-27 15:21:52 -0400260FramebufferState::FramebufferState()
Jamie Madill2274b652018-05-31 10:56:08 -0400261 : mId(0),
262 mLabel(),
Geoff Lang70d0f492015-12-10 17:45:46 -0500263 mColorAttachments(1),
Corentin Walleze7557742017-06-01 13:09:57 -0400264 mDrawBufferStates(1, GL_BACK),
Jamie Madill6f60d052017-02-22 15:20:11 -0500265 mReadBufferState(GL_BACK),
Brandon Jones76746f92017-11-22 11:44:41 -0800266 mDrawBufferTypeMask(),
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800267 mDefaultWidth(0),
268 mDefaultHeight(0),
269 mDefaultSamples(0),
Jamie Madilla02315b2017-02-23 14:14:47 -0500270 mDefaultFixedSampleLocations(GL_FALSE),
Jiawei Shaob1e91382018-05-17 14:33:55 +0800271 mDefaultLayers(0),
Jamie Madilla02315b2017-02-23 14:14:47 -0500272 mWebGLDepthStencilConsistent(true)
Corentin Wallez37c39792015-08-20 14:19:46 -0400273{
Geoff Langd90d3882017-03-21 10:49:54 -0400274 ASSERT(mDrawBufferStates.size() > 0);
Jamie Madilla4595b82017-01-11 17:36:34 -0500275 mEnabledDrawBuffers.set(0);
Corentin Wallez37c39792015-08-20 14:19:46 -0400276}
277
Jamie Madill2274b652018-05-31 10:56:08 -0400278FramebufferState::FramebufferState(const Caps &caps, GLuint id)
279 : mId(id),
280 mLabel(),
Geoff Lang70d0f492015-12-10 17:45:46 -0500281 mColorAttachments(caps.maxColorAttachments),
Jamie Madilld1405e52015-03-05 15:41:39 -0500282 mDrawBufferStates(caps.maxDrawBuffers, GL_NONE),
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800283 mReadBufferState(GL_COLOR_ATTACHMENT0_EXT),
Brandon Jones76746f92017-11-22 11:44:41 -0800284 mDrawBufferTypeMask(),
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800285 mDefaultWidth(0),
286 mDefaultHeight(0),
287 mDefaultSamples(0),
Jamie Madilla02315b2017-02-23 14:14:47 -0500288 mDefaultFixedSampleLocations(GL_FALSE),
Jiawei Shaob1e91382018-05-17 14:33:55 +0800289 mDefaultLayers(0),
Jamie Madilla02315b2017-02-23 14:14:47 -0500290 mWebGLDepthStencilConsistent(true)
Jamie Madilld1405e52015-03-05 15:41:39 -0500291{
Jamie Madill2274b652018-05-31 10:56:08 -0400292 ASSERT(mId != 0);
Geoff Langa15472a2015-08-11 11:48:03 -0400293 ASSERT(mDrawBufferStates.size() > 0);
Jamie Madilld1405e52015-03-05 15:41:39 -0500294 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
295}
296
Jamie Madill48ef11b2016-04-27 15:21:52 -0400297FramebufferState::~FramebufferState()
Jamie Madilld1405e52015-03-05 15:41:39 -0500298{
Jamie Madilld1405e52015-03-05 15:41:39 -0500299}
300
Jamie Madill48ef11b2016-04-27 15:21:52 -0400301const std::string &FramebufferState::getLabel()
Geoff Lang70d0f492015-12-10 17:45:46 -0500302{
303 return mLabel;
304}
305
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800306const FramebufferAttachment *FramebufferState::getAttachment(const Context *context,
307 GLenum attachment) const
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400308{
309 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
310 {
311 return getColorAttachment(attachment - GL_COLOR_ATTACHMENT0);
312 }
313
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800314 // WebGL1 allows a developer to query for attachment parameters even when "inconsistant" (i.e.
315 // multiple conflicting attachment points) and requires us to return the framebuffer attachment
316 // associated with WebGL.
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400317 switch (attachment)
318 {
319 case GL_COLOR:
320 case GL_BACK:
321 return getColorAttachment(0);
322 case GL_DEPTH:
323 case GL_DEPTH_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800324 if (context->isWebGL1())
325 {
326 return getWebGLDepthAttachment();
327 }
328 else
329 {
330 return getDepthAttachment();
331 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400332 case GL_STENCIL:
333 case GL_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800334 if (context->isWebGL1())
335 {
336 return getWebGLStencilAttachment();
337 }
338 else
339 {
340 return getStencilAttachment();
341 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400342 case GL_DEPTH_STENCIL:
343 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800344 if (context->isWebGL1())
345 {
346 return getWebGLDepthStencilAttachment();
347 }
348 else
349 {
350 return getDepthStencilAttachment();
351 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400352 default:
353 UNREACHABLE();
354 return nullptr;
355 }
356}
357
Jamie Madill05b35b22017-10-03 09:01:44 -0400358size_t FramebufferState::getReadIndex() const
Jamie Madill7147f012015-03-05 15:41:40 -0500359{
Jamie Madill231c7f52017-04-26 13:45:37 -0400360 ASSERT(mReadBufferState == GL_BACK ||
361 (mReadBufferState >= GL_COLOR_ATTACHMENT0 && mReadBufferState <= GL_COLOR_ATTACHMENT15));
362 size_t readIndex = (mReadBufferState == GL_BACK
363 ? 0
364 : static_cast<size_t>(mReadBufferState - GL_COLOR_ATTACHMENT0));
Jamie Madill7147f012015-03-05 15:41:40 -0500365 ASSERT(readIndex < mColorAttachments.size());
Jamie Madill05b35b22017-10-03 09:01:44 -0400366 return readIndex;
367}
368
369const FramebufferAttachment *FramebufferState::getReadAttachment() const
370{
371 if (mReadBufferState == GL_NONE)
372 {
373 return nullptr;
374 }
375 size_t readIndex = getReadIndex();
Jamie Madill2d06b732015-04-20 12:53:28 -0400376 return mColorAttachments[readIndex].isAttached() ? &mColorAttachments[readIndex] : nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500377}
378
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500379const FramebufferAttachment *FramebufferState::getFirstNonNullAttachment() const
380{
381 auto *colorAttachment = getFirstColorAttachment();
382 if (colorAttachment)
383 {
384 return colorAttachment;
385 }
386 return getDepthOrStencilAttachment();
387}
388
Jamie Madill48ef11b2016-04-27 15:21:52 -0400389const FramebufferAttachment *FramebufferState::getFirstColorAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500390{
Jamie Madill2d06b732015-04-20 12:53:28 -0400391 for (const FramebufferAttachment &colorAttachment : mColorAttachments)
Jamie Madill7147f012015-03-05 15:41:40 -0500392 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400393 if (colorAttachment.isAttached())
Jamie Madill7147f012015-03-05 15:41:40 -0500394 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400395 return &colorAttachment;
Jamie Madill7147f012015-03-05 15:41:40 -0500396 }
397 }
398
399 return nullptr;
400}
401
Jamie Madill48ef11b2016-04-27 15:21:52 -0400402const FramebufferAttachment *FramebufferState::getDepthOrStencilAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500403{
Jamie Madill2d06b732015-04-20 12:53:28 -0400404 if (mDepthAttachment.isAttached())
405 {
406 return &mDepthAttachment;
407 }
408 if (mStencilAttachment.isAttached())
409 {
410 return &mStencilAttachment;
411 }
412 return nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500413}
414
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500415const FramebufferAttachment *FramebufferState::getStencilOrDepthStencilAttachment() const
416{
417 if (mStencilAttachment.isAttached())
418 {
419 return &mStencilAttachment;
420 }
421 return getDepthStencilAttachment();
422}
423
Jamie Madill48ef11b2016-04-27 15:21:52 -0400424const FramebufferAttachment *FramebufferState::getColorAttachment(size_t colorAttachment) const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400425{
426 ASSERT(colorAttachment < mColorAttachments.size());
Jamie Madill231c7f52017-04-26 13:45:37 -0400427 return mColorAttachments[colorAttachment].isAttached() ? &mColorAttachments[colorAttachment]
428 : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400429}
430
Jamie Madill48ef11b2016-04-27 15:21:52 -0400431const FramebufferAttachment *FramebufferState::getDepthAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400432{
Jamie Madill2d06b732015-04-20 12:53:28 -0400433 return mDepthAttachment.isAttached() ? &mDepthAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400434}
435
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800436const FramebufferAttachment *FramebufferState::getWebGLDepthAttachment() const
437{
438 return mWebGLDepthAttachment.isAttached() ? &mWebGLDepthAttachment : nullptr;
439}
440
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800441const FramebufferAttachment *FramebufferState::getWebGLDepthStencilAttachment() const
442{
443 return mWebGLDepthStencilAttachment.isAttached() ? &mWebGLDepthStencilAttachment : nullptr;
444}
445
Jamie Madill48ef11b2016-04-27 15:21:52 -0400446const FramebufferAttachment *FramebufferState::getStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400447{
Jamie Madill2d06b732015-04-20 12:53:28 -0400448 return mStencilAttachment.isAttached() ? &mStencilAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400449}
450
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800451const FramebufferAttachment *FramebufferState::getWebGLStencilAttachment() const
452{
453 return mWebGLStencilAttachment.isAttached() ? &mWebGLStencilAttachment : nullptr;
454}
455
Jamie Madill48ef11b2016-04-27 15:21:52 -0400456const FramebufferAttachment *FramebufferState::getDepthStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400457{
458 // A valid depth-stencil attachment has the same resource bound to both the
459 // depth and stencil attachment points.
Jamie Madill2d06b732015-04-20 12:53:28 -0400460 if (mDepthAttachment.isAttached() && mStencilAttachment.isAttached() &&
Jamie Madill44f26482016-11-18 12:49:15 -0500461 mDepthAttachment == mStencilAttachment)
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400462 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400463 return &mDepthAttachment;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400464 }
465
466 return nullptr;
467}
468
Jamie Madill48ef11b2016-04-27 15:21:52 -0400469bool FramebufferState::attachmentsHaveSameDimensions() const
Jamie Madillcc86d642015-11-24 13:00:07 -0500470{
471 Optional<Extents> attachmentSize;
472
Jamie Madill231c7f52017-04-26 13:45:37 -0400473 auto hasMismatchedSize = [&attachmentSize](const FramebufferAttachment &attachment) {
Jamie Madillcc86d642015-11-24 13:00:07 -0500474 if (!attachment.isAttached())
475 {
476 return false;
477 }
478
479 if (!attachmentSize.valid())
480 {
481 attachmentSize = attachment.getSize();
482 return false;
483 }
484
Jeff Gilbert8f8edd62017-10-31 14:26:30 -0700485 const auto &prevSize = attachmentSize.value();
486 const auto &curSize = attachment.getSize();
487 return (curSize.width != prevSize.width || curSize.height != prevSize.height);
Jamie Madillcc86d642015-11-24 13:00:07 -0500488 };
489
490 for (const auto &attachment : mColorAttachments)
491 {
492 if (hasMismatchedSize(attachment))
493 {
494 return false;
495 }
496 }
497
498 if (hasMismatchedSize(mDepthAttachment))
499 {
500 return false;
501 }
502
503 return !hasMismatchedSize(mStencilAttachment);
504}
505
Jamie Madilld4442552018-02-27 22:03:47 -0500506const FramebufferAttachment *FramebufferState::getDrawBuffer(size_t drawBufferIdx) const
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400507{
508 ASSERT(drawBufferIdx < mDrawBufferStates.size());
509 if (mDrawBufferStates[drawBufferIdx] != GL_NONE)
510 {
511 // ES3 spec: "If the GL is bound to a draw framebuffer object, the ith buffer listed in bufs
512 // must be COLOR_ATTACHMENTi or NONE"
513 ASSERT(mDrawBufferStates[drawBufferIdx] == GL_COLOR_ATTACHMENT0 + drawBufferIdx ||
514 (drawBufferIdx == 0 && mDrawBufferStates[drawBufferIdx] == GL_BACK));
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800515
516 if (mDrawBufferStates[drawBufferIdx] == GL_BACK)
517 {
518 return getColorAttachment(0);
519 }
520 else
521 {
522 return getColorAttachment(mDrawBufferStates[drawBufferIdx] - GL_COLOR_ATTACHMENT0);
523 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400524 }
525 else
526 {
527 return nullptr;
528 }
529}
530
531size_t FramebufferState::getDrawBufferCount() const
532{
533 return mDrawBufferStates.size();
534}
535
Geoff Langb21e20d2016-07-19 15:35:41 -0400536bool FramebufferState::colorAttachmentsAreUniqueImages() const
537{
538 for (size_t firstAttachmentIdx = 0; firstAttachmentIdx < mColorAttachments.size();
539 firstAttachmentIdx++)
540 {
Jamie Madilld4442552018-02-27 22:03:47 -0500541 const FramebufferAttachment &firstAttachment = mColorAttachments[firstAttachmentIdx];
Geoff Langb21e20d2016-07-19 15:35:41 -0400542 if (!firstAttachment.isAttached())
543 {
544 continue;
545 }
546
547 for (size_t secondAttachmentIdx = firstAttachmentIdx + 1;
548 secondAttachmentIdx < mColorAttachments.size(); secondAttachmentIdx++)
549 {
Jamie Madilld4442552018-02-27 22:03:47 -0500550 const FramebufferAttachment &secondAttachment = mColorAttachments[secondAttachmentIdx];
Geoff Langb21e20d2016-07-19 15:35:41 -0400551 if (!secondAttachment.isAttached())
552 {
553 continue;
554 }
555
556 if (firstAttachment == secondAttachment)
557 {
558 return false;
559 }
560 }
561 }
562
563 return true;
564}
565
Jamie Madill9c335862017-07-18 11:51:38 -0400566bool FramebufferState::hasDepth() const
567{
568 return (mDepthAttachment.isAttached() && mDepthAttachment.getDepthSize() > 0);
569}
570
571bool FramebufferState::hasStencil() const
572{
573 return (mStencilAttachment.isAttached() && mStencilAttachment.getStencilSize() > 0);
574}
575
Martin Radev5c00d0d2017-08-07 10:06:59 +0300576GLsizei FramebufferState::getNumViews() const
577{
578 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
579 if (attachment == nullptr)
580 {
581 return FramebufferAttachment::kDefaultNumViews;
582 }
583 return attachment->getNumViews();
584}
585
586const std::vector<Offset> *FramebufferState::getViewportOffsets() const
587{
588 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
589 if (attachment == nullptr)
590 {
591 return nullptr;
592 }
593 return &attachment->getMultiviewViewportOffsets();
594}
595
596GLenum FramebufferState::getMultiviewLayout() const
597{
598 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
599 if (attachment == nullptr)
600 {
601 return GL_NONE;
602 }
603 return attachment->getMultiviewLayout();
604}
605
Martin Radev4e619f52017-08-09 11:50:06 +0300606int FramebufferState::getBaseViewIndex() const
607{
608 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
609 if (attachment == nullptr)
610 {
611 return GL_NONE;
612 }
613 return attachment->getBaseViewIndex();
614}
615
Jamie Madill05b35b22017-10-03 09:01:44 -0400616Box FramebufferState::getDimensions() const
617{
618 ASSERT(attachmentsHaveSameDimensions());
619 ASSERT(getFirstNonNullAttachment() != nullptr);
620 Extents extents = getFirstNonNullAttachment()->getSize();
621 return Box(0, 0, 0, extents.width, extents.height, extents.depth);
622}
623
Jamie Madill7aea7e02016-05-10 10:39:45 -0400624Framebuffer::Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id)
Jamie Madill2274b652018-05-31 10:56:08 -0400625 : mState(caps, id),
Jamie Madill362876b2016-06-16 14:46:59 -0400626 mImpl(factory->createFramebuffer(mState)),
Jamie Madill362876b2016-06-16 14:46:59 -0400627 mCachedStatus(),
628 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
629 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000630{
Corentin Wallez37c39792015-08-20 14:19:46 -0400631 ASSERT(mImpl != nullptr);
Jamie Madill362876b2016-06-16 14:46:59 -0400632 ASSERT(mState.mColorAttachments.size() == static_cast<size_t>(caps.maxColorAttachments));
633
Jamie Madill1e5499d2017-04-05 11:22:16 -0400634 for (uint32_t colorIndex = 0;
635 colorIndex < static_cast<uint32_t>(mState.mColorAttachments.size()); ++colorIndex)
Jamie Madill362876b2016-06-16 14:46:59 -0400636 {
Jamie Madill1e5499d2017-04-05 11:22:16 -0400637 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
Jamie Madill362876b2016-06-16 14:46:59 -0400638 }
Corentin Wallez37c39792015-08-20 14:19:46 -0400639}
640
Geoff Langbf7b95d2018-05-01 16:48:21 -0400641Framebuffer::Framebuffer(const Context *context, egl::Surface *surface)
Jamie Madill362876b2016-06-16 14:46:59 -0400642 : mState(),
Geoff Langbf7b95d2018-05-01 16:48:21 -0400643 mImpl(surface->getImplementation()->createDefaultFramebuffer(context, mState)),
Jamie Madill362876b2016-06-16 14:46:59 -0400644 mCachedStatus(GL_FRAMEBUFFER_COMPLETE),
645 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
646 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
Corentin Wallez37c39792015-08-20 14:19:46 -0400647{
Geoff Langda88add2014-12-01 10:22:01 -0500648 ASSERT(mImpl != nullptr);
Jamie Madill1e5499d2017-04-05 11:22:16 -0400649 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
Jamie Madill6f60d052017-02-22 15:20:11 -0500650
Geoff Langbf7b95d2018-05-01 16:48:21 -0400651 setAttachmentImpl(context, GL_FRAMEBUFFER_DEFAULT, GL_BACK, ImageIndex(), surface,
Jamie Madillcc129372018-04-12 09:13:18 -0400652 FramebufferAttachment::kDefaultNumViews,
Martin Radev5dae57b2017-07-14 16:15:55 +0300653 FramebufferAttachment::kDefaultBaseViewIndex,
654 FramebufferAttachment::kDefaultMultiviewLayout,
655 FramebufferAttachment::kDefaultViewportOffsets);
Jamie Madill6f60d052017-02-22 15:20:11 -0500656
657 if (surface->getConfig()->depthSize > 0)
658 {
Geoff Langbf7b95d2018-05-01 16:48:21 -0400659 setAttachmentImpl(context, GL_FRAMEBUFFER_DEFAULT, GL_DEPTH, ImageIndex(), surface,
Jamie Madillcc129372018-04-12 09:13:18 -0400660 FramebufferAttachment::kDefaultNumViews,
Jamie Madilld4442552018-02-27 22:03:47 -0500661 FramebufferAttachment::kDefaultBaseViewIndex,
662 FramebufferAttachment::kDefaultMultiviewLayout,
663 FramebufferAttachment::kDefaultViewportOffsets);
Jamie Madill6f60d052017-02-22 15:20:11 -0500664 }
665
666 if (surface->getConfig()->stencilSize > 0)
667 {
Geoff Langbf7b95d2018-05-01 16:48:21 -0400668 setAttachmentImpl(context, GL_FRAMEBUFFER_DEFAULT, GL_STENCIL, ImageIndex(), surface,
Jamie Madillcc129372018-04-12 09:13:18 -0400669 FramebufferAttachment::kDefaultNumViews,
670 FramebufferAttachment::kDefaultBaseViewIndex,
671 FramebufferAttachment::kDefaultMultiviewLayout,
672 FramebufferAttachment::kDefaultViewportOffsets);
Jamie Madill6f60d052017-02-22 15:20:11 -0500673 }
Brandon Jones76746f92017-11-22 11:44:41 -0800674 mState.mDrawBufferTypeMask.setIndex(getDrawbufferWriteType(0), 0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000675}
676
Corentin Wallezccab69d2017-01-27 16:57:15 -0500677Framebuffer::Framebuffer(rx::GLImplFactory *factory)
678 : mState(),
679 mImpl(factory->createFramebuffer(mState)),
Corentin Wallezccab69d2017-01-27 16:57:15 -0500680 mCachedStatus(GL_FRAMEBUFFER_UNDEFINED_OES),
681 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
682 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
683{
Jamie Madill1e5499d2017-04-05 11:22:16 -0400684 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
Brandon Jones76746f92017-11-22 11:44:41 -0800685 mState.mDrawBufferTypeMask.setIndex(getDrawbufferWriteType(0), 0);
Corentin Wallezccab69d2017-01-27 16:57:15 -0500686}
687
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000688Framebuffer::~Framebuffer()
689{
Geoff Langda88add2014-12-01 10:22:01 -0500690 SafeDelete(mImpl);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000691}
692
Jamie Madill4928b7c2017-06-20 12:57:39 -0400693void Framebuffer::onDestroy(const Context *context)
Jamie Madill6c1f6712017-02-14 19:08:04 -0500694{
Jamie Madill4928b7c2017-06-20 12:57:39 -0400695 for (auto &attachment : mState.mColorAttachments)
696 {
697 attachment.detach(context);
698 }
699 mState.mDepthAttachment.detach(context);
700 mState.mStencilAttachment.detach(context);
701 mState.mWebGLDepthAttachment.detach(context);
702 mState.mWebGLStencilAttachment.detach(context);
703 mState.mWebGLDepthStencilAttachment.detach(context);
704
Jamie Madillc564c072017-06-01 12:45:42 -0400705 mImpl->destroy(context);
Jamie Madill6c1f6712017-02-14 19:08:04 -0500706}
707
Geoff Lang70d0f492015-12-10 17:45:46 -0500708void Framebuffer::setLabel(const std::string &label)
709{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400710 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -0500711}
712
713const std::string &Framebuffer::getLabel() const
714{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400715 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -0500716}
717
Jamie Madill8693bdb2017-09-02 15:32:14 -0400718bool Framebuffer::detachTexture(const Context *context, GLuint textureId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000719{
Jamie Madill8693bdb2017-09-02 15:32:14 -0400720 return detachResourceById(context, GL_TEXTURE, textureId);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000721}
722
Jamie Madill8693bdb2017-09-02 15:32:14 -0400723bool Framebuffer::detachRenderbuffer(const Context *context, GLuint renderbufferId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000724{
Jamie Madill8693bdb2017-09-02 15:32:14 -0400725 return detachResourceById(context, GL_RENDERBUFFER, renderbufferId);
Jamie Madilld1405e52015-03-05 15:41:39 -0500726}
Jamie Madille261b442014-06-25 12:42:21 -0400727
Jamie Madill8693bdb2017-09-02 15:32:14 -0400728bool Framebuffer::detachResourceById(const Context *context, GLenum resourceType, GLuint resourceId)
Jamie Madilld1405e52015-03-05 15:41:39 -0500729{
Jamie Madill8693bdb2017-09-02 15:32:14 -0400730 bool found = false;
731
Jamie Madill362876b2016-06-16 14:46:59 -0400732 for (size_t colorIndex = 0; colorIndex < mState.mColorAttachments.size(); ++colorIndex)
Jamie Madilld1405e52015-03-05 15:41:39 -0500733 {
Jamie Madill8693bdb2017-09-02 15:32:14 -0400734 if (detachMatchingAttachment(context, &mState.mColorAttachments[colorIndex], resourceType,
735 resourceId, DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex))
736 {
737 found = true;
738 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000739 }
740
Jamie Madilla02315b2017-02-23 14:14:47 -0500741 if (context->isWebGL1())
742 {
743 const std::array<FramebufferAttachment *, 3> attachments = {
744 {&mState.mWebGLDepthStencilAttachment, &mState.mWebGLDepthAttachment,
745 &mState.mWebGLStencilAttachment}};
746 for (FramebufferAttachment *attachment : attachments)
747 {
748 if (attachment->isAttached() && attachment->type() == resourceType &&
749 attachment->id() == resourceId)
750 {
751 resetAttachment(context, attachment->getBinding());
Jamie Madill8693bdb2017-09-02 15:32:14 -0400752 found = true;
Jamie Madilla02315b2017-02-23 14:14:47 -0500753 }
754 }
755 }
756 else
757 {
Jamie Madill8693bdb2017-09-02 15:32:14 -0400758 if (detachMatchingAttachment(context, &mState.mDepthAttachment, resourceType, resourceId,
759 DIRTY_BIT_DEPTH_ATTACHMENT))
760 {
761 found = true;
762 }
763 if (detachMatchingAttachment(context, &mState.mStencilAttachment, resourceType, resourceId,
764 DIRTY_BIT_STENCIL_ATTACHMENT))
765 {
766 found = true;
767 }
Jamie Madilla02315b2017-02-23 14:14:47 -0500768 }
Jamie Madill8693bdb2017-09-02 15:32:14 -0400769
770 return found;
Jamie Madill362876b2016-06-16 14:46:59 -0400771}
772
Jamie Madill8693bdb2017-09-02 15:32:14 -0400773bool Framebuffer::detachMatchingAttachment(const Context *context,
Jamie Madill4928b7c2017-06-20 12:57:39 -0400774 FramebufferAttachment *attachment,
Jamie Madill362876b2016-06-16 14:46:59 -0400775 GLenum matchType,
776 GLuint matchId,
777 size_t dirtyBit)
778{
779 if (attachment->isAttached() && attachment->type() == matchType && attachment->id() == matchId)
780 {
Jamie Madill4928b7c2017-06-20 12:57:39 -0400781 attachment->detach(context);
Jamie Madill362876b2016-06-16 14:46:59 -0400782 mDirtyBits.set(dirtyBit);
Jamie Madill05b35b22017-10-03 09:01:44 -0400783 mState.mResourceNeedsInit.set(dirtyBit, false);
Jamie Madill8693bdb2017-09-02 15:32:14 -0400784 return true;
Jamie Madill362876b2016-06-16 14:46:59 -0400785 }
Jamie Madill8693bdb2017-09-02 15:32:14 -0400786
787 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000788}
789
Corentin Wallez37c39792015-08-20 14:19:46 -0400790const FramebufferAttachment *Framebuffer::getColorbuffer(size_t colorAttachment) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000791{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400792 return mState.getColorAttachment(colorAttachment);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000793}
794
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400795const FramebufferAttachment *Framebuffer::getDepthbuffer() const
Geoff Lang646559f2013-08-15 11:08:15 -0400796{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400797 return mState.getDepthAttachment();
Geoff Lang646559f2013-08-15 11:08:15 -0400798}
799
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400800const FramebufferAttachment *Framebuffer::getStencilbuffer() const
801{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400802 return mState.getStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400803}
804
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400805const FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
806{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400807 return mState.getDepthStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400808}
809
810const FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000811{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400812 return mState.getDepthOrStencilAttachment();
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000813}
814
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500815const FramebufferAttachment *Framebuffer::getStencilOrDepthStencilAttachment() const
816{
817 return mState.getStencilOrDepthStencilAttachment();
818}
819
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400820const FramebufferAttachment *Framebuffer::getReadColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000821{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400822 return mState.getReadAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000823}
824
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000825GLenum Framebuffer::getReadColorbufferType() const
826{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400827 const FramebufferAttachment *readAttachment = mState.getReadAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400828 return (readAttachment != nullptr ? readAttachment->type() : GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000829}
830
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400831const FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000832{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400833 return mState.getFirstColorAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000834}
835
Jamie Madill6dd06ea2017-07-19 13:47:55 -0400836const FramebufferAttachment *Framebuffer::getFirstNonNullAttachment() const
837{
838 return mState.getFirstNonNullAttachment();
839}
840
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800841const FramebufferAttachment *Framebuffer::getAttachment(const Context *context,
842 GLenum attachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000843{
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800844 return mState.getAttachment(context, attachment);
Geoff Lang55ba29c2013-07-11 16:57:53 -0400845}
846
Geoff Langa15472a2015-08-11 11:48:03 -0400847size_t Framebuffer::getDrawbufferStateCount() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000848{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400849 return mState.mDrawBufferStates.size();
Geoff Langa15472a2015-08-11 11:48:03 -0400850}
851
852GLenum Framebuffer::getDrawBufferState(size_t drawBuffer) const
853{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400854 ASSERT(drawBuffer < mState.mDrawBufferStates.size());
855 return mState.mDrawBufferStates[drawBuffer];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000856}
857
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500858const std::vector<GLenum> &Framebuffer::getDrawBufferStates() const
859{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400860 return mState.getDrawBufferStates();
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500861}
862
Geoff Lang164d54e2014-12-01 10:55:33 -0500863void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000864{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400865 auto &drawStates = mState.mDrawBufferStates;
Jamie Madilld1405e52015-03-05 15:41:39 -0500866
867 ASSERT(count <= drawStates.size());
868 std::copy(buffers, buffers + count, drawStates.begin());
869 std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500870 mDirtyBits.set(DIRTY_BIT_DRAW_BUFFERS);
Jamie Madilla4595b82017-01-11 17:36:34 -0500871
872 mState.mEnabledDrawBuffers.reset();
Brandon Jones76746f92017-11-22 11:44:41 -0800873 mState.mDrawBufferTypeMask.reset();
874
Jamie Madilla4595b82017-01-11 17:36:34 -0500875 for (size_t index = 0; index < count; ++index)
876 {
Brandon Jones76746f92017-11-22 11:44:41 -0800877 mState.mDrawBufferTypeMask.setIndex(getDrawbufferWriteType(index), index);
878
Jamie Madilla4595b82017-01-11 17:36:34 -0500879 if (drawStates[index] != GL_NONE && mState.mColorAttachments[index].isAttached())
880 {
881 mState.mEnabledDrawBuffers.set(index);
882 }
883 }
Geoff Lang9dd95802014-12-01 11:12:59 -0500884}
885
Geoff Langa15472a2015-08-11 11:48:03 -0400886const FramebufferAttachment *Framebuffer::getDrawBuffer(size_t drawBuffer) const
887{
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400888 return mState.getDrawBuffer(drawBuffer);
Geoff Langa15472a2015-08-11 11:48:03 -0400889}
890
Geoff Lange0cff192017-05-30 13:04:56 -0400891GLenum Framebuffer::getDrawbufferWriteType(size_t drawBuffer) const
892{
893 const FramebufferAttachment *attachment = mState.getDrawBuffer(drawBuffer);
894 if (attachment == nullptr)
895 {
896 return GL_NONE;
897 }
898
899 GLenum componentType = attachment->getFormat().info->componentType;
900 switch (componentType)
901 {
902 case GL_INT:
903 case GL_UNSIGNED_INT:
904 return componentType;
905
906 default:
907 return GL_FLOAT;
908 }
909}
910
Brandon Jonesc405ae72017-12-06 14:15:03 -0800911ComponentTypeMask Framebuffer::getDrawBufferTypeMask() const
Brandon Jones76746f92017-11-22 11:44:41 -0800912{
913 return mState.mDrawBufferTypeMask;
914}
915
916DrawBufferMask Framebuffer::getDrawBufferMask() const
917{
918 return mState.mEnabledDrawBuffers;
919}
920
Geoff Langa15472a2015-08-11 11:48:03 -0400921bool Framebuffer::hasEnabledDrawBuffer() const
922{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400923 for (size_t drawbufferIdx = 0; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
Geoff Langa15472a2015-08-11 11:48:03 -0400924 {
925 if (getDrawBuffer(drawbufferIdx) != nullptr)
926 {
927 return true;
928 }
929 }
930
931 return false;
932}
933
Geoff Lang9dd95802014-12-01 11:12:59 -0500934GLenum Framebuffer::getReadBufferState() const
935{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400936 return mState.mReadBufferState;
Geoff Lang9dd95802014-12-01 11:12:59 -0500937}
938
939void Framebuffer::setReadBuffer(GLenum buffer)
940{
Jamie Madillb885e572015-02-03 16:16:04 -0500941 ASSERT(buffer == GL_BACK || buffer == GL_NONE ||
942 (buffer >= GL_COLOR_ATTACHMENT0 &&
Jamie Madill48ef11b2016-04-27 15:21:52 -0400943 (buffer - GL_COLOR_ATTACHMENT0) < mState.mColorAttachments.size()));
944 mState.mReadBufferState = buffer;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500945 mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000946}
947
Corentin Wallez37c39792015-08-20 14:19:46 -0400948size_t Framebuffer::getNumColorBuffers() const
949{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400950 return mState.mColorAttachments.size();
Corentin Wallez37c39792015-08-20 14:19:46 -0400951}
952
Jamie Madill0df8fe42015-11-24 16:10:24 -0500953bool Framebuffer::hasDepth() const
954{
Jamie Madill9c335862017-07-18 11:51:38 -0400955 return mState.hasDepth();
Jamie Madill0df8fe42015-11-24 16:10:24 -0500956}
957
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000958bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000959{
Jamie Madill9c335862017-07-18 11:51:38 -0400960 return mState.hasStencil();
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000961}
962
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000963bool Framebuffer::usingExtendedDrawBuffers() const
964{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400965 for (size_t drawbufferIdx = 1; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000966 {
Geoff Langa15472a2015-08-11 11:48:03 -0400967 if (getDrawBuffer(drawbufferIdx) != nullptr)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000968 {
969 return true;
970 }
971 }
972
973 return false;
974}
975
Geoff Lang9aded172017-04-05 11:07:56 -0400976void Framebuffer::invalidateCompletenessCache()
977{
Jamie Madill2274b652018-05-31 10:56:08 -0400978 if (mState.mId != 0)
Geoff Lang9aded172017-04-05 11:07:56 -0400979 {
980 mCachedStatus.reset();
981 }
982}
983
Jamie Madill427064d2018-04-13 16:20:34 -0400984GLenum Framebuffer::checkStatus(const Context *context)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000985{
Corentin Wallezccab69d2017-01-27 16:57:15 -0500986 // The default framebuffer is always complete except when it is surfaceless in which
987 // case it is always unsupported. We return early because the default framebuffer may
988 // not be subject to the same rules as application FBOs. ie, it could have 0x0 size.
Jamie Madill2274b652018-05-31 10:56:08 -0400989 if (mState.mId == 0)
Geoff Lang528ce3c2014-12-01 10:44:07 -0500990 {
Corentin Wallezccab69d2017-01-27 16:57:15 -0500991 ASSERT(mCachedStatus.valid());
992 ASSERT(mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE ||
993 mCachedStatus.value() == GL_FRAMEBUFFER_UNDEFINED_OES);
Jamie Madill427064d2018-04-13 16:20:34 -0400994 return mCachedStatus.value();
Geoff Lang528ce3c2014-12-01 10:44:07 -0500995 }
996
Jamie Madill362876b2016-06-16 14:46:59 -0400997 if (hasAnyDirtyBit() || !mCachedStatus.valid())
998 {
Jamie Madille98b1b52018-03-08 09:47:23 -0500999 mCachedStatus = checkStatusWithGLFrontEnd(context);
1000
1001 if (mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE)
1002 {
Jamie Madill427064d2018-04-13 16:20:34 -04001003 Error err = syncState(context);
1004 if (err.isError())
1005 {
1006 context->handleError(err);
1007 return GetDefaultReturnValue<EntryPoint::CheckFramebufferStatus, GLenum>();
1008 }
Jamie Madille98b1b52018-03-08 09:47:23 -05001009 if (!mImpl->checkStatus(context))
1010 {
1011 mCachedStatus = GL_FRAMEBUFFER_UNSUPPORTED;
1012 }
1013 }
Jamie Madill362876b2016-06-16 14:46:59 -04001014 }
1015
Jamie Madill427064d2018-04-13 16:20:34 -04001016 return mCachedStatus.value();
Jamie Madill362876b2016-06-16 14:46:59 -04001017}
1018
Jamie Madille98b1b52018-03-08 09:47:23 -05001019GLenum Framebuffer::checkStatusWithGLFrontEnd(const Context *context)
Jamie Madill362876b2016-06-16 14:46:59 -04001020{
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001021 const ContextState &state = context->getContextState();
1022
Jamie Madill2274b652018-05-31 10:56:08 -04001023 ASSERT(mState.mId != 0);
Jamie Madill362876b2016-06-16 14:46:59 -04001024
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001025 bool hasAttachments = false;
1026 Optional<unsigned int> colorbufferSize;
1027 Optional<int> samples;
Geoff Lang92019432017-11-20 13:09:34 -05001028 Optional<bool> fixedSampleLocations;
JiangYizhou461d9a32017-01-04 16:37:26 +08001029 bool hasRenderbuffer = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001030
Martin Radev9bc9a322017-07-21 14:28:17 +03001031 const FramebufferAttachment *firstAttachment = getFirstNonNullAttachment();
1032
Jamie Madill48ef11b2016-04-27 15:21:52 -04001033 for (const FramebufferAttachment &colorAttachment : mState.mColorAttachments)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001034 {
Jamie Madill2d06b732015-04-20 12:53:28 -04001035 if (colorAttachment.isAttached())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001036 {
Geoff Lang9f10b772017-05-16 15:51:03 -04001037 if (!CheckAttachmentCompleteness(context, colorAttachment))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001038 {
1039 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1040 }
daniel@transgaming.com01868132010-08-24 19:21:17 +00001041
Geoff Lang677bb6f2017-04-05 12:40:40 -04001042 const InternalFormat &format = *colorAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -04001043 if (format.depthBits > 0 || format.stencilBits > 0)
1044 {
1045 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1046 }
1047
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001048 if (!CheckAttachmentSampleCompleteness(context, colorAttachment, true, &samples,
1049 &fixedSampleLocations))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001050 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001051 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001052 }
1053
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001054 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
1055 // in GLES 3.0, there is no such restriction
1056 if (state.getClientMajorVersion() < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001057 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001058 if (colorbufferSize.valid())
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001059 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001060 if (format.pixelBytes != colorbufferSize.value())
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +00001061 {
1062 return GL_FRAMEBUFFER_UNSUPPORTED;
1063 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001064 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001065 else
1066 {
1067 colorbufferSize = format.pixelBytes;
1068 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001069 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001070
Martin Radev9bc9a322017-07-21 14:28:17 +03001071 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &colorAttachment))
1072 {
1073 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
1074 }
1075
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001076 hasRenderbuffer = hasRenderbuffer || (colorAttachment.type() == GL_RENDERBUFFER);
1077 hasAttachments = true;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001078 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001079 }
1080
Jamie Madill48ef11b2016-04-27 15:21:52 -04001081 const FramebufferAttachment &depthAttachment = mState.mDepthAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -04001082 if (depthAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001083 {
Geoff Lang9f10b772017-05-16 15:51:03 -04001084 if (!CheckAttachmentCompleteness(context, depthAttachment))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001085 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001086 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001087 }
1088
Geoff Lang677bb6f2017-04-05 12:40:40 -04001089 const InternalFormat &format = *depthAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -04001090 if (format.depthBits == 0)
1091 {
1092 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001093 }
1094
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001095 if (!CheckAttachmentSampleCompleteness(context, depthAttachment, false, &samples,
1096 &fixedSampleLocations))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001097 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001098 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001099 }
Sami Väisänena797e062016-05-12 15:23:40 +03001100
Martin Radev9bc9a322017-07-21 14:28:17 +03001101 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &depthAttachment))
1102 {
1103 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
1104 }
1105
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001106 hasRenderbuffer = hasRenderbuffer || (depthAttachment.type() == GL_RENDERBUFFER);
1107 hasAttachments = true;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001108 }
1109
Jamie Madill48ef11b2016-04-27 15:21:52 -04001110 const FramebufferAttachment &stencilAttachment = mState.mStencilAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -04001111 if (stencilAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001112 {
Geoff Lang9f10b772017-05-16 15:51:03 -04001113 if (!CheckAttachmentCompleteness(context, stencilAttachment))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001114 {
1115 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1116 }
1117
Geoff Lang677bb6f2017-04-05 12:40:40 -04001118 const InternalFormat &format = *stencilAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -04001119 if (format.stencilBits == 0)
1120 {
1121 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001122 }
1123
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001124 if (!CheckAttachmentSampleCompleteness(context, stencilAttachment, false, &samples,
1125 &fixedSampleLocations))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001126 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001127 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001128 }
Corentin Wallez086d59a2016-04-29 09:06:49 -04001129
Martin Radev9bc9a322017-07-21 14:28:17 +03001130 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &stencilAttachment))
1131 {
1132 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
1133 }
1134
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001135 hasRenderbuffer = hasRenderbuffer || (stencilAttachment.type() == GL_RENDERBUFFER);
1136 hasAttachments = true;
1137 }
1138
1139 // Starting from ES 3.0 stencil and depth, if present, should be the same image
1140 if (state.getClientMajorVersion() >= 3 && depthAttachment.isAttached() &&
1141 stencilAttachment.isAttached() && stencilAttachment != depthAttachment)
1142 {
1143 return GL_FRAMEBUFFER_UNSUPPORTED;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001144 }
1145
Jamie Madilla02315b2017-02-23 14:14:47 -05001146 // Special additional validation for WebGL 1 DEPTH/STENCIL/DEPTH_STENCIL.
1147 if (state.isWebGL1())
1148 {
1149 if (!mState.mWebGLDepthStencilConsistent)
1150 {
1151 return GL_FRAMEBUFFER_UNSUPPORTED;
1152 }
1153
1154 if (mState.mWebGLDepthStencilAttachment.isAttached())
1155 {
1156 if (mState.mWebGLDepthStencilAttachment.getDepthSize() == 0 ||
1157 mState.mWebGLDepthStencilAttachment.getStencilSize() == 0)
1158 {
1159 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1160 }
Martin Radev9bc9a322017-07-21 14:28:17 +03001161
1162 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment,
1163 &mState.mWebGLDepthStencilAttachment))
1164 {
1165 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
1166 }
Jamie Madilla02315b2017-02-23 14:14:47 -05001167 }
1168 else if (mState.mStencilAttachment.isAttached() &&
1169 mState.mStencilAttachment.getDepthSize() > 0)
1170 {
1171 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1172 }
1173 else if (mState.mDepthAttachment.isAttached() &&
1174 mState.mDepthAttachment.getStencilSize() > 0)
1175 {
1176 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1177 }
1178 }
1179
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001180 // ES3.1(section 9.4) requires that if no image is attached to the framebuffer, and either the
1181 // value of the framebuffer's FRAMEBUFFER_DEFAULT_WIDTH or FRAMEBUFFER_DEFAULT_HEIGHT parameters
1182 // is zero, the framebuffer is considered incomplete.
JiangYizhou461d9a32017-01-04 16:37:26 +08001183 GLint defaultWidth = mState.getDefaultWidth();
1184 GLint defaultHeight = mState.getDefaultHeight();
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001185 if (!hasAttachments && (defaultWidth == 0 || defaultHeight == 0))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001186 {
1187 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001188 }
1189
Geoff Langa0e0aeb2017-04-12 15:06:29 -04001190 // In ES 2.0 and WebGL, all color attachments must have the same width and height.
Jamie Madillcc86d642015-11-24 13:00:07 -05001191 // In ES 3.0, there is no such restriction.
Geoff Langa0e0aeb2017-04-12 15:06:29 -04001192 if ((state.getClientMajorVersion() < 3 || state.getExtensions().webglCompatibility) &&
1193 !mState.attachmentsHaveSameDimensions())
Jamie Madillcc86d642015-11-24 13:00:07 -05001194 {
1195 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
1196 }
1197
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001198 // ES3.1(section 9.4) requires that if the attached images are a mix of renderbuffers and
1199 // textures, the value of TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all attached textures.
JiangYizhou461d9a32017-01-04 16:37:26 +08001200 if (fixedSampleLocations.valid() && hasRenderbuffer && !fixedSampleLocations.value())
1201 {
1202 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1203 }
1204
Kenneth Russellce8602a2017-10-03 18:23:08 -07001205 // The WebGL conformance tests implicitly define that all framebuffer
1206 // attachments must be unique. For example, the same level of a texture can
1207 // not be attached to two different color attachments.
1208 if (state.getExtensions().webglCompatibility)
1209 {
1210 if (!mState.colorAttachmentsAreUniqueImages())
1211 {
1212 return GL_FRAMEBUFFER_UNSUPPORTED;
1213 }
1214 }
1215
Jamie Madillcc86d642015-11-24 13:00:07 -05001216 return GL_FRAMEBUFFER_COMPLETE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001217}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001218
Jamie Madill4928b7c2017-06-20 12:57:39 -04001219Error Framebuffer::discard(const Context *context, size_t count, const GLenum *attachments)
Austin Kinross08332632015-05-05 13:35:47 -07001220{
Jamie Madill05b35b22017-10-03 09:01:44 -04001221 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1222 // can be no-ops, so we should probably do that to ensure consistency.
1223 // TODO(jmadill): WebGL behaviour, and robust resource init behaviour without WebGL.
1224
Jamie Madill4928b7c2017-06-20 12:57:39 -04001225 return mImpl->discard(context, count, attachments);
Austin Kinross08332632015-05-05 13:35:47 -07001226}
1227
Jamie Madill4928b7c2017-06-20 12:57:39 -04001228Error Framebuffer::invalidate(const Context *context, size_t count, const GLenum *attachments)
Jamie Madill2d96b9e2014-08-29 15:46:47 -04001229{
Jamie Madill05b35b22017-10-03 09:01:44 -04001230 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1231 // can be no-ops, so we should probably do that to ensure consistency.
1232 // TODO(jmadill): WebGL behaviour, and robust resource init behaviour without WebGL.
1233
Jamie Madill4928b7c2017-06-20 12:57:39 -04001234 return mImpl->invalidate(context, count, attachments);
Jamie Madill2d96b9e2014-08-29 15:46:47 -04001235}
1236
Jamie Madill05b35b22017-10-03 09:01:44 -04001237bool Framebuffer::partialClearNeedsInit(const Context *context,
1238 bool color,
1239 bool depth,
1240 bool stencil)
1241{
1242 const auto &glState = context->getGLState();
1243
1244 if (!glState.isRobustResourceInitEnabled())
1245 {
1246 return false;
1247 }
1248
1249 // Scissors can affect clearing.
1250 // TODO(jmadill): Check for complete scissor overlap.
1251 if (glState.isScissorTestEnabled())
1252 {
1253 return true;
1254 }
1255
1256 // If colors masked, we must clear before we clear. Do a simple check.
1257 // TODO(jmadill): Filter out unused color channels from the test.
1258 if (color)
1259 {
1260 const auto &blend = glState.getBlendState();
1261 if (!(blend.colorMaskRed && blend.colorMaskGreen && blend.colorMaskBlue &&
1262 blend.colorMaskAlpha))
1263 {
1264 return true;
1265 }
1266 }
1267
1268 const auto &depthStencil = glState.getDepthStencilState();
1269 ASSERT(depthStencil.stencilBackMask == depthStencil.stencilMask);
1270 if (stencil && depthStencil.stencilMask != depthStencil.stencilWritemask)
1271 {
1272 return true;
1273 }
1274
1275 return false;
1276}
1277
Jamie Madill4928b7c2017-06-20 12:57:39 -04001278Error Framebuffer::invalidateSub(const Context *context,
1279 size_t count,
1280 const GLenum *attachments,
Jamie Madilld4442552018-02-27 22:03:47 -05001281 const Rectangle &area)
Jamie Madill400a4412014-08-29 15:46:45 -04001282{
Jamie Madill05b35b22017-10-03 09:01:44 -04001283 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1284 // can be no-ops, so we should probably do that to ensure consistency.
1285 // TODO(jmadill): Make a invalidate no-op in WebGL 2.0.
1286
Jamie Madill4928b7c2017-06-20 12:57:39 -04001287 return mImpl->invalidateSub(context, count, attachments, area);
Jamie Madill400a4412014-08-29 15:46:45 -04001288}
1289
Jamie Madilld4442552018-02-27 22:03:47 -05001290Error Framebuffer::clear(const Context *context, GLbitfield mask)
Geoff Langb04dc822014-12-01 12:02:02 -05001291{
Jamie Madill05b35b22017-10-03 09:01:44 -04001292 const auto &glState = context->getGLState();
1293 if (glState.isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -05001294 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001295 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001296 }
1297
Jamie Madill05b35b22017-10-03 09:01:44 -04001298 ANGLE_TRY(mImpl->clear(context, mask));
1299
Jamie Madill05b35b22017-10-03 09:01:44 -04001300 return NoError();
Geoff Langb04dc822014-12-01 12:02:02 -05001301}
1302
Jamie Madilld4442552018-02-27 22:03:47 -05001303Error Framebuffer::clearBufferfv(const Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001304 GLenum buffer,
1305 GLint drawbuffer,
1306 const GLfloat *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001307{
Jamie Madill05b35b22017-10-03 09:01:44 -04001308 if (context->getGLState().isRasterizerDiscardEnabled() ||
1309 IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001310 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001311 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001312 }
1313
Jamie Madill05b35b22017-10-03 09:01:44 -04001314 ANGLE_TRY(mImpl->clearBufferfv(context, buffer, drawbuffer, values));
1315
Jamie Madill05b35b22017-10-03 09:01:44 -04001316 return NoError();
Geoff Langb04dc822014-12-01 12:02:02 -05001317}
1318
Jamie Madilld4442552018-02-27 22:03:47 -05001319Error Framebuffer::clearBufferuiv(const Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001320 GLenum buffer,
1321 GLint drawbuffer,
1322 const GLuint *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001323{
Jamie Madill05b35b22017-10-03 09:01:44 -04001324 if (context->getGLState().isRasterizerDiscardEnabled() ||
1325 IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001326 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001327 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001328 }
1329
Jamie Madill05b35b22017-10-03 09:01:44 -04001330 ANGLE_TRY(mImpl->clearBufferuiv(context, buffer, drawbuffer, values));
1331
Jamie Madill05b35b22017-10-03 09:01:44 -04001332 return NoError();
Geoff Langb04dc822014-12-01 12:02:02 -05001333}
1334
Jamie Madilld4442552018-02-27 22:03:47 -05001335Error Framebuffer::clearBufferiv(const Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001336 GLenum buffer,
1337 GLint drawbuffer,
1338 const GLint *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001339{
Jamie Madill05b35b22017-10-03 09:01:44 -04001340 if (context->getGLState().isRasterizerDiscardEnabled() ||
1341 IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001342 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001343 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001344 }
1345
Jamie Madill05b35b22017-10-03 09:01:44 -04001346 ANGLE_TRY(mImpl->clearBufferiv(context, buffer, drawbuffer, values));
1347
Jamie Madill05b35b22017-10-03 09:01:44 -04001348 return NoError();
Geoff Langb04dc822014-12-01 12:02:02 -05001349}
1350
Jamie Madilld4442552018-02-27 22:03:47 -05001351Error Framebuffer::clearBufferfi(const Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001352 GLenum buffer,
1353 GLint drawbuffer,
1354 GLfloat depth,
1355 GLint stencil)
Geoff Langb04dc822014-12-01 12:02:02 -05001356{
Jamie Madill05b35b22017-10-03 09:01:44 -04001357 if (context->getGLState().isRasterizerDiscardEnabled() ||
1358 IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001359 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001360 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001361 }
1362
Jamie Madill05b35b22017-10-03 09:01:44 -04001363 ANGLE_TRY(mImpl->clearBufferfi(context, buffer, drawbuffer, depth, stencil));
1364
Jamie Madill05b35b22017-10-03 09:01:44 -04001365 return NoError();
Geoff Langb04dc822014-12-01 12:02:02 -05001366}
1367
Jamie Madill690c8eb2018-03-12 15:20:03 -04001368Error Framebuffer::getImplementationColorReadFormat(const Context *context, GLenum *formatOut)
Geoff Langbce529e2014-12-01 12:48:41 -05001369{
Jamie Madill690c8eb2018-03-12 15:20:03 -04001370 ANGLE_TRY(syncState(context));
1371 *formatOut = mImpl->getImplementationColorReadFormat(context);
1372 return NoError();
Geoff Langbce529e2014-12-01 12:48:41 -05001373}
1374
Jamie Madill690c8eb2018-03-12 15:20:03 -04001375Error Framebuffer::getImplementationColorReadType(const Context *context, GLenum *typeOut)
Geoff Langbce529e2014-12-01 12:48:41 -05001376{
Jamie Madill690c8eb2018-03-12 15:20:03 -04001377 ANGLE_TRY(syncState(context));
1378 *typeOut = mImpl->getImplementationColorReadType(context);
1379 return NoError();
Geoff Langbce529e2014-12-01 12:48:41 -05001380}
1381
Jamie Madilld4442552018-02-27 22:03:47 -05001382Error Framebuffer::readPixels(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001383 const Rectangle &area,
Jamie Madill1b94d432015-08-07 13:23:23 -04001384 GLenum format,
1385 GLenum type,
Jamie Madill05b35b22017-10-03 09:01:44 -04001386 void *pixels)
Geoff Langbce529e2014-12-01 12:48:41 -05001387{
Jamie Madill05b35b22017-10-03 09:01:44 -04001388 ANGLE_TRY(ensureReadAttachmentInitialized(context, GL_COLOR_BUFFER_BIT));
Jamie Madill362876b2016-06-16 14:46:59 -04001389 ANGLE_TRY(mImpl->readPixels(context, area, format, type, pixels));
Geoff Lang520c4ae2015-05-05 13:12:36 -04001390
Jamie Madilld4442552018-02-27 22:03:47 -05001391 Buffer *unpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Lang520c4ae2015-05-05 13:12:36 -04001392 if (unpackBuffer)
1393 {
Jamie Madill09463932018-04-04 05:26:59 -04001394 unpackBuffer->onPixelPack(context);
Geoff Lang520c4ae2015-05-05 13:12:36 -04001395 }
1396
Jamie Madill362876b2016-06-16 14:46:59 -04001397 return NoError();
Geoff Langbce529e2014-12-01 12:48:41 -05001398}
1399
Jamie Madilld4442552018-02-27 22:03:47 -05001400Error Framebuffer::blit(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001401 const Rectangle &sourceArea,
1402 const Rectangle &destArea,
Geoff Lang242468f2015-09-24 14:15:41 -04001403 GLbitfield mask,
Jamie Madill8415b5f2016-04-26 13:41:39 -04001404 GLenum filter)
Geoff Lang54bd5a42014-12-01 12:51:04 -05001405{
He Yunchao6be602d2016-12-22 14:33:07 +08001406 GLbitfield blitMask = mask;
1407
1408 // Note that blitting is called against draw framebuffer.
1409 // See the code in gl::Context::blitFramebuffer.
1410 if ((mask & GL_COLOR_BUFFER_BIT) && !hasEnabledDrawBuffer())
1411 {
1412 blitMask &= ~GL_COLOR_BUFFER_BIT;
1413 }
1414
1415 if ((mask & GL_STENCIL_BUFFER_BIT) && mState.getStencilAttachment() == nullptr)
1416 {
1417 blitMask &= ~GL_STENCIL_BUFFER_BIT;
1418 }
1419
1420 if ((mask & GL_DEPTH_BUFFER_BIT) && mState.getDepthAttachment() == nullptr)
1421 {
1422 blitMask &= ~GL_DEPTH_BUFFER_BIT;
1423 }
1424
1425 if (!blitMask)
1426 {
1427 return NoError();
1428 }
1429
Jamie Madill05b35b22017-10-03 09:01:44 -04001430 auto *sourceFBO = context->getGLState().getReadFramebuffer();
1431 ANGLE_TRY(sourceFBO->ensureReadAttachmentInitialized(context, blitMask));
1432
1433 // TODO(jmadill): Only clear if not the full FBO dimensions, and only specified bitmask.
1434 ANGLE_TRY(ensureDrawAttachmentsInitialized(context));
1435
He Yunchao6be602d2016-12-22 14:33:07 +08001436 return mImpl->blit(context, sourceArea, destArea, blitMask, filter);
Geoff Lang54bd5a42014-12-01 12:51:04 -05001437}
1438
Jamie Madill427064d2018-04-13 16:20:34 -04001439int Framebuffer::getSamples(const Context *context)
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001440{
Jamie Madill427064d2018-04-13 16:20:34 -04001441 return (isComplete(context) ? getCachedSamples(context) : 0);
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001442}
1443
Jamie Madill9c335862017-07-18 11:51:38 -04001444int Framebuffer::getCachedSamples(const Context *context)
1445{
Jamie Madill5b772312018-03-08 20:28:32 -05001446 ASSERT(mCachedStatus.valid() && mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE);
1447
Jamie Madill9c335862017-07-18 11:51:38 -04001448 // For a complete framebuffer, all attachments must have the same sample count.
1449 // In this case return the first nonzero sample size.
1450 const auto *firstNonNullAttachment = mState.getFirstNonNullAttachment();
1451 if (firstNonNullAttachment)
1452 {
1453 ASSERT(firstNonNullAttachment->isAttached());
1454 return firstNonNullAttachment->getSamples();
1455 }
1456
1457 // No attachments found.
1458 return 0;
1459}
1460
Geoff Lang13455072018-05-09 11:24:43 -04001461Error Framebuffer::getSamplePosition(const Context *context, size_t index, GLfloat *xy) const
Corentin Wallezccab69d2017-01-27 16:57:15 -05001462{
Geoff Lang13455072018-05-09 11:24:43 -04001463 ANGLE_TRY(mImpl->getSamplePosition(context, index, xy));
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001464 return NoError();
Corentin Wallezccab69d2017-01-27 16:57:15 -05001465}
1466
Jamie Madille261b442014-06-25 12:42:21 -04001467bool Framebuffer::hasValidDepthStencil() const
1468{
Jamie Madill48ef11b2016-04-27 15:21:52 -04001469 return mState.getDepthStencilAttachment() != nullptr;
Jamie Madille261b442014-06-25 12:42:21 -04001470}
1471
Jamie Madilla02315b2017-02-23 14:14:47 -05001472void Framebuffer::setAttachment(const Context *context,
1473 GLenum type,
Jamie Madill2d06b732015-04-20 12:53:28 -04001474 GLenum binding,
1475 const ImageIndex &textureIndex,
1476 FramebufferAttachmentObject *resource)
Geoff Langab75a052014-10-15 12:56:37 -04001477{
Martin Radev5dae57b2017-07-14 16:15:55 +03001478 setAttachment(context, type, binding, textureIndex, resource,
1479 FramebufferAttachment::kDefaultNumViews,
1480 FramebufferAttachment::kDefaultBaseViewIndex,
1481 FramebufferAttachment::kDefaultMultiviewLayout,
1482 FramebufferAttachment::kDefaultViewportOffsets);
1483}
1484
1485void Framebuffer::setAttachment(const Context *context,
1486 GLenum type,
1487 GLenum binding,
1488 const ImageIndex &textureIndex,
1489 FramebufferAttachmentObject *resource,
1490 GLsizei numViews,
1491 GLuint baseViewIndex,
1492 GLenum multiviewLayout,
1493 const GLint *viewportOffsets)
1494{
Jamie Madilla02315b2017-02-23 14:14:47 -05001495 // Context may be null in unit tests.
1496 if (!context || !context->isWebGL1())
1497 {
Martin Radev5dae57b2017-07-14 16:15:55 +03001498 setAttachmentImpl(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
1499 multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001500 return;
1501 }
1502
1503 switch (binding)
1504 {
1505 case GL_DEPTH_STENCIL:
1506 case GL_DEPTH_STENCIL_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001507 mState.mWebGLDepthStencilAttachment.attach(context, type, binding, textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001508 resource, numViews, baseViewIndex,
1509 multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001510 break;
1511 case GL_DEPTH:
1512 case GL_DEPTH_ATTACHMENT:
Martin Radev5dae57b2017-07-14 16:15:55 +03001513 mState.mWebGLDepthAttachment.attach(context, type, binding, textureIndex, resource,
1514 numViews, baseViewIndex, multiviewLayout,
1515 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001516 break;
1517 case GL_STENCIL:
1518 case GL_STENCIL_ATTACHMENT:
Martin Radev5dae57b2017-07-14 16:15:55 +03001519 mState.mWebGLStencilAttachment.attach(context, type, binding, textureIndex, resource,
1520 numViews, baseViewIndex, multiviewLayout,
1521 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001522 break;
1523 default:
Martin Radev5dae57b2017-07-14 16:15:55 +03001524 setAttachmentImpl(context, type, binding, textureIndex, resource, numViews,
1525 baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001526 return;
1527 }
1528
Martin Radev5dae57b2017-07-14 16:15:55 +03001529 commitWebGL1DepthStencilIfConsistent(context, numViews, baseViewIndex, multiviewLayout,
1530 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001531}
1532
Martin Radev82ef7742017-08-08 17:44:58 +03001533void Framebuffer::setAttachmentMultiviewLayered(const Context *context,
1534 GLenum type,
1535 GLenum binding,
1536 const ImageIndex &textureIndex,
1537 FramebufferAttachmentObject *resource,
1538 GLsizei numViews,
1539 GLint baseViewIndex)
1540{
1541 setAttachment(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
1542 GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE,
1543 FramebufferAttachment::kDefaultViewportOffsets);
1544}
1545
Martin Radev5dae57b2017-07-14 16:15:55 +03001546void Framebuffer::setAttachmentMultiviewSideBySide(const Context *context,
1547 GLenum type,
1548 GLenum binding,
1549 const ImageIndex &textureIndex,
1550 FramebufferAttachmentObject *resource,
1551 GLsizei numViews,
1552 const GLint *viewportOffsets)
1553{
1554 setAttachment(context, type, binding, textureIndex, resource, numViews,
1555 FramebufferAttachment::kDefaultBaseViewIndex,
1556 GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, viewportOffsets);
1557}
1558
1559void Framebuffer::commitWebGL1DepthStencilIfConsistent(const Context *context,
1560 GLsizei numViews,
1561 GLuint baseViewIndex,
1562 GLenum multiviewLayout,
1563 const GLint *viewportOffsets)
Jamie Madilla02315b2017-02-23 14:14:47 -05001564{
1565 int count = 0;
1566
1567 std::array<FramebufferAttachment *, 3> attachments = {{&mState.mWebGLDepthStencilAttachment,
1568 &mState.mWebGLDepthAttachment,
1569 &mState.mWebGLStencilAttachment}};
1570 for (FramebufferAttachment *attachment : attachments)
1571 {
1572 if (attachment->isAttached())
1573 {
1574 count++;
1575 }
1576 }
1577
1578 mState.mWebGLDepthStencilConsistent = (count <= 1);
1579 if (!mState.mWebGLDepthStencilConsistent)
1580 {
1581 // Inconsistent.
1582 return;
1583 }
1584
Geoff Lange466c552017-03-17 15:24:12 -04001585 auto getImageIndexIfTextureAttachment = [](const FramebufferAttachment &attachment) {
1586 if (attachment.type() == GL_TEXTURE)
1587 {
1588 return attachment.getTextureImageIndex();
1589 }
1590 else
1591 {
Jamie Madillcc129372018-04-12 09:13:18 -04001592 return ImageIndex();
Geoff Lange466c552017-03-17 15:24:12 -04001593 }
1594 };
1595
Jamie Madilla02315b2017-02-23 14:14:47 -05001596 if (mState.mWebGLDepthAttachment.isAttached())
1597 {
1598 const auto &depth = mState.mWebGLDepthAttachment;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001599 setAttachmentImpl(context, depth.type(), GL_DEPTH_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001600 getImageIndexIfTextureAttachment(depth), depth.getResource(), numViews,
1601 baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madillcc129372018-04-12 09:13:18 -04001602 setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex(), nullptr, numViews,
1603 baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001604 }
1605 else if (mState.mWebGLStencilAttachment.isAttached())
1606 {
1607 const auto &stencil = mState.mWebGLStencilAttachment;
Jamie Madillcc129372018-04-12 09:13:18 -04001608 setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex(), nullptr, numViews,
1609 baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001610 setAttachmentImpl(context, stencil.type(), GL_STENCIL_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001611 getImageIndexIfTextureAttachment(stencil), stencil.getResource(),
1612 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001613 }
1614 else if (mState.mWebGLDepthStencilAttachment.isAttached())
1615 {
1616 const auto &depthStencil = mState.mWebGLDepthStencilAttachment;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001617 setAttachmentImpl(context, depthStencil.type(), GL_DEPTH_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 Madill4928b7c2017-06-20 12:57:39 -04001621 setAttachmentImpl(context, depthStencil.type(), GL_STENCIL_ATTACHMENT,
Geoff Lange466c552017-03-17 15:24:12 -04001622 getImageIndexIfTextureAttachment(depthStencil),
Martin Radev5dae57b2017-07-14 16:15:55 +03001623 depthStencil.getResource(), numViews, baseViewIndex, multiviewLayout,
1624 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001625 }
1626 else
1627 {
Jamie Madillcc129372018-04-12 09:13:18 -04001628 setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex(), nullptr, numViews,
1629 baseViewIndex, multiviewLayout, viewportOffsets);
1630 setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex(), nullptr, numViews,
1631 baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001632 }
1633}
1634
Jamie Madill4928b7c2017-06-20 12:57:39 -04001635void Framebuffer::setAttachmentImpl(const Context *context,
1636 GLenum type,
Jamie Madilla02315b2017-02-23 14:14:47 -05001637 GLenum binding,
1638 const ImageIndex &textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001639 FramebufferAttachmentObject *resource,
1640 GLsizei numViews,
1641 GLuint baseViewIndex,
1642 GLenum multiviewLayout,
1643 const GLint *viewportOffsets)
Jamie Madilla02315b2017-02-23 14:14:47 -05001644{
Jamie Madilla02315b2017-02-23 14:14:47 -05001645 switch (binding)
1646 {
Jamie Madillb8126692017-04-05 11:22:17 -04001647 case GL_DEPTH_STENCIL:
1648 case GL_DEPTH_STENCIL_ATTACHMENT:
1649 {
1650 // ensure this is a legitimate depth+stencil format
1651 FramebufferAttachmentObject *attachmentObj = resource;
1652 if (resource)
1653 {
Jamie Madill4fd95d52017-04-05 11:22:18 -04001654 const Format &format = resource->getAttachmentFormat(binding, textureIndex);
Jamie Madillb8126692017-04-05 11:22:17 -04001655 if (format.info->depthBits == 0 || format.info->stencilBits == 0)
1656 {
1657 // Attaching nullptr detaches the current attachment.
1658 attachmentObj = nullptr;
1659 }
1660 }
1661
Jamie Madill4928b7c2017-06-20 12:57:39 -04001662 updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
Jamie Madillb8126692017-04-05 11:22:17 -04001663 &mDirtyDepthAttachmentBinding, type, binding, textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001664 attachmentObj, numViews, baseViewIndex, multiviewLayout,
1665 viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001666 updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
Jamie Madillb8126692017-04-05 11:22:17 -04001667 &mDirtyStencilAttachmentBinding, type, binding, textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001668 attachmentObj, numViews, baseViewIndex, multiviewLayout,
1669 viewportOffsets);
Jamie Madill42975642017-10-12 12:31:51 -04001670 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001671 }
1672
Jamie Madilla02315b2017-02-23 14:14:47 -05001673 case GL_DEPTH:
1674 case GL_DEPTH_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001675 updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001676 &mDirtyDepthAttachmentBinding, type, binding, textureIndex, resource,
1677 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madill2d06b732015-04-20 12:53:28 -04001678 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001679
Jamie Madilla02315b2017-02-23 14:14:47 -05001680 case GL_STENCIL:
1681 case GL_STENCIL_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001682 updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001683 &mDirtyStencilAttachmentBinding, type, binding, textureIndex, resource,
1684 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001685 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001686
Jamie Madilla02315b2017-02-23 14:14:47 -05001687 case GL_BACK:
Geoff Lang8170eab2017-09-21 13:59:04 -04001688 updateAttachment(context, &mState.mColorAttachments[0], DIRTY_BIT_COLOR_ATTACHMENT_0,
1689 &mDirtyColorAttachmentBindings[0], type, binding, textureIndex,
1690 resource, numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001691 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001692
Jamie Madilla02315b2017-02-23 14:14:47 -05001693 default:
1694 {
1695 size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
1696 ASSERT(colorIndex < mState.mColorAttachments.size());
Jamie Madillb8126692017-04-05 11:22:17 -04001697 size_t dirtyBit = DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001698 updateAttachment(context, &mState.mColorAttachments[colorIndex], dirtyBit,
Jamie Madillb8126692017-04-05 11:22:17 -04001699 &mDirtyColorAttachmentBindings[colorIndex], type, binding,
Martin Radev5dae57b2017-07-14 16:15:55 +03001700 textureIndex, resource, numViews, baseViewIndex, multiviewLayout,
1701 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001702
Corentin Walleze7557742017-06-01 13:09:57 -04001703 // TODO(jmadill): ASSERT instead of checking the attachment exists in
1704 // formsRenderingFeedbackLoopWith
Jamie Madilla02315b2017-02-23 14:14:47 -05001705 bool enabled = (type != GL_NONE && getDrawBufferState(colorIndex) != GL_NONE);
1706 mState.mEnabledDrawBuffers.set(colorIndex, enabled);
Brandon Jones76746f92017-11-22 11:44:41 -08001707 mState.mDrawBufferTypeMask.setIndex(getDrawbufferWriteType(colorIndex), colorIndex);
Jamie Madill2d06b732015-04-20 12:53:28 -04001708 }
Jamie Madilla02315b2017-02-23 14:14:47 -05001709 break;
Geoff Langab75a052014-10-15 12:56:37 -04001710 }
Jamie Madill42975642017-10-12 12:31:51 -04001711
1712 mAttachedTextures.reset();
Geoff Langab75a052014-10-15 12:56:37 -04001713}
1714
Jamie Madill4928b7c2017-06-20 12:57:39 -04001715void Framebuffer::updateAttachment(const Context *context,
1716 FramebufferAttachment *attachment,
Jamie Madillb8126692017-04-05 11:22:17 -04001717 size_t dirtyBit,
Jamie Madilld4442552018-02-27 22:03:47 -05001718 angle::ObserverBinding *onDirtyBinding,
Jamie Madillb8126692017-04-05 11:22:17 -04001719 GLenum type,
1720 GLenum binding,
1721 const ImageIndex &textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001722 FramebufferAttachmentObject *resource,
1723 GLsizei numViews,
1724 GLuint baseViewIndex,
1725 GLenum multiviewLayout,
1726 const GLint *viewportOffsets)
Jamie Madillb8126692017-04-05 11:22:17 -04001727{
Martin Radev5dae57b2017-07-14 16:15:55 +03001728 attachment->attach(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
1729 multiviewLayout, viewportOffsets);
Jamie Madillb8126692017-04-05 11:22:17 -04001730 mDirtyBits.set(dirtyBit);
Jamie Madill05b35b22017-10-03 09:01:44 -04001731 mState.mResourceNeedsInit.set(dirtyBit, attachment->initState() == InitState::MayNeedInit);
Jamie Madill888081d2018-02-27 00:24:46 -05001732 onDirtyBinding->bind(resource ? resource->getSubject() : nullptr);
Jamie Madille98b1b52018-03-08 09:47:23 -05001733
1734 invalidateCompletenessCache();
Jamie Madillb8126692017-04-05 11:22:17 -04001735}
1736
Jamie Madilla02315b2017-02-23 14:14:47 -05001737void Framebuffer::resetAttachment(const Context *context, GLenum binding)
Jamie Madill2d06b732015-04-20 12:53:28 -04001738{
Jamie Madillcc129372018-04-12 09:13:18 -04001739 setAttachment(context, GL_NONE, binding, ImageIndex(), nullptr);
Jamie Madill2d06b732015-04-20 12:53:28 -04001740}
1741
Jamie Madill19fa1c62018-03-08 09:47:21 -05001742Error Framebuffer::syncState(const Context *context)
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001743{
1744 if (mDirtyBits.any())
1745 {
Jamie Madill888081d2018-02-27 00:24:46 -05001746 mDirtyBitsGuard = mDirtyBits;
Jamie Madill19fa1c62018-03-08 09:47:21 -05001747 ANGLE_TRY(mImpl->syncState(context, mDirtyBits));
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001748 mDirtyBits.reset();
Jamie Madill888081d2018-02-27 00:24:46 -05001749 mDirtyBitsGuard.reset();
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001750 }
Jamie Madill19fa1c62018-03-08 09:47:21 -05001751 return NoError();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001752}
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001753
Jamie Madilld4442552018-02-27 22:03:47 -05001754void Framebuffer::onSubjectStateChange(const Context *context,
1755 angle::SubjectIndex index,
1756 angle::SubjectMessage message)
Jamie Madill51f40ec2016-06-15 14:06:00 -04001757{
Jamie Madill888081d2018-02-27 00:24:46 -05001758 if (message == angle::SubjectMessage::DEPENDENT_DIRTY_BITS)
1759 {
1760 ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(index));
1761 mDirtyBits.set(index);
1762 context->getGLState().setFramebufferDirty(this);
1763 return;
1764 }
1765
Geoff Lang8170eab2017-09-21 13:59:04 -04001766 // Only reset the cached status if this is not the default framebuffer. The default framebuffer
1767 // will still use this channel to mark itself dirty.
Jamie Madill2274b652018-05-31 10:56:08 -04001768 if (mState.mId != 0)
Geoff Lang8170eab2017-09-21 13:59:04 -04001769 {
1770 // TOOD(jmadill): Make this only update individual attachments to do less work.
1771 mCachedStatus.reset();
1772 }
Jamie Madill05b35b22017-10-03 09:01:44 -04001773
Jamie Madilld4442552018-02-27 22:03:47 -05001774 FramebufferAttachment *attachment = getAttachmentFromSubjectIndex(index);
1775
Jamie Madill05b35b22017-10-03 09:01:44 -04001776 // Mark the appropriate init flag.
Jamie Madilld4442552018-02-27 22:03:47 -05001777 mState.mResourceNeedsInit.set(index, attachment->initState() == InitState::MayNeedInit);
1778}
1779
1780FramebufferAttachment *Framebuffer::getAttachmentFromSubjectIndex(angle::SubjectIndex index)
1781{
1782 switch (index)
1783 {
1784 case DIRTY_BIT_DEPTH_ATTACHMENT:
1785 return &mState.mDepthAttachment;
1786 case DIRTY_BIT_STENCIL_ATTACHMENT:
1787 return &mState.mStencilAttachment;
1788 default:
1789 size_t colorIndex = (index - DIRTY_BIT_COLOR_ATTACHMENT_0);
1790 ASSERT(colorIndex < mState.mColorAttachments.size());
1791 return &mState.mColorAttachments[colorIndex];
1792 }
Jamie Madill51f40ec2016-06-15 14:06:00 -04001793}
1794
Jamie Madill427064d2018-04-13 16:20:34 -04001795bool Framebuffer::isComplete(const Context *context)
Jamie Madill51f40ec2016-06-15 14:06:00 -04001796{
Jamie Madill427064d2018-04-13 16:20:34 -04001797 return (checkStatus(context) == GL_FRAMEBUFFER_COMPLETE);
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001798}
1799
Jamie Madilla4595b82017-01-11 17:36:34 -05001800bool Framebuffer::formsRenderingFeedbackLoopWith(const State &state) const
1801{
1802 const Program *program = state.getProgram();
1803
1804 // TODO(jmadill): Default framebuffer feedback loops.
Jamie Madill2274b652018-05-31 10:56:08 -04001805 if (mState.mId == 0)
Jamie Madilla4595b82017-01-11 17:36:34 -05001806 {
1807 return false;
1808 }
1809
1810 // The bitset will skip inactive draw buffers.
Jamie Madill6de51852017-04-12 09:53:01 -04001811 for (size_t drawIndex : mState.mEnabledDrawBuffers)
Jamie Madilla4595b82017-01-11 17:36:34 -05001812 {
Jamie Madill5aca1932017-07-21 12:22:01 -04001813 const FramebufferAttachment &attachment = mState.mColorAttachments[drawIndex];
1814 ASSERT(attachment.isAttached());
1815 if (attachment.type() == GL_TEXTURE)
Jamie Madilla4595b82017-01-11 17:36:34 -05001816 {
1817 // Validate the feedback loop.
Jamie Madill5aca1932017-07-21 12:22:01 -04001818 if (program->samplesFromTexture(state, attachment.id()))
Jamie Madilla4595b82017-01-11 17:36:34 -05001819 {
1820 return true;
1821 }
1822 }
1823 }
1824
Jamie Madill1d37bc52017-02-02 19:59:58 -05001825 // Validate depth-stencil feedback loop.
1826 const auto &dsState = state.getDepthStencilState();
1827
1828 // We can skip the feedback loop checks if depth/stencil is masked out or disabled.
1829 const FramebufferAttachment *depth = getDepthbuffer();
1830 if (depth && depth->type() == GL_TEXTURE && dsState.depthTest && dsState.depthMask)
1831 {
1832 if (program->samplesFromTexture(state, depth->id()))
1833 {
1834 return true;
1835 }
1836 }
1837
Jamie Madill1d37bc52017-02-02 19:59:58 -05001838 const FramebufferAttachment *stencil = getStencilbuffer();
Ken Russellb9f92502018-01-27 19:00:26 -08001839 if (dsState.stencilTest && stencil)
Jamie Madill1d37bc52017-02-02 19:59:58 -05001840 {
Ken Russellb9f92502018-01-27 19:00:26 -08001841 GLuint stencilSize = stencil->getStencilSize();
1842 ASSERT(stencilSize <= 8);
1843 GLuint maxStencilValue = (1 << stencilSize) - 1;
1844 // We assume the front and back masks are the same for WebGL.
1845 ASSERT((dsState.stencilBackWritemask & maxStencilValue) ==
1846 (dsState.stencilWritemask & maxStencilValue));
1847 if (stencil->type() == GL_TEXTURE && dsState.stencilWritemask != 0)
Jamie Madill1d37bc52017-02-02 19:59:58 -05001848 {
Ken Russellb9f92502018-01-27 19:00:26 -08001849 // Skip the feedback loop check if depth/stencil point to the same resource.
1850 if (!depth || *stencil != *depth)
Jamie Madill1d37bc52017-02-02 19:59:58 -05001851 {
Ken Russellb9f92502018-01-27 19:00:26 -08001852 if (program->samplesFromTexture(state, stencil->id()))
1853 {
1854 return true;
1855 }
Jamie Madill1d37bc52017-02-02 19:59:58 -05001856 }
1857 }
1858 }
1859
Jamie Madilla4595b82017-01-11 17:36:34 -05001860 return false;
1861}
1862
Jamie Madillfd3dd432017-02-02 19:59:59 -05001863bool Framebuffer::formsCopyingFeedbackLoopWith(GLuint copyTextureID,
1864 GLint copyTextureLevel,
1865 GLint copyTextureLayer) const
Jamie Madillf695a3a2017-01-11 17:36:35 -05001866{
Jamie Madill2274b652018-05-31 10:56:08 -04001867 if (mState.mId == 0)
Jamie Madillf695a3a2017-01-11 17:36:35 -05001868 {
1869 // It seems impossible to form a texture copying feedback loop with the default FBO.
1870 return false;
1871 }
1872
1873 const FramebufferAttachment *readAttachment = getReadColorbuffer();
1874 ASSERT(readAttachment);
1875
1876 if (readAttachment->isTextureWithId(copyTextureID))
1877 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05001878 const auto &imageIndex = readAttachment->getTextureImageIndex();
Jamie Madillcc129372018-04-12 09:13:18 -04001879 if (imageIndex.getLevelIndex() == copyTextureLevel)
Jamie Madillf695a3a2017-01-11 17:36:35 -05001880 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05001881 // Check 3D/Array texture layers.
Jamie Madillcc129372018-04-12 09:13:18 -04001882 return !imageIndex.hasLayer() || copyTextureLayer == ImageIndex::kEntireLevel ||
1883 imageIndex.getLayerIndex() == copyTextureLayer;
Jamie Madillf695a3a2017-01-11 17:36:35 -05001884 }
1885 }
1886 return false;
1887}
1888
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001889GLint Framebuffer::getDefaultWidth() const
1890{
1891 return mState.getDefaultWidth();
1892}
1893
1894GLint Framebuffer::getDefaultHeight() const
1895{
1896 return mState.getDefaultHeight();
1897}
1898
1899GLint Framebuffer::getDefaultSamples() const
1900{
1901 return mState.getDefaultSamples();
1902}
1903
Geoff Lang92019432017-11-20 13:09:34 -05001904bool Framebuffer::getDefaultFixedSampleLocations() const
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001905{
1906 return mState.getDefaultFixedSampleLocations();
1907}
1908
Jiawei Shaob1e91382018-05-17 14:33:55 +08001909GLint Framebuffer::getDefaultLayers() const
1910{
1911 return mState.getDefaultLayers();
1912}
1913
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001914void Framebuffer::setDefaultWidth(GLint defaultWidth)
1915{
1916 mState.mDefaultWidth = defaultWidth;
1917 mDirtyBits.set(DIRTY_BIT_DEFAULT_WIDTH);
Jamie Madille98b1b52018-03-08 09:47:23 -05001918 invalidateCompletenessCache();
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001919}
1920
1921void Framebuffer::setDefaultHeight(GLint defaultHeight)
1922{
1923 mState.mDefaultHeight = defaultHeight;
1924 mDirtyBits.set(DIRTY_BIT_DEFAULT_HEIGHT);
Jamie Madille98b1b52018-03-08 09:47:23 -05001925 invalidateCompletenessCache();
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001926}
1927
1928void Framebuffer::setDefaultSamples(GLint defaultSamples)
1929{
1930 mState.mDefaultSamples = defaultSamples;
1931 mDirtyBits.set(DIRTY_BIT_DEFAULT_SAMPLES);
Jamie Madille98b1b52018-03-08 09:47:23 -05001932 invalidateCompletenessCache();
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001933}
1934
Geoff Lang92019432017-11-20 13:09:34 -05001935void Framebuffer::setDefaultFixedSampleLocations(bool defaultFixedSampleLocations)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001936{
1937 mState.mDefaultFixedSampleLocations = defaultFixedSampleLocations;
1938 mDirtyBits.set(DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS);
Jamie Madille98b1b52018-03-08 09:47:23 -05001939 invalidateCompletenessCache();
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001940}
1941
Jiawei Shaob1e91382018-05-17 14:33:55 +08001942void Framebuffer::setDefaultLayers(GLint defaultLayers)
1943{
1944 mState.mDefaultLayers = defaultLayers;
1945 mDirtyBits.set(DIRTY_BIT_DEFAULT_LAYERS);
1946}
1947
Martin Radev14a26ae2017-07-24 15:56:29 +03001948GLsizei Framebuffer::getNumViews() const
1949{
Martin Radev5c00d0d2017-08-07 10:06:59 +03001950 return mState.getNumViews();
Martin Radev14a26ae2017-07-24 15:56:29 +03001951}
1952
Martin Radev4e619f52017-08-09 11:50:06 +03001953GLint Framebuffer::getBaseViewIndex() const
1954{
1955 return mState.getBaseViewIndex();
1956}
1957
Martin Radev878c8b12017-07-28 09:51:04 +03001958const std::vector<Offset> *Framebuffer::getViewportOffsets() const
1959{
Martin Radev5c00d0d2017-08-07 10:06:59 +03001960 return mState.getViewportOffsets();
Martin Radev878c8b12017-07-28 09:51:04 +03001961}
1962
1963GLenum Framebuffer::getMultiviewLayout() const
1964{
Martin Radev5c00d0d2017-08-07 10:06:59 +03001965 return mState.getMultiviewLayout();
Martin Radev878c8b12017-07-28 09:51:04 +03001966}
1967
Geoff Langd4fff502017-09-22 11:28:28 -04001968Error Framebuffer::ensureClearAttachmentsInitialized(const Context *context, GLbitfield mask)
1969{
1970 const auto &glState = context->getGLState();
1971 if (!context->isRobustResourceInitEnabled() || glState.isRasterizerDiscardEnabled())
1972 {
1973 return NoError();
1974 }
1975
Geoff Langa36483f2018-03-09 16:11:21 -05001976 const BlendState &blend = glState.getBlendState();
1977 const DepthStencilState &depthStencil = glState.getDepthStencilState();
Geoff Langd4fff502017-09-22 11:28:28 -04001978
1979 bool color = (mask & GL_COLOR_BUFFER_BIT) != 0 && !IsColorMaskedOut(blend);
1980 bool depth = (mask & GL_DEPTH_BUFFER_BIT) != 0 && !IsDepthMaskedOut(depthStencil);
1981 bool stencil = (mask & GL_STENCIL_BUFFER_BIT) != 0 && !IsStencilMaskedOut(depthStencil);
1982
1983 if (!color && !depth && !stencil)
1984 {
1985 return NoError();
1986 }
1987
1988 if (partialClearNeedsInit(context, color, depth, stencil))
1989 {
1990 ANGLE_TRY(ensureDrawAttachmentsInitialized(context));
1991 }
1992
1993 // If the impl encounters an error during a a full (non-partial) clear, the attachments will
1994 // still be marked initialized. This simplifies design, allowing this method to be called before
1995 // the clear.
1996 markDrawAttachmentsInitialized(color, depth, stencil);
1997
1998 return NoError();
1999}
2000
2001Error Framebuffer::ensureClearBufferAttachmentsInitialized(const Context *context,
2002 GLenum buffer,
2003 GLint drawbuffer)
2004{
2005 if (!context->isRobustResourceInitEnabled() ||
2006 context->getGLState().isRasterizerDiscardEnabled() ||
2007 IsClearBufferMaskedOut(context, buffer))
2008 {
2009 return NoError();
2010 }
2011
2012 if (partialBufferClearNeedsInit(context, buffer))
2013 {
2014 ANGLE_TRY(ensureBufferInitialized(context, buffer, drawbuffer));
2015 }
2016
2017 // If the impl encounters an error during a a full (non-partial) clear, the attachments will
2018 // still be marked initialized. This simplifies design, allowing this method to be called before
2019 // the clear.
2020 markBufferInitialized(buffer, drawbuffer);
2021
2022 return NoError();
2023}
2024
Jamie Madill05b35b22017-10-03 09:01:44 -04002025Error Framebuffer::ensureDrawAttachmentsInitialized(const Context *context)
2026{
2027 if (!context->isRobustResourceInitEnabled())
2028 {
2029 return NoError();
2030 }
2031
2032 // Note: we don't actually filter by the draw attachment enum. Just init everything.
2033 for (size_t bit : mState.mResourceNeedsInit)
2034 {
2035 switch (bit)
2036 {
2037 case DIRTY_BIT_DEPTH_ATTACHMENT:
2038 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2039 break;
2040 case DIRTY_BIT_STENCIL_ATTACHMENT:
2041 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2042 break;
2043 default:
2044 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[bit]));
2045 break;
2046 }
2047 }
2048
2049 mState.mResourceNeedsInit.reset();
2050 return NoError();
2051}
2052
2053Error Framebuffer::ensureReadAttachmentInitialized(const Context *context, GLbitfield blitMask)
2054{
2055 if (!context->isRobustResourceInitEnabled() || mState.mResourceNeedsInit.none())
2056 {
2057 return NoError();
2058 }
2059
2060 if ((blitMask & GL_COLOR_BUFFER_BIT) != 0 && mState.mReadBufferState != GL_NONE)
2061 {
2062 size_t readIndex = mState.getReadIndex();
2063 if (mState.mResourceNeedsInit[readIndex])
2064 {
2065 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[readIndex]));
2066 mState.mResourceNeedsInit.reset(readIndex);
2067 }
2068 }
2069
2070 if ((blitMask & GL_DEPTH_BUFFER_BIT) != 0 && hasDepth())
2071 {
2072 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2073 {
2074 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2075 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2076 }
2077 }
2078
2079 if ((blitMask & GL_STENCIL_BUFFER_BIT) != 0 && hasStencil())
2080 {
2081 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2082 {
2083 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2084 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2085 }
2086 }
2087
2088 return NoError();
2089}
2090
2091void Framebuffer::markDrawAttachmentsInitialized(bool color, bool depth, bool stencil)
2092{
2093 // Mark attachments as initialized.
2094 if (color)
2095 {
2096 for (auto colorIndex : mState.mEnabledDrawBuffers)
2097 {
2098 auto &colorAttachment = mState.mColorAttachments[colorIndex];
2099 ASSERT(colorAttachment.isAttached());
2100 colorAttachment.setInitState(InitState::Initialized);
2101 mState.mResourceNeedsInit.reset(colorIndex);
2102 }
2103 }
2104
2105 if (depth && mState.mDepthAttachment.isAttached())
2106 {
2107 mState.mDepthAttachment.setInitState(InitState::Initialized);
2108 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2109 }
2110
2111 if (stencil && mState.mStencilAttachment.isAttached())
2112 {
2113 mState.mStencilAttachment.setInitState(InitState::Initialized);
2114 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2115 }
2116}
2117
2118void Framebuffer::markBufferInitialized(GLenum bufferType, GLint bufferIndex)
2119{
2120 switch (bufferType)
2121 {
2122 case GL_COLOR:
2123 {
2124 ASSERT(bufferIndex < static_cast<GLint>(mState.mColorAttachments.size()));
2125 if (mState.mColorAttachments[bufferIndex].isAttached())
2126 {
2127 mState.mColorAttachments[bufferIndex].setInitState(InitState::Initialized);
2128 mState.mResourceNeedsInit.reset(bufferIndex);
2129 }
2130 break;
2131 }
2132 case GL_DEPTH:
2133 {
2134 if (mState.mDepthAttachment.isAttached())
2135 {
2136 mState.mDepthAttachment.setInitState(InitState::Initialized);
2137 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2138 }
2139 break;
2140 }
2141 case GL_STENCIL:
2142 {
2143 if (mState.mStencilAttachment.isAttached())
2144 {
2145 mState.mStencilAttachment.setInitState(InitState::Initialized);
2146 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2147 }
2148 break;
2149 }
2150 case GL_DEPTH_STENCIL:
2151 {
2152 if (mState.mDepthAttachment.isAttached())
2153 {
2154 mState.mDepthAttachment.setInitState(InitState::Initialized);
2155 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2156 }
2157 if (mState.mStencilAttachment.isAttached())
2158 {
2159 mState.mStencilAttachment.setInitState(InitState::Initialized);
2160 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2161 }
2162 break;
2163 }
2164 default:
2165 UNREACHABLE();
2166 break;
2167 }
2168}
2169
2170Box Framebuffer::getDimensions() const
2171{
2172 return mState.getDimensions();
2173}
2174
2175Error Framebuffer::ensureBufferInitialized(const Context *context,
2176 GLenum bufferType,
2177 GLint bufferIndex)
2178{
2179 ASSERT(context->isRobustResourceInitEnabled());
2180
2181 if (mState.mResourceNeedsInit.none())
2182 {
2183 return NoError();
2184 }
2185
2186 switch (bufferType)
2187 {
2188 case GL_COLOR:
2189 {
2190 ASSERT(bufferIndex < static_cast<GLint>(mState.mColorAttachments.size()));
2191 if (mState.mResourceNeedsInit[bufferIndex])
2192 {
2193 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[bufferIndex]));
2194 mState.mResourceNeedsInit.reset(bufferIndex);
2195 }
2196 break;
2197 }
2198 case GL_DEPTH:
2199 {
2200 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2201 {
2202 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2203 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2204 }
2205 break;
2206 }
2207 case GL_STENCIL:
2208 {
2209 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2210 {
2211 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2212 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2213 }
2214 break;
2215 }
2216 case GL_DEPTH_STENCIL:
2217 {
2218 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2219 {
2220 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2221 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2222 }
2223 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2224 {
2225 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2226 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2227 }
2228 break;
2229 }
2230 default:
2231 UNREACHABLE();
2232 break;
2233 }
2234
2235 return NoError();
2236}
2237
2238bool Framebuffer::partialBufferClearNeedsInit(const Context *context, GLenum bufferType)
2239{
2240 if (!context->isRobustResourceInitEnabled() || mState.mResourceNeedsInit.none())
2241 {
2242 return false;
2243 }
2244
2245 switch (bufferType)
2246 {
2247 case GL_COLOR:
2248 return partialClearNeedsInit(context, true, false, false);
2249 case GL_DEPTH:
2250 return partialClearNeedsInit(context, false, true, false);
2251 case GL_STENCIL:
2252 return partialClearNeedsInit(context, false, false, true);
2253 case GL_DEPTH_STENCIL:
2254 return partialClearNeedsInit(context, false, true, true);
2255 default:
2256 UNREACHABLE();
2257 return false;
2258 }
2259}
2260
Jamie Madill42975642017-10-12 12:31:51 -04002261bool Framebuffer::hasTextureAttachment(const Texture *texture) const
2262{
2263 if (!mAttachedTextures.valid())
2264 {
2265 std::set<const FramebufferAttachmentObject *> attachedTextures;
2266
2267 for (const auto &colorAttachment : mState.mColorAttachments)
2268 {
2269 if (colorAttachment.isAttached() && colorAttachment.type() == GL_TEXTURE)
2270 {
2271 attachedTextures.insert(colorAttachment.getResource());
2272 }
2273 }
2274
2275 if (mState.mDepthAttachment.isAttached() && mState.mDepthAttachment.type() == GL_TEXTURE)
2276 {
2277 attachedTextures.insert(mState.mDepthAttachment.getResource());
2278 }
2279
2280 if (mState.mStencilAttachment.isAttached() &&
2281 mState.mStencilAttachment.type() == GL_TEXTURE)
2282 {
2283 attachedTextures.insert(mState.mStencilAttachment.getResource());
2284 }
2285
2286 mAttachedTextures = std::move(attachedTextures);
2287 }
2288
2289 return (mAttachedTextures.value().count(texture) > 0);
2290}
2291
Jamie Madill60ec6ea2016-01-22 15:27:19 -05002292} // namespace gl