blob: 87405697fd421b68f1cb89a25304fbfaacedfd2c [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
Yuly Novikov2eb54072018-08-22 16:41:26 -040074 if (!attachment.isRenderable(context))
Geoff Lang9f10b772017-05-16 15:51:03 -040075 {
76 return false;
77 }
78
79 if (attachment.type() == GL_TEXTURE)
80 {
Jiawei Shaoa8802472018-05-28 11:17:47 +080081 // [EXT_geometry_shader] Section 9.4.1, "Framebuffer Completeness"
82 // If <image> is a three-dimensional texture or a two-dimensional array texture and the
83 // attachment is not layered, the selected layer is less than the depth or layer count,
84 // respectively, of the texture.
85 if (!attachment.isLayered())
Geoff Lang9f10b772017-05-16 15:51:03 -040086 {
Jiawei Shaoa8802472018-05-28 11:17:47 +080087 if (attachment.layer() >= size.depth)
88 {
89 return false;
90 }
91 }
92 // If <image> is a three-dimensional texture or a two-dimensional array texture and the
93 // attachment is layered, the depth or layer count, respectively, of the texture is less
94 // than or equal to the value of MAX_FRAMEBUFFER_LAYERS_EXT.
95 else
96 {
97 if (static_cast<GLuint>(size.depth) >= context->getCaps().maxFramebufferLayers)
98 {
99 return false;
100 }
Geoff Lang9f10b772017-05-16 15:51:03 -0400101 }
102
103 // ES3 specifies that cube map texture attachments must be cube complete.
104 // This language is missing from the ES2 spec, but we enforce it here because some
105 // desktop OpenGL drivers also enforce this validation.
106 // TODO(jmadill): Check if OpenGL ES2 drivers enforce cube completeness.
107 const Texture *texture = attachment.getTexture();
108 ASSERT(texture);
Corentin Wallez99d492c2018-02-27 15:17:10 -0500109 if (texture->getType() == TextureType::CubeMap &&
Geoff Lang9f10b772017-05-16 15:51:03 -0400110 !texture->getTextureState().isCubeComplete())
111 {
112 return false;
113 }
Geoff Lang857c09d2017-05-16 15:55:04 -0400114
115 if (!texture->getImmutableFormat())
116 {
117 GLuint attachmentMipLevel = static_cast<GLuint>(attachment.mipLevel());
118
119 // From the ES 3.0 spec, pg 213:
120 // If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is TEXTURE and the value of
121 // FRAMEBUFFER_ATTACHMENT_OBJECT_NAME does not name an immutable-format texture,
122 // then the value of FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL must be in the
123 // range[levelbase, q], where levelbase is the value of TEXTURE_BASE_LEVEL and q is
124 // the effective maximum texture level defined in the Mipmapping discussion of
125 // section 3.8.10.4.
126 if (attachmentMipLevel < texture->getBaseLevel() ||
127 attachmentMipLevel > texture->getMipmapMaxLevel())
128 {
129 return false;
130 }
131
132 // Form the ES 3.0 spec, pg 213/214:
133 // If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is TEXTURE and the value of
134 // FRAMEBUFFER_ATTACHMENT_OBJECT_NAME does not name an immutable-format texture and
135 // the value of FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL is not levelbase, then the
136 // texture must be mipmap complete, and if FRAMEBUFFER_ATTACHMENT_OBJECT_NAME names
137 // a cubemap texture, the texture must also be cube complete.
138 if (attachmentMipLevel != texture->getBaseLevel() && !texture->isMipmapComplete())
139 {
140 return false;
141 }
142 }
Geoff Lang9f10b772017-05-16 15:51:03 -0400143 }
144
145 return true;
146};
147
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400148bool CheckAttachmentSampleCompleteness(const Context *context,
149 const FramebufferAttachment &attachment,
150 bool colorAttachment,
151 Optional<int> *samples,
Geoff Lang92019432017-11-20 13:09:34 -0500152 Optional<bool> *fixedSampleLocations)
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400153{
154 ASSERT(attachment.isAttached());
155
156 if (attachment.type() == GL_TEXTURE)
157 {
158 const Texture *texture = attachment.getTexture();
159 ASSERT(texture);
160
161 const ImageIndex &attachmentImageIndex = attachment.getTextureImageIndex();
Jiawei Shaoa8802472018-05-28 11:17:47 +0800162 bool fixedSampleloc = texture->getAttachmentFixedSampleLocations(attachmentImageIndex);
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400163 if (fixedSampleLocations->valid() && fixedSampleloc != fixedSampleLocations->value())
164 {
165 return false;
166 }
167 else
168 {
169 *fixedSampleLocations = fixedSampleloc;
170 }
171 }
172
173 if (samples->valid())
174 {
175 if (attachment.getSamples() != samples->value())
176 {
177 if (colorAttachment)
178 {
179 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
180 // all color attachments have the same number of samples for the FBO to be complete.
181 return false;
182 }
183 else
184 {
185 // CHROMIUM_framebuffer_mixed_samples allows a framebuffer to be considered complete
186 // when its depth or stencil samples are a multiple of the number of color samples.
187 if (!context->getExtensions().framebufferMixedSamples)
188 {
189 return false;
190 }
191
192 if ((attachment.getSamples() % std::max(samples->value(), 1)) != 0)
193 {
194 return false;
195 }
196 }
197 }
198 }
199 else
200 {
201 *samples = attachment.getSamples();
202 }
203
204 return true;
205}
206
Jamie Madill05b35b22017-10-03 09:01:44 -0400207// Needed to index into the attachment arrays/bitsets.
Jamie Madill682efdc2017-10-03 14:10:29 -0400208static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS) ==
Jamie Madilld4442552018-02-27 22:03:47 -0500209 Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX,
Jamie Madill05b35b22017-10-03 09:01:44 -0400210 "Framebuffer Dirty bit mismatch");
Jamie Madill682efdc2017-10-03 14:10:29 -0400211static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS) ==
Jamie Madilld4442552018-02-27 22:03:47 -0500212 Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT,
Jamie Madill05b35b22017-10-03 09:01:44 -0400213 "Framebuffer Dirty bit mismatch");
Jamie Madill682efdc2017-10-03 14:10:29 -0400214static_assert(static_cast<size_t>(IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS + 1) ==
Jamie Madilld4442552018-02-27 22:03:47 -0500215 Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT,
Jamie Madill05b35b22017-10-03 09:01:44 -0400216 "Framebuffer Dirty bit mismatch");
217
Jamie Madill6f755b22018-10-09 12:48:54 -0400218angle::Result InitAttachment(const Context *context, FramebufferAttachment *attachment)
Jamie Madill05b35b22017-10-03 09:01:44 -0400219{
220 ASSERT(attachment->isAttached());
221 if (attachment->initState() == InitState::MayNeedInit)
222 {
223 ANGLE_TRY(attachment->initializeContents(context));
224 }
Jamie Madill6f755b22018-10-09 12:48:54 -0400225 return angle::Result::Continue();
Jamie Madill05b35b22017-10-03 09:01:44 -0400226}
227
228bool IsColorMaskedOut(const BlendState &blend)
229{
230 return (!blend.colorMaskRed && !blend.colorMaskGreen && !blend.colorMaskBlue &&
231 !blend.colorMaskAlpha);
232}
233
234bool IsDepthMaskedOut(const DepthStencilState &depthStencil)
235{
236 return !depthStencil.depthMask;
237}
238
239bool IsStencilMaskedOut(const DepthStencilState &depthStencil)
240{
241 return ((depthStencil.stencilMask & depthStencil.stencilWritemask) == 0);
242}
243
244bool IsClearBufferMaskedOut(const Context *context, GLenum buffer)
245{
246 switch (buffer)
247 {
248 case GL_COLOR:
249 return IsColorMaskedOut(context->getGLState().getBlendState());
250 case GL_DEPTH:
251 return IsDepthMaskedOut(context->getGLState().getDepthStencilState());
252 case GL_STENCIL:
253 return IsStencilMaskedOut(context->getGLState().getDepthStencilState());
254 case GL_DEPTH_STENCIL:
255 return IsDepthMaskedOut(context->getGLState().getDepthStencilState()) &&
256 IsStencilMaskedOut(context->getGLState().getDepthStencilState());
257 default:
258 UNREACHABLE();
259 return true;
260 }
261}
262
Jamie Madill362876b2016-06-16 14:46:59 -0400263} // anonymous namespace
Jamie Madilld1405e52015-03-05 15:41:39 -0500264
Jamie Madill6f60d052017-02-22 15:20:11 -0500265// This constructor is only used for default framebuffers.
Jamie Madill48ef11b2016-04-27 15:21:52 -0400266FramebufferState::FramebufferState()
Jamie Madill2274b652018-05-31 10:56:08 -0400267 : mId(0),
268 mLabel(),
Geoff Lang70d0f492015-12-10 17:45:46 -0500269 mColorAttachments(1),
Corentin Walleze7557742017-06-01 13:09:57 -0400270 mDrawBufferStates(1, GL_BACK),
Jamie Madill6f60d052017-02-22 15:20:11 -0500271 mReadBufferState(GL_BACK),
Brandon Jones76746f92017-11-22 11:44:41 -0800272 mDrawBufferTypeMask(),
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800273 mDefaultWidth(0),
274 mDefaultHeight(0),
275 mDefaultSamples(0),
Jamie Madilla02315b2017-02-23 14:14:47 -0500276 mDefaultFixedSampleLocations(GL_FALSE),
Jiawei Shaob1e91382018-05-17 14:33:55 +0800277 mDefaultLayers(0),
Jamie Madilla02315b2017-02-23 14:14:47 -0500278 mWebGLDepthStencilConsistent(true)
Corentin Wallez37c39792015-08-20 14:19:46 -0400279{
Geoff Langd90d3882017-03-21 10:49:54 -0400280 ASSERT(mDrawBufferStates.size() > 0);
Jamie Madilla4595b82017-01-11 17:36:34 -0500281 mEnabledDrawBuffers.set(0);
Corentin Wallez37c39792015-08-20 14:19:46 -0400282}
283
Jamie Madill2274b652018-05-31 10:56:08 -0400284FramebufferState::FramebufferState(const Caps &caps, GLuint id)
285 : mId(id),
286 mLabel(),
Geoff Lang70d0f492015-12-10 17:45:46 -0500287 mColorAttachments(caps.maxColorAttachments),
Jamie Madilld1405e52015-03-05 15:41:39 -0500288 mDrawBufferStates(caps.maxDrawBuffers, GL_NONE),
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800289 mReadBufferState(GL_COLOR_ATTACHMENT0_EXT),
Brandon Jones76746f92017-11-22 11:44:41 -0800290 mDrawBufferTypeMask(),
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800291 mDefaultWidth(0),
292 mDefaultHeight(0),
293 mDefaultSamples(0),
Jamie Madilla02315b2017-02-23 14:14:47 -0500294 mDefaultFixedSampleLocations(GL_FALSE),
Jiawei Shaob1e91382018-05-17 14:33:55 +0800295 mDefaultLayers(0),
Jamie Madilla02315b2017-02-23 14:14:47 -0500296 mWebGLDepthStencilConsistent(true)
Jamie Madilld1405e52015-03-05 15:41:39 -0500297{
Jamie Madill2274b652018-05-31 10:56:08 -0400298 ASSERT(mId != 0);
Geoff Langa15472a2015-08-11 11:48:03 -0400299 ASSERT(mDrawBufferStates.size() > 0);
Jamie Madilld1405e52015-03-05 15:41:39 -0500300 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
301}
302
Jamie Madillb980c562018-11-27 11:34:27 -0500303FramebufferState::~FramebufferState() {}
Jamie Madilld1405e52015-03-05 15:41:39 -0500304
Jamie Madill48ef11b2016-04-27 15:21:52 -0400305const std::string &FramebufferState::getLabel()
Geoff Lang70d0f492015-12-10 17:45:46 -0500306{
307 return mLabel;
308}
309
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800310const FramebufferAttachment *FramebufferState::getAttachment(const Context *context,
311 GLenum attachment) const
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400312{
313 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
314 {
315 return getColorAttachment(attachment - GL_COLOR_ATTACHMENT0);
316 }
317
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800318 // WebGL1 allows a developer to query for attachment parameters even when "inconsistant" (i.e.
319 // multiple conflicting attachment points) and requires us to return the framebuffer attachment
320 // associated with WebGL.
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400321 switch (attachment)
322 {
323 case GL_COLOR:
324 case GL_BACK:
325 return getColorAttachment(0);
326 case GL_DEPTH:
327 case GL_DEPTH_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800328 if (context->isWebGL1())
329 {
330 return getWebGLDepthAttachment();
331 }
332 else
333 {
334 return getDepthAttachment();
335 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400336 case GL_STENCIL:
337 case GL_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800338 if (context->isWebGL1())
339 {
340 return getWebGLStencilAttachment();
341 }
342 else
343 {
344 return getStencilAttachment();
345 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400346 case GL_DEPTH_STENCIL:
347 case GL_DEPTH_STENCIL_ATTACHMENT:
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800348 if (context->isWebGL1())
349 {
350 return getWebGLDepthStencilAttachment();
351 }
352 else
353 {
354 return getDepthStencilAttachment();
355 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400356 default:
357 UNREACHABLE();
358 return nullptr;
359 }
360}
361
Jamie Madill05b35b22017-10-03 09:01:44 -0400362size_t FramebufferState::getReadIndex() const
Jamie Madill7147f012015-03-05 15:41:40 -0500363{
Jamie Madill231c7f52017-04-26 13:45:37 -0400364 ASSERT(mReadBufferState == GL_BACK ||
365 (mReadBufferState >= GL_COLOR_ATTACHMENT0 && mReadBufferState <= GL_COLOR_ATTACHMENT15));
366 size_t readIndex = (mReadBufferState == GL_BACK
367 ? 0
368 : static_cast<size_t>(mReadBufferState - GL_COLOR_ATTACHMENT0));
Jamie Madill7147f012015-03-05 15:41:40 -0500369 ASSERT(readIndex < mColorAttachments.size());
Jamie Madill05b35b22017-10-03 09:01:44 -0400370 return readIndex;
371}
372
373const FramebufferAttachment *FramebufferState::getReadAttachment() const
374{
375 if (mReadBufferState == GL_NONE)
376 {
377 return nullptr;
378 }
379 size_t readIndex = getReadIndex();
Jamie Madill2d06b732015-04-20 12:53:28 -0400380 return mColorAttachments[readIndex].isAttached() ? &mColorAttachments[readIndex] : nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500381}
382
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500383const FramebufferAttachment *FramebufferState::getFirstNonNullAttachment() const
384{
385 auto *colorAttachment = getFirstColorAttachment();
386 if (colorAttachment)
387 {
388 return colorAttachment;
389 }
390 return getDepthOrStencilAttachment();
391}
392
Jamie Madill48ef11b2016-04-27 15:21:52 -0400393const FramebufferAttachment *FramebufferState::getFirstColorAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500394{
Jamie Madill2d06b732015-04-20 12:53:28 -0400395 for (const FramebufferAttachment &colorAttachment : mColorAttachments)
Jamie Madill7147f012015-03-05 15:41:40 -0500396 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400397 if (colorAttachment.isAttached())
Jamie Madill7147f012015-03-05 15:41:40 -0500398 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400399 return &colorAttachment;
Jamie Madill7147f012015-03-05 15:41:40 -0500400 }
401 }
402
403 return nullptr;
404}
405
Jamie Madill48ef11b2016-04-27 15:21:52 -0400406const FramebufferAttachment *FramebufferState::getDepthOrStencilAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500407{
Jamie Madill2d06b732015-04-20 12:53:28 -0400408 if (mDepthAttachment.isAttached())
409 {
410 return &mDepthAttachment;
411 }
412 if (mStencilAttachment.isAttached())
413 {
414 return &mStencilAttachment;
415 }
416 return nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500417}
418
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500419const FramebufferAttachment *FramebufferState::getStencilOrDepthStencilAttachment() const
420{
421 if (mStencilAttachment.isAttached())
422 {
423 return &mStencilAttachment;
424 }
425 return getDepthStencilAttachment();
426}
427
Jamie Madill48ef11b2016-04-27 15:21:52 -0400428const FramebufferAttachment *FramebufferState::getColorAttachment(size_t colorAttachment) const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400429{
430 ASSERT(colorAttachment < mColorAttachments.size());
Jamie Madill231c7f52017-04-26 13:45:37 -0400431 return mColorAttachments[colorAttachment].isAttached() ? &mColorAttachments[colorAttachment]
432 : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400433}
434
Jamie Madill48ef11b2016-04-27 15:21:52 -0400435const FramebufferAttachment *FramebufferState::getDepthAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400436{
Jamie Madill2d06b732015-04-20 12:53:28 -0400437 return mDepthAttachment.isAttached() ? &mDepthAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400438}
439
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800440const FramebufferAttachment *FramebufferState::getWebGLDepthAttachment() const
441{
442 return mWebGLDepthAttachment.isAttached() ? &mWebGLDepthAttachment : nullptr;
443}
444
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800445const FramebufferAttachment *FramebufferState::getWebGLDepthStencilAttachment() const
446{
447 return mWebGLDepthStencilAttachment.isAttached() ? &mWebGLDepthStencilAttachment : nullptr;
448}
449
Jamie Madill48ef11b2016-04-27 15:21:52 -0400450const FramebufferAttachment *FramebufferState::getStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400451{
Jamie Madill2d06b732015-04-20 12:53:28 -0400452 return mStencilAttachment.isAttached() ? &mStencilAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400453}
454
Bryan Bernhart (Intel Americas Inc)5f198102017-12-12 14:21:39 -0800455const FramebufferAttachment *FramebufferState::getWebGLStencilAttachment() const
456{
457 return mWebGLStencilAttachment.isAttached() ? &mWebGLStencilAttachment : nullptr;
458}
459
Jamie Madill48ef11b2016-04-27 15:21:52 -0400460const FramebufferAttachment *FramebufferState::getDepthStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400461{
462 // A valid depth-stencil attachment has the same resource bound to both the
463 // depth and stencil attachment points.
Jamie Madill2d06b732015-04-20 12:53:28 -0400464 if (mDepthAttachment.isAttached() && mStencilAttachment.isAttached() &&
Jamie Madill44f26482016-11-18 12:49:15 -0500465 mDepthAttachment == mStencilAttachment)
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400466 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400467 return &mDepthAttachment;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400468 }
469
470 return nullptr;
471}
472
Jamie Madill48ef11b2016-04-27 15:21:52 -0400473bool FramebufferState::attachmentsHaveSameDimensions() const
Jamie Madillcc86d642015-11-24 13:00:07 -0500474{
475 Optional<Extents> attachmentSize;
476
Jamie Madill231c7f52017-04-26 13:45:37 -0400477 auto hasMismatchedSize = [&attachmentSize](const FramebufferAttachment &attachment) {
Jamie Madillcc86d642015-11-24 13:00:07 -0500478 if (!attachment.isAttached())
479 {
480 return false;
481 }
482
483 if (!attachmentSize.valid())
484 {
485 attachmentSize = attachment.getSize();
486 return false;
487 }
488
Jeff Gilbert8f8edd62017-10-31 14:26:30 -0700489 const auto &prevSize = attachmentSize.value();
490 const auto &curSize = attachment.getSize();
491 return (curSize.width != prevSize.width || curSize.height != prevSize.height);
Jamie Madillcc86d642015-11-24 13:00:07 -0500492 };
493
494 for (const auto &attachment : mColorAttachments)
495 {
496 if (hasMismatchedSize(attachment))
497 {
498 return false;
499 }
500 }
501
502 if (hasMismatchedSize(mDepthAttachment))
503 {
504 return false;
505 }
506
507 return !hasMismatchedSize(mStencilAttachment);
508}
509
Luc Ferron5bdf8bd2018-06-20 09:51:37 -0400510bool FramebufferState::hasSeparateDepthAndStencilAttachments() const
511{
512 // if we have both a depth and stencil buffer, they must refer to the same object
513 // since we only support packed_depth_stencil and not separate depth and stencil
514 return (getDepthAttachment() != nullptr && getStencilAttachment() != nullptr &&
515 getDepthStencilAttachment() == nullptr);
516}
517
Jamie Madilld4442552018-02-27 22:03:47 -0500518const FramebufferAttachment *FramebufferState::getDrawBuffer(size_t drawBufferIdx) const
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400519{
520 ASSERT(drawBufferIdx < mDrawBufferStates.size());
521 if (mDrawBufferStates[drawBufferIdx] != GL_NONE)
522 {
523 // ES3 spec: "If the GL is bound to a draw framebuffer object, the ith buffer listed in bufs
524 // must be COLOR_ATTACHMENTi or NONE"
525 ASSERT(mDrawBufferStates[drawBufferIdx] == GL_COLOR_ATTACHMENT0 + drawBufferIdx ||
526 (drawBufferIdx == 0 && mDrawBufferStates[drawBufferIdx] == GL_BACK));
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800527
528 if (mDrawBufferStates[drawBufferIdx] == GL_BACK)
529 {
530 return getColorAttachment(0);
531 }
532 else
533 {
534 return getColorAttachment(mDrawBufferStates[drawBufferIdx] - GL_COLOR_ATTACHMENT0);
535 }
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400536 }
537 else
538 {
539 return nullptr;
540 }
541}
542
543size_t FramebufferState::getDrawBufferCount() const
544{
545 return mDrawBufferStates.size();
546}
547
Geoff Langb21e20d2016-07-19 15:35:41 -0400548bool FramebufferState::colorAttachmentsAreUniqueImages() const
549{
550 for (size_t firstAttachmentIdx = 0; firstAttachmentIdx < mColorAttachments.size();
551 firstAttachmentIdx++)
552 {
Jamie Madilld4442552018-02-27 22:03:47 -0500553 const FramebufferAttachment &firstAttachment = mColorAttachments[firstAttachmentIdx];
Geoff Langb21e20d2016-07-19 15:35:41 -0400554 if (!firstAttachment.isAttached())
555 {
556 continue;
557 }
558
559 for (size_t secondAttachmentIdx = firstAttachmentIdx + 1;
560 secondAttachmentIdx < mColorAttachments.size(); secondAttachmentIdx++)
561 {
Jamie Madilld4442552018-02-27 22:03:47 -0500562 const FramebufferAttachment &secondAttachment = mColorAttachments[secondAttachmentIdx];
Geoff Langb21e20d2016-07-19 15:35:41 -0400563 if (!secondAttachment.isAttached())
564 {
565 continue;
566 }
567
568 if (firstAttachment == secondAttachment)
569 {
570 return false;
571 }
572 }
573 }
574
575 return true;
576}
577
Jamie Madill9c335862017-07-18 11:51:38 -0400578bool FramebufferState::hasDepth() const
579{
580 return (mDepthAttachment.isAttached() && mDepthAttachment.getDepthSize() > 0);
581}
582
583bool FramebufferState::hasStencil() const
584{
585 return (mStencilAttachment.isAttached() && mStencilAttachment.getStencilSize() > 0);
586}
587
Martin Radev5c00d0d2017-08-07 10:06:59 +0300588const std::vector<Offset> *FramebufferState::getViewportOffsets() const
589{
590 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
591 if (attachment == nullptr)
592 {
593 return nullptr;
594 }
595 return &attachment->getMultiviewViewportOffsets();
596}
597
598GLenum FramebufferState::getMultiviewLayout() const
599{
600 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
601 if (attachment == nullptr)
602 {
603 return GL_NONE;
604 }
605 return attachment->getMultiviewLayout();
606}
607
Martin Radev4e619f52017-08-09 11:50:06 +0300608int FramebufferState::getBaseViewIndex() const
609{
610 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
611 if (attachment == nullptr)
612 {
613 return GL_NONE;
614 }
615 return attachment->getBaseViewIndex();
616}
617
Jamie Madill05b35b22017-10-03 09:01:44 -0400618Box FramebufferState::getDimensions() const
619{
620 ASSERT(attachmentsHaveSameDimensions());
621 ASSERT(getFirstNonNullAttachment() != nullptr);
622 Extents extents = getFirstNonNullAttachment()->getSize();
623 return Box(0, 0, 0, extents.width, extents.height, extents.depth);
624}
625
Jamie Madill7aea7e02016-05-10 10:39:45 -0400626Framebuffer::Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id)
Jamie Madill2274b652018-05-31 10:56:08 -0400627 : mState(caps, id),
Jamie Madill362876b2016-06-16 14:46:59 -0400628 mImpl(factory->createFramebuffer(mState)),
Jamie Madill362876b2016-06-16 14:46:59 -0400629 mCachedStatus(),
630 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
631 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000632{
Corentin Wallez37c39792015-08-20 14:19:46 -0400633 ASSERT(mImpl != nullptr);
Jamie Madill362876b2016-06-16 14:46:59 -0400634 ASSERT(mState.mColorAttachments.size() == static_cast<size_t>(caps.maxColorAttachments));
635
Jamie Madill1e5499d2017-04-05 11:22:16 -0400636 for (uint32_t colorIndex = 0;
637 colorIndex < static_cast<uint32_t>(mState.mColorAttachments.size()); ++colorIndex)
Jamie Madill362876b2016-06-16 14:46:59 -0400638 {
Jamie Madill1e5499d2017-04-05 11:22:16 -0400639 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
Jamie Madill362876b2016-06-16 14:46:59 -0400640 }
Corentin Wallez37c39792015-08-20 14:19:46 -0400641}
642
Geoff Langbf7b95d2018-05-01 16:48:21 -0400643Framebuffer::Framebuffer(const Context *context, egl::Surface *surface)
Jamie Madill362876b2016-06-16 14:46:59 -0400644 : mState(),
Geoff Langbf7b95d2018-05-01 16:48:21 -0400645 mImpl(surface->getImplementation()->createDefaultFramebuffer(context, mState)),
Jamie Madill362876b2016-06-16 14:46:59 -0400646 mCachedStatus(GL_FRAMEBUFFER_COMPLETE),
647 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
648 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
Corentin Wallez37c39792015-08-20 14:19:46 -0400649{
Geoff Langda88add2014-12-01 10:22:01 -0500650 ASSERT(mImpl != nullptr);
Jamie Madill1e5499d2017-04-05 11:22:16 -0400651 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
Jamie Madill6f60d052017-02-22 15:20:11 -0500652
Geoff Langbf7b95d2018-05-01 16:48:21 -0400653 setAttachmentImpl(context, GL_FRAMEBUFFER_DEFAULT, GL_BACK, ImageIndex(), surface,
Jamie Madillcc129372018-04-12 09:13:18 -0400654 FramebufferAttachment::kDefaultNumViews,
Martin Radev5dae57b2017-07-14 16:15:55 +0300655 FramebufferAttachment::kDefaultBaseViewIndex,
656 FramebufferAttachment::kDefaultMultiviewLayout,
657 FramebufferAttachment::kDefaultViewportOffsets);
Jamie Madill6f60d052017-02-22 15:20:11 -0500658
659 if (surface->getConfig()->depthSize > 0)
660 {
Geoff Langbf7b95d2018-05-01 16:48:21 -0400661 setAttachmentImpl(context, GL_FRAMEBUFFER_DEFAULT, GL_DEPTH, ImageIndex(), surface,
Jamie Madillcc129372018-04-12 09:13:18 -0400662 FramebufferAttachment::kDefaultNumViews,
Jamie Madilld4442552018-02-27 22:03:47 -0500663 FramebufferAttachment::kDefaultBaseViewIndex,
664 FramebufferAttachment::kDefaultMultiviewLayout,
665 FramebufferAttachment::kDefaultViewportOffsets);
Jamie Madill6f60d052017-02-22 15:20:11 -0500666 }
667
668 if (surface->getConfig()->stencilSize > 0)
669 {
Geoff Langbf7b95d2018-05-01 16:48:21 -0400670 setAttachmentImpl(context, GL_FRAMEBUFFER_DEFAULT, GL_STENCIL, ImageIndex(), surface,
Jamie Madillcc129372018-04-12 09:13:18 -0400671 FramebufferAttachment::kDefaultNumViews,
672 FramebufferAttachment::kDefaultBaseViewIndex,
673 FramebufferAttachment::kDefaultMultiviewLayout,
674 FramebufferAttachment::kDefaultViewportOffsets);
Jamie Madill6f60d052017-02-22 15:20:11 -0500675 }
Brandon Jones76746f92017-11-22 11:44:41 -0800676 mState.mDrawBufferTypeMask.setIndex(getDrawbufferWriteType(0), 0);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000677}
678
Corentin Wallezccab69d2017-01-27 16:57:15 -0500679Framebuffer::Framebuffer(rx::GLImplFactory *factory)
680 : mState(),
681 mImpl(factory->createFramebuffer(mState)),
Corentin Wallezccab69d2017-01-27 16:57:15 -0500682 mCachedStatus(GL_FRAMEBUFFER_UNDEFINED_OES),
683 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
684 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
685{
Jamie Madill1e5499d2017-04-05 11:22:16 -0400686 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
Brandon Jones76746f92017-11-22 11:44:41 -0800687 mState.mDrawBufferTypeMask.setIndex(getDrawbufferWriteType(0), 0);
Corentin Wallezccab69d2017-01-27 16:57:15 -0500688}
689
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000690Framebuffer::~Framebuffer()
691{
Geoff Langda88add2014-12-01 10:22:01 -0500692 SafeDelete(mImpl);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000693}
694
Jamie Madill4928b7c2017-06-20 12:57:39 -0400695void Framebuffer::onDestroy(const Context *context)
Jamie Madill6c1f6712017-02-14 19:08:04 -0500696{
Jamie Madill4928b7c2017-06-20 12:57:39 -0400697 for (auto &attachment : mState.mColorAttachments)
698 {
699 attachment.detach(context);
700 }
701 mState.mDepthAttachment.detach(context);
702 mState.mStencilAttachment.detach(context);
703 mState.mWebGLDepthAttachment.detach(context);
704 mState.mWebGLStencilAttachment.detach(context);
705 mState.mWebGLDepthStencilAttachment.detach(context);
706
Jamie Madillc564c072017-06-01 12:45:42 -0400707 mImpl->destroy(context);
Jamie Madill6c1f6712017-02-14 19:08:04 -0500708}
709
Jamie Madille90d4ee2018-11-28 14:04:00 -0500710void Framebuffer::setLabel(const Context *context, const std::string &label)
Geoff Lang70d0f492015-12-10 17:45:46 -0500711{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400712 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -0500713}
714
715const std::string &Framebuffer::getLabel() const
716{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400717 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -0500718}
719
Jamie Madill8693bdb2017-09-02 15:32:14 -0400720bool Framebuffer::detachTexture(const Context *context, GLuint textureId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000721{
Jamie Madill8693bdb2017-09-02 15:32:14 -0400722 return detachResourceById(context, GL_TEXTURE, textureId);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000723}
724
Jamie Madill8693bdb2017-09-02 15:32:14 -0400725bool Framebuffer::detachRenderbuffer(const Context *context, GLuint renderbufferId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000726{
Jamie Madill8693bdb2017-09-02 15:32:14 -0400727 return detachResourceById(context, GL_RENDERBUFFER, renderbufferId);
Jamie Madilld1405e52015-03-05 15:41:39 -0500728}
Jamie Madille261b442014-06-25 12:42:21 -0400729
Jamie Madill8693bdb2017-09-02 15:32:14 -0400730bool Framebuffer::detachResourceById(const Context *context, GLenum resourceType, GLuint resourceId)
Jamie Madilld1405e52015-03-05 15:41:39 -0500731{
Jamie Madill8693bdb2017-09-02 15:32:14 -0400732 bool found = false;
733
Jamie Madill362876b2016-06-16 14:46:59 -0400734 for (size_t colorIndex = 0; colorIndex < mState.mColorAttachments.size(); ++colorIndex)
Jamie Madilld1405e52015-03-05 15:41:39 -0500735 {
Jamie Madill8693bdb2017-09-02 15:32:14 -0400736 if (detachMatchingAttachment(context, &mState.mColorAttachments[colorIndex], resourceType,
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300737 resourceId))
Jamie Madill8693bdb2017-09-02 15:32:14 -0400738 {
739 found = true;
740 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000741 }
742
Jamie Madilla02315b2017-02-23 14:14:47 -0500743 if (context->isWebGL1())
744 {
745 const std::array<FramebufferAttachment *, 3> attachments = {
746 {&mState.mWebGLDepthStencilAttachment, &mState.mWebGLDepthAttachment,
747 &mState.mWebGLStencilAttachment}};
748 for (FramebufferAttachment *attachment : attachments)
749 {
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300750 if (detachMatchingAttachment(context, attachment, resourceType, resourceId))
Jamie Madilla02315b2017-02-23 14:14:47 -0500751 {
Jamie Madill8693bdb2017-09-02 15:32:14 -0400752 found = true;
Jamie Madilla02315b2017-02-23 14:14:47 -0500753 }
754 }
755 }
756 else
757 {
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300758 if (detachMatchingAttachment(context, &mState.mDepthAttachment, resourceType, resourceId))
Jamie Madill8693bdb2017-09-02 15:32:14 -0400759 {
760 found = true;
761 }
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300762 if (detachMatchingAttachment(context, &mState.mStencilAttachment, resourceType, resourceId))
Jamie Madill8693bdb2017-09-02 15:32:14 -0400763 {
764 found = true;
765 }
Jamie Madilla02315b2017-02-23 14:14:47 -0500766 }
Jamie Madill8693bdb2017-09-02 15:32:14 -0400767
768 return found;
Jamie Madill362876b2016-06-16 14:46:59 -0400769}
770
Jamie Madill8693bdb2017-09-02 15:32:14 -0400771bool Framebuffer::detachMatchingAttachment(const Context *context,
Jamie Madill4928b7c2017-06-20 12:57:39 -0400772 FramebufferAttachment *attachment,
Jamie Madill362876b2016-06-16 14:46:59 -0400773 GLenum matchType,
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300774 GLuint matchId)
Jamie Madill362876b2016-06-16 14:46:59 -0400775{
776 if (attachment->isAttached() && attachment->type() == matchType && attachment->id() == matchId)
777 {
Olli Etuaho4ebd8f32018-09-20 11:12:46 +0300778 // We go through resetAttachment to make sure that all the required bookkeeping will be done
779 // such as updating enabled draw buffer state.
780 resetAttachment(context, attachment->getBinding());
Jamie Madill8693bdb2017-09-02 15:32:14 -0400781 return true;
Jamie Madill362876b2016-06-16 14:46:59 -0400782 }
Jamie Madill8693bdb2017-09-02 15:32:14 -0400783
784 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000785}
786
Corentin Wallez37c39792015-08-20 14:19:46 -0400787const FramebufferAttachment *Framebuffer::getColorbuffer(size_t colorAttachment) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000788{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400789 return mState.getColorAttachment(colorAttachment);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000790}
791
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400792const FramebufferAttachment *Framebuffer::getDepthbuffer() const
Geoff Lang646559f2013-08-15 11:08:15 -0400793{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400794 return mState.getDepthAttachment();
Geoff Lang646559f2013-08-15 11:08:15 -0400795}
796
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400797const FramebufferAttachment *Framebuffer::getStencilbuffer() const
798{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400799 return mState.getStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400800}
801
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400802const FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
803{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400804 return mState.getDepthStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400805}
806
807const FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000808{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400809 return mState.getDepthOrStencilAttachment();
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000810}
811
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500812const FramebufferAttachment *Framebuffer::getStencilOrDepthStencilAttachment() const
813{
814 return mState.getStencilOrDepthStencilAttachment();
815}
816
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400817const FramebufferAttachment *Framebuffer::getReadColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000818{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400819 return mState.getReadAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000820}
821
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000822GLenum Framebuffer::getReadColorbufferType() const
823{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400824 const FramebufferAttachment *readAttachment = mState.getReadAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400825 return (readAttachment != nullptr ? readAttachment->type() : GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000826}
827
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400828const FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000829{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400830 return mState.getFirstColorAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000831}
832
Jamie Madill6dd06ea2017-07-19 13:47:55 -0400833const FramebufferAttachment *Framebuffer::getFirstNonNullAttachment() const
834{
835 return mState.getFirstNonNullAttachment();
836}
837
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800838const FramebufferAttachment *Framebuffer::getAttachment(const Context *context,
839 GLenum attachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000840{
Bryan Bernhart (Intel Americas Inc)2eeb1b32017-11-29 16:06:43 -0800841 return mState.getAttachment(context, attachment);
Geoff Lang55ba29c2013-07-11 16:57:53 -0400842}
843
Geoff Langa15472a2015-08-11 11:48:03 -0400844size_t Framebuffer::getDrawbufferStateCount() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000845{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400846 return mState.mDrawBufferStates.size();
Geoff Langa15472a2015-08-11 11:48:03 -0400847}
848
849GLenum Framebuffer::getDrawBufferState(size_t drawBuffer) const
850{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400851 ASSERT(drawBuffer < mState.mDrawBufferStates.size());
852 return mState.mDrawBufferStates[drawBuffer];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000853}
854
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500855const std::vector<GLenum> &Framebuffer::getDrawBufferStates() const
856{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400857 return mState.getDrawBufferStates();
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500858}
859
Geoff Lang164d54e2014-12-01 10:55:33 -0500860void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000861{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400862 auto &drawStates = mState.mDrawBufferStates;
Jamie Madilld1405e52015-03-05 15:41:39 -0500863
864 ASSERT(count <= drawStates.size());
865 std::copy(buffers, buffers + count, drawStates.begin());
866 std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500867 mDirtyBits.set(DIRTY_BIT_DRAW_BUFFERS);
Jamie Madilla4595b82017-01-11 17:36:34 -0500868
869 mState.mEnabledDrawBuffers.reset();
Brandon Jones76746f92017-11-22 11:44:41 -0800870 mState.mDrawBufferTypeMask.reset();
871
Jamie Madilla4595b82017-01-11 17:36:34 -0500872 for (size_t index = 0; index < count; ++index)
873 {
Brandon Jones76746f92017-11-22 11:44:41 -0800874 mState.mDrawBufferTypeMask.setIndex(getDrawbufferWriteType(index), index);
875
Jamie Madilla4595b82017-01-11 17:36:34 -0500876 if (drawStates[index] != GL_NONE && mState.mColorAttachments[index].isAttached())
877 {
878 mState.mEnabledDrawBuffers.set(index);
879 }
880 }
Geoff Lang9dd95802014-12-01 11:12:59 -0500881}
882
Geoff Langa15472a2015-08-11 11:48:03 -0400883const FramebufferAttachment *Framebuffer::getDrawBuffer(size_t drawBuffer) const
884{
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400885 return mState.getDrawBuffer(drawBuffer);
Geoff Langa15472a2015-08-11 11:48:03 -0400886}
887
Geoff Lange0cff192017-05-30 13:04:56 -0400888GLenum Framebuffer::getDrawbufferWriteType(size_t drawBuffer) const
889{
890 const FramebufferAttachment *attachment = mState.getDrawBuffer(drawBuffer);
891 if (attachment == nullptr)
892 {
893 return GL_NONE;
894 }
895
896 GLenum componentType = attachment->getFormat().info->componentType;
897 switch (componentType)
898 {
899 case GL_INT:
900 case GL_UNSIGNED_INT:
901 return componentType;
902
903 default:
904 return GL_FLOAT;
905 }
906}
907
Brandon Jonesc405ae72017-12-06 14:15:03 -0800908ComponentTypeMask Framebuffer::getDrawBufferTypeMask() const
Brandon Jones76746f92017-11-22 11:44:41 -0800909{
910 return mState.mDrawBufferTypeMask;
911}
912
913DrawBufferMask Framebuffer::getDrawBufferMask() const
914{
915 return mState.mEnabledDrawBuffers;
916}
917
Geoff Langa15472a2015-08-11 11:48:03 -0400918bool Framebuffer::hasEnabledDrawBuffer() const
919{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400920 for (size_t drawbufferIdx = 0; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
Geoff Langa15472a2015-08-11 11:48:03 -0400921 {
922 if (getDrawBuffer(drawbufferIdx) != nullptr)
923 {
924 return true;
925 }
926 }
927
928 return false;
929}
930
Geoff Lang9dd95802014-12-01 11:12:59 -0500931GLenum Framebuffer::getReadBufferState() const
932{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400933 return mState.mReadBufferState;
Geoff Lang9dd95802014-12-01 11:12:59 -0500934}
935
936void Framebuffer::setReadBuffer(GLenum buffer)
937{
Jamie Madillb885e572015-02-03 16:16:04 -0500938 ASSERT(buffer == GL_BACK || buffer == GL_NONE ||
939 (buffer >= GL_COLOR_ATTACHMENT0 &&
Jamie Madill48ef11b2016-04-27 15:21:52 -0400940 (buffer - GL_COLOR_ATTACHMENT0) < mState.mColorAttachments.size()));
941 mState.mReadBufferState = buffer;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500942 mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000943}
944
Corentin Wallez37c39792015-08-20 14:19:46 -0400945size_t Framebuffer::getNumColorBuffers() const
946{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400947 return mState.mColorAttachments.size();
Corentin Wallez37c39792015-08-20 14:19:46 -0400948}
949
Jamie Madill0df8fe42015-11-24 16:10:24 -0500950bool Framebuffer::hasDepth() const
951{
Jamie Madill9c335862017-07-18 11:51:38 -0400952 return mState.hasDepth();
Jamie Madill0df8fe42015-11-24 16:10:24 -0500953}
954
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000955bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000956{
Jamie Madill9c335862017-07-18 11:51:38 -0400957 return mState.hasStencil();
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000958}
959
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000960bool Framebuffer::usingExtendedDrawBuffers() const
961{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400962 for (size_t drawbufferIdx = 1; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000963 {
Geoff Langa15472a2015-08-11 11:48:03 -0400964 if (getDrawBuffer(drawbufferIdx) != nullptr)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000965 {
966 return true;
967 }
968 }
969
970 return false;
971}
972
Jamie Madillb983a4b2018-08-01 11:34:51 -0400973void Framebuffer::invalidateCompletenessCache(const Context *context)
Geoff Lang9aded172017-04-05 11:07:56 -0400974{
Jamie Madill2274b652018-05-31 10:56:08 -0400975 if (mState.mId != 0)
Geoff Lang9aded172017-04-05 11:07:56 -0400976 {
977 mCachedStatus.reset();
Jamie Madilld84b6732018-09-06 15:54:35 -0400978 onStateChange(context, angle::SubjectMessage::CONTENTS_CHANGED);
Geoff Lang9aded172017-04-05 11:07:56 -0400979 }
980}
981
Jamie Madillcc73f242018-08-01 11:34:48 -0400982GLenum Framebuffer::checkStatusImpl(const Context *context)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000983{
Jamie Madillcc73f242018-08-01 11:34:48 -0400984 ASSERT(!isDefault());
985 ASSERT(hasAnyDirtyBit() || !mCachedStatus.valid());
Geoff Lang528ce3c2014-12-01 10:44:07 -0500986
Jamie Madillcc73f242018-08-01 11:34:48 -0400987 mCachedStatus = checkStatusWithGLFrontEnd(context);
Jamie Madille98b1b52018-03-08 09:47:23 -0500988
Jamie Madillcc73f242018-08-01 11:34:48 -0400989 if (mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE)
990 {
Jamie Madill77abad82018-10-25 17:03:48 -0400991 angle::Result err = syncState(context);
992 if (err != angle::Result::Continue())
Jamie Madille98b1b52018-03-08 09:47:23 -0500993 {
Jamie Madill77abad82018-10-25 17:03:48 -0400994 return 0;
Jamie Madillcc73f242018-08-01 11:34:48 -0400995 }
996 if (!mImpl->checkStatus(context))
997 {
998 mCachedStatus = GL_FRAMEBUFFER_UNSUPPORTED;
Jamie Madille98b1b52018-03-08 09:47:23 -0500999 }
Jamie Madill362876b2016-06-16 14:46:59 -04001000 }
1001
Jamie Madill427064d2018-04-13 16:20:34 -04001002 return mCachedStatus.value();
Jamie Madill362876b2016-06-16 14:46:59 -04001003}
1004
Jamie Madille98b1b52018-03-08 09:47:23 -05001005GLenum Framebuffer::checkStatusWithGLFrontEnd(const Context *context)
Jamie Madill362876b2016-06-16 14:46:59 -04001006{
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001007 const ContextState &state = context->getContextState();
1008
Jamie Madill2274b652018-05-31 10:56:08 -04001009 ASSERT(mState.mId != 0);
Jamie Madill362876b2016-06-16 14:46:59 -04001010
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001011 bool hasAttachments = false;
1012 Optional<unsigned int> colorbufferSize;
1013 Optional<int> samples;
Geoff Lang92019432017-11-20 13:09:34 -05001014 Optional<bool> fixedSampleLocations;
JiangYizhou461d9a32017-01-04 16:37:26 +08001015 bool hasRenderbuffer = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001016
Martin Radev9bc9a322017-07-21 14:28:17 +03001017 const FramebufferAttachment *firstAttachment = getFirstNonNullAttachment();
1018
Jiawei Shaoa8802472018-05-28 11:17:47 +08001019 Optional<bool> isLayered;
1020 Optional<TextureType> colorAttachmentsTextureType;
1021
Jamie Madill48ef11b2016-04-27 15:21:52 -04001022 for (const FramebufferAttachment &colorAttachment : mState.mColorAttachments)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001023 {
Jamie Madill2d06b732015-04-20 12:53:28 -04001024 if (colorAttachment.isAttached())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001025 {
Geoff Lang9f10b772017-05-16 15:51:03 -04001026 if (!CheckAttachmentCompleteness(context, colorAttachment))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001027 {
1028 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1029 }
daniel@transgaming.com01868132010-08-24 19:21:17 +00001030
Geoff Lang677bb6f2017-04-05 12:40:40 -04001031 const InternalFormat &format = *colorAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -04001032 if (format.depthBits > 0 || format.stencilBits > 0)
1033 {
1034 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1035 }
1036
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001037 if (!CheckAttachmentSampleCompleteness(context, colorAttachment, true, &samples,
1038 &fixedSampleLocations))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001039 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001040 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001041 }
1042
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001043 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
1044 // in GLES 3.0, there is no such restriction
1045 if (state.getClientMajorVersion() < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001046 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001047 if (colorbufferSize.valid())
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001048 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001049 if (format.pixelBytes != colorbufferSize.value())
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +00001050 {
1051 return GL_FRAMEBUFFER_UNSUPPORTED;
1052 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001053 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001054 else
1055 {
1056 colorbufferSize = format.pixelBytes;
1057 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001058 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001059
Martin Radev9bc9a322017-07-21 14:28:17 +03001060 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &colorAttachment))
1061 {
1062 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
1063 }
1064
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001065 hasRenderbuffer = hasRenderbuffer || (colorAttachment.type() == GL_RENDERBUFFER);
Jiawei Shaoa8802472018-05-28 11:17:47 +08001066
1067 if (!hasAttachments)
1068 {
1069 isLayered = colorAttachment.isLayered();
1070 if (isLayered.value())
1071 {
1072 colorAttachmentsTextureType = colorAttachment.getTextureImageIndex().getType();
1073 }
1074 hasAttachments = true;
1075 }
1076 else
1077 {
1078 // [EXT_geometry_shader] section 9.4.1, "Framebuffer Completeness"
1079 // If any framebuffer attachment is layered, all populated attachments
1080 // must be layered. Additionally, all populated color attachments must
1081 // be from textures of the same target. {FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT }
1082 ASSERT(isLayered.valid());
1083 if (isLayered.value() != colorAttachment.isLayered())
1084 {
1085 return GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT;
1086 }
1087 else if (isLayered.value())
1088 {
1089 ASSERT(colorAttachmentsTextureType.valid());
1090 if (colorAttachmentsTextureType.value() !=
1091 colorAttachment.getTextureImageIndex().getType())
1092 {
1093 return GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT;
1094 }
1095 }
1096 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001097 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001098 }
1099
Jamie Madill48ef11b2016-04-27 15:21:52 -04001100 const FramebufferAttachment &depthAttachment = mState.mDepthAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -04001101 if (depthAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001102 {
Geoff Lang9f10b772017-05-16 15:51:03 -04001103 if (!CheckAttachmentCompleteness(context, depthAttachment))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001104 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001105 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001106 }
1107
Geoff Lang677bb6f2017-04-05 12:40:40 -04001108 const InternalFormat &format = *depthAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -04001109 if (format.depthBits == 0)
1110 {
1111 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001112 }
1113
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001114 if (!CheckAttachmentSampleCompleteness(context, depthAttachment, false, &samples,
1115 &fixedSampleLocations))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001116 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001117 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001118 }
Sami Väisänena797e062016-05-12 15:23:40 +03001119
Martin Radev9bc9a322017-07-21 14:28:17 +03001120 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &depthAttachment))
1121 {
1122 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
1123 }
1124
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001125 hasRenderbuffer = hasRenderbuffer || (depthAttachment.type() == GL_RENDERBUFFER);
Jiawei Shaoa8802472018-05-28 11:17:47 +08001126
1127 if (!hasAttachments)
1128 {
1129 isLayered = depthAttachment.isLayered();
1130 hasAttachments = true;
1131 }
1132 else
1133 {
1134 // [EXT_geometry_shader] section 9.4.1, "Framebuffer Completeness"
1135 // If any framebuffer attachment is layered, all populated attachments
1136 // must be layered. {FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT }
1137 ASSERT(isLayered.valid());
1138 if (isLayered.value() != depthAttachment.isLayered())
1139 {
1140 return GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT;
1141 }
1142 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001143 }
1144
Jamie Madill48ef11b2016-04-27 15:21:52 -04001145 const FramebufferAttachment &stencilAttachment = mState.mStencilAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -04001146 if (stencilAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001147 {
Geoff Lang9f10b772017-05-16 15:51:03 -04001148 if (!CheckAttachmentCompleteness(context, stencilAttachment))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001149 {
1150 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1151 }
1152
Geoff Lang677bb6f2017-04-05 12:40:40 -04001153 const InternalFormat &format = *stencilAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -04001154 if (format.stencilBits == 0)
1155 {
1156 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001157 }
1158
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001159 if (!CheckAttachmentSampleCompleteness(context, stencilAttachment, false, &samples,
1160 &fixedSampleLocations))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001161 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001162 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001163 }
Corentin Wallez086d59a2016-04-29 09:06:49 -04001164
Martin Radev9bc9a322017-07-21 14:28:17 +03001165 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &stencilAttachment))
1166 {
1167 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
1168 }
1169
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001170 hasRenderbuffer = hasRenderbuffer || (stencilAttachment.type() == GL_RENDERBUFFER);
Jiawei Shaoa8802472018-05-28 11:17:47 +08001171
1172 if (!hasAttachments)
1173 {
1174 hasAttachments = true;
1175 }
1176 else
1177 {
1178 // [EXT_geometry_shader] section 9.4.1, "Framebuffer Completeness"
1179 // If any framebuffer attachment is layered, all populated attachments
1180 // must be layered.
1181 // {FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT }
1182 ASSERT(isLayered.valid());
1183 if (isLayered.value() != stencilAttachment.isLayered())
1184 {
1185 return GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT;
1186 }
1187 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001188 }
1189
1190 // Starting from ES 3.0 stencil and depth, if present, should be the same image
1191 if (state.getClientMajorVersion() >= 3 && depthAttachment.isAttached() &&
1192 stencilAttachment.isAttached() && stencilAttachment != depthAttachment)
1193 {
1194 return GL_FRAMEBUFFER_UNSUPPORTED;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001195 }
1196
Jamie Madilla02315b2017-02-23 14:14:47 -05001197 // Special additional validation for WebGL 1 DEPTH/STENCIL/DEPTH_STENCIL.
1198 if (state.isWebGL1())
1199 {
1200 if (!mState.mWebGLDepthStencilConsistent)
1201 {
1202 return GL_FRAMEBUFFER_UNSUPPORTED;
1203 }
1204
1205 if (mState.mWebGLDepthStencilAttachment.isAttached())
1206 {
1207 if (mState.mWebGLDepthStencilAttachment.getDepthSize() == 0 ||
1208 mState.mWebGLDepthStencilAttachment.getStencilSize() == 0)
1209 {
1210 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1211 }
Martin Radev9bc9a322017-07-21 14:28:17 +03001212
1213 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment,
1214 &mState.mWebGLDepthStencilAttachment))
1215 {
1216 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
1217 }
Jamie Madilla02315b2017-02-23 14:14:47 -05001218 }
1219 else if (mState.mStencilAttachment.isAttached() &&
1220 mState.mStencilAttachment.getDepthSize() > 0)
1221 {
1222 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1223 }
1224 else if (mState.mDepthAttachment.isAttached() &&
1225 mState.mDepthAttachment.getStencilSize() > 0)
1226 {
1227 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1228 }
1229 }
1230
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001231 // ES3.1(section 9.4) requires that if no image is attached to the framebuffer, and either the
1232 // value of the framebuffer's FRAMEBUFFER_DEFAULT_WIDTH or FRAMEBUFFER_DEFAULT_HEIGHT parameters
1233 // is zero, the framebuffer is considered incomplete.
JiangYizhou461d9a32017-01-04 16:37:26 +08001234 GLint defaultWidth = mState.getDefaultWidth();
1235 GLint defaultHeight = mState.getDefaultHeight();
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001236 if (!hasAttachments && (defaultWidth == 0 || defaultHeight == 0))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001237 {
1238 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001239 }
1240
Geoff Langa0e0aeb2017-04-12 15:06:29 -04001241 // In ES 2.0 and WebGL, all color attachments must have the same width and height.
Jamie Madillcc86d642015-11-24 13:00:07 -05001242 // In ES 3.0, there is no such restriction.
Geoff Langa0e0aeb2017-04-12 15:06:29 -04001243 if ((state.getClientMajorVersion() < 3 || state.getExtensions().webglCompatibility) &&
1244 !mState.attachmentsHaveSameDimensions())
Jamie Madillcc86d642015-11-24 13:00:07 -05001245 {
1246 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
1247 }
1248
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001249 // ES3.1(section 9.4) requires that if the attached images are a mix of renderbuffers and
1250 // textures, the value of TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all attached textures.
JiangYizhou461d9a32017-01-04 16:37:26 +08001251 if (fixedSampleLocations.valid() && hasRenderbuffer && !fixedSampleLocations.value())
1252 {
1253 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1254 }
1255
Kenneth Russellce8602a2017-10-03 18:23:08 -07001256 // The WebGL conformance tests implicitly define that all framebuffer
1257 // attachments must be unique. For example, the same level of a texture can
1258 // not be attached to two different color attachments.
1259 if (state.getExtensions().webglCompatibility)
1260 {
1261 if (!mState.colorAttachmentsAreUniqueImages())
1262 {
1263 return GL_FRAMEBUFFER_UNSUPPORTED;
1264 }
1265 }
1266
Jamie Madillcc86d642015-11-24 13:00:07 -05001267 return GL_FRAMEBUFFER_COMPLETE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001268}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001269
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001270angle::Result Framebuffer::discard(const Context *context, size_t count, const GLenum *attachments)
Austin Kinross08332632015-05-05 13:35:47 -07001271{
Jamie Madill05b35b22017-10-03 09:01:44 -04001272 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1273 // can be no-ops, so we should probably do that to ensure consistency.
1274 // TODO(jmadill): WebGL behaviour, and robust resource init behaviour without WebGL.
1275
Jamie Madill4928b7c2017-06-20 12:57:39 -04001276 return mImpl->discard(context, count, attachments);
Austin Kinross08332632015-05-05 13:35:47 -07001277}
1278
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001279angle::Result Framebuffer::invalidate(const Context *context,
1280 size_t count,
1281 const GLenum *attachments)
Jamie Madill2d96b9e2014-08-29 15:46:47 -04001282{
Jamie Madill05b35b22017-10-03 09:01:44 -04001283 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1284 // can be no-ops, so we should probably do that to ensure consistency.
1285 // TODO(jmadill): WebGL behaviour, and robust resource init behaviour without WebGL.
1286
Jamie Madill4928b7c2017-06-20 12:57:39 -04001287 return mImpl->invalidate(context, count, attachments);
Jamie Madill2d96b9e2014-08-29 15:46:47 -04001288}
1289
Jamie Madill05b35b22017-10-03 09:01:44 -04001290bool Framebuffer::partialClearNeedsInit(const Context *context,
1291 bool color,
1292 bool depth,
1293 bool stencil)
1294{
1295 const auto &glState = context->getGLState();
1296
1297 if (!glState.isRobustResourceInitEnabled())
1298 {
1299 return false;
1300 }
1301
1302 // Scissors can affect clearing.
1303 // TODO(jmadill): Check for complete scissor overlap.
1304 if (glState.isScissorTestEnabled())
1305 {
1306 return true;
1307 }
1308
1309 // If colors masked, we must clear before we clear. Do a simple check.
1310 // TODO(jmadill): Filter out unused color channels from the test.
1311 if (color)
1312 {
1313 const auto &blend = glState.getBlendState();
1314 if (!(blend.colorMaskRed && blend.colorMaskGreen && blend.colorMaskBlue &&
1315 blend.colorMaskAlpha))
1316 {
1317 return true;
1318 }
1319 }
1320
1321 const auto &depthStencil = glState.getDepthStencilState();
Yuly Novikov21edf3d2018-07-23 16:44:16 -04001322 if (stencil && (depthStencil.stencilMask != depthStencil.stencilWritemask ||
1323 depthStencil.stencilBackMask != depthStencil.stencilBackWritemask))
Jamie Madill05b35b22017-10-03 09:01:44 -04001324 {
1325 return true;
1326 }
1327
1328 return false;
1329}
1330
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001331angle::Result Framebuffer::invalidateSub(const Context *context,
1332 size_t count,
1333 const GLenum *attachments,
1334 const Rectangle &area)
Jamie Madill400a4412014-08-29 15:46:45 -04001335{
Jamie Madill05b35b22017-10-03 09:01:44 -04001336 // Back-ends might make the contents of the FBO undefined. In WebGL 2.0, invalidate operations
1337 // can be no-ops, so we should probably do that to ensure consistency.
1338 // TODO(jmadill): Make a invalidate no-op in WebGL 2.0.
1339
Jamie Madill4928b7c2017-06-20 12:57:39 -04001340 return mImpl->invalidateSub(context, count, attachments, area);
Jamie Madill400a4412014-08-29 15:46:45 -04001341}
1342
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001343angle::Result Framebuffer::clear(const Context *context, GLbitfield mask)
Geoff Langb04dc822014-12-01 12:02:02 -05001344{
Jamie Madill05b35b22017-10-03 09:01:44 -04001345 const auto &glState = context->getGLState();
1346 if (glState.isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -05001347 {
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001348 return angle::Result::Continue();
Jamie Madill984ef412015-11-24 16:10:21 -05001349 }
1350
Jamie Madill05b35b22017-10-03 09:01:44 -04001351 ANGLE_TRY(mImpl->clear(context, mask));
1352
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001353 return angle::Result::Continue();
Geoff Langb04dc822014-12-01 12:02:02 -05001354}
1355
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001356angle::Result Framebuffer::clearBufferfv(const Context *context,
1357 GLenum buffer,
1358 GLint drawbuffer,
1359 const GLfloat *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001360{
Jamie Madill05b35b22017-10-03 09:01:44 -04001361 if (context->getGLState().isRasterizerDiscardEnabled() ||
1362 IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001363 {
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001364 return angle::Result::Continue();
Jamie Madill984ef412015-11-24 16:10:21 -05001365 }
1366
Jamie Madill05b35b22017-10-03 09:01:44 -04001367 ANGLE_TRY(mImpl->clearBufferfv(context, buffer, drawbuffer, values));
1368
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001369 return angle::Result::Continue();
Geoff Langb04dc822014-12-01 12:02:02 -05001370}
1371
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001372angle::Result Framebuffer::clearBufferuiv(const Context *context,
1373 GLenum buffer,
1374 GLint drawbuffer,
1375 const GLuint *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001376{
Jamie Madill05b35b22017-10-03 09:01:44 -04001377 if (context->getGLState().isRasterizerDiscardEnabled() ||
1378 IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001379 {
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001380 return angle::Result::Continue();
Jamie Madill984ef412015-11-24 16:10:21 -05001381 }
1382
Jamie Madill05b35b22017-10-03 09:01:44 -04001383 ANGLE_TRY(mImpl->clearBufferuiv(context, buffer, drawbuffer, values));
1384
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001385 return angle::Result::Continue();
Geoff Langb04dc822014-12-01 12:02:02 -05001386}
1387
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001388angle::Result Framebuffer::clearBufferiv(const Context *context,
1389 GLenum buffer,
1390 GLint drawbuffer,
1391 const GLint *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001392{
Jamie Madill05b35b22017-10-03 09:01:44 -04001393 if (context->getGLState().isRasterizerDiscardEnabled() ||
1394 IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001395 {
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001396 return angle::Result::Continue();
Jamie Madill984ef412015-11-24 16:10:21 -05001397 }
1398
Jamie Madill05b35b22017-10-03 09:01:44 -04001399 ANGLE_TRY(mImpl->clearBufferiv(context, buffer, drawbuffer, values));
1400
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001401 return angle::Result::Continue();
Geoff Langb04dc822014-12-01 12:02:02 -05001402}
1403
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001404angle::Result Framebuffer::clearBufferfi(const Context *context,
1405 GLenum buffer,
1406 GLint drawbuffer,
1407 GLfloat depth,
1408 GLint stencil)
Geoff Langb04dc822014-12-01 12:02:02 -05001409{
Jamie Madill05b35b22017-10-03 09:01:44 -04001410 if (context->getGLState().isRasterizerDiscardEnabled() ||
1411 IsClearBufferMaskedOut(context, buffer))
Jamie Madill984ef412015-11-24 16:10:21 -05001412 {
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001413 return angle::Result::Continue();
Jamie Madill984ef412015-11-24 16:10:21 -05001414 }
1415
Jamie Madill05b35b22017-10-03 09:01:44 -04001416 ANGLE_TRY(mImpl->clearBufferfi(context, buffer, drawbuffer, depth, stencil));
1417
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001418 return angle::Result::Continue();
Geoff Langb04dc822014-12-01 12:02:02 -05001419}
1420
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001421angle::Result Framebuffer::getImplementationColorReadFormat(const Context *context,
1422 GLenum *formatOut)
Geoff Langbce529e2014-12-01 12:48:41 -05001423{
Jamie Madill690c8eb2018-03-12 15:20:03 -04001424 ANGLE_TRY(syncState(context));
1425 *formatOut = mImpl->getImplementationColorReadFormat(context);
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001426 return angle::Result::Continue();
Geoff Langbce529e2014-12-01 12:48:41 -05001427}
1428
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001429angle::Result Framebuffer::getImplementationColorReadType(const Context *context, GLenum *typeOut)
Geoff Langbce529e2014-12-01 12:48:41 -05001430{
Jamie Madill690c8eb2018-03-12 15:20:03 -04001431 ANGLE_TRY(syncState(context));
1432 *typeOut = mImpl->getImplementationColorReadType(context);
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001433 return angle::Result::Continue();
Geoff Langbce529e2014-12-01 12:48:41 -05001434}
1435
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001436angle::Result Framebuffer::readPixels(const Context *context,
1437 const Rectangle &area,
1438 GLenum format,
1439 GLenum type,
1440 void *pixels)
Geoff Langbce529e2014-12-01 12:48:41 -05001441{
Jamie Madill05b35b22017-10-03 09:01:44 -04001442 ANGLE_TRY(ensureReadAttachmentInitialized(context, GL_COLOR_BUFFER_BIT));
Jamie Madill362876b2016-06-16 14:46:59 -04001443 ANGLE_TRY(mImpl->readPixels(context, area, format, type, pixels));
Geoff Lang520c4ae2015-05-05 13:12:36 -04001444
Jamie Madilld4442552018-02-27 22:03:47 -05001445 Buffer *unpackBuffer = context->getGLState().getTargetBuffer(BufferBinding::PixelUnpack);
Geoff Lang520c4ae2015-05-05 13:12:36 -04001446 if (unpackBuffer)
1447 {
Jamie Madill09463932018-04-04 05:26:59 -04001448 unpackBuffer->onPixelPack(context);
Geoff Lang520c4ae2015-05-05 13:12:36 -04001449 }
1450
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001451 return angle::Result::Continue();
Geoff Langbce529e2014-12-01 12:48:41 -05001452}
1453
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001454angle::Result Framebuffer::blit(const Context *context,
1455 const Rectangle &sourceArea,
1456 const Rectangle &destArea,
1457 GLbitfield mask,
1458 GLenum filter)
Geoff Lang54bd5a42014-12-01 12:51:04 -05001459{
He Yunchao6be602d2016-12-22 14:33:07 +08001460 GLbitfield blitMask = mask;
1461
1462 // Note that blitting is called against draw framebuffer.
1463 // See the code in gl::Context::blitFramebuffer.
1464 if ((mask & GL_COLOR_BUFFER_BIT) && !hasEnabledDrawBuffer())
1465 {
1466 blitMask &= ~GL_COLOR_BUFFER_BIT;
1467 }
1468
1469 if ((mask & GL_STENCIL_BUFFER_BIT) && mState.getStencilAttachment() == nullptr)
1470 {
1471 blitMask &= ~GL_STENCIL_BUFFER_BIT;
1472 }
1473
1474 if ((mask & GL_DEPTH_BUFFER_BIT) && mState.getDepthAttachment() == nullptr)
1475 {
1476 blitMask &= ~GL_DEPTH_BUFFER_BIT;
1477 }
1478
1479 if (!blitMask)
1480 {
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001481 return angle::Result::Continue();
He Yunchao6be602d2016-12-22 14:33:07 +08001482 }
1483
Jamie Madill05b35b22017-10-03 09:01:44 -04001484 auto *sourceFBO = context->getGLState().getReadFramebuffer();
1485 ANGLE_TRY(sourceFBO->ensureReadAttachmentInitialized(context, blitMask));
1486
1487 // TODO(jmadill): Only clear if not the full FBO dimensions, and only specified bitmask.
1488 ANGLE_TRY(ensureDrawAttachmentsInitialized(context));
1489
He Yunchao6be602d2016-12-22 14:33:07 +08001490 return mImpl->blit(context, sourceArea, destArea, blitMask, filter);
Geoff Lang54bd5a42014-12-01 12:51:04 -05001491}
1492
Luc Ferronbf6dc372018-06-28 15:24:19 -04001493bool Framebuffer::isDefault() const
1494{
1495 return id() == 0;
1496}
1497
Jamie Madill427064d2018-04-13 16:20:34 -04001498int Framebuffer::getSamples(const Context *context)
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001499{
Jamie Madill427064d2018-04-13 16:20:34 -04001500 return (isComplete(context) ? getCachedSamples(context) : 0);
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001501}
1502
Jamie Madill9c335862017-07-18 11:51:38 -04001503int Framebuffer::getCachedSamples(const Context *context)
1504{
Jamie Madill5b772312018-03-08 20:28:32 -05001505 ASSERT(mCachedStatus.valid() && mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE);
1506
Jamie Madill9c335862017-07-18 11:51:38 -04001507 // For a complete framebuffer, all attachments must have the same sample count.
1508 // In this case return the first nonzero sample size.
1509 const auto *firstNonNullAttachment = mState.getFirstNonNullAttachment();
1510 if (firstNonNullAttachment)
1511 {
1512 ASSERT(firstNonNullAttachment->isAttached());
1513 return firstNonNullAttachment->getSamples();
1514 }
1515
1516 // No attachments found.
1517 return 0;
1518}
1519
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001520angle::Result Framebuffer::getSamplePosition(const Context *context,
1521 size_t index,
1522 GLfloat *xy) const
Corentin Wallezccab69d2017-01-27 16:57:15 -05001523{
Geoff Lang13455072018-05-09 11:24:43 -04001524 ANGLE_TRY(mImpl->getSamplePosition(context, index, xy));
Jamie Madill64b7c4f2018-10-19 11:38:04 -04001525 return angle::Result::Continue();
Corentin Wallezccab69d2017-01-27 16:57:15 -05001526}
1527
Jamie Madille261b442014-06-25 12:42:21 -04001528bool Framebuffer::hasValidDepthStencil() const
1529{
Jamie Madill48ef11b2016-04-27 15:21:52 -04001530 return mState.getDepthStencilAttachment() != nullptr;
Jamie Madille261b442014-06-25 12:42:21 -04001531}
1532
Jamie Madilla02315b2017-02-23 14:14:47 -05001533void Framebuffer::setAttachment(const Context *context,
1534 GLenum type,
Jamie Madill2d06b732015-04-20 12:53:28 -04001535 GLenum binding,
1536 const ImageIndex &textureIndex,
1537 FramebufferAttachmentObject *resource)
Geoff Langab75a052014-10-15 12:56:37 -04001538{
Martin Radev5dae57b2017-07-14 16:15:55 +03001539 setAttachment(context, type, binding, textureIndex, resource,
1540 FramebufferAttachment::kDefaultNumViews,
1541 FramebufferAttachment::kDefaultBaseViewIndex,
1542 FramebufferAttachment::kDefaultMultiviewLayout,
1543 FramebufferAttachment::kDefaultViewportOffsets);
1544}
1545
1546void Framebuffer::setAttachment(const Context *context,
1547 GLenum type,
1548 GLenum binding,
1549 const ImageIndex &textureIndex,
1550 FramebufferAttachmentObject *resource,
1551 GLsizei numViews,
1552 GLuint baseViewIndex,
1553 GLenum multiviewLayout,
1554 const GLint *viewportOffsets)
1555{
Jamie Madilla02315b2017-02-23 14:14:47 -05001556 // Context may be null in unit tests.
1557 if (!context || !context->isWebGL1())
1558 {
Martin Radev5dae57b2017-07-14 16:15:55 +03001559 setAttachmentImpl(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
1560 multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001561 return;
1562 }
1563
1564 switch (binding)
1565 {
1566 case GL_DEPTH_STENCIL:
1567 case GL_DEPTH_STENCIL_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001568 mState.mWebGLDepthStencilAttachment.attach(context, type, binding, textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001569 resource, numViews, baseViewIndex,
1570 multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001571 break;
1572 case GL_DEPTH:
1573 case GL_DEPTH_ATTACHMENT:
Martin Radev5dae57b2017-07-14 16:15:55 +03001574 mState.mWebGLDepthAttachment.attach(context, type, binding, textureIndex, resource,
1575 numViews, baseViewIndex, multiviewLayout,
1576 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001577 break;
1578 case GL_STENCIL:
1579 case GL_STENCIL_ATTACHMENT:
Martin Radev5dae57b2017-07-14 16:15:55 +03001580 mState.mWebGLStencilAttachment.attach(context, type, binding, textureIndex, resource,
1581 numViews, baseViewIndex, multiviewLayout,
1582 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001583 break;
1584 default:
Martin Radev5dae57b2017-07-14 16:15:55 +03001585 setAttachmentImpl(context, type, binding, textureIndex, resource, numViews,
1586 baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001587 return;
1588 }
1589
Martin Radev5dae57b2017-07-14 16:15:55 +03001590 commitWebGL1DepthStencilIfConsistent(context, numViews, baseViewIndex, multiviewLayout,
1591 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001592}
1593
Martin Radev82ef7742017-08-08 17:44:58 +03001594void Framebuffer::setAttachmentMultiviewLayered(const Context *context,
1595 GLenum type,
1596 GLenum binding,
1597 const ImageIndex &textureIndex,
1598 FramebufferAttachmentObject *resource,
1599 GLsizei numViews,
1600 GLint baseViewIndex)
1601{
1602 setAttachment(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
1603 GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE,
1604 FramebufferAttachment::kDefaultViewportOffsets);
1605}
1606
Martin Radev5dae57b2017-07-14 16:15:55 +03001607void Framebuffer::setAttachmentMultiviewSideBySide(const Context *context,
1608 GLenum type,
1609 GLenum binding,
1610 const ImageIndex &textureIndex,
1611 FramebufferAttachmentObject *resource,
1612 GLsizei numViews,
1613 const GLint *viewportOffsets)
1614{
1615 setAttachment(context, type, binding, textureIndex, resource, numViews,
1616 FramebufferAttachment::kDefaultBaseViewIndex,
1617 GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, viewportOffsets);
1618}
1619
1620void Framebuffer::commitWebGL1DepthStencilIfConsistent(const Context *context,
1621 GLsizei numViews,
1622 GLuint baseViewIndex,
1623 GLenum multiviewLayout,
1624 const GLint *viewportOffsets)
Jamie Madilla02315b2017-02-23 14:14:47 -05001625{
1626 int count = 0;
1627
1628 std::array<FramebufferAttachment *, 3> attachments = {{&mState.mWebGLDepthStencilAttachment,
1629 &mState.mWebGLDepthAttachment,
1630 &mState.mWebGLStencilAttachment}};
1631 for (FramebufferAttachment *attachment : attachments)
1632 {
1633 if (attachment->isAttached())
1634 {
1635 count++;
1636 }
1637 }
1638
1639 mState.mWebGLDepthStencilConsistent = (count <= 1);
1640 if (!mState.mWebGLDepthStencilConsistent)
1641 {
1642 // Inconsistent.
1643 return;
1644 }
1645
Geoff Lange466c552017-03-17 15:24:12 -04001646 auto getImageIndexIfTextureAttachment = [](const FramebufferAttachment &attachment) {
1647 if (attachment.type() == GL_TEXTURE)
1648 {
1649 return attachment.getTextureImageIndex();
1650 }
1651 else
1652 {
Jamie Madillcc129372018-04-12 09:13:18 -04001653 return ImageIndex();
Geoff Lange466c552017-03-17 15:24:12 -04001654 }
1655 };
1656
Jamie Madilla02315b2017-02-23 14:14:47 -05001657 if (mState.mWebGLDepthAttachment.isAttached())
1658 {
1659 const auto &depth = mState.mWebGLDepthAttachment;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001660 setAttachmentImpl(context, depth.type(), GL_DEPTH_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001661 getImageIndexIfTextureAttachment(depth), depth.getResource(), numViews,
1662 baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madillcc129372018-04-12 09:13:18 -04001663 setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex(), nullptr, numViews,
1664 baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001665 }
1666 else if (mState.mWebGLStencilAttachment.isAttached())
1667 {
1668 const auto &stencil = mState.mWebGLStencilAttachment;
Jamie Madillcc129372018-04-12 09:13:18 -04001669 setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex(), nullptr, numViews,
1670 baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001671 setAttachmentImpl(context, stencil.type(), GL_STENCIL_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001672 getImageIndexIfTextureAttachment(stencil), stencil.getResource(),
1673 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001674 }
1675 else if (mState.mWebGLDepthStencilAttachment.isAttached())
1676 {
1677 const auto &depthStencil = mState.mWebGLDepthStencilAttachment;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001678 setAttachmentImpl(context, depthStencil.type(), GL_DEPTH_ATTACHMENT,
Geoff Lange466c552017-03-17 15:24:12 -04001679 getImageIndexIfTextureAttachment(depthStencil),
Martin Radev5dae57b2017-07-14 16:15:55 +03001680 depthStencil.getResource(), numViews, baseViewIndex, multiviewLayout,
1681 viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001682 setAttachmentImpl(context, depthStencil.type(), GL_STENCIL_ATTACHMENT,
Geoff Lange466c552017-03-17 15:24:12 -04001683 getImageIndexIfTextureAttachment(depthStencil),
Martin Radev5dae57b2017-07-14 16:15:55 +03001684 depthStencil.getResource(), numViews, baseViewIndex, multiviewLayout,
1685 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001686 }
1687 else
1688 {
Jamie Madillcc129372018-04-12 09:13:18 -04001689 setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex(), nullptr, numViews,
1690 baseViewIndex, multiviewLayout, viewportOffsets);
1691 setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex(), nullptr, numViews,
1692 baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001693 }
1694}
1695
Jamie Madill4928b7c2017-06-20 12:57:39 -04001696void Framebuffer::setAttachmentImpl(const Context *context,
1697 GLenum type,
Jamie Madilla02315b2017-02-23 14:14:47 -05001698 GLenum binding,
1699 const ImageIndex &textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001700 FramebufferAttachmentObject *resource,
1701 GLsizei numViews,
1702 GLuint baseViewIndex,
1703 GLenum multiviewLayout,
1704 const GLint *viewportOffsets)
Jamie Madilla02315b2017-02-23 14:14:47 -05001705{
Jamie Madilla02315b2017-02-23 14:14:47 -05001706 switch (binding)
1707 {
Jamie Madillb8126692017-04-05 11:22:17 -04001708 case GL_DEPTH_STENCIL:
1709 case GL_DEPTH_STENCIL_ATTACHMENT:
1710 {
1711 // ensure this is a legitimate depth+stencil format
1712 FramebufferAttachmentObject *attachmentObj = resource;
1713 if (resource)
1714 {
Jamie Madill4fd95d52017-04-05 11:22:18 -04001715 const Format &format = resource->getAttachmentFormat(binding, textureIndex);
Jamie Madillb8126692017-04-05 11:22:17 -04001716 if (format.info->depthBits == 0 || format.info->stencilBits == 0)
1717 {
1718 // Attaching nullptr detaches the current attachment.
1719 attachmentObj = nullptr;
1720 }
1721 }
1722
Jamie Madill4928b7c2017-06-20 12:57:39 -04001723 updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
Jamie Madillb8126692017-04-05 11:22:17 -04001724 &mDirtyDepthAttachmentBinding, type, binding, textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001725 attachmentObj, numViews, baseViewIndex, multiviewLayout,
1726 viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001727 updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
Jamie Madillb8126692017-04-05 11:22:17 -04001728 &mDirtyStencilAttachmentBinding, type, binding, textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001729 attachmentObj, numViews, baseViewIndex, multiviewLayout,
1730 viewportOffsets);
Jamie Madill42975642017-10-12 12:31:51 -04001731 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001732 }
1733
Jamie Madilla02315b2017-02-23 14:14:47 -05001734 case GL_DEPTH:
1735 case GL_DEPTH_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001736 updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001737 &mDirtyDepthAttachmentBinding, type, binding, textureIndex, resource,
1738 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madill2d06b732015-04-20 12:53:28 -04001739 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001740
Jamie Madilla02315b2017-02-23 14:14:47 -05001741 case GL_STENCIL:
1742 case GL_STENCIL_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001743 updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001744 &mDirtyStencilAttachmentBinding, type, binding, textureIndex, resource,
1745 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001746 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001747
Jamie Madilla02315b2017-02-23 14:14:47 -05001748 case GL_BACK:
Geoff Lang8170eab2017-09-21 13:59:04 -04001749 updateAttachment(context, &mState.mColorAttachments[0], DIRTY_BIT_COLOR_ATTACHMENT_0,
1750 &mDirtyColorAttachmentBindings[0], type, binding, textureIndex,
1751 resource, numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001752 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001753
Jamie Madilla02315b2017-02-23 14:14:47 -05001754 default:
1755 {
1756 size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
1757 ASSERT(colorIndex < mState.mColorAttachments.size());
Jamie Madillb8126692017-04-05 11:22:17 -04001758 size_t dirtyBit = DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001759 updateAttachment(context, &mState.mColorAttachments[colorIndex], dirtyBit,
Jamie Madillb8126692017-04-05 11:22:17 -04001760 &mDirtyColorAttachmentBindings[colorIndex], type, binding,
Martin Radev5dae57b2017-07-14 16:15:55 +03001761 textureIndex, resource, numViews, baseViewIndex, multiviewLayout,
1762 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001763
Corentin Walleze7557742017-06-01 13:09:57 -04001764 // TODO(jmadill): ASSERT instead of checking the attachment exists in
1765 // formsRenderingFeedbackLoopWith
Jamie Madilla02315b2017-02-23 14:14:47 -05001766 bool enabled = (type != GL_NONE && getDrawBufferState(colorIndex) != GL_NONE);
1767 mState.mEnabledDrawBuffers.set(colorIndex, enabled);
Brandon Jones76746f92017-11-22 11:44:41 -08001768 mState.mDrawBufferTypeMask.setIndex(getDrawbufferWriteType(colorIndex), colorIndex);
Jamie Madill2d06b732015-04-20 12:53:28 -04001769 }
Jamie Madilla02315b2017-02-23 14:14:47 -05001770 break;
Geoff Langab75a052014-10-15 12:56:37 -04001771 }
1772}
1773
Jamie Madill4928b7c2017-06-20 12:57:39 -04001774void Framebuffer::updateAttachment(const Context *context,
1775 FramebufferAttachment *attachment,
Jamie Madillb8126692017-04-05 11:22:17 -04001776 size_t dirtyBit,
Jamie Madilld4442552018-02-27 22:03:47 -05001777 angle::ObserverBinding *onDirtyBinding,
Jamie Madillb8126692017-04-05 11:22:17 -04001778 GLenum type,
1779 GLenum binding,
1780 const ImageIndex &textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001781 FramebufferAttachmentObject *resource,
1782 GLsizei numViews,
1783 GLuint baseViewIndex,
1784 GLenum multiviewLayout,
1785 const GLint *viewportOffsets)
Jamie Madillb8126692017-04-05 11:22:17 -04001786{
Martin Radev5dae57b2017-07-14 16:15:55 +03001787 attachment->attach(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
1788 multiviewLayout, viewportOffsets);
Jamie Madillb8126692017-04-05 11:22:17 -04001789 mDirtyBits.set(dirtyBit);
Jamie Madill05b35b22017-10-03 09:01:44 -04001790 mState.mResourceNeedsInit.set(dirtyBit, attachment->initState() == InitState::MayNeedInit);
Jamie Madill66f0d2c2018-11-30 15:25:36 -05001791 onDirtyBinding->bind(resource);
Jamie Madille98b1b52018-03-08 09:47:23 -05001792
Jamie Madillb983a4b2018-08-01 11:34:51 -04001793 invalidateCompletenessCache(context);
Jamie Madillb8126692017-04-05 11:22:17 -04001794}
1795
Jamie Madilla02315b2017-02-23 14:14:47 -05001796void Framebuffer::resetAttachment(const Context *context, GLenum binding)
Jamie Madill2d06b732015-04-20 12:53:28 -04001797{
Jamie Madillcc129372018-04-12 09:13:18 -04001798 setAttachment(context, GL_NONE, binding, ImageIndex(), nullptr);
Jamie Madill2d06b732015-04-20 12:53:28 -04001799}
1800
Jamie Madill6f755b22018-10-09 12:48:54 -04001801angle::Result Framebuffer::syncState(const Context *context)
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001802{
1803 if (mDirtyBits.any())
1804 {
Jamie Madill888081d2018-02-27 00:24:46 -05001805 mDirtyBitsGuard = mDirtyBits;
Jamie Madill19fa1c62018-03-08 09:47:21 -05001806 ANGLE_TRY(mImpl->syncState(context, mDirtyBits));
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001807 mDirtyBits.reset();
Jamie Madill888081d2018-02-27 00:24:46 -05001808 mDirtyBitsGuard.reset();
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001809 }
Jamie Madill6f755b22018-10-09 12:48:54 -04001810 return angle::Result::Continue();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001811}
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001812
Jamie Madilld4442552018-02-27 22:03:47 -05001813void Framebuffer::onSubjectStateChange(const Context *context,
1814 angle::SubjectIndex index,
1815 angle::SubjectMessage message)
Jamie Madill51f40ec2016-06-15 14:06:00 -04001816{
Jamie Madillf668a4b2018-09-23 17:01:20 -04001817 if (message != angle::SubjectMessage::STORAGE_CHANGED)
1818 {
1819 // This can be triggered by the GL back-end TextureGL class.
1820 ASSERT(message == angle::SubjectMessage::DEPENDENT_DIRTY_BITS);
1821 return;
1822 }
Jamie Madill55e57f92018-09-18 11:32:43 -04001823
1824 ASSERT(!mDirtyBitsGuard.valid() || mDirtyBitsGuard.value().test(index));
1825 mDirtyBits.set(index);
1826 onStateChange(context, angle::SubjectMessage::STORAGE_CHANGED);
Jamie Madill888081d2018-02-27 00:24:46 -05001827
Jamie Madillb983a4b2018-08-01 11:34:51 -04001828 invalidateCompletenessCache(context);
Jamie Madill05b35b22017-10-03 09:01:44 -04001829
Jamie Madilld4442552018-02-27 22:03:47 -05001830 FramebufferAttachment *attachment = getAttachmentFromSubjectIndex(index);
1831
Jamie Madill05b35b22017-10-03 09:01:44 -04001832 // Mark the appropriate init flag.
Jamie Madilld4442552018-02-27 22:03:47 -05001833 mState.mResourceNeedsInit.set(index, attachment->initState() == InitState::MayNeedInit);
1834}
1835
1836FramebufferAttachment *Framebuffer::getAttachmentFromSubjectIndex(angle::SubjectIndex index)
1837{
1838 switch (index)
1839 {
1840 case DIRTY_BIT_DEPTH_ATTACHMENT:
1841 return &mState.mDepthAttachment;
1842 case DIRTY_BIT_STENCIL_ATTACHMENT:
1843 return &mState.mStencilAttachment;
1844 default:
1845 size_t colorIndex = (index - DIRTY_BIT_COLOR_ATTACHMENT_0);
1846 ASSERT(colorIndex < mState.mColorAttachments.size());
1847 return &mState.mColorAttachments[colorIndex];
1848 }
Jamie Madill51f40ec2016-06-15 14:06:00 -04001849}
1850
Jamie Madilla4595b82017-01-11 17:36:34 -05001851bool Framebuffer::formsRenderingFeedbackLoopWith(const State &state) const
1852{
Jamie Madill785e8a02018-10-04 17:42:00 -04001853 const Program *program = state.getProgram();
Jamie Madilla4595b82017-01-11 17:36:34 -05001854
1855 // TODO(jmadill): Default framebuffer feedback loops.
Jamie Madill2274b652018-05-31 10:56:08 -04001856 if (mState.mId == 0)
Jamie Madilla4595b82017-01-11 17:36:34 -05001857 {
1858 return false;
1859 }
1860
1861 // The bitset will skip inactive draw buffers.
Jamie Madill6de51852017-04-12 09:53:01 -04001862 for (size_t drawIndex : mState.mEnabledDrawBuffers)
Jamie Madilla4595b82017-01-11 17:36:34 -05001863 {
Jamie Madill5aca1932017-07-21 12:22:01 -04001864 const FramebufferAttachment &attachment = mState.mColorAttachments[drawIndex];
1865 ASSERT(attachment.isAttached());
1866 if (attachment.type() == GL_TEXTURE)
Jamie Madilla4595b82017-01-11 17:36:34 -05001867 {
1868 // Validate the feedback loop.
Jamie Madill5aca1932017-07-21 12:22:01 -04001869 if (program->samplesFromTexture(state, attachment.id()))
Jamie Madilla4595b82017-01-11 17:36:34 -05001870 {
1871 return true;
1872 }
1873 }
1874 }
1875
Jamie Madill38fe6842018-09-19 07:20:00 -04001876 // Validate depth-stencil feedback loop. This is independent of Depth/Stencil state.
Jamie Madill1d37bc52017-02-02 19:59:58 -05001877 const FramebufferAttachment *depth = getDepthbuffer();
Jamie Madill38fe6842018-09-19 07:20:00 -04001878 if (depth && depth->type() == GL_TEXTURE)
Jamie Madill1d37bc52017-02-02 19:59:58 -05001879 {
1880 if (program->samplesFromTexture(state, depth->id()))
1881 {
1882 return true;
1883 }
1884 }
1885
Jamie Madill1d37bc52017-02-02 19:59:58 -05001886 const FramebufferAttachment *stencil = getStencilbuffer();
Jamie Madill38fe6842018-09-19 07:20:00 -04001887 if (stencil && stencil->type() == GL_TEXTURE)
Jamie Madill1d37bc52017-02-02 19:59:58 -05001888 {
Jamie Madill38fe6842018-09-19 07:20:00 -04001889 // Skip the feedback loop check if depth/stencil point to the same resource.
1890 if (!depth || *stencil != *depth)
Jamie Madill1d37bc52017-02-02 19:59:58 -05001891 {
Jamie Madill38fe6842018-09-19 07:20:00 -04001892 if (program->samplesFromTexture(state, stencil->id()))
Jamie Madill1d37bc52017-02-02 19:59:58 -05001893 {
Jamie Madill38fe6842018-09-19 07:20:00 -04001894 return true;
Jamie Madill1d37bc52017-02-02 19:59:58 -05001895 }
1896 }
1897 }
1898
Jamie Madilla4595b82017-01-11 17:36:34 -05001899 return false;
1900}
1901
Jamie Madillfd3dd432017-02-02 19:59:59 -05001902bool Framebuffer::formsCopyingFeedbackLoopWith(GLuint copyTextureID,
1903 GLint copyTextureLevel,
1904 GLint copyTextureLayer) const
Jamie Madillf695a3a2017-01-11 17:36:35 -05001905{
Jamie Madill2274b652018-05-31 10:56:08 -04001906 if (mState.mId == 0)
Jamie Madillf695a3a2017-01-11 17:36:35 -05001907 {
1908 // It seems impossible to form a texture copying feedback loop with the default FBO.
1909 return false;
1910 }
1911
1912 const FramebufferAttachment *readAttachment = getReadColorbuffer();
1913 ASSERT(readAttachment);
1914
1915 if (readAttachment->isTextureWithId(copyTextureID))
1916 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05001917 const auto &imageIndex = readAttachment->getTextureImageIndex();
Jamie Madillcc129372018-04-12 09:13:18 -04001918 if (imageIndex.getLevelIndex() == copyTextureLevel)
Jamie Madillf695a3a2017-01-11 17:36:35 -05001919 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05001920 // Check 3D/Array texture layers.
Jamie Madillcc129372018-04-12 09:13:18 -04001921 return !imageIndex.hasLayer() || copyTextureLayer == ImageIndex::kEntireLevel ||
1922 imageIndex.getLayerIndex() == copyTextureLayer;
Jamie Madillf695a3a2017-01-11 17:36:35 -05001923 }
1924 }
1925 return false;
1926}
1927
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001928GLint Framebuffer::getDefaultWidth() const
1929{
1930 return mState.getDefaultWidth();
1931}
1932
1933GLint Framebuffer::getDefaultHeight() const
1934{
1935 return mState.getDefaultHeight();
1936}
1937
1938GLint Framebuffer::getDefaultSamples() const
1939{
1940 return mState.getDefaultSamples();
1941}
1942
Geoff Lang92019432017-11-20 13:09:34 -05001943bool Framebuffer::getDefaultFixedSampleLocations() const
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001944{
1945 return mState.getDefaultFixedSampleLocations();
1946}
1947
Jiawei Shaob1e91382018-05-17 14:33:55 +08001948GLint Framebuffer::getDefaultLayers() const
1949{
1950 return mState.getDefaultLayers();
1951}
1952
Jamie Madillb983a4b2018-08-01 11:34:51 -04001953void Framebuffer::setDefaultWidth(const Context *context, GLint defaultWidth)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001954{
1955 mState.mDefaultWidth = defaultWidth;
1956 mDirtyBits.set(DIRTY_BIT_DEFAULT_WIDTH);
Jamie Madillb983a4b2018-08-01 11:34:51 -04001957 invalidateCompletenessCache(context);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001958}
1959
Jamie Madillb983a4b2018-08-01 11:34:51 -04001960void Framebuffer::setDefaultHeight(const Context *context, GLint defaultHeight)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001961{
1962 mState.mDefaultHeight = defaultHeight;
1963 mDirtyBits.set(DIRTY_BIT_DEFAULT_HEIGHT);
Jamie Madillb983a4b2018-08-01 11:34:51 -04001964 invalidateCompletenessCache(context);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001965}
1966
Jamie Madillb983a4b2018-08-01 11:34:51 -04001967void Framebuffer::setDefaultSamples(const Context *context, GLint defaultSamples)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001968{
1969 mState.mDefaultSamples = defaultSamples;
1970 mDirtyBits.set(DIRTY_BIT_DEFAULT_SAMPLES);
Jamie Madillb983a4b2018-08-01 11:34:51 -04001971 invalidateCompletenessCache(context);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001972}
1973
Jamie Madillb983a4b2018-08-01 11:34:51 -04001974void Framebuffer::setDefaultFixedSampleLocations(const Context *context,
1975 bool defaultFixedSampleLocations)
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001976{
1977 mState.mDefaultFixedSampleLocations = defaultFixedSampleLocations;
1978 mDirtyBits.set(DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS);
Jamie Madillb983a4b2018-08-01 11:34:51 -04001979 invalidateCompletenessCache(context);
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001980}
1981
Jiawei Shaob1e91382018-05-17 14:33:55 +08001982void Framebuffer::setDefaultLayers(GLint defaultLayers)
1983{
1984 mState.mDefaultLayers = defaultLayers;
1985 mDirtyBits.set(DIRTY_BIT_DEFAULT_LAYERS);
1986}
1987
Martin Radev14a26ae2017-07-24 15:56:29 +03001988GLsizei Framebuffer::getNumViews() const
1989{
Martin Radev5c00d0d2017-08-07 10:06:59 +03001990 return mState.getNumViews();
Martin Radev14a26ae2017-07-24 15:56:29 +03001991}
1992
Martin Radev4e619f52017-08-09 11:50:06 +03001993GLint Framebuffer::getBaseViewIndex() const
1994{
1995 return mState.getBaseViewIndex();
1996}
1997
Martin Radev878c8b12017-07-28 09:51:04 +03001998const std::vector<Offset> *Framebuffer::getViewportOffsets() const
1999{
Martin Radev5c00d0d2017-08-07 10:06:59 +03002000 return mState.getViewportOffsets();
Martin Radev878c8b12017-07-28 09:51:04 +03002001}
2002
2003GLenum Framebuffer::getMultiviewLayout() const
2004{
Martin Radev5c00d0d2017-08-07 10:06:59 +03002005 return mState.getMultiviewLayout();
Martin Radev878c8b12017-07-28 09:51:04 +03002006}
2007
Olli Etuaho8acb1b62018-07-30 16:20:54 +03002008bool Framebuffer::readDisallowedByMultiview() const
2009{
2010 return (mState.getMultiviewLayout() != GL_NONE && mState.getNumViews() > 1) ||
2011 mState.getMultiviewLayout() == GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE;
2012}
2013
Jamie Madill64b7c4f2018-10-19 11:38:04 -04002014angle::Result Framebuffer::ensureClearAttachmentsInitialized(const Context *context,
2015 GLbitfield mask)
Geoff Langd4fff502017-09-22 11:28:28 -04002016{
2017 const auto &glState = context->getGLState();
2018 if (!context->isRobustResourceInitEnabled() || glState.isRasterizerDiscardEnabled())
2019 {
Jamie Madill64b7c4f2018-10-19 11:38:04 -04002020 return angle::Result::Continue();
Geoff Langd4fff502017-09-22 11:28:28 -04002021 }
2022
Geoff Langa36483f2018-03-09 16:11:21 -05002023 const BlendState &blend = glState.getBlendState();
2024 const DepthStencilState &depthStencil = glState.getDepthStencilState();
Geoff Langd4fff502017-09-22 11:28:28 -04002025
2026 bool color = (mask & GL_COLOR_BUFFER_BIT) != 0 && !IsColorMaskedOut(blend);
2027 bool depth = (mask & GL_DEPTH_BUFFER_BIT) != 0 && !IsDepthMaskedOut(depthStencil);
2028 bool stencil = (mask & GL_STENCIL_BUFFER_BIT) != 0 && !IsStencilMaskedOut(depthStencil);
2029
2030 if (!color && !depth && !stencil)
2031 {
Jamie Madill64b7c4f2018-10-19 11:38:04 -04002032 return angle::Result::Continue();
Geoff Langd4fff502017-09-22 11:28:28 -04002033 }
2034
2035 if (partialClearNeedsInit(context, color, depth, stencil))
2036 {
2037 ANGLE_TRY(ensureDrawAttachmentsInitialized(context));
2038 }
2039
2040 // If the impl encounters an error during a a full (non-partial) clear, the attachments will
2041 // still be marked initialized. This simplifies design, allowing this method to be called before
2042 // the clear.
2043 markDrawAttachmentsInitialized(color, depth, stencil);
2044
Jamie Madill64b7c4f2018-10-19 11:38:04 -04002045 return angle::Result::Continue();
Geoff Langd4fff502017-09-22 11:28:28 -04002046}
2047
Jamie Madill64b7c4f2018-10-19 11:38:04 -04002048angle::Result Framebuffer::ensureClearBufferAttachmentsInitialized(const Context *context,
2049 GLenum buffer,
2050 GLint drawbuffer)
Geoff Langd4fff502017-09-22 11:28:28 -04002051{
2052 if (!context->isRobustResourceInitEnabled() ||
2053 context->getGLState().isRasterizerDiscardEnabled() ||
2054 IsClearBufferMaskedOut(context, buffer))
2055 {
Jamie Madill64b7c4f2018-10-19 11:38:04 -04002056 return angle::Result::Continue();
Geoff Langd4fff502017-09-22 11:28:28 -04002057 }
2058
2059 if (partialBufferClearNeedsInit(context, buffer))
2060 {
2061 ANGLE_TRY(ensureBufferInitialized(context, buffer, drawbuffer));
2062 }
2063
2064 // If the impl encounters an error during a a full (non-partial) clear, the attachments will
2065 // still be marked initialized. This simplifies design, allowing this method to be called before
2066 // the clear.
2067 markBufferInitialized(buffer, drawbuffer);
2068
Jamie Madill64b7c4f2018-10-19 11:38:04 -04002069 return angle::Result::Continue();
Geoff Langd4fff502017-09-22 11:28:28 -04002070}
2071
Jamie Madill6f755b22018-10-09 12:48:54 -04002072angle::Result Framebuffer::ensureDrawAttachmentsInitialized(const Context *context)
Jamie Madill05b35b22017-10-03 09:01:44 -04002073{
2074 if (!context->isRobustResourceInitEnabled())
2075 {
Jamie Madill6f755b22018-10-09 12:48:54 -04002076 return angle::Result::Continue();
Jamie Madill05b35b22017-10-03 09:01:44 -04002077 }
2078
2079 // Note: we don't actually filter by the draw attachment enum. Just init everything.
2080 for (size_t bit : mState.mResourceNeedsInit)
2081 {
2082 switch (bit)
2083 {
2084 case DIRTY_BIT_DEPTH_ATTACHMENT:
2085 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2086 break;
2087 case DIRTY_BIT_STENCIL_ATTACHMENT:
2088 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2089 break;
2090 default:
2091 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[bit]));
2092 break;
2093 }
2094 }
2095
2096 mState.mResourceNeedsInit.reset();
Jamie Madill6f755b22018-10-09 12:48:54 -04002097 return angle::Result::Continue();
Jamie Madill05b35b22017-10-03 09:01:44 -04002098}
2099
Jamie Madill64b7c4f2018-10-19 11:38:04 -04002100angle::Result Framebuffer::ensureReadAttachmentInitialized(const Context *context,
2101 GLbitfield blitMask)
Jamie Madill05b35b22017-10-03 09:01:44 -04002102{
2103 if (!context->isRobustResourceInitEnabled() || mState.mResourceNeedsInit.none())
2104 {
Jamie Madill64b7c4f2018-10-19 11:38:04 -04002105 return angle::Result::Continue();
Jamie Madill05b35b22017-10-03 09:01:44 -04002106 }
2107
2108 if ((blitMask & GL_COLOR_BUFFER_BIT) != 0 && mState.mReadBufferState != GL_NONE)
2109 {
2110 size_t readIndex = mState.getReadIndex();
2111 if (mState.mResourceNeedsInit[readIndex])
2112 {
2113 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[readIndex]));
2114 mState.mResourceNeedsInit.reset(readIndex);
2115 }
2116 }
2117
2118 if ((blitMask & GL_DEPTH_BUFFER_BIT) != 0 && hasDepth())
2119 {
2120 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2121 {
2122 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2123 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2124 }
2125 }
2126
2127 if ((blitMask & GL_STENCIL_BUFFER_BIT) != 0 && hasStencil())
2128 {
2129 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2130 {
2131 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2132 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2133 }
2134 }
2135
Jamie Madill64b7c4f2018-10-19 11:38:04 -04002136 return angle::Result::Continue();
Jamie Madill05b35b22017-10-03 09:01:44 -04002137}
2138
2139void Framebuffer::markDrawAttachmentsInitialized(bool color, bool depth, bool stencil)
2140{
2141 // Mark attachments as initialized.
2142 if (color)
2143 {
2144 for (auto colorIndex : mState.mEnabledDrawBuffers)
2145 {
2146 auto &colorAttachment = mState.mColorAttachments[colorIndex];
2147 ASSERT(colorAttachment.isAttached());
2148 colorAttachment.setInitState(InitState::Initialized);
2149 mState.mResourceNeedsInit.reset(colorIndex);
2150 }
2151 }
2152
2153 if (depth && mState.mDepthAttachment.isAttached())
2154 {
2155 mState.mDepthAttachment.setInitState(InitState::Initialized);
2156 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2157 }
2158
2159 if (stencil && mState.mStencilAttachment.isAttached())
2160 {
2161 mState.mStencilAttachment.setInitState(InitState::Initialized);
2162 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2163 }
2164}
2165
2166void Framebuffer::markBufferInitialized(GLenum bufferType, GLint bufferIndex)
2167{
2168 switch (bufferType)
2169 {
2170 case GL_COLOR:
2171 {
2172 ASSERT(bufferIndex < static_cast<GLint>(mState.mColorAttachments.size()));
2173 if (mState.mColorAttachments[bufferIndex].isAttached())
2174 {
2175 mState.mColorAttachments[bufferIndex].setInitState(InitState::Initialized);
2176 mState.mResourceNeedsInit.reset(bufferIndex);
2177 }
2178 break;
2179 }
2180 case GL_DEPTH:
2181 {
2182 if (mState.mDepthAttachment.isAttached())
2183 {
2184 mState.mDepthAttachment.setInitState(InitState::Initialized);
2185 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2186 }
2187 break;
2188 }
2189 case GL_STENCIL:
2190 {
2191 if (mState.mStencilAttachment.isAttached())
2192 {
2193 mState.mStencilAttachment.setInitState(InitState::Initialized);
2194 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2195 }
2196 break;
2197 }
2198 case GL_DEPTH_STENCIL:
2199 {
2200 if (mState.mDepthAttachment.isAttached())
2201 {
2202 mState.mDepthAttachment.setInitState(InitState::Initialized);
2203 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2204 }
2205 if (mState.mStencilAttachment.isAttached())
2206 {
2207 mState.mStencilAttachment.setInitState(InitState::Initialized);
2208 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2209 }
2210 break;
2211 }
2212 default:
2213 UNREACHABLE();
2214 break;
2215 }
2216}
2217
2218Box Framebuffer::getDimensions() const
2219{
2220 return mState.getDimensions();
2221}
2222
Jamie Madill64b7c4f2018-10-19 11:38:04 -04002223angle::Result Framebuffer::ensureBufferInitialized(const Context *context,
2224 GLenum bufferType,
2225 GLint bufferIndex)
Jamie Madill05b35b22017-10-03 09:01:44 -04002226{
2227 ASSERT(context->isRobustResourceInitEnabled());
2228
2229 if (mState.mResourceNeedsInit.none())
2230 {
Jamie Madill64b7c4f2018-10-19 11:38:04 -04002231 return angle::Result::Continue();
Jamie Madill05b35b22017-10-03 09:01:44 -04002232 }
2233
2234 switch (bufferType)
2235 {
2236 case GL_COLOR:
2237 {
2238 ASSERT(bufferIndex < static_cast<GLint>(mState.mColorAttachments.size()));
2239 if (mState.mResourceNeedsInit[bufferIndex])
2240 {
2241 ANGLE_TRY(InitAttachment(context, &mState.mColorAttachments[bufferIndex]));
2242 mState.mResourceNeedsInit.reset(bufferIndex);
2243 }
2244 break;
2245 }
2246 case GL_DEPTH:
2247 {
2248 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2249 {
2250 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2251 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2252 }
2253 break;
2254 }
2255 case GL_STENCIL:
2256 {
2257 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2258 {
2259 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2260 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2261 }
2262 break;
2263 }
2264 case GL_DEPTH_STENCIL:
2265 {
2266 if (mState.mResourceNeedsInit[DIRTY_BIT_DEPTH_ATTACHMENT])
2267 {
2268 ANGLE_TRY(InitAttachment(context, &mState.mDepthAttachment));
2269 mState.mResourceNeedsInit.reset(DIRTY_BIT_DEPTH_ATTACHMENT);
2270 }
2271 if (mState.mResourceNeedsInit[DIRTY_BIT_STENCIL_ATTACHMENT])
2272 {
2273 ANGLE_TRY(InitAttachment(context, &mState.mStencilAttachment));
2274 mState.mResourceNeedsInit.reset(DIRTY_BIT_STENCIL_ATTACHMENT);
2275 }
2276 break;
2277 }
2278 default:
2279 UNREACHABLE();
2280 break;
2281 }
2282
Jamie Madill64b7c4f2018-10-19 11:38:04 -04002283 return angle::Result::Continue();
Jamie Madill05b35b22017-10-03 09:01:44 -04002284}
2285
2286bool Framebuffer::partialBufferClearNeedsInit(const Context *context, GLenum bufferType)
2287{
2288 if (!context->isRobustResourceInitEnabled() || mState.mResourceNeedsInit.none())
2289 {
2290 return false;
2291 }
2292
2293 switch (bufferType)
2294 {
2295 case GL_COLOR:
2296 return partialClearNeedsInit(context, true, false, false);
2297 case GL_DEPTH:
2298 return partialClearNeedsInit(context, false, true, false);
2299 case GL_STENCIL:
2300 return partialClearNeedsInit(context, false, false, true);
2301 case GL_DEPTH_STENCIL:
2302 return partialClearNeedsInit(context, false, true, true);
2303 default:
2304 UNREACHABLE();
2305 return false;
2306 }
2307}
Jamie Madill60ec6ea2016-01-22 15:27:19 -05002308} // namespace gl