blob: 202abbc2b640268425c898c29b4dcd2be257171c [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
Jamie Madill7aea7e02016-05-10 10:39:45 -0400486Framebuffer::Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id)
Jamie Madill362876b2016-06-16 14:46:59 -0400487 : mState(caps),
488 mImpl(factory->createFramebuffer(mState)),
489 mId(id),
490 mCachedStatus(),
491 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
492 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000493{
Corentin Wallez37c39792015-08-20 14:19:46 -0400494 ASSERT(mId != 0);
495 ASSERT(mImpl != nullptr);
Jamie Madill362876b2016-06-16 14:46:59 -0400496 ASSERT(mState.mColorAttachments.size() == static_cast<size_t>(caps.maxColorAttachments));
497
Jamie Madill1e5499d2017-04-05 11:22:16 -0400498 for (uint32_t colorIndex = 0;
499 colorIndex < static_cast<uint32_t>(mState.mColorAttachments.size()); ++colorIndex)
Jamie Madill362876b2016-06-16 14:46:59 -0400500 {
Jamie Madill1e5499d2017-04-05 11:22:16 -0400501 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
Jamie Madill362876b2016-06-16 14:46:59 -0400502 }
Corentin Wallez37c39792015-08-20 14:19:46 -0400503}
504
Jamie Madill4928b7c2017-06-20 12:57:39 -0400505Framebuffer::Framebuffer(const egl::Display *display, egl::Surface *surface)
Jamie Madill362876b2016-06-16 14:46:59 -0400506 : mState(),
Jamie Madill6f60d052017-02-22 15:20:11 -0500507 mImpl(surface->getImplementation()->createDefaultFramebuffer(mState)),
Jamie Madill362876b2016-06-16 14:46:59 -0400508 mId(0),
509 mCachedStatus(GL_FRAMEBUFFER_COMPLETE),
510 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
511 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
Corentin Wallez37c39792015-08-20 14:19:46 -0400512{
Geoff Langda88add2014-12-01 10:22:01 -0500513 ASSERT(mImpl != nullptr);
Jamie Madill1e5499d2017-04-05 11:22:16 -0400514 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
Jamie Madill6f60d052017-02-22 15:20:11 -0500515
Jamie Madill4928b7c2017-06-20 12:57:39 -0400516 const Context *proxyContext = display->getProxyContext();
517
518 setAttachmentImpl(proxyContext, GL_FRAMEBUFFER_DEFAULT, GL_BACK, gl::ImageIndex::MakeInvalid(),
Martin Radev5dae57b2017-07-14 16:15:55 +0300519 surface, FramebufferAttachment::kDefaultNumViews,
520 FramebufferAttachment::kDefaultBaseViewIndex,
521 FramebufferAttachment::kDefaultMultiviewLayout,
522 FramebufferAttachment::kDefaultViewportOffsets);
Jamie Madill6f60d052017-02-22 15:20:11 -0500523
524 if (surface->getConfig()->depthSize > 0)
525 {
Martin Radev5dae57b2017-07-14 16:15:55 +0300526 setAttachmentImpl(
527 proxyContext, GL_FRAMEBUFFER_DEFAULT, GL_DEPTH, gl::ImageIndex::MakeInvalid(), surface,
528 FramebufferAttachment::kDefaultNumViews, FramebufferAttachment::kDefaultBaseViewIndex,
529 FramebufferAttachment::kDefaultMultiviewLayout,
530 FramebufferAttachment::kDefaultViewportOffsets);
Jamie Madill6f60d052017-02-22 15:20:11 -0500531 }
532
533 if (surface->getConfig()->stencilSize > 0)
534 {
Jamie Madill4928b7c2017-06-20 12:57:39 -0400535 setAttachmentImpl(proxyContext, GL_FRAMEBUFFER_DEFAULT, GL_STENCIL,
Martin Radev5dae57b2017-07-14 16:15:55 +0300536 gl::ImageIndex::MakeInvalid(), surface,
537 FramebufferAttachment::kDefaultNumViews,
538 FramebufferAttachment::kDefaultBaseViewIndex,
539 FramebufferAttachment::kDefaultMultiviewLayout,
540 FramebufferAttachment::kDefaultViewportOffsets);
Jamie Madill6f60d052017-02-22 15:20:11 -0500541 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000542}
543
Corentin Wallezccab69d2017-01-27 16:57:15 -0500544Framebuffer::Framebuffer(rx::GLImplFactory *factory)
545 : mState(),
546 mImpl(factory->createFramebuffer(mState)),
547 mId(0),
548 mCachedStatus(GL_FRAMEBUFFER_UNDEFINED_OES),
549 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
550 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
551{
Jamie Madill1e5499d2017-04-05 11:22:16 -0400552 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
Corentin Wallezccab69d2017-01-27 16:57:15 -0500553}
554
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000555Framebuffer::~Framebuffer()
556{
Geoff Langda88add2014-12-01 10:22:01 -0500557 SafeDelete(mImpl);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000558}
559
Jamie Madill4928b7c2017-06-20 12:57:39 -0400560void Framebuffer::onDestroy(const Context *context)
Jamie Madill6c1f6712017-02-14 19:08:04 -0500561{
Jamie Madill4928b7c2017-06-20 12:57:39 -0400562 for (auto &attachment : mState.mColorAttachments)
563 {
564 attachment.detach(context);
565 }
566 mState.mDepthAttachment.detach(context);
567 mState.mStencilAttachment.detach(context);
568 mState.mWebGLDepthAttachment.detach(context);
569 mState.mWebGLStencilAttachment.detach(context);
570 mState.mWebGLDepthStencilAttachment.detach(context);
571
Jamie Madillc564c072017-06-01 12:45:42 -0400572 mImpl->destroy(context);
Jamie Madill6c1f6712017-02-14 19:08:04 -0500573}
574
575void Framebuffer::destroyDefault(const egl::Display *display)
576{
Jamie Madillc564c072017-06-01 12:45:42 -0400577 mImpl->destroyDefault(display);
Jamie Madill6c1f6712017-02-14 19:08:04 -0500578}
579
Geoff Lang70d0f492015-12-10 17:45:46 -0500580void Framebuffer::setLabel(const std::string &label)
581{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400582 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -0500583}
584
585const std::string &Framebuffer::getLabel() const
586{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400587 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -0500588}
589
Jamie Madilla02315b2017-02-23 14:14:47 -0500590void Framebuffer::detachTexture(const Context *context, GLuint textureId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000591{
Jamie Madilla02315b2017-02-23 14:14:47 -0500592 detachResourceById(context, GL_TEXTURE, textureId);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000593}
594
Jamie Madilla02315b2017-02-23 14:14:47 -0500595void Framebuffer::detachRenderbuffer(const Context *context, GLuint renderbufferId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000596{
Jamie Madilla02315b2017-02-23 14:14:47 -0500597 detachResourceById(context, GL_RENDERBUFFER, renderbufferId);
Jamie Madilld1405e52015-03-05 15:41:39 -0500598}
Jamie Madille261b442014-06-25 12:42:21 -0400599
Jamie Madilla02315b2017-02-23 14:14:47 -0500600void Framebuffer::detachResourceById(const Context *context, GLenum resourceType, GLuint resourceId)
Jamie Madilld1405e52015-03-05 15:41:39 -0500601{
Jamie Madill362876b2016-06-16 14:46:59 -0400602 for (size_t colorIndex = 0; colorIndex < mState.mColorAttachments.size(); ++colorIndex)
Jamie Madilld1405e52015-03-05 15:41:39 -0500603 {
Jamie Madill4928b7c2017-06-20 12:57:39 -0400604 detachMatchingAttachment(context, &mState.mColorAttachments[colorIndex], resourceType,
605 resourceId, DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000606 }
607
Jamie Madilla02315b2017-02-23 14:14:47 -0500608 if (context->isWebGL1())
609 {
610 const std::array<FramebufferAttachment *, 3> attachments = {
611 {&mState.mWebGLDepthStencilAttachment, &mState.mWebGLDepthAttachment,
612 &mState.mWebGLStencilAttachment}};
613 for (FramebufferAttachment *attachment : attachments)
614 {
615 if (attachment->isAttached() && attachment->type() == resourceType &&
616 attachment->id() == resourceId)
617 {
618 resetAttachment(context, attachment->getBinding());
619 }
620 }
621 }
622 else
623 {
Jamie Madill4928b7c2017-06-20 12:57:39 -0400624 detachMatchingAttachment(context, &mState.mDepthAttachment, resourceType, resourceId,
Jamie Madilla02315b2017-02-23 14:14:47 -0500625 DIRTY_BIT_DEPTH_ATTACHMENT);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400626 detachMatchingAttachment(context, &mState.mStencilAttachment, resourceType, resourceId,
Jamie Madilla02315b2017-02-23 14:14:47 -0500627 DIRTY_BIT_STENCIL_ATTACHMENT);
628 }
Jamie Madill362876b2016-06-16 14:46:59 -0400629}
630
Jamie Madill4928b7c2017-06-20 12:57:39 -0400631void Framebuffer::detachMatchingAttachment(const Context *context,
632 FramebufferAttachment *attachment,
Jamie Madill362876b2016-06-16 14:46:59 -0400633 GLenum matchType,
634 GLuint matchId,
635 size_t dirtyBit)
636{
637 if (attachment->isAttached() && attachment->type() == matchType && attachment->id() == matchId)
638 {
Jamie Madill4928b7c2017-06-20 12:57:39 -0400639 attachment->detach(context);
Jamie Madill362876b2016-06-16 14:46:59 -0400640 mDirtyBits.set(dirtyBit);
641 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000642}
643
Corentin Wallez37c39792015-08-20 14:19:46 -0400644const FramebufferAttachment *Framebuffer::getColorbuffer(size_t colorAttachment) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000645{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400646 return mState.getColorAttachment(colorAttachment);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000647}
648
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400649const FramebufferAttachment *Framebuffer::getDepthbuffer() const
Geoff Lang646559f2013-08-15 11:08:15 -0400650{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400651 return mState.getDepthAttachment();
Geoff Lang646559f2013-08-15 11:08:15 -0400652}
653
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400654const FramebufferAttachment *Framebuffer::getStencilbuffer() const
655{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400656 return mState.getStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400657}
658
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400659const FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
660{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400661 return mState.getDepthStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400662}
663
664const FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000665{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400666 return mState.getDepthOrStencilAttachment();
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000667}
668
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500669const FramebufferAttachment *Framebuffer::getStencilOrDepthStencilAttachment() const
670{
671 return mState.getStencilOrDepthStencilAttachment();
672}
673
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400674const FramebufferAttachment *Framebuffer::getReadColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000675{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400676 return mState.getReadAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000677}
678
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000679GLenum Framebuffer::getReadColorbufferType() const
680{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400681 const FramebufferAttachment *readAttachment = mState.getReadAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400682 return (readAttachment != nullptr ? readAttachment->type() : GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000683}
684
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400685const FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000686{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400687 return mState.getFirstColorAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000688}
689
Jamie Madill6dd06ea2017-07-19 13:47:55 -0400690const FramebufferAttachment *Framebuffer::getFirstNonNullAttachment() const
691{
692 return mState.getFirstNonNullAttachment();
693}
694
Jamie Madill2d06b732015-04-20 12:53:28 -0400695const FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000696{
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400697 return mState.getAttachment(attachment);
Geoff Lang55ba29c2013-07-11 16:57:53 -0400698}
699
Geoff Langa15472a2015-08-11 11:48:03 -0400700size_t Framebuffer::getDrawbufferStateCount() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000701{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400702 return mState.mDrawBufferStates.size();
Geoff Langa15472a2015-08-11 11:48:03 -0400703}
704
705GLenum Framebuffer::getDrawBufferState(size_t drawBuffer) const
706{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400707 ASSERT(drawBuffer < mState.mDrawBufferStates.size());
708 return mState.mDrawBufferStates[drawBuffer];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000709}
710
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500711const std::vector<GLenum> &Framebuffer::getDrawBufferStates() const
712{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400713 return mState.getDrawBufferStates();
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500714}
715
Geoff Lang164d54e2014-12-01 10:55:33 -0500716void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000717{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400718 auto &drawStates = mState.mDrawBufferStates;
Jamie Madilld1405e52015-03-05 15:41:39 -0500719
720 ASSERT(count <= drawStates.size());
721 std::copy(buffers, buffers + count, drawStates.begin());
722 std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500723 mDirtyBits.set(DIRTY_BIT_DRAW_BUFFERS);
Jamie Madilla4595b82017-01-11 17:36:34 -0500724
725 mState.mEnabledDrawBuffers.reset();
726 for (size_t index = 0; index < count; ++index)
727 {
728 if (drawStates[index] != GL_NONE && mState.mColorAttachments[index].isAttached())
729 {
730 mState.mEnabledDrawBuffers.set(index);
731 }
732 }
Geoff Lang9dd95802014-12-01 11:12:59 -0500733}
734
Geoff Langa15472a2015-08-11 11:48:03 -0400735const FramebufferAttachment *Framebuffer::getDrawBuffer(size_t drawBuffer) const
736{
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400737 return mState.getDrawBuffer(drawBuffer);
Geoff Langa15472a2015-08-11 11:48:03 -0400738}
739
Geoff Lange0cff192017-05-30 13:04:56 -0400740GLenum Framebuffer::getDrawbufferWriteType(size_t drawBuffer) const
741{
742 const FramebufferAttachment *attachment = mState.getDrawBuffer(drawBuffer);
743 if (attachment == nullptr)
744 {
745 return GL_NONE;
746 }
747
748 GLenum componentType = attachment->getFormat().info->componentType;
749 switch (componentType)
750 {
751 case GL_INT:
752 case GL_UNSIGNED_INT:
753 return componentType;
754
755 default:
756 return GL_FLOAT;
757 }
758}
759
Geoff Langa15472a2015-08-11 11:48:03 -0400760bool Framebuffer::hasEnabledDrawBuffer() const
761{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400762 for (size_t drawbufferIdx = 0; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
Geoff Langa15472a2015-08-11 11:48:03 -0400763 {
764 if (getDrawBuffer(drawbufferIdx) != nullptr)
765 {
766 return true;
767 }
768 }
769
770 return false;
771}
772
Geoff Lang9dd95802014-12-01 11:12:59 -0500773GLenum Framebuffer::getReadBufferState() const
774{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400775 return mState.mReadBufferState;
Geoff Lang9dd95802014-12-01 11:12:59 -0500776}
777
778void Framebuffer::setReadBuffer(GLenum buffer)
779{
Jamie Madillb885e572015-02-03 16:16:04 -0500780 ASSERT(buffer == GL_BACK || buffer == GL_NONE ||
781 (buffer >= GL_COLOR_ATTACHMENT0 &&
Jamie Madill48ef11b2016-04-27 15:21:52 -0400782 (buffer - GL_COLOR_ATTACHMENT0) < mState.mColorAttachments.size()));
783 mState.mReadBufferState = buffer;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500784 mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000785}
786
Corentin Wallez37c39792015-08-20 14:19:46 -0400787size_t Framebuffer::getNumColorBuffers() const
788{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400789 return mState.mColorAttachments.size();
Corentin Wallez37c39792015-08-20 14:19:46 -0400790}
791
Jamie Madill0df8fe42015-11-24 16:10:24 -0500792bool Framebuffer::hasDepth() const
793{
Jamie Madill9c335862017-07-18 11:51:38 -0400794 return mState.hasDepth();
Jamie Madill0df8fe42015-11-24 16:10:24 -0500795}
796
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000797bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000798{
Jamie Madill9c335862017-07-18 11:51:38 -0400799 return mState.hasStencil();
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000800}
801
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000802bool Framebuffer::usingExtendedDrawBuffers() const
803{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400804 for (size_t drawbufferIdx = 1; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000805 {
Geoff Langa15472a2015-08-11 11:48:03 -0400806 if (getDrawBuffer(drawbufferIdx) != nullptr)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000807 {
808 return true;
809 }
810 }
811
812 return false;
813}
814
Geoff Lang9aded172017-04-05 11:07:56 -0400815void Framebuffer::invalidateCompletenessCache()
816{
817 if (mId != 0)
818 {
819 mCachedStatus.reset();
820 }
821}
822
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400823GLenum Framebuffer::checkStatus(const Context *context)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000824{
Corentin Wallezccab69d2017-01-27 16:57:15 -0500825 // The default framebuffer is always complete except when it is surfaceless in which
826 // case it is always unsupported. We return early because the default framebuffer may
827 // not be subject to the same rules as application FBOs. ie, it could have 0x0 size.
Geoff Lang528ce3c2014-12-01 10:44:07 -0500828 if (mId == 0)
829 {
Corentin Wallezccab69d2017-01-27 16:57:15 -0500830 ASSERT(mCachedStatus.valid());
831 ASSERT(mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE ||
832 mCachedStatus.value() == GL_FRAMEBUFFER_UNDEFINED_OES);
833 return mCachedStatus.value();
Geoff Lang528ce3c2014-12-01 10:44:07 -0500834 }
835
Jamie Madill362876b2016-06-16 14:46:59 -0400836 if (hasAnyDirtyBit() || !mCachedStatus.valid())
837 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400838 mCachedStatus = checkStatusImpl(context);
Jamie Madill362876b2016-06-16 14:46:59 -0400839 }
840
841 return mCachedStatus.value();
842}
843
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400844GLenum Framebuffer::checkStatusImpl(const Context *context)
Jamie Madill362876b2016-06-16 14:46:59 -0400845{
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400846 const ContextState &state = context->getContextState();
847
Jamie Madill362876b2016-06-16 14:46:59 -0400848 ASSERT(mId != 0);
849
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400850 bool hasAttachments = false;
851 Optional<unsigned int> colorbufferSize;
852 Optional<int> samples;
JiangYizhou461d9a32017-01-04 16:37:26 +0800853 Optional<GLboolean> fixedSampleLocations;
854 bool hasRenderbuffer = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000855
Martin Radev9bc9a322017-07-21 14:28:17 +0300856 const FramebufferAttachment *firstAttachment = getFirstNonNullAttachment();
857
Jamie Madill48ef11b2016-04-27 15:21:52 -0400858 for (const FramebufferAttachment &colorAttachment : mState.mColorAttachments)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000859 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400860 if (colorAttachment.isAttached())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000861 {
Geoff Lang9f10b772017-05-16 15:51:03 -0400862 if (!CheckAttachmentCompleteness(context, colorAttachment))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000863 {
864 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
865 }
daniel@transgaming.com01868132010-08-24 19:21:17 +0000866
Geoff Lang677bb6f2017-04-05 12:40:40 -0400867 const InternalFormat &format = *colorAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -0400868 if (format.depthBits > 0 || format.stencilBits > 0)
869 {
870 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
871 }
872
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400873 if (!CheckAttachmentSampleCompleteness(context, colorAttachment, true, &samples,
874 &fixedSampleLocations))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000875 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400876 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000877 }
878
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400879 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
880 // in GLES 3.0, there is no such restriction
881 if (state.getClientMajorVersion() < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000882 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400883 if (colorbufferSize.valid())
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000884 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400885 if (format.pixelBytes != colorbufferSize.value())
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000886 {
887 return GL_FRAMEBUFFER_UNSUPPORTED;
888 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000889 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400890 else
891 {
892 colorbufferSize = format.pixelBytes;
893 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000894 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400895
Martin Radev9bc9a322017-07-21 14:28:17 +0300896 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &colorAttachment))
897 {
898 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
899 }
900
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400901 hasRenderbuffer = hasRenderbuffer || (colorAttachment.type() == GL_RENDERBUFFER);
902 hasAttachments = true;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000903 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000904 }
905
Jamie Madill48ef11b2016-04-27 15:21:52 -0400906 const FramebufferAttachment &depthAttachment = mState.mDepthAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -0400907 if (depthAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000908 {
Geoff Lang9f10b772017-05-16 15:51:03 -0400909 if (!CheckAttachmentCompleteness(context, depthAttachment))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000910 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000911 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000912 }
913
Geoff Lang677bb6f2017-04-05 12:40:40 -0400914 const InternalFormat &format = *depthAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -0400915 if (format.depthBits == 0)
916 {
917 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000918 }
919
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400920 if (!CheckAttachmentSampleCompleteness(context, depthAttachment, false, &samples,
921 &fixedSampleLocations))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000922 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400923 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000924 }
Sami Väisänena797e062016-05-12 15:23:40 +0300925
Martin Radev9bc9a322017-07-21 14:28:17 +0300926 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &depthAttachment))
927 {
928 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
929 }
930
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400931 hasRenderbuffer = hasRenderbuffer || (depthAttachment.type() == GL_RENDERBUFFER);
932 hasAttachments = true;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000933 }
934
Jamie Madill48ef11b2016-04-27 15:21:52 -0400935 const FramebufferAttachment &stencilAttachment = mState.mStencilAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -0400936 if (stencilAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000937 {
Geoff Lang9f10b772017-05-16 15:51:03 -0400938 if (!CheckAttachmentCompleteness(context, stencilAttachment))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000939 {
940 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
941 }
942
Geoff Lang677bb6f2017-04-05 12:40:40 -0400943 const InternalFormat &format = *stencilAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -0400944 if (format.stencilBits == 0)
945 {
946 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000947 }
948
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400949 if (!CheckAttachmentSampleCompleteness(context, stencilAttachment, false, &samples,
950 &fixedSampleLocations))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000951 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400952 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000953 }
Corentin Wallez086d59a2016-04-29 09:06:49 -0400954
Martin Radev9bc9a322017-07-21 14:28:17 +0300955 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &stencilAttachment))
956 {
957 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
958 }
959
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400960 hasRenderbuffer = hasRenderbuffer || (stencilAttachment.type() == GL_RENDERBUFFER);
961 hasAttachments = true;
962 }
963
964 // Starting from ES 3.0 stencil and depth, if present, should be the same image
965 if (state.getClientMajorVersion() >= 3 && depthAttachment.isAttached() &&
966 stencilAttachment.isAttached() && stencilAttachment != depthAttachment)
967 {
968 return GL_FRAMEBUFFER_UNSUPPORTED;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000969 }
970
Jamie Madilla02315b2017-02-23 14:14:47 -0500971 // Special additional validation for WebGL 1 DEPTH/STENCIL/DEPTH_STENCIL.
972 if (state.isWebGL1())
973 {
974 if (!mState.mWebGLDepthStencilConsistent)
975 {
976 return GL_FRAMEBUFFER_UNSUPPORTED;
977 }
978
979 if (mState.mWebGLDepthStencilAttachment.isAttached())
980 {
981 if (mState.mWebGLDepthStencilAttachment.getDepthSize() == 0 ||
982 mState.mWebGLDepthStencilAttachment.getStencilSize() == 0)
983 {
984 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
985 }
Martin Radev9bc9a322017-07-21 14:28:17 +0300986
987 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment,
988 &mState.mWebGLDepthStencilAttachment))
989 {
990 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
991 }
Jamie Madilla02315b2017-02-23 14:14:47 -0500992 }
993 else if (mState.mStencilAttachment.isAttached() &&
994 mState.mStencilAttachment.getDepthSize() > 0)
995 {
996 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
997 }
998 else if (mState.mDepthAttachment.isAttached() &&
999 mState.mDepthAttachment.getStencilSize() > 0)
1000 {
1001 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1002 }
1003 }
1004
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001005 // ES3.1(section 9.4) requires that if no image is attached to the framebuffer, and either the
1006 // value of the framebuffer's FRAMEBUFFER_DEFAULT_WIDTH or FRAMEBUFFER_DEFAULT_HEIGHT parameters
1007 // is zero, the framebuffer is considered incomplete.
JiangYizhou461d9a32017-01-04 16:37:26 +08001008 GLint defaultWidth = mState.getDefaultWidth();
1009 GLint defaultHeight = mState.getDefaultHeight();
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001010 if (!hasAttachments && (defaultWidth == 0 || defaultHeight == 0))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001011 {
1012 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001013 }
1014
Geoff Langa0e0aeb2017-04-12 15:06:29 -04001015 // In ES 2.0 and WebGL, all color attachments must have the same width and height.
Jamie Madillcc86d642015-11-24 13:00:07 -05001016 // In ES 3.0, there is no such restriction.
Geoff Langa0e0aeb2017-04-12 15:06:29 -04001017 if ((state.getClientMajorVersion() < 3 || state.getExtensions().webglCompatibility) &&
1018 !mState.attachmentsHaveSameDimensions())
Jamie Madillcc86d642015-11-24 13:00:07 -05001019 {
1020 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
1021 }
1022
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001023 // ES3.1(section 9.4) requires that if the attached images are a mix of renderbuffers and
1024 // textures, the value of TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all attached textures.
JiangYizhou461d9a32017-01-04 16:37:26 +08001025 if (fixedSampleLocations.valid() && hasRenderbuffer && !fixedSampleLocations.value())
1026 {
1027 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1028 }
1029
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001030 syncState(context);
Jamie Madillcc86d642015-11-24 13:00:07 -05001031 if (!mImpl->checkStatus())
1032 {
1033 return GL_FRAMEBUFFER_UNSUPPORTED;
1034 }
1035
1036 return GL_FRAMEBUFFER_COMPLETE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001037}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001038
Jamie Madill4928b7c2017-06-20 12:57:39 -04001039Error Framebuffer::discard(const Context *context, size_t count, const GLenum *attachments)
Austin Kinross08332632015-05-05 13:35:47 -07001040{
Jamie Madill4928b7c2017-06-20 12:57:39 -04001041 return mImpl->discard(context, count, attachments);
Austin Kinross08332632015-05-05 13:35:47 -07001042}
1043
Jamie Madill4928b7c2017-06-20 12:57:39 -04001044Error Framebuffer::invalidate(const Context *context, size_t count, const GLenum *attachments)
Jamie Madill2d96b9e2014-08-29 15:46:47 -04001045{
Jamie Madill4928b7c2017-06-20 12:57:39 -04001046 return mImpl->invalidate(context, count, attachments);
Jamie Madill2d96b9e2014-08-29 15:46:47 -04001047}
1048
Jamie Madill4928b7c2017-06-20 12:57:39 -04001049Error Framebuffer::invalidateSub(const Context *context,
1050 size_t count,
1051 const GLenum *attachments,
1052 const gl::Rectangle &area)
Jamie Madill400a4412014-08-29 15:46:45 -04001053{
Jamie Madill4928b7c2017-06-20 12:57:39 -04001054 return mImpl->invalidateSub(context, count, attachments, area);
Jamie Madill400a4412014-08-29 15:46:45 -04001055}
1056
Jamie Madillc564c072017-06-01 12:45:42 -04001057Error Framebuffer::clear(const gl::Context *context, GLbitfield mask)
Geoff Langb04dc822014-12-01 12:02:02 -05001058{
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001059 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -05001060 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001061 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001062 }
1063
Jamie Madill8415b5f2016-04-26 13:41:39 -04001064 return mImpl->clear(context, mask);
Geoff Langb04dc822014-12-01 12:02:02 -05001065}
1066
Jamie Madillc564c072017-06-01 12:45:42 -04001067Error Framebuffer::clearBufferfv(const gl::Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001068 GLenum buffer,
1069 GLint drawbuffer,
1070 const GLfloat *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001071{
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001072 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -05001073 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001074 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001075 }
1076
Jamie Madill8415b5f2016-04-26 13:41:39 -04001077 return mImpl->clearBufferfv(context, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -05001078}
1079
Jamie Madillc564c072017-06-01 12:45:42 -04001080Error Framebuffer::clearBufferuiv(const gl::Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001081 GLenum buffer,
1082 GLint drawbuffer,
1083 const GLuint *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001084{
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001085 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -05001086 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001087 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001088 }
1089
Jamie Madill8415b5f2016-04-26 13:41:39 -04001090 return mImpl->clearBufferuiv(context, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -05001091}
1092
Jamie Madillc564c072017-06-01 12:45:42 -04001093Error Framebuffer::clearBufferiv(const gl::Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001094 GLenum buffer,
1095 GLint drawbuffer,
1096 const GLint *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001097{
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001098 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -05001099 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001100 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001101 }
1102
Jamie Madill8415b5f2016-04-26 13:41:39 -04001103 return mImpl->clearBufferiv(context, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -05001104}
1105
Jamie Madillc564c072017-06-01 12:45:42 -04001106Error Framebuffer::clearBufferfi(const gl::Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001107 GLenum buffer,
1108 GLint drawbuffer,
1109 GLfloat depth,
1110 GLint stencil)
Geoff Langb04dc822014-12-01 12:02:02 -05001111{
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001112 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -05001113 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001114 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001115 }
1116
Jamie Madill8415b5f2016-04-26 13:41:39 -04001117 return mImpl->clearBufferfi(context, buffer, drawbuffer, depth, stencil);
Geoff Langb04dc822014-12-01 12:02:02 -05001118}
1119
Jamie Madill4928b7c2017-06-20 12:57:39 -04001120GLenum Framebuffer::getImplementationColorReadFormat(const Context *context) const
Geoff Langbce529e2014-12-01 12:48:41 -05001121{
Jamie Madill4928b7c2017-06-20 12:57:39 -04001122 return mImpl->getImplementationColorReadFormat(context);
Geoff Langbce529e2014-12-01 12:48:41 -05001123}
1124
Jamie Madill4928b7c2017-06-20 12:57:39 -04001125GLenum Framebuffer::getImplementationColorReadType(const Context *context) const
Geoff Langbce529e2014-12-01 12:48:41 -05001126{
Jamie Madill4928b7c2017-06-20 12:57:39 -04001127 return mImpl->getImplementationColorReadType(context);
Geoff Langbce529e2014-12-01 12:48:41 -05001128}
1129
Jamie Madillc564c072017-06-01 12:45:42 -04001130Error Framebuffer::readPixels(const gl::Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001131 const Rectangle &area,
Jamie Madill1b94d432015-08-07 13:23:23 -04001132 GLenum format,
1133 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001134 void *pixels) const
Geoff Langbce529e2014-12-01 12:48:41 -05001135{
Jamie Madill362876b2016-06-16 14:46:59 -04001136 ANGLE_TRY(mImpl->readPixels(context, area, format, type, pixels));
Geoff Lang520c4ae2015-05-05 13:12:36 -04001137
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001138 Buffer *unpackBuffer = context->getGLState().getUnpackState().pixelBuffer.get();
Geoff Lang520c4ae2015-05-05 13:12:36 -04001139 if (unpackBuffer)
1140 {
1141 unpackBuffer->onPixelUnpack();
1142 }
1143
Jamie Madill362876b2016-06-16 14:46:59 -04001144 return NoError();
Geoff Langbce529e2014-12-01 12:48:41 -05001145}
1146
Jamie Madillc564c072017-06-01 12:45:42 -04001147Error Framebuffer::blit(const gl::Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001148 const Rectangle &sourceArea,
1149 const Rectangle &destArea,
Geoff Lang242468f2015-09-24 14:15:41 -04001150 GLbitfield mask,
Jamie Madill8415b5f2016-04-26 13:41:39 -04001151 GLenum filter)
Geoff Lang54bd5a42014-12-01 12:51:04 -05001152{
He Yunchao6be602d2016-12-22 14:33:07 +08001153 GLbitfield blitMask = mask;
1154
1155 // Note that blitting is called against draw framebuffer.
1156 // See the code in gl::Context::blitFramebuffer.
1157 if ((mask & GL_COLOR_BUFFER_BIT) && !hasEnabledDrawBuffer())
1158 {
1159 blitMask &= ~GL_COLOR_BUFFER_BIT;
1160 }
1161
1162 if ((mask & GL_STENCIL_BUFFER_BIT) && mState.getStencilAttachment() == nullptr)
1163 {
1164 blitMask &= ~GL_STENCIL_BUFFER_BIT;
1165 }
1166
1167 if ((mask & GL_DEPTH_BUFFER_BIT) && mState.getDepthAttachment() == nullptr)
1168 {
1169 blitMask &= ~GL_DEPTH_BUFFER_BIT;
1170 }
1171
1172 if (!blitMask)
1173 {
1174 return NoError();
1175 }
1176
1177 return mImpl->blit(context, sourceArea, destArea, blitMask, filter);
Geoff Lang54bd5a42014-12-01 12:51:04 -05001178}
1179
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001180int Framebuffer::getSamples(const Context *context)
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001181{
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001182 if (complete(context))
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001183 {
Jamie Madill9c335862017-07-18 11:51:38 -04001184 return getCachedSamples(context);
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001185 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001186
1187 return 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001188}
1189
Jamie Madill9c335862017-07-18 11:51:38 -04001190int Framebuffer::getCachedSamples(const Context *context)
1191{
1192 // For a complete framebuffer, all attachments must have the same sample count.
1193 // In this case return the first nonzero sample size.
1194 const auto *firstNonNullAttachment = mState.getFirstNonNullAttachment();
1195 if (firstNonNullAttachment)
1196 {
1197 ASSERT(firstNonNullAttachment->isAttached());
1198 return firstNonNullAttachment->getSamples();
1199 }
1200
1201 // No attachments found.
1202 return 0;
1203}
1204
Corentin Wallezccab69d2017-01-27 16:57:15 -05001205Error Framebuffer::getSamplePosition(size_t index, GLfloat *xy) const
1206{
1207 ANGLE_TRY(mImpl->getSamplePosition(index, xy));
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001208 return NoError();
Corentin Wallezccab69d2017-01-27 16:57:15 -05001209}
1210
Jamie Madille261b442014-06-25 12:42:21 -04001211bool Framebuffer::hasValidDepthStencil() const
1212{
Jamie Madill48ef11b2016-04-27 15:21:52 -04001213 return mState.getDepthStencilAttachment() != nullptr;
Jamie Madille261b442014-06-25 12:42:21 -04001214}
1215
Jamie Madilla02315b2017-02-23 14:14:47 -05001216void Framebuffer::setAttachment(const Context *context,
1217 GLenum type,
Jamie Madill2d06b732015-04-20 12:53:28 -04001218 GLenum binding,
1219 const ImageIndex &textureIndex,
1220 FramebufferAttachmentObject *resource)
Geoff Langab75a052014-10-15 12:56:37 -04001221{
Martin Radev5dae57b2017-07-14 16:15:55 +03001222 setAttachment(context, type, binding, textureIndex, resource,
1223 FramebufferAttachment::kDefaultNumViews,
1224 FramebufferAttachment::kDefaultBaseViewIndex,
1225 FramebufferAttachment::kDefaultMultiviewLayout,
1226 FramebufferAttachment::kDefaultViewportOffsets);
1227}
1228
1229void Framebuffer::setAttachment(const Context *context,
1230 GLenum type,
1231 GLenum binding,
1232 const ImageIndex &textureIndex,
1233 FramebufferAttachmentObject *resource,
1234 GLsizei numViews,
1235 GLuint baseViewIndex,
1236 GLenum multiviewLayout,
1237 const GLint *viewportOffsets)
1238{
Jamie Madilla02315b2017-02-23 14:14:47 -05001239 // Context may be null in unit tests.
1240 if (!context || !context->isWebGL1())
1241 {
Martin Radev5dae57b2017-07-14 16:15:55 +03001242 setAttachmentImpl(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
1243 multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001244 return;
1245 }
1246
1247 switch (binding)
1248 {
1249 case GL_DEPTH_STENCIL:
1250 case GL_DEPTH_STENCIL_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001251 mState.mWebGLDepthStencilAttachment.attach(context, type, binding, textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001252 resource, numViews, baseViewIndex,
1253 multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001254 break;
1255 case GL_DEPTH:
1256 case GL_DEPTH_ATTACHMENT:
Martin Radev5dae57b2017-07-14 16:15:55 +03001257 mState.mWebGLDepthAttachment.attach(context, type, binding, textureIndex, resource,
1258 numViews, baseViewIndex, multiviewLayout,
1259 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001260 break;
1261 case GL_STENCIL:
1262 case GL_STENCIL_ATTACHMENT:
Martin Radev5dae57b2017-07-14 16:15:55 +03001263 mState.mWebGLStencilAttachment.attach(context, type, binding, textureIndex, resource,
1264 numViews, baseViewIndex, multiviewLayout,
1265 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001266 break;
1267 default:
Martin Radev5dae57b2017-07-14 16:15:55 +03001268 setAttachmentImpl(context, type, binding, textureIndex, resource, numViews,
1269 baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001270 return;
1271 }
1272
Martin Radev5dae57b2017-07-14 16:15:55 +03001273 commitWebGL1DepthStencilIfConsistent(context, numViews, baseViewIndex, multiviewLayout,
1274 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001275}
1276
Martin Radev82ef7742017-08-08 17:44:58 +03001277void Framebuffer::setAttachmentMultiviewLayered(const Context *context,
1278 GLenum type,
1279 GLenum binding,
1280 const ImageIndex &textureIndex,
1281 FramebufferAttachmentObject *resource,
1282 GLsizei numViews,
1283 GLint baseViewIndex)
1284{
1285 setAttachment(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
1286 GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE,
1287 FramebufferAttachment::kDefaultViewportOffsets);
1288}
1289
Martin Radev5dae57b2017-07-14 16:15:55 +03001290void Framebuffer::setAttachmentMultiviewSideBySide(const Context *context,
1291 GLenum type,
1292 GLenum binding,
1293 const ImageIndex &textureIndex,
1294 FramebufferAttachmentObject *resource,
1295 GLsizei numViews,
1296 const GLint *viewportOffsets)
1297{
1298 setAttachment(context, type, binding, textureIndex, resource, numViews,
1299 FramebufferAttachment::kDefaultBaseViewIndex,
1300 GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, viewportOffsets);
1301}
1302
1303void Framebuffer::commitWebGL1DepthStencilIfConsistent(const Context *context,
1304 GLsizei numViews,
1305 GLuint baseViewIndex,
1306 GLenum multiviewLayout,
1307 const GLint *viewportOffsets)
Jamie Madilla02315b2017-02-23 14:14:47 -05001308{
1309 int count = 0;
1310
1311 std::array<FramebufferAttachment *, 3> attachments = {{&mState.mWebGLDepthStencilAttachment,
1312 &mState.mWebGLDepthAttachment,
1313 &mState.mWebGLStencilAttachment}};
1314 for (FramebufferAttachment *attachment : attachments)
1315 {
1316 if (attachment->isAttached())
1317 {
1318 count++;
1319 }
1320 }
1321
1322 mState.mWebGLDepthStencilConsistent = (count <= 1);
1323 if (!mState.mWebGLDepthStencilConsistent)
1324 {
1325 // Inconsistent.
1326 return;
1327 }
1328
Geoff Lange466c552017-03-17 15:24:12 -04001329 auto getImageIndexIfTextureAttachment = [](const FramebufferAttachment &attachment) {
1330 if (attachment.type() == GL_TEXTURE)
1331 {
1332 return attachment.getTextureImageIndex();
1333 }
1334 else
1335 {
1336 return ImageIndex::MakeInvalid();
1337 }
1338 };
1339
Jamie Madilla02315b2017-02-23 14:14:47 -05001340 if (mState.mWebGLDepthAttachment.isAttached())
1341 {
1342 const auto &depth = mState.mWebGLDepthAttachment;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001343 setAttachmentImpl(context, depth.type(), GL_DEPTH_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001344 getImageIndexIfTextureAttachment(depth), depth.getResource(), numViews,
1345 baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001346 setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex::MakeInvalid(),
Martin Radev5dae57b2017-07-14 16:15:55 +03001347 nullptr, numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001348 }
1349 else if (mState.mWebGLStencilAttachment.isAttached())
1350 {
1351 const auto &stencil = mState.mWebGLStencilAttachment;
Martin Radev5dae57b2017-07-14 16:15:55 +03001352 setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex::MakeInvalid(), nullptr,
1353 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001354 setAttachmentImpl(context, stencil.type(), GL_STENCIL_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001355 getImageIndexIfTextureAttachment(stencil), stencil.getResource(),
1356 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001357 }
1358 else if (mState.mWebGLDepthStencilAttachment.isAttached())
1359 {
1360 const auto &depthStencil = mState.mWebGLDepthStencilAttachment;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001361 setAttachmentImpl(context, depthStencil.type(), GL_DEPTH_ATTACHMENT,
Geoff Lange466c552017-03-17 15:24:12 -04001362 getImageIndexIfTextureAttachment(depthStencil),
Martin Radev5dae57b2017-07-14 16:15:55 +03001363 depthStencil.getResource(), numViews, baseViewIndex, multiviewLayout,
1364 viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001365 setAttachmentImpl(context, depthStencil.type(), GL_STENCIL_ATTACHMENT,
Geoff Lange466c552017-03-17 15:24:12 -04001366 getImageIndexIfTextureAttachment(depthStencil),
Martin Radev5dae57b2017-07-14 16:15:55 +03001367 depthStencil.getResource(), numViews, baseViewIndex, multiviewLayout,
1368 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001369 }
1370 else
1371 {
Martin Radev5dae57b2017-07-14 16:15:55 +03001372 setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex::MakeInvalid(), nullptr,
1373 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001374 setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex::MakeInvalid(),
Martin Radev5dae57b2017-07-14 16:15:55 +03001375 nullptr, numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001376 }
1377}
1378
Jamie Madill4928b7c2017-06-20 12:57:39 -04001379void Framebuffer::setAttachmentImpl(const Context *context,
1380 GLenum type,
Jamie Madilla02315b2017-02-23 14:14:47 -05001381 GLenum binding,
1382 const ImageIndex &textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001383 FramebufferAttachmentObject *resource,
1384 GLsizei numViews,
1385 GLuint baseViewIndex,
1386 GLenum multiviewLayout,
1387 const GLint *viewportOffsets)
Jamie Madilla02315b2017-02-23 14:14:47 -05001388{
Jamie Madilla02315b2017-02-23 14:14:47 -05001389 switch (binding)
1390 {
Jamie Madillb8126692017-04-05 11:22:17 -04001391 case GL_DEPTH_STENCIL:
1392 case GL_DEPTH_STENCIL_ATTACHMENT:
1393 {
1394 // ensure this is a legitimate depth+stencil format
1395 FramebufferAttachmentObject *attachmentObj = resource;
1396 if (resource)
1397 {
Jamie Madill4fd95d52017-04-05 11:22:18 -04001398 const Format &format = resource->getAttachmentFormat(binding, textureIndex);
Jamie Madillb8126692017-04-05 11:22:17 -04001399 if (format.info->depthBits == 0 || format.info->stencilBits == 0)
1400 {
1401 // Attaching nullptr detaches the current attachment.
1402 attachmentObj = nullptr;
1403 }
1404 }
1405
Jamie Madill4928b7c2017-06-20 12:57:39 -04001406 updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
Jamie Madillb8126692017-04-05 11:22:17 -04001407 &mDirtyDepthAttachmentBinding, type, binding, textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001408 attachmentObj, numViews, baseViewIndex, multiviewLayout,
1409 viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001410 updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
Jamie Madillb8126692017-04-05 11:22:17 -04001411 &mDirtyStencilAttachmentBinding, type, binding, textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001412 attachmentObj, numViews, baseViewIndex, multiviewLayout,
1413 viewportOffsets);
Jamie Madillb8126692017-04-05 11:22:17 -04001414 return;
1415 }
1416
Jamie Madilla02315b2017-02-23 14:14:47 -05001417 case GL_DEPTH:
1418 case GL_DEPTH_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001419 updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001420 &mDirtyDepthAttachmentBinding, type, binding, textureIndex, resource,
1421 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madill2d06b732015-04-20 12:53:28 -04001422 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001423
Jamie Madilla02315b2017-02-23 14:14:47 -05001424 case GL_STENCIL:
1425 case GL_STENCIL_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001426 updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001427 &mDirtyStencilAttachmentBinding, type, binding, textureIndex, resource,
1428 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001429 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001430
Jamie Madilla02315b2017-02-23 14:14:47 -05001431 case GL_BACK:
Martin Radev5dae57b2017-07-14 16:15:55 +03001432 mState.mColorAttachments[0].attach(context, type, binding, textureIndex, resource,
1433 numViews, baseViewIndex, multiviewLayout,
1434 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001435 mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0);
1436 // No need for a resource binding for the default FBO, it's always complete.
1437 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001438
Jamie Madilla02315b2017-02-23 14:14:47 -05001439 default:
1440 {
1441 size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
1442 ASSERT(colorIndex < mState.mColorAttachments.size());
Jamie Madillb8126692017-04-05 11:22:17 -04001443 size_t dirtyBit = DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001444 updateAttachment(context, &mState.mColorAttachments[colorIndex], dirtyBit,
Jamie Madillb8126692017-04-05 11:22:17 -04001445 &mDirtyColorAttachmentBindings[colorIndex], type, binding,
Martin Radev5dae57b2017-07-14 16:15:55 +03001446 textureIndex, resource, numViews, baseViewIndex, multiviewLayout,
1447 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001448
Corentin Walleze7557742017-06-01 13:09:57 -04001449 // TODO(jmadill): ASSERT instead of checking the attachment exists in
1450 // formsRenderingFeedbackLoopWith
Jamie Madilla02315b2017-02-23 14:14:47 -05001451 bool enabled = (type != GL_NONE && getDrawBufferState(colorIndex) != GL_NONE);
1452 mState.mEnabledDrawBuffers.set(colorIndex, enabled);
Jamie Madill2d06b732015-04-20 12:53:28 -04001453 }
Jamie Madilla02315b2017-02-23 14:14:47 -05001454 break;
Geoff Langab75a052014-10-15 12:56:37 -04001455 }
1456}
1457
Jamie Madill4928b7c2017-06-20 12:57:39 -04001458void Framebuffer::updateAttachment(const Context *context,
1459 FramebufferAttachment *attachment,
Jamie Madillb8126692017-04-05 11:22:17 -04001460 size_t dirtyBit,
1461 OnAttachmentDirtyBinding *onDirtyBinding,
1462 GLenum type,
1463 GLenum binding,
1464 const ImageIndex &textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001465 FramebufferAttachmentObject *resource,
1466 GLsizei numViews,
1467 GLuint baseViewIndex,
1468 GLenum multiviewLayout,
1469 const GLint *viewportOffsets)
Jamie Madillb8126692017-04-05 11:22:17 -04001470{
Martin Radev5dae57b2017-07-14 16:15:55 +03001471 attachment->attach(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
1472 multiviewLayout, viewportOffsets);
Jamie Madillb8126692017-04-05 11:22:17 -04001473 mDirtyBits.set(dirtyBit);
1474 BindResourceChannel(onDirtyBinding, resource);
1475}
1476
Jamie Madilla02315b2017-02-23 14:14:47 -05001477void Framebuffer::resetAttachment(const Context *context, GLenum binding)
Jamie Madill2d06b732015-04-20 12:53:28 -04001478{
Jamie Madilla02315b2017-02-23 14:14:47 -05001479 setAttachment(context, GL_NONE, binding, ImageIndex::MakeInvalid(), nullptr);
Jamie Madill2d06b732015-04-20 12:53:28 -04001480}
1481
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001482void Framebuffer::syncState(const Context *context)
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001483{
1484 if (mDirtyBits.any())
1485 {
Jamie Madillc564c072017-06-01 12:45:42 -04001486 mImpl->syncState(context, mDirtyBits);
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001487 mDirtyBits.reset();
Corentin Wallezccab69d2017-01-27 16:57:15 -05001488 if (mId != 0)
1489 {
1490 mCachedStatus.reset();
1491 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001492 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001493}
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001494
Jamie Madill1e5499d2017-04-05 11:22:16 -04001495void Framebuffer::signal(uint32_t token)
Jamie Madill51f40ec2016-06-15 14:06:00 -04001496{
Jamie Madill362876b2016-06-16 14:46:59 -04001497 // TOOD(jmadill): Make this only update individual attachments to do less work.
1498 mCachedStatus.reset();
Jamie Madill51f40ec2016-06-15 14:06:00 -04001499}
1500
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001501bool Framebuffer::complete(const Context *context)
Jamie Madill51f40ec2016-06-15 14:06:00 -04001502{
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001503 return (checkStatus(context) == GL_FRAMEBUFFER_COMPLETE);
1504}
1505
1506bool Framebuffer::cachedComplete() const
1507{
1508 return (mCachedStatus.valid() && mCachedStatus == GL_FRAMEBUFFER_COMPLETE);
Jamie Madill51f40ec2016-06-15 14:06:00 -04001509}
1510
Jamie Madilla4595b82017-01-11 17:36:34 -05001511bool Framebuffer::formsRenderingFeedbackLoopWith(const State &state) const
1512{
1513 const Program *program = state.getProgram();
1514
1515 // TODO(jmadill): Default framebuffer feedback loops.
1516 if (mId == 0)
1517 {
1518 return false;
1519 }
1520
1521 // The bitset will skip inactive draw buffers.
Jamie Madill6de51852017-04-12 09:53:01 -04001522 for (size_t drawIndex : mState.mEnabledDrawBuffers)
Jamie Madilla4595b82017-01-11 17:36:34 -05001523 {
Jamie Madill5aca1932017-07-21 12:22:01 -04001524 const FramebufferAttachment &attachment = mState.mColorAttachments[drawIndex];
1525 ASSERT(attachment.isAttached());
1526 if (attachment.type() == GL_TEXTURE)
Jamie Madilla4595b82017-01-11 17:36:34 -05001527 {
1528 // Validate the feedback loop.
Jamie Madill5aca1932017-07-21 12:22:01 -04001529 if (program->samplesFromTexture(state, attachment.id()))
Jamie Madilla4595b82017-01-11 17:36:34 -05001530 {
1531 return true;
1532 }
1533 }
1534 }
1535
Jamie Madill1d37bc52017-02-02 19:59:58 -05001536 // Validate depth-stencil feedback loop.
1537 const auto &dsState = state.getDepthStencilState();
1538
1539 // We can skip the feedback loop checks if depth/stencil is masked out or disabled.
1540 const FramebufferAttachment *depth = getDepthbuffer();
1541 if (depth && depth->type() == GL_TEXTURE && dsState.depthTest && dsState.depthMask)
1542 {
1543 if (program->samplesFromTexture(state, depth->id()))
1544 {
1545 return true;
1546 }
1547 }
1548
1549 // Note: we assume the front and back masks are the same for WebGL.
1550 const FramebufferAttachment *stencil = getStencilbuffer();
1551 ASSERT(dsState.stencilBackWritemask == dsState.stencilWritemask);
1552 if (stencil && stencil->type() == GL_TEXTURE && dsState.stencilTest &&
1553 dsState.stencilWritemask != 0)
1554 {
1555 // Skip the feedback loop check if depth/stencil point to the same resource.
1556 if (!depth || *stencil != *depth)
1557 {
1558 if (program->samplesFromTexture(state, stencil->id()))
1559 {
1560 return true;
1561 }
1562 }
1563 }
1564
Jamie Madilla4595b82017-01-11 17:36:34 -05001565 return false;
1566}
1567
Jamie Madillfd3dd432017-02-02 19:59:59 -05001568bool Framebuffer::formsCopyingFeedbackLoopWith(GLuint copyTextureID,
1569 GLint copyTextureLevel,
1570 GLint copyTextureLayer) const
Jamie Madillf695a3a2017-01-11 17:36:35 -05001571{
1572 if (mId == 0)
1573 {
1574 // It seems impossible to form a texture copying feedback loop with the default FBO.
1575 return false;
1576 }
1577
1578 const FramebufferAttachment *readAttachment = getReadColorbuffer();
1579 ASSERT(readAttachment);
1580
1581 if (readAttachment->isTextureWithId(copyTextureID))
1582 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05001583 const auto &imageIndex = readAttachment->getTextureImageIndex();
1584 if (imageIndex.mipIndex == copyTextureLevel)
Jamie Madillf695a3a2017-01-11 17:36:35 -05001585 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05001586 // Check 3D/Array texture layers.
1587 return imageIndex.layerIndex == ImageIndex::ENTIRE_LEVEL ||
1588 copyTextureLayer == ImageIndex::ENTIRE_LEVEL ||
1589 imageIndex.layerIndex == copyTextureLayer;
Jamie Madillf695a3a2017-01-11 17:36:35 -05001590 }
1591 }
1592 return false;
1593}
1594
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001595GLint Framebuffer::getDefaultWidth() const
1596{
1597 return mState.getDefaultWidth();
1598}
1599
1600GLint Framebuffer::getDefaultHeight() const
1601{
1602 return mState.getDefaultHeight();
1603}
1604
1605GLint Framebuffer::getDefaultSamples() const
1606{
1607 return mState.getDefaultSamples();
1608}
1609
1610GLboolean Framebuffer::getDefaultFixedSampleLocations() const
1611{
1612 return mState.getDefaultFixedSampleLocations();
1613}
1614
1615void Framebuffer::setDefaultWidth(GLint defaultWidth)
1616{
1617 mState.mDefaultWidth = defaultWidth;
1618 mDirtyBits.set(DIRTY_BIT_DEFAULT_WIDTH);
1619}
1620
1621void Framebuffer::setDefaultHeight(GLint defaultHeight)
1622{
1623 mState.mDefaultHeight = defaultHeight;
1624 mDirtyBits.set(DIRTY_BIT_DEFAULT_HEIGHT);
1625}
1626
1627void Framebuffer::setDefaultSamples(GLint defaultSamples)
1628{
1629 mState.mDefaultSamples = defaultSamples;
1630 mDirtyBits.set(DIRTY_BIT_DEFAULT_SAMPLES);
1631}
1632
1633void Framebuffer::setDefaultFixedSampleLocations(GLboolean defaultFixedSampleLocations)
1634{
1635 mState.mDefaultFixedSampleLocations = defaultFixedSampleLocations;
1636 mDirtyBits.set(DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS);
1637}
1638
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001639// TODO(jmadill): Remove this kludge.
1640GLenum Framebuffer::checkStatus(const ValidationContext *context)
1641{
1642 return checkStatus(static_cast<const Context *>(context));
1643}
1644
1645int Framebuffer::getSamples(const ValidationContext *context)
1646{
1647 return getSamples(static_cast<const Context *>(context));
1648}
1649
Martin Radev14a26ae2017-07-24 15:56:29 +03001650GLsizei Framebuffer::getNumViews() const
1651{
Martin Radev5c00d0d2017-08-07 10:06:59 +03001652 return mState.getNumViews();
Martin Radev14a26ae2017-07-24 15:56:29 +03001653}
1654
Martin Radev878c8b12017-07-28 09:51:04 +03001655const std::vector<Offset> *Framebuffer::getViewportOffsets() const
1656{
Martin Radev5c00d0d2017-08-07 10:06:59 +03001657 return mState.getViewportOffsets();
Martin Radev878c8b12017-07-28 09:51:04 +03001658}
1659
1660GLenum Framebuffer::getMultiviewLayout() const
1661{
Martin Radev5c00d0d2017-08-07 10:06:59 +03001662 return mState.getMultiviewLayout();
Martin Radev878c8b12017-07-28 09:51:04 +03001663}
1664
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001665} // namespace gl