blob: 7371bc7181d6f98f7d11d054d4f61bea0d2cf493 [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 Madilla4595b82017-01-11 17:36:34 -050012#include "common/BitSetIterator.h"
Jamie Madillcc86d642015-11-24 13:00:07 -050013#include "common/Optional.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
37void BindResourceChannel(ChannelBinding *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
42} // anonymous namespace
Jamie Madilld1405e52015-03-05 15:41:39 -050043
Jamie Madill6f60d052017-02-22 15:20:11 -050044// This constructor is only used for default framebuffers.
Jamie Madill48ef11b2016-04-27 15:21:52 -040045FramebufferState::FramebufferState()
Geoff Lang70d0f492015-12-10 17:45:46 -050046 : mLabel(),
47 mColorAttachments(1),
Jamie Madill6f60d052017-02-22 15:20:11 -050048 mDrawBufferStates(1, GL_BACK),
49 mReadBufferState(GL_BACK),
JiangYizhouf7bbc8a2016-11-16 09:57:22 +080050 mDefaultWidth(0),
51 mDefaultHeight(0),
52 mDefaultSamples(0),
53 mDefaultFixedSampleLocations(GL_FALSE)
Corentin Wallez37c39792015-08-20 14:19:46 -040054{
Jamie Madilla4595b82017-01-11 17:36:34 -050055 mEnabledDrawBuffers.set(0);
Corentin Wallez37c39792015-08-20 14:19:46 -040056}
57
Jamie Madill48ef11b2016-04-27 15:21:52 -040058FramebufferState::FramebufferState(const Caps &caps)
Geoff Lang70d0f492015-12-10 17:45:46 -050059 : mLabel(),
60 mColorAttachments(caps.maxColorAttachments),
Jamie Madilld1405e52015-03-05 15:41:39 -050061 mDrawBufferStates(caps.maxDrawBuffers, GL_NONE),
JiangYizhouf7bbc8a2016-11-16 09:57:22 +080062 mReadBufferState(GL_COLOR_ATTACHMENT0_EXT),
63 mDefaultWidth(0),
64 mDefaultHeight(0),
65 mDefaultSamples(0),
66 mDefaultFixedSampleLocations(GL_FALSE)
Jamie Madilld1405e52015-03-05 15:41:39 -050067{
Geoff Langa15472a2015-08-11 11:48:03 -040068 ASSERT(mDrawBufferStates.size() > 0);
Jamie Madilld1405e52015-03-05 15:41:39 -050069 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
70}
71
Jamie Madill48ef11b2016-04-27 15:21:52 -040072FramebufferState::~FramebufferState()
Jamie Madilld1405e52015-03-05 15:41:39 -050073{
Jamie Madilld1405e52015-03-05 15:41:39 -050074}
75
Jamie Madill48ef11b2016-04-27 15:21:52 -040076const std::string &FramebufferState::getLabel()
Geoff Lang70d0f492015-12-10 17:45:46 -050077{
78 return mLabel;
79}
80
Geoff Lang4b7f12b2016-06-21 16:47:07 -040081const FramebufferAttachment *FramebufferState::getAttachment(GLenum attachment) const
82{
83 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
84 {
85 return getColorAttachment(attachment - GL_COLOR_ATTACHMENT0);
86 }
87
88 switch (attachment)
89 {
90 case GL_COLOR:
91 case GL_BACK:
92 return getColorAttachment(0);
93 case GL_DEPTH:
94 case GL_DEPTH_ATTACHMENT:
95 return getDepthAttachment();
96 case GL_STENCIL:
97 case GL_STENCIL_ATTACHMENT:
98 return getStencilAttachment();
99 case GL_DEPTH_STENCIL:
100 case GL_DEPTH_STENCIL_ATTACHMENT:
101 return getDepthStencilAttachment();
102 default:
103 UNREACHABLE();
104 return nullptr;
105 }
106}
107
Jamie Madill48ef11b2016-04-27 15:21:52 -0400108const FramebufferAttachment *FramebufferState::getReadAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500109{
Antoine Labour2ec65dc2016-11-30 16:28:58 -0800110 if (mReadBufferState == GL_NONE)
111 {
112 return nullptr;
113 }
Jamie Madill7147f012015-03-05 15:41:40 -0500114 ASSERT(mReadBufferState == GL_BACK || (mReadBufferState >= GL_COLOR_ATTACHMENT0 && mReadBufferState <= GL_COLOR_ATTACHMENT15));
115 size_t readIndex = (mReadBufferState == GL_BACK ? 0 : static_cast<size_t>(mReadBufferState - GL_COLOR_ATTACHMENT0));
116 ASSERT(readIndex < mColorAttachments.size());
Jamie Madill2d06b732015-04-20 12:53:28 -0400117 return mColorAttachments[readIndex].isAttached() ? &mColorAttachments[readIndex] : nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500118}
119
Jamie Madill7b57b9d2017-01-13 09:33:38 -0500120const FramebufferAttachment *FramebufferState::getFirstNonNullAttachment() const
121{
122 auto *colorAttachment = getFirstColorAttachment();
123 if (colorAttachment)
124 {
125 return colorAttachment;
126 }
127 return getDepthOrStencilAttachment();
128}
129
Jamie Madill48ef11b2016-04-27 15:21:52 -0400130const FramebufferAttachment *FramebufferState::getFirstColorAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500131{
Jamie Madill2d06b732015-04-20 12:53:28 -0400132 for (const FramebufferAttachment &colorAttachment : mColorAttachments)
Jamie Madill7147f012015-03-05 15:41:40 -0500133 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400134 if (colorAttachment.isAttached())
Jamie Madill7147f012015-03-05 15:41:40 -0500135 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400136 return &colorAttachment;
Jamie Madill7147f012015-03-05 15:41:40 -0500137 }
138 }
139
140 return nullptr;
141}
142
Jamie Madill48ef11b2016-04-27 15:21:52 -0400143const FramebufferAttachment *FramebufferState::getDepthOrStencilAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500144{
Jamie Madill2d06b732015-04-20 12:53:28 -0400145 if (mDepthAttachment.isAttached())
146 {
147 return &mDepthAttachment;
148 }
149 if (mStencilAttachment.isAttached())
150 {
151 return &mStencilAttachment;
152 }
153 return nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500154}
155
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500156const FramebufferAttachment *FramebufferState::getStencilOrDepthStencilAttachment() const
157{
158 if (mStencilAttachment.isAttached())
159 {
160 return &mStencilAttachment;
161 }
162 return getDepthStencilAttachment();
163}
164
Jamie Madill48ef11b2016-04-27 15:21:52 -0400165const FramebufferAttachment *FramebufferState::getColorAttachment(size_t colorAttachment) const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400166{
167 ASSERT(colorAttachment < mColorAttachments.size());
Jamie Madill2d06b732015-04-20 12:53:28 -0400168 return mColorAttachments[colorAttachment].isAttached() ?
169 &mColorAttachments[colorAttachment] :
170 nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400171}
172
Jamie Madill48ef11b2016-04-27 15:21:52 -0400173const FramebufferAttachment *FramebufferState::getDepthAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400174{
Jamie Madill2d06b732015-04-20 12:53:28 -0400175 return mDepthAttachment.isAttached() ? &mDepthAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400176}
177
Jamie Madill48ef11b2016-04-27 15:21:52 -0400178const FramebufferAttachment *FramebufferState::getStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400179{
Jamie Madill2d06b732015-04-20 12:53:28 -0400180 return mStencilAttachment.isAttached() ? &mStencilAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400181}
182
Jamie Madill48ef11b2016-04-27 15:21:52 -0400183const FramebufferAttachment *FramebufferState::getDepthStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400184{
185 // A valid depth-stencil attachment has the same resource bound to both the
186 // depth and stencil attachment points.
Jamie Madill2d06b732015-04-20 12:53:28 -0400187 if (mDepthAttachment.isAttached() && mStencilAttachment.isAttached() &&
Jamie Madill44f26482016-11-18 12:49:15 -0500188 mDepthAttachment == mStencilAttachment)
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400189 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400190 return &mDepthAttachment;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400191 }
192
193 return nullptr;
194}
195
Jamie Madill48ef11b2016-04-27 15:21:52 -0400196bool FramebufferState::attachmentsHaveSameDimensions() const
Jamie Madillcc86d642015-11-24 13:00:07 -0500197{
198 Optional<Extents> attachmentSize;
199
200 auto hasMismatchedSize = [&attachmentSize](const FramebufferAttachment &attachment)
201 {
202 if (!attachment.isAttached())
203 {
204 return false;
205 }
206
207 if (!attachmentSize.valid())
208 {
209 attachmentSize = attachment.getSize();
210 return false;
211 }
212
213 return (attachment.getSize() != attachmentSize.value());
214 };
215
216 for (const auto &attachment : mColorAttachments)
217 {
218 if (hasMismatchedSize(attachment))
219 {
220 return false;
221 }
222 }
223
224 if (hasMismatchedSize(mDepthAttachment))
225 {
226 return false;
227 }
228
229 return !hasMismatchedSize(mStencilAttachment);
230}
231
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400232const gl::FramebufferAttachment *FramebufferState::getDrawBuffer(size_t drawBufferIdx) const
233{
234 ASSERT(drawBufferIdx < mDrawBufferStates.size());
235 if (mDrawBufferStates[drawBufferIdx] != GL_NONE)
236 {
237 // ES3 spec: "If the GL is bound to a draw framebuffer object, the ith buffer listed in bufs
238 // must be COLOR_ATTACHMENTi or NONE"
239 ASSERT(mDrawBufferStates[drawBufferIdx] == GL_COLOR_ATTACHMENT0 + drawBufferIdx ||
240 (drawBufferIdx == 0 && mDrawBufferStates[drawBufferIdx] == GL_BACK));
241 return getAttachment(mDrawBufferStates[drawBufferIdx]);
242 }
243 else
244 {
245 return nullptr;
246 }
247}
248
249size_t FramebufferState::getDrawBufferCount() const
250{
251 return mDrawBufferStates.size();
252}
253
Geoff Langb21e20d2016-07-19 15:35:41 -0400254bool FramebufferState::colorAttachmentsAreUniqueImages() const
255{
256 for (size_t firstAttachmentIdx = 0; firstAttachmentIdx < mColorAttachments.size();
257 firstAttachmentIdx++)
258 {
259 const gl::FramebufferAttachment &firstAttachment = mColorAttachments[firstAttachmentIdx];
260 if (!firstAttachment.isAttached())
261 {
262 continue;
263 }
264
265 for (size_t secondAttachmentIdx = firstAttachmentIdx + 1;
266 secondAttachmentIdx < mColorAttachments.size(); secondAttachmentIdx++)
267 {
268 const gl::FramebufferAttachment &secondAttachment =
269 mColorAttachments[secondAttachmentIdx];
270 if (!secondAttachment.isAttached())
271 {
272 continue;
273 }
274
275 if (firstAttachment == secondAttachment)
276 {
277 return false;
278 }
279 }
280 }
281
282 return true;
283}
284
Jamie Madill7aea7e02016-05-10 10:39:45 -0400285Framebuffer::Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id)
Jamie Madill362876b2016-06-16 14:46:59 -0400286 : mState(caps),
287 mImpl(factory->createFramebuffer(mState)),
288 mId(id),
289 mCachedStatus(),
290 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
291 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000292{
Corentin Wallez37c39792015-08-20 14:19:46 -0400293 ASSERT(mId != 0);
294 ASSERT(mImpl != nullptr);
Jamie Madill362876b2016-06-16 14:46:59 -0400295 ASSERT(mState.mColorAttachments.size() == static_cast<size_t>(caps.maxColorAttachments));
296
297 for (size_t colorIndex = 0; colorIndex < mState.mColorAttachments.size(); ++colorIndex)
298 {
299 mDirtyColorAttachmentBindings.push_back(ChannelBinding(
300 this, static_cast<SignalToken>(DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex)));
301 }
Corentin Wallez37c39792015-08-20 14:19:46 -0400302}
303
Jamie Madill6f60d052017-02-22 15:20:11 -0500304Framebuffer::Framebuffer(egl::Surface *surface)
Jamie Madill362876b2016-06-16 14:46:59 -0400305 : mState(),
Jamie Madill6f60d052017-02-22 15:20:11 -0500306 mImpl(surface->getImplementation()->createDefaultFramebuffer(mState)),
Jamie Madill362876b2016-06-16 14:46:59 -0400307 mId(0),
308 mCachedStatus(GL_FRAMEBUFFER_COMPLETE),
309 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
310 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
Corentin Wallez37c39792015-08-20 14:19:46 -0400311{
Geoff Langda88add2014-12-01 10:22:01 -0500312 ASSERT(mImpl != nullptr);
Jamie Madill362876b2016-06-16 14:46:59 -0400313 mDirtyColorAttachmentBindings.push_back(
314 ChannelBinding(this, static_cast<SignalToken>(DIRTY_BIT_COLOR_ATTACHMENT_0)));
Jamie Madill6f60d052017-02-22 15:20:11 -0500315
316 setAttachment(GL_FRAMEBUFFER_DEFAULT, GL_BACK, gl::ImageIndex::MakeInvalid(), surface);
317
318 if (surface->getConfig()->depthSize > 0)
319 {
320 setAttachment(GL_FRAMEBUFFER_DEFAULT, GL_DEPTH, gl::ImageIndex::MakeInvalid(), surface);
321 }
322
323 if (surface->getConfig()->stencilSize > 0)
324 {
325 setAttachment(GL_FRAMEBUFFER_DEFAULT, GL_STENCIL, gl::ImageIndex::MakeInvalid(), surface);
326 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000327}
328
Corentin Wallezccab69d2017-01-27 16:57:15 -0500329Framebuffer::Framebuffer(rx::GLImplFactory *factory)
330 : mState(),
331 mImpl(factory->createFramebuffer(mState)),
332 mId(0),
333 mCachedStatus(GL_FRAMEBUFFER_UNDEFINED_OES),
334 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
335 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
336{
337 mDirtyColorAttachmentBindings.push_back(
338 ChannelBinding(this, static_cast<SignalToken>(DIRTY_BIT_COLOR_ATTACHMENT_0)));
339}
340
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000341Framebuffer::~Framebuffer()
342{
Geoff Langda88add2014-12-01 10:22:01 -0500343 SafeDelete(mImpl);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000344}
345
Jamie Madill6c1f6712017-02-14 19:08:04 -0500346void Framebuffer::destroy(const Context *context)
347{
348 mImpl->destroy(rx::SafeGetImpl(context));
349}
350
351void Framebuffer::destroyDefault(const egl::Display *display)
352{
353 mImpl->destroyDefault(rx::SafeGetImpl(display));
354}
355
Geoff Lang70d0f492015-12-10 17:45:46 -0500356void Framebuffer::setLabel(const std::string &label)
357{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400358 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -0500359}
360
361const std::string &Framebuffer::getLabel() const
362{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400363 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -0500364}
365
Jamie Madille261b442014-06-25 12:42:21 -0400366void Framebuffer::detachTexture(GLuint textureId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000367{
Jamie Madilld1405e52015-03-05 15:41:39 -0500368 detachResourceById(GL_TEXTURE, textureId);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000369}
370
Jamie Madille261b442014-06-25 12:42:21 -0400371void Framebuffer::detachRenderbuffer(GLuint renderbufferId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000372{
Jamie Madilld1405e52015-03-05 15:41:39 -0500373 detachResourceById(GL_RENDERBUFFER, renderbufferId);
374}
Jamie Madille261b442014-06-25 12:42:21 -0400375
Jamie Madilld1405e52015-03-05 15:41:39 -0500376void Framebuffer::detachResourceById(GLenum resourceType, GLuint resourceId)
377{
Jamie Madill362876b2016-06-16 14:46:59 -0400378 for (size_t colorIndex = 0; colorIndex < mState.mColorAttachments.size(); ++colorIndex)
Jamie Madilld1405e52015-03-05 15:41:39 -0500379 {
Jamie Madill362876b2016-06-16 14:46:59 -0400380 detachMatchingAttachment(&mState.mColorAttachments[colorIndex], resourceType, resourceId,
381 DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000382 }
383
Jamie Madill362876b2016-06-16 14:46:59 -0400384 detachMatchingAttachment(&mState.mDepthAttachment, resourceType, resourceId,
385 DIRTY_BIT_DEPTH_ATTACHMENT);
386 detachMatchingAttachment(&mState.mStencilAttachment, resourceType, resourceId,
387 DIRTY_BIT_STENCIL_ATTACHMENT);
388}
389
390void Framebuffer::detachMatchingAttachment(FramebufferAttachment *attachment,
391 GLenum matchType,
392 GLuint matchId,
393 size_t dirtyBit)
394{
395 if (attachment->isAttached() && attachment->type() == matchType && attachment->id() == matchId)
396 {
397 attachment->detach();
398 mDirtyBits.set(dirtyBit);
399 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000400}
401
Corentin Wallez37c39792015-08-20 14:19:46 -0400402const FramebufferAttachment *Framebuffer::getColorbuffer(size_t colorAttachment) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000403{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400404 return mState.getColorAttachment(colorAttachment);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000405}
406
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400407const FramebufferAttachment *Framebuffer::getDepthbuffer() const
Geoff Lang646559f2013-08-15 11:08:15 -0400408{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400409 return mState.getDepthAttachment();
Geoff Lang646559f2013-08-15 11:08:15 -0400410}
411
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400412const FramebufferAttachment *Framebuffer::getStencilbuffer() const
413{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400414 return mState.getStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400415}
416
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400417const FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
418{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400419 return mState.getDepthStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400420}
421
422const FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000423{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400424 return mState.getDepthOrStencilAttachment();
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000425}
426
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500427const FramebufferAttachment *Framebuffer::getStencilOrDepthStencilAttachment() const
428{
429 return mState.getStencilOrDepthStencilAttachment();
430}
431
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400432const FramebufferAttachment *Framebuffer::getReadColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000433{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400434 return mState.getReadAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000435}
436
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000437GLenum Framebuffer::getReadColorbufferType() const
438{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400439 const FramebufferAttachment *readAttachment = mState.getReadAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400440 return (readAttachment != nullptr ? readAttachment->type() : GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000441}
442
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400443const FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000444{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400445 return mState.getFirstColorAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000446}
447
Jamie Madill2d06b732015-04-20 12:53:28 -0400448const FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000449{
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400450 return mState.getAttachment(attachment);
Geoff Lang55ba29c2013-07-11 16:57:53 -0400451}
452
Geoff Langa15472a2015-08-11 11:48:03 -0400453size_t Framebuffer::getDrawbufferStateCount() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000454{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400455 return mState.mDrawBufferStates.size();
Geoff Langa15472a2015-08-11 11:48:03 -0400456}
457
458GLenum Framebuffer::getDrawBufferState(size_t drawBuffer) const
459{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400460 ASSERT(drawBuffer < mState.mDrawBufferStates.size());
461 return mState.mDrawBufferStates[drawBuffer];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000462}
463
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500464const std::vector<GLenum> &Framebuffer::getDrawBufferStates() const
465{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400466 return mState.getDrawBufferStates();
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500467}
468
Geoff Lang164d54e2014-12-01 10:55:33 -0500469void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000470{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400471 auto &drawStates = mState.mDrawBufferStates;
Jamie Madilld1405e52015-03-05 15:41:39 -0500472
473 ASSERT(count <= drawStates.size());
474 std::copy(buffers, buffers + count, drawStates.begin());
475 std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500476 mDirtyBits.set(DIRTY_BIT_DRAW_BUFFERS);
Jamie Madilla4595b82017-01-11 17:36:34 -0500477
478 mState.mEnabledDrawBuffers.reset();
479 for (size_t index = 0; index < count; ++index)
480 {
481 if (drawStates[index] != GL_NONE && mState.mColorAttachments[index].isAttached())
482 {
483 mState.mEnabledDrawBuffers.set(index);
484 }
485 }
Geoff Lang9dd95802014-12-01 11:12:59 -0500486}
487
Geoff Langa15472a2015-08-11 11:48:03 -0400488const FramebufferAttachment *Framebuffer::getDrawBuffer(size_t drawBuffer) const
489{
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400490 return mState.getDrawBuffer(drawBuffer);
Geoff Langa15472a2015-08-11 11:48:03 -0400491}
492
493bool Framebuffer::hasEnabledDrawBuffer() const
494{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400495 for (size_t drawbufferIdx = 0; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
Geoff Langa15472a2015-08-11 11:48:03 -0400496 {
497 if (getDrawBuffer(drawbufferIdx) != nullptr)
498 {
499 return true;
500 }
501 }
502
503 return false;
504}
505
Geoff Lang9dd95802014-12-01 11:12:59 -0500506GLenum Framebuffer::getReadBufferState() const
507{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400508 return mState.mReadBufferState;
Geoff Lang9dd95802014-12-01 11:12:59 -0500509}
510
511void Framebuffer::setReadBuffer(GLenum buffer)
512{
Jamie Madillb885e572015-02-03 16:16:04 -0500513 ASSERT(buffer == GL_BACK || buffer == GL_NONE ||
514 (buffer >= GL_COLOR_ATTACHMENT0 &&
Jamie Madill48ef11b2016-04-27 15:21:52 -0400515 (buffer - GL_COLOR_ATTACHMENT0) < mState.mColorAttachments.size()));
516 mState.mReadBufferState = buffer;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500517 mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000518}
519
Corentin Wallez37c39792015-08-20 14:19:46 -0400520size_t Framebuffer::getNumColorBuffers() const
521{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400522 return mState.mColorAttachments.size();
Corentin Wallez37c39792015-08-20 14:19:46 -0400523}
524
Jamie Madill0df8fe42015-11-24 16:10:24 -0500525bool Framebuffer::hasDepth() const
526{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400527 return (mState.mDepthAttachment.isAttached() && mState.mDepthAttachment.getDepthSize() > 0);
Jamie Madill0df8fe42015-11-24 16:10:24 -0500528}
529
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000530bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000531{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400532 return (mState.mStencilAttachment.isAttached() &&
533 mState.mStencilAttachment.getStencilSize() > 0);
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000534}
535
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000536bool Framebuffer::usingExtendedDrawBuffers() const
537{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400538 for (size_t drawbufferIdx = 1; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000539 {
Geoff Langa15472a2015-08-11 11:48:03 -0400540 if (getDrawBuffer(drawbufferIdx) != nullptr)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000541 {
542 return true;
543 }
544 }
545
546 return false;
547}
548
Jamie Madill51f40ec2016-06-15 14:06:00 -0400549GLenum Framebuffer::checkStatus(const ContextState &state)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000550{
Corentin Wallezccab69d2017-01-27 16:57:15 -0500551 // The default framebuffer is always complete except when it is surfaceless in which
552 // case it is always unsupported. We return early because the default framebuffer may
553 // not be subject to the same rules as application FBOs. ie, it could have 0x0 size.
Geoff Lang528ce3c2014-12-01 10:44:07 -0500554 if (mId == 0)
555 {
Corentin Wallezccab69d2017-01-27 16:57:15 -0500556 ASSERT(mCachedStatus.valid());
557 ASSERT(mCachedStatus.value() == GL_FRAMEBUFFER_COMPLETE ||
558 mCachedStatus.value() == GL_FRAMEBUFFER_UNDEFINED_OES);
559 return mCachedStatus.value();
Geoff Lang528ce3c2014-12-01 10:44:07 -0500560 }
561
Jamie Madill362876b2016-06-16 14:46:59 -0400562 if (hasAnyDirtyBit() || !mCachedStatus.valid())
563 {
564 mCachedStatus = checkStatusImpl(state);
565 }
566
567 return mCachedStatus.value();
568}
569
570GLenum Framebuffer::checkStatusImpl(const ContextState &state)
571{
572 ASSERT(mId != 0);
573
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000574 unsigned int colorbufferSize = 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000575 int samples = -1;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000576 bool missingAttachment = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000577
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800578 // TODO(yizhou): Check status for default framebuffer parameters.
Jamie Madill48ef11b2016-04-27 15:21:52 -0400579 for (const FramebufferAttachment &colorAttachment : mState.mColorAttachments)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000580 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400581 if (colorAttachment.isAttached())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000582 {
Jamie Madill6b120b92015-11-24 13:00:07 -0500583 const Extents &size = colorAttachment.getSize();
584 if (size.width == 0 || size.height == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000585 {
586 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
587 }
daniel@transgaming.com01868132010-08-24 19:21:17 +0000588
Jamie Madilla3944d42016-07-22 22:13:26 -0400589 const Format &format = colorAttachment.getFormat();
590 const TextureCaps &formatCaps = state.getTextureCap(format.asSized());
Jamie Madill2d06b732015-04-20 12:53:28 -0400591 if (colorAttachment.type() == GL_TEXTURE)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000592 {
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400593 if (!formatCaps.renderable)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000594 {
Jamie Madill81176782015-11-24 16:10:23 -0500595 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000596 }
597
Jamie Madilla3944d42016-07-22 22:13:26 -0400598 if (format.info->depthBits > 0 || format.info->stencilBits > 0)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000599 {
600 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
601 }
Jamie Madill6b120b92015-11-24 13:00:07 -0500602
603 if (colorAttachment.layer() >= size.depth)
604 {
605 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
606 }
Jamie Madill3215b202015-12-15 16:41:39 -0500607
608 // ES3 specifies that cube map texture attachments must be cube complete.
609 // This language is missing from the ES2 spec, but we enforce it here because some
610 // desktop OpenGL drivers also enforce this validation.
611 // TODO(jmadill): Check if OpenGL ES2 drivers enforce cube completeness.
612 const Texture *texture = colorAttachment.getTexture();
613 ASSERT(texture);
Olli Etuahoe8528d82016-05-16 17:50:52 +0300614 if (texture->getTarget() == GL_TEXTURE_CUBE_MAP &&
615 !texture->getTextureState().isCubeComplete())
Jamie Madill3215b202015-12-15 16:41:39 -0500616 {
617 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
618 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000619 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400620 else if (colorAttachment.type() == GL_RENDERBUFFER)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000621 {
Jamie Madilla3944d42016-07-22 22:13:26 -0400622 if (!formatCaps.renderable || format.info->depthBits > 0 ||
623 format.info->stencilBits > 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400624 {
625 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
626 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000627 }
628
629 if (!missingAttachment)
630 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000631 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
632 // all color attachments have the same number of samples for the FBO to be complete.
Jamie Madill2d06b732015-04-20 12:53:28 -0400633 if (colorAttachment.getSamples() != samples)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000634 {
635 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
636 }
637
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000638 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
639 // in GLES 3.0, there is no such restriction
Martin Radev1be913c2016-07-11 17:59:16 +0300640 if (state.getClientMajorVersion() < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000641 {
Jamie Madilla3944d42016-07-22 22:13:26 -0400642 if (format.info->pixelBytes != colorbufferSize)
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000643 {
644 return GL_FRAMEBUFFER_UNSUPPORTED;
645 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000646 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000647 }
648 else
649 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400650 samples = colorAttachment.getSamples();
Jamie Madilla3944d42016-07-22 22:13:26 -0400651 colorbufferSize = format.info->pixelBytes;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000652 missingAttachment = false;
653 }
654 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000655 }
656
Jamie Madill48ef11b2016-04-27 15:21:52 -0400657 const FramebufferAttachment &depthAttachment = mState.mDepthAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -0400658 if (depthAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000659 {
Jamie Madill6b120b92015-11-24 13:00:07 -0500660 const Extents &size = depthAttachment.getSize();
661 if (size.width == 0 || size.height == 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000662 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000663 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000664 }
665
Jamie Madilla3944d42016-07-22 22:13:26 -0400666 const Format &format = depthAttachment.getFormat();
667 const TextureCaps &formatCaps = state.getTextureCap(format.asSized());
Jamie Madill2d06b732015-04-20 12:53:28 -0400668 if (depthAttachment.type() == GL_TEXTURE)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000669 {
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400670 if (!formatCaps.renderable)
Geoff Langcec35902014-04-16 10:52:36 -0400671 {
Jamie Madill81176782015-11-24 16:10:23 -0500672 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
Geoff Langcec35902014-04-16 10:52:36 -0400673 }
674
Jamie Madilla3944d42016-07-22 22:13:26 -0400675 if (format.info->depthBits == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000676 {
677 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
678 }
679 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400680 else if (depthAttachment.type() == GL_RENDERBUFFER)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000681 {
Jamie Madilla3944d42016-07-22 22:13:26 -0400682 if (!formatCaps.renderable || format.info->depthBits == 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400683 {
684 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
685 }
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000686 }
687
688 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000689 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400690 samples = depthAttachment.getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000691 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000692 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400693 else if (samples != depthAttachment.getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000694 {
Sami Väisänena797e062016-05-12 15:23:40 +0300695 // CHROMIUM_framebuffer_mixed_samples allows a framebuffer to be
696 // considered complete when its depth or stencil samples are a
697 // multiple of the number of color samples.
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700698 const bool mixedSamples = state.getExtensions().framebufferMixedSamples;
Sami Väisänena797e062016-05-12 15:23:40 +0300699 if (!mixedSamples)
700 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
701
702 const int colorSamples = samples ? samples : 1;
703 const int depthSamples = depthAttachment.getSamples();
704 if ((depthSamples % colorSamples) != 0)
705 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000706 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000707 }
708
Jamie Madill48ef11b2016-04-27 15:21:52 -0400709 const FramebufferAttachment &stencilAttachment = mState.mStencilAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -0400710 if (stencilAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000711 {
Jamie Madill6b120b92015-11-24 13:00:07 -0500712 const Extents &size = stencilAttachment.getSize();
713 if (size.width == 0 || size.height == 0)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000714 {
715 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
716 }
717
Jamie Madilla3944d42016-07-22 22:13:26 -0400718 const Format &format = stencilAttachment.getFormat();
719 const TextureCaps &formatCaps = state.getTextureCap(format.asSized());
Jamie Madill2d06b732015-04-20 12:53:28 -0400720 if (stencilAttachment.type() == GL_TEXTURE)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000721 {
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400722 if (!formatCaps.renderable)
Geoff Langcec35902014-04-16 10:52:36 -0400723 {
Jamie Madill81176782015-11-24 16:10:23 -0500724 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
Geoff Langcec35902014-04-16 10:52:36 -0400725 }
726
Jamie Madilla3944d42016-07-22 22:13:26 -0400727 if (format.info->stencilBits == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000728 {
729 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
730 }
731 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400732 else if (stencilAttachment.type() == GL_RENDERBUFFER)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000733 {
Jamie Madilla3944d42016-07-22 22:13:26 -0400734 if (!formatCaps.renderable || format.info->stencilBits == 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400735 {
736 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
737 }
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000738 }
739
740 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000741 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400742 samples = stencilAttachment.getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000743 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000744 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400745 else if (samples != stencilAttachment.getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000746 {
Sami Väisänena797e062016-05-12 15:23:40 +0300747 // see the comments in depth attachment check.
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700748 const bool mixedSamples = state.getExtensions().framebufferMixedSamples;
Sami Väisänena797e062016-05-12 15:23:40 +0300749 if (!mixedSamples)
750 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
751
752 const int colorSamples = samples ? samples : 1;
753 const int stencilSamples = stencilAttachment.getSamples();
754 if ((stencilSamples % colorSamples) != 0)
755 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000756 }
Corentin Wallez086d59a2016-04-29 09:06:49 -0400757
758 // Starting from ES 3.0 stencil and depth, if present, should be the same image
Martin Radev1be913c2016-07-11 17:59:16 +0300759 if (state.getClientMajorVersion() >= 3 && depthAttachment.isAttached() &&
Corentin Wallez086d59a2016-04-29 09:06:49 -0400760 stencilAttachment != depthAttachment)
761 {
762 return GL_FRAMEBUFFER_UNSUPPORTED;
763 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000764 }
765
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000766 // we need to have at least one attachment to be complete
767 if (missingAttachment)
768 {
769 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000770 }
771
Jamie Madillcc86d642015-11-24 13:00:07 -0500772 // In ES 2.0, all color attachments must have the same width and height.
773 // In ES 3.0, there is no such restriction.
Martin Radev1be913c2016-07-11 17:59:16 +0300774 if (state.getClientMajorVersion() < 3 && !mState.attachmentsHaveSameDimensions())
Jamie Madillcc86d642015-11-24 13:00:07 -0500775 {
776 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
777 }
778
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500779 syncState();
Jamie Madillcc86d642015-11-24 13:00:07 -0500780 if (!mImpl->checkStatus())
781 {
782 return GL_FRAMEBUFFER_UNSUPPORTED;
783 }
784
785 return GL_FRAMEBUFFER_COMPLETE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000786}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000787
Austin Kinross08332632015-05-05 13:35:47 -0700788Error Framebuffer::discard(size_t count, const GLenum *attachments)
789{
790 return mImpl->discard(count, attachments);
791}
792
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500793Error Framebuffer::invalidate(size_t count, const GLenum *attachments)
Jamie Madill2d96b9e2014-08-29 15:46:47 -0400794{
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500795 return mImpl->invalidate(count, attachments);
Jamie Madill2d96b9e2014-08-29 15:46:47 -0400796}
797
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500798Error Framebuffer::invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area)
Jamie Madill400a4412014-08-29 15:46:45 -0400799{
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500800 return mImpl->invalidateSub(count, attachments, area);
Jamie Madill400a4412014-08-29 15:46:45 -0400801}
802
Jamie Madill8415b5f2016-04-26 13:41:39 -0400803Error Framebuffer::clear(rx::ContextImpl *context, GLbitfield mask)
Geoff Langb04dc822014-12-01 12:02:02 -0500804{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700805 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500806 {
Jamie Madill362876b2016-06-16 14:46:59 -0400807 return gl::NoError();
Jamie Madill984ef412015-11-24 16:10:21 -0500808 }
809
Jamie Madill8415b5f2016-04-26 13:41:39 -0400810 return mImpl->clear(context, mask);
Geoff Langb04dc822014-12-01 12:02:02 -0500811}
812
Jamie Madill8415b5f2016-04-26 13:41:39 -0400813Error Framebuffer::clearBufferfv(rx::ContextImpl *context,
Jamie Madill1b94d432015-08-07 13:23:23 -0400814 GLenum buffer,
815 GLint drawbuffer,
816 const GLfloat *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500817{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700818 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500819 {
Jamie Madill362876b2016-06-16 14:46:59 -0400820 return gl::NoError();
Jamie Madill984ef412015-11-24 16:10:21 -0500821 }
822
Jamie Madill8415b5f2016-04-26 13:41:39 -0400823 return mImpl->clearBufferfv(context, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500824}
825
Jamie Madill8415b5f2016-04-26 13:41:39 -0400826Error Framebuffer::clearBufferuiv(rx::ContextImpl *context,
Jamie Madill1b94d432015-08-07 13:23:23 -0400827 GLenum buffer,
828 GLint drawbuffer,
829 const GLuint *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500830{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700831 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500832 {
Jamie Madill362876b2016-06-16 14:46:59 -0400833 return gl::NoError();
Jamie Madill984ef412015-11-24 16:10:21 -0500834 }
835
Jamie Madill8415b5f2016-04-26 13:41:39 -0400836 return mImpl->clearBufferuiv(context, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500837}
838
Jamie Madill8415b5f2016-04-26 13:41:39 -0400839Error Framebuffer::clearBufferiv(rx::ContextImpl *context,
Jamie Madill1b94d432015-08-07 13:23:23 -0400840 GLenum buffer,
841 GLint drawbuffer,
842 const GLint *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500843{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700844 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500845 {
Jamie Madill362876b2016-06-16 14:46:59 -0400846 return gl::NoError();
Jamie Madill984ef412015-11-24 16:10:21 -0500847 }
848
Jamie Madill8415b5f2016-04-26 13:41:39 -0400849 return mImpl->clearBufferiv(context, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500850}
851
Jamie Madill8415b5f2016-04-26 13:41:39 -0400852Error Framebuffer::clearBufferfi(rx::ContextImpl *context,
Jamie Madill1b94d432015-08-07 13:23:23 -0400853 GLenum buffer,
854 GLint drawbuffer,
855 GLfloat depth,
856 GLint stencil)
Geoff Langb04dc822014-12-01 12:02:02 -0500857{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700858 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500859 {
Jamie Madill362876b2016-06-16 14:46:59 -0400860 return gl::NoError();
Jamie Madill984ef412015-11-24 16:10:21 -0500861 }
862
Jamie Madill8415b5f2016-04-26 13:41:39 -0400863 return mImpl->clearBufferfi(context, buffer, drawbuffer, depth, stencil);
Geoff Langb04dc822014-12-01 12:02:02 -0500864}
865
Geoff Langbce529e2014-12-01 12:48:41 -0500866GLenum Framebuffer::getImplementationColorReadFormat() const
867{
868 return mImpl->getImplementationColorReadFormat();
869}
870
871GLenum Framebuffer::getImplementationColorReadType() const
872{
873 return mImpl->getImplementationColorReadType();
874}
875
Jamie Madill8415b5f2016-04-26 13:41:39 -0400876Error Framebuffer::readPixels(rx::ContextImpl *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500877 const Rectangle &area,
Jamie Madill1b94d432015-08-07 13:23:23 -0400878 GLenum format,
879 GLenum type,
880 GLvoid *pixels) const
Geoff Langbce529e2014-12-01 12:48:41 -0500881{
Jamie Madill362876b2016-06-16 14:46:59 -0400882 ANGLE_TRY(mImpl->readPixels(context, area, format, type, pixels));
Geoff Lang520c4ae2015-05-05 13:12:36 -0400883
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700884 Buffer *unpackBuffer = context->getGLState().getUnpackState().pixelBuffer.get();
Geoff Lang520c4ae2015-05-05 13:12:36 -0400885 if (unpackBuffer)
886 {
887 unpackBuffer->onPixelUnpack();
888 }
889
Jamie Madill362876b2016-06-16 14:46:59 -0400890 return NoError();
Geoff Langbce529e2014-12-01 12:48:41 -0500891}
892
Jamie Madill8415b5f2016-04-26 13:41:39 -0400893Error Framebuffer::blit(rx::ContextImpl *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500894 const Rectangle &sourceArea,
895 const Rectangle &destArea,
Geoff Lang242468f2015-09-24 14:15:41 -0400896 GLbitfield mask,
Jamie Madill8415b5f2016-04-26 13:41:39 -0400897 GLenum filter)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500898{
He Yunchao6be602d2016-12-22 14:33:07 +0800899 GLbitfield blitMask = mask;
900
901 // Note that blitting is called against draw framebuffer.
902 // See the code in gl::Context::blitFramebuffer.
903 if ((mask & GL_COLOR_BUFFER_BIT) && !hasEnabledDrawBuffer())
904 {
905 blitMask &= ~GL_COLOR_BUFFER_BIT;
906 }
907
908 if ((mask & GL_STENCIL_BUFFER_BIT) && mState.getStencilAttachment() == nullptr)
909 {
910 blitMask &= ~GL_STENCIL_BUFFER_BIT;
911 }
912
913 if ((mask & GL_DEPTH_BUFFER_BIT) && mState.getDepthAttachment() == nullptr)
914 {
915 blitMask &= ~GL_DEPTH_BUFFER_BIT;
916 }
917
918 if (!blitMask)
919 {
920 return NoError();
921 }
922
923 return mImpl->blit(context, sourceArea, destArea, blitMask, filter);
Geoff Lang54bd5a42014-12-01 12:51:04 -0500924}
925
Jamie Madill51f40ec2016-06-15 14:06:00 -0400926int Framebuffer::getSamples(const ContextState &state)
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000927{
Jamie Madill362876b2016-06-16 14:46:59 -0400928 if (complete(state))
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000929 {
Jamie Madill362876b2016-06-16 14:46:59 -0400930 // For a complete framebuffer, all attachments must have the same sample count.
931 // In this case return the first nonzero sample size.
932 const auto *firstColorAttachment = mState.getFirstColorAttachment();
933 if (firstColorAttachment)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000934 {
Jamie Madill362876b2016-06-16 14:46:59 -0400935 ASSERT(firstColorAttachment->isAttached());
936 return firstColorAttachment->getSamples();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000937 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000938 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000939
940 return 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000941}
942
Corentin Wallezccab69d2017-01-27 16:57:15 -0500943Error Framebuffer::getSamplePosition(size_t index, GLfloat *xy) const
944{
945 ANGLE_TRY(mImpl->getSamplePosition(index, xy));
946 return gl::NoError();
947}
948
Jamie Madille261b442014-06-25 12:42:21 -0400949bool Framebuffer::hasValidDepthStencil() const
950{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400951 return mState.getDepthStencilAttachment() != nullptr;
Jamie Madille261b442014-06-25 12:42:21 -0400952}
953
Jamie Madill2d06b732015-04-20 12:53:28 -0400954void Framebuffer::setAttachment(GLenum type,
955 GLenum binding,
956 const ImageIndex &textureIndex,
957 FramebufferAttachmentObject *resource)
Geoff Langab75a052014-10-15 12:56:37 -0400958{
Jamie Madill2d06b732015-04-20 12:53:28 -0400959 if (binding == GL_DEPTH_STENCIL || binding == GL_DEPTH_STENCIL_ATTACHMENT)
Geoff Langab75a052014-10-15 12:56:37 -0400960 {
Geoff Langab75a052014-10-15 12:56:37 -0400961 // ensure this is a legitimate depth+stencil format
Jamie Madill375c37c2015-07-21 15:14:08 -0400962 FramebufferAttachmentObject *attachmentObj = resource;
963 if (resource)
Geoff Langab75a052014-10-15 12:56:37 -0400964 {
Jamie Madill375c37c2015-07-21 15:14:08 -0400965 FramebufferAttachment::Target target(binding, textureIndex);
Jamie Madilla3944d42016-07-22 22:13:26 -0400966 const Format &format = resource->getAttachmentFormat(target);
967 if (format.info->depthBits == 0 || format.info->stencilBits == 0)
Jamie Madill375c37c2015-07-21 15:14:08 -0400968 {
969 // Attaching nullptr detaches the current attachment.
970 attachmentObj = nullptr;
971 }
Geoff Langab75a052014-10-15 12:56:37 -0400972 }
Jamie Madill375c37c2015-07-21 15:14:08 -0400973
Jamie Madill48ef11b2016-04-27 15:21:52 -0400974 mState.mDepthAttachment.attach(type, binding, textureIndex, attachmentObj);
975 mState.mStencilAttachment.attach(type, binding, textureIndex, attachmentObj);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500976 mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT);
977 mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT);
Jamie Madill362876b2016-06-16 14:46:59 -0400978 BindResourceChannel(&mDirtyDepthAttachmentBinding, resource);
979 BindResourceChannel(&mDirtyStencilAttachmentBinding, resource);
Geoff Langab75a052014-10-15 12:56:37 -0400980 }
981 else
982 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400983 switch (binding)
984 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500985 case GL_DEPTH:
986 case GL_DEPTH_ATTACHMENT:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400987 mState.mDepthAttachment.attach(type, binding, textureIndex, resource);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500988 mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT);
Jamie Madill362876b2016-06-16 14:46:59 -0400989 BindResourceChannel(&mDirtyDepthAttachmentBinding, resource);
990 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500991 case GL_STENCIL:
992 case GL_STENCIL_ATTACHMENT:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400993 mState.mStencilAttachment.attach(type, binding, textureIndex, resource);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500994 mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT);
Jamie Madill362876b2016-06-16 14:46:59 -0400995 BindResourceChannel(&mDirtyStencilAttachmentBinding, resource);
996 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500997 case GL_BACK:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400998 mState.mColorAttachments[0].attach(type, binding, textureIndex, resource);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500999 mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0);
Jamie Madill362876b2016-06-16 14:46:59 -04001000 // No need for a resource binding for the default FBO, it's always complete.
1001 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001002 default:
Jamie Madill2d06b732015-04-20 12:53:28 -04001003 {
1004 size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
Jamie Madill48ef11b2016-04-27 15:21:52 -04001005 ASSERT(colorIndex < mState.mColorAttachments.size());
1006 mState.mColorAttachments[colorIndex].attach(type, binding, textureIndex, resource);
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001007 mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
Jamie Madill362876b2016-06-16 14:46:59 -04001008 BindResourceChannel(&mDirtyColorAttachmentBindings[colorIndex], resource);
Jamie Madilla4595b82017-01-11 17:36:34 -05001009
1010 bool enabled = (type != GL_NONE && getDrawBufferState(colorIndex) != GL_NONE);
1011 mState.mEnabledDrawBuffers.set(colorIndex, enabled);
Jamie Madill2d06b732015-04-20 12:53:28 -04001012 }
1013 break;
1014 }
Geoff Langab75a052014-10-15 12:56:37 -04001015 }
1016}
1017
Jamie Madill2d06b732015-04-20 12:53:28 -04001018void Framebuffer::resetAttachment(GLenum binding)
1019{
1020 setAttachment(GL_NONE, binding, ImageIndex::MakeInvalid(), nullptr);
1021}
1022
Jamie Madill362876b2016-06-16 14:46:59 -04001023void Framebuffer::syncState()
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001024{
1025 if (mDirtyBits.any())
1026 {
1027 mImpl->syncState(mDirtyBits);
1028 mDirtyBits.reset();
Corentin Wallezccab69d2017-01-27 16:57:15 -05001029 if (mId != 0)
1030 {
1031 mCachedStatus.reset();
1032 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001033 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001034}
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001035
Jamie Madill362876b2016-06-16 14:46:59 -04001036void Framebuffer::signal(SignalToken token)
Jamie Madill51f40ec2016-06-15 14:06:00 -04001037{
Jamie Madill362876b2016-06-16 14:46:59 -04001038 // TOOD(jmadill): Make this only update individual attachments to do less work.
1039 mCachedStatus.reset();
Jamie Madill51f40ec2016-06-15 14:06:00 -04001040}
1041
Jamie Madill362876b2016-06-16 14:46:59 -04001042bool Framebuffer::complete(const ContextState &state)
Jamie Madill51f40ec2016-06-15 14:06:00 -04001043{
Jamie Madill362876b2016-06-16 14:46:59 -04001044 return (checkStatus(state) == GL_FRAMEBUFFER_COMPLETE);
Jamie Madill51f40ec2016-06-15 14:06:00 -04001045}
1046
Jamie Madilla4595b82017-01-11 17:36:34 -05001047bool Framebuffer::formsRenderingFeedbackLoopWith(const State &state) const
1048{
1049 const Program *program = state.getProgram();
1050
1051 // TODO(jmadill): Default framebuffer feedback loops.
1052 if (mId == 0)
1053 {
1054 return false;
1055 }
1056
1057 // The bitset will skip inactive draw buffers.
1058 for (GLuint drawIndex : angle::IterateBitSet(mState.mEnabledDrawBuffers))
1059 {
1060 const FramebufferAttachment *attachment = getDrawBuffer(drawIndex);
1061 if (attachment && attachment->type() == GL_TEXTURE)
1062 {
1063 // Validate the feedback loop.
1064 if (program->samplesFromTexture(state, attachment->id()))
1065 {
1066 return true;
1067 }
1068 }
1069 }
1070
Jamie Madill1d37bc52017-02-02 19:59:58 -05001071 // Validate depth-stencil feedback loop.
1072 const auto &dsState = state.getDepthStencilState();
1073
1074 // We can skip the feedback loop checks if depth/stencil is masked out or disabled.
1075 const FramebufferAttachment *depth = getDepthbuffer();
1076 if (depth && depth->type() == GL_TEXTURE && dsState.depthTest && dsState.depthMask)
1077 {
1078 if (program->samplesFromTexture(state, depth->id()))
1079 {
1080 return true;
1081 }
1082 }
1083
1084 // Note: we assume the front and back masks are the same for WebGL.
1085 const FramebufferAttachment *stencil = getStencilbuffer();
1086 ASSERT(dsState.stencilBackWritemask == dsState.stencilWritemask);
1087 if (stencil && stencil->type() == GL_TEXTURE && dsState.stencilTest &&
1088 dsState.stencilWritemask != 0)
1089 {
1090 // Skip the feedback loop check if depth/stencil point to the same resource.
1091 if (!depth || *stencil != *depth)
1092 {
1093 if (program->samplesFromTexture(state, stencil->id()))
1094 {
1095 return true;
1096 }
1097 }
1098 }
1099
Jamie Madilla4595b82017-01-11 17:36:34 -05001100 return false;
1101}
1102
Jamie Madillfd3dd432017-02-02 19:59:59 -05001103bool Framebuffer::formsCopyingFeedbackLoopWith(GLuint copyTextureID,
1104 GLint copyTextureLevel,
1105 GLint copyTextureLayer) const
Jamie Madillf695a3a2017-01-11 17:36:35 -05001106{
1107 if (mId == 0)
1108 {
1109 // It seems impossible to form a texture copying feedback loop with the default FBO.
1110 return false;
1111 }
1112
1113 const FramebufferAttachment *readAttachment = getReadColorbuffer();
1114 ASSERT(readAttachment);
1115
1116 if (readAttachment->isTextureWithId(copyTextureID))
1117 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05001118 const auto &imageIndex = readAttachment->getTextureImageIndex();
1119 if (imageIndex.mipIndex == copyTextureLevel)
Jamie Madillf695a3a2017-01-11 17:36:35 -05001120 {
Jamie Madillfd3dd432017-02-02 19:59:59 -05001121 // Check 3D/Array texture layers.
1122 return imageIndex.layerIndex == ImageIndex::ENTIRE_LEVEL ||
1123 copyTextureLayer == ImageIndex::ENTIRE_LEVEL ||
1124 imageIndex.layerIndex == copyTextureLayer;
Jamie Madillf695a3a2017-01-11 17:36:35 -05001125 }
1126 }
1127 return false;
1128}
1129
JiangYizhouf7bbc8a2016-11-16 09:57:22 +08001130GLint Framebuffer::getDefaultWidth() const
1131{
1132 return mState.getDefaultWidth();
1133}
1134
1135GLint Framebuffer::getDefaultHeight() const
1136{
1137 return mState.getDefaultHeight();
1138}
1139
1140GLint Framebuffer::getDefaultSamples() const
1141{
1142 return mState.getDefaultSamples();
1143}
1144
1145GLboolean Framebuffer::getDefaultFixedSampleLocations() const
1146{
1147 return mState.getDefaultFixedSampleLocations();
1148}
1149
1150void Framebuffer::setDefaultWidth(GLint defaultWidth)
1151{
1152 mState.mDefaultWidth = defaultWidth;
1153 mDirtyBits.set(DIRTY_BIT_DEFAULT_WIDTH);
1154}
1155
1156void Framebuffer::setDefaultHeight(GLint defaultHeight)
1157{
1158 mState.mDefaultHeight = defaultHeight;
1159 mDirtyBits.set(DIRTY_BIT_DEFAULT_HEIGHT);
1160}
1161
1162void Framebuffer::setDefaultSamples(GLint defaultSamples)
1163{
1164 mState.mDefaultSamples = defaultSamples;
1165 mDirtyBits.set(DIRTY_BIT_DEFAULT_SAMPLES);
1166}
1167
1168void Framebuffer::setDefaultFixedSampleLocations(GLboolean defaultFixedSampleLocations)
1169{
1170 mState.mDefaultFixedSampleLocations = defaultFixedSampleLocations;
1171 mDirtyBits.set(DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS);
1172}
1173
Jamie Madill60ec6ea2016-01-22 15:27:19 -05001174} // namespace gl