blob: 77fce7e98c802d10a044a3fae67b3a80e07edcde [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 {
Jiawei Shaoa8802472018-05-28 11:17:47 +080088 // [EXT_geometry_shader] Section 9.4.1, "Framebuffer Completeness"
89 // If <image> is a three-dimensional texture or a two-dimensional array texture and the
90 // attachment is not layered, the selected layer is less than the depth or layer count,
91 // respectively, of the texture.
92 if (!attachment.isLayered())
Geoff Lang9f10b772017-05-16 15:51:03 -040093 {
Jiawei Shaoa8802472018-05-28 11:17:47 +080094 if (attachment.layer() >= size.depth)
95 {
96 return false;
97 }
98 }
99 // If <image> is a three-dimensional texture or a two-dimensional array texture and the
100 // attachment is layered, the depth or layer count, respectively, of the texture is less
101 // than or equal to the value of MAX_FRAMEBUFFER_LAYERS_EXT.
102 else
103 {
104 if (static_cast<GLuint>(size.depth) >= context->getCaps().maxFramebufferLayers)
105 {
106 return false;
107 }
Geoff Lang9f10b772017-05-16 15:51:03 -0400108 }
109
110 // ES3 specifies that cube map texture attachments must be cube complete.
111 // This language is missing from the ES2 spec, but we enforce it here because some
112 // desktop OpenGL drivers also enforce this validation.
113 // TODO(jmadill): Check if OpenGL ES2 drivers enforce cube completeness.
114 const Texture *texture = attachment.getTexture();
115 ASSERT(texture);
Corentin Wallez99d492c2018-02-27 15:17:10 -0500116 if (texture->getType() == TextureType::CubeMap &&
Geoff Lang9f10b772017-05-16 15:51:03 -0400117 !texture->getTextureState().isCubeComplete())
118 {
119 return false;
120 }
Geoff Lang857c09d2017-05-16 15:55:04 -0400121
122 if (!texture->getImmutableFormat())
123 {
124 GLuint attachmentMipLevel = static_cast<GLuint>(attachment.mipLevel());
125
126 // From the ES 3.0 spec, pg 213:
127 // If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is TEXTURE and the value of
128 // FRAMEBUFFER_ATTACHMENT_OBJECT_NAME does not name an immutable-format texture,
129 // then the value of FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL must be in the
130 // range[levelbase, q], where levelbase is the value of TEXTURE_BASE_LEVEL and q is
131 // the effective maximum texture level defined in the Mipmapping discussion of
132 // section 3.8.10.4.
133 if (attachmentMipLevel < texture->getBaseLevel() ||
134 attachmentMipLevel > texture->getMipmapMaxLevel())
135 {
136 return false;
137 }
138
139 // Form the ES 3.0 spec, pg 213/214:
140 // If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is TEXTURE and the value of
141 // FRAMEBUFFER_ATTACHMENT_OBJECT_NAME does not name an immutable-format texture and
142 // the value of FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL is not levelbase, then the
143 // texture must be mipmap complete, and if FRAMEBUFFER_ATTACHMENT_OBJECT_NAME names
144 // a cubemap texture, the texture must also be cube complete.
145 if (attachmentMipLevel != texture->getBaseLevel() && !texture->isMipmapComplete())
146 {
147 return false;
148 }
149 }
Geoff Lang9f10b772017-05-16 15:51:03 -0400150 }
151
152 return true;
153};
154
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400155bool CheckAttachmentSampleCompleteness(const Context *context,
156 const FramebufferAttachment &attachment,
157 bool colorAttachment,
158 Optional<int> *samples,
Geoff Lang92019432017-11-20 13:09:34 -0500159 Optional<bool> *fixedSampleLocations)
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400160{
161 ASSERT(attachment.isAttached());
162
163 if (attachment.type() == GL_TEXTURE)
164 {
165 const Texture *texture = attachment.getTexture();
166 ASSERT(texture);
167
168 const ImageIndex &attachmentImageIndex = attachment.getTextureImageIndex();
Jiawei Shaoa8802472018-05-28 11:17:47 +0800169 bool fixedSampleloc = texture->getAttachmentFixedSampleLocations(attachmentImageIndex);
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400170 if (fixedSampleLocations->valid() && fixedSampleloc != fixedSampleLocations->value())
171 {
172 return false;
173 }
174 else
175 {
176 *fixedSampleLocations = fixedSampleloc;
177 }
178 }
179
180 if (samples->valid())
181 {
182 if (attachment.getSamples() != samples->value())
183 {
184 if (colorAttachment)
185 {
186 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
187 // all color attachments have the same number of samples for the FBO to be complete.
188 return false;
189 }
190 else
191 {
192 // CHROMIUM_framebuffer_mixed_samples allows a framebuffer to be considered complete
193 // when its depth or stencil samples are a multiple of the number of color samples.
194 if (!context->getExtensions().framebufferMixedSamples)
195 {
196 return false;
197 }
198
199 if ((attachment.getSamples() % std::max(samples->value(), 1)) != 0)
200 {
201 return false;
202 }
203 }
204 }
205 }
206 else
207 {
208 *samples = attachment.getSamples();
209 }
210
211 return true;
212}
213
Jamie Madill05b35b22017-10-03 09:01:44 -0400214// Needed to index into the attachment arrays/bitsets.
Jamie Madill682efdc2017-10-03 14:10:29 -0400215static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS) ==
Jamie Madilld4442552018-02-27 22:03:47 -0500216 Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX,
Jamie Madill05b35b22017-10-03 09:01:44 -0400217 "Framebuffer Dirty bit mismatch");
Jamie Madill682efdc2017-10-03 14:10:29 -0400218static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS) ==
Jamie Madilld4442552018-02-27 22:03:47 -0500219 Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT,
Jamie Madill05b35b22017-10-03 09:01:44 -0400220 "Framebuffer Dirty bit mismatch");
Jamie Madill682efdc2017-10-03 14:10:29 -0400221static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS + 1) ==
Jamie Madilld4442552018-02-27 22:03:47 -0500222 Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT,
Jamie Madill05b35b22017-10-03 09:01:44 -0400223 "Framebuffer Dirty bit mismatch");
224
225Error InitAttachment(const Context *context, FramebufferAttachment *attachment)
226{
227 ASSERT(attachment->isAttached());
228 if (attachment->initState() == InitState::MayNeedInit)
229 {
230 ANGLE_TRY(attachment->initializeContents(context));
231 }
232 return NoError();
233}
234
235bool IsColorMaskedOut(const BlendState &blend)
236{
237 return (!blend.colorMaskRed && !blend.colorMaskGreen && !blend.colorMaskBlue &&
238 !blend.colorMaskAlpha);
239}
240
241bool IsDepthMaskedOut(const DepthStencilState &depthStencil)
242{
243 return !depthStencil.depthMask;
244}
245
246bool IsStencilMaskedOut(const DepthStencilState &depthStencil)
247{
248 return ((depthStencil.stencilMask & depthStencil.stencilWritemask) == 0);
249}
250
251bool IsClearBufferMaskedOut(const Context *context, GLenum buffer)
252{
253 switch (buffer)
254 {
255 case GL_COLOR:
256 return IsColorMaskedOut(context->getGLState().getBlendState());
257 case GL_DEPTH:
258 return IsDepthMaskedOut(context->getGLState().getDepthStencilState());
259 case GL_STENCIL:
260 return IsStencilMaskedOut(context->getGLState().getDepthStencilState());
261 case GL_DEPTH_STENCIL:
262 return IsDepthMaskedOut(context->getGLState().getDepthStencilState()) &&
263 IsStencilMaskedOut(context->getGLState().getDepthStencilState());
264 default:
265 UNREACHABLE();
266 return true;
267 }
268}
269
Jamie Madill362876b2016-06-16 14:46:59 -0400270} // anonymous namespace
Jamie Madilld1405e52015-03-05 15:41:39 -0500271
Jamie Madill6f60d052017-02-22 15:20:11 -0500272// This constructor is only used for default framebuffers.
Jamie Madill48ef11b2016-04-27 15:21:52 -0400273FramebufferState::FramebufferState()
Jamie Madill2274b652018-05-31 10:56:08 -0400274 : mId(0),
275 mLabel(),
Geoff Lang70d0f492015-12-10 17:45:46 -0500276 mColorAttachments(1),
Corentin Walleze7557742017-06-01 13:09:57 -0400277 mDrawBufferStates(1, GL_BACK),
Jamie Madill6f60d052017-02-22 15:20:11 -0500278 mReadBufferState(GL_BACK),
Brandon Jones76746f92017-11-22 11:44:41 -0800279 mDrawBufferTypeMask(),
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800280 mDefaultWidth(0),
281 mDefaultHeight(0),
282 mDefaultSamples(0),
Jamie Madilla02315b2017-02-23 14:14:47 -0500283 mDefaultFixedSampleLocations(GL_FALSE),
Jiawei Shaob1e91382018-05-17 14:33:55 +0800284 mDefaultLayers(0),
Jamie Madilla02315b2017-02-23 14:14:47 -0500285 mWebGLDepthStencilConsistent(true)
Corentin Wallez37c39792015-08-20 14:19:46 -0400286{
Geoff Langd90d3882017-03-21 10:49:54 -0400287 ASSERT(mDrawBufferStates.size() > 0);
Jamie Madilla4595b82017-01-11 17:36:34 -0500288 mEnabledDrawBuffers.set(0);
Corentin Wallez37c39792015-08-20 14:19:46 -0400289}
290
Jamie Madill2274b652018-05-31 10:56:08 -0400291FramebufferState::FramebufferState(const Caps &caps, GLuint id)
292 : mId(id),
293 mLabel(),
Geoff Lang70d0f492015-12-10 17:45:46 -0500294 mColorAttachments(caps.maxColorAttachments),
Jamie Madilld1405e52015-03-05 15:41:39 -0500295 mDrawBufferStates(caps.maxDrawBuffers, GL_NONE),
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800296 mReadBufferState(GL_COLOR_ATTACHMENT0_EXT),
Brandon Jones76746f92017-11-22 11:44:41 -0800297 mDrawBufferTypeMask(),
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800298 mDefaultWidth(0),
299 mDefaultHeight(0),
300 mDefaultSamples(0),
Jamie Madilla02315b2017-02-23 14:14:47 -0500301 mDefaultFixedSampleLocations(GL_FALSE),
Jiawei Shaob1e91382018-05-17 14:33:55 +0800302 mDefaultLayers(0),
Jamie Madilla02315b2017-02-23 14:14:47 -0500303 mWebGLDepthStencilConsistent(true)
Jamie Madilld1405e52015-03-05 15:41:39 -0500304{
Jamie Madill2274b652018-05-31 10:56:08 -0400305 ASSERT(mId != 0);
Geoff Langa15472a2015-08-11 11:48:03 -0400306 ASSERT(mDrawBufferStates.size() > 0);
Jamie Madilld1405e52015-03-05 15:41:39 -0500307 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
308}
309
Jamie Madill48ef11b2016-04-27 15:21:52 -0400310FramebufferState::~FramebufferState()
Jamie Madilld1405e52015-03-05 15:41:39 -0500311{
Jamie Madilld1405e52015-03-05 15:41:39 -0500312}
313
Jamie Madill48ef11b2016-04-27 15:21:52 -0400314const std::string &FramebufferState::getLabel()
Geoff Lang70d0f492015-12-10 17:45:46 -0500315{
316 return mLabel;
317}
318
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800319const FramebufferAttachment *FramebufferState::getAttachment(const Context *context,
320 GLenum attachment) const
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400321{
322 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
323 {
324 return getColorAttachment(attachment - GL_COLOR_ATTACHMENT0);
325 }
326
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800327 // WebGL1 allows a developer to query for attachment parameters even when "inconsistant" (i.e.
328 // multiple conflicting attachment points) and requires us to return the framebuffer attachment
329 // associated with WebGL.
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400330 switch (attachment)
331 {
332 case GL_COLOR:
333 case GL_BACK:
334 return getColorAttachment(0);
335 case GL_DEPTH:
336 case GL_DEPTH_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800337 if (context->isWebGL1())
338 {
339 return getWebGLDepthAttachment();
340 }
341 else
342 {
343 return getDepthAttachment();
344 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400345 case GL_STENCIL:
346 case GL_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800347 if (context->isWebGL1())
348 {
349 return getWebGLStencilAttachment();
350 }
351 else
352 {
353 return getStencilAttachment();
354 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400355 case GL_DEPTH_STENCIL:
356 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800357 if (context->isWebGL1())
358 {
359 return getWebGLDepthStencilAttachment();
360 }
361 else
362 {
363 return getDepthStencilAttachment();
364 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400365 default:
366 UNREACHABLE();
367 return nullptr;
368 }
369}
370
Jamie Madill05b35b22017-10-03 09:01:44 -0400371size_t FramebufferState::getReadIndex() const
Jamie Madill7147f012015-03-05 15:41:40 -0500372{
Jamie Madill231c7f52017-04-26 13:45:37 -0400373 ASSERT(mReadBufferState == GL_BACK ||
374 (mReadBufferState >= GL_COLOR_ATTACHMENT0 && mReadBufferState <= GL_COLOR_ATTACHMENT15));
375 size_t readIndex = (mReadBufferState == GL_BACK
376 ? 0
377 : static_cast<size_t>(mReadBufferState - GL_COLOR_ATTACHMENT0));
Jamie Madill7147f012015-03-05 15:41:40 -0500378 ASSERT(readIndex < mColorAttachments.size());
Jamie Madill05b35b22017-10-03 09:01:44 -0400379 return readIndex;
380}
381
382const FramebufferAttachment *FramebufferState::getReadAttachment() const
383{
384 if (mReadBufferState == GL_NONE)
385 {
386 return nullptr;
387 }
388 size_t readIndex = getReadIndex();
Jamie Madill2d06b732015-04-20 12:53:28 -0400389 return mColorAttachments[readIndex].isAttached() ? &mColorAttachments[readIndex] : nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500390}
391
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500392const FramebufferAttachment *FramebufferState::getFirstNonNullAttachment() const
393{
394 auto *colorAttachment = getFirstColorAttachment();
395 if (colorAttachment)
396 {
397 return colorAttachment;
398 }
399 return getDepthOrStencilAttachment();
400}
401
Jamie Madill48ef11b2016-04-27 15:21:52 -0400402const FramebufferAttachment *FramebufferState::getFirstColorAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500403{
Jamie Madill2d06b732015-04-20 12:53:28 -0400404 for (const FramebufferAttachment &colorAttachment : mColorAttachments)
Jamie Madill7147f012015-03-05 15:41:40 -0500405 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400406 if (colorAttachment.isAttached())
Jamie Madill7147f012015-03-05 15:41:40 -0500407 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400408 return &colorAttachment;
Jamie Madill7147f012015-03-05 15:41:40 -0500409 }
410 }
411
412 return nullptr;
413}
414
Jamie Madill48ef11b2016-04-27 15:21:52 -0400415const FramebufferAttachment *FramebufferState::getDepthOrStencilAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500416{
Jamie Madill2d06b732015-04-20 12:53:28 -0400417 if (mDepthAttachment.isAttached())
418 {
419 return &mDepthAttachment;
420 }
421 if (mStencilAttachment.isAttached())
422 {
423 return &mStencilAttachment;
424 }
425 return nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500426}
427
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500428const FramebufferAttachment *FramebufferState::getStencilOrDepthStencilAttachment() const
429{
430 if (mStencilAttachment.isAttached())
431 {
432 return &mStencilAttachment;
433 }
434 return getDepthStencilAttachment();
435}
436
Jamie Madill48ef11b2016-04-27 15:21:52 -0400437const FramebufferAttachment *FramebufferState::getColorAttachment(size_t colorAttachment) const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400438{
439 ASSERT(colorAttachment < mColorAttachments.size());
Jamie Madill231c7f52017-04-26 13:45:37 -0400440 return mColorAttachments[colorAttachment].isAttached() ? &mColorAttachments[colorAttachment]
441 : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400442}
443
Jamie Madill48ef11b2016-04-27 15:21:52 -0400444const FramebufferAttachment *FramebufferState::getDepthAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400445{
Jamie Madill2d06b732015-04-20 12:53:28 -0400446 return mDepthAttachment.isAttached() ? &mDepthAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400447}
448
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800449const FramebufferAttachment *FramebufferState::getWebGLDepthAttachment() const
450{
451 return mWebGLDepthAttachment.isAttached() ? &mWebGLDepthAttachment : nullptr;
452}
453
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800454const FramebufferAttachment *FramebufferState::getWebGLDepthStencilAttachment() const
455{
456 return mWebGLDepthStencilAttachment.isAttached() ? &mWebGLDepthStencilAttachment : nullptr;
457}
458
Jamie Madill48ef11b2016-04-27 15:21:52 -0400459const FramebufferAttachment *FramebufferState::getStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400460{
Jamie Madill2d06b732015-04-20 12:53:28 -0400461 return mStencilAttachment.isAttached() ? &mStencilAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400462}
463
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800464const FramebufferAttachment *FramebufferState::getWebGLStencilAttachment() const
465{
466 return mWebGLStencilAttachment.isAttached() ? &mWebGLStencilAttachment : nullptr;
467}
468
Jamie Madill48ef11b2016-04-27 15:21:52 -0400469const FramebufferAttachment *FramebufferState::getDepthStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400470{
471 // A valid depth-stencil attachment has the same resource bound to both the
472 // depth and stencil attachment points.
Jamie Madill2d06b732015-04-20 12:53:28 -0400473 if (mDepthAttachment.isAttached() && mStencilAttachment.isAttached() &&
Jamie Madill44f26482016-11-18 12:49:15 -0500474 mDepthAttachment == mStencilAttachment)
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400475 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400476 return &mDepthAttachment;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400477 }
478
479 return nullptr;
480}
481
Jamie Madill48ef11b2016-04-27 15:21:52 -0400482bool FramebufferState::attachmentsHaveSameDimensions() const
Jamie Madillcc86d642015-11-24 13:00:07 -0500483{
484 Optional<Extents> attachmentSize;
485
Jamie Madill231c7f52017-04-26 13:45:37 -0400486 auto hasMismatchedSize = [&attachmentSize](const FramebufferAttachment &attachment) {
Jamie Madillcc86d642015-11-24 13:00:07 -0500487 if (!attachment.isAttached())
488 {
489 return false;
490 }
491
492 if (!attachmentSize.valid())
493 {
494 attachmentSize = attachment.getSize();
495 return false;
496 }
497
Jeff Gilbert8f8edd62017-10-31 14:26:30 -0700498 const auto &prevSize = attachmentSize.value();
499 const auto &curSize = attachment.getSize();
500 return (curSize.width != prevSize.width || curSize.height != prevSize.height);
Jamie Madillcc86d642015-11-24 13:00:07 -0500501 };
502
503 for (const auto &attachment : mColorAttachments)
504 {
505 if (hasMismatchedSize(attachment))
506 {
507 return false;
508 }
509 }
510
511 if (hasMismatchedSize(mDepthAttachment))
512 {
513 return false;
514 }
515
516 return !hasMismatchedSize(mStencilAttachment);
517}
518
Luc Ferron5bdf8bd2018-06-20 09:51:37 -0400519bool FramebufferState::hasSeparateDepthAndStencilAttachments() const
520{
521 // if we have both a depth and stencil buffer, they must refer to the same object
522 // since we only support packed_depth_stencil and not separate depth and stencil
523 return (getDepthAttachment() != nullptr && getStencilAttachment() != nullptr &&
524 getDepthStencilAttachment() == nullptr);
525}
526
Jamie Madilld4442552018-02-27 22:03:47 -0500527const FramebufferAttachment *FramebufferState::getDrawBuffer(size_t drawBufferIdx) const
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400528{
529 ASSERT(drawBufferIdx < mDrawBufferStates.size());
530 if (mDrawBufferStates[drawBufferIdx] != GL_NONE)
531 {
532 // ES3 spec: "If the GL is bound to a draw framebuffer object, the ith buffer listed in bufs
533 // must be COLOR_ATTACHMENTi or NONE"
534 ASSERT(mDrawBufferStates[drawBufferIdx] == GL_COLOR_ATTACHMENT0 + drawBufferIdx ||
535 (drawBufferIdx == 0 && mDrawBufferStates[drawBufferIdx] == GL_BACK));
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800536
537 if (mDrawBufferStates[drawBufferIdx] == GL_BACK)
538 {
539 return getColorAttachment(0);
540 }
541 else
542 {
543 return getColorAttachment(mDrawBufferStates[drawBufferIdx] - GL_COLOR_ATTACHMENT0);
544 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400545 }
546 else
547 {
548 return nullptr;
549 }
550}
551
552size_t FramebufferState::getDrawBufferCount() const
553{
554 return mDrawBufferStates.size();
555}
556
Geoff Langb21e20d2016-07-19 15:35:41 -0400557bool FramebufferState::colorAttachmentsAreUniqueImages() const
558{
559 for (size_t firstAttachmentIdx = 0; firstAttachmentIdx < mColorAttachments.size();
560 firstAttachmentIdx++)
561 {
Jamie Madilld4442552018-02-27 22:03:47 -0500562 const FramebufferAttachment &firstAttachment = mColorAttachments[firstAttachmentIdx];
Geoff Langb21e20d2016-07-19 15:35:41 -0400563 if (!firstAttachment.isAttached())
564 {
565 continue;
566 }
567
568 for (size_t secondAttachmentIdx = firstAttachmentIdx + 1;
569 secondAttachmentIdx < mColorAttachments.size(); secondAttachmentIdx++)
570 {
Jamie Madilld4442552018-02-27 22:03:47 -0500571 const FramebufferAttachment &secondAttachment = mColorAttachments[secondAttachmentIdx];
Geoff Langb21e20d2016-07-19 15:35:41 -0400572 if (!secondAttachment.isAttached())
573 {
574 continue;
575 }
576
577 if (firstAttachment == secondAttachment)
578 {
579 return false;
580 }
581 }
582 }
583
584 return true;
585}
586
Jamie Madill9c335862017-07-18 11:51:38 -0400587bool FramebufferState::hasDepth() const
588{
589 return (mDepthAttachment.isAttached() && mDepthAttachment.getDepthSize() > 0);
590}
591
592bool FramebufferState::hasStencil() const
593{
594 return (mStencilAttachment.isAttached() && mStencilAttachment.getStencilSize() > 0);
595}
596
Martin Radev5c00d0d2017-08-07 10:06:59 +0300597GLsizei FramebufferState::getNumViews() const
598{
599 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
600 if (attachment == nullptr)
601 {
602 return FramebufferAttachment::kDefaultNumViews;
603 }
604 return attachment->getNumViews();
605}
606
607const std::vector<Offset> *FramebufferState::getViewportOffsets() const
608{
609 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
610 if (attachment == nullptr)
611 {
612 return nullptr;
613 }
614 return &attachment->getMultiviewViewportOffsets();
615}
616
617GLenum FramebufferState::getMultiviewLayout() const
618{
619 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
620 if (attachment == nullptr)
621 {
622 return GL_NONE;
623 }
624 return attachment->getMultiviewLayout();
625}
626
Martin Radev4e619f52017-08-09 11:50:06 +0300627int FramebufferState::getBaseViewIndex() const
628{
629 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
630 if (attachment == nullptr)
631 {
632 return GL_NONE;
633 }
634 return attachment->getBaseViewIndex();
635}
636
Jamie Madill05b35b22017-10-03 09:01:44 -0400637Box FramebufferState::getDimensions() const
638{
639 ASSERT(attachmentsHaveSameDimensions());
640 ASSERT(getFirstNonNullAttachment() != nullptr);
641 Extents extents = getFirstNonNullAttachment()->getSize();
642 return Box(0, 0, 0, extents.width, extents.height, extents.depth);
643}
644
Jamie Madill7aea7e02016-05-10 10:39:45 -0400645Framebuffer::Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id)
Jamie Madill2274b652018-05-31 10:56:08 -0400646 : mState(caps, id),
Jamie Madill362876b2016-06-16 14:46:59 -0400647 mImpl(factory->createFramebuffer(mState)),
Jamie Madill362876b2016-06-16 14:46:59 -0400648 mCachedStatus(),
649 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
650 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000651{
Corentin Wallez37c39792015-08-20 14:19:46 -0400652 ASSERT(mImpl != nullptr);
Jamie Madill362876b2016-06-16 14:46:59 -0400653 ASSERT(mState.mColorAttachments.size() == static_cast<size_t>(caps.maxColorAttachments));
654
Jamie Madill1e5499d2017-04-05 11:22:16 -0400655 for (uint32_t colorIndex = 0;
656 colorIndex < static_cast<uint32_t>(mState.mColorAttachments.size()); ++colorIndex)
Jamie Madill362876b2016-06-16 14:46:59 -0400657 {
Jamie Madill1e5499d2017-04-05 11:22:16 -0400658 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
Jamie Madill362876b2016-06-16 14:46:59 -0400659 }
Corentin Wallez37c39792015-08-20 14:19:46 -0400660}
661
Geoff Langbf7b95d2018-05-01 16:48:21 -0400662Framebuffer::Framebuffer(const Context *context, egl::Surface *surface)
Jamie Madill362876b2016-06-16 14:46:59 -0400663 : mState(),
Geoff Langbf7b95d2018-05-01 16:48:21 -0400664 mImpl(surface->getImplementation()->createDefaultFramebuffer(context, mState)),
Jamie Madill362876b2016-06-16 14:46:59 -0400665 mCachedStatus(GL_FRAMEBUFFER_COMPLETE),
666 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
667 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
Corentin Wallez37c39792015-08-20 14:19:46 -0400668{
Geoff Langda88add2014-12-01 10:22:01 -0500669 ASSERT(mImpl != nullptr);
Jamie Madill1e5499d2017-04-05 11:22:16 -0400670 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
Jamie Madill6f60d052017-02-22 15:20:11 -0500671
Geoff Langbf7b95d2018-05-01 16:48:21 -0400672 setAttachmentImpl(context, GL_FRAMEBUFFER_DEFAULT, GL_BACK, ImageIndex(), surface,
Jamie Madillcc129372018-04-12 09:13:18 -0400673 FramebufferAttachment::kDefaultNumViews,
Martin Radev5dae57b2017-07-14 16:15:55 +0300674 FramebufferAttachment::kDefaultBaseViewIndex,
675 FramebufferAttachment::kDefaultMultiviewLayout,
676 FramebufferAttachment::kDefaultViewportOffsets);
Jamie Madill6f60d052017-02-22 15:20:11 -0500677
678 if (surface->getConfig()->depthSize > 0)
679 {
Geoff Langbf7b95d2018-05-01 16:48:21 -0400680 setAttachmentImpl(context, GL_FRAMEBUFFER_DEFAULT, GL_DEPTH, ImageIndex(), surface,
Jamie Madillcc129372018-04-12 09:13:18 -0400681 FramebufferAttachment::kDefaultNumViews,
Jamie Madilld4442552018-02-27 22:03:47 -0500682 FramebufferAttachment::kDefaultBaseViewIndex,
683 FramebufferAttachment::kDefaultMultiviewLayout,
684 FramebufferAttachment::kDefaultViewportOffsets);
Jamie Madill6f60d052017-02-22 15:20:11 -0500685 }
686
687 if (surface->getConfig()->stencilSize > 0)
688 {
Geoff Langbf7b95d2018-05-01 16:48:21 -0400689 setAttachmentImpl(context, GL_FRAMEBUFFER_DEFAULT, GL_STENCIL, ImageIndex(), surface,
Jamie Madillcc129372018-04-12 09:13:18 -0400690 FramebufferAttachment::kDefaultNumViews,
691 FramebufferAttachment::kDefaultBaseViewIndex,
692 FramebufferAttachment::kDefaultMultiviewLayout,
693 FramebufferAttachment::kDefaultViewportOffsets);
Jamie Madill6f60d052017-02-22 15:20:11 -0500694 }
Brandon Jones76746f92017-11-22 11:44:41 -0800695 mState.mDrawBufferTypeMask.setIndex(getDrawbufferWriteType(0), 0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000696}
697
Corentin Wallezccab69d2017-01-27 16:57:15 -0500698Framebuffer::Framebuffer(rx::GLImplFactory *factory)
699 : mState(),
700 mImpl(factory->createFramebuffer(mState)),
Corentin Wallezccab69d2017-01-27 16:57:15 -0500701 mCachedStatus(GL_FRAMEBUFFER_UNDEFINED_OES),
702 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
703 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
704{
Jamie Madill1e5499d2017-04-05 11:22:16 -0400705 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
Brandon Jones76746f92017-11-22 11:44:41 -0800706 mState.mDrawBufferTypeMask.setIndex(getDrawbufferWriteType(0), 0);
Corentin Wallezccab69d2017-01-27 16:57:15 -0500707}
708
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000709Framebuffer::~Framebuffer()
710{
Geoff Langda88add2014-12-01 10:22:01 -0500711 SafeDelete(mImpl);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000712}
713
Jamie Madill4928b7c2017-06-20 12:57:39 -0400714void Framebuffer::onDestroy(const Context *context)
Jamie Madill6c1f6712017-02-14 19:08:04 -0500715{
Jamie Madill4928b7c2017-06-20 12:57:39 -0400716 for (auto &attachment : mState.mColorAttachments)
717 {
718 attachment.detach(context);
719 }
720 mState.mDepthAttachment.detach(context);
721 mState.mStencilAttachment.detach(context);
722 mState.mWebGLDepthAttachment.detach(context);
723 mState.mWebGLStencilAttachment.detach(context);
724 mState.mWebGLDepthStencilAttachment.detach(context);
725
Jamie Madillc564c072017-06-01 12:45:42 -0400726 mImpl->destroy(context);
Jamie Madill6c1f6712017-02-14 19:08:04 -0500727}
728
Geoff Lang70d0f492015-12-10 17:45:46 -0500729void Framebuffer::setLabel(const std::string &label)
730{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400731 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -0500732}
733
734const std::string &Framebuffer::getLabel() const
735{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400736 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -0500737}
738
Jamie Madill8693bdb2017-09-02 15:32:14 -0400739bool Framebuffer::detachTexture(const Context *context, GLuint textureId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000740{
Jamie Madill8693bdb2017-09-02 15:32:14 -0400741 return detachResourceById(context, GL_TEXTURE, textureId);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000742}
743
Jamie Madill8693bdb2017-09-02 15:32:14 -0400744bool Framebuffer::detachRenderbuffer(const Context *context, GLuint renderbufferId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000745{
Jamie Madill8693bdb2017-09-02 15:32:14 -0400746 return detachResourceById(context, GL_RENDERBUFFER, renderbufferId);
Jamie Madilld1405e52015-03-05 15:41:39 -0500747}
Jamie Madille261b442014-06-25 12:42:21 -0400748
Jamie Madill8693bdb2017-09-02 15:32:14 -0400749bool Framebuffer::detachResourceById(const Context *context, GLenum resourceType, GLuint resourceId)
Jamie Madilld1405e52015-03-05 15:41:39 -0500750{
Jamie Madill8693bdb2017-09-02 15:32:14 -0400751 bool found = false;
752
Jamie Madill362876b2016-06-16 14:46:59 -0400753 for (size_t colorIndex = 0; colorIndex < mState.mColorAttachments.size(); ++colorIndex)
Jamie Madilld1405e52015-03-05 15:41:39 -0500754 {
Jamie Madill8693bdb2017-09-02 15:32:14 -0400755 if (detachMatchingAttachment(context, &mState.mColorAttachments[colorIndex], resourceType,
756 resourceId, DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex))
757 {
758 found = true;
759 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000760 }
761
Jamie Madilla02315b2017-02-23 14:14:47 -0500762 if (context->isWebGL1())
763 {
764 const std::array<FramebufferAttachment *, 3> attachments = {
765 {&mState.mWebGLDepthStencilAttachment, &mState.mWebGLDepthAttachment,
766 &mState.mWebGLStencilAttachment}};
767 for (FramebufferAttachment *attachment : attachments)
768 {
769 if (attachment->isAttached() && attachment->type() == resourceType &&
770 attachment->id() == resourceId)
771 {
772 resetAttachment(context, attachment->getBinding());
Jamie Madill8693bdb2017-09-02 15:32:14 -0400773 found = true;
Jamie Madilla02315b2017-02-23 14:14:47 -0500774 }
775 }
776 }
777 else
778 {
Jamie Madill8693bdb2017-09-02 15:32:14 -0400779 if (detachMatchingAttachment(context, &mState.mDepthAttachment, resourceType, resourceId,
780 DIRTY_BIT_DEPTH_ATTACHMENT))
781 {
782 found = true;
783 }
784 if (detachMatchingAttachment(context, &mState.mStencilAttachment, resourceType, resourceId,
785 DIRTY_BIT_STENCIL_ATTACHMENT))
786 {
787 found = true;
788 }
Jamie Madilla02315b2017-02-23 14:14:47 -0500789 }
Jamie Madill8693bdb2017-09-02 15:32:14 -0400790
791 return found;
Jamie Madill362876b2016-06-16 14:46:59 -0400792}
793
Jamie Madill8693bdb2017-09-02 15:32:14 -0400794bool Framebuffer::detachMatchingAttachment(const Context *context,
Jamie Madill4928b7c2017-06-20 12:57:39 -0400795 FramebufferAttachment *attachment,
Jamie Madill362876b2016-06-16 14:46:59 -0400796 GLenum matchType,
797 GLuint matchId,
798 size_t dirtyBit)
799{
800 if (attachment->isAttached() && attachment->type() == matchType && attachment->id() == matchId)
801 {
Jamie Madill4928b7c2017-06-20 12:57:39 -0400802 attachment->detach(context);
Jamie Madill362876b2016-06-16 14:46:59 -0400803 mDirtyBits.set(dirtyBit);
Jamie Madill05b35b22017-10-03 09:01:44 -0400804 mState.mResourceNeedsInit.set(dirtyBit, false);
Jamie Madill8693bdb2017-09-02 15:32:14 -0400805 return true;
Jamie Madill362876b2016-06-16 14:46:59 -0400806 }
Jamie Madill8693bdb2017-09-02 15:32:14 -0400807
808 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000809}
810
Corentin Wallez37c39792015-08-20 14:19:46 -0400811const FramebufferAttachment *Framebuffer::getColorbuffer(size_t colorAttachment) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000812{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400813 return mState.getColorAttachment(colorAttachment);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000814}
815
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400816const FramebufferAttachment *Framebuffer::getDepthbuffer() const
Geoff Lang646559f2013-08-15 11:08:15 -0400817{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400818 return mState.getDepthAttachment();
Geoff Lang646559f2013-08-15 11:08:15 -0400819}
820
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400821const FramebufferAttachment *Framebuffer::getStencilbuffer() const
822{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400823 return mState.getStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400824}
825
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400826const FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
827{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400828 return mState.getDepthStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400829}
830
831const FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000832{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400833 return mState.getDepthOrStencilAttachment();
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000834}
835
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500836const FramebufferAttachment *Framebuffer::getStencilOrDepthStencilAttachment() const
837{
838 return mState.getStencilOrDepthStencilAttachment();
839}
840
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400841const FramebufferAttachment *Framebuffer::getReadColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000842{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400843 return mState.getReadAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000844}
845
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000846GLenum Framebuffer::getReadColorbufferType() const
847{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400848 const FramebufferAttachment *readAttachment = mState.getReadAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400849 return (readAttachment != nullptr ? readAttachment->type() : GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000850}
851
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400852const FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000853{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400854 return mState.getFirstColorAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000855}
856
Jamie Madill6dd06ea2017-07-19 13:47:55 -0400857const FramebufferAttachment *Framebuffer::getFirstNonNullAttachment() const
858{
859 return mState.getFirstNonNullAttachment();
860}
861
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800862const FramebufferAttachment *Framebuffer::getAttachment(const Context *context,
863 GLenum attachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000864{
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800865 return mState.getAttachment(context, attachment);
Geoff Lang55ba29c2013-07-11 16:57:53 -0400866}
867
Geoff Langa15472a2015-08-11 11:48:03 -0400868size_t Framebuffer::getDrawbufferStateCount() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000869{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400870 return mState.mDrawBufferStates.size();
Geoff Langa15472a2015-08-11 11:48:03 -0400871}
872
873GLenum Framebuffer::getDrawBufferState(size_t drawBuffer) const
874{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400875 ASSERT(drawBuffer < mState.mDrawBufferStates.size());
876 return mState.mDrawBufferStates[drawBuffer];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000877}
878
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500879const std::vector<GLenum> &Framebuffer::getDrawBufferStates() const
880{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400881 return mState.getDrawBufferStates();
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500882}
883
Geoff Lang164d54e2014-12-01 10:55:33 -0500884void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000885{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400886 auto &drawStates = mState.mDrawBufferStates;
Jamie Madilld1405e52015-03-05 15:41:39 -0500887
888 ASSERT(count <= drawStates.size());
889 std::copy(buffers, buffers + count, drawStates.begin());
890 std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500891 mDirtyBits.set(DIRTY_BIT_DRAW_BUFFERS);
Jamie Madilla4595b82017-01-11 17:36:34 -0500892
893 mState.mEnabledDrawBuffers.reset();
Brandon Jones76746f92017-11-22 11:44:41 -0800894 mState.mDrawBufferTypeMask.reset();
895
Jamie Madilla4595b82017-01-11 17:36:34 -0500896 for (size_t index = 0; index < count; ++index)
897 {
Brandon Jones76746f92017-11-22 11:44:41 -0800898 mState.mDrawBufferTypeMask.setIndex(getDrawbufferWriteType(index), index);
899
Jamie Madilla4595b82017-01-11 17:36:34 -0500900 if (drawStates[index] != GL_NONE && mState.mColorAttachments[index].isAttached())
901 {
902 mState.mEnabledDrawBuffers.set(index);
903 }
904 }
Geoff Lang9dd95802014-12-01 11:12:59 -0500905}
906
Geoff Langa15472a2015-08-11 11:48:03 -0400907const FramebufferAttachment *Framebuffer::getDrawBuffer(size_t drawBuffer) const
908{
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400909 return mState.getDrawBuffer(drawBuffer);
Geoff Langa15472a2015-08-11 11:48:03 -0400910}
911
Geoff Lange0cff192017-05-30 13:04:56 -0400912GLenum Framebuffer::getDrawbufferWriteType(size_t drawBuffer) const
913{
914 const FramebufferAttachment *attachment = mState.getDrawBuffer(drawBuffer);
915 if (attachment == nullptr)
916 {
917 return GL_NONE;
918 }
919
920 GLenum componentType = attachment->getFormat().info->componentType;
921 switch (componentType)
922 {
923 case GL_INT:
924 case GL_UNSIGNED_INT:
925 return componentType;
926
927 default:
928 return GL_FLOAT;
929 }
930}
931
Brandon Jonesc405ae72017-12-06 14:15:03 -0800932ComponentTypeMask Framebuffer::getDrawBufferTypeMask() const
Brandon Jones76746f92017-11-22 11:44:41 -0800933{
934 return mState.mDrawBufferTypeMask;
935}
936
937DrawBufferMask Framebuffer::getDrawBufferMask() const
938{
939 return mState.mEnabledDrawBuffers;
940}
941
Geoff Langa15472a2015-08-11 11:48:03 -0400942bool Framebuffer::hasEnabledDrawBuffer() const
943{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400944 for (size_t drawbufferIdx = 0; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
Geoff Langa15472a2015-08-11 11:48:03 -0400945 {
946 if (getDrawBuffer(drawbufferIdx) != nullptr)
947 {
948 return true;
949 }
950 }
951
952 return false;
953}
954
Geoff Lang9dd95802014-12-01 11:12:59 -0500955GLenum Framebuffer::getReadBufferState() const
956{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400957 return mState.mReadBufferState;
Geoff Lang9dd95802014-12-01 11:12:59 -0500958}
959
960void Framebuffer::setReadBuffer(GLenum buffer)
961{
Jamie Madillb885e572015-02-03 16:16:04 -0500962 ASSERT(buffer == GL_BACK || buffer == GL_NONE ||
963 (buffer >= GL_COLOR_ATTACHMENT0 &&
Jamie Madill48ef11b2016-04-27 15:21:52 -0400964 (buffer - GL_COLOR_ATTACHMENT0) < mState.mColorAttachments.size()));
965 mState.mReadBufferState = buffer;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500966 mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000967}
968
Corentin Wallez37c39792015-08-20 14:19:46 -0400969size_t Framebuffer::getNumColorBuffers() const
970{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400971 return mState.mColorAttachments.size();
Corentin Wallez37c39792015-08-20 14:19:46 -0400972}
973
Jamie Madill0df8fe42015-11-24 16:10:24 -0500974bool Framebuffer::hasDepth() const
975{
Jamie Madill9c335862017-07-18 11:51:38 -0400976 return mState.hasDepth();
Jamie Madill0df8fe42015-11-24 16:10:24 -0500977}
978
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000979bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000980{
Jamie Madill9c335862017-07-18 11:51:38 -0400981 return mState.hasStencil();
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000982}
983
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000984bool Framebuffer::usingExtendedDrawBuffers() const
985{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400986 for (size_t drawbufferIdx = 1; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000987 {
Geoff Langa15472a2015-08-11 11:48:03 -0400988 if (getDrawBuffer(drawbufferIdx) != nullptr)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000989 {
990 return true;
991 }
992 }
993
994 return false;
995}
996
Geoff Lang9aded172017-04-05 11:07:56 -0400997void Framebuffer::invalidateCompletenessCache()
998{
Jamie Madill2274b652018-05-31 10:56:08 -0400999 if (mState.mId != 0)
Geoff Lang9aded172017-04-05 11:07:56 -04001000 {
1001 mCachedStatus.reset();
1002 }
1003}
1004
Jamie Madillcc73f242018-08-01 11:34:48 -04001005GLenum Framebuffer::checkStatusImpl(const Context *context)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001006{
Jamie Madillcc73f242018-08-01 11:34:48 -04001007 ASSERT(!isDefault());
1008 ASSERT(hasAnyDirtyBit() || !mCachedStatus.valid());
Geoff Lang528ce3c2014-12-01 10:44:07 -05001009
Jamie Madillcc73f242018-08-01 11:34:48 -04001010 mCachedStatus = checkStatusWithGLFrontEnd(context);
Jamie Madille98b1b52018-03-08 09:47:23 -05001011
Jamie Madillcc73f242018-08-01 11:34:48 -04001012 if (mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE)
1013 {
1014 Error err = syncState(context);
1015 if (err.isError())
Jamie Madille98b1b52018-03-08 09:47:23 -05001016 {
Jamie Madillcc73f242018-08-01 11:34:48 -04001017 // TODO(jmadill): Remove when refactor complete. http://anglebug.com/2491
1018 const_cast<Context *>(context)->handleError(err);
1019 return GetDefaultReturnValue<EntryPoint::CheckFramebufferStatus, GLenum>();
1020 }
1021 if (!mImpl->checkStatus(context))
1022 {
1023 mCachedStatus = GL_FRAMEBUFFER_UNSUPPORTED;
Jamie Madille98b1b52018-03-08 09:47:23 -05001024 }
Jamie Madill362876b2016-06-16 14:46:59 -04001025 }
1026
Jamie Madill427064d2018-04-13 16:20:34 -04001027 return mCachedStatus.value();
Jamie Madill362876b2016-06-16 14:46:59 -04001028}
1029
Jamie Madille98b1b52018-03-08 09:47:23 -05001030GLenum Framebuffer::checkStatusWithGLFrontEnd(const Context *context)
Jamie Madill362876b2016-06-16 14:46:59 -04001031{
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001032 const ContextState &state = context->getContextState();
1033
Jamie Madill2274b652018-05-31 10:56:08 -04001034 ASSERT(mState.mId != 0);
Jamie Madill362876b2016-06-16 14:46:59 -04001035
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001036 bool hasAttachments = false;
1037 Optional<unsigned int> colorbufferSize;
1038 Optional<int> samples;
Geoff Lang92019432017-11-20 13:09:34 -05001039 Optional<bool> fixedSampleLocations;
JiangYizhou461d9a32017-01-04 16:37:26 +08001040 bool hasRenderbuffer = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001041
Martin Radev9bc9a322017-07-21 14:28:17 +03001042 const FramebufferAttachment *firstAttachment = getFirstNonNullAttachment();
1043
Jiawei Shaoa8802472018-05-28 11:17:47 +08001044 Optional<bool> isLayered;
1045 Optional<TextureType> colorAttachmentsTextureType;
1046
Jamie Madill48ef11b2016-04-27 15:21:52 -04001047 for (const FramebufferAttachment &colorAttachment : mState.mColorAttachments)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001048 {
Jamie Madill2d06b732015-04-20 12:53:28 -04001049 if (colorAttachment.isAttached())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001050 {
Geoff Lang9f10b772017-05-16 15:51:03 -04001051 if (!CheckAttachmentCompleteness(context, colorAttachment))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001052 {
1053 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1054 }
daniel@transgaming.com01868132010-08-24 19:21:17 +00001055
Geoff Lang677bb6f2017-04-05 12:40:40 -04001056 const InternalFormat &format = *colorAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -04001057 if (format.depthBits > 0 || format.stencilBits > 0)
1058 {
1059 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1060 }
1061
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001062 if (!CheckAttachmentSampleCompleteness(context, colorAttachment, true, &samples,
1063 &fixedSampleLocations))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001064 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001065 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001066 }
1067
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001068 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
1069 // in GLES 3.0, there is no such restriction
1070 if (state.getClientMajorVersion() < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001071 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001072 if (colorbufferSize.valid())
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001073 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001074 if (format.pixelBytes != colorbufferSize.value())
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +00001075 {
1076 return GL_FRAMEBUFFER_UNSUPPORTED;
1077 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001078 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001079 else
1080 {
1081 colorbufferSize = format.pixelBytes;
1082 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001083 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001084
Martin Radev9bc9a322017-07-21 14:28:17 +03001085 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &colorAttachment))
1086 {
1087 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
1088 }
1089
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001090 hasRenderbuffer = hasRenderbuffer || (colorAttachment.type() == GL_RENDERBUFFER);
Jiawei Shaoa8802472018-05-28 11:17:47 +08001091
1092 if (!hasAttachments)
1093 {
1094 isLayered = colorAttachment.isLayered();
1095 if (isLayered.value())
1096 {
1097 colorAttachmentsTextureType = colorAttachment.getTextureImageIndex().getType();
1098 }
1099 hasAttachments = true;
1100 }
1101 else
1102 {
1103 // [EXT_geometry_shader] section 9.4.1, "Framebuffer Completeness"
1104 // If any framebuffer attachment is layered, all populated attachments
1105 // must be layered. Additionally, all populated color attachments must
1106 // be from textures of the same target. {FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT }
1107 ASSERT(isLayered.valid());
1108 if (isLayered.value() != colorAttachment.isLayered())
1109 {
1110 return GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT;
1111 }
1112 else if (isLayered.value())
1113 {
1114 ASSERT(colorAttachmentsTextureType.valid());
1115 if (colorAttachmentsTextureType.value() !=
1116 colorAttachment.getTextureImageIndex().getType())
1117 {
1118 return GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT;
1119 }
1120 }
1121 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001122 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001123 }
1124
Jamie Madill48ef11b2016-04-27 15:21:52 -04001125 const FramebufferAttachment &depthAttachment = mState.mDepthAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -04001126 if (depthAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001127 {
Geoff Lang9f10b772017-05-16 15:51:03 -04001128 if (!CheckAttachmentCompleteness(context, depthAttachment))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001129 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001130 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001131 }
1132
Geoff Lang677bb6f2017-04-05 12:40:40 -04001133 const InternalFormat &format = *depthAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -04001134 if (format.depthBits == 0)
1135 {
1136 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001137 }
1138
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001139 if (!CheckAttachmentSampleCompleteness(context, depthAttachment, false, &samples,
1140 &fixedSampleLocations))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001141 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001142 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001143 }
Sami Väisänena797e062016-05-12 15:23:40 +03001144
Martin Radev9bc9a322017-07-21 14:28:17 +03001145 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &depthAttachment))
1146 {
1147 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
1148 }
1149
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001150 hasRenderbuffer = hasRenderbuffer || (depthAttachment.type() == GL_RENDERBUFFER);
Jiawei Shaoa8802472018-05-28 11:17:47 +08001151
1152 if (!hasAttachments)
1153 {
1154 isLayered = depthAttachment.isLayered();
1155 hasAttachments = true;
1156 }
1157 else
1158 {
1159 // [EXT_geometry_shader] section 9.4.1, "Framebuffer Completeness"
1160 // If any framebuffer attachment is layered, all populated attachments
1161 // must be layered. {FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT }
1162 ASSERT(isLayered.valid());
1163 if (isLayered.value() != depthAttachment.isLayered())
1164 {
1165 return GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT;
1166 }
1167 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001168 }
1169
Jamie Madill48ef11b2016-04-27 15:21:52 -04001170 const FramebufferAttachment &stencilAttachment = mState.mStencilAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -04001171 if (stencilAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001172 {
Geoff Lang9f10b772017-05-16 15:51:03 -04001173 if (!CheckAttachmentCompleteness(context, stencilAttachment))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001174 {
1175 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1176 }
1177
Geoff Lang677bb6f2017-04-05 12:40:40 -04001178 const InternalFormat &format = *stencilAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -04001179 if (format.stencilBits == 0)
1180 {
1181 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001182 }
1183
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001184 if (!CheckAttachmentSampleCompleteness(context, stencilAttachment, false, &samples,
1185 &fixedSampleLocations))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001186 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001187 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001188 }
Corentin Wallez086d59a2016-04-29 09:06:49 -04001189
Martin Radev9bc9a322017-07-21 14:28:17 +03001190 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &stencilAttachment))
1191 {
1192 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
1193 }
1194
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001195 hasRenderbuffer = hasRenderbuffer || (stencilAttachment.type() == GL_RENDERBUFFER);
Jiawei Shaoa8802472018-05-28 11:17:47 +08001196
1197 if (!hasAttachments)
1198 {
1199 hasAttachments = true;
1200 }
1201 else
1202 {
1203 // [EXT_geometry_shader] section 9.4.1, "Framebuffer Completeness"
1204 // If any framebuffer attachment is layered, all populated attachments
1205 // must be layered.
1206 // {FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT }
1207 ASSERT(isLayered.valid());
1208 if (isLayered.value() != stencilAttachment.isLayered())
1209 {
1210 return GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT;
1211 }
1212 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001213 }
1214
1215 // Starting from ES 3.0 stencil and depth, if present, should be the same image
1216 if (state.getClientMajorVersion() >= 3 && depthAttachment.isAttached() &&
1217 stencilAttachment.isAttached() && stencilAttachment != depthAttachment)
1218 {
1219 return GL_FRAMEBUFFER_UNSUPPORTED;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001220 }
1221
Jamie Madilla02315b2017-02-23 14:14:47 -05001222 // Special additional validation for WebGL 1 DEPTH/STENCIL/DEPTH_STENCIL.
1223 if (state.isWebGL1())
1224 {
1225 if (!mState.mWebGLDepthStencilConsistent)
1226 {
1227 return GL_FRAMEBUFFER_UNSUPPORTED;
1228 }
1229
1230 if (mState.mWebGLDepthStencilAttachment.isAttached())
1231 {
1232 if (mState.mWebGLDepthStencilAttachment.getDepthSize() == 0 ||
1233 mState.mWebGLDepthStencilAttachment.getStencilSize() == 0)
1234 {
1235 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1236 }
Martin Radev9bc9a322017-07-21 14:28:17 +03001237
1238 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment,
1239 &mState.mWebGLDepthStencilAttachment))
1240 {
1241 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
1242 }
Jamie Madilla02315b2017-02-23 14:14:47 -05001243 }
1244 else if (mState.mStencilAttachment.isAttached() &&
1245 mState.mStencilAttachment.getDepthSize() > 0)
1246 {
1247 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1248 }
1249 else if (mState.mDepthAttachment.isAttached() &&
1250 mState.mDepthAttachment.getStencilSize() > 0)
1251 {
1252 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1253 }
1254 }
1255
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001256 // ES3.1(section 9.4) requires that if no image is attached to the framebuffer, and either the
1257 // value of the framebuffer's FRAMEBUFFER_DEFAULT_WIDTH or FRAMEBUFFER_DEFAULT_HEIGHT parameters
1258 // is zero, the framebuffer is considered incomplete.
JiangYizhou461d9a32017-01-04 16:37:26 +08001259 GLint defaultWidth = mState.getDefaultWidth();
1260 GLint defaultHeight = mState.getDefaultHeight();
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001261 if (!hasAttachments && (defaultWidth == 0 || defaultHeight == 0))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001262 {
1263 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001264 }
1265
Geoff Langa0e0aeb2017-04-12 15:06:29 -04001266 // In ES 2.0 and WebGL, all color attachments must have the same width and height.
Jamie Madillcc86d642015-11-24 13:00:07 -05001267 // In ES 3.0, there is no such restriction.
Geoff Langa0e0aeb2017-04-12 15:06:29 -04001268 if ((state.getClientMajorVersion() < 3 || state.getExtensions().webglCompatibility) &&
1269 !mState.attachmentsHaveSameDimensions())
Jamie Madillcc86d642015-11-24 13:00:07 -05001270 {
1271 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
1272 }
1273
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001274 // ES3.1(section 9.4) requires that if the attached images are a mix of renderbuffers and
1275 // textures, the value of TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all attached textures.
JiangYizhou461d9a32017-01-04 16:37:26 +08001276 if (fixedSampleLocations.valid() && hasRenderbuffer && !fixedSampleLocations.value())
1277 {
1278 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1279 }
1280
Kenneth Russellce8602a2017-10-03 18:23:08 -07001281 // The WebGL conformance tests implicitly define that all framebuffer
1282 // attachments must be unique. For example, the same level of a texture can
1283 // not be attached to two different color attachments.
1284 if (state.getExtensions().webglCompatibility)
1285 {
1286 if (!mState.colorAttachmentsAreUniqueImages())
1287 {
1288 return GL_FRAMEBUFFER_UNSUPPORTED;
1289 }
1290 }
1291
Jamie Madillcc86d642015-11-24 13:00:07 -05001292 return GL_FRAMEBUFFER_COMPLETE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001293}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001294
Jamie Madill4928b7c2017-06-20 12:57:39 -04001295Error Framebuffer::discard(const Context *context, size_t count, const GLenum *attachments)
Austin Kinross08332632015-05-05 13:35:47 -07001296{
Jamie Madill05b35b22017-10-03 09:01:44 -04001297 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1298 // can be no-ops, so we should probably do that to ensure consistency.
1299 // TODO(jmadill): WebGL behaviour, and robust resource init behaviour without WebGL.
1300
Jamie Madill4928b7c2017-06-20 12:57:39 -04001301 return mImpl->discard(context, count, attachments);
Austin Kinross08332632015-05-05 13:35:47 -07001302}
1303
Jamie Madill4928b7c2017-06-20 12:57:39 -04001304Error Framebuffer::invalidate(const Context *context, size_t count, const GLenum *attachments)
Jamie Madill2d96b9e2014-08-29 15:46:47 -04001305{
Jamie Madill05b35b22017-10-03 09:01:44 -04001306 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1307 // can be no-ops, so we should probably do that to ensure consistency.
1308 // TODO(jmadill): WebGL behaviour, and robust resource init behaviour without WebGL.
1309
Jamie Madill4928b7c2017-06-20 12:57:39 -04001310 return mImpl->invalidate(context, count, attachments);
Jamie Madill2d96b9e2014-08-29 15:46:47 -04001311}
1312
Jamie Madill05b35b22017-10-03 09:01:44 -04001313bool Framebuffer::partialClearNeedsInit(const Context *context,
1314 bool color,
1315 bool depth,
1316 bool stencil)
1317{
1318 const auto &glState = context->getGLState();
1319
1320 if (!glState.isRobustResourceInitEnabled())
1321 {
1322 return false;
1323 }
1324
1325 // Scissors can affect clearing.
1326 // TODO(jmadill): Check for complete scissor overlap.
1327 if (glState.isScissorTestEnabled())
1328 {
1329 return true;
1330 }
1331
1332 // If colors masked, we must clear before we clear. Do a simple check.
1333 // TODO(jmadill): Filter out unused color channels from the test.
1334 if (color)
1335 {
1336 const auto &blend = glState.getBlendState();
1337 if (!(blend.colorMaskRed && blend.colorMaskGreen && blend.colorMaskBlue &&
1338 blend.colorMaskAlpha))
1339 {
1340 return true;
1341 }
1342 }
1343
1344 const auto &depthStencil = glState.getDepthStencilState();
Yuly Novikov21edf3d2018-07-23 16:44:16 -04001345 if (stencil && (depthStencil.stencilMask != depthStencil.stencilWritemask ||
1346 depthStencil.stencilBackMask != depthStencil.stencilBackWritemask))
Jamie Madill05b35b22017-10-03 09:01:44 -04001347 {
1348 return true;
1349 }
1350
1351 return false;
1352}
1353
Jamie Madill4928b7c2017-06-20 12:57:39 -04001354Error Framebuffer::invalidateSub(const Context *context,
1355 size_t count,
1356 const GLenum *attachments,
Jamie Madilld4442552018-02-27 22:03:47 -05001357 const Rectangle &area)
Jamie Madill400a4412014-08-29 15:46:45 -04001358{
Jamie Madill05b35b22017-10-03 09:01:44 -04001359 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1360 // can be no-ops, so we should probably do that to ensure consistency.
1361 // TODO(jmadill): Make a invalidate no-op in WebGL 2.0.
1362
Jamie Madill4928b7c2017-06-20 12:57:39 -04001363 return mImpl->invalidateSub(context, count, attachments, area);
Jamie Madill400a4412014-08-29 15:46:45 -04001364}
1365
Jamie Madilld4442552018-02-27 22:03:47 -05001366Error Framebuffer::clear(const Context *context, GLbitfield mask)
Geoff Langb04dc822014-12-01 12:02:02 -05001367{
Jamie Madill05b35b22017-10-03 09:01:44 -04001368 const auto &glState = context->getGLState();
1369 if (glState.isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -05001370 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001371 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001372 }
1373
Jamie Madill05b35b22017-10-03 09:01:44 -04001374 ANGLE_TRY(mImpl->clear(context, mask));
1375
Jamie Madill05b35b22017-10-03 09:01:44 -04001376 return NoError();
Geoff Langb04dc822014-12-01 12:02:02 -05001377}
1378
Jamie Madilld4442552018-02-27 22:03:47 -05001379Error Framebuffer::clearBufferfv(const Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001380 GLenum buffer,
1381 GLint drawbuffer,
1382 const GLfloat *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001383{
Jamie Madill05b35b22017-10-03 09:01:44 -04001384 if (context->getGLState().isRasterizerDiscardEnabled() ||
1385 IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001386 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001387 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001388 }
1389
Jamie Madill05b35b22017-10-03 09:01:44 -04001390 ANGLE_TRY(mImpl->clearBufferfv(context, buffer, drawbuffer, values));
1391
Jamie Madill05b35b22017-10-03 09:01:44 -04001392 return NoError();
Geoff Langb04dc822014-12-01 12:02:02 -05001393}
1394
Jamie Madilld4442552018-02-27 22:03:47 -05001395Error Framebuffer::clearBufferuiv(const Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001396 GLenum buffer,
1397 GLint drawbuffer,
1398 const GLuint *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001399{
Jamie Madill05b35b22017-10-03 09:01:44 -04001400 if (context->getGLState().isRasterizerDiscardEnabled() ||
1401 IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001402 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001403 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001404 }
1405
Jamie Madill05b35b22017-10-03 09:01:44 -04001406 ANGLE_TRY(mImpl->clearBufferuiv(context, buffer, drawbuffer, values));
1407
Jamie Madill05b35b22017-10-03 09:01:44 -04001408 return NoError();
Geoff Langb04dc822014-12-01 12:02:02 -05001409}
1410
Jamie Madilld4442552018-02-27 22:03:47 -05001411Error Framebuffer::clearBufferiv(const Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001412 GLenum buffer,
1413 GLint drawbuffer,
1414 const GLint *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001415{
Jamie Madill05b35b22017-10-03 09:01:44 -04001416 if (context->getGLState().isRasterizerDiscardEnabled() ||
1417 IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001418 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001419 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001420 }
1421
Jamie Madill05b35b22017-10-03 09:01:44 -04001422 ANGLE_TRY(mImpl->clearBufferiv(context, buffer, drawbuffer, values));
1423
Jamie Madill05b35b22017-10-03 09:01:44 -04001424 return NoError();
Geoff Langb04dc822014-12-01 12:02:02 -05001425}
1426
Jamie Madilld4442552018-02-27 22:03:47 -05001427Error Framebuffer::clearBufferfi(const Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001428 GLenum buffer,
1429 GLint drawbuffer,
1430 GLfloat depth,
1431 GLint stencil)
Geoff Langb04dc822014-12-01 12:02:02 -05001432{
Jamie Madill05b35b22017-10-03 09:01:44 -04001433 if (context->getGLState().isRasterizerDiscardEnabled() ||
1434 IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001435 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001436 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001437 }
1438
Jamie Madill05b35b22017-10-03 09:01:44 -04001439 ANGLE_TRY(mImpl->clearBufferfi(context, buffer, drawbuffer, depth, stencil));
1440
Jamie Madill05b35b22017-10-03 09:01:44 -04001441 return NoError();
Geoff Langb04dc822014-12-01 12:02:02 -05001442}
1443
Jamie Madill690c8eb2018-03-12 15:20:03 -04001444Error Framebuffer::getImplementationColorReadFormat(const Context *context, GLenum *formatOut)
Geoff Langbce529e2014-12-01 12:48:41 -05001445{
Jamie Madill690c8eb2018-03-12 15:20:03 -04001446 ANGLE_TRY(syncState(context));
1447 *formatOut = mImpl->getImplementationColorReadFormat(context);
1448 return NoError();
Geoff Langbce529e2014-12-01 12:48:41 -05001449}
1450
Jamie Madill690c8eb2018-03-12 15:20:03 -04001451Error Framebuffer::getImplementationColorReadType(const Context *context, GLenum *typeOut)
Geoff Langbce529e2014-12-01 12:48:41 -05001452{
Jamie Madill690c8eb2018-03-12 15:20:03 -04001453 ANGLE_TRY(syncState(context));
1454 *typeOut = mImpl->getImplementationColorReadType(context);
1455 return NoError();
Geoff Langbce529e2014-12-01 12:48:41 -05001456}
1457
Jamie Madilld4442552018-02-27 22:03:47 -05001458Error Framebuffer::readPixels(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001459 const Rectangle &area,
Jamie Madill1b94d432015-08-07 13:23:23 -04001460 GLenum format,
1461 GLenum type,
Jamie Madill05b35b22017-10-03 09:01:44 -04001462 void *pixels)
Geoff Langbce529e2014-12-01 12:48:41 -05001463{
Jamie Madill05b35b22017-10-03 09:01:44 -04001464 ANGLE_TRY(ensureReadAttachmentInitialized(context, GL_COLOR_BUFFER_BIT));
Jamie Madill362876b2016-06-16 14:46:59 -04001465 ANGLE_TRY(mImpl->readPixels(context, area, format, type, pixels));
Geoff Lang520c4ae2015-05-05 13:12:36 -04001466
Jamie Madilld4442552018-02-27 22:03:47 -05001467 Buffer *unpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Lang520c4ae2015-05-05 13:12:36 -04001468 if (unpackBuffer)
1469 {
Jamie Madill09463932018-04-04 05:26:59 -04001470 unpackBuffer->onPixelPack(context);
Geoff Lang520c4ae2015-05-05 13:12:36 -04001471 }
1472
Jamie Madill362876b2016-06-16 14:46:59 -04001473 return NoError();
Geoff Langbce529e2014-12-01 12:48:41 -05001474}
1475
Jamie Madilld4442552018-02-27 22:03:47 -05001476Error Framebuffer::blit(const Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001477 const Rectangle &sourceArea,
1478 const Rectangle &destArea,
Geoff Lang242468f2015-09-24 14:15:41 -04001479 GLbitfield mask,
Jamie Madill8415b5f2016-04-26 13:41:39 -04001480 GLenum filter)
Geoff Lang54bd5a42014-12-01 12:51:04 -05001481{
He Yunchao6be602d2016-12-22 14:33:07 +08001482 GLbitfield blitMask = mask;
1483
1484 // Note that blitting is called against draw framebuffer.
1485 // See the code in gl::Context::blitFramebuffer.
1486 if ((mask & GL_COLOR_BUFFER_BIT) && !hasEnabledDrawBuffer())
1487 {
1488 blitMask &= ~GL_COLOR_BUFFER_BIT;
1489 }
1490
1491 if ((mask & GL_STENCIL_BUFFER_BIT) && mState.getStencilAttachment() == nullptr)
1492 {
1493 blitMask &= ~GL_STENCIL_BUFFER_BIT;
1494 }
1495
1496 if ((mask & GL_DEPTH_BUFFER_BIT) && mState.getDepthAttachment() == nullptr)
1497 {
1498 blitMask &= ~GL_DEPTH_BUFFER_BIT;
1499 }
1500
1501 if (!blitMask)
1502 {
1503 return NoError();
1504 }
1505
Jamie Madill05b35b22017-10-03 09:01:44 -04001506 auto *sourceFBO = context->getGLState().getReadFramebuffer();
1507 ANGLE_TRY(sourceFBO->ensureReadAttachmentInitialized(context, blitMask));
1508
1509 // TODO(jmadill): Only clear if not the full FBO dimensions, and only specified bitmask.
1510 ANGLE_TRY(ensureDrawAttachmentsInitialized(context));
1511
He Yunchao6be602d2016-12-22 14:33:07 +08001512 return mImpl->blit(context, sourceArea, destArea, blitMask, filter);
Geoff Lang54bd5a42014-12-01 12:51:04 -05001513}
1514
Luc Ferronbf6dc372018-06-28 15:24:19 -04001515bool Framebuffer::isDefault() const
1516{
1517 return id() == 0;
1518}
1519
Jamie Madill427064d2018-04-13 16:20:34 -04001520int Framebuffer::getSamples(const Context *context)
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001521{
Jamie Madill427064d2018-04-13 16:20:34 -04001522 return (isComplete(context) ? getCachedSamples(context) : 0);
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001523}
1524
Jamie Madill9c335862017-07-18 11:51:38 -04001525int Framebuffer::getCachedSamples(const Context *context)
1526{
Jamie Madill5b772312018-03-08 20:28:32 -05001527 ASSERT(mCachedStatus.valid() && mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE);
1528
Jamie Madill9c335862017-07-18 11:51:38 -04001529 // For a complete framebuffer, all attachments must have the same sample count.
1530 // In this case return the first nonzero sample size.
1531 const auto *firstNonNullAttachment = mState.getFirstNonNullAttachment();
1532 if (firstNonNullAttachment)
1533 {
1534 ASSERT(firstNonNullAttachment->isAttached());
1535 return firstNonNullAttachment->getSamples();
1536 }
1537
1538 // No attachments found.
1539 return 0;
1540}
1541
Geoff Lang13455072018-05-09 11:24:43 -04001542Error Framebuffer::getSamplePosition(const Context *context, size_t index, GLfloat *xy) const
Corentin Wallezccab69d2017-01-27 16:57:15 -05001543{
Geoff Lang13455072018-05-09 11:24:43 -04001544 ANGLE_TRY(mImpl->getSamplePosition(context, index, xy));
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001545 return NoError();
Corentin Wallezccab69d2017-01-27 16:57:15 -05001546}
1547
Jamie Madille261b442014-06-25 12:42:21 -04001548bool Framebuffer::hasValidDepthStencil() const
1549{
Jamie Madill48ef11b2016-04-27 15:21:52 -04001550 return mState.getDepthStencilAttachment() != nullptr;
Jamie Madille261b442014-06-25 12:42:21 -04001551}
1552
Jamie Madilla02315b2017-02-23 14:14:47 -05001553void Framebuffer::setAttachment(const Context *context,
1554 GLenum type,
Jamie Madill2d06b732015-04-20 12:53:28 -04001555 GLenum binding,
1556 const ImageIndex &textureIndex,
1557 FramebufferAttachmentObject *resource)
Geoff Langab75a052014-10-15 12:56:37 -04001558{
Martin Radev5dae57b2017-07-14 16:15:55 +03001559 setAttachment(context, type, binding, textureIndex, resource,
1560 FramebufferAttachment::kDefaultNumViews,
1561 FramebufferAttachment::kDefaultBaseViewIndex,
1562 FramebufferAttachment::kDefaultMultiviewLayout,
1563 FramebufferAttachment::kDefaultViewportOffsets);
1564}
1565
1566void Framebuffer::setAttachment(const Context *context,
1567 GLenum type,
1568 GLenum binding,
1569 const ImageIndex &textureIndex,
1570 FramebufferAttachmentObject *resource,
1571 GLsizei numViews,
1572 GLuint baseViewIndex,
1573 GLenum multiviewLayout,
1574 const GLint *viewportOffsets)
1575{
Jamie Madilla02315b2017-02-23 14:14:47 -05001576 // Context may be null in unit tests.
1577 if (!context || !context->isWebGL1())
1578 {
Martin Radev5dae57b2017-07-14 16:15:55 +03001579 setAttachmentImpl(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
1580 multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001581 return;
1582 }
1583
1584 switch (binding)
1585 {
1586 case GL_DEPTH_STENCIL:
1587 case GL_DEPTH_STENCIL_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001588 mState.mWebGLDepthStencilAttachment.attach(context, type, binding, textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001589 resource, numViews, baseViewIndex,
1590 multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001591 break;
1592 case GL_DEPTH:
1593 case GL_DEPTH_ATTACHMENT:
Martin Radev5dae57b2017-07-14 16:15:55 +03001594 mState.mWebGLDepthAttachment.attach(context, type, binding, textureIndex, resource,
1595 numViews, baseViewIndex, multiviewLayout,
1596 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001597 break;
1598 case GL_STENCIL:
1599 case GL_STENCIL_ATTACHMENT:
Martin Radev5dae57b2017-07-14 16:15:55 +03001600 mState.mWebGLStencilAttachment.attach(context, type, binding, textureIndex, resource,
1601 numViews, baseViewIndex, multiviewLayout,
1602 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001603 break;
1604 default:
Martin Radev5dae57b2017-07-14 16:15:55 +03001605 setAttachmentImpl(context, type, binding, textureIndex, resource, numViews,
1606 baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001607 return;
1608 }
1609
Martin Radev5dae57b2017-07-14 16:15:55 +03001610 commitWebGL1DepthStencilIfConsistent(context, numViews, baseViewIndex, multiviewLayout,
1611 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001612}
1613
Martin Radev82ef7742017-08-08 17:44:58 +03001614void Framebuffer::setAttachmentMultiviewLayered(const Context *context,
1615 GLenum type,
1616 GLenum binding,
1617 const ImageIndex &textureIndex,
1618 FramebufferAttachmentObject *resource,
1619 GLsizei numViews,
1620 GLint baseViewIndex)
1621{
1622 setAttachment(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
1623 GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE,
1624 FramebufferAttachment::kDefaultViewportOffsets);
1625}
1626
Martin Radev5dae57b2017-07-14 16:15:55 +03001627void Framebuffer::setAttachmentMultiviewSideBySide(const Context *context,
1628 GLenum type,
1629 GLenum binding,
1630 const ImageIndex &textureIndex,
1631 FramebufferAttachmentObject *resource,
1632 GLsizei numViews,
1633 const GLint *viewportOffsets)
1634{
1635 setAttachment(context, type, binding, textureIndex, resource, numViews,
1636 FramebufferAttachment::kDefaultBaseViewIndex,
1637 GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, viewportOffsets);
1638}
1639
1640void Framebuffer::commitWebGL1DepthStencilIfConsistent(const Context *context,
1641 GLsizei numViews,
1642 GLuint baseViewIndex,
1643 GLenum multiviewLayout,
1644 const GLint *viewportOffsets)
Jamie Madilla02315b2017-02-23 14:14:47 -05001645{
1646 int count = 0;
1647
1648 std::array<FramebufferAttachment *, 3> attachments = {{&mState.mWebGLDepthStencilAttachment,
1649 &mState.mWebGLDepthAttachment,
1650 &mState.mWebGLStencilAttachment}};
1651 for (FramebufferAttachment *attachment : attachments)
1652 {
1653 if (attachment->isAttached())
1654 {
1655 count++;
1656 }
1657 }
1658
1659 mState.mWebGLDepthStencilConsistent = (count <= 1);
1660 if (!mState.mWebGLDepthStencilConsistent)
1661 {
1662 // Inconsistent.
1663 return;
1664 }
1665
Geoff Lange466c552017-03-17 15:24:12 -04001666 auto getImageIndexIfTextureAttachment = [](const FramebufferAttachment &attachment) {
1667 if (attachment.type() == GL_TEXTURE)
1668 {
1669 return attachment.getTextureImageIndex();
1670 }
1671 else
1672 {
Jamie Madillcc129372018-04-12 09:13:18 -04001673 return ImageIndex();
Geoff Lange466c552017-03-17 15:24:12 -04001674 }
1675 };
1676
Jamie Madilla02315b2017-02-23 14:14:47 -05001677 if (mState.mWebGLDepthAttachment.isAttached())
1678 {
1679 const auto &depth = mState.mWebGLDepthAttachment;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001680 setAttachmentImpl(context, depth.type(), GL_DEPTH_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001681 getImageIndexIfTextureAttachment(depth), depth.getResource(), numViews,
1682 baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madillcc129372018-04-12 09:13:18 -04001683 setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex(), nullptr, numViews,
1684 baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001685 }
1686 else if (mState.mWebGLStencilAttachment.isAttached())
1687 {
1688 const auto &stencil = mState.mWebGLStencilAttachment;
Jamie Madillcc129372018-04-12 09:13:18 -04001689 setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex(), nullptr, numViews,
1690 baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001691 setAttachmentImpl(context, stencil.type(), GL_STENCIL_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001692 getImageIndexIfTextureAttachment(stencil), stencil.getResource(),
1693 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001694 }
1695 else if (mState.mWebGLDepthStencilAttachment.isAttached())
1696 {
1697 const auto &depthStencil = mState.mWebGLDepthStencilAttachment;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001698 setAttachmentImpl(context, depthStencil.type(), GL_DEPTH_ATTACHMENT,
Geoff Lange466c552017-03-17 15:24:12 -04001699 getImageIndexIfTextureAttachment(depthStencil),
Martin Radev5dae57b2017-07-14 16:15:55 +03001700 depthStencil.getResource(), numViews, baseViewIndex, multiviewLayout,
1701 viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001702 setAttachmentImpl(context, depthStencil.type(), GL_STENCIL_ATTACHMENT,
Geoff Lange466c552017-03-17 15:24:12 -04001703 getImageIndexIfTextureAttachment(depthStencil),
Martin Radev5dae57b2017-07-14 16:15:55 +03001704 depthStencil.getResource(), numViews, baseViewIndex, multiviewLayout,
1705 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001706 }
1707 else
1708 {
Jamie Madillcc129372018-04-12 09:13:18 -04001709 setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex(), nullptr, numViews,
1710 baseViewIndex, multiviewLayout, viewportOffsets);
1711 setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex(), nullptr, numViews,
1712 baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001713 }
1714}
1715
Jamie Madill4928b7c2017-06-20 12:57:39 -04001716void Framebuffer::setAttachmentImpl(const Context *context,
1717 GLenum type,
Jamie Madilla02315b2017-02-23 14:14:47 -05001718 GLenum binding,
1719 const ImageIndex &textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001720 FramebufferAttachmentObject *resource,
1721 GLsizei numViews,
1722 GLuint baseViewIndex,
1723 GLenum multiviewLayout,
1724 const GLint *viewportOffsets)
Jamie Madilla02315b2017-02-23 14:14:47 -05001725{
Jamie Madilla02315b2017-02-23 14:14:47 -05001726 switch (binding)
1727 {
Jamie Madillb8126692017-04-05 11:22:17 -04001728 case GL_DEPTH_STENCIL:
1729 case GL_DEPTH_STENCIL_ATTACHMENT:
1730 {
1731 // ensure this is a legitimate depth+stencil format
1732 FramebufferAttachmentObject *attachmentObj = resource;
1733 if (resource)
1734 {
Jamie Madill4fd95d52017-04-05 11:22:18 -04001735 const Format &format = resource->getAttachmentFormat(binding, textureIndex);
Jamie Madillb8126692017-04-05 11:22:17 -04001736 if (format.info->depthBits == 0 || format.info->stencilBits == 0)
1737 {
1738 // Attaching nullptr detaches the current attachment.
1739 attachmentObj = nullptr;
1740 }
1741 }
1742
Jamie Madill4928b7c2017-06-20 12:57:39 -04001743 updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
Jamie Madillb8126692017-04-05 11:22:17 -04001744 &mDirtyDepthAttachmentBinding, type, binding, textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001745 attachmentObj, numViews, baseViewIndex, multiviewLayout,
1746 viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001747 updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
Jamie Madillb8126692017-04-05 11:22:17 -04001748 &mDirtyStencilAttachmentBinding, type, binding, textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001749 attachmentObj, numViews, baseViewIndex, multiviewLayout,
1750 viewportOffsets);
Jamie Madill42975642017-10-12 12:31:51 -04001751 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001752 }
1753
Jamie Madilla02315b2017-02-23 14:14:47 -05001754 case GL_DEPTH:
1755 case GL_DEPTH_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001756 updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001757 &mDirtyDepthAttachmentBinding, type, binding, textureIndex, resource,
1758 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madill2d06b732015-04-20 12:53:28 -04001759 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001760
Jamie Madilla02315b2017-02-23 14:14:47 -05001761 case GL_STENCIL:
1762 case GL_STENCIL_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001763 updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001764 &mDirtyStencilAttachmentBinding, type, binding, textureIndex, resource,
1765 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001766 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001767
Jamie Madilla02315b2017-02-23 14:14:47 -05001768 case GL_BACK:
Geoff Lang8170eab2017-09-21 13:59:04 -04001769 updateAttachment(context, &mState.mColorAttachments[0], DIRTY_BIT_COLOR_ATTACHMENT_0,
1770 &mDirtyColorAttachmentBindings[0], type, binding, textureIndex,
1771 resource, numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001772 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001773
Jamie Madilla02315b2017-02-23 14:14:47 -05001774 default:
1775 {
1776 size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
1777 ASSERT(colorIndex < mState.mColorAttachments.size());
Jamie Madillb8126692017-04-05 11:22:17 -04001778 size_t dirtyBit = DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001779 updateAttachment(context, &mState.mColorAttachments[colorIndex], dirtyBit,
Jamie Madillb8126692017-04-05 11:22:17 -04001780 &mDirtyColorAttachmentBindings[colorIndex], type, binding,
Martin Radev5dae57b2017-07-14 16:15:55 +03001781 textureIndex, resource, numViews, baseViewIndex, multiviewLayout,
1782 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001783
Corentin Walleze7557742017-06-01 13:09:57 -04001784 // TODO(jmadill): ASSERT instead of checking the attachment exists in
1785 // formsRenderingFeedbackLoopWith
Jamie Madilla02315b2017-02-23 14:14:47 -05001786 bool enabled = (type != GL_NONE && getDrawBufferState(colorIndex) != GL_NONE);
1787 mState.mEnabledDrawBuffers.set(colorIndex, enabled);
Brandon Jones76746f92017-11-22 11:44:41 -08001788 mState.mDrawBufferTypeMask.setIndex(getDrawbufferWriteType(colorIndex), colorIndex);
Jamie Madill2d06b732015-04-20 12:53:28 -04001789 }
Jamie Madilla02315b2017-02-23 14:14:47 -05001790 break;
Geoff Langab75a052014-10-15 12:56:37 -04001791 }
Jamie Madill42975642017-10-12 12:31:51 -04001792
1793 mAttachedTextures.reset();
Geoff Langab75a052014-10-15 12:56:37 -04001794}
1795
Jamie Madill4928b7c2017-06-20 12:57:39 -04001796void Framebuffer::updateAttachment(const Context *context,
1797 FramebufferAttachment *attachment,
Jamie Madillb8126692017-04-05 11:22:17 -04001798 size_t dirtyBit,
Jamie Madilld4442552018-02-27 22:03:47 -05001799 angle::ObserverBinding *onDirtyBinding,
Jamie Madillb8126692017-04-05 11:22:17 -04001800 GLenum type,
1801 GLenum binding,
1802 const ImageIndex &textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001803 FramebufferAttachmentObject *resource,
1804 GLsizei numViews,
1805 GLuint baseViewIndex,
1806 GLenum multiviewLayout,
1807 const GLint *viewportOffsets)
Jamie Madillb8126692017-04-05 11:22:17 -04001808{
Martin Radev5dae57b2017-07-14 16:15:55 +03001809 attachment->attach(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
1810 multiviewLayout, viewportOffsets);
Jamie Madillb8126692017-04-05 11:22:17 -04001811 mDirtyBits.set(dirtyBit);
Jamie Madill05b35b22017-10-03 09:01:44 -04001812 mState.mResourceNeedsInit.set(dirtyBit, attachment->initState() == InitState::MayNeedInit);
Jamie Madill888081d2018-02-27 00:24:46 -05001813 onDirtyBinding->bind(resource ? resource->getSubject() : nullptr);
Jamie Madille98b1b52018-03-08 09:47:23 -05001814
1815 invalidateCompletenessCache();
Jamie Madillb8126692017-04-05 11:22:17 -04001816}
1817
Jamie Madilla02315b2017-02-23 14:14:47 -05001818void Framebuffer::resetAttachment(const Context *context, GLenum binding)
Jamie Madill2d06b732015-04-20 12:53:28 -04001819{
Jamie Madillcc129372018-04-12 09:13:18 -04001820 setAttachment(context, GL_NONE, binding, ImageIndex(), nullptr);
Jamie Madill2d06b732015-04-20 12:53:28 -04001821}
1822
Jamie Madill19fa1c62018-03-08 09:47:21 -05001823Error Framebuffer::syncState(const Context *context)
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001824{
1825 if (mDirtyBits.any())
1826 {
Jamie Madill888081d2018-02-27 00:24:46 -05001827 mDirtyBitsGuard = mDirtyBits;
Jamie Madill19fa1c62018-03-08 09:47:21 -05001828 ANGLE_TRY(mImpl->syncState(context, mDirtyBits));
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001829 mDirtyBits.reset();
Jamie Madill888081d2018-02-27 00:24:46 -05001830 mDirtyBitsGuard.reset();
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001831 }
Jamie Madill19fa1c62018-03-08 09:47:21 -05001832 return NoError();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001833}
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001834
Jamie Madilld4442552018-02-27 22:03:47 -05001835void Framebuffer::onSubjectStateChange(const Context *context,
1836 angle::SubjectIndex index,
1837 angle::SubjectMessage message)
Jamie Madill51f40ec2016-06-15 14:06:00 -04001838{
Jamie Madill888081d2018-02-27 00:24:46 -05001839 if (message == angle::SubjectMessage::DEPENDENT_DIRTY_BITS)
1840 {
1841 ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(index));
1842 mDirtyBits.set(index);
Jamie Madilla11819d2018-07-30 10:26:01 -04001843 onStateChange(context, angle::SubjectMessage::CONTENTS_CHANGED);
Jamie Madill888081d2018-02-27 00:24:46 -05001844 return;
1845 }
1846
Geoff Lang8170eab2017-09-21 13:59:04 -04001847 // Only reset the cached status if this is not the default framebuffer. The default framebuffer
1848 // will still use this channel to mark itself dirty.
Jamie Madill2274b652018-05-31 10:56:08 -04001849 if (mState.mId != 0)
Geoff Lang8170eab2017-09-21 13:59:04 -04001850 {
1851 // TOOD(jmadill): Make this only update individual attachments to do less work.
1852 mCachedStatus.reset();
1853 }
Jamie Madill05b35b22017-10-03 09:01:44 -04001854
Jamie Madilld4442552018-02-27 22:03:47 -05001855 FramebufferAttachment *attachment = getAttachmentFromSubjectIndex(index);
1856
Jamie Madill05b35b22017-10-03 09:01:44 -04001857 // Mark the appropriate init flag.
Jamie Madilld4442552018-02-27 22:03:47 -05001858 mState.mResourceNeedsInit.set(index, attachment->initState() == InitState::MayNeedInit);
1859}
1860
1861FramebufferAttachment *Framebuffer::getAttachmentFromSubjectIndex(angle::SubjectIndex index)
1862{
1863 switch (index)
1864 {
1865 case DIRTY_BIT_DEPTH_ATTACHMENT:
1866 return &mState.mDepthAttachment;
1867 case DIRTY_BIT_STENCIL_ATTACHMENT:
1868 return &mState.mStencilAttachment;
1869 default:
1870 size_t colorIndex = (index - DIRTY_BIT_COLOR_ATTACHMENT_0);
1871 ASSERT(colorIndex < mState.mColorAttachments.size());
1872 return &mState.mColorAttachments[colorIndex];
1873 }
Jamie Madill51f40ec2016-06-15 14:06:00 -04001874}
1875
Jamie Madilla4595b82017-01-11 17:36:34 -05001876bool Framebuffer::formsRenderingFeedbackLoopWith(const State &state) const
1877{
1878 const Program *program = state.getProgram();
1879
1880 // TODO(jmadill): Default framebuffer feedback loops.
Jamie Madill2274b652018-05-31 10:56:08 -04001881 if (mState.mId == 0)
Jamie Madilla4595b82017-01-11 17:36:34 -05001882 {
1883 return false;
1884 }
1885
1886 // The bitset will skip inactive draw buffers.
Jamie Madill6de51852017-04-12 09:53:01 -04001887 for (size_t drawIndex : mState.mEnabledDrawBuffers)
Jamie Madilla4595b82017-01-11 17:36:34 -05001888 {
Jamie Madill5aca1932017-07-21 12:22:01 -04001889 const FramebufferAttachment &attachment = mState.mColorAttachments[drawIndex];
1890 ASSERT(attachment.isAttached());
1891 if (attachment.type() == GL_TEXTURE)
Jamie Madilla4595b82017-01-11 17:36:34 -05001892 {
1893 // Validate the feedback loop.
Jamie Madill5aca1932017-07-21 12:22:01 -04001894 if (program->samplesFromTexture(state, attachment.id()))
Jamie Madilla4595b82017-01-11 17:36:34 -05001895 {
1896 return true;
1897 }
1898 }
1899 }
1900
Jamie Madill1d37bc52017-02-02 19:59:58 -05001901 // Validate depth-stencil feedback loop.
1902 const auto &dsState = state.getDepthStencilState();
1903
1904 // We can skip the feedback loop checks if depth/stencil is masked out or disabled.
1905 const FramebufferAttachment *depth = getDepthbuffer();
1906 if (depth && depth->type() == GL_TEXTURE && dsState.depthTest && dsState.depthMask)
1907 {
1908 if (program->samplesFromTexture(state, depth->id()))
1909 {
1910 return true;
1911 }
1912 }
1913
Jamie Madill1d37bc52017-02-02 19:59:58 -05001914 const FramebufferAttachment *stencil = getStencilbuffer();
Ken Russellb9f92502018-01-27 19:00:26 -08001915 if (dsState.stencilTest && stencil)
Jamie Madill1d37bc52017-02-02 19:59:58 -05001916 {
Ken Russellb9f92502018-01-27 19:00:26 -08001917 GLuint stencilSize = stencil->getStencilSize();
1918 ASSERT(stencilSize <= 8);
1919 GLuint maxStencilValue = (1 << stencilSize) - 1;
1920 // We assume the front and back masks are the same for WebGL.
1921 ASSERT((dsState.stencilBackWritemask & maxStencilValue) ==
1922 (dsState.stencilWritemask & maxStencilValue));
1923 if (stencil->type() == GL_TEXTURE && dsState.stencilWritemask != 0)
Jamie Madill1d37bc52017-02-02 19:59:58 -05001924 {
Ken Russellb9f92502018-01-27 19:00:26 -08001925 // Skip the feedback loop check if depth/stencil point to the same resource.
1926 if (!depth || *stencil != *depth)
Jamie Madill1d37bc52017-02-02 19:59:58 -05001927 {
Ken Russellb9f92502018-01-27 19:00:26 -08001928 if (program->samplesFromTexture(state, stencil->id()))
1929 {
1930 return true;
1931 }
Jamie Madill1d37bc52017-02-02 19:59:58 -05001932 }
1933 }
1934 }
1935
Jamie Madilla4595b82017-01-11 17:36:34 -05001936 return false;
1937}
1938
Jamie Madillfd3dd432017-02-02 19:59:59 -05001939bool Framebuffer::formsCopyingFeedbackLoopWith(GLuint copyTextureID,
1940 GLint copyTextureLevel,
1941 GLint copyTextureLayer) const
Jamie Madillf695a3a2017-01-11 17:36:35 -05001942{
Jamie Madill2274b652018-05-31 10:56:08 -04001943 if (mState.mId == 0)
Jamie Madillf695a3a2017-01-11 17:36:35 -05001944 {
1945 // It seems impossible to form a texture copying feedback loop with the default FBO.
1946 return false;
1947 }
1948
1949 const FramebufferAttachment *readAttachment = getReadColorbuffer();
1950 ASSERT(readAttachment);
1951
1952 if (readAttachment->isTextureWithId(copyTextureID))
1953 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05001954 const auto &imageIndex = readAttachment->getTextureImageIndex();
Jamie Madillcc129372018-04-12 09:13:18 -04001955 if (imageIndex.getLevelIndex() == copyTextureLevel)
Jamie Madillf695a3a2017-01-11 17:36:35 -05001956 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05001957 // Check 3D/Array texture layers.
Jamie Madillcc129372018-04-12 09:13:18 -04001958 return !imageIndex.hasLayer() || copyTextureLayer == ImageIndex::kEntireLevel ||
1959 imageIndex.getLayerIndex() == copyTextureLayer;
Jamie Madillf695a3a2017-01-11 17:36:35 -05001960 }
1961 }
1962 return false;
1963}
1964
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001965GLint Framebuffer::getDefaultWidth() const
1966{
1967 return mState.getDefaultWidth();
1968}
1969
1970GLint Framebuffer::getDefaultHeight() const
1971{
1972 return mState.getDefaultHeight();
1973}
1974
1975GLint Framebuffer::getDefaultSamples() const
1976{
1977 return mState.getDefaultSamples();
1978}
1979
Geoff Lang92019432017-11-20 13:09:34 -05001980bool Framebuffer::getDefaultFixedSampleLocations() const
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001981{
1982 return mState.getDefaultFixedSampleLocations();
1983}
1984
Jiawei Shaob1e91382018-05-17 14:33:55 +08001985GLint Framebuffer::getDefaultLayers() const
1986{
1987 return mState.getDefaultLayers();
1988}
1989
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001990void Framebuffer::setDefaultWidth(GLint defaultWidth)
1991{
1992 mState.mDefaultWidth = defaultWidth;
1993 mDirtyBits.set(DIRTY_BIT_DEFAULT_WIDTH);
Jamie Madille98b1b52018-03-08 09:47:23 -05001994 invalidateCompletenessCache();
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001995}
1996
1997void Framebuffer::setDefaultHeight(GLint defaultHeight)
1998{
1999 mState.mDefaultHeight = defaultHeight;
2000 mDirtyBits.set(DIRTY_BIT_DEFAULT_HEIGHT);
Jamie Madille98b1b52018-03-08 09:47:23 -05002001 invalidateCompletenessCache();
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002002}
2003
2004void Framebuffer::setDefaultSamples(GLint defaultSamples)
2005{
2006 mState.mDefaultSamples = defaultSamples;
2007 mDirtyBits.set(DIRTY_BIT_DEFAULT_SAMPLES);
Jamie Madille98b1b52018-03-08 09:47:23 -05002008 invalidateCompletenessCache();
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002009}
2010
Geoff Lang92019432017-11-20 13:09:34 -05002011void Framebuffer::setDefaultFixedSampleLocations(bool defaultFixedSampleLocations)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002012{
2013 mState.mDefaultFixedSampleLocations = defaultFixedSampleLocations;
2014 mDirtyBits.set(DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS);
Jamie Madille98b1b52018-03-08 09:47:23 -05002015 invalidateCompletenessCache();
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08002016}
2017
Jiawei Shaob1e91382018-05-17 14:33:55 +08002018void Framebuffer::setDefaultLayers(GLint defaultLayers)
2019{
2020 mState.mDefaultLayers = defaultLayers;
2021 mDirtyBits.set(DIRTY_BIT_DEFAULT_LAYERS);
2022}
2023
Martin Radev14a26ae2017-07-24 15:56:29 +03002024GLsizei Framebuffer::getNumViews() const
2025{
Martin Radev5c00d0d2017-08-07 10:06:59 +03002026 return mState.getNumViews();
Martin Radev14a26ae2017-07-24 15:56:29 +03002027}
2028
Martin Radev4e619f52017-08-09 11:50:06 +03002029GLint Framebuffer::getBaseViewIndex() const
2030{
2031 return mState.getBaseViewIndex();
2032}
2033
Martin Radev878c8b12017-07-28 09:51:04 +03002034const std::vector<Offset> *Framebuffer::getViewportOffsets() const
2035{
Martin Radev5c00d0d2017-08-07 10:06:59 +03002036 return mState.getViewportOffsets();
Martin Radev878c8b12017-07-28 09:51:04 +03002037}
2038
2039GLenum Framebuffer::getMultiviewLayout() const
2040{
Martin Radev5c00d0d2017-08-07 10:06:59 +03002041 return mState.getMultiviewLayout();
Martin Radev878c8b12017-07-28 09:51:04 +03002042}
2043
Olli Etuaho8acb1b62018-07-30 16:20:54 +03002044bool Framebuffer::readDisallowedByMultiview() const
2045{
2046 return (mState.getMultiviewLayout() != GL_NONE && mState.getNumViews() > 1) ||
2047 mState.getMultiviewLayout() == GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE;
2048}
2049
Geoff Langd4fff502017-09-22 11:28:28 -04002050Error Framebuffer::ensureClearAttachmentsInitialized(const Context *context, GLbitfield mask)
2051{
2052 const auto &glState = context->getGLState();
2053 if (!context->isRobustResourceInitEnabled() || glState.isRasterizerDiscardEnabled())
2054 {
2055 return NoError();
2056 }
2057
Geoff Langa36483f2018-03-09 16:11:21 -05002058 const BlendState &blend = glState.getBlendState();
2059 const DepthStencilState &depthStencil = glState.getDepthStencilState();
Geoff Langd4fff502017-09-22 11:28:28 -04002060
2061 bool color = (mask & GL_COLOR_BUFFER_BIT) != 0 && !IsColorMaskedOut(blend);
2062 bool depth = (mask & GL_DEPTH_BUFFER_BIT) != 0 && !IsDepthMaskedOut(depthStencil);
2063 bool stencil = (mask & GL_STENCIL_BUFFER_BIT) != 0 && !IsStencilMaskedOut(depthStencil);
2064
2065 if (!color && !depth && !stencil)
2066 {
2067 return NoError();
2068 }
2069
2070 if (partialClearNeedsInit(context, color, depth, stencil))
2071 {
2072 ANGLE_TRY(ensureDrawAttachmentsInitialized(context));
2073 }
2074
2075 // If the impl encounters an error during a a full (non-partial) clear, the attachments will
2076 // still be marked initialized. This simplifies design, allowing this method to be called before
2077 // the clear.
2078 markDrawAttachmentsInitialized(color, depth, stencil);
2079
2080 return NoError();
2081}
2082
2083Error Framebuffer::ensureClearBufferAttachmentsInitialized(const Context *context,
2084 GLenum buffer,
2085 GLint drawbuffer)
2086{
2087 if (!context->isRobustResourceInitEnabled() ||
2088 context->getGLState().isRasterizerDiscardEnabled() ||
2089 IsClearBufferMaskedOut(context, buffer))
2090 {
2091 return NoError();
2092 }
2093
2094 if (partialBufferClearNeedsInit(context, buffer))
2095 {
2096 ANGLE_TRY(ensureBufferInitialized(context, buffer, drawbuffer));
2097 }
2098
2099 // If the impl encounters an error during a a full (non-partial) clear, the attachments will
2100 // still be marked initialized. This simplifies design, allowing this method to be called before
2101 // the clear.
2102 markBufferInitialized(buffer, drawbuffer);
2103
2104 return NoError();
2105}
2106
Jamie Madill05b35b22017-10-03 09:01:44 -04002107Error Framebuffer::ensureDrawAttachmentsInitialized(const Context *context)
2108{
2109 if (!context->isRobustResourceInitEnabled())
2110 {
2111 return NoError();
2112 }
2113
2114 // Note: we don't actually filter by the draw attachment enum. Just init everything.
2115 for (size_t bit : mState.mResourceNeedsInit)
2116 {
2117 switch (bit)
2118 {
2119 case DIRTY_BIT_DEPTH_ATTACHMENT:
2120 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2121 break;
2122 case DIRTY_BIT_STENCIL_ATTACHMENT:
2123 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2124 break;
2125 default:
2126 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[bit]));
2127 break;
2128 }
2129 }
2130
2131 mState.mResourceNeedsInit.reset();
2132 return NoError();
2133}
2134
2135Error Framebuffer::ensureReadAttachmentInitialized(const Context *context, GLbitfield blitMask)
2136{
2137 if (!context->isRobustResourceInitEnabled() || mState.mResourceNeedsInit.none())
2138 {
2139 return NoError();
2140 }
2141
2142 if ((blitMask & GL_COLOR_BUFFER_BIT) != 0 && mState.mReadBufferState != GL_NONE)
2143 {
2144 size_t readIndex = mState.getReadIndex();
2145 if (mState.mResourceNeedsInit[readIndex])
2146 {
2147 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[readIndex]));
2148 mState.mResourceNeedsInit.reset(readIndex);
2149 }
2150 }
2151
2152 if ((blitMask & GL_DEPTH_BUFFER_BIT) != 0 && hasDepth())
2153 {
2154 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2155 {
2156 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2157 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2158 }
2159 }
2160
2161 if ((blitMask & GL_STENCIL_BUFFER_BIT) != 0 && hasStencil())
2162 {
2163 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2164 {
2165 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2166 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2167 }
2168 }
2169
2170 return NoError();
2171}
2172
2173void Framebuffer::markDrawAttachmentsInitialized(bool color, bool depth, bool stencil)
2174{
2175 // Mark attachments as initialized.
2176 if (color)
2177 {
2178 for (auto colorIndex : mState.mEnabledDrawBuffers)
2179 {
2180 auto &colorAttachment = mState.mColorAttachments[colorIndex];
2181 ASSERT(colorAttachment.isAttached());
2182 colorAttachment.setInitState(InitState::Initialized);
2183 mState.mResourceNeedsInit.reset(colorIndex);
2184 }
2185 }
2186
2187 if (depth && mState.mDepthAttachment.isAttached())
2188 {
2189 mState.mDepthAttachment.setInitState(InitState::Initialized);
2190 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2191 }
2192
2193 if (stencil && mState.mStencilAttachment.isAttached())
2194 {
2195 mState.mStencilAttachment.setInitState(InitState::Initialized);
2196 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2197 }
2198}
2199
2200void Framebuffer::markBufferInitialized(GLenum bufferType, GLint bufferIndex)
2201{
2202 switch (bufferType)
2203 {
2204 case GL_COLOR:
2205 {
2206 ASSERT(bufferIndex < static_cast<GLint>(mState.mColorAttachments.size()));
2207 if (mState.mColorAttachments[bufferIndex].isAttached())
2208 {
2209 mState.mColorAttachments[bufferIndex].setInitState(InitState::Initialized);
2210 mState.mResourceNeedsInit.reset(bufferIndex);
2211 }
2212 break;
2213 }
2214 case GL_DEPTH:
2215 {
2216 if (mState.mDepthAttachment.isAttached())
2217 {
2218 mState.mDepthAttachment.setInitState(InitState::Initialized);
2219 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2220 }
2221 break;
2222 }
2223 case GL_STENCIL:
2224 {
2225 if (mState.mStencilAttachment.isAttached())
2226 {
2227 mState.mStencilAttachment.setInitState(InitState::Initialized);
2228 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2229 }
2230 break;
2231 }
2232 case GL_DEPTH_STENCIL:
2233 {
2234 if (mState.mDepthAttachment.isAttached())
2235 {
2236 mState.mDepthAttachment.setInitState(InitState::Initialized);
2237 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2238 }
2239 if (mState.mStencilAttachment.isAttached())
2240 {
2241 mState.mStencilAttachment.setInitState(InitState::Initialized);
2242 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2243 }
2244 break;
2245 }
2246 default:
2247 UNREACHABLE();
2248 break;
2249 }
2250}
2251
2252Box Framebuffer::getDimensions() const
2253{
2254 return mState.getDimensions();
2255}
2256
2257Error Framebuffer::ensureBufferInitialized(const Context *context,
2258 GLenum bufferType,
2259 GLint bufferIndex)
2260{
2261 ASSERT(context->isRobustResourceInitEnabled());
2262
2263 if (mState.mResourceNeedsInit.none())
2264 {
2265 return NoError();
2266 }
2267
2268 switch (bufferType)
2269 {
2270 case GL_COLOR:
2271 {
2272 ASSERT(bufferIndex < static_cast<GLint>(mState.mColorAttachments.size()));
2273 if (mState.mResourceNeedsInit[bufferIndex])
2274 {
2275 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[bufferIndex]));
2276 mState.mResourceNeedsInit.reset(bufferIndex);
2277 }
2278 break;
2279 }
2280 case GL_DEPTH:
2281 {
2282 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2283 {
2284 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2285 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2286 }
2287 break;
2288 }
2289 case GL_STENCIL:
2290 {
2291 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2292 {
2293 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2294 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2295 }
2296 break;
2297 }
2298 case GL_DEPTH_STENCIL:
2299 {
2300 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2301 {
2302 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2303 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2304 }
2305 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2306 {
2307 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2308 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2309 }
2310 break;
2311 }
2312 default:
2313 UNREACHABLE();
2314 break;
2315 }
2316
2317 return NoError();
2318}
2319
2320bool Framebuffer::partialBufferClearNeedsInit(const Context *context, GLenum bufferType)
2321{
2322 if (!context->isRobustResourceInitEnabled() || mState.mResourceNeedsInit.none())
2323 {
2324 return false;
2325 }
2326
2327 switch (bufferType)
2328 {
2329 case GL_COLOR:
2330 return partialClearNeedsInit(context, true, false, false);
2331 case GL_DEPTH:
2332 return partialClearNeedsInit(context, false, true, false);
2333 case GL_STENCIL:
2334 return partialClearNeedsInit(context, false, false, true);
2335 case GL_DEPTH_STENCIL:
2336 return partialClearNeedsInit(context, false, true, true);
2337 default:
2338 UNREACHABLE();
2339 return false;
2340 }
2341}
2342
Jamie Madill42975642017-10-12 12:31:51 -04002343bool Framebuffer::hasTextureAttachment(const Texture *texture) const
2344{
2345 if (!mAttachedTextures.valid())
2346 {
Geoff Langb8430dd2018-08-01 15:27:18 -04002347 FramebufferTextureAttachmentVector attachedTextures;
Jamie Madill42975642017-10-12 12:31:51 -04002348
2349 for (const auto &colorAttachment : mState.mColorAttachments)
2350 {
2351 if (colorAttachment.isAttached() && colorAttachment.type() == GL_TEXTURE)
2352 {
Geoff Langb8430dd2018-08-01 15:27:18 -04002353 attachedTextures.push_back(colorAttachment.getResource());
Jamie Madill42975642017-10-12 12:31:51 -04002354 }
2355 }
2356
2357 if (mState.mDepthAttachment.isAttached() && mState.mDepthAttachment.type() == GL_TEXTURE)
2358 {
Geoff Langb8430dd2018-08-01 15:27:18 -04002359 attachedTextures.push_back(mState.mDepthAttachment.getResource());
Jamie Madill42975642017-10-12 12:31:51 -04002360 }
2361
2362 if (mState.mStencilAttachment.isAttached() &&
2363 mState.mStencilAttachment.type() == GL_TEXTURE)
2364 {
Geoff Langb8430dd2018-08-01 15:27:18 -04002365 attachedTextures.push_back(mState.mStencilAttachment.getResource());
Jamie Madill42975642017-10-12 12:31:51 -04002366 }
2367
2368 mAttachedTextures = std::move(attachedTextures);
2369 }
2370
Geoff Langb8430dd2018-08-01 15:27:18 -04002371 return std::find(mAttachedTextures.value().begin(), mAttachedTextures.value().end(), texture) !=
2372 mAttachedTextures.value().end();
Jamie Madill42975642017-10-12 12:31:51 -04002373}
2374
Jamie Madill60ec6ea2016-01-22 15:27:19 -05002375} // namespace gl