blob: 3892f1fddb4f6cf8d1f157484c9cee17f9bfe7b1 [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"
22#include "libANGLE/formatutils.h"
Jamie Madill8415b5f2016-04-26 13:41:39 -040023#include "libANGLE/renderer/ContextImpl.h"
Geoff Langb5d8f232014-12-04 15:43:01 -050024#include "libANGLE/renderer/FramebufferImpl.h"
Jamie Madill7aea7e02016-05-10 10:39:45 -040025#include "libANGLE/renderer/GLImplFactory.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050026#include "libANGLE/renderer/RenderbufferImpl.h"
Corentin Wallez37c39792015-08-20 14:19:46 -040027#include "libANGLE/renderer/SurfaceImpl.h"
Geoff Lang0b7eef72014-06-12 14:10:47 -040028
Jamie Madill362876b2016-06-16 14:46:59 -040029using namespace angle;
30
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000031namespace gl
32{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000033
Jamie Madilld1405e52015-03-05 15:41:39 -050034namespace
35{
Jamie Madill362876b2016-06-16 14:46:59 -040036
Jamie Madill1e5499d2017-04-05 11:22:16 -040037void BindResourceChannel(OnAttachmentDirtyBinding *binding, FramebufferAttachmentObject *resource)
Jamie Madilld1405e52015-03-05 15:41:39 -050038{
Jamie Madill362876b2016-06-16 14:46:59 -040039 binding->bind(resource ? resource->getDirtyChannel() : nullptr);
Jamie Madilld1405e52015-03-05 15:41:39 -050040}
Jamie Madill362876b2016-06-16 14:46:59 -040041
Martin Radev9bc9a322017-07-21 14:28:17 +030042bool CheckMultiviewStateMatchesForCompleteness(const FramebufferAttachment *firstAttachment,
43 const FramebufferAttachment *secondAttachment)
44{
45 ASSERT(firstAttachment && secondAttachment);
46 ASSERT(firstAttachment->isAttached() && secondAttachment->isAttached());
47
48 if (firstAttachment->getNumViews() != secondAttachment->getNumViews())
49 {
50 return false;
51 }
52 if (firstAttachment->getBaseViewIndex() != secondAttachment->getBaseViewIndex())
53 {
54 return false;
55 }
56 if (firstAttachment->getMultiviewLayout() != secondAttachment->getMultiviewLayout())
57 {
58 return false;
59 }
60 if (firstAttachment->getMultiviewViewportOffsets() !=
61 secondAttachment->getMultiviewViewportOffsets())
62 {
63 return false;
64 }
65 return true;
66}
67
Geoff Lang9f10b772017-05-16 15:51:03 -040068bool CheckAttachmentCompleteness(const Context *context, const FramebufferAttachment &attachment)
69{
70 ASSERT(attachment.isAttached());
71
72 const Extents &size = attachment.getSize();
73 if (size.width == 0 || size.height == 0)
74 {
75 return false;
76 }
77
78 const InternalFormat &format = *attachment.getFormat().info;
79 if (!format.renderSupport(context->getClientVersion(), context->getExtensions()))
80 {
81 return false;
82 }
83
84 if (attachment.type() == GL_TEXTURE)
85 {
86 if (attachment.layer() >= size.depth)
87 {
88 return false;
89 }
90
91 // ES3 specifies that cube map texture attachments must be cube complete.
92 // This language is missing from the ES2 spec, but we enforce it here because some
93 // desktop OpenGL drivers also enforce this validation.
94 // TODO(jmadill): Check if OpenGL ES2 drivers enforce cube completeness.
95 const Texture *texture = attachment.getTexture();
96 ASSERT(texture);
97 if (texture->getTarget() == GL_TEXTURE_CUBE_MAP &&
98 !texture->getTextureState().isCubeComplete())
99 {
100 return false;
101 }
Geoff Lang857c09d2017-05-16 15:55:04 -0400102
103 if (!texture->getImmutableFormat())
104 {
105 GLuint attachmentMipLevel = static_cast<GLuint>(attachment.mipLevel());
106
107 // From the ES 3.0 spec, pg 213:
108 // If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is TEXTURE and the value of
109 // FRAMEBUFFER_ATTACHMENT_OBJECT_NAME does not name an immutable-format texture,
110 // then the value of FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL must be in the
111 // range[levelbase, q], where levelbase is the value of TEXTURE_BASE_LEVEL and q is
112 // the effective maximum texture level defined in the Mipmapping discussion of
113 // section 3.8.10.4.
114 if (attachmentMipLevel < texture->getBaseLevel() ||
115 attachmentMipLevel > texture->getMipmapMaxLevel())
116 {
117 return false;
118 }
119
120 // Form the ES 3.0 spec, pg 213/214:
121 // If the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE is TEXTURE and the value of
122 // FRAMEBUFFER_ATTACHMENT_OBJECT_NAME does not name an immutable-format texture and
123 // the value of FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL is not levelbase, then the
124 // texture must be mipmap complete, and if FRAMEBUFFER_ATTACHMENT_OBJECT_NAME names
125 // a cubemap texture, the texture must also be cube complete.
126 if (attachmentMipLevel != texture->getBaseLevel() && !texture->isMipmapComplete())
127 {
128 return false;
129 }
130 }
Geoff Lang9f10b772017-05-16 15:51:03 -0400131 }
132
133 return true;
134};
135
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400136bool CheckAttachmentSampleCompleteness(const Context *context,
137 const FramebufferAttachment &attachment,
138 bool colorAttachment,
139 Optional<int> *samples,
140 Optional<GLboolean> *fixedSampleLocations)
141{
142 ASSERT(attachment.isAttached());
143
144 if (attachment.type() == GL_TEXTURE)
145 {
146 const Texture *texture = attachment.getTexture();
147 ASSERT(texture);
148
149 const ImageIndex &attachmentImageIndex = attachment.getTextureImageIndex();
150
151 // ES3.1 (section 9.4) requires that the value of TEXTURE_FIXED_SAMPLE_LOCATIONS should be
152 // the same for all attached textures.
153 GLboolean fixedSampleloc = texture->getFixedSampleLocations(attachmentImageIndex.type,
154 attachmentImageIndex.mipIndex);
155 if (fixedSampleLocations->valid() && fixedSampleloc != fixedSampleLocations->value())
156 {
157 return false;
158 }
159 else
160 {
161 *fixedSampleLocations = fixedSampleloc;
162 }
163 }
164
165 if (samples->valid())
166 {
167 if (attachment.getSamples() != samples->value())
168 {
169 if (colorAttachment)
170 {
171 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
172 // all color attachments have the same number of samples for the FBO to be complete.
173 return false;
174 }
175 else
176 {
177 // CHROMIUM_framebuffer_mixed_samples allows a framebuffer to be considered complete
178 // when its depth or stencil samples are a multiple of the number of color samples.
179 if (!context->getExtensions().framebufferMixedSamples)
180 {
181 return false;
182 }
183
184 if ((attachment.getSamples() % std::max(samples->value(), 1)) != 0)
185 {
186 return false;
187 }
188 }
189 }
190 }
191 else
192 {
193 *samples = attachment.getSamples();
194 }
195
196 return true;
197}
198
Jamie Madill362876b2016-06-16 14:46:59 -0400199} // anonymous namespace
Jamie Madilld1405e52015-03-05 15:41:39 -0500200
Jamie Madill6f60d052017-02-22 15:20:11 -0500201// This constructor is only used for default framebuffers.
Jamie Madill48ef11b2016-04-27 15:21:52 -0400202FramebufferState::FramebufferState()
Geoff Lang70d0f492015-12-10 17:45:46 -0500203 : mLabel(),
204 mColorAttachments(1),
Corentin Walleze7557742017-06-01 13:09:57 -0400205 mDrawBufferStates(1, GL_BACK),
Jamie Madill6f60d052017-02-22 15:20:11 -0500206 mReadBufferState(GL_BACK),
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800207 mDefaultWidth(0),
208 mDefaultHeight(0),
209 mDefaultSamples(0),
Jamie Madilla02315b2017-02-23 14:14:47 -0500210 mDefaultFixedSampleLocations(GL_FALSE),
211 mWebGLDepthStencilConsistent(true)
Corentin Wallez37c39792015-08-20 14:19:46 -0400212{
Geoff Langd90d3882017-03-21 10:49:54 -0400213 ASSERT(mDrawBufferStates.size() > 0);
Jamie Madilla4595b82017-01-11 17:36:34 -0500214 mEnabledDrawBuffers.set(0);
Corentin Wallez37c39792015-08-20 14:19:46 -0400215}
216
Jamie Madill48ef11b2016-04-27 15:21:52 -0400217FramebufferState::FramebufferState(const Caps &caps)
Geoff Lang70d0f492015-12-10 17:45:46 -0500218 : mLabel(),
219 mColorAttachments(caps.maxColorAttachments),
Jamie Madilld1405e52015-03-05 15:41:39 -0500220 mDrawBufferStates(caps.maxDrawBuffers, GL_NONE),
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800221 mReadBufferState(GL_COLOR_ATTACHMENT0_EXT),
222 mDefaultWidth(0),
223 mDefaultHeight(0),
224 mDefaultSamples(0),
Jamie Madilla02315b2017-02-23 14:14:47 -0500225 mDefaultFixedSampleLocations(GL_FALSE),
226 mWebGLDepthStencilConsistent(true)
Jamie Madilld1405e52015-03-05 15:41:39 -0500227{
Geoff Langa15472a2015-08-11 11:48:03 -0400228 ASSERT(mDrawBufferStates.size() > 0);
Jamie Madilld1405e52015-03-05 15:41:39 -0500229 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
230}
231
Jamie Madill48ef11b2016-04-27 15:21:52 -0400232FramebufferState::~FramebufferState()
Jamie Madilld1405e52015-03-05 15:41:39 -0500233{
Jamie Madilld1405e52015-03-05 15:41:39 -0500234}
235
Jamie Madill48ef11b2016-04-27 15:21:52 -0400236const std::string &FramebufferState::getLabel()
Geoff Lang70d0f492015-12-10 17:45:46 -0500237{
238 return mLabel;
239}
240
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400241const FramebufferAttachment *FramebufferState::getAttachment(GLenum attachment) const
242{
243 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
244 {
245 return getColorAttachment(attachment - GL_COLOR_ATTACHMENT0);
246 }
247
248 switch (attachment)
249 {
250 case GL_COLOR:
251 case GL_BACK:
252 return getColorAttachment(0);
253 case GL_DEPTH:
254 case GL_DEPTH_ATTACHMENT:
255 return getDepthAttachment();
256 case GL_STENCIL:
257 case GL_STENCIL_ATTACHMENT:
258 return getStencilAttachment();
259 case GL_DEPTH_STENCIL:
260 case GL_DEPTH_STENCIL_ATTACHMENT:
261 return getDepthStencilAttachment();
262 default:
263 UNREACHABLE();
264 return nullptr;
265 }
266}
267
Jamie Madill48ef11b2016-04-27 15:21:52 -0400268const FramebufferAttachment *FramebufferState::getReadAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500269{
Antoine Labour2ec65dc2016-11-30 16:28:58 -0800270 if (mReadBufferState == GL_NONE)
271 {
272 return nullptr;
273 }
Jamie Madill231c7f52017-04-26 13:45:37 -0400274 ASSERT(mReadBufferState == GL_BACK ||
275 (mReadBufferState >= GL_COLOR_ATTACHMENT0 && mReadBufferState <= GL_COLOR_ATTACHMENT15));
276 size_t readIndex = (mReadBufferState == GL_BACK
277 ? 0
278 : static_cast<size_t>(mReadBufferState - GL_COLOR_ATTACHMENT0));
Jamie Madill7147f012015-03-05 15:41:40 -0500279 ASSERT(readIndex < mColorAttachments.size());
Jamie Madill2d06b732015-04-20 12:53:28 -0400280 return mColorAttachments[readIndex].isAttached() ? &mColorAttachments[readIndex] : nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500281}
282
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500283const FramebufferAttachment *FramebufferState::getFirstNonNullAttachment() const
284{
285 auto *colorAttachment = getFirstColorAttachment();
286 if (colorAttachment)
287 {
288 return colorAttachment;
289 }
290 return getDepthOrStencilAttachment();
291}
292
Jamie Madill48ef11b2016-04-27 15:21:52 -0400293const FramebufferAttachment *FramebufferState::getFirstColorAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500294{
Jamie Madill2d06b732015-04-20 12:53:28 -0400295 for (const FramebufferAttachment &colorAttachment : mColorAttachments)
Jamie Madill7147f012015-03-05 15:41:40 -0500296 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400297 if (colorAttachment.isAttached())
Jamie Madill7147f012015-03-05 15:41:40 -0500298 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400299 return &colorAttachment;
Jamie Madill7147f012015-03-05 15:41:40 -0500300 }
301 }
302
303 return nullptr;
304}
305
Jamie Madill48ef11b2016-04-27 15:21:52 -0400306const FramebufferAttachment *FramebufferState::getDepthOrStencilAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500307{
Jamie Madill2d06b732015-04-20 12:53:28 -0400308 if (mDepthAttachment.isAttached())
309 {
310 return &mDepthAttachment;
311 }
312 if (mStencilAttachment.isAttached())
313 {
314 return &mStencilAttachment;
315 }
316 return nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500317}
318
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500319const FramebufferAttachment *FramebufferState::getStencilOrDepthStencilAttachment() const
320{
321 if (mStencilAttachment.isAttached())
322 {
323 return &mStencilAttachment;
324 }
325 return getDepthStencilAttachment();
326}
327
Jamie Madill48ef11b2016-04-27 15:21:52 -0400328const FramebufferAttachment *FramebufferState::getColorAttachment(size_t colorAttachment) const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400329{
330 ASSERT(colorAttachment < mColorAttachments.size());
Jamie Madill231c7f52017-04-26 13:45:37 -0400331 return mColorAttachments[colorAttachment].isAttached() ? &mColorAttachments[colorAttachment]
332 : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400333}
334
Jamie Madill48ef11b2016-04-27 15:21:52 -0400335const FramebufferAttachment *FramebufferState::getDepthAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400336{
Jamie Madill2d06b732015-04-20 12:53:28 -0400337 return mDepthAttachment.isAttached() ? &mDepthAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400338}
339
Jamie Madill48ef11b2016-04-27 15:21:52 -0400340const FramebufferAttachment *FramebufferState::getStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400341{
Jamie Madill2d06b732015-04-20 12:53:28 -0400342 return mStencilAttachment.isAttached() ? &mStencilAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400343}
344
Jamie Madill48ef11b2016-04-27 15:21:52 -0400345const FramebufferAttachment *FramebufferState::getDepthStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400346{
347 // A valid depth-stencil attachment has the same resource bound to both the
348 // depth and stencil attachment points.
Jamie Madill2d06b732015-04-20 12:53:28 -0400349 if (mDepthAttachment.isAttached() && mStencilAttachment.isAttached() &&
Jamie Madill44f26482016-11-18 12:49:15 -0500350 mDepthAttachment == mStencilAttachment)
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400351 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400352 return &mDepthAttachment;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400353 }
354
355 return nullptr;
356}
357
Jamie Madill48ef11b2016-04-27 15:21:52 -0400358bool FramebufferState::attachmentsHaveSameDimensions() const
Jamie Madillcc86d642015-11-24 13:00:07 -0500359{
360 Optional<Extents> attachmentSize;
361
Jamie Madill231c7f52017-04-26 13:45:37 -0400362 auto hasMismatchedSize = [&attachmentSize](const FramebufferAttachment &attachment) {
Jamie Madillcc86d642015-11-24 13:00:07 -0500363 if (!attachment.isAttached())
364 {
365 return false;
366 }
367
368 if (!attachmentSize.valid())
369 {
370 attachmentSize = attachment.getSize();
371 return false;
372 }
373
374 return (attachment.getSize() != attachmentSize.value());
375 };
376
377 for (const auto &attachment : mColorAttachments)
378 {
379 if (hasMismatchedSize(attachment))
380 {
381 return false;
382 }
383 }
384
385 if (hasMismatchedSize(mDepthAttachment))
386 {
387 return false;
388 }
389
390 return !hasMismatchedSize(mStencilAttachment);
391}
392
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400393const gl::FramebufferAttachment *FramebufferState::getDrawBuffer(size_t drawBufferIdx) const
394{
395 ASSERT(drawBufferIdx < mDrawBufferStates.size());
396 if (mDrawBufferStates[drawBufferIdx] != GL_NONE)
397 {
398 // ES3 spec: "If the GL is bound to a draw framebuffer object, the ith buffer listed in bufs
399 // must be COLOR_ATTACHMENTi or NONE"
400 ASSERT(mDrawBufferStates[drawBufferIdx] == GL_COLOR_ATTACHMENT0 + drawBufferIdx ||
401 (drawBufferIdx == 0 && mDrawBufferStates[drawBufferIdx] == GL_BACK));
402 return getAttachment(mDrawBufferStates[drawBufferIdx]);
403 }
404 else
405 {
406 return nullptr;
407 }
408}
409
410size_t FramebufferState::getDrawBufferCount() const
411{
412 return mDrawBufferStates.size();
413}
414
Geoff Langb21e20d2016-07-19 15:35:41 -0400415bool FramebufferState::colorAttachmentsAreUniqueImages() const
416{
417 for (size_t firstAttachmentIdx = 0; firstAttachmentIdx < mColorAttachments.size();
418 firstAttachmentIdx++)
419 {
420 const gl::FramebufferAttachment &firstAttachment = mColorAttachments[firstAttachmentIdx];
421 if (!firstAttachment.isAttached())
422 {
423 continue;
424 }
425
426 for (size_t secondAttachmentIdx = firstAttachmentIdx + 1;
427 secondAttachmentIdx < mColorAttachments.size(); secondAttachmentIdx++)
428 {
429 const gl::FramebufferAttachment &secondAttachment =
430 mColorAttachments[secondAttachmentIdx];
431 if (!secondAttachment.isAttached())
432 {
433 continue;
434 }
435
436 if (firstAttachment == secondAttachment)
437 {
438 return false;
439 }
440 }
441 }
442
443 return true;
444}
445
Jamie Madill9c335862017-07-18 11:51:38 -0400446bool FramebufferState::hasDepth() const
447{
448 return (mDepthAttachment.isAttached() && mDepthAttachment.getDepthSize() > 0);
449}
450
451bool FramebufferState::hasStencil() const
452{
453 return (mStencilAttachment.isAttached() && mStencilAttachment.getStencilSize() > 0);
454}
455
Martin Radev5c00d0d2017-08-07 10:06:59 +0300456GLsizei FramebufferState::getNumViews() const
457{
458 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
459 if (attachment == nullptr)
460 {
461 return FramebufferAttachment::kDefaultNumViews;
462 }
463 return attachment->getNumViews();
464}
465
466const std::vector<Offset> *FramebufferState::getViewportOffsets() const
467{
468 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
469 if (attachment == nullptr)
470 {
471 return nullptr;
472 }
473 return &attachment->getMultiviewViewportOffsets();
474}
475
476GLenum FramebufferState::getMultiviewLayout() const
477{
478 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
479 if (attachment == nullptr)
480 {
481 return GL_NONE;
482 }
483 return attachment->getMultiviewLayout();
484}
485
Martin Radev4e619f52017-08-09 11:50:06 +0300486int FramebufferState::getBaseViewIndex() const
487{
488 const FramebufferAttachment *attachment = getFirstNonNullAttachment();
489 if (attachment == nullptr)
490 {
491 return GL_NONE;
492 }
493 return attachment->getBaseViewIndex();
494}
495
Jamie Madill7aea7e02016-05-10 10:39:45 -0400496Framebuffer::Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id)
Jamie Madill362876b2016-06-16 14:46:59 -0400497 : mState(caps),
498 mImpl(factory->createFramebuffer(mState)),
499 mId(id),
500 mCachedStatus(),
501 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
502 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000503{
Corentin Wallez37c39792015-08-20 14:19:46 -0400504 ASSERT(mId != 0);
505 ASSERT(mImpl != nullptr);
Jamie Madill362876b2016-06-16 14:46:59 -0400506 ASSERT(mState.mColorAttachments.size() == static_cast<size_t>(caps.maxColorAttachments));
507
Jamie Madill1e5499d2017-04-05 11:22:16 -0400508 for (uint32_t colorIndex = 0;
509 colorIndex < static_cast<uint32_t>(mState.mColorAttachments.size()); ++colorIndex)
Jamie Madill362876b2016-06-16 14:46:59 -0400510 {
Jamie Madill1e5499d2017-04-05 11:22:16 -0400511 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
Jamie Madill362876b2016-06-16 14:46:59 -0400512 }
Corentin Wallez37c39792015-08-20 14:19:46 -0400513}
514
Jamie Madill4928b7c2017-06-20 12:57:39 -0400515Framebuffer::Framebuffer(const egl::Display *display, egl::Surface *surface)
Jamie Madill362876b2016-06-16 14:46:59 -0400516 : mState(),
Jamie Madill6f60d052017-02-22 15:20:11 -0500517 mImpl(surface->getImplementation()->createDefaultFramebuffer(mState)),
Jamie Madill362876b2016-06-16 14:46:59 -0400518 mId(0),
519 mCachedStatus(GL_FRAMEBUFFER_COMPLETE),
520 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
521 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
Corentin Wallez37c39792015-08-20 14:19:46 -0400522{
Geoff Langda88add2014-12-01 10:22:01 -0500523 ASSERT(mImpl != nullptr);
Jamie Madill1e5499d2017-04-05 11:22:16 -0400524 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
Jamie Madill6f60d052017-02-22 15:20:11 -0500525
Jamie Madill4928b7c2017-06-20 12:57:39 -0400526 const Context *proxyContext = display->getProxyContext();
527
528 setAttachmentImpl(proxyContext, GL_FRAMEBUFFER_DEFAULT, GL_BACK, gl::ImageIndex::MakeInvalid(),
Martin Radev5dae57b2017-07-14 16:15:55 +0300529 surface, FramebufferAttachment::kDefaultNumViews,
530 FramebufferAttachment::kDefaultBaseViewIndex,
531 FramebufferAttachment::kDefaultMultiviewLayout,
532 FramebufferAttachment::kDefaultViewportOffsets);
Jamie Madill6f60d052017-02-22 15:20:11 -0500533
534 if (surface->getConfig()->depthSize > 0)
535 {
Martin Radev5dae57b2017-07-14 16:15:55 +0300536 setAttachmentImpl(
537 proxyContext, GL_FRAMEBUFFER_DEFAULT, GL_DEPTH, gl::ImageIndex::MakeInvalid(), surface,
538 FramebufferAttachment::kDefaultNumViews, FramebufferAttachment::kDefaultBaseViewIndex,
539 FramebufferAttachment::kDefaultMultiviewLayout,
540 FramebufferAttachment::kDefaultViewportOffsets);
Jamie Madill6f60d052017-02-22 15:20:11 -0500541 }
542
543 if (surface->getConfig()->stencilSize > 0)
544 {
Jamie Madill4928b7c2017-06-20 12:57:39 -0400545 setAttachmentImpl(proxyContext, GL_FRAMEBUFFER_DEFAULT, GL_STENCIL,
Martin Radev5dae57b2017-07-14 16:15:55 +0300546 gl::ImageIndex::MakeInvalid(), surface,
547 FramebufferAttachment::kDefaultNumViews,
548 FramebufferAttachment::kDefaultBaseViewIndex,
549 FramebufferAttachment::kDefaultMultiviewLayout,
550 FramebufferAttachment::kDefaultViewportOffsets);
Jamie Madill6f60d052017-02-22 15:20:11 -0500551 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000552}
553
Corentin Wallezccab69d2017-01-27 16:57:15 -0500554Framebuffer::Framebuffer(rx::GLImplFactory *factory)
555 : mState(),
556 mImpl(factory->createFramebuffer(mState)),
557 mId(0),
558 mCachedStatus(GL_FRAMEBUFFER_UNDEFINED_OES),
559 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
560 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
561{
Jamie Madill1e5499d2017-04-05 11:22:16 -0400562 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
Corentin Wallezccab69d2017-01-27 16:57:15 -0500563}
564
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000565Framebuffer::~Framebuffer()
566{
Geoff Langda88add2014-12-01 10:22:01 -0500567 SafeDelete(mImpl);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000568}
569
Jamie Madill4928b7c2017-06-20 12:57:39 -0400570void Framebuffer::onDestroy(const Context *context)
Jamie Madill6c1f6712017-02-14 19:08:04 -0500571{
Jamie Madill4928b7c2017-06-20 12:57:39 -0400572 for (auto &attachment : mState.mColorAttachments)
573 {
574 attachment.detach(context);
575 }
576 mState.mDepthAttachment.detach(context);
577 mState.mStencilAttachment.detach(context);
578 mState.mWebGLDepthAttachment.detach(context);
579 mState.mWebGLStencilAttachment.detach(context);
580 mState.mWebGLDepthStencilAttachment.detach(context);
581
Jamie Madillc564c072017-06-01 12:45:42 -0400582 mImpl->destroy(context);
Jamie Madill6c1f6712017-02-14 19:08:04 -0500583}
584
585void Framebuffer::destroyDefault(const egl::Display *display)
586{
Jamie Madillc564c072017-06-01 12:45:42 -0400587 mImpl->destroyDefault(display);
Jamie Madill6c1f6712017-02-14 19:08:04 -0500588}
589
Geoff Lang70d0f492015-12-10 17:45:46 -0500590void Framebuffer::setLabel(const std::string &label)
591{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400592 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -0500593}
594
595const std::string &Framebuffer::getLabel() const
596{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400597 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -0500598}
599
Jamie Madilla02315b2017-02-23 14:14:47 -0500600void Framebuffer::detachTexture(const Context *context, GLuint textureId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000601{
Jamie Madilla02315b2017-02-23 14:14:47 -0500602 detachResourceById(context, GL_TEXTURE, textureId);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000603}
604
Jamie Madilla02315b2017-02-23 14:14:47 -0500605void Framebuffer::detachRenderbuffer(const Context *context, GLuint renderbufferId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000606{
Jamie Madilla02315b2017-02-23 14:14:47 -0500607 detachResourceById(context, GL_RENDERBUFFER, renderbufferId);
Jamie Madilld1405e52015-03-05 15:41:39 -0500608}
Jamie Madille261b442014-06-25 12:42:21 -0400609
Jamie Madilla02315b2017-02-23 14:14:47 -0500610void Framebuffer::detachResourceById(const Context *context, GLenum resourceType, GLuint resourceId)
Jamie Madilld1405e52015-03-05 15:41:39 -0500611{
Jamie Madill362876b2016-06-16 14:46:59 -0400612 for (size_t colorIndex = 0; colorIndex < mState.mColorAttachments.size(); ++colorIndex)
Jamie Madilld1405e52015-03-05 15:41:39 -0500613 {
Jamie Madill4928b7c2017-06-20 12:57:39 -0400614 detachMatchingAttachment(context, &mState.mColorAttachments[colorIndex], resourceType,
615 resourceId, DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000616 }
617
Jamie Madilla02315b2017-02-23 14:14:47 -0500618 if (context->isWebGL1())
619 {
620 const std::array<FramebufferAttachment *, 3> attachments = {
621 {&mState.mWebGLDepthStencilAttachment, &mState.mWebGLDepthAttachment,
622 &mState.mWebGLStencilAttachment}};
623 for (FramebufferAttachment *attachment : attachments)
624 {
625 if (attachment->isAttached() && attachment->type() == resourceType &&
626 attachment->id() == resourceId)
627 {
628 resetAttachment(context, attachment->getBinding());
629 }
630 }
631 }
632 else
633 {
Jamie Madill4928b7c2017-06-20 12:57:39 -0400634 detachMatchingAttachment(context, &mState.mDepthAttachment, resourceType, resourceId,
Jamie Madilla02315b2017-02-23 14:14:47 -0500635 DIRTY_BIT_DEPTH_ATTACHMENT);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400636 detachMatchingAttachment(context, &mState.mStencilAttachment, resourceType, resourceId,
Jamie Madilla02315b2017-02-23 14:14:47 -0500637 DIRTY_BIT_STENCIL_ATTACHMENT);
638 }
Jamie Madill362876b2016-06-16 14:46:59 -0400639}
640
Jamie Madill4928b7c2017-06-20 12:57:39 -0400641void Framebuffer::detachMatchingAttachment(const Context *context,
642 FramebufferAttachment *attachment,
Jamie Madill362876b2016-06-16 14:46:59 -0400643 GLenum matchType,
644 GLuint matchId,
645 size_t dirtyBit)
646{
647 if (attachment->isAttached() && attachment->type() == matchType && attachment->id() == matchId)
648 {
Jamie Madill4928b7c2017-06-20 12:57:39 -0400649 attachment->detach(context);
Jamie Madill362876b2016-06-16 14:46:59 -0400650 mDirtyBits.set(dirtyBit);
651 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000652}
653
Corentin Wallez37c39792015-08-20 14:19:46 -0400654const FramebufferAttachment *Framebuffer::getColorbuffer(size_t colorAttachment) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000655{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400656 return mState.getColorAttachment(colorAttachment);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000657}
658
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400659const FramebufferAttachment *Framebuffer::getDepthbuffer() const
Geoff Lang646559f2013-08-15 11:08:15 -0400660{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400661 return mState.getDepthAttachment();
Geoff Lang646559f2013-08-15 11:08:15 -0400662}
663
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400664const FramebufferAttachment *Framebuffer::getStencilbuffer() const
665{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400666 return mState.getStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400667}
668
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400669const FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
670{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400671 return mState.getDepthStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400672}
673
674const FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000675{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400676 return mState.getDepthOrStencilAttachment();
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000677}
678
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500679const FramebufferAttachment *Framebuffer::getStencilOrDepthStencilAttachment() const
680{
681 return mState.getStencilOrDepthStencilAttachment();
682}
683
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400684const FramebufferAttachment *Framebuffer::getReadColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000685{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400686 return mState.getReadAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000687}
688
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000689GLenum Framebuffer::getReadColorbufferType() const
690{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400691 const FramebufferAttachment *readAttachment = mState.getReadAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400692 return (readAttachment != nullptr ? readAttachment->type() : GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000693}
694
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400695const FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000696{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400697 return mState.getFirstColorAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000698}
699
Jamie Madill6dd06ea2017-07-19 13:47:55 -0400700const FramebufferAttachment *Framebuffer::getFirstNonNullAttachment() const
701{
702 return mState.getFirstNonNullAttachment();
703}
704
Jamie Madill2d06b732015-04-20 12:53:28 -0400705const FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000706{
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400707 return mState.getAttachment(attachment);
Geoff Lang55ba29c2013-07-11 16:57:53 -0400708}
709
Geoff Langa15472a2015-08-11 11:48:03 -0400710size_t Framebuffer::getDrawbufferStateCount() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000711{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400712 return mState.mDrawBufferStates.size();
Geoff Langa15472a2015-08-11 11:48:03 -0400713}
714
715GLenum Framebuffer::getDrawBufferState(size_t drawBuffer) const
716{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400717 ASSERT(drawBuffer < mState.mDrawBufferStates.size());
718 return mState.mDrawBufferStates[drawBuffer];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000719}
720
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500721const std::vector<GLenum> &Framebuffer::getDrawBufferStates() const
722{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400723 return mState.getDrawBufferStates();
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500724}
725
Geoff Lang164d54e2014-12-01 10:55:33 -0500726void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000727{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400728 auto &drawStates = mState.mDrawBufferStates;
Jamie Madilld1405e52015-03-05 15:41:39 -0500729
730 ASSERT(count <= drawStates.size());
731 std::copy(buffers, buffers + count, drawStates.begin());
732 std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500733 mDirtyBits.set(DIRTY_BIT_DRAW_BUFFERS);
Jamie Madilla4595b82017-01-11 17:36:34 -0500734
735 mState.mEnabledDrawBuffers.reset();
736 for (size_t index = 0; index < count; ++index)
737 {
738 if (drawStates[index] != GL_NONE && mState.mColorAttachments[index].isAttached())
739 {
740 mState.mEnabledDrawBuffers.set(index);
741 }
742 }
Geoff Lang9dd95802014-12-01 11:12:59 -0500743}
744
Geoff Langa15472a2015-08-11 11:48:03 -0400745const FramebufferAttachment *Framebuffer::getDrawBuffer(size_t drawBuffer) const
746{
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400747 return mState.getDrawBuffer(drawBuffer);
Geoff Langa15472a2015-08-11 11:48:03 -0400748}
749
Geoff Lange0cff192017-05-30 13:04:56 -0400750GLenum Framebuffer::getDrawbufferWriteType(size_t drawBuffer) const
751{
752 const FramebufferAttachment *attachment = mState.getDrawBuffer(drawBuffer);
753 if (attachment == nullptr)
754 {
755 return GL_NONE;
756 }
757
758 GLenum componentType = attachment->getFormat().info->componentType;
759 switch (componentType)
760 {
761 case GL_INT:
762 case GL_UNSIGNED_INT:
763 return componentType;
764
765 default:
766 return GL_FLOAT;
767 }
768}
769
Geoff Langa15472a2015-08-11 11:48:03 -0400770bool Framebuffer::hasEnabledDrawBuffer() const
771{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400772 for (size_t drawbufferIdx = 0; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
Geoff Langa15472a2015-08-11 11:48:03 -0400773 {
774 if (getDrawBuffer(drawbufferIdx) != nullptr)
775 {
776 return true;
777 }
778 }
779
780 return false;
781}
782
Geoff Lang9dd95802014-12-01 11:12:59 -0500783GLenum Framebuffer::getReadBufferState() const
784{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400785 return mState.mReadBufferState;
Geoff Lang9dd95802014-12-01 11:12:59 -0500786}
787
788void Framebuffer::setReadBuffer(GLenum buffer)
789{
Jamie Madillb885e572015-02-03 16:16:04 -0500790 ASSERT(buffer == GL_BACK || buffer == GL_NONE ||
791 (buffer >= GL_COLOR_ATTACHMENT0 &&
Jamie Madill48ef11b2016-04-27 15:21:52 -0400792 (buffer - GL_COLOR_ATTACHMENT0) < mState.mColorAttachments.size()));
793 mState.mReadBufferState = buffer;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500794 mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000795}
796
Corentin Wallez37c39792015-08-20 14:19:46 -0400797size_t Framebuffer::getNumColorBuffers() const
798{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400799 return mState.mColorAttachments.size();
Corentin Wallez37c39792015-08-20 14:19:46 -0400800}
801
Jamie Madill0df8fe42015-11-24 16:10:24 -0500802bool Framebuffer::hasDepth() const
803{
Jamie Madill9c335862017-07-18 11:51:38 -0400804 return mState.hasDepth();
Jamie Madill0df8fe42015-11-24 16:10:24 -0500805}
806
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000807bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000808{
Jamie Madill9c335862017-07-18 11:51:38 -0400809 return mState.hasStencil();
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000810}
811
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000812bool Framebuffer::usingExtendedDrawBuffers() const
813{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400814 for (size_t drawbufferIdx = 1; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000815 {
Geoff Langa15472a2015-08-11 11:48:03 -0400816 if (getDrawBuffer(drawbufferIdx) != nullptr)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000817 {
818 return true;
819 }
820 }
821
822 return false;
823}
824
Geoff Lang9aded172017-04-05 11:07:56 -0400825void Framebuffer::invalidateCompletenessCache()
826{
827 if (mId != 0)
828 {
829 mCachedStatus.reset();
830 }
831}
832
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400833GLenum Framebuffer::checkStatus(const Context *context)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000834{
Corentin Wallezccab69d2017-01-27 16:57:15 -0500835 // The default framebuffer is always complete except when it is surfaceless in which
836 // case it is always unsupported. We return early because the default framebuffer may
837 // not be subject to the same rules as application FBOs. ie, it could have 0x0 size.
Geoff Lang528ce3c2014-12-01 10:44:07 -0500838 if (mId == 0)
839 {
Corentin Wallezccab69d2017-01-27 16:57:15 -0500840 ASSERT(mCachedStatus.valid());
841 ASSERT(mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE ||
842 mCachedStatus.value() == GL_FRAMEBUFFER_UNDEFINED_OES);
843 return mCachedStatus.value();
Geoff Lang528ce3c2014-12-01 10:44:07 -0500844 }
845
Jamie Madill362876b2016-06-16 14:46:59 -0400846 if (hasAnyDirtyBit() || !mCachedStatus.valid())
847 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400848 mCachedStatus = checkStatusImpl(context);
Jamie Madill362876b2016-06-16 14:46:59 -0400849 }
850
851 return mCachedStatus.value();
852}
853
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400854GLenum Framebuffer::checkStatusImpl(const Context *context)
Jamie Madill362876b2016-06-16 14:46:59 -0400855{
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400856 const ContextState &state = context->getContextState();
857
Jamie Madill362876b2016-06-16 14:46:59 -0400858 ASSERT(mId != 0);
859
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400860 bool hasAttachments = false;
861 Optional<unsigned int> colorbufferSize;
862 Optional<int> samples;
JiangYizhou461d9a32017-01-04 16:37:26 +0800863 Optional<GLboolean> fixedSampleLocations;
864 bool hasRenderbuffer = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000865
Martin Radev9bc9a322017-07-21 14:28:17 +0300866 const FramebufferAttachment *firstAttachment = getFirstNonNullAttachment();
867
Jamie Madill48ef11b2016-04-27 15:21:52 -0400868 for (const FramebufferAttachment &colorAttachment : mState.mColorAttachments)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000869 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400870 if (colorAttachment.isAttached())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000871 {
Geoff Lang9f10b772017-05-16 15:51:03 -0400872 if (!CheckAttachmentCompleteness(context, colorAttachment))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000873 {
874 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
875 }
daniel@transgaming.com01868132010-08-24 19:21:17 +0000876
Geoff Lang677bb6f2017-04-05 12:40:40 -0400877 const InternalFormat &format = *colorAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -0400878 if (format.depthBits > 0 || format.stencilBits > 0)
879 {
880 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
881 }
882
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400883 if (!CheckAttachmentSampleCompleteness(context, colorAttachment, true, &samples,
884 &fixedSampleLocations))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000885 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400886 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000887 }
888
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400889 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
890 // in GLES 3.0, there is no such restriction
891 if (state.getClientMajorVersion() < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000892 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400893 if (colorbufferSize.valid())
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000894 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400895 if (format.pixelBytes != colorbufferSize.value())
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000896 {
897 return GL_FRAMEBUFFER_UNSUPPORTED;
898 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000899 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400900 else
901 {
902 colorbufferSize = format.pixelBytes;
903 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000904 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400905
Martin Radev9bc9a322017-07-21 14:28:17 +0300906 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &colorAttachment))
907 {
908 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
909 }
910
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400911 hasRenderbuffer = hasRenderbuffer || (colorAttachment.type() == GL_RENDERBUFFER);
912 hasAttachments = true;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000913 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000914 }
915
Jamie Madill48ef11b2016-04-27 15:21:52 -0400916 const FramebufferAttachment &depthAttachment = mState.mDepthAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -0400917 if (depthAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000918 {
Geoff Lang9f10b772017-05-16 15:51:03 -0400919 if (!CheckAttachmentCompleteness(context, depthAttachment))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000920 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000921 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000922 }
923
Geoff Lang677bb6f2017-04-05 12:40:40 -0400924 const InternalFormat &format = *depthAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -0400925 if (format.depthBits == 0)
926 {
927 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000928 }
929
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400930 if (!CheckAttachmentSampleCompleteness(context, depthAttachment, false, &samples,
931 &fixedSampleLocations))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000932 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400933 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000934 }
Sami Väisänena797e062016-05-12 15:23:40 +0300935
Martin Radev9bc9a322017-07-21 14:28:17 +0300936 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &depthAttachment))
937 {
938 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
939 }
940
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400941 hasRenderbuffer = hasRenderbuffer || (depthAttachment.type() == GL_RENDERBUFFER);
942 hasAttachments = true;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000943 }
944
Jamie Madill48ef11b2016-04-27 15:21:52 -0400945 const FramebufferAttachment &stencilAttachment = mState.mStencilAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -0400946 if (stencilAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000947 {
Geoff Lang9f10b772017-05-16 15:51:03 -0400948 if (!CheckAttachmentCompleteness(context, stencilAttachment))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000949 {
950 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
951 }
952
Geoff Lang677bb6f2017-04-05 12:40:40 -0400953 const InternalFormat &format = *stencilAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -0400954 if (format.stencilBits == 0)
955 {
956 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000957 }
958
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400959 if (!CheckAttachmentSampleCompleteness(context, stencilAttachment, false, &samples,
960 &fixedSampleLocations))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000961 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400962 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000963 }
Corentin Wallez086d59a2016-04-29 09:06:49 -0400964
Martin Radev9bc9a322017-07-21 14:28:17 +0300965 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &stencilAttachment))
966 {
967 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
968 }
969
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400970 hasRenderbuffer = hasRenderbuffer || (stencilAttachment.type() == GL_RENDERBUFFER);
971 hasAttachments = true;
972 }
973
974 // Starting from ES 3.0 stencil and depth, if present, should be the same image
975 if (state.getClientMajorVersion() >= 3 && depthAttachment.isAttached() &&
976 stencilAttachment.isAttached() && stencilAttachment != depthAttachment)
977 {
978 return GL_FRAMEBUFFER_UNSUPPORTED;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000979 }
980
Jamie Madilla02315b2017-02-23 14:14:47 -0500981 // Special additional validation for WebGL 1 DEPTH/STENCIL/DEPTH_STENCIL.
982 if (state.isWebGL1())
983 {
984 if (!mState.mWebGLDepthStencilConsistent)
985 {
986 return GL_FRAMEBUFFER_UNSUPPORTED;
987 }
988
989 if (mState.mWebGLDepthStencilAttachment.isAttached())
990 {
991 if (mState.mWebGLDepthStencilAttachment.getDepthSize() == 0 ||
992 mState.mWebGLDepthStencilAttachment.getStencilSize() == 0)
993 {
994 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
995 }
Martin Radev9bc9a322017-07-21 14:28:17 +0300996
997 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment,
998 &mState.mWebGLDepthStencilAttachment))
999 {
1000 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
1001 }
Jamie Madilla02315b2017-02-23 14:14:47 -05001002 }
1003 else if (mState.mStencilAttachment.isAttached() &&
1004 mState.mStencilAttachment.getDepthSize() > 0)
1005 {
1006 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1007 }
1008 else if (mState.mDepthAttachment.isAttached() &&
1009 mState.mDepthAttachment.getStencilSize() > 0)
1010 {
1011 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1012 }
1013 }
1014
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001015 // ES3.1(section 9.4) requires that if no image is attached to the framebuffer, and either the
1016 // value of the framebuffer's FRAMEBUFFER_DEFAULT_WIDTH or FRAMEBUFFER_DEFAULT_HEIGHT parameters
1017 // is zero, the framebuffer is considered incomplete.
JiangYizhou461d9a32017-01-04 16:37:26 +08001018 GLint defaultWidth = mState.getDefaultWidth();
1019 GLint defaultHeight = mState.getDefaultHeight();
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001020 if (!hasAttachments && (defaultWidth == 0 || defaultHeight == 0))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001021 {
1022 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001023 }
1024
Geoff Langa0e0aeb2017-04-12 15:06:29 -04001025 // In ES 2.0 and WebGL, all color attachments must have the same width and height.
Jamie Madillcc86d642015-11-24 13:00:07 -05001026 // In ES 3.0, there is no such restriction.
Geoff Langa0e0aeb2017-04-12 15:06:29 -04001027 if ((state.getClientMajorVersion() < 3 || state.getExtensions().webglCompatibility) &&
1028 !mState.attachmentsHaveSameDimensions())
Jamie Madillcc86d642015-11-24 13:00:07 -05001029 {
1030 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
1031 }
1032
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001033 // ES3.1(section 9.4) requires that if the attached images are a mix of renderbuffers and
1034 // textures, the value of TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all attached textures.
JiangYizhou461d9a32017-01-04 16:37:26 +08001035 if (fixedSampleLocations.valid() && hasRenderbuffer && !fixedSampleLocations.value())
1036 {
1037 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1038 }
1039
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001040 syncState(context);
Jamie Madillcc86d642015-11-24 13:00:07 -05001041 if (!mImpl->checkStatus())
1042 {
1043 return GL_FRAMEBUFFER_UNSUPPORTED;
1044 }
1045
1046 return GL_FRAMEBUFFER_COMPLETE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001047}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001048
Jamie Madill4928b7c2017-06-20 12:57:39 -04001049Error Framebuffer::discard(const Context *context, size_t count, const GLenum *attachments)
Austin Kinross08332632015-05-05 13:35:47 -07001050{
Jamie Madill4928b7c2017-06-20 12:57:39 -04001051 return mImpl->discard(context, count, attachments);
Austin Kinross08332632015-05-05 13:35:47 -07001052}
1053
Jamie Madill4928b7c2017-06-20 12:57:39 -04001054Error Framebuffer::invalidate(const Context *context, size_t count, const GLenum *attachments)
Jamie Madill2d96b9e2014-08-29 15:46:47 -04001055{
Jamie Madill4928b7c2017-06-20 12:57:39 -04001056 return mImpl->invalidate(context, count, attachments);
Jamie Madill2d96b9e2014-08-29 15:46:47 -04001057}
1058
Jamie Madill4928b7c2017-06-20 12:57:39 -04001059Error Framebuffer::invalidateSub(const Context *context,
1060 size_t count,
1061 const GLenum *attachments,
1062 const gl::Rectangle &area)
Jamie Madill400a4412014-08-29 15:46:45 -04001063{
Jamie Madill4928b7c2017-06-20 12:57:39 -04001064 return mImpl->invalidateSub(context, count, attachments, area);
Jamie Madill400a4412014-08-29 15:46:45 -04001065}
1066
Jamie Madillc564c072017-06-01 12:45:42 -04001067Error Framebuffer::clear(const gl::Context *context, GLbitfield mask)
Geoff Langb04dc822014-12-01 12:02:02 -05001068{
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001069 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -05001070 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001071 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001072 }
1073
Jamie Madill8415b5f2016-04-26 13:41:39 -04001074 return mImpl->clear(context, mask);
Geoff Langb04dc822014-12-01 12:02:02 -05001075}
1076
Jamie Madillc564c072017-06-01 12:45:42 -04001077Error Framebuffer::clearBufferfv(const gl::Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001078 GLenum buffer,
1079 GLint drawbuffer,
1080 const GLfloat *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001081{
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001082 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -05001083 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001084 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001085 }
1086
Jamie Madill8415b5f2016-04-26 13:41:39 -04001087 return mImpl->clearBufferfv(context, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -05001088}
1089
Jamie Madillc564c072017-06-01 12:45:42 -04001090Error Framebuffer::clearBufferuiv(const gl::Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001091 GLenum buffer,
1092 GLint drawbuffer,
1093 const GLuint *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001094{
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001095 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -05001096 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001097 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001098 }
1099
Jamie Madill8415b5f2016-04-26 13:41:39 -04001100 return mImpl->clearBufferuiv(context, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -05001101}
1102
Jamie Madillc564c072017-06-01 12:45:42 -04001103Error Framebuffer::clearBufferiv(const gl::Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001104 GLenum buffer,
1105 GLint drawbuffer,
1106 const GLint *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001107{
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001108 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -05001109 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001110 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001111 }
1112
Jamie Madill8415b5f2016-04-26 13:41:39 -04001113 return mImpl->clearBufferiv(context, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -05001114}
1115
Jamie Madillc564c072017-06-01 12:45:42 -04001116Error Framebuffer::clearBufferfi(const gl::Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001117 GLenum buffer,
1118 GLint drawbuffer,
1119 GLfloat depth,
1120 GLint stencil)
Geoff Langb04dc822014-12-01 12:02:02 -05001121{
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001122 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -05001123 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001124 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001125 }
1126
Jamie Madill8415b5f2016-04-26 13:41:39 -04001127 return mImpl->clearBufferfi(context, buffer, drawbuffer, depth, stencil);
Geoff Langb04dc822014-12-01 12:02:02 -05001128}
1129
Jamie Madill4928b7c2017-06-20 12:57:39 -04001130GLenum Framebuffer::getImplementationColorReadFormat(const Context *context) const
Geoff Langbce529e2014-12-01 12:48:41 -05001131{
Jamie Madill4928b7c2017-06-20 12:57:39 -04001132 return mImpl->getImplementationColorReadFormat(context);
Geoff Langbce529e2014-12-01 12:48:41 -05001133}
1134
Jamie Madill4928b7c2017-06-20 12:57:39 -04001135GLenum Framebuffer::getImplementationColorReadType(const Context *context) const
Geoff Langbce529e2014-12-01 12:48:41 -05001136{
Jamie Madill4928b7c2017-06-20 12:57:39 -04001137 return mImpl->getImplementationColorReadType(context);
Geoff Langbce529e2014-12-01 12:48:41 -05001138}
1139
Jamie Madillc564c072017-06-01 12:45:42 -04001140Error Framebuffer::readPixels(const gl::Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001141 const Rectangle &area,
Jamie Madill1b94d432015-08-07 13:23:23 -04001142 GLenum format,
1143 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001144 void *pixels) const
Geoff Langbce529e2014-12-01 12:48:41 -05001145{
Jamie Madill362876b2016-06-16 14:46:59 -04001146 ANGLE_TRY(mImpl->readPixels(context, area, format, type, pixels));
Geoff Lang520c4ae2015-05-05 13:12:36 -04001147
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001148 Buffer *unpackBuffer = context->getGLState().getUnpackState().pixelBuffer.get();
Geoff Lang520c4ae2015-05-05 13:12:36 -04001149 if (unpackBuffer)
1150 {
1151 unpackBuffer->onPixelUnpack();
1152 }
1153
Jamie Madill362876b2016-06-16 14:46:59 -04001154 return NoError();
Geoff Langbce529e2014-12-01 12:48:41 -05001155}
1156
Jamie Madillc564c072017-06-01 12:45:42 -04001157Error Framebuffer::blit(const gl::Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001158 const Rectangle &sourceArea,
1159 const Rectangle &destArea,
Geoff Lang242468f2015-09-24 14:15:41 -04001160 GLbitfield mask,
Jamie Madill8415b5f2016-04-26 13:41:39 -04001161 GLenum filter)
Geoff Lang54bd5a42014-12-01 12:51:04 -05001162{
He Yunchao6be602d2016-12-22 14:33:07 +08001163 GLbitfield blitMask = mask;
1164
1165 // Note that blitting is called against draw framebuffer.
1166 // See the code in gl::Context::blitFramebuffer.
1167 if ((mask & GL_COLOR_BUFFER_BIT) && !hasEnabledDrawBuffer())
1168 {
1169 blitMask &= ~GL_COLOR_BUFFER_BIT;
1170 }
1171
1172 if ((mask & GL_STENCIL_BUFFER_BIT) && mState.getStencilAttachment() == nullptr)
1173 {
1174 blitMask &= ~GL_STENCIL_BUFFER_BIT;
1175 }
1176
1177 if ((mask & GL_DEPTH_BUFFER_BIT) && mState.getDepthAttachment() == nullptr)
1178 {
1179 blitMask &= ~GL_DEPTH_BUFFER_BIT;
1180 }
1181
1182 if (!blitMask)
1183 {
1184 return NoError();
1185 }
1186
1187 return mImpl->blit(context, sourceArea, destArea, blitMask, filter);
Geoff Lang54bd5a42014-12-01 12:51:04 -05001188}
1189
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001190int Framebuffer::getSamples(const Context *context)
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001191{
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001192 if (complete(context))
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001193 {
Jamie Madill9c335862017-07-18 11:51:38 -04001194 return getCachedSamples(context);
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001195 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001196
1197 return 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001198}
1199
Jamie Madill9c335862017-07-18 11:51:38 -04001200int Framebuffer::getCachedSamples(const Context *context)
1201{
1202 // For a complete framebuffer, all attachments must have the same sample count.
1203 // In this case return the first nonzero sample size.
1204 const auto *firstNonNullAttachment = mState.getFirstNonNullAttachment();
1205 if (firstNonNullAttachment)
1206 {
1207 ASSERT(firstNonNullAttachment->isAttached());
1208 return firstNonNullAttachment->getSamples();
1209 }
1210
1211 // No attachments found.
1212 return 0;
1213}
1214
Corentin Wallezccab69d2017-01-27 16:57:15 -05001215Error Framebuffer::getSamplePosition(size_t index, GLfloat *xy) const
1216{
1217 ANGLE_TRY(mImpl->getSamplePosition(index, xy));
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001218 return NoError();
Corentin Wallezccab69d2017-01-27 16:57:15 -05001219}
1220
Jamie Madille261b442014-06-25 12:42:21 -04001221bool Framebuffer::hasValidDepthStencil() const
1222{
Jamie Madill48ef11b2016-04-27 15:21:52 -04001223 return mState.getDepthStencilAttachment() != nullptr;
Jamie Madille261b442014-06-25 12:42:21 -04001224}
1225
Jamie Madilla02315b2017-02-23 14:14:47 -05001226void Framebuffer::setAttachment(const Context *context,
1227 GLenum type,
Jamie Madill2d06b732015-04-20 12:53:28 -04001228 GLenum binding,
1229 const ImageIndex &textureIndex,
1230 FramebufferAttachmentObject *resource)
Geoff Langab75a052014-10-15 12:56:37 -04001231{
Martin Radev5dae57b2017-07-14 16:15:55 +03001232 setAttachment(context, type, binding, textureIndex, resource,
1233 FramebufferAttachment::kDefaultNumViews,
1234 FramebufferAttachment::kDefaultBaseViewIndex,
1235 FramebufferAttachment::kDefaultMultiviewLayout,
1236 FramebufferAttachment::kDefaultViewportOffsets);
1237}
1238
1239void Framebuffer::setAttachment(const Context *context,
1240 GLenum type,
1241 GLenum binding,
1242 const ImageIndex &textureIndex,
1243 FramebufferAttachmentObject *resource,
1244 GLsizei numViews,
1245 GLuint baseViewIndex,
1246 GLenum multiviewLayout,
1247 const GLint *viewportOffsets)
1248{
Jamie Madilla02315b2017-02-23 14:14:47 -05001249 // Context may be null in unit tests.
1250 if (!context || !context->isWebGL1())
1251 {
Martin Radev5dae57b2017-07-14 16:15:55 +03001252 setAttachmentImpl(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
1253 multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001254 return;
1255 }
1256
1257 switch (binding)
1258 {
1259 case GL_DEPTH_STENCIL:
1260 case GL_DEPTH_STENCIL_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001261 mState.mWebGLDepthStencilAttachment.attach(context, type, binding, textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001262 resource, numViews, baseViewIndex,
1263 multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001264 break;
1265 case GL_DEPTH:
1266 case GL_DEPTH_ATTACHMENT:
Martin Radev5dae57b2017-07-14 16:15:55 +03001267 mState.mWebGLDepthAttachment.attach(context, type, binding, textureIndex, resource,
1268 numViews, baseViewIndex, multiviewLayout,
1269 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001270 break;
1271 case GL_STENCIL:
1272 case GL_STENCIL_ATTACHMENT:
Martin Radev5dae57b2017-07-14 16:15:55 +03001273 mState.mWebGLStencilAttachment.attach(context, type, binding, textureIndex, resource,
1274 numViews, baseViewIndex, multiviewLayout,
1275 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001276 break;
1277 default:
Martin Radev5dae57b2017-07-14 16:15:55 +03001278 setAttachmentImpl(context, type, binding, textureIndex, resource, numViews,
1279 baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001280 return;
1281 }
1282
Martin Radev5dae57b2017-07-14 16:15:55 +03001283 commitWebGL1DepthStencilIfConsistent(context, numViews, baseViewIndex, multiviewLayout,
1284 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001285}
1286
Martin Radev82ef7742017-08-08 17:44:58 +03001287void Framebuffer::setAttachmentMultiviewLayered(const Context *context,
1288 GLenum type,
1289 GLenum binding,
1290 const ImageIndex &textureIndex,
1291 FramebufferAttachmentObject *resource,
1292 GLsizei numViews,
1293 GLint baseViewIndex)
1294{
1295 setAttachment(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
1296 GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE,
1297 FramebufferAttachment::kDefaultViewportOffsets);
1298}
1299
Martin Radev5dae57b2017-07-14 16:15:55 +03001300void Framebuffer::setAttachmentMultiviewSideBySide(const Context *context,
1301 GLenum type,
1302 GLenum binding,
1303 const ImageIndex &textureIndex,
1304 FramebufferAttachmentObject *resource,
1305 GLsizei numViews,
1306 const GLint *viewportOffsets)
1307{
1308 setAttachment(context, type, binding, textureIndex, resource, numViews,
1309 FramebufferAttachment::kDefaultBaseViewIndex,
1310 GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, viewportOffsets);
1311}
1312
1313void Framebuffer::commitWebGL1DepthStencilIfConsistent(const Context *context,
1314 GLsizei numViews,
1315 GLuint baseViewIndex,
1316 GLenum multiviewLayout,
1317 const GLint *viewportOffsets)
Jamie Madilla02315b2017-02-23 14:14:47 -05001318{
1319 int count = 0;
1320
1321 std::array<FramebufferAttachment *, 3> attachments = {{&mState.mWebGLDepthStencilAttachment,
1322 &mState.mWebGLDepthAttachment,
1323 &mState.mWebGLStencilAttachment}};
1324 for (FramebufferAttachment *attachment : attachments)
1325 {
1326 if (attachment->isAttached())
1327 {
1328 count++;
1329 }
1330 }
1331
1332 mState.mWebGLDepthStencilConsistent = (count <= 1);
1333 if (!mState.mWebGLDepthStencilConsistent)
1334 {
1335 // Inconsistent.
1336 return;
1337 }
1338
Geoff Lange466c552017-03-17 15:24:12 -04001339 auto getImageIndexIfTextureAttachment = [](const FramebufferAttachment &attachment) {
1340 if (attachment.type() == GL_TEXTURE)
1341 {
1342 return attachment.getTextureImageIndex();
1343 }
1344 else
1345 {
1346 return ImageIndex::MakeInvalid();
1347 }
1348 };
1349
Jamie Madilla02315b2017-02-23 14:14:47 -05001350 if (mState.mWebGLDepthAttachment.isAttached())
1351 {
1352 const auto &depth = mState.mWebGLDepthAttachment;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001353 setAttachmentImpl(context, depth.type(), GL_DEPTH_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001354 getImageIndexIfTextureAttachment(depth), depth.getResource(), numViews,
1355 baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001356 setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex::MakeInvalid(),
Martin Radev5dae57b2017-07-14 16:15:55 +03001357 nullptr, numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001358 }
1359 else if (mState.mWebGLStencilAttachment.isAttached())
1360 {
1361 const auto &stencil = mState.mWebGLStencilAttachment;
Martin Radev5dae57b2017-07-14 16:15:55 +03001362 setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex::MakeInvalid(), nullptr,
1363 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001364 setAttachmentImpl(context, stencil.type(), GL_STENCIL_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001365 getImageIndexIfTextureAttachment(stencil), stencil.getResource(),
1366 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001367 }
1368 else if (mState.mWebGLDepthStencilAttachment.isAttached())
1369 {
1370 const auto &depthStencil = mState.mWebGLDepthStencilAttachment;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001371 setAttachmentImpl(context, depthStencil.type(), GL_DEPTH_ATTACHMENT,
Geoff Lange466c552017-03-17 15:24:12 -04001372 getImageIndexIfTextureAttachment(depthStencil),
Martin Radev5dae57b2017-07-14 16:15:55 +03001373 depthStencil.getResource(), numViews, baseViewIndex, multiviewLayout,
1374 viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001375 setAttachmentImpl(context, depthStencil.type(), GL_STENCIL_ATTACHMENT,
Geoff Lange466c552017-03-17 15:24:12 -04001376 getImageIndexIfTextureAttachment(depthStencil),
Martin Radev5dae57b2017-07-14 16:15:55 +03001377 depthStencil.getResource(), numViews, baseViewIndex, multiviewLayout,
1378 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001379 }
1380 else
1381 {
Martin Radev5dae57b2017-07-14 16:15:55 +03001382 setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex::MakeInvalid(), nullptr,
1383 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001384 setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex::MakeInvalid(),
Martin Radev5dae57b2017-07-14 16:15:55 +03001385 nullptr, numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001386 }
1387}
1388
Jamie Madill4928b7c2017-06-20 12:57:39 -04001389void Framebuffer::setAttachmentImpl(const Context *context,
1390 GLenum type,
Jamie Madilla02315b2017-02-23 14:14:47 -05001391 GLenum binding,
1392 const ImageIndex &textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001393 FramebufferAttachmentObject *resource,
1394 GLsizei numViews,
1395 GLuint baseViewIndex,
1396 GLenum multiviewLayout,
1397 const GLint *viewportOffsets)
Jamie Madilla02315b2017-02-23 14:14:47 -05001398{
Jamie Madilla02315b2017-02-23 14:14:47 -05001399 switch (binding)
1400 {
Jamie Madillb8126692017-04-05 11:22:17 -04001401 case GL_DEPTH_STENCIL:
1402 case GL_DEPTH_STENCIL_ATTACHMENT:
1403 {
1404 // ensure this is a legitimate depth+stencil format
1405 FramebufferAttachmentObject *attachmentObj = resource;
1406 if (resource)
1407 {
Jamie Madill4fd95d52017-04-05 11:22:18 -04001408 const Format &format = resource->getAttachmentFormat(binding, textureIndex);
Jamie Madillb8126692017-04-05 11:22:17 -04001409 if (format.info->depthBits == 0 || format.info->stencilBits == 0)
1410 {
1411 // Attaching nullptr detaches the current attachment.
1412 attachmentObj = nullptr;
1413 }
1414 }
1415
Jamie Madill4928b7c2017-06-20 12:57:39 -04001416 updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
Jamie Madillb8126692017-04-05 11:22:17 -04001417 &mDirtyDepthAttachmentBinding, type, binding, textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001418 attachmentObj, numViews, baseViewIndex, multiviewLayout,
1419 viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001420 updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
Jamie Madillb8126692017-04-05 11:22:17 -04001421 &mDirtyStencilAttachmentBinding, type, binding, textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001422 attachmentObj, numViews, baseViewIndex, multiviewLayout,
1423 viewportOffsets);
Jamie Madillb8126692017-04-05 11:22:17 -04001424 return;
1425 }
1426
Jamie Madilla02315b2017-02-23 14:14:47 -05001427 case GL_DEPTH:
1428 case GL_DEPTH_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001429 updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001430 &mDirtyDepthAttachmentBinding, type, binding, textureIndex, resource,
1431 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madill2d06b732015-04-20 12:53:28 -04001432 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001433
Jamie Madilla02315b2017-02-23 14:14:47 -05001434 case GL_STENCIL:
1435 case GL_STENCIL_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001436 updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001437 &mDirtyStencilAttachmentBinding, type, binding, textureIndex, resource,
1438 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001439 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001440
Jamie Madilla02315b2017-02-23 14:14:47 -05001441 case GL_BACK:
Martin Radev5dae57b2017-07-14 16:15:55 +03001442 mState.mColorAttachments[0].attach(context, type, binding, textureIndex, resource,
1443 numViews, baseViewIndex, multiviewLayout,
1444 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001445 mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0);
1446 // No need for a resource binding for the default FBO, it's always complete.
1447 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001448
Jamie Madilla02315b2017-02-23 14:14:47 -05001449 default:
1450 {
1451 size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
1452 ASSERT(colorIndex < mState.mColorAttachments.size());
Jamie Madillb8126692017-04-05 11:22:17 -04001453 size_t dirtyBit = DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001454 updateAttachment(context, &mState.mColorAttachments[colorIndex], dirtyBit,
Jamie Madillb8126692017-04-05 11:22:17 -04001455 &mDirtyColorAttachmentBindings[colorIndex], type, binding,
Martin Radev5dae57b2017-07-14 16:15:55 +03001456 textureIndex, resource, numViews, baseViewIndex, multiviewLayout,
1457 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001458
Corentin Walleze7557742017-06-01 13:09:57 -04001459 // TODO(jmadill): ASSERT instead of checking the attachment exists in
1460 // formsRenderingFeedbackLoopWith
Jamie Madilla02315b2017-02-23 14:14:47 -05001461 bool enabled = (type != GL_NONE && getDrawBufferState(colorIndex) != GL_NONE);
1462 mState.mEnabledDrawBuffers.set(colorIndex, enabled);
Jamie Madill2d06b732015-04-20 12:53:28 -04001463 }
Jamie Madilla02315b2017-02-23 14:14:47 -05001464 break;
Geoff Langab75a052014-10-15 12:56:37 -04001465 }
1466}
1467
Jamie Madill4928b7c2017-06-20 12:57:39 -04001468void Framebuffer::updateAttachment(const Context *context,
1469 FramebufferAttachment *attachment,
Jamie Madillb8126692017-04-05 11:22:17 -04001470 size_t dirtyBit,
1471 OnAttachmentDirtyBinding *onDirtyBinding,
1472 GLenum type,
1473 GLenum binding,
1474 const ImageIndex &textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001475 FramebufferAttachmentObject *resource,
1476 GLsizei numViews,
1477 GLuint baseViewIndex,
1478 GLenum multiviewLayout,
1479 const GLint *viewportOffsets)
Jamie Madillb8126692017-04-05 11:22:17 -04001480{
Martin Radev5dae57b2017-07-14 16:15:55 +03001481 attachment->attach(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
1482 multiviewLayout, viewportOffsets);
Jamie Madillb8126692017-04-05 11:22:17 -04001483 mDirtyBits.set(dirtyBit);
1484 BindResourceChannel(onDirtyBinding, resource);
1485}
1486
Jamie Madilla02315b2017-02-23 14:14:47 -05001487void Framebuffer::resetAttachment(const Context *context, GLenum binding)
Jamie Madill2d06b732015-04-20 12:53:28 -04001488{
Jamie Madilla02315b2017-02-23 14:14:47 -05001489 setAttachment(context, GL_NONE, binding, ImageIndex::MakeInvalid(), nullptr);
Jamie Madill2d06b732015-04-20 12:53:28 -04001490}
1491
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001492void Framebuffer::syncState(const Context *context)
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001493{
1494 if (mDirtyBits.any())
1495 {
Jamie Madillc564c072017-06-01 12:45:42 -04001496 mImpl->syncState(context, mDirtyBits);
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001497 mDirtyBits.reset();
Corentin Wallezccab69d2017-01-27 16:57:15 -05001498 if (mId != 0)
1499 {
1500 mCachedStatus.reset();
1501 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001502 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001503}
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001504
Jamie Madill1e5499d2017-04-05 11:22:16 -04001505void Framebuffer::signal(uint32_t token)
Jamie Madill51f40ec2016-06-15 14:06:00 -04001506{
Jamie Madill362876b2016-06-16 14:46:59 -04001507 // TOOD(jmadill): Make this only update individual attachments to do less work.
1508 mCachedStatus.reset();
Jamie Madill51f40ec2016-06-15 14:06:00 -04001509}
1510
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001511bool Framebuffer::complete(const Context *context)
Jamie Madill51f40ec2016-06-15 14:06:00 -04001512{
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001513 return (checkStatus(context) == GL_FRAMEBUFFER_COMPLETE);
1514}
1515
1516bool Framebuffer::cachedComplete() const
1517{
1518 return (mCachedStatus.valid() && mCachedStatus == GL_FRAMEBUFFER_COMPLETE);
Jamie Madill51f40ec2016-06-15 14:06:00 -04001519}
1520
Jamie Madilla4595b82017-01-11 17:36:34 -05001521bool Framebuffer::formsRenderingFeedbackLoopWith(const State &state) const
1522{
1523 const Program *program = state.getProgram();
1524
1525 // TODO(jmadill): Default framebuffer feedback loops.
1526 if (mId == 0)
1527 {
1528 return false;
1529 }
1530
1531 // The bitset will skip inactive draw buffers.
Jamie Madill6de51852017-04-12 09:53:01 -04001532 for (size_t drawIndex : mState.mEnabledDrawBuffers)
Jamie Madilla4595b82017-01-11 17:36:34 -05001533 {
Jamie Madill5aca1932017-07-21 12:22:01 -04001534 const FramebufferAttachment &attachment = mState.mColorAttachments[drawIndex];
1535 ASSERT(attachment.isAttached());
1536 if (attachment.type() == GL_TEXTURE)
Jamie Madilla4595b82017-01-11 17:36:34 -05001537 {
1538 // Validate the feedback loop.
Jamie Madill5aca1932017-07-21 12:22:01 -04001539 if (program->samplesFromTexture(state, attachment.id()))
Jamie Madilla4595b82017-01-11 17:36:34 -05001540 {
1541 return true;
1542 }
1543 }
1544 }
1545
Jamie Madill1d37bc52017-02-02 19:59:58 -05001546 // Validate depth-stencil feedback loop.
1547 const auto &dsState = state.getDepthStencilState();
1548
1549 // We can skip the feedback loop checks if depth/stencil is masked out or disabled.
1550 const FramebufferAttachment *depth = getDepthbuffer();
1551 if (depth && depth->type() == GL_TEXTURE && dsState.depthTest && dsState.depthMask)
1552 {
1553 if (program->samplesFromTexture(state, depth->id()))
1554 {
1555 return true;
1556 }
1557 }
1558
1559 // Note: we assume the front and back masks are the same for WebGL.
1560 const FramebufferAttachment *stencil = getStencilbuffer();
1561 ASSERT(dsState.stencilBackWritemask == dsState.stencilWritemask);
1562 if (stencil && stencil->type() == GL_TEXTURE && dsState.stencilTest &&
1563 dsState.stencilWritemask != 0)
1564 {
1565 // Skip the feedback loop check if depth/stencil point to the same resource.
1566 if (!depth || *stencil != *depth)
1567 {
1568 if (program->samplesFromTexture(state, stencil->id()))
1569 {
1570 return true;
1571 }
1572 }
1573 }
1574
Jamie Madilla4595b82017-01-11 17:36:34 -05001575 return false;
1576}
1577
Jamie Madillfd3dd432017-02-02 19:59:59 -05001578bool Framebuffer::formsCopyingFeedbackLoopWith(GLuint copyTextureID,
1579 GLint copyTextureLevel,
1580 GLint copyTextureLayer) const
Jamie Madillf695a3a2017-01-11 17:36:35 -05001581{
1582 if (mId == 0)
1583 {
1584 // It seems impossible to form a texture copying feedback loop with the default FBO.
1585 return false;
1586 }
1587
1588 const FramebufferAttachment *readAttachment = getReadColorbuffer();
1589 ASSERT(readAttachment);
1590
1591 if (readAttachment->isTextureWithId(copyTextureID))
1592 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05001593 const auto &imageIndex = readAttachment->getTextureImageIndex();
1594 if (imageIndex.mipIndex == copyTextureLevel)
Jamie Madillf695a3a2017-01-11 17:36:35 -05001595 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05001596 // Check 3D/Array texture layers.
1597 return imageIndex.layerIndex == ImageIndex::ENTIRE_LEVEL ||
1598 copyTextureLayer == ImageIndex::ENTIRE_LEVEL ||
1599 imageIndex.layerIndex == copyTextureLayer;
Jamie Madillf695a3a2017-01-11 17:36:35 -05001600 }
1601 }
1602 return false;
1603}
1604
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001605GLint Framebuffer::getDefaultWidth() const
1606{
1607 return mState.getDefaultWidth();
1608}
1609
1610GLint Framebuffer::getDefaultHeight() const
1611{
1612 return mState.getDefaultHeight();
1613}
1614
1615GLint Framebuffer::getDefaultSamples() const
1616{
1617 return mState.getDefaultSamples();
1618}
1619
1620GLboolean Framebuffer::getDefaultFixedSampleLocations() const
1621{
1622 return mState.getDefaultFixedSampleLocations();
1623}
1624
1625void Framebuffer::setDefaultWidth(GLint defaultWidth)
1626{
1627 mState.mDefaultWidth = defaultWidth;
1628 mDirtyBits.set(DIRTY_BIT_DEFAULT_WIDTH);
1629}
1630
1631void Framebuffer::setDefaultHeight(GLint defaultHeight)
1632{
1633 mState.mDefaultHeight = defaultHeight;
1634 mDirtyBits.set(DIRTY_BIT_DEFAULT_HEIGHT);
1635}
1636
1637void Framebuffer::setDefaultSamples(GLint defaultSamples)
1638{
1639 mState.mDefaultSamples = defaultSamples;
1640 mDirtyBits.set(DIRTY_BIT_DEFAULT_SAMPLES);
1641}
1642
1643void Framebuffer::setDefaultFixedSampleLocations(GLboolean defaultFixedSampleLocations)
1644{
1645 mState.mDefaultFixedSampleLocations = defaultFixedSampleLocations;
1646 mDirtyBits.set(DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS);
1647}
1648
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001649// TODO(jmadill): Remove this kludge.
1650GLenum Framebuffer::checkStatus(const ValidationContext *context)
1651{
1652 return checkStatus(static_cast<const Context *>(context));
1653}
1654
1655int Framebuffer::getSamples(const ValidationContext *context)
1656{
1657 return getSamples(static_cast<const Context *>(context));
1658}
1659
Martin Radev14a26ae2017-07-24 15:56:29 +03001660GLsizei Framebuffer::getNumViews() const
1661{
Martin Radev5c00d0d2017-08-07 10:06:59 +03001662 return mState.getNumViews();
Martin Radev14a26ae2017-07-24 15:56:29 +03001663}
1664
Martin Radev4e619f52017-08-09 11:50:06 +03001665GLint Framebuffer::getBaseViewIndex() const
1666{
1667 return mState.getBaseViewIndex();
1668}
1669
Martin Radev878c8b12017-07-28 09:51:04 +03001670const std::vector<Offset> *Framebuffer::getViewportOffsets() const
1671{
Martin Radev5c00d0d2017-08-07 10:06:59 +03001672 return mState.getViewportOffsets();
Martin Radev878c8b12017-07-28 09:51:04 +03001673}
1674
1675GLenum Framebuffer::getMultiviewLayout() const
1676{
Martin Radev5c00d0d2017-08-07 10:06:59 +03001677 return mState.getMultiviewLayout();
Martin Radev878c8b12017-07-28 09:51:04 +03001678}
1679
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001680} // namespace gl