blob: 9632abba5b3367ae17233e0e3e7ff0a7021407e9 [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
Geoff Lang9f10b772017-05-16 15:51:03 -040042bool CheckAttachmentCompleteness(const Context *context, const FramebufferAttachment &attachment)
43{
44 ASSERT(attachment.isAttached());
45
46 const Extents &size = attachment.getSize();
47 if (size.width == 0 || size.height == 0)
48 {
49 return false;
50 }
51
52 const InternalFormat &format = *attachment.getFormat().info;
53 if (!format.renderSupport(context->getClientVersion(), context->getExtensions()))
54 {
55 return false;
56 }
57
58 if (attachment.type() == GL_TEXTURE)
59 {
60 if (attachment.layer() >= size.depth)
61 {
62 return false;
63 }
64
65 // ES3 specifies that cube map texture attachments must be cube complete.
66 // This language is missing from the ES2 spec, but we enforce it here because some
67 // desktop OpenGL drivers also enforce this validation.
68 // TODO(jmadill): Check if OpenGL ES2 drivers enforce cube completeness.
69 const Texture *texture = attachment.getTexture();
70 ASSERT(texture);
71 if (texture->getTarget() == GL_TEXTURE_CUBE_MAP &&
72 !texture->getTextureState().isCubeComplete())
73 {
74 return false;
75 }
76 }
77
78 return true;
79};
80
Geoff Langa1b9d5a2017-05-18 11:22:27 -040081bool CheckAttachmentSampleCompleteness(const Context *context,
82 const FramebufferAttachment &attachment,
83 bool colorAttachment,
84 Optional<int> *samples,
85 Optional<GLboolean> *fixedSampleLocations)
86{
87 ASSERT(attachment.isAttached());
88
89 if (attachment.type() == GL_TEXTURE)
90 {
91 const Texture *texture = attachment.getTexture();
92 ASSERT(texture);
93
94 const ImageIndex &attachmentImageIndex = attachment.getTextureImageIndex();
95
96 // ES3.1 (section 9.4) requires that the value of TEXTURE_FIXED_SAMPLE_LOCATIONS should be
97 // the same for all attached textures.
98 GLboolean fixedSampleloc = texture->getFixedSampleLocations(attachmentImageIndex.type,
99 attachmentImageIndex.mipIndex);
100 if (fixedSampleLocations->valid() && fixedSampleloc != fixedSampleLocations->value())
101 {
102 return false;
103 }
104 else
105 {
106 *fixedSampleLocations = fixedSampleloc;
107 }
108 }
109
110 if (samples->valid())
111 {
112 if (attachment.getSamples() != samples->value())
113 {
114 if (colorAttachment)
115 {
116 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
117 // all color attachments have the same number of samples for the FBO to be complete.
118 return false;
119 }
120 else
121 {
122 // CHROMIUM_framebuffer_mixed_samples allows a framebuffer to be considered complete
123 // when its depth or stencil samples are a multiple of the number of color samples.
124 if (!context->getExtensions().framebufferMixedSamples)
125 {
126 return false;
127 }
128
129 if ((attachment.getSamples() % std::max(samples->value(), 1)) != 0)
130 {
131 return false;
132 }
133 }
134 }
135 }
136 else
137 {
138 *samples = attachment.getSamples();
139 }
140
141 return true;
142}
143
Jamie Madill362876b2016-06-16 14:46:59 -0400144} // anonymous namespace
Jamie Madilld1405e52015-03-05 15:41:39 -0500145
Jamie Madill6f60d052017-02-22 15:20:11 -0500146// This constructor is only used for default framebuffers.
Jamie Madill48ef11b2016-04-27 15:21:52 -0400147FramebufferState::FramebufferState()
Geoff Lang70d0f492015-12-10 17:45:46 -0500148 : mLabel(),
149 mColorAttachments(1),
Geoff Langd90d3882017-03-21 10:49:54 -0400150 mDrawBufferStates(IMPLEMENTATION_MAX_DRAW_BUFFERS, GL_NONE),
Jamie Madill6f60d052017-02-22 15:20:11 -0500151 mReadBufferState(GL_BACK),
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800152 mDefaultWidth(0),
153 mDefaultHeight(0),
154 mDefaultSamples(0),
Jamie Madilla02315b2017-02-23 14:14:47 -0500155 mDefaultFixedSampleLocations(GL_FALSE),
156 mWebGLDepthStencilConsistent(true)
Corentin Wallez37c39792015-08-20 14:19:46 -0400157{
Geoff Langd90d3882017-03-21 10:49:54 -0400158 ASSERT(mDrawBufferStates.size() > 0);
159 mDrawBufferStates[0] = GL_BACK;
Jamie Madilla4595b82017-01-11 17:36:34 -0500160 mEnabledDrawBuffers.set(0);
Corentin Wallez37c39792015-08-20 14:19:46 -0400161}
162
Jamie Madill48ef11b2016-04-27 15:21:52 -0400163FramebufferState::FramebufferState(const Caps &caps)
Geoff Lang70d0f492015-12-10 17:45:46 -0500164 : mLabel(),
165 mColorAttachments(caps.maxColorAttachments),
Jamie Madilld1405e52015-03-05 15:41:39 -0500166 mDrawBufferStates(caps.maxDrawBuffers, GL_NONE),
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800167 mReadBufferState(GL_COLOR_ATTACHMENT0_EXT),
168 mDefaultWidth(0),
169 mDefaultHeight(0),
170 mDefaultSamples(0),
Jamie Madilla02315b2017-02-23 14:14:47 -0500171 mDefaultFixedSampleLocations(GL_FALSE),
172 mWebGLDepthStencilConsistent(true)
Jamie Madilld1405e52015-03-05 15:41:39 -0500173{
Geoff Langa15472a2015-08-11 11:48:03 -0400174 ASSERT(mDrawBufferStates.size() > 0);
Jamie Madilld1405e52015-03-05 15:41:39 -0500175 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
176}
177
Jamie Madill48ef11b2016-04-27 15:21:52 -0400178FramebufferState::~FramebufferState()
Jamie Madilld1405e52015-03-05 15:41:39 -0500179{
Jamie Madilld1405e52015-03-05 15:41:39 -0500180}
181
Jamie Madill48ef11b2016-04-27 15:21:52 -0400182const std::string &FramebufferState::getLabel()
Geoff Lang70d0f492015-12-10 17:45:46 -0500183{
184 return mLabel;
185}
186
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400187const FramebufferAttachment *FramebufferState::getAttachment(GLenum attachment) const
188{
189 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
190 {
191 return getColorAttachment(attachment - GL_COLOR_ATTACHMENT0);
192 }
193
194 switch (attachment)
195 {
196 case GL_COLOR:
197 case GL_BACK:
198 return getColorAttachment(0);
199 case GL_DEPTH:
200 case GL_DEPTH_ATTACHMENT:
201 return getDepthAttachment();
202 case GL_STENCIL:
203 case GL_STENCIL_ATTACHMENT:
204 return getStencilAttachment();
205 case GL_DEPTH_STENCIL:
206 case GL_DEPTH_STENCIL_ATTACHMENT:
207 return getDepthStencilAttachment();
208 default:
209 UNREACHABLE();
210 return nullptr;
211 }
212}
213
Jamie Madill48ef11b2016-04-27 15:21:52 -0400214const FramebufferAttachment *FramebufferState::getReadAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500215{
Antoine Labour2ec65dc2016-11-30 16:28:58 -0800216 if (mReadBufferState == GL_NONE)
217 {
218 return nullptr;
219 }
Jamie Madill231c7f52017-04-26 13:45:37 -0400220 ASSERT(mReadBufferState == GL_BACK ||
221 (mReadBufferState >= GL_COLOR_ATTACHMENT0 && mReadBufferState <= GL_COLOR_ATTACHMENT15));
222 size_t readIndex = (mReadBufferState == GL_BACK
223 ? 0
224 : static_cast<size_t>(mReadBufferState - GL_COLOR_ATTACHMENT0));
Jamie Madill7147f012015-03-05 15:41:40 -0500225 ASSERT(readIndex < mColorAttachments.size());
Jamie Madill2d06b732015-04-20 12:53:28 -0400226 return mColorAttachments[readIndex].isAttached() ? &mColorAttachments[readIndex] : nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500227}
228
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500229const FramebufferAttachment *FramebufferState::getFirstNonNullAttachment() const
230{
231 auto *colorAttachment = getFirstColorAttachment();
232 if (colorAttachment)
233 {
234 return colorAttachment;
235 }
236 return getDepthOrStencilAttachment();
237}
238
Jamie Madill48ef11b2016-04-27 15:21:52 -0400239const FramebufferAttachment *FramebufferState::getFirstColorAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500240{
Jamie Madill2d06b732015-04-20 12:53:28 -0400241 for (const FramebufferAttachment &colorAttachment : mColorAttachments)
Jamie Madill7147f012015-03-05 15:41:40 -0500242 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400243 if (colorAttachment.isAttached())
Jamie Madill7147f012015-03-05 15:41:40 -0500244 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400245 return &colorAttachment;
Jamie Madill7147f012015-03-05 15:41:40 -0500246 }
247 }
248
249 return nullptr;
250}
251
Jamie Madill48ef11b2016-04-27 15:21:52 -0400252const FramebufferAttachment *FramebufferState::getDepthOrStencilAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500253{
Jamie Madill2d06b732015-04-20 12:53:28 -0400254 if (mDepthAttachment.isAttached())
255 {
256 return &mDepthAttachment;
257 }
258 if (mStencilAttachment.isAttached())
259 {
260 return &mStencilAttachment;
261 }
262 return nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500263}
264
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500265const FramebufferAttachment *FramebufferState::getStencilOrDepthStencilAttachment() const
266{
267 if (mStencilAttachment.isAttached())
268 {
269 return &mStencilAttachment;
270 }
271 return getDepthStencilAttachment();
272}
273
Jamie Madill48ef11b2016-04-27 15:21:52 -0400274const FramebufferAttachment *FramebufferState::getColorAttachment(size_t colorAttachment) const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400275{
276 ASSERT(colorAttachment < mColorAttachments.size());
Jamie Madill231c7f52017-04-26 13:45:37 -0400277 return mColorAttachments[colorAttachment].isAttached() ? &mColorAttachments[colorAttachment]
278 : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400279}
280
Jamie Madill48ef11b2016-04-27 15:21:52 -0400281const FramebufferAttachment *FramebufferState::getDepthAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400282{
Jamie Madill2d06b732015-04-20 12:53:28 -0400283 return mDepthAttachment.isAttached() ? &mDepthAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400284}
285
Jamie Madill48ef11b2016-04-27 15:21:52 -0400286const FramebufferAttachment *FramebufferState::getStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400287{
Jamie Madill2d06b732015-04-20 12:53:28 -0400288 return mStencilAttachment.isAttached() ? &mStencilAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400289}
290
Jamie Madill48ef11b2016-04-27 15:21:52 -0400291const FramebufferAttachment *FramebufferState::getDepthStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400292{
293 // A valid depth-stencil attachment has the same resource bound to both the
294 // depth and stencil attachment points.
Jamie Madill2d06b732015-04-20 12:53:28 -0400295 if (mDepthAttachment.isAttached() && mStencilAttachment.isAttached() &&
Jamie Madill44f26482016-11-18 12:49:15 -0500296 mDepthAttachment == mStencilAttachment)
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400297 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400298 return &mDepthAttachment;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400299 }
300
301 return nullptr;
302}
303
Jamie Madill48ef11b2016-04-27 15:21:52 -0400304bool FramebufferState::attachmentsHaveSameDimensions() const
Jamie Madillcc86d642015-11-24 13:00:07 -0500305{
306 Optional<Extents> attachmentSize;
307
Jamie Madill231c7f52017-04-26 13:45:37 -0400308 auto hasMismatchedSize = [&attachmentSize](const FramebufferAttachment &attachment) {
Jamie Madillcc86d642015-11-24 13:00:07 -0500309 if (!attachment.isAttached())
310 {
311 return false;
312 }
313
314 if (!attachmentSize.valid())
315 {
316 attachmentSize = attachment.getSize();
317 return false;
318 }
319
320 return (attachment.getSize() != attachmentSize.value());
321 };
322
323 for (const auto &attachment : mColorAttachments)
324 {
325 if (hasMismatchedSize(attachment))
326 {
327 return false;
328 }
329 }
330
331 if (hasMismatchedSize(mDepthAttachment))
332 {
333 return false;
334 }
335
336 return !hasMismatchedSize(mStencilAttachment);
337}
338
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400339const gl::FramebufferAttachment *FramebufferState::getDrawBuffer(size_t drawBufferIdx) const
340{
341 ASSERT(drawBufferIdx < mDrawBufferStates.size());
342 if (mDrawBufferStates[drawBufferIdx] != GL_NONE)
343 {
344 // ES3 spec: "If the GL is bound to a draw framebuffer object, the ith buffer listed in bufs
345 // must be COLOR_ATTACHMENTi or NONE"
346 ASSERT(mDrawBufferStates[drawBufferIdx] == GL_COLOR_ATTACHMENT0 + drawBufferIdx ||
347 (drawBufferIdx == 0 && mDrawBufferStates[drawBufferIdx] == GL_BACK));
348 return getAttachment(mDrawBufferStates[drawBufferIdx]);
349 }
350 else
351 {
352 return nullptr;
353 }
354}
355
356size_t FramebufferState::getDrawBufferCount() const
357{
358 return mDrawBufferStates.size();
359}
360
Geoff Langb21e20d2016-07-19 15:35:41 -0400361bool FramebufferState::colorAttachmentsAreUniqueImages() const
362{
363 for (size_t firstAttachmentIdx = 0; firstAttachmentIdx < mColorAttachments.size();
364 firstAttachmentIdx++)
365 {
366 const gl::FramebufferAttachment &firstAttachment = mColorAttachments[firstAttachmentIdx];
367 if (!firstAttachment.isAttached())
368 {
369 continue;
370 }
371
372 for (size_t secondAttachmentIdx = firstAttachmentIdx + 1;
373 secondAttachmentIdx < mColorAttachments.size(); secondAttachmentIdx++)
374 {
375 const gl::FramebufferAttachment &secondAttachment =
376 mColorAttachments[secondAttachmentIdx];
377 if (!secondAttachment.isAttached())
378 {
379 continue;
380 }
381
382 if (firstAttachment == secondAttachment)
383 {
384 return false;
385 }
386 }
387 }
388
389 return true;
390}
391
Jamie Madill7aea7e02016-05-10 10:39:45 -0400392Framebuffer::Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id)
Jamie Madill362876b2016-06-16 14:46:59 -0400393 : mState(caps),
394 mImpl(factory->createFramebuffer(mState)),
395 mId(id),
396 mCachedStatus(),
397 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
398 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000399{
Corentin Wallez37c39792015-08-20 14:19:46 -0400400 ASSERT(mId != 0);
401 ASSERT(mImpl != nullptr);
Jamie Madill362876b2016-06-16 14:46:59 -0400402 ASSERT(mState.mColorAttachments.size() == static_cast<size_t>(caps.maxColorAttachments));
403
Jamie Madill1e5499d2017-04-05 11:22:16 -0400404 for (uint32_t colorIndex = 0;
405 colorIndex < static_cast<uint32_t>(mState.mColorAttachments.size()); ++colorIndex)
Jamie Madill362876b2016-06-16 14:46:59 -0400406 {
Jamie Madill1e5499d2017-04-05 11:22:16 -0400407 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
Jamie Madill362876b2016-06-16 14:46:59 -0400408 }
Corentin Wallez37c39792015-08-20 14:19:46 -0400409}
410
Jamie Madill6f60d052017-02-22 15:20:11 -0500411Framebuffer::Framebuffer(egl::Surface *surface)
Jamie Madill362876b2016-06-16 14:46:59 -0400412 : mState(),
Jamie Madill6f60d052017-02-22 15:20:11 -0500413 mImpl(surface->getImplementation()->createDefaultFramebuffer(mState)),
Jamie Madill362876b2016-06-16 14:46:59 -0400414 mId(0),
415 mCachedStatus(GL_FRAMEBUFFER_COMPLETE),
416 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
417 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
Corentin Wallez37c39792015-08-20 14:19:46 -0400418{
Geoff Langda88add2014-12-01 10:22:01 -0500419 ASSERT(mImpl != nullptr);
Jamie Madill1e5499d2017-04-05 11:22:16 -0400420 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
Jamie Madill6f60d052017-02-22 15:20:11 -0500421
Jamie Madilla02315b2017-02-23 14:14:47 -0500422 setAttachmentImpl(GL_FRAMEBUFFER_DEFAULT, GL_BACK, gl::ImageIndex::MakeInvalid(), surface);
Jamie Madill6f60d052017-02-22 15:20:11 -0500423
424 if (surface->getConfig()->depthSize > 0)
425 {
Jamie Madilla02315b2017-02-23 14:14:47 -0500426 setAttachmentImpl(GL_FRAMEBUFFER_DEFAULT, GL_DEPTH, gl::ImageIndex::MakeInvalid(), surface);
Jamie Madill6f60d052017-02-22 15:20:11 -0500427 }
428
429 if (surface->getConfig()->stencilSize > 0)
430 {
Jamie Madilla02315b2017-02-23 14:14:47 -0500431 setAttachmentImpl(GL_FRAMEBUFFER_DEFAULT, GL_STENCIL, gl::ImageIndex::MakeInvalid(),
432 surface);
Jamie Madill6f60d052017-02-22 15:20:11 -0500433 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000434}
435
Corentin Wallezccab69d2017-01-27 16:57:15 -0500436Framebuffer::Framebuffer(rx::GLImplFactory *factory)
437 : mState(),
438 mImpl(factory->createFramebuffer(mState)),
439 mId(0),
440 mCachedStatus(GL_FRAMEBUFFER_UNDEFINED_OES),
441 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
442 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
443{
Jamie Madill1e5499d2017-04-05 11:22:16 -0400444 mDirtyColorAttachmentBindings.emplace_back(this, DIRTY_BIT_COLOR_ATTACHMENT_0);
Corentin Wallezccab69d2017-01-27 16:57:15 -0500445}
446
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000447Framebuffer::~Framebuffer()
448{
Geoff Langda88add2014-12-01 10:22:01 -0500449 SafeDelete(mImpl);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000450}
451
Jamie Madill6c1f6712017-02-14 19:08:04 -0500452void Framebuffer::destroy(const Context *context)
453{
454 mImpl->destroy(rx::SafeGetImpl(context));
455}
456
457void Framebuffer::destroyDefault(const egl::Display *display)
458{
459 mImpl->destroyDefault(rx::SafeGetImpl(display));
460}
461
Geoff Lang70d0f492015-12-10 17:45:46 -0500462void Framebuffer::setLabel(const std::string &label)
463{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400464 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -0500465}
466
467const std::string &Framebuffer::getLabel() const
468{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400469 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -0500470}
471
Jamie Madilla02315b2017-02-23 14:14:47 -0500472void Framebuffer::detachTexture(const Context *context, GLuint textureId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000473{
Jamie Madilla02315b2017-02-23 14:14:47 -0500474 detachResourceById(context, GL_TEXTURE, textureId);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000475}
476
Jamie Madilla02315b2017-02-23 14:14:47 -0500477void Framebuffer::detachRenderbuffer(const Context *context, GLuint renderbufferId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000478{
Jamie Madilla02315b2017-02-23 14:14:47 -0500479 detachResourceById(context, GL_RENDERBUFFER, renderbufferId);
Jamie Madilld1405e52015-03-05 15:41:39 -0500480}
Jamie Madille261b442014-06-25 12:42:21 -0400481
Jamie Madilla02315b2017-02-23 14:14:47 -0500482void Framebuffer::detachResourceById(const Context *context, GLenum resourceType, GLuint resourceId)
Jamie Madilld1405e52015-03-05 15:41:39 -0500483{
Jamie Madill362876b2016-06-16 14:46:59 -0400484 for (size_t colorIndex = 0; colorIndex < mState.mColorAttachments.size(); ++colorIndex)
Jamie Madilld1405e52015-03-05 15:41:39 -0500485 {
Jamie Madill362876b2016-06-16 14:46:59 -0400486 detachMatchingAttachment(&mState.mColorAttachments[colorIndex], resourceType, resourceId,
487 DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000488 }
489
Jamie Madilla02315b2017-02-23 14:14:47 -0500490 if (context->isWebGL1())
491 {
492 const std::array<FramebufferAttachment *, 3> attachments = {
493 {&mState.mWebGLDepthStencilAttachment, &mState.mWebGLDepthAttachment,
494 &mState.mWebGLStencilAttachment}};
495 for (FramebufferAttachment *attachment : attachments)
496 {
497 if (attachment->isAttached() && attachment->type() == resourceType &&
498 attachment->id() == resourceId)
499 {
500 resetAttachment(context, attachment->getBinding());
501 }
502 }
503 }
504 else
505 {
506 detachMatchingAttachment(&mState.mDepthAttachment, resourceType, resourceId,
507 DIRTY_BIT_DEPTH_ATTACHMENT);
508 detachMatchingAttachment(&mState.mStencilAttachment, resourceType, resourceId,
509 DIRTY_BIT_STENCIL_ATTACHMENT);
510 }
Jamie Madill362876b2016-06-16 14:46:59 -0400511}
512
513void Framebuffer::detachMatchingAttachment(FramebufferAttachment *attachment,
514 GLenum matchType,
515 GLuint matchId,
516 size_t dirtyBit)
517{
518 if (attachment->isAttached() && attachment->type() == matchType && attachment->id() == matchId)
519 {
520 attachment->detach();
521 mDirtyBits.set(dirtyBit);
522 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000523}
524
Corentin Wallez37c39792015-08-20 14:19:46 -0400525const FramebufferAttachment *Framebuffer::getColorbuffer(size_t colorAttachment) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000526{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400527 return mState.getColorAttachment(colorAttachment);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000528}
529
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400530const FramebufferAttachment *Framebuffer::getDepthbuffer() const
Geoff Lang646559f2013-08-15 11:08:15 -0400531{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400532 return mState.getDepthAttachment();
Geoff Lang646559f2013-08-15 11:08:15 -0400533}
534
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400535const FramebufferAttachment *Framebuffer::getStencilbuffer() const
536{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400537 return mState.getStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400538}
539
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400540const FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
541{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400542 return mState.getDepthStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400543}
544
545const FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000546{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400547 return mState.getDepthOrStencilAttachment();
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000548}
549
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500550const FramebufferAttachment *Framebuffer::getStencilOrDepthStencilAttachment() const
551{
552 return mState.getStencilOrDepthStencilAttachment();
553}
554
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400555const FramebufferAttachment *Framebuffer::getReadColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000556{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400557 return mState.getReadAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000558}
559
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000560GLenum Framebuffer::getReadColorbufferType() const
561{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400562 const FramebufferAttachment *readAttachment = mState.getReadAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400563 return (readAttachment != nullptr ? readAttachment->type() : GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000564}
565
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400566const FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000567{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400568 return mState.getFirstColorAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000569}
570
Jamie Madill2d06b732015-04-20 12:53:28 -0400571const FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000572{
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400573 return mState.getAttachment(attachment);
Geoff Lang55ba29c2013-07-11 16:57:53 -0400574}
575
Geoff Langa15472a2015-08-11 11:48:03 -0400576size_t Framebuffer::getDrawbufferStateCount() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000577{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400578 return mState.mDrawBufferStates.size();
Geoff Langa15472a2015-08-11 11:48:03 -0400579}
580
581GLenum Framebuffer::getDrawBufferState(size_t drawBuffer) const
582{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400583 ASSERT(drawBuffer < mState.mDrawBufferStates.size());
584 return mState.mDrawBufferStates[drawBuffer];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000585}
586
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500587const std::vector<GLenum> &Framebuffer::getDrawBufferStates() const
588{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400589 return mState.getDrawBufferStates();
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500590}
591
Geoff Lang164d54e2014-12-01 10:55:33 -0500592void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000593{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400594 auto &drawStates = mState.mDrawBufferStates;
Jamie Madilld1405e52015-03-05 15:41:39 -0500595
596 ASSERT(count <= drawStates.size());
597 std::copy(buffers, buffers + count, drawStates.begin());
598 std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500599 mDirtyBits.set(DIRTY_BIT_DRAW_BUFFERS);
Jamie Madilla4595b82017-01-11 17:36:34 -0500600
601 mState.mEnabledDrawBuffers.reset();
602 for (size_t index = 0; index < count; ++index)
603 {
604 if (drawStates[index] != GL_NONE && mState.mColorAttachments[index].isAttached())
605 {
606 mState.mEnabledDrawBuffers.set(index);
607 }
608 }
Geoff Lang9dd95802014-12-01 11:12:59 -0500609}
610
Geoff Langa15472a2015-08-11 11:48:03 -0400611const FramebufferAttachment *Framebuffer::getDrawBuffer(size_t drawBuffer) const
612{
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400613 return mState.getDrawBuffer(drawBuffer);
Geoff Langa15472a2015-08-11 11:48:03 -0400614}
615
616bool Framebuffer::hasEnabledDrawBuffer() const
617{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400618 for (size_t drawbufferIdx = 0; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
Geoff Langa15472a2015-08-11 11:48:03 -0400619 {
620 if (getDrawBuffer(drawbufferIdx) != nullptr)
621 {
622 return true;
623 }
624 }
625
626 return false;
627}
628
Geoff Lang9dd95802014-12-01 11:12:59 -0500629GLenum Framebuffer::getReadBufferState() const
630{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400631 return mState.mReadBufferState;
Geoff Lang9dd95802014-12-01 11:12:59 -0500632}
633
634void Framebuffer::setReadBuffer(GLenum buffer)
635{
Jamie Madillb885e572015-02-03 16:16:04 -0500636 ASSERT(buffer == GL_BACK || buffer == GL_NONE ||
637 (buffer >= GL_COLOR_ATTACHMENT0 &&
Jamie Madill48ef11b2016-04-27 15:21:52 -0400638 (buffer - GL_COLOR_ATTACHMENT0) < mState.mColorAttachments.size()));
639 mState.mReadBufferState = buffer;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500640 mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000641}
642
Corentin Wallez37c39792015-08-20 14:19:46 -0400643size_t Framebuffer::getNumColorBuffers() const
644{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400645 return mState.mColorAttachments.size();
Corentin Wallez37c39792015-08-20 14:19:46 -0400646}
647
Jamie Madill0df8fe42015-11-24 16:10:24 -0500648bool Framebuffer::hasDepth() const
649{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400650 return (mState.mDepthAttachment.isAttached() && mState.mDepthAttachment.getDepthSize() > 0);
Jamie Madill0df8fe42015-11-24 16:10:24 -0500651}
652
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000653bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000654{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400655 return (mState.mStencilAttachment.isAttached() &&
656 mState.mStencilAttachment.getStencilSize() > 0);
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000657}
658
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000659bool Framebuffer::usingExtendedDrawBuffers() const
660{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400661 for (size_t drawbufferIdx = 1; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000662 {
Geoff Langa15472a2015-08-11 11:48:03 -0400663 if (getDrawBuffer(drawbufferIdx) != nullptr)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000664 {
665 return true;
666 }
667 }
668
669 return false;
670}
671
Geoff Lang9aded172017-04-05 11:07:56 -0400672void Framebuffer::invalidateCompletenessCache()
673{
674 if (mId != 0)
675 {
676 mCachedStatus.reset();
677 }
678}
679
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400680GLenum Framebuffer::checkStatus(const Context *context)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000681{
Corentin Wallezccab69d2017-01-27 16:57:15 -0500682 // The default framebuffer is always complete except when it is surfaceless in which
683 // case it is always unsupported. We return early because the default framebuffer may
684 // not be subject to the same rules as application FBOs. ie, it could have 0x0 size.
Geoff Lang528ce3c2014-12-01 10:44:07 -0500685 if (mId == 0)
686 {
Corentin Wallezccab69d2017-01-27 16:57:15 -0500687 ASSERT(mCachedStatus.valid());
688 ASSERT(mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE ||
689 mCachedStatus.value() == GL_FRAMEBUFFER_UNDEFINED_OES);
690 return mCachedStatus.value();
Geoff Lang528ce3c2014-12-01 10:44:07 -0500691 }
692
Jamie Madill362876b2016-06-16 14:46:59 -0400693 if (hasAnyDirtyBit() || !mCachedStatus.valid())
694 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400695 mCachedStatus = checkStatusImpl(context);
Jamie Madill362876b2016-06-16 14:46:59 -0400696 }
697
698 return mCachedStatus.value();
699}
700
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400701GLenum Framebuffer::checkStatusImpl(const Context *context)
Jamie Madill362876b2016-06-16 14:46:59 -0400702{
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400703 const ContextState &state = context->getContextState();
704
Jamie Madill362876b2016-06-16 14:46:59 -0400705 ASSERT(mId != 0);
706
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400707 bool hasAttachments = false;
708 Optional<unsigned int> colorbufferSize;
709 Optional<int> samples;
JiangYizhou461d9a32017-01-04 16:37:26 +0800710 Optional<GLboolean> fixedSampleLocations;
711 bool hasRenderbuffer = false;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000712
Jamie Madill48ef11b2016-04-27 15:21:52 -0400713 for (const FramebufferAttachment &colorAttachment : mState.mColorAttachments)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000714 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400715 if (colorAttachment.isAttached())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000716 {
Geoff Lang9f10b772017-05-16 15:51:03 -0400717 if (!CheckAttachmentCompleteness(context, colorAttachment))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000718 {
719 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
720 }
daniel@transgaming.com01868132010-08-24 19:21:17 +0000721
Geoff Lang677bb6f2017-04-05 12:40:40 -0400722 const InternalFormat &format = *colorAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -0400723 if (format.depthBits > 0 || format.stencilBits > 0)
724 {
725 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
726 }
727
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400728 if (!CheckAttachmentSampleCompleteness(context, colorAttachment, true, &samples,
729 &fixedSampleLocations))
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000730 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400731 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000732 }
733
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400734 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
735 // in GLES 3.0, there is no such restriction
736 if (state.getClientMajorVersion() < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000737 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400738 if (colorbufferSize.valid())
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000739 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400740 if (format.pixelBytes != colorbufferSize.value())
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000741 {
742 return GL_FRAMEBUFFER_UNSUPPORTED;
743 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000744 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400745 else
746 {
747 colorbufferSize = format.pixelBytes;
748 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000749 }
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400750
751 hasRenderbuffer = hasRenderbuffer || (colorAttachment.type() == GL_RENDERBUFFER);
752 hasAttachments = true;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000753 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000754 }
755
Jamie Madill48ef11b2016-04-27 15:21:52 -0400756 const FramebufferAttachment &depthAttachment = mState.mDepthAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -0400757 if (depthAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000758 {
Geoff Lang9f10b772017-05-16 15:51:03 -0400759 if (!CheckAttachmentCompleteness(context, depthAttachment))
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000760 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000761 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000762 }
763
Geoff Lang677bb6f2017-04-05 12:40:40 -0400764 const InternalFormat &format = *depthAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -0400765 if (format.depthBits == 0)
766 {
767 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000768 }
769
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400770 if (!CheckAttachmentSampleCompleteness(context, depthAttachment, false, &samples,
771 &fixedSampleLocations))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000772 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400773 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000774 }
Sami Väisänena797e062016-05-12 15:23:40 +0300775
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400776 hasRenderbuffer = hasRenderbuffer || (depthAttachment.type() == GL_RENDERBUFFER);
777 hasAttachments = true;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000778 }
779
Jamie Madill48ef11b2016-04-27 15:21:52 -0400780 const FramebufferAttachment &stencilAttachment = mState.mStencilAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -0400781 if (stencilAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000782 {
Geoff Lang9f10b772017-05-16 15:51:03 -0400783 if (!CheckAttachmentCompleteness(context, stencilAttachment))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000784 {
785 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
786 }
787
Geoff Lang677bb6f2017-04-05 12:40:40 -0400788 const InternalFormat &format = *stencilAttachment.getFormat().info;
Geoff Lang677bb6f2017-04-05 12:40:40 -0400789 if (format.stencilBits == 0)
790 {
791 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000792 }
793
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400794 if (!CheckAttachmentSampleCompleteness(context, stencilAttachment, false, &samples,
795 &fixedSampleLocations))
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000796 {
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400797 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000798 }
Corentin Wallez086d59a2016-04-29 09:06:49 -0400799
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400800 hasRenderbuffer = hasRenderbuffer || (stencilAttachment.type() == GL_RENDERBUFFER);
801 hasAttachments = true;
802 }
803
804 // Starting from ES 3.0 stencil and depth, if present, should be the same image
805 if (state.getClientMajorVersion() >= 3 && depthAttachment.isAttached() &&
806 stencilAttachment.isAttached() && stencilAttachment != depthAttachment)
807 {
808 return GL_FRAMEBUFFER_UNSUPPORTED;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000809 }
810
Jamie Madilla02315b2017-02-23 14:14:47 -0500811 // Special additional validation for WebGL 1 DEPTH/STENCIL/DEPTH_STENCIL.
812 if (state.isWebGL1())
813 {
814 if (!mState.mWebGLDepthStencilConsistent)
815 {
816 return GL_FRAMEBUFFER_UNSUPPORTED;
817 }
818
819 if (mState.mWebGLDepthStencilAttachment.isAttached())
820 {
821 if (mState.mWebGLDepthStencilAttachment.getDepthSize() == 0 ||
822 mState.mWebGLDepthStencilAttachment.getStencilSize() == 0)
823 {
824 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
825 }
826 }
827 else if (mState.mStencilAttachment.isAttached() &&
828 mState.mStencilAttachment.getDepthSize() > 0)
829 {
830 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
831 }
832 else if (mState.mDepthAttachment.isAttached() &&
833 mState.mDepthAttachment.getStencilSize() > 0)
834 {
835 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
836 }
837 }
838
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400839 // ES3.1(section 9.4) requires that if no image is attached to the framebuffer, and either the
840 // value of the framebuffer's FRAMEBUFFER_DEFAULT_WIDTH or FRAMEBUFFER_DEFAULT_HEIGHT parameters
841 // is zero, the framebuffer is considered incomplete.
JiangYizhou461d9a32017-01-04 16:37:26 +0800842 GLint defaultWidth = mState.getDefaultWidth();
843 GLint defaultHeight = mState.getDefaultHeight();
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400844 if (!hasAttachments && (defaultWidth == 0 || defaultHeight == 0))
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000845 {
846 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000847 }
848
Geoff Langa0e0aeb2017-04-12 15:06:29 -0400849 // In ES 2.0 and WebGL, all color attachments must have the same width and height.
Jamie Madillcc86d642015-11-24 13:00:07 -0500850 // In ES 3.0, there is no such restriction.
Geoff Langa0e0aeb2017-04-12 15:06:29 -0400851 if ((state.getClientMajorVersion() < 3 || state.getExtensions().webglCompatibility) &&
852 !mState.attachmentsHaveSameDimensions())
Jamie Madillcc86d642015-11-24 13:00:07 -0500853 {
854 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
855 }
856
Geoff Langa1b9d5a2017-05-18 11:22:27 -0400857 // ES3.1(section 9.4) requires that if the attached images are a mix of renderbuffers and
858 // textures, the value of TEXTURE_FIXED_SAMPLE_LOCATIONS must be TRUE for all attached textures.
JiangYizhou461d9a32017-01-04 16:37:26 +0800859 if (fixedSampleLocations.valid() && hasRenderbuffer && !fixedSampleLocations.value())
860 {
861 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE;
862 }
863
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400864 syncState(context);
Jamie Madillcc86d642015-11-24 13:00:07 -0500865 if (!mImpl->checkStatus())
866 {
867 return GL_FRAMEBUFFER_UNSUPPORTED;
868 }
869
870 return GL_FRAMEBUFFER_COMPLETE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000871}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000872
Austin Kinross08332632015-05-05 13:35:47 -0700873Error Framebuffer::discard(size_t count, const GLenum *attachments)
874{
875 return mImpl->discard(count, attachments);
876}
877
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500878Error Framebuffer::invalidate(size_t count, const GLenum *attachments)
Jamie Madill2d96b9e2014-08-29 15:46:47 -0400879{
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500880 return mImpl->invalidate(count, attachments);
Jamie Madill2d96b9e2014-08-29 15:46:47 -0400881}
882
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500883Error Framebuffer::invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area)
Jamie Madill400a4412014-08-29 15:46:45 -0400884{
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500885 return mImpl->invalidateSub(count, attachments, area);
Jamie Madill400a4412014-08-29 15:46:45 -0400886}
887
Jamie Madill8415b5f2016-04-26 13:41:39 -0400888Error Framebuffer::clear(rx::ContextImpl *context, GLbitfield mask)
Geoff Langb04dc822014-12-01 12:02:02 -0500889{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700890 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500891 {
Jamie Madill362876b2016-06-16 14:46:59 -0400892 return gl::NoError();
Jamie Madill984ef412015-11-24 16:10:21 -0500893 }
894
Jamie Madill8415b5f2016-04-26 13:41:39 -0400895 return mImpl->clear(context, mask);
Geoff Langb04dc822014-12-01 12:02:02 -0500896}
897
Jamie Madill8415b5f2016-04-26 13:41:39 -0400898Error Framebuffer::clearBufferfv(rx::ContextImpl *context,
Jamie Madill1b94d432015-08-07 13:23:23 -0400899 GLenum buffer,
900 GLint drawbuffer,
901 const GLfloat *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500902{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700903 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500904 {
Jamie Madill362876b2016-06-16 14:46:59 -0400905 return gl::NoError();
Jamie Madill984ef412015-11-24 16:10:21 -0500906 }
907
Jamie Madill8415b5f2016-04-26 13:41:39 -0400908 return mImpl->clearBufferfv(context, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500909}
910
Jamie Madill8415b5f2016-04-26 13:41:39 -0400911Error Framebuffer::clearBufferuiv(rx::ContextImpl *context,
Jamie Madill1b94d432015-08-07 13:23:23 -0400912 GLenum buffer,
913 GLint drawbuffer,
914 const GLuint *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500915{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700916 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500917 {
Jamie Madill362876b2016-06-16 14:46:59 -0400918 return gl::NoError();
Jamie Madill984ef412015-11-24 16:10:21 -0500919 }
920
Jamie Madill8415b5f2016-04-26 13:41:39 -0400921 return mImpl->clearBufferuiv(context, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500922}
923
Jamie Madill8415b5f2016-04-26 13:41:39 -0400924Error Framebuffer::clearBufferiv(rx::ContextImpl *context,
Jamie Madill1b94d432015-08-07 13:23:23 -0400925 GLenum buffer,
926 GLint drawbuffer,
927 const GLint *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500928{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700929 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500930 {
Jamie Madill362876b2016-06-16 14:46:59 -0400931 return gl::NoError();
Jamie Madill984ef412015-11-24 16:10:21 -0500932 }
933
Jamie Madill8415b5f2016-04-26 13:41:39 -0400934 return mImpl->clearBufferiv(context, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500935}
936
Jamie Madill8415b5f2016-04-26 13:41:39 -0400937Error Framebuffer::clearBufferfi(rx::ContextImpl *context,
Jamie Madill1b94d432015-08-07 13:23:23 -0400938 GLenum buffer,
939 GLint drawbuffer,
940 GLfloat depth,
941 GLint stencil)
Geoff Langb04dc822014-12-01 12:02:02 -0500942{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700943 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500944 {
Jamie Madill362876b2016-06-16 14:46:59 -0400945 return gl::NoError();
Jamie Madill984ef412015-11-24 16:10:21 -0500946 }
947
Jamie Madill8415b5f2016-04-26 13:41:39 -0400948 return mImpl->clearBufferfi(context, buffer, drawbuffer, depth, stencil);
Geoff Langb04dc822014-12-01 12:02:02 -0500949}
950
Geoff Langbce529e2014-12-01 12:48:41 -0500951GLenum Framebuffer::getImplementationColorReadFormat() const
952{
953 return mImpl->getImplementationColorReadFormat();
954}
955
956GLenum Framebuffer::getImplementationColorReadType() const
957{
958 return mImpl->getImplementationColorReadType();
959}
960
Jamie Madill8415b5f2016-04-26 13:41:39 -0400961Error Framebuffer::readPixels(rx::ContextImpl *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500962 const Rectangle &area,
Jamie Madill1b94d432015-08-07 13:23:23 -0400963 GLenum format,
964 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400965 void *pixels) const
Geoff Langbce529e2014-12-01 12:48:41 -0500966{
Jamie Madill362876b2016-06-16 14:46:59 -0400967 ANGLE_TRY(mImpl->readPixels(context, area, format, type, pixels));
Geoff Lang520c4ae2015-05-05 13:12:36 -0400968
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700969 Buffer *unpackBuffer = context->getGLState().getUnpackState().pixelBuffer.get();
Geoff Lang520c4ae2015-05-05 13:12:36 -0400970 if (unpackBuffer)
971 {
972 unpackBuffer->onPixelUnpack();
973 }
974
Jamie Madill362876b2016-06-16 14:46:59 -0400975 return NoError();
Geoff Langbce529e2014-12-01 12:48:41 -0500976}
977
Jamie Madill8415b5f2016-04-26 13:41:39 -0400978Error Framebuffer::blit(rx::ContextImpl *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500979 const Rectangle &sourceArea,
980 const Rectangle &destArea,
Geoff Lang242468f2015-09-24 14:15:41 -0400981 GLbitfield mask,
Jamie Madill8415b5f2016-04-26 13:41:39 -0400982 GLenum filter)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500983{
He Yunchao6be602d2016-12-22 14:33:07 +0800984 GLbitfield blitMask = mask;
985
986 // Note that blitting is called against draw framebuffer.
987 // See the code in gl::Context::blitFramebuffer.
988 if ((mask & GL_COLOR_BUFFER_BIT) && !hasEnabledDrawBuffer())
989 {
990 blitMask &= ~GL_COLOR_BUFFER_BIT;
991 }
992
993 if ((mask & GL_STENCIL_BUFFER_BIT) && mState.getStencilAttachment() == nullptr)
994 {
995 blitMask &= ~GL_STENCIL_BUFFER_BIT;
996 }
997
998 if ((mask & GL_DEPTH_BUFFER_BIT) && mState.getDepthAttachment() == nullptr)
999 {
1000 blitMask &= ~GL_DEPTH_BUFFER_BIT;
1001 }
1002
1003 if (!blitMask)
1004 {
1005 return NoError();
1006 }
1007
1008 return mImpl->blit(context, sourceArea, destArea, blitMask, filter);
Geoff Lang54bd5a42014-12-01 12:51:04 -05001009}
1010
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001011int Framebuffer::getSamples(const Context *context)
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001012{
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001013 if (complete(context))
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001014 {
Jamie Madill362876b2016-06-16 14:46:59 -04001015 // For a complete framebuffer, all attachments must have the same sample count.
1016 // In this case return the first nonzero sample size.
1017 const auto *firstColorAttachment = mState.getFirstColorAttachment();
1018 if (firstColorAttachment)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001019 {
Jamie Madill362876b2016-06-16 14:46:59 -04001020 ASSERT(firstColorAttachment->isAttached());
1021 return firstColorAttachment->getSamples();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001022 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001023 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +00001024
1025 return 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +00001026}
1027
Corentin Wallezccab69d2017-01-27 16:57:15 -05001028Error Framebuffer::getSamplePosition(size_t index, GLfloat *xy) const
1029{
1030 ANGLE_TRY(mImpl->getSamplePosition(index, xy));
1031 return gl::NoError();
1032}
1033
Jamie Madille261b442014-06-25 12:42:21 -04001034bool Framebuffer::hasValidDepthStencil() const
1035{
Jamie Madill48ef11b2016-04-27 15:21:52 -04001036 return mState.getDepthStencilAttachment() != nullptr;
Jamie Madille261b442014-06-25 12:42:21 -04001037}
1038
Jamie Madilla02315b2017-02-23 14:14:47 -05001039void Framebuffer::setAttachment(const Context *context,
1040 GLenum type,
Jamie Madill2d06b732015-04-20 12:53:28 -04001041 GLenum binding,
1042 const ImageIndex &textureIndex,
1043 FramebufferAttachmentObject *resource)
Geoff Langab75a052014-10-15 12:56:37 -04001044{
Jamie Madilla02315b2017-02-23 14:14:47 -05001045 // Context may be null in unit tests.
1046 if (!context || !context->isWebGL1())
1047 {
1048 setAttachmentImpl(type, binding, textureIndex, resource);
1049 return;
1050 }
1051
1052 switch (binding)
1053 {
1054 case GL_DEPTH_STENCIL:
1055 case GL_DEPTH_STENCIL_ATTACHMENT:
1056 mState.mWebGLDepthStencilAttachment.attach(type, binding, textureIndex, resource);
1057 break;
1058 case GL_DEPTH:
1059 case GL_DEPTH_ATTACHMENT:
1060 mState.mWebGLDepthAttachment.attach(type, binding, textureIndex, resource);
1061 break;
1062 case GL_STENCIL:
1063 case GL_STENCIL_ATTACHMENT:
1064 mState.mWebGLStencilAttachment.attach(type, binding, textureIndex, resource);
1065 break;
1066 default:
1067 setAttachmentImpl(type, binding, textureIndex, resource);
1068 return;
1069 }
1070
1071 commitWebGL1DepthStencilIfConsistent();
1072}
1073
1074void Framebuffer::commitWebGL1DepthStencilIfConsistent()
1075{
1076 int count = 0;
1077
1078 std::array<FramebufferAttachment *, 3> attachments = {{&mState.mWebGLDepthStencilAttachment,
1079 &mState.mWebGLDepthAttachment,
1080 &mState.mWebGLStencilAttachment}};
1081 for (FramebufferAttachment *attachment : attachments)
1082 {
1083 if (attachment->isAttached())
1084 {
1085 count++;
1086 }
1087 }
1088
1089 mState.mWebGLDepthStencilConsistent = (count <= 1);
1090 if (!mState.mWebGLDepthStencilConsistent)
1091 {
1092 // Inconsistent.
1093 return;
1094 }
1095
Geoff Lange466c552017-03-17 15:24:12 -04001096 auto getImageIndexIfTextureAttachment = [](const FramebufferAttachment &attachment) {
1097 if (attachment.type() == GL_TEXTURE)
1098 {
1099 return attachment.getTextureImageIndex();
1100 }
1101 else
1102 {
1103 return ImageIndex::MakeInvalid();
1104 }
1105 };
1106
Jamie Madilla02315b2017-02-23 14:14:47 -05001107 if (mState.mWebGLDepthAttachment.isAttached())
1108 {
1109 const auto &depth = mState.mWebGLDepthAttachment;
Geoff Lange466c552017-03-17 15:24:12 -04001110 setAttachmentImpl(depth.type(), GL_DEPTH_ATTACHMENT,
1111 getImageIndexIfTextureAttachment(depth), depth.getResource());
Jamie Madilla02315b2017-02-23 14:14:47 -05001112 setAttachmentImpl(GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex::MakeInvalid(), nullptr);
1113 }
1114 else if (mState.mWebGLStencilAttachment.isAttached())
1115 {
1116 const auto &stencil = mState.mWebGLStencilAttachment;
1117 setAttachmentImpl(GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex::MakeInvalid(), nullptr);
Geoff Lange466c552017-03-17 15:24:12 -04001118 setAttachmentImpl(stencil.type(), GL_STENCIL_ATTACHMENT,
1119 getImageIndexIfTextureAttachment(stencil), stencil.getResource());
Jamie Madilla02315b2017-02-23 14:14:47 -05001120 }
1121 else if (mState.mWebGLDepthStencilAttachment.isAttached())
1122 {
1123 const auto &depthStencil = mState.mWebGLDepthStencilAttachment;
Geoff Lange466c552017-03-17 15:24:12 -04001124 setAttachmentImpl(depthStencil.type(), GL_DEPTH_ATTACHMENT,
1125 getImageIndexIfTextureAttachment(depthStencil),
Jamie Madilla02315b2017-02-23 14:14:47 -05001126 depthStencil.getResource());
Geoff Lange466c552017-03-17 15:24:12 -04001127 setAttachmentImpl(depthStencil.type(), GL_STENCIL_ATTACHMENT,
1128 getImageIndexIfTextureAttachment(depthStencil),
Jamie Madilla02315b2017-02-23 14:14:47 -05001129 depthStencil.getResource());
1130 }
1131 else
1132 {
1133 setAttachmentImpl(GL_NONE, GL_DEPTH_ATTACHMENT, ImageIndex::MakeInvalid(), nullptr);
1134 setAttachmentImpl(GL_NONE, GL_STENCIL_ATTACHMENT, ImageIndex::MakeInvalid(), nullptr);
1135 }
1136}
1137
1138void Framebuffer::setAttachmentImpl(GLenum type,
1139 GLenum binding,
1140 const ImageIndex &textureIndex,
1141 FramebufferAttachmentObject *resource)
1142{
Jamie Madilla02315b2017-02-23 14:14:47 -05001143 switch (binding)
1144 {
Jamie Madillb8126692017-04-05 11:22:17 -04001145 case GL_DEPTH_STENCIL:
1146 case GL_DEPTH_STENCIL_ATTACHMENT:
1147 {
1148 // ensure this is a legitimate depth+stencil format
1149 FramebufferAttachmentObject *attachmentObj = resource;
1150 if (resource)
1151 {
Jamie Madill4fd95d52017-04-05 11:22:18 -04001152 const Format &format = resource->getAttachmentFormat(binding, textureIndex);
Jamie Madillb8126692017-04-05 11:22:17 -04001153 if (format.info->depthBits == 0 || format.info->stencilBits == 0)
1154 {
1155 // Attaching nullptr detaches the current attachment.
1156 attachmentObj = nullptr;
1157 }
1158 }
1159
1160 updateAttachment(&mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
1161 &mDirtyDepthAttachmentBinding, type, binding, textureIndex,
1162 attachmentObj);
1163 updateAttachment(&mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
1164 &mDirtyStencilAttachmentBinding, type, binding, textureIndex,
1165 attachmentObj);
1166 return;
1167 }
1168
Jamie Madilla02315b2017-02-23 14:14:47 -05001169 case GL_DEPTH:
1170 case GL_DEPTH_ATTACHMENT:
Jamie Madillb8126692017-04-05 11:22:17 -04001171 updateAttachment(&mState.mDepthAttachment, DIRTY_BIT_DEPTH_ATTACHMENT,
1172 &mDirtyDepthAttachmentBinding, type, binding, textureIndex, resource);
Jamie Madill2d06b732015-04-20 12:53:28 -04001173 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001174
Jamie Madilla02315b2017-02-23 14:14:47 -05001175 case GL_STENCIL:
1176 case GL_STENCIL_ATTACHMENT:
Jamie Madillb8126692017-04-05 11:22:17 -04001177 updateAttachment(&mState.mStencilAttachment, DIRTY_BIT_STENCIL_ATTACHMENT,
1178 &mDirtyStencilAttachmentBinding, type, binding, textureIndex,
1179 resource);
Jamie Madilla02315b2017-02-23 14:14:47 -05001180 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001181
Jamie Madilla02315b2017-02-23 14:14:47 -05001182 case GL_BACK:
1183 mState.mColorAttachments[0].attach(type, binding, textureIndex, resource);
1184 mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0);
1185 // No need for a resource binding for the default FBO, it's always complete.
1186 break;
Jamie Madillb8126692017-04-05 11:22:17 -04001187
Jamie Madilla02315b2017-02-23 14:14:47 -05001188 default:
1189 {
1190 size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
1191 ASSERT(colorIndex < mState.mColorAttachments.size());
Jamie Madillb8126692017-04-05 11:22:17 -04001192 size_t dirtyBit = DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex;
1193 updateAttachment(&mState.mColorAttachments[colorIndex], dirtyBit,
1194 &mDirtyColorAttachmentBindings[colorIndex], type, binding,
1195 textureIndex, resource);
Jamie Madilla02315b2017-02-23 14:14:47 -05001196
1197 bool enabled = (type != GL_NONE && getDrawBufferState(colorIndex) != GL_NONE);
1198 mState.mEnabledDrawBuffers.set(colorIndex, enabled);
Jamie Madill2d06b732015-04-20 12:53:28 -04001199 }
Jamie Madilla02315b2017-02-23 14:14:47 -05001200 break;
Geoff Langab75a052014-10-15 12:56:37 -04001201 }
1202}
1203
Jamie Madillb8126692017-04-05 11:22:17 -04001204void Framebuffer::updateAttachment(FramebufferAttachment *attachment,
1205 size_t dirtyBit,
1206 OnAttachmentDirtyBinding *onDirtyBinding,
1207 GLenum type,
1208 GLenum binding,
1209 const ImageIndex &textureIndex,
1210 FramebufferAttachmentObject *resource)
1211{
1212 attachment->attach(type, binding, textureIndex, resource);
1213 mDirtyBits.set(dirtyBit);
1214 BindResourceChannel(onDirtyBinding, resource);
1215}
1216
Jamie Madilla02315b2017-02-23 14:14:47 -05001217void Framebuffer::resetAttachment(const Context *context, GLenum binding)
Jamie Madill2d06b732015-04-20 12:53:28 -04001218{
Jamie Madilla02315b2017-02-23 14:14:47 -05001219 setAttachment(context, GL_NONE, binding, ImageIndex::MakeInvalid(), nullptr);
Jamie Madill2d06b732015-04-20 12:53:28 -04001220}
1221
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001222void Framebuffer::syncState(const Context *context)
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001223{
1224 if (mDirtyBits.any())
1225 {
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001226 mImpl->syncState(rx::SafeGetImpl(context), mDirtyBits);
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001227 mDirtyBits.reset();
Corentin Wallezccab69d2017-01-27 16:57:15 -05001228 if (mId != 0)
1229 {
1230 mCachedStatus.reset();
1231 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001232 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001233}
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001234
Jamie Madill1e5499d2017-04-05 11:22:16 -04001235void Framebuffer::signal(uint32_t token)
Jamie Madill51f40ec2016-06-15 14:06:00 -04001236{
Jamie Madill362876b2016-06-16 14:46:59 -04001237 // TOOD(jmadill): Make this only update individual attachments to do less work.
1238 mCachedStatus.reset();
Jamie Madill51f40ec2016-06-15 14:06:00 -04001239}
1240
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001241bool Framebuffer::complete(const Context *context)
Jamie Madill51f40ec2016-06-15 14:06:00 -04001242{
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001243 return (checkStatus(context) == GL_FRAMEBUFFER_COMPLETE);
1244}
1245
1246bool Framebuffer::cachedComplete() const
1247{
1248 return (mCachedStatus.valid() && mCachedStatus == GL_FRAMEBUFFER_COMPLETE);
Jamie Madill51f40ec2016-06-15 14:06:00 -04001249}
1250
Jamie Madilla4595b82017-01-11 17:36:34 -05001251bool Framebuffer::formsRenderingFeedbackLoopWith(const State &state) const
1252{
1253 const Program *program = state.getProgram();
1254
1255 // TODO(jmadill): Default framebuffer feedback loops.
1256 if (mId == 0)
1257 {
1258 return false;
1259 }
1260
1261 // The bitset will skip inactive draw buffers.
Jamie Madill6de51852017-04-12 09:53:01 -04001262 for (size_t drawIndex : mState.mEnabledDrawBuffers)
Jamie Madilla4595b82017-01-11 17:36:34 -05001263 {
1264 const FramebufferAttachment *attachment = getDrawBuffer(drawIndex);
1265 if (attachment && attachment->type() == GL_TEXTURE)
1266 {
1267 // Validate the feedback loop.
1268 if (program->samplesFromTexture(state, attachment->id()))
1269 {
1270 return true;
1271 }
1272 }
1273 }
1274
Jamie Madill1d37bc52017-02-02 19:59:58 -05001275 // Validate depth-stencil feedback loop.
1276 const auto &dsState = state.getDepthStencilState();
1277
1278 // We can skip the feedback loop checks if depth/stencil is masked out or disabled.
1279 const FramebufferAttachment *depth = getDepthbuffer();
1280 if (depth && depth->type() == GL_TEXTURE && dsState.depthTest && dsState.depthMask)
1281 {
1282 if (program->samplesFromTexture(state, depth->id()))
1283 {
1284 return true;
1285 }
1286 }
1287
1288 // Note: we assume the front and back masks are the same for WebGL.
1289 const FramebufferAttachment *stencil = getStencilbuffer();
1290 ASSERT(dsState.stencilBackWritemask == dsState.stencilWritemask);
1291 if (stencil && stencil->type() == GL_TEXTURE && dsState.stencilTest &&
1292 dsState.stencilWritemask != 0)
1293 {
1294 // Skip the feedback loop check if depth/stencil point to the same resource.
1295 if (!depth || *stencil != *depth)
1296 {
1297 if (program->samplesFromTexture(state, stencil->id()))
1298 {
1299 return true;
1300 }
1301 }
1302 }
1303
Jamie Madilla4595b82017-01-11 17:36:34 -05001304 return false;
1305}
1306
Jamie Madillfd3dd432017-02-02 19:59:59 -05001307bool Framebuffer::formsCopyingFeedbackLoopWith(GLuint copyTextureID,
1308 GLint copyTextureLevel,
1309 GLint copyTextureLayer) const
Jamie Madillf695a3a2017-01-11 17:36:35 -05001310{
1311 if (mId == 0)
1312 {
1313 // It seems impossible to form a texture copying feedback loop with the default FBO.
1314 return false;
1315 }
1316
1317 const FramebufferAttachment *readAttachment = getReadColorbuffer();
1318 ASSERT(readAttachment);
1319
1320 if (readAttachment->isTextureWithId(copyTextureID))
1321 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05001322 const auto &imageIndex = readAttachment->getTextureImageIndex();
1323 if (imageIndex.mipIndex == copyTextureLevel)
Jamie Madillf695a3a2017-01-11 17:36:35 -05001324 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05001325 // Check 3D/Array texture layers.
1326 return imageIndex.layerIndex == ImageIndex::ENTIRE_LEVEL ||
1327 copyTextureLayer == ImageIndex::ENTIRE_LEVEL ||
1328 imageIndex.layerIndex == copyTextureLayer;
Jamie Madillf695a3a2017-01-11 17:36:35 -05001329 }
1330 }
1331 return false;
1332}
1333
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001334GLint Framebuffer::getDefaultWidth() const
1335{
1336 return mState.getDefaultWidth();
1337}
1338
1339GLint Framebuffer::getDefaultHeight() const
1340{
1341 return mState.getDefaultHeight();
1342}
1343
1344GLint Framebuffer::getDefaultSamples() const
1345{
1346 return mState.getDefaultSamples();
1347}
1348
1349GLboolean Framebuffer::getDefaultFixedSampleLocations() const
1350{
1351 return mState.getDefaultFixedSampleLocations();
1352}
1353
1354void Framebuffer::setDefaultWidth(GLint defaultWidth)
1355{
1356 mState.mDefaultWidth = defaultWidth;
1357 mDirtyBits.set(DIRTY_BIT_DEFAULT_WIDTH);
1358}
1359
1360void Framebuffer::setDefaultHeight(GLint defaultHeight)
1361{
1362 mState.mDefaultHeight = defaultHeight;
1363 mDirtyBits.set(DIRTY_BIT_DEFAULT_HEIGHT);
1364}
1365
1366void Framebuffer::setDefaultSamples(GLint defaultSamples)
1367{
1368 mState.mDefaultSamples = defaultSamples;
1369 mDirtyBits.set(DIRTY_BIT_DEFAULT_SAMPLES);
1370}
1371
1372void Framebuffer::setDefaultFixedSampleLocations(GLboolean defaultFixedSampleLocations)
1373{
1374 mState.mDefaultFixedSampleLocations = defaultFixedSampleLocations;
1375 mDirtyBits.set(DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS);
1376}
1377
Jamie Madilldd43e6c2017-03-24 14:18:49 -04001378// TODO(jmadill): Remove this kludge.
1379GLenum Framebuffer::checkStatus(const ValidationContext *context)
1380{
1381 return checkStatus(static_cast<const Context *>(context));
1382}
1383
1384int Framebuffer::getSamples(const ValidationContext *context)
1385{
1386 return getSamples(static_cast<const Context *>(context));
1387}
1388
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001389} // namespace gl