blob: 66fbe8bb4dba4fa9480e3034d0b888870db939ca [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 Madill8693bdb2017-09-02 15:32:14 -0400600bool Framebuffer::detachTexture(const Context *context, GLuint textureId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000601{
Jamie Madill8693bdb2017-09-02 15:32:14 -0400602 return detachResourceById(context, GL_TEXTURE, textureId);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000603}
604
Jamie Madill8693bdb2017-09-02 15:32:14 -0400605bool Framebuffer::detachRenderbuffer(const Context *context, GLuint renderbufferId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000606{
Jamie Madill8693bdb2017-09-02 15:32:14 -0400607 return detachResourceById(context, GL_RENDERBUFFER, renderbufferId);
Jamie Madilld1405e52015-03-05 15:41:39 -0500608}
Jamie Madille261b442014-06-25 12:42:21 -0400609
Jamie Madill8693bdb2017-09-02 15:32:14 -0400610bool Framebuffer::detachResourceById(const Context *context, GLenum resourceType, GLuint resourceId)
Jamie Madilld1405e52015-03-05 15:41:39 -0500611{
Jamie Madill8693bdb2017-09-02 15:32:14 -0400612 bool found = false;
613
Jamie Madill362876b2016-06-16 14:46:59 -0400614 for (size_t colorIndex = 0; colorIndex < mState.mColorAttachments.size(); ++colorIndex)
Jamie Madilld1405e52015-03-05 15:41:39 -0500615 {
Jamie Madill8693bdb2017-09-02 15:32:14 -0400616 if (detachMatchingAttachment(context, &mState.mColorAttachments[colorIndex], resourceType,
617 resourceId, DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex))
618 {
619 found = true;
620 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000621 }
622
Jamie Madilla02315b2017-02-23 14:14:47 -0500623 if (context->isWebGL1())
624 {
625 const std::array<FramebufferAttachment *, 3> attachments = {
626 {&mState.mWebGLDepthStencilAttachment, &mState.mWebGLDepthAttachment,
627 &mState.mWebGLStencilAttachment}};
628 for (FramebufferAttachment *attachment : attachments)
629 {
630 if (attachment->isAttached() && attachment->type() == resourceType &&
631 attachment->id() == resourceId)
632 {
633 resetAttachment(context, attachment->getBinding());
Jamie Madill8693bdb2017-09-02 15:32:14 -0400634 found = true;
Jamie Madilla02315b2017-02-23 14:14:47 -0500635 }
636 }
637 }
638 else
639 {
Jamie Madill8693bdb2017-09-02 15:32:14 -0400640 if (detachMatchingAttachment(context, &mState.mDepthAttachment, resourceType, resourceId,
641 DIRTY_BIT_DEPTH_ATTACHMENT))
642 {
643 found = true;
644 }
645 if (detachMatchingAttachment(context, &mState.mStencilAttachment, resourceType, resourceId,
646 DIRTY_BIT_STENCIL_ATTACHMENT))
647 {
648 found = true;
649 }
Jamie Madilla02315b2017-02-23 14:14:47 -0500650 }
Jamie Madill8693bdb2017-09-02 15:32:14 -0400651
652 return found;
Jamie Madill362876b2016-06-16 14:46:59 -0400653}
654
Jamie Madill8693bdb2017-09-02 15:32:14 -0400655bool Framebuffer::detachMatchingAttachment(const Context *context,
Jamie Madill4928b7c2017-06-20 12:57:39 -0400656 FramebufferAttachment *attachment,
Jamie Madill362876b2016-06-16 14:46:59 -0400657 GLenum matchType,
658 GLuint matchId,
659 size_t dirtyBit)
660{
661 if (attachment->isAttached() && attachment->type() == matchType && attachment->id() == matchId)
662 {
Jamie Madill4928b7c2017-06-20 12:57:39 -0400663 attachment->detach(context);
Jamie Madill362876b2016-06-16 14:46:59 -0400664 mDirtyBits.set(dirtyBit);
Jamie Madill8693bdb2017-09-02 15:32:14 -0400665 return true;
Jamie Madill362876b2016-06-16 14:46:59 -0400666 }
Jamie Madill8693bdb2017-09-02 15:32:14 -0400667
668 return false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000669}
670
Corentin Wallez37c39792015-08-20 14:19:46 -0400671const FramebufferAttachment *Framebuffer::getColorbuffer(size_t colorAttachment) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000672{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400673 return mState.getColorAttachment(colorAttachment);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000674}
675
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400676const FramebufferAttachment *Framebuffer::getDepthbuffer() const
Geoff Lang646559f2013-08-15 11:08:15 -0400677{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400678 return mState.getDepthAttachment();
Geoff Lang646559f2013-08-15 11:08:15 -0400679}
680
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400681const FramebufferAttachment *Framebuffer::getStencilbuffer() const
682{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400683 return mState.getStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400684}
685
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400686const FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
687{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400688 return mState.getDepthStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400689}
690
691const FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000692{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400693 return mState.getDepthOrStencilAttachment();
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000694}
695
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500696const FramebufferAttachment *Framebuffer::getStencilOrDepthStencilAttachment() const
697{
698 return mState.getStencilOrDepthStencilAttachment();
699}
700
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400701const FramebufferAttachment *Framebuffer::getReadColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000702{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400703 return mState.getReadAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000704}
705
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000706GLenum Framebuffer::getReadColorbufferType() const
707{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400708 const FramebufferAttachment *readAttachment = mState.getReadAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400709 return (readAttachment != nullptr ? readAttachment->type() : GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000710}
711
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400712const FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000713{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400714 return mState.getFirstColorAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000715}
716
Jamie Madill6dd06ea2017-07-19 13:47:55 -0400717const FramebufferAttachment *Framebuffer::getFirstNonNullAttachment() const
718{
719 return mState.getFirstNonNullAttachment();
720}
721
Jamie Madill2d06b732015-04-20 12:53:28 -0400722const FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000723{
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400724 return mState.getAttachment(attachment);
Geoff Lang55ba29c2013-07-11 16:57:53 -0400725}
726
Geoff Langa15472a2015-08-11 11:48:03 -0400727size_t Framebuffer::getDrawbufferStateCount() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000728{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400729 return mState.mDrawBufferStates.size();
Geoff Langa15472a2015-08-11 11:48:03 -0400730}
731
732GLenum Framebuffer::getDrawBufferState(size_t drawBuffer) const
733{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400734 ASSERT(drawBuffer < mState.mDrawBufferStates.size());
735 return mState.mDrawBufferStates[drawBuffer];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000736}
737
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500738const std::vector<GLenum> &Framebuffer::getDrawBufferStates() const
739{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400740 return mState.getDrawBufferStates();
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500741}
742
Geoff Lang164d54e2014-12-01 10:55:33 -0500743void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000744{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400745 auto &drawStates = mState.mDrawBufferStates;
Jamie Madilld1405e52015-03-05 15:41:39 -0500746
747 ASSERT(count <= drawStates.size());
748 std::copy(buffers, buffers + count, drawStates.begin());
749 std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500750 mDirtyBits.set(DIRTY_BIT_DRAW_BUFFERS);
Jamie Madilla4595b82017-01-11 17:36:34 -0500751
752 mState.mEnabledDrawBuffers.reset();
753 for (size_t index = 0; index < count; ++index)
754 {
755 if (drawStates[index] != GL_NONE && mState.mColorAttachments[index].isAttached())
756 {
757 mState.mEnabledDrawBuffers.set(index);
758 }
759 }
Geoff Lang9dd95802014-12-01 11:12:59 -0500760}
761
Geoff Langa15472a2015-08-11 11:48:03 -0400762const FramebufferAttachment *Framebuffer::getDrawBuffer(size_t drawBuffer) const
763{
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400764 return mState.getDrawBuffer(drawBuffer);
Geoff Langa15472a2015-08-11 11:48:03 -0400765}
766
Geoff Lange0cff192017-05-30 13:04:56 -0400767GLenum Framebuffer::getDrawbufferWriteType(size_t drawBuffer) const
768{
769 const FramebufferAttachment *attachment = mState.getDrawBuffer(drawBuffer);
770 if (attachment == nullptr)
771 {
772 return GL_NONE;
773 }
774
775 GLenum componentType = attachment->getFormat().info->componentType;
776 switch (componentType)
777 {
778 case GL_INT:
779 case GL_UNSIGNED_INT:
780 return componentType;
781
782 default:
783 return GL_FLOAT;
784 }
785}
786
Geoff Langa15472a2015-08-11 11:48:03 -0400787bool Framebuffer::hasEnabledDrawBuffer() const
788{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400789 for (size_t drawbufferIdx = 0; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
Geoff Langa15472a2015-08-11 11:48:03 -0400790 {
791 if (getDrawBuffer(drawbufferIdx) != nullptr)
792 {
793 return true;
794 }
795 }
796
797 return false;
798}
799
Geoff Lang9dd95802014-12-01 11:12:59 -0500800GLenum Framebuffer::getReadBufferState() const
801{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400802 return mState.mReadBufferState;
Geoff Lang9dd95802014-12-01 11:12:59 -0500803}
804
805void Framebuffer::setReadBuffer(GLenum buffer)
806{
Jamie Madillb885e572015-02-03 16:16:04 -0500807 ASSERT(buffer == GL_BACK || buffer == GL_NONE ||
808 (buffer >= GL_COLOR_ATTACHMENT0 &&
Jamie Madill48ef11b2016-04-27 15:21:52 -0400809 (buffer - GL_COLOR_ATTACHMENT0) < mState.mColorAttachments.size()));
810 mState.mReadBufferState = buffer;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500811 mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000812}
813
Corentin Wallez37c39792015-08-20 14:19:46 -0400814size_t Framebuffer::getNumColorBuffers() const
815{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400816 return mState.mColorAttachments.size();
Corentin Wallez37c39792015-08-20 14:19:46 -0400817}
818
Jamie Madill0df8fe42015-11-24 16:10:24 -0500819bool Framebuffer::hasDepth() const
820{
Jamie Madill9c335862017-07-18 11:51:38 -0400821 return mState.hasDepth();
Jamie Madill0df8fe42015-11-24 16:10:24 -0500822}
823
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000824bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000825{
Jamie Madill9c335862017-07-18 11:51:38 -0400826 return mState.hasStencil();
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000827}
828
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000829bool Framebuffer::usingExtendedDrawBuffers() const
830{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400831 for (size_t drawbufferIdx = 1; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000832 {
Geoff Langa15472a2015-08-11 11:48:03 -0400833 if (getDrawBuffer(drawbufferIdx) != nullptr)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000834 {
835 return true;
836 }
837 }
838
839 return false;
840}
841
Geoff Lang9aded172017-04-05 11:07:56 -0400842void Framebuffer::invalidateCompletenessCache()
843{
844 if (mId != 0)
845 {
846 mCachedStatus.reset();
847 }
848}
849
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400850GLenum Framebuffer::checkStatus(const Context *context)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000851{
Corentin Wallezccab69d2017-01-27 16:57:15 -0500852 // The default framebuffer is always complete except when it is surfaceless in which
853 // case it is always unsupported. We return early because the default framebuffer may
854 // not be subject to the same rules as application FBOs. ie, it could have 0x0 size.
Geoff Lang528ce3c2014-12-01 10:44:07 -0500855 if (mId == 0)
856 {
Corentin Wallezccab69d2017-01-27 16:57:15 -0500857 ASSERT(mCachedStatus.valid());
858 ASSERT(mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE ||
859 mCachedStatus.value() == GL_FRAMEBUFFER_UNDEFINED_OES);
860 return mCachedStatus.value();
Geoff Lang528ce3c2014-12-01 10:44:07 -0500861 }
862
Jamie Madill362876b2016-06-16 14:46:59 -0400863 if (hasAnyDirtyBit() || !mCachedStatus.valid())
864 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400865 mCachedStatus = checkStatusImpl(context);
Jamie Madill362876b2016-06-16 14:46:59 -0400866 }
867
868 return mCachedStatus.value();
869}
870
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400871GLenum Framebuffer::checkStatusImpl(const Context *context)
Jamie Madill362876b2016-06-16 14:46:59 -0400872{
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400873 const ContextState &state = context->getContextState();
874
Jamie Madill362876b2016-06-16 14:46:59 -0400875 ASSERT(mId != 0);
876
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400877 bool hasAttachments = false;
878 Optional<unsigned int> colorbufferSize;
879 Optional<int> samples;
JiangYizhou461d9a32017-01-04 16:37:26 +0800880 Optional<GLboolean> fixedSampleLocations;
881 bool hasRenderbuffer = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000882
Martin Radev9bc9a322017-07-21 14:28:17 +0300883 const FramebufferAttachment *firstAttachment = getFirstNonNullAttachment();
884
Jamie Madill48ef11b2016-04-27 15:21:52 -0400885 for (const FramebufferAttachment &colorAttachment : mState.mColorAttachments)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000886 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400887 if (colorAttachment.isAttached())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000888 {
Geoff Lang9f10b772017-05-16 15:51:03 -0400889 if (!CheckAttachmentCompleteness(context, colorAttachment))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000890 {
891 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
892 }
daniel@transgaming.com01868132010-08-24 19:21:17 +0000893
Geoff Lang677bb6f2017-04-05 12:40:40 -0400894 const InternalFormat &format = *colorAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -0400895 if (format.depthBits > 0 || format.stencilBits > 0)
896 {
897 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
898 }
899
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400900 if (!CheckAttachmentSampleCompleteness(context, colorAttachment, true, &samples,
901 &fixedSampleLocations))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000902 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400903 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000904 }
905
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400906 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
907 // in GLES 3.0, there is no such restriction
908 if (state.getClientMajorVersion() < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000909 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400910 if (colorbufferSize.valid())
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000911 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400912 if (format.pixelBytes != colorbufferSize.value())
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000913 {
914 return GL_FRAMEBUFFER_UNSUPPORTED;
915 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000916 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400917 else
918 {
919 colorbufferSize = format.pixelBytes;
920 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000921 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400922
Martin Radev9bc9a322017-07-21 14:28:17 +0300923 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &colorAttachment))
924 {
925 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
926 }
927
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400928 hasRenderbuffer = hasRenderbuffer || (colorAttachment.type() == GL_RENDERBUFFER);
929 hasAttachments = true;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000930 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000931 }
932
Jamie Madill48ef11b2016-04-27 15:21:52 -0400933 const FramebufferAttachment &depthAttachment = mState.mDepthAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -0400934 if (depthAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000935 {
Geoff Lang9f10b772017-05-16 15:51:03 -0400936 if (!CheckAttachmentCompleteness(context, depthAttachment))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000937 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000938 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000939 }
940
Geoff Lang677bb6f2017-04-05 12:40:40 -0400941 const InternalFormat &format = *depthAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -0400942 if (format.depthBits == 0)
943 {
944 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000945 }
946
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400947 if (!CheckAttachmentSampleCompleteness(context, depthAttachment, false, &samples,
948 &fixedSampleLocations))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000949 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400950 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000951 }
Sami Väisänena797e062016-05-12 15:23:40 +0300952
Martin Radev9bc9a322017-07-21 14:28:17 +0300953 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &depthAttachment))
954 {
955 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
956 }
957
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400958 hasRenderbuffer = hasRenderbuffer || (depthAttachment.type() == GL_RENDERBUFFER);
959 hasAttachments = true;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000960 }
961
Jamie Madill48ef11b2016-04-27 15:21:52 -0400962 const FramebufferAttachment &stencilAttachment = mState.mStencilAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -0400963 if (stencilAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000964 {
Geoff Lang9f10b772017-05-16 15:51:03 -0400965 if (!CheckAttachmentCompleteness(context, stencilAttachment))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000966 {
967 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
968 }
969
Geoff Lang677bb6f2017-04-05 12:40:40 -0400970 const InternalFormat &format = *stencilAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -0400971 if (format.stencilBits == 0)
972 {
973 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000974 }
975
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400976 if (!CheckAttachmentSampleCompleteness(context, stencilAttachment, false, &samples,
977 &fixedSampleLocations))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000978 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400979 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000980 }
Corentin Wallez086d59a2016-04-29 09:06:49 -0400981
Martin Radev9bc9a322017-07-21 14:28:17 +0300982 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment, &stencilAttachment))
983 {
984 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
985 }
986
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400987 hasRenderbuffer = hasRenderbuffer || (stencilAttachment.type() == GL_RENDERBUFFER);
988 hasAttachments = true;
989 }
990
991 // Starting from ES 3.0 stencil and depth, if present, should be the same image
992 if (state.getClientMajorVersion() >= 3 && depthAttachment.isAttached() &&
993 stencilAttachment.isAttached() && stencilAttachment != depthAttachment)
994 {
995 return GL_FRAMEBUFFER_UNSUPPORTED;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000996 }
997
Jamie Madilla02315b2017-02-23 14:14:47 -0500998 // Special additional validation for WebGL 1 DEPTH/STENCIL/DEPTH_STENCIL.
999 if (state.isWebGL1())
1000 {
1001 if (!mState.mWebGLDepthStencilConsistent)
1002 {
1003 return GL_FRAMEBUFFER_UNSUPPORTED;
1004 }
1005
1006 if (mState.mWebGLDepthStencilAttachment.isAttached())
1007 {
1008 if (mState.mWebGLDepthStencilAttachment.getDepthSize() == 0 ||
1009 mState.mWebGLDepthStencilAttachment.getStencilSize() == 0)
1010 {
1011 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1012 }
Martin Radev9bc9a322017-07-21 14:28:17 +03001013
1014 if (!CheckMultiviewStateMatchesForCompleteness(firstAttachment,
1015 &mState.mWebGLDepthStencilAttachment))
1016 {
1017 return GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_ANGLE;
1018 }
Jamie Madilla02315b2017-02-23 14:14:47 -05001019 }
1020 else if (mState.mStencilAttachment.isAttached() &&
1021 mState.mStencilAttachment.getDepthSize() > 0)
1022 {
1023 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1024 }
1025 else if (mState.mDepthAttachment.isAttached() &&
1026 mState.mDepthAttachment.getStencilSize() > 0)
1027 {
1028 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
1029 }
1030 }
1031
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001032 // ES3.1(section 9.4) requires that if no image is attached to the framebuffer, and either the
1033 // value of the framebuffer's FRAMEBUFFER_DEFAULT_WIDTH or FRAMEBUFFER_DEFAULT_HEIGHT parameters
1034 // is zero, the framebuffer is considered incomplete.
JiangYizhou461d9a32017-01-04 16:37:26 +08001035 GLint defaultWidth = mState.getDefaultWidth();
1036 GLint defaultHeight = mState.getDefaultHeight();
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001037 if (!hasAttachments && (defaultWidth == 0 || defaultHeight == 0))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +00001038 {
1039 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +00001040 }
1041
Geoff Langa0e0aeb2017-04-12 15:06:29 -04001042 // In ES 2.0 and WebGL, all color attachments must have the same width and height.
Jamie Madillcc86d642015-11-24 13:00:07 -05001043 // In ES 3.0, there is no such restriction.
Geoff Langa0e0aeb2017-04-12 15:06:29 -04001044 if ((state.getClientMajorVersion() < 3 || state.getExtensions().webglCompatibility) &&
1045 !mState.attachmentsHaveSameDimensions())
Jamie Madillcc86d642015-11-24 13:00:07 -05001046 {
1047 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
1048 }
1049
Geoff Langa1b9d5a2017-05-18 11:22:27 -04001050 // ES3.1(section 9.4) requires that if the attached images are a mix of renderbuffers and
1051 // textures, the value of TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all attached textures.
JiangYizhou461d9a32017-01-04 16:37:26 +08001052 if (fixedSampleLocations.valid() && hasRenderbuffer && !fixedSampleLocations.value())
1053 {
1054 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
1055 }
1056
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001057 syncState(context);
Jamie Madillcc86d642015-11-24 13:00:07 -05001058 if (!mImpl->checkStatus())
1059 {
1060 return GL_FRAMEBUFFER_UNSUPPORTED;
1061 }
1062
1063 return GL_FRAMEBUFFER_COMPLETE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001064}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +00001065
Jamie Madill4928b7c2017-06-20 12:57:39 -04001066Error Framebuffer::discard(const Context *context, size_t count, const GLenum *attachments)
Austin Kinross08332632015-05-05 13:35:47 -07001067{
Jamie Madill4928b7c2017-06-20 12:57:39 -04001068 return mImpl->discard(context, count, attachments);
Austin Kinross08332632015-05-05 13:35:47 -07001069}
1070
Jamie Madill4928b7c2017-06-20 12:57:39 -04001071Error Framebuffer::invalidate(const Context *context, size_t count, const GLenum *attachments)
Jamie Madill2d96b9e2014-08-29 15:46:47 -04001072{
Jamie Madill4928b7c2017-06-20 12:57:39 -04001073 return mImpl->invalidate(context, count, attachments);
Jamie Madill2d96b9e2014-08-29 15:46:47 -04001074}
1075
Jamie Madill4928b7c2017-06-20 12:57:39 -04001076Error Framebuffer::invalidateSub(const Context *context,
1077 size_t count,
1078 const GLenum *attachments,
1079 const gl::Rectangle &area)
Jamie Madill400a4412014-08-29 15:46:45 -04001080{
Jamie Madill4928b7c2017-06-20 12:57:39 -04001081 return mImpl->invalidateSub(context, count, attachments, area);
Jamie Madill400a4412014-08-29 15:46:45 -04001082}
1083
Jamie Madillc564c072017-06-01 12:45:42 -04001084Error Framebuffer::clear(const gl::Context *context, GLbitfield mask)
Geoff Langb04dc822014-12-01 12:02:02 -05001085{
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001086 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -05001087 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001088 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001089 }
1090
Jamie Madill8415b5f2016-04-26 13:41:39 -04001091 return mImpl->clear(context, mask);
Geoff Langb04dc822014-12-01 12:02:02 -05001092}
1093
Jamie Madillc564c072017-06-01 12:45:42 -04001094Error Framebuffer::clearBufferfv(const gl::Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001095 GLenum buffer,
1096 GLint drawbuffer,
1097 const GLfloat *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001098{
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001099 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -05001100 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001101 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001102 }
1103
Jamie Madill8415b5f2016-04-26 13:41:39 -04001104 return mImpl->clearBufferfv(context, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -05001105}
1106
Jamie Madillc564c072017-06-01 12:45:42 -04001107Error Framebuffer::clearBufferuiv(const gl::Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001108 GLenum buffer,
1109 GLint drawbuffer,
1110 const GLuint *values)
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->clearBufferuiv(context, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -05001118}
1119
Jamie Madillc564c072017-06-01 12:45:42 -04001120Error Framebuffer::clearBufferiv(const gl::Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001121 GLenum buffer,
1122 GLint drawbuffer,
1123 const GLint *values)
Geoff Langb04dc822014-12-01 12:02:02 -05001124{
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001125 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -05001126 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001127 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001128 }
1129
Jamie Madill8415b5f2016-04-26 13:41:39 -04001130 return mImpl->clearBufferiv(context, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -05001131}
1132
Jamie Madillc564c072017-06-01 12:45:42 -04001133Error Framebuffer::clearBufferfi(const gl::Context *context,
Jamie Madill1b94d432015-08-07 13:23:23 -04001134 GLenum buffer,
1135 GLint drawbuffer,
1136 GLfloat depth,
1137 GLint stencil)
Geoff Langb04dc822014-12-01 12:02:02 -05001138{
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001139 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -05001140 {
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001141 return NoError();
Jamie Madill984ef412015-11-24 16:10:21 -05001142 }
1143
Jamie Madill8415b5f2016-04-26 13:41:39 -04001144 return mImpl->clearBufferfi(context, buffer, drawbuffer, depth, stencil);
Geoff Langb04dc822014-12-01 12:02:02 -05001145}
1146
Jamie Madill4928b7c2017-06-20 12:57:39 -04001147GLenum Framebuffer::getImplementationColorReadFormat(const Context *context) const
Geoff Langbce529e2014-12-01 12:48:41 -05001148{
Jamie Madill4928b7c2017-06-20 12:57:39 -04001149 return mImpl->getImplementationColorReadFormat(context);
Geoff Langbce529e2014-12-01 12:48:41 -05001150}
1151
Jamie Madill4928b7c2017-06-20 12:57:39 -04001152GLenum Framebuffer::getImplementationColorReadType(const Context *context) const
Geoff Langbce529e2014-12-01 12:48:41 -05001153{
Jamie Madill4928b7c2017-06-20 12:57:39 -04001154 return mImpl->getImplementationColorReadType(context);
Geoff Langbce529e2014-12-01 12:48:41 -05001155}
1156
Jamie Madillc564c072017-06-01 12:45:42 -04001157Error Framebuffer::readPixels(const gl::Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001158 const Rectangle &area,
Jamie Madill1b94d432015-08-07 13:23:23 -04001159 GLenum format,
1160 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -04001161 void *pixels) const
Geoff Langbce529e2014-12-01 12:48:41 -05001162{
Jamie Madill362876b2016-06-16 14:46:59 -04001163 ANGLE_TRY(mImpl->readPixels(context, area, format, type, pixels));
Geoff Lang520c4ae2015-05-05 13:12:36 -04001164
Jamie Madilldfde6ab2016-06-09 07:07:18 -07001165 Buffer *unpackBuffer = context->getGLState().getUnpackState().pixelBuffer.get();
Geoff Lang520c4ae2015-05-05 13:12:36 -04001166 if (unpackBuffer)
1167 {
1168 unpackBuffer->onPixelUnpack();
1169 }
1170
Jamie Madill362876b2016-06-16 14:46:59 -04001171 return NoError();
Geoff Langbce529e2014-12-01 12:48:41 -05001172}
1173
Jamie Madillc564c072017-06-01 12:45:42 -04001174Error Framebuffer::blit(const gl::Context *context,
Jamie Madillc29968b2016-01-20 11:17:23 -05001175 const Rectangle &sourceArea,
1176 const Rectangle &destArea,
Geoff Lang242468f2015-09-24 14:15:41 -04001177 GLbitfield mask,
Jamie Madill8415b5f2016-04-26 13:41:39 -04001178 GLenum filter)
Geoff Lang54bd5a42014-12-01 12:51:04 -05001179{
He Yunchao6be602d2016-12-22 14:33:07 +08001180 GLbitfield blitMask = mask;
1181
1182 // Note that blitting is called against draw framebuffer.
1183 // See the code in gl::Context::blitFramebuffer.
1184 if ((mask & GL_COLOR_BUFFER_BIT) && !hasEnabledDrawBuffer())
1185 {
1186 blitMask &= ~GL_COLOR_BUFFER_BIT;
1187 }
1188
1189 if ((mask & GL_STENCIL_BUFFER_BIT) && mState.getStencilAttachment() == nullptr)
1190 {
1191 blitMask &= ~GL_STENCIL_BUFFER_BIT;
1192 }
1193
1194 if ((mask & GL_DEPTH_BUFFER_BIT) && mState.getDepthAttachment() == nullptr)
1195 {
1196 blitMask &= ~GL_DEPTH_BUFFER_BIT;
1197 }
1198
1199 if (!blitMask)
1200 {
1201 return NoError();
1202 }
1203
1204 return mImpl->blit(context, sourceArea, destArea, blitMask, filter);
Geoff Lang54bd5a42014-12-01 12:51:04 -05001205}
1206
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001207int Framebuffer::getSamples(const Context *context)
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001208{
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001209 if (complete(context))
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001210 {
Jamie Madill9c335862017-07-18 11:51:38 -04001211 return getCachedSamples(context);
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001212 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001213
1214 return 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001215}
1216
Jamie Madill9c335862017-07-18 11:51:38 -04001217int Framebuffer::getCachedSamples(const Context *context)
1218{
1219 // For a complete framebuffer, all attachments must have the same sample count.
1220 // In this case return the first nonzero sample size.
1221 const auto *firstNonNullAttachment = mState.getFirstNonNullAttachment();
1222 if (firstNonNullAttachment)
1223 {
1224 ASSERT(firstNonNullAttachment->isAttached());
1225 return firstNonNullAttachment->getSamples();
1226 }
1227
1228 // No attachments found.
1229 return 0;
1230}
1231
Corentin Wallezccab69d2017-01-27 16:57:15 -05001232Error Framebuffer::getSamplePosition(size_t index, GLfloat *xy) const
1233{
1234 ANGLE_TRY(mImpl->getSamplePosition(index, xy));
Yuly Novikovc4d18aa2017-03-09 18:45:02 -05001235 return NoError();
Corentin Wallezccab69d2017-01-27 16:57:15 -05001236}
1237
Jamie Madille261b442014-06-25 12:42:21 -04001238bool Framebuffer::hasValidDepthStencil() const
1239{
Jamie Madill48ef11b2016-04-27 15:21:52 -04001240 return mState.getDepthStencilAttachment() != nullptr;
Jamie Madille261b442014-06-25 12:42:21 -04001241}
1242
Jamie Madilla02315b2017-02-23 14:14:47 -05001243void Framebuffer::setAttachment(const Context *context,
1244 GLenum type,
Jamie Madill2d06b732015-04-20 12:53:28 -04001245 GLenum binding,
1246 const ImageIndex &textureIndex,
1247 FramebufferAttachmentObject *resource)
Geoff Langab75a052014-10-15 12:56:37 -04001248{
Martin Radev5dae57b2017-07-14 16:15:55 +03001249 setAttachment(context, type, binding, textureIndex, resource,
1250 FramebufferAttachment::kDefaultNumViews,
1251 FramebufferAttachment::kDefaultBaseViewIndex,
1252 FramebufferAttachment::kDefaultMultiviewLayout,
1253 FramebufferAttachment::kDefaultViewportOffsets);
1254}
1255
1256void Framebuffer::setAttachment(const Context *context,
1257 GLenum type,
1258 GLenum binding,
1259 const ImageIndex &textureIndex,
1260 FramebufferAttachmentObject *resource,
1261 GLsizei numViews,
1262 GLuint baseViewIndex,
1263 GLenum multiviewLayout,
1264 const GLint *viewportOffsets)
1265{
Jamie Madilla02315b2017-02-23 14:14:47 -05001266 // Context may be null in unit tests.
1267 if (!context || !context->isWebGL1())
1268 {
Martin Radev5dae57b2017-07-14 16:15:55 +03001269 setAttachmentImpl(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
1270 multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001271 return;
1272 }
1273
1274 switch (binding)
1275 {
1276 case GL_DEPTH_STENCIL:
1277 case GL_DEPTH_STENCIL_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001278 mState.mWebGLDepthStencilAttachment.attach(context, type, binding, textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001279 resource, numViews, baseViewIndex,
1280 multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001281 break;
1282 case GL_DEPTH:
1283 case GL_DEPTH_ATTACHMENT:
Martin Radev5dae57b2017-07-14 16:15:55 +03001284 mState.mWebGLDepthAttachment.attach(context, type, binding, textureIndex, resource,
1285 numViews, baseViewIndex, multiviewLayout,
1286 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001287 break;
1288 case GL_STENCIL:
1289 case GL_STENCIL_ATTACHMENT:
Martin Radev5dae57b2017-07-14 16:15:55 +03001290 mState.mWebGLStencilAttachment.attach(context, type, binding, textureIndex, resource,
1291 numViews, baseViewIndex, multiviewLayout,
1292 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001293 break;
1294 default:
Martin Radev5dae57b2017-07-14 16:15:55 +03001295 setAttachmentImpl(context, type, binding, textureIndex, resource, numViews,
1296 baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001297 return;
1298 }
1299
Martin Radev5dae57b2017-07-14 16:15:55 +03001300 commitWebGL1DepthStencilIfConsistent(context, numViews, baseViewIndex, multiviewLayout,
1301 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001302}
1303
Martin Radev82ef7742017-08-08 17:44:58 +03001304void Framebuffer::setAttachmentMultiviewLayered(const Context *context,
1305 GLenum type,
1306 GLenum binding,
1307 const ImageIndex &textureIndex,
1308 FramebufferAttachmentObject *resource,
1309 GLsizei numViews,
1310 GLint baseViewIndex)
1311{
1312 setAttachment(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
1313 GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE,
1314 FramebufferAttachment::kDefaultViewportOffsets);
1315}
1316
Martin Radev5dae57b2017-07-14 16:15:55 +03001317void Framebuffer::setAttachmentMultiviewSideBySide(const Context *context,
1318 GLenum type,
1319 GLenum binding,
1320 const ImageIndex &textureIndex,
1321 FramebufferAttachmentObject *resource,
1322 GLsizei numViews,
1323 const GLint *viewportOffsets)
1324{
1325 setAttachment(context, type, binding, textureIndex, resource, numViews,
1326 FramebufferAttachment::kDefaultBaseViewIndex,
1327 GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE, viewportOffsets);
1328}
1329
1330void Framebuffer::commitWebGL1DepthStencilIfConsistent(const Context *context,
1331 GLsizei numViews,
1332 GLuint baseViewIndex,
1333 GLenum multiviewLayout,
1334 const GLint *viewportOffsets)
Jamie Madilla02315b2017-02-23 14:14:47 -05001335{
1336 int count = 0;
1337
1338 std::array<FramebufferAttachment *, 3> attachments = {{&mState.mWebGLDepthStencilAttachment,
1339 &mState.mWebGLDepthAttachment,
1340 &mState.mWebGLStencilAttachment}};
1341 for (FramebufferAttachment *attachment : attachments)
1342 {
1343 if (attachment->isAttached())
1344 {
1345 count++;
1346 }
1347 }
1348
1349 mState.mWebGLDepthStencilConsistent = (count <= 1);
1350 if (!mState.mWebGLDepthStencilConsistent)
1351 {
1352 // Inconsistent.
1353 return;
1354 }
1355
Geoff Lange466c552017-03-17 15:24:12 -04001356 auto getImageIndexIfTextureAttachment = [](const FramebufferAttachment &attachment) {
1357 if (attachment.type() == GL_TEXTURE)
1358 {
1359 return attachment.getTextureImageIndex();
1360 }
1361 else
1362 {
1363 return ImageIndex::MakeInvalid();
1364 }
1365 };
1366
Jamie Madilla02315b2017-02-23 14:14:47 -05001367 if (mState.mWebGLDepthAttachment.isAttached())
1368 {
1369 const auto &depth = mState.mWebGLDepthAttachment;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001370 setAttachmentImpl(context, depth.type(), GL_DEPTH_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001371 getImageIndexIfTextureAttachment(depth), depth.getResource(), numViews,
1372 baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001373 setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex::MakeInvalid(),
Martin Radev5dae57b2017-07-14 16:15:55 +03001374 nullptr, numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001375 }
1376 else if (mState.mWebGLStencilAttachment.isAttached())
1377 {
1378 const auto &stencil = mState.mWebGLStencilAttachment;
Martin Radev5dae57b2017-07-14 16:15:55 +03001379 setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex::MakeInvalid(), nullptr,
1380 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001381 setAttachmentImpl(context, stencil.type(), GL_STENCIL_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001382 getImageIndexIfTextureAttachment(stencil), stencil.getResource(),
1383 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001384 }
1385 else if (mState.mWebGLDepthStencilAttachment.isAttached())
1386 {
1387 const auto &depthStencil = mState.mWebGLDepthStencilAttachment;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001388 setAttachmentImpl(context, depthStencil.type(), GL_DEPTH_ATTACHMENT,
Geoff Lange466c552017-03-17 15:24:12 -04001389 getImageIndexIfTextureAttachment(depthStencil),
Martin Radev5dae57b2017-07-14 16:15:55 +03001390 depthStencil.getResource(), numViews, baseViewIndex, multiviewLayout,
1391 viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001392 setAttachmentImpl(context, depthStencil.type(), GL_STENCIL_ATTACHMENT,
Geoff Lange466c552017-03-17 15:24:12 -04001393 getImageIndexIfTextureAttachment(depthStencil),
Martin Radev5dae57b2017-07-14 16:15:55 +03001394 depthStencil.getResource(), numViews, baseViewIndex, multiviewLayout,
1395 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001396 }
1397 else
1398 {
Martin Radev5dae57b2017-07-14 16:15:55 +03001399 setAttachmentImpl(context, GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex::MakeInvalid(), nullptr,
1400 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001401 setAttachmentImpl(context, GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex::MakeInvalid(),
Martin Radev5dae57b2017-07-14 16:15:55 +03001402 nullptr, numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001403 }
1404}
1405
Jamie Madill4928b7c2017-06-20 12:57:39 -04001406void Framebuffer::setAttachmentImpl(const Context *context,
1407 GLenum type,
Jamie Madilla02315b2017-02-23 14:14:47 -05001408 GLenum binding,
1409 const ImageIndex &textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001410 FramebufferAttachmentObject *resource,
1411 GLsizei numViews,
1412 GLuint baseViewIndex,
1413 GLenum multiviewLayout,
1414 const GLint *viewportOffsets)
Jamie Madilla02315b2017-02-23 14:14:47 -05001415{
Jamie Madilla02315b2017-02-23 14:14:47 -05001416 switch (binding)
1417 {
Jamie Madillb8126692017-04-05 11:22:17 -04001418 case GL_DEPTH_STENCIL:
1419 case GL_DEPTH_STENCIL_ATTACHMENT:
1420 {
1421 // ensure this is a legitimate depth+stencil format
1422 FramebufferAttachmentObject *attachmentObj = resource;
1423 if (resource)
1424 {
Jamie Madill4fd95d52017-04-05 11:22:18 -04001425 const Format &format = resource->getAttachmentFormat(binding, textureIndex);
Jamie Madillb8126692017-04-05 11:22:17 -04001426 if (format.info->depthBits == 0 || format.info->stencilBits == 0)
1427 {
1428 // Attaching nullptr detaches the current attachment.
1429 attachmentObj = nullptr;
1430 }
1431 }
1432
Jamie Madill4928b7c2017-06-20 12:57:39 -04001433 updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
Jamie Madillb8126692017-04-05 11:22:17 -04001434 &mDirtyDepthAttachmentBinding, type, binding, textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001435 attachmentObj, numViews, baseViewIndex, multiviewLayout,
1436 viewportOffsets);
Jamie Madill4928b7c2017-06-20 12:57:39 -04001437 updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
Jamie Madillb8126692017-04-05 11:22:17 -04001438 &mDirtyStencilAttachmentBinding, type, binding, textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001439 attachmentObj, numViews, baseViewIndex, multiviewLayout,
1440 viewportOffsets);
Jamie Madillb8126692017-04-05 11:22:17 -04001441 return;
1442 }
1443
Jamie Madilla02315b2017-02-23 14:14:47 -05001444 case GL_DEPTH:
1445 case GL_DEPTH_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001446 updateAttachment(context, &mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001447 &mDirtyDepthAttachmentBinding, type, binding, textureIndex, resource,
1448 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madill2d06b732015-04-20 12:53:28 -04001449 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001450
Jamie Madilla02315b2017-02-23 14:14:47 -05001451 case GL_STENCIL:
1452 case GL_STENCIL_ATTACHMENT:
Jamie Madill4928b7c2017-06-20 12:57:39 -04001453 updateAttachment(context, &mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
Martin Radev5dae57b2017-07-14 16:15:55 +03001454 &mDirtyStencilAttachmentBinding, type, binding, textureIndex, resource,
1455 numViews, baseViewIndex, multiviewLayout, viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001456 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001457
Jamie Madilla02315b2017-02-23 14:14:47 -05001458 case GL_BACK:
Martin Radev5dae57b2017-07-14 16:15:55 +03001459 mState.mColorAttachments[0].attach(context, type, binding, textureIndex, resource,
1460 numViews, baseViewIndex, multiviewLayout,
1461 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001462 mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0);
1463 // No need for a resource binding for the default FBO, it's always complete.
1464 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001465
Jamie Madilla02315b2017-02-23 14:14:47 -05001466 default:
1467 {
1468 size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
1469 ASSERT(colorIndex < mState.mColorAttachments.size());
Jamie Madillb8126692017-04-05 11:22:17 -04001470 size_t dirtyBit = DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex;
Jamie Madill4928b7c2017-06-20 12:57:39 -04001471 updateAttachment(context, &mState.mColorAttachments[colorIndex], dirtyBit,
Jamie Madillb8126692017-04-05 11:22:17 -04001472 &mDirtyColorAttachmentBindings[colorIndex], type, binding,
Martin Radev5dae57b2017-07-14 16:15:55 +03001473 textureIndex, resource, numViews, baseViewIndex, multiviewLayout,
1474 viewportOffsets);
Jamie Madilla02315b2017-02-23 14:14:47 -05001475
Corentin Walleze7557742017-06-01 13:09:57 -04001476 // TODO(jmadill): ASSERT instead of checking the attachment exists in
1477 // formsRenderingFeedbackLoopWith
Jamie Madilla02315b2017-02-23 14:14:47 -05001478 bool enabled = (type != GL_NONE && getDrawBufferState(colorIndex) != GL_NONE);
1479 mState.mEnabledDrawBuffers.set(colorIndex, enabled);
Jamie Madill2d06b732015-04-20 12:53:28 -04001480 }
Jamie Madilla02315b2017-02-23 14:14:47 -05001481 break;
Geoff Langab75a052014-10-15 12:56:37 -04001482 }
1483}
1484
Jamie Madill4928b7c2017-06-20 12:57:39 -04001485void Framebuffer::updateAttachment(const Context *context,
1486 FramebufferAttachment *attachment,
Jamie Madillb8126692017-04-05 11:22:17 -04001487 size_t dirtyBit,
1488 OnAttachmentDirtyBinding *onDirtyBinding,
1489 GLenum type,
1490 GLenum binding,
1491 const ImageIndex &textureIndex,
Martin Radev5dae57b2017-07-14 16:15:55 +03001492 FramebufferAttachmentObject *resource,
1493 GLsizei numViews,
1494 GLuint baseViewIndex,
1495 GLenum multiviewLayout,
1496 const GLint *viewportOffsets)
Jamie Madillb8126692017-04-05 11:22:17 -04001497{
Martin Radev5dae57b2017-07-14 16:15:55 +03001498 attachment->attach(context, type, binding, textureIndex, resource, numViews, baseViewIndex,
1499 multiviewLayout, viewportOffsets);
Jamie Madillb8126692017-04-05 11:22:17 -04001500 mDirtyBits.set(dirtyBit);
1501 BindResourceChannel(onDirtyBinding, resource);
1502}
1503
Jamie Madilla02315b2017-02-23 14:14:47 -05001504void Framebuffer::resetAttachment(const Context *context, GLenum binding)
Jamie Madill2d06b732015-04-20 12:53:28 -04001505{
Jamie Madilla02315b2017-02-23 14:14:47 -05001506 setAttachment(context, GL_NONE, binding, ImageIndex::MakeInvalid(), nullptr);
Jamie Madill2d06b732015-04-20 12:53:28 -04001507}
1508
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001509void Framebuffer::syncState(const Context *context)
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001510{
1511 if (mDirtyBits.any())
1512 {
Jamie Madillc564c072017-06-01 12:45:42 -04001513 mImpl->syncState(context, mDirtyBits);
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001514 mDirtyBits.reset();
Corentin Wallezccab69d2017-01-27 16:57:15 -05001515 if (mId != 0)
1516 {
1517 mCachedStatus.reset();
1518 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001519 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001520}
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001521
Jamie Madill1e5499d2017-04-05 11:22:16 -04001522void Framebuffer::signal(uint32_t token)
Jamie Madill51f40ec2016-06-15 14:06:00 -04001523{
Jamie Madill362876b2016-06-16 14:46:59 -04001524 // TOOD(jmadill): Make this only update individual attachments to do less work.
1525 mCachedStatus.reset();
Jamie Madill51f40ec2016-06-15 14:06:00 -04001526}
1527
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001528bool Framebuffer::complete(const Context *context)
Jamie Madill51f40ec2016-06-15 14:06:00 -04001529{
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001530 return (checkStatus(context) == GL_FRAMEBUFFER_COMPLETE);
1531}
1532
1533bool Framebuffer::cachedComplete() const
1534{
1535 return (mCachedStatus.valid() && mCachedStatus == GL_FRAMEBUFFER_COMPLETE);
Jamie Madill51f40ec2016-06-15 14:06:00 -04001536}
1537
Jamie Madilla4595b82017-01-11 17:36:34 -05001538bool Framebuffer::formsRenderingFeedbackLoopWith(const State &state) const
1539{
1540 const Program *program = state.getProgram();
1541
1542 // TODO(jmadill): Default framebuffer feedback loops.
1543 if (mId == 0)
1544 {
1545 return false;
1546 }
1547
1548 // The bitset will skip inactive draw buffers.
Jamie Madill6de51852017-04-12 09:53:01 -04001549 for (size_t drawIndex : mState.mEnabledDrawBuffers)
Jamie Madilla4595b82017-01-11 17:36:34 -05001550 {
Jamie Madill5aca1932017-07-21 12:22:01 -04001551 const FramebufferAttachment &attachment = mState.mColorAttachments[drawIndex];
1552 ASSERT(attachment.isAttached());
1553 if (attachment.type() == GL_TEXTURE)
Jamie Madilla4595b82017-01-11 17:36:34 -05001554 {
1555 // Validate the feedback loop.
Jamie Madill5aca1932017-07-21 12:22:01 -04001556 if (program->samplesFromTexture(state, attachment.id()))
Jamie Madilla4595b82017-01-11 17:36:34 -05001557 {
1558 return true;
1559 }
1560 }
1561 }
1562
Jamie Madill1d37bc52017-02-02 19:59:58 -05001563 // Validate depth-stencil feedback loop.
1564 const auto &dsState = state.getDepthStencilState();
1565
1566 // We can skip the feedback loop checks if depth/stencil is masked out or disabled.
1567 const FramebufferAttachment *depth = getDepthbuffer();
1568 if (depth && depth->type() == GL_TEXTURE && dsState.depthTest && dsState.depthMask)
1569 {
1570 if (program->samplesFromTexture(state, depth->id()))
1571 {
1572 return true;
1573 }
1574 }
1575
1576 // Note: we assume the front and back masks are the same for WebGL.
1577 const FramebufferAttachment *stencil = getStencilbuffer();
1578 ASSERT(dsState.stencilBackWritemask == dsState.stencilWritemask);
1579 if (stencil && stencil->type() == GL_TEXTURE && dsState.stencilTest &&
1580 dsState.stencilWritemask != 0)
1581 {
1582 // Skip the feedback loop check if depth/stencil point to the same resource.
1583 if (!depth || *stencil != *depth)
1584 {
1585 if (program->samplesFromTexture(state, stencil->id()))
1586 {
1587 return true;
1588 }
1589 }
1590 }
1591
Jamie Madilla4595b82017-01-11 17:36:34 -05001592 return false;
1593}
1594
Jamie Madillfd3dd432017-02-02 19:59:59 -05001595bool Framebuffer::formsCopyingFeedbackLoopWith(GLuint copyTextureID,
1596 GLint copyTextureLevel,
1597 GLint copyTextureLayer) const
Jamie Madillf695a3a2017-01-11 17:36:35 -05001598{
1599 if (mId == 0)
1600 {
1601 // It seems impossible to form a texture copying feedback loop with the default FBO.
1602 return false;
1603 }
1604
1605 const FramebufferAttachment *readAttachment = getReadColorbuffer();
1606 ASSERT(readAttachment);
1607
1608 if (readAttachment->isTextureWithId(copyTextureID))
1609 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05001610 const auto &imageIndex = readAttachment->getTextureImageIndex();
1611 if (imageIndex.mipIndex == copyTextureLevel)
Jamie Madillf695a3a2017-01-11 17:36:35 -05001612 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05001613 // Check 3D/Array texture layers.
1614 return imageIndex.layerIndex == ImageIndex::ENTIRE_LEVEL ||
1615 copyTextureLayer == ImageIndex::ENTIRE_LEVEL ||
1616 imageIndex.layerIndex == copyTextureLayer;
Jamie Madillf695a3a2017-01-11 17:36:35 -05001617 }
1618 }
1619 return false;
1620}
1621
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001622GLint Framebuffer::getDefaultWidth() const
1623{
1624 return mState.getDefaultWidth();
1625}
1626
1627GLint Framebuffer::getDefaultHeight() const
1628{
1629 return mState.getDefaultHeight();
1630}
1631
1632GLint Framebuffer::getDefaultSamples() const
1633{
1634 return mState.getDefaultSamples();
1635}
1636
1637GLboolean Framebuffer::getDefaultFixedSampleLocations() const
1638{
1639 return mState.getDefaultFixedSampleLocations();
1640}
1641
1642void Framebuffer::setDefaultWidth(GLint defaultWidth)
1643{
1644 mState.mDefaultWidth = defaultWidth;
1645 mDirtyBits.set(DIRTY_BIT_DEFAULT_WIDTH);
1646}
1647
1648void Framebuffer::setDefaultHeight(GLint defaultHeight)
1649{
1650 mState.mDefaultHeight = defaultHeight;
1651 mDirtyBits.set(DIRTY_BIT_DEFAULT_HEIGHT);
1652}
1653
1654void Framebuffer::setDefaultSamples(GLint defaultSamples)
1655{
1656 mState.mDefaultSamples = defaultSamples;
1657 mDirtyBits.set(DIRTY_BIT_DEFAULT_SAMPLES);
1658}
1659
1660void Framebuffer::setDefaultFixedSampleLocations(GLboolean defaultFixedSampleLocations)
1661{
1662 mState.mDefaultFixedSampleLocations = defaultFixedSampleLocations;
1663 mDirtyBits.set(DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS);
1664}
1665
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001666// TODO(jmadill): Remove this kludge.
1667GLenum Framebuffer::checkStatus(const ValidationContext *context)
1668{
1669 return checkStatus(static_cast<const Context *>(context));
1670}
1671
1672int Framebuffer::getSamples(const ValidationContext *context)
1673{
1674 return getSamples(static_cast<const Context *>(context));
1675}
1676
Martin Radev14a26ae2017-07-24 15:56:29 +03001677GLsizei Framebuffer::getNumViews() const
1678{
Martin Radev5c00d0d2017-08-07 10:06:59 +03001679 return mState.getNumViews();
Martin Radev14a26ae2017-07-24 15:56:29 +03001680}
1681
Martin Radev4e619f52017-08-09 11:50:06 +03001682GLint Framebuffer::getBaseViewIndex() const
1683{
1684 return mState.getBaseViewIndex();
1685}
1686
Martin Radev878c8b12017-07-28 09:51:04 +03001687const std::vector<Offset> *Framebuffer::getViewportOffsets() const
1688{
Martin Radev5c00d0d2017-08-07 10:06:59 +03001689 return mState.getViewportOffsets();
Martin Radev878c8b12017-07-28 09:51:04 +03001690}
1691
1692GLenum Framebuffer::getMultiviewLayout() const
1693{
Martin Radev5c00d0d2017-08-07 10:06:59 +03001694 return mState.getMultiviewLayout();
Martin Radev878c8b12017-07-28 09:51:04 +03001695}
1696
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001697} // namespace gl