blob: ee72b3612b43878d8fea3770161690238f81f163 [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 Madillc46f45d2015-03-31 13:20:55 -040013#include "common/utilities.h"
14#include "libANGLE/Config.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050015#include "libANGLE/Context.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050016#include "libANGLE/FramebufferAttachment.h"
Jamie Madillc46f45d2015-03-31 13:20:55 -040017#include "libANGLE/Renderbuffer.h"
18#include "libANGLE/Surface.h"
19#include "libANGLE/Texture.h"
20#include "libANGLE/formatutils.h"
Jamie Madill8415b5f2016-04-26 13:41:39 -040021#include "libANGLE/renderer/ContextImpl.h"
Geoff Langb5d8f232014-12-04 15:43:01 -050022#include "libANGLE/renderer/FramebufferImpl.h"
Jamie Madill7aea7e02016-05-10 10:39:45 -040023#include "libANGLE/renderer/GLImplFactory.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050024#include "libANGLE/renderer/RenderbufferImpl.h"
Corentin Wallez37c39792015-08-20 14:19:46 -040025#include "libANGLE/renderer/SurfaceImpl.h"
Geoff Lang0b7eef72014-06-12 14:10:47 -040026
Jamie Madill362876b2016-06-16 14:46:59 -040027using namespace angle;
28
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000029namespace gl
30{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000031
Jamie Madilld1405e52015-03-05 15:41:39 -050032namespace
33{
Jamie Madill362876b2016-06-16 14:46:59 -040034
35void BindResourceChannel(ChannelBinding *binding, FramebufferAttachmentObject *resource)
Jamie Madilld1405e52015-03-05 15:41:39 -050036{
Jamie Madill362876b2016-06-16 14:46:59 -040037 binding->bind(resource ? resource->getDirtyChannel() : nullptr);
Jamie Madilld1405e52015-03-05 15:41:39 -050038}
Jamie Madill362876b2016-06-16 14:46:59 -040039
40} // anonymous namespace
Jamie Madilld1405e52015-03-05 15:41:39 -050041
Jamie Madill48ef11b2016-04-27 15:21:52 -040042FramebufferState::FramebufferState()
Geoff Lang70d0f492015-12-10 17:45:46 -050043 : mLabel(),
44 mColorAttachments(1),
Corentin Wallez37c39792015-08-20 14:19:46 -040045 mDrawBufferStates(1, GL_NONE),
46 mReadBufferState(GL_COLOR_ATTACHMENT0_EXT)
47{
48 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
49}
50
Jamie Madill48ef11b2016-04-27 15:21:52 -040051FramebufferState::FramebufferState(const Caps &caps)
Geoff Lang70d0f492015-12-10 17:45:46 -050052 : mLabel(),
53 mColorAttachments(caps.maxColorAttachments),
Jamie Madilld1405e52015-03-05 15:41:39 -050054 mDrawBufferStates(caps.maxDrawBuffers, GL_NONE),
55 mReadBufferState(GL_COLOR_ATTACHMENT0_EXT)
56{
Geoff Langa15472a2015-08-11 11:48:03 -040057 ASSERT(mDrawBufferStates.size() > 0);
Jamie Madilld1405e52015-03-05 15:41:39 -050058 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
59}
60
Jamie Madill48ef11b2016-04-27 15:21:52 -040061FramebufferState::~FramebufferState()
Jamie Madilld1405e52015-03-05 15:41:39 -050062{
Jamie Madilld1405e52015-03-05 15:41:39 -050063}
64
Jamie Madill48ef11b2016-04-27 15:21:52 -040065const std::string &FramebufferState::getLabel()
Geoff Lang70d0f492015-12-10 17:45:46 -050066{
67 return mLabel;
68}
69
Geoff Lang4b7f12b2016-06-21 16:47:07 -040070const FramebufferAttachment *FramebufferState::getAttachment(GLenum attachment) const
71{
72 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
73 {
74 return getColorAttachment(attachment - GL_COLOR_ATTACHMENT0);
75 }
76
77 switch (attachment)
78 {
79 case GL_COLOR:
80 case GL_BACK:
81 return getColorAttachment(0);
82 case GL_DEPTH:
83 case GL_DEPTH_ATTACHMENT:
84 return getDepthAttachment();
85 case GL_STENCIL:
86 case GL_STENCIL_ATTACHMENT:
87 return getStencilAttachment();
88 case GL_DEPTH_STENCIL:
89 case GL_DEPTH_STENCIL_ATTACHMENT:
90 return getDepthStencilAttachment();
91 default:
92 UNREACHABLE();
93 return nullptr;
94 }
95}
96
Jamie Madill48ef11b2016-04-27 15:21:52 -040097const FramebufferAttachment *FramebufferState::getReadAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -050098{
Antoine Labour2ec65dc2016-11-30 16:28:58 -080099 if (mReadBufferState == GL_NONE)
100 {
101 return nullptr;
102 }
Jamie Madill7147f012015-03-05 15:41:40 -0500103 ASSERT(mReadBufferState == GL_BACK || (mReadBufferState >= GL_COLOR_ATTACHMENT0 && mReadBufferState <= GL_COLOR_ATTACHMENT15));
104 size_t readIndex = (mReadBufferState == GL_BACK ? 0 : static_cast<size_t>(mReadBufferState - GL_COLOR_ATTACHMENT0));
105 ASSERT(readIndex < mColorAttachments.size());
Jamie Madill2d06b732015-04-20 12:53:28 -0400106 return mColorAttachments[readIndex].isAttached() ? &mColorAttachments[readIndex] : nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500107}
108
Jamie Madill48ef11b2016-04-27 15:21:52 -0400109const FramebufferAttachment *FramebufferState::getFirstColorAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500110{
Jamie Madill2d06b732015-04-20 12:53:28 -0400111 for (const FramebufferAttachment &colorAttachment : mColorAttachments)
Jamie Madill7147f012015-03-05 15:41:40 -0500112 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400113 if (colorAttachment.isAttached())
Jamie Madill7147f012015-03-05 15:41:40 -0500114 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400115 return &colorAttachment;
Jamie Madill7147f012015-03-05 15:41:40 -0500116 }
117 }
118
119 return nullptr;
120}
121
Jamie Madill48ef11b2016-04-27 15:21:52 -0400122const FramebufferAttachment *FramebufferState::getDepthOrStencilAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500123{
Jamie Madill2d06b732015-04-20 12:53:28 -0400124 if (mDepthAttachment.isAttached())
125 {
126 return &mDepthAttachment;
127 }
128 if (mStencilAttachment.isAttached())
129 {
130 return &mStencilAttachment;
131 }
132 return nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500133}
134
Jamie Madill48ef11b2016-04-27 15:21:52 -0400135const FramebufferAttachment *FramebufferState::getColorAttachment(size_t colorAttachment) const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400136{
137 ASSERT(colorAttachment < mColorAttachments.size());
Jamie Madill2d06b732015-04-20 12:53:28 -0400138 return mColorAttachments[colorAttachment].isAttached() ?
139 &mColorAttachments[colorAttachment] :
140 nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400141}
142
Jamie Madill48ef11b2016-04-27 15:21:52 -0400143const FramebufferAttachment *FramebufferState::getDepthAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400144{
Jamie Madill2d06b732015-04-20 12:53:28 -0400145 return mDepthAttachment.isAttached() ? &mDepthAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400146}
147
Jamie Madill48ef11b2016-04-27 15:21:52 -0400148const FramebufferAttachment *FramebufferState::getStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400149{
Jamie Madill2d06b732015-04-20 12:53:28 -0400150 return mStencilAttachment.isAttached() ? &mStencilAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400151}
152
Jamie Madill48ef11b2016-04-27 15:21:52 -0400153const FramebufferAttachment *FramebufferState::getDepthStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400154{
155 // A valid depth-stencil attachment has the same resource bound to both the
156 // depth and stencil attachment points.
Jamie Madill2d06b732015-04-20 12:53:28 -0400157 if (mDepthAttachment.isAttached() && mStencilAttachment.isAttached() &&
Jamie Madill44f26482016-11-18 12:49:15 -0500158 mDepthAttachment == mStencilAttachment)
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400159 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400160 return &mDepthAttachment;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400161 }
162
163 return nullptr;
164}
165
Jamie Madill48ef11b2016-04-27 15:21:52 -0400166bool FramebufferState::attachmentsHaveSameDimensions() const
Jamie Madillcc86d642015-11-24 13:00:07 -0500167{
168 Optional<Extents> attachmentSize;
169
170 auto hasMismatchedSize = [&attachmentSize](const FramebufferAttachment &attachment)
171 {
172 if (!attachment.isAttached())
173 {
174 return false;
175 }
176
177 if (!attachmentSize.valid())
178 {
179 attachmentSize = attachment.getSize();
180 return false;
181 }
182
183 return (attachment.getSize() != attachmentSize.value());
184 };
185
186 for (const auto &attachment : mColorAttachments)
187 {
188 if (hasMismatchedSize(attachment))
189 {
190 return false;
191 }
192 }
193
194 if (hasMismatchedSize(mDepthAttachment))
195 {
196 return false;
197 }
198
199 return !hasMismatchedSize(mStencilAttachment);
200}
201
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400202const gl::FramebufferAttachment *FramebufferState::getDrawBuffer(size_t drawBufferIdx) const
203{
204 ASSERT(drawBufferIdx < mDrawBufferStates.size());
205 if (mDrawBufferStates[drawBufferIdx] != GL_NONE)
206 {
207 // ES3 spec: "If the GL is bound to a draw framebuffer object, the ith buffer listed in bufs
208 // must be COLOR_ATTACHMENTi or NONE"
209 ASSERT(mDrawBufferStates[drawBufferIdx] == GL_COLOR_ATTACHMENT0 + drawBufferIdx ||
210 (drawBufferIdx == 0 && mDrawBufferStates[drawBufferIdx] == GL_BACK));
211 return getAttachment(mDrawBufferStates[drawBufferIdx]);
212 }
213 else
214 {
215 return nullptr;
216 }
217}
218
219size_t FramebufferState::getDrawBufferCount() const
220{
221 return mDrawBufferStates.size();
222}
223
Geoff Langb21e20d2016-07-19 15:35:41 -0400224bool FramebufferState::colorAttachmentsAreUniqueImages() const
225{
226 for (size_t firstAttachmentIdx = 0; firstAttachmentIdx < mColorAttachments.size();
227 firstAttachmentIdx++)
228 {
229 const gl::FramebufferAttachment &firstAttachment = mColorAttachments[firstAttachmentIdx];
230 if (!firstAttachment.isAttached())
231 {
232 continue;
233 }
234
235 for (size_t secondAttachmentIdx = firstAttachmentIdx + 1;
236 secondAttachmentIdx < mColorAttachments.size(); secondAttachmentIdx++)
237 {
238 const gl::FramebufferAttachment &secondAttachment =
239 mColorAttachments[secondAttachmentIdx];
240 if (!secondAttachment.isAttached())
241 {
242 continue;
243 }
244
245 if (firstAttachment == secondAttachment)
246 {
247 return false;
248 }
249 }
250 }
251
252 return true;
253}
254
Jamie Madill7aea7e02016-05-10 10:39:45 -0400255Framebuffer::Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id)
Jamie Madill362876b2016-06-16 14:46:59 -0400256 : mState(caps),
257 mImpl(factory->createFramebuffer(mState)),
258 mId(id),
259 mCachedStatus(),
260 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
261 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000262{
Corentin Wallez37c39792015-08-20 14:19:46 -0400263 ASSERT(mId != 0);
264 ASSERT(mImpl != nullptr);
Jamie Madill362876b2016-06-16 14:46:59 -0400265 ASSERT(mState.mColorAttachments.size() == static_cast<size_t>(caps.maxColorAttachments));
266
267 for (size_t colorIndex = 0; colorIndex < mState.mColorAttachments.size(); ++colorIndex)
268 {
269 mDirtyColorAttachmentBindings.push_back(ChannelBinding(
270 this, static_cast<SignalToken>(DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex)));
271 }
Corentin Wallez37c39792015-08-20 14:19:46 -0400272}
273
274Framebuffer::Framebuffer(rx::SurfaceImpl *surface)
Jamie Madill362876b2016-06-16 14:46:59 -0400275 : mState(),
276 mImpl(surface->createDefaultFramebuffer(mState)),
277 mId(0),
278 mCachedStatus(GL_FRAMEBUFFER_COMPLETE),
279 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
280 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
Corentin Wallez37c39792015-08-20 14:19:46 -0400281{
Geoff Langda88add2014-12-01 10:22:01 -0500282 ASSERT(mImpl != nullptr);
Jamie Madill362876b2016-06-16 14:46:59 -0400283 mDirtyColorAttachmentBindings.push_back(
284 ChannelBinding(this, static_cast<SignalToken>(DIRTY_BIT_COLOR_ATTACHMENT_0)));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000285}
286
287Framebuffer::~Framebuffer()
288{
Geoff Langda88add2014-12-01 10:22:01 -0500289 SafeDelete(mImpl);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000290}
291
Geoff Lang70d0f492015-12-10 17:45:46 -0500292void Framebuffer::setLabel(const std::string &label)
293{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400294 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -0500295}
296
297const std::string &Framebuffer::getLabel() const
298{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400299 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -0500300}
301
Jamie Madille261b442014-06-25 12:42:21 -0400302void Framebuffer::detachTexture(GLuint textureId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000303{
Jamie Madilld1405e52015-03-05 15:41:39 -0500304 detachResourceById(GL_TEXTURE, textureId);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000305}
306
Jamie Madille261b442014-06-25 12:42:21 -0400307void Framebuffer::detachRenderbuffer(GLuint renderbufferId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000308{
Jamie Madilld1405e52015-03-05 15:41:39 -0500309 detachResourceById(GL_RENDERBUFFER, renderbufferId);
310}
Jamie Madille261b442014-06-25 12:42:21 -0400311
Jamie Madilld1405e52015-03-05 15:41:39 -0500312void Framebuffer::detachResourceById(GLenum resourceType, GLuint resourceId)
313{
Jamie Madill362876b2016-06-16 14:46:59 -0400314 for (size_t colorIndex = 0; colorIndex < mState.mColorAttachments.size(); ++colorIndex)
Jamie Madilld1405e52015-03-05 15:41:39 -0500315 {
Jamie Madill362876b2016-06-16 14:46:59 -0400316 detachMatchingAttachment(&mState.mColorAttachments[colorIndex], resourceType, resourceId,
317 DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000318 }
319
Jamie Madill362876b2016-06-16 14:46:59 -0400320 detachMatchingAttachment(&mState.mDepthAttachment, resourceType, resourceId,
321 DIRTY_BIT_DEPTH_ATTACHMENT);
322 detachMatchingAttachment(&mState.mStencilAttachment, resourceType, resourceId,
323 DIRTY_BIT_STENCIL_ATTACHMENT);
324}
325
326void Framebuffer::detachMatchingAttachment(FramebufferAttachment *attachment,
327 GLenum matchType,
328 GLuint matchId,
329 size_t dirtyBit)
330{
331 if (attachment->isAttached() && attachment->type() == matchType && attachment->id() == matchId)
332 {
333 attachment->detach();
334 mDirtyBits.set(dirtyBit);
335 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000336}
337
Corentin Wallez37c39792015-08-20 14:19:46 -0400338const FramebufferAttachment *Framebuffer::getColorbuffer(size_t colorAttachment) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000339{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400340 return mState.getColorAttachment(colorAttachment);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000341}
342
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400343const FramebufferAttachment *Framebuffer::getDepthbuffer() const
Geoff Lang646559f2013-08-15 11:08:15 -0400344{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400345 return mState.getDepthAttachment();
Geoff Lang646559f2013-08-15 11:08:15 -0400346}
347
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400348const FramebufferAttachment *Framebuffer::getStencilbuffer() const
349{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400350 return mState.getStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400351}
352
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400353const FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
354{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400355 return mState.getDepthStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400356}
357
358const FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000359{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400360 return mState.getDepthOrStencilAttachment();
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000361}
362
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400363const FramebufferAttachment *Framebuffer::getReadColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000364{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400365 return mState.getReadAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000366}
367
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000368GLenum Framebuffer::getReadColorbufferType() const
369{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400370 const FramebufferAttachment *readAttachment = mState.getReadAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400371 return (readAttachment != nullptr ? readAttachment->type() : GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000372}
373
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400374const FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000375{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400376 return mState.getFirstColorAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000377}
378
Jamie Madill2d06b732015-04-20 12:53:28 -0400379const FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000380{
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400381 return mState.getAttachment(attachment);
Geoff Lang55ba29c2013-07-11 16:57:53 -0400382}
383
Geoff Langa15472a2015-08-11 11:48:03 -0400384size_t Framebuffer::getDrawbufferStateCount() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000385{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400386 return mState.mDrawBufferStates.size();
Geoff Langa15472a2015-08-11 11:48:03 -0400387}
388
389GLenum Framebuffer::getDrawBufferState(size_t drawBuffer) const
390{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400391 ASSERT(drawBuffer < mState.mDrawBufferStates.size());
392 return mState.mDrawBufferStates[drawBuffer];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000393}
394
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500395const std::vector<GLenum> &Framebuffer::getDrawBufferStates() const
396{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400397 return mState.getDrawBufferStates();
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500398}
399
Geoff Lang164d54e2014-12-01 10:55:33 -0500400void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000401{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400402 auto &drawStates = mState.mDrawBufferStates;
Jamie Madilld1405e52015-03-05 15:41:39 -0500403
404 ASSERT(count <= drawStates.size());
405 std::copy(buffers, buffers + count, drawStates.begin());
406 std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500407 mDirtyBits.set(DIRTY_BIT_DRAW_BUFFERS);
Geoff Lang9dd95802014-12-01 11:12:59 -0500408}
409
Geoff Langa15472a2015-08-11 11:48:03 -0400410const FramebufferAttachment *Framebuffer::getDrawBuffer(size_t drawBuffer) const
411{
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400412 return mState.getDrawBuffer(drawBuffer);
Geoff Langa15472a2015-08-11 11:48:03 -0400413}
414
415bool Framebuffer::hasEnabledDrawBuffer() const
416{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400417 for (size_t drawbufferIdx = 0; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
Geoff Langa15472a2015-08-11 11:48:03 -0400418 {
419 if (getDrawBuffer(drawbufferIdx) != nullptr)
420 {
421 return true;
422 }
423 }
424
425 return false;
426}
427
Geoff Lang9dd95802014-12-01 11:12:59 -0500428GLenum Framebuffer::getReadBufferState() const
429{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400430 return mState.mReadBufferState;
Geoff Lang9dd95802014-12-01 11:12:59 -0500431}
432
433void Framebuffer::setReadBuffer(GLenum buffer)
434{
Jamie Madillb885e572015-02-03 16:16:04 -0500435 ASSERT(buffer == GL_BACK || buffer == GL_NONE ||
436 (buffer >= GL_COLOR_ATTACHMENT0 &&
Jamie Madill48ef11b2016-04-27 15:21:52 -0400437 (buffer - GL_COLOR_ATTACHMENT0) < mState.mColorAttachments.size()));
438 mState.mReadBufferState = buffer;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500439 mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000440}
441
Corentin Wallez37c39792015-08-20 14:19:46 -0400442size_t Framebuffer::getNumColorBuffers() const
443{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400444 return mState.mColorAttachments.size();
Corentin Wallez37c39792015-08-20 14:19:46 -0400445}
446
Jamie Madill0df8fe42015-11-24 16:10:24 -0500447bool Framebuffer::hasDepth() const
448{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400449 return (mState.mDepthAttachment.isAttached() && mState.mDepthAttachment.getDepthSize() > 0);
Jamie Madill0df8fe42015-11-24 16:10:24 -0500450}
451
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000452bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000453{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400454 return (mState.mStencilAttachment.isAttached() &&
455 mState.mStencilAttachment.getStencilSize() > 0);
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000456}
457
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000458bool Framebuffer::usingExtendedDrawBuffers() const
459{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400460 for (size_t drawbufferIdx = 1; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000461 {
Geoff Langa15472a2015-08-11 11:48:03 -0400462 if (getDrawBuffer(drawbufferIdx) != nullptr)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000463 {
464 return true;
465 }
466 }
467
468 return false;
469}
470
Jamie Madill51f40ec2016-06-15 14:06:00 -0400471GLenum Framebuffer::checkStatus(const ContextState &state)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000472{
Geoff Lang528ce3c2014-12-01 10:44:07 -0500473 // The default framebuffer *must* always be complete, though it may not be
474 // subject to the same rules as application FBOs. ie, it could have 0x0 size.
475 if (mId == 0)
476 {
477 return GL_FRAMEBUFFER_COMPLETE;
478 }
479
Jamie Madill362876b2016-06-16 14:46:59 -0400480 if (hasAnyDirtyBit() || !mCachedStatus.valid())
481 {
482 mCachedStatus = checkStatusImpl(state);
483 }
484
485 return mCachedStatus.value();
486}
487
488GLenum Framebuffer::checkStatusImpl(const ContextState &state)
489{
490 ASSERT(mId != 0);
491
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000492 unsigned int colorbufferSize = 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000493 int samples = -1;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000494 bool missingAttachment = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000495
Jamie Madill48ef11b2016-04-27 15:21:52 -0400496 for (const FramebufferAttachment &colorAttachment : mState.mColorAttachments)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000497 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400498 if (colorAttachment.isAttached())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000499 {
Jamie Madill6b120b92015-11-24 13:00:07 -0500500 const Extents &size = colorAttachment.getSize();
501 if (size.width == 0 || size.height == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000502 {
503 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
504 }
daniel@transgaming.com01868132010-08-24 19:21:17 +0000505
Jamie Madilla3944d42016-07-22 22:13:26 -0400506 const Format &format = colorAttachment.getFormat();
507 const TextureCaps &formatCaps = state.getTextureCap(format.asSized());
Jamie Madill2d06b732015-04-20 12:53:28 -0400508 if (colorAttachment.type() == GL_TEXTURE)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000509 {
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400510 if (!formatCaps.renderable)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000511 {
Jamie Madill81176782015-11-24 16:10:23 -0500512 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000513 }
514
Jamie Madilla3944d42016-07-22 22:13:26 -0400515 if (format.info->depthBits > 0 || format.info->stencilBits > 0)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000516 {
517 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
518 }
Jamie Madill6b120b92015-11-24 13:00:07 -0500519
520 if (colorAttachment.layer() >= size.depth)
521 {
522 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
523 }
Jamie Madill3215b202015-12-15 16:41:39 -0500524
525 // ES3 specifies that cube map texture attachments must be cube complete.
526 // This language is missing from the ES2 spec, but we enforce it here because some
527 // desktop OpenGL drivers also enforce this validation.
528 // TODO(jmadill): Check if OpenGL ES2 drivers enforce cube completeness.
529 const Texture *texture = colorAttachment.getTexture();
530 ASSERT(texture);
Olli Etuahoe8528d82016-05-16 17:50:52 +0300531 if (texture->getTarget() == GL_TEXTURE_CUBE_MAP &&
532 !texture->getTextureState().isCubeComplete())
Jamie Madill3215b202015-12-15 16:41:39 -0500533 {
534 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
535 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000536 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400537 else if (colorAttachment.type() == GL_RENDERBUFFER)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000538 {
Jamie Madilla3944d42016-07-22 22:13:26 -0400539 if (!formatCaps.renderable || format.info->depthBits > 0 ||
540 format.info->stencilBits > 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400541 {
542 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
543 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000544 }
545
546 if (!missingAttachment)
547 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000548 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
549 // all color attachments have the same number of samples for the FBO to be complete.
Jamie Madill2d06b732015-04-20 12:53:28 -0400550 if (colorAttachment.getSamples() != samples)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000551 {
552 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
553 }
554
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000555 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
556 // in GLES 3.0, there is no such restriction
Martin Radev1be913c2016-07-11 17:59:16 +0300557 if (state.getClientMajorVersion() < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000558 {
Jamie Madilla3944d42016-07-22 22:13:26 -0400559 if (format.info->pixelBytes != colorbufferSize)
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000560 {
561 return GL_FRAMEBUFFER_UNSUPPORTED;
562 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000563 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000564 }
565 else
566 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400567 samples = colorAttachment.getSamples();
Jamie Madilla3944d42016-07-22 22:13:26 -0400568 colorbufferSize = format.info->pixelBytes;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000569 missingAttachment = false;
570 }
571 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000572 }
573
Jamie Madill48ef11b2016-04-27 15:21:52 -0400574 const FramebufferAttachment &depthAttachment = mState.mDepthAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -0400575 if (depthAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000576 {
Jamie Madill6b120b92015-11-24 13:00:07 -0500577 const Extents &size = depthAttachment.getSize();
578 if (size.width == 0 || size.height == 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000579 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000580 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000581 }
582
Jamie Madilla3944d42016-07-22 22:13:26 -0400583 const Format &format = depthAttachment.getFormat();
584 const TextureCaps &formatCaps = state.getTextureCap(format.asSized());
Jamie Madill2d06b732015-04-20 12:53:28 -0400585 if (depthAttachment.type() == GL_TEXTURE)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000586 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000587 // depth texture attachments require OES/ANGLE_depth_texture
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700588 if (!state.getExtensions().depthTextures)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000589 {
590 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
591 }
592
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400593 if (!formatCaps.renderable)
Geoff Langcec35902014-04-16 10:52:36 -0400594 {
Jamie Madill81176782015-11-24 16:10:23 -0500595 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
Geoff Langcec35902014-04-16 10:52:36 -0400596 }
597
Jamie Madilla3944d42016-07-22 22:13:26 -0400598 if (format.info->depthBits == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000599 {
600 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
601 }
602 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400603 else if (depthAttachment.type() == GL_RENDERBUFFER)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000604 {
Jamie Madilla3944d42016-07-22 22:13:26 -0400605 if (!formatCaps.renderable || format.info->depthBits == 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400606 {
607 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
608 }
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000609 }
610
611 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000612 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400613 samples = depthAttachment.getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000614 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000615 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400616 else if (samples != depthAttachment.getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000617 {
Sami Väisänena797e062016-05-12 15:23:40 +0300618 // CHROMIUM_framebuffer_mixed_samples allows a framebuffer to be
619 // considered complete when its depth or stencil samples are a
620 // multiple of the number of color samples.
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700621 const bool mixedSamples = state.getExtensions().framebufferMixedSamples;
Sami Väisänena797e062016-05-12 15:23:40 +0300622 if (!mixedSamples)
623 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
624
625 const int colorSamples = samples ? samples : 1;
626 const int depthSamples = depthAttachment.getSamples();
627 if ((depthSamples % colorSamples) != 0)
628 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000629 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000630 }
631
Jamie Madill48ef11b2016-04-27 15:21:52 -0400632 const FramebufferAttachment &stencilAttachment = mState.mStencilAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -0400633 if (stencilAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000634 {
Jamie Madill6b120b92015-11-24 13:00:07 -0500635 const Extents &size = stencilAttachment.getSize();
636 if (size.width == 0 || size.height == 0)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000637 {
638 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
639 }
640
Jamie Madilla3944d42016-07-22 22:13:26 -0400641 const Format &format = stencilAttachment.getFormat();
642 const TextureCaps &formatCaps = state.getTextureCap(format.asSized());
Jamie Madill2d06b732015-04-20 12:53:28 -0400643 if (stencilAttachment.type() == GL_TEXTURE)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000644 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000645 // texture stencil attachments come along as part
646 // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700647 if (!state.getExtensions().depthTextures)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000648 {
649 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
650 }
651
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400652 if (!formatCaps.renderable)
Geoff Langcec35902014-04-16 10:52:36 -0400653 {
Jamie Madill81176782015-11-24 16:10:23 -0500654 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
Geoff Langcec35902014-04-16 10:52:36 -0400655 }
656
Jamie Madilla3944d42016-07-22 22:13:26 -0400657 if (format.info->stencilBits == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000658 {
659 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
660 }
661 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400662 else if (stencilAttachment.type() == GL_RENDERBUFFER)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000663 {
Jamie Madilla3944d42016-07-22 22:13:26 -0400664 if (!formatCaps.renderable || format.info->stencilBits == 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400665 {
666 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
667 }
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000668 }
669
670 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000671 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400672 samples = stencilAttachment.getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000673 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000674 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400675 else if (samples != stencilAttachment.getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000676 {
Sami Väisänena797e062016-05-12 15:23:40 +0300677 // see the comments in depth attachment check.
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700678 const bool mixedSamples = state.getExtensions().framebufferMixedSamples;
Sami Väisänena797e062016-05-12 15:23:40 +0300679 if (!mixedSamples)
680 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
681
682 const int colorSamples = samples ? samples : 1;
683 const int stencilSamples = stencilAttachment.getSamples();
684 if ((stencilSamples % colorSamples) != 0)
685 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000686 }
Corentin Wallez086d59a2016-04-29 09:06:49 -0400687
688 // Starting from ES 3.0 stencil and depth, if present, should be the same image
Martin Radev1be913c2016-07-11 17:59:16 +0300689 if (state.getClientMajorVersion() >= 3 && depthAttachment.isAttached() &&
Corentin Wallez086d59a2016-04-29 09:06:49 -0400690 stencilAttachment != depthAttachment)
691 {
692 return GL_FRAMEBUFFER_UNSUPPORTED;
693 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000694 }
695
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000696 // we need to have at least one attachment to be complete
697 if (missingAttachment)
698 {
699 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000700 }
701
Jamie Madillcc86d642015-11-24 13:00:07 -0500702 // In ES 2.0, all color attachments must have the same width and height.
703 // In ES 3.0, there is no such restriction.
Martin Radev1be913c2016-07-11 17:59:16 +0300704 if (state.getClientMajorVersion() < 3 && !mState.attachmentsHaveSameDimensions())
Jamie Madillcc86d642015-11-24 13:00:07 -0500705 {
706 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
707 }
708
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500709 syncState();
Jamie Madillcc86d642015-11-24 13:00:07 -0500710 if (!mImpl->checkStatus())
711 {
712 return GL_FRAMEBUFFER_UNSUPPORTED;
713 }
714
715 return GL_FRAMEBUFFER_COMPLETE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000716}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000717
Austin Kinross08332632015-05-05 13:35:47 -0700718Error Framebuffer::discard(size_t count, const GLenum *attachments)
719{
720 return mImpl->discard(count, attachments);
721}
722
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500723Error Framebuffer::invalidate(size_t count, const GLenum *attachments)
Jamie Madill2d96b9e2014-08-29 15:46:47 -0400724{
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500725 return mImpl->invalidate(count, attachments);
Jamie Madill2d96b9e2014-08-29 15:46:47 -0400726}
727
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500728Error Framebuffer::invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area)
Jamie Madill400a4412014-08-29 15:46:45 -0400729{
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500730 return mImpl->invalidateSub(count, attachments, area);
Jamie Madill400a4412014-08-29 15:46:45 -0400731}
732
Jamie Madill8415b5f2016-04-26 13:41:39 -0400733Error Framebuffer::clear(rx::ContextImpl *context, GLbitfield mask)
Geoff Langb04dc822014-12-01 12:02:02 -0500734{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700735 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500736 {
Jamie Madill362876b2016-06-16 14:46:59 -0400737 return gl::NoError();
Jamie Madill984ef412015-11-24 16:10:21 -0500738 }
739
Jamie Madill8415b5f2016-04-26 13:41:39 -0400740 return mImpl->clear(context, mask);
Geoff Langb04dc822014-12-01 12:02:02 -0500741}
742
Jamie Madill8415b5f2016-04-26 13:41:39 -0400743Error Framebuffer::clearBufferfv(rx::ContextImpl *context,
Jamie Madill1b94d432015-08-07 13:23:23 -0400744 GLenum buffer,
745 GLint drawbuffer,
746 const GLfloat *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500747{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700748 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500749 {
Jamie Madill362876b2016-06-16 14:46:59 -0400750 return gl::NoError();
Jamie Madill984ef412015-11-24 16:10:21 -0500751 }
752
Jamie Madill8415b5f2016-04-26 13:41:39 -0400753 return mImpl->clearBufferfv(context, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500754}
755
Jamie Madill8415b5f2016-04-26 13:41:39 -0400756Error Framebuffer::clearBufferuiv(rx::ContextImpl *context,
Jamie Madill1b94d432015-08-07 13:23:23 -0400757 GLenum buffer,
758 GLint drawbuffer,
759 const GLuint *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500760{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700761 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500762 {
Jamie Madill362876b2016-06-16 14:46:59 -0400763 return gl::NoError();
Jamie Madill984ef412015-11-24 16:10:21 -0500764 }
765
Jamie Madill8415b5f2016-04-26 13:41:39 -0400766 return mImpl->clearBufferuiv(context, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500767}
768
Jamie Madill8415b5f2016-04-26 13:41:39 -0400769Error Framebuffer::clearBufferiv(rx::ContextImpl *context,
Jamie Madill1b94d432015-08-07 13:23:23 -0400770 GLenum buffer,
771 GLint drawbuffer,
772 const GLint *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500773{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700774 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500775 {
Jamie Madill362876b2016-06-16 14:46:59 -0400776 return gl::NoError();
Jamie Madill984ef412015-11-24 16:10:21 -0500777 }
778
Jamie Madill8415b5f2016-04-26 13:41:39 -0400779 return mImpl->clearBufferiv(context, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500780}
781
Jamie Madill8415b5f2016-04-26 13:41:39 -0400782Error Framebuffer::clearBufferfi(rx::ContextImpl *context,
Jamie Madill1b94d432015-08-07 13:23:23 -0400783 GLenum buffer,
784 GLint drawbuffer,
785 GLfloat depth,
786 GLint stencil)
Geoff Langb04dc822014-12-01 12:02:02 -0500787{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700788 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500789 {
Jamie Madill362876b2016-06-16 14:46:59 -0400790 return gl::NoError();
Jamie Madill984ef412015-11-24 16:10:21 -0500791 }
792
Jamie Madill8415b5f2016-04-26 13:41:39 -0400793 return mImpl->clearBufferfi(context, buffer, drawbuffer, depth, stencil);
Geoff Langb04dc822014-12-01 12:02:02 -0500794}
795
Geoff Langbce529e2014-12-01 12:48:41 -0500796GLenum Framebuffer::getImplementationColorReadFormat() const
797{
798 return mImpl->getImplementationColorReadFormat();
799}
800
801GLenum Framebuffer::getImplementationColorReadType() const
802{
803 return mImpl->getImplementationColorReadType();
804}
805
Jamie Madill8415b5f2016-04-26 13:41:39 -0400806Error Framebuffer::readPixels(rx::ContextImpl *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500807 const Rectangle &area,
Jamie Madill1b94d432015-08-07 13:23:23 -0400808 GLenum format,
809 GLenum type,
810 GLvoid *pixels) const
Geoff Langbce529e2014-12-01 12:48:41 -0500811{
Jamie Madill362876b2016-06-16 14:46:59 -0400812 ANGLE_TRY(mImpl->readPixels(context, area, format, type, pixels));
Geoff Lang520c4ae2015-05-05 13:12:36 -0400813
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700814 Buffer *unpackBuffer = context->getGLState().getUnpackState().pixelBuffer.get();
Geoff Lang520c4ae2015-05-05 13:12:36 -0400815 if (unpackBuffer)
816 {
817 unpackBuffer->onPixelUnpack();
818 }
819
Jamie Madill362876b2016-06-16 14:46:59 -0400820 return NoError();
Geoff Langbce529e2014-12-01 12:48:41 -0500821}
822
Jamie Madill8415b5f2016-04-26 13:41:39 -0400823Error Framebuffer::blit(rx::ContextImpl *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500824 const Rectangle &sourceArea,
825 const Rectangle &destArea,
Geoff Lang242468f2015-09-24 14:15:41 -0400826 GLbitfield mask,
Jamie Madill8415b5f2016-04-26 13:41:39 -0400827 GLenum filter)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500828{
Jamie Madill8415b5f2016-04-26 13:41:39 -0400829 return mImpl->blit(context, sourceArea, destArea, mask, filter);
Geoff Lang54bd5a42014-12-01 12:51:04 -0500830}
831
Jamie Madill51f40ec2016-06-15 14:06:00 -0400832int Framebuffer::getSamples(const ContextState &state)
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000833{
Jamie Madill362876b2016-06-16 14:46:59 -0400834 if (complete(state))
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000835 {
Jamie Madill362876b2016-06-16 14:46:59 -0400836 // For a complete framebuffer, all attachments must have the same sample count.
837 // In this case return the first nonzero sample size.
838 const auto *firstColorAttachment = mState.getFirstColorAttachment();
839 if (firstColorAttachment)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000840 {
Jamie Madill362876b2016-06-16 14:46:59 -0400841 ASSERT(firstColorAttachment->isAttached());
842 return firstColorAttachment->getSamples();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000843 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000844 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000845
846 return 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000847}
848
Jamie Madille261b442014-06-25 12:42:21 -0400849bool Framebuffer::hasValidDepthStencil() const
850{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400851 return mState.getDepthStencilAttachment() != nullptr;
Jamie Madille261b442014-06-25 12:42:21 -0400852}
853
Jamie Madill2d06b732015-04-20 12:53:28 -0400854void Framebuffer::setAttachment(GLenum type,
855 GLenum binding,
856 const ImageIndex &textureIndex,
857 FramebufferAttachmentObject *resource)
Geoff Langab75a052014-10-15 12:56:37 -0400858{
Jamie Madill2d06b732015-04-20 12:53:28 -0400859 if (binding == GL_DEPTH_STENCIL || binding == GL_DEPTH_STENCIL_ATTACHMENT)
Geoff Langab75a052014-10-15 12:56:37 -0400860 {
Geoff Langab75a052014-10-15 12:56:37 -0400861 // ensure this is a legitimate depth+stencil format
Jamie Madill375c37c2015-07-21 15:14:08 -0400862 FramebufferAttachmentObject *attachmentObj = resource;
863 if (resource)
Geoff Langab75a052014-10-15 12:56:37 -0400864 {
Jamie Madill375c37c2015-07-21 15:14:08 -0400865 FramebufferAttachment::Target target(binding, textureIndex);
Jamie Madilla3944d42016-07-22 22:13:26 -0400866 const Format &format = resource->getAttachmentFormat(target);
867 if (format.info->depthBits == 0 || format.info->stencilBits == 0)
Jamie Madill375c37c2015-07-21 15:14:08 -0400868 {
869 // Attaching nullptr detaches the current attachment.
870 attachmentObj = nullptr;
871 }
Geoff Langab75a052014-10-15 12:56:37 -0400872 }
Jamie Madill375c37c2015-07-21 15:14:08 -0400873
Jamie Madill48ef11b2016-04-27 15:21:52 -0400874 mState.mDepthAttachment.attach(type, binding, textureIndex, attachmentObj);
875 mState.mStencilAttachment.attach(type, binding, textureIndex, attachmentObj);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500876 mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT);
877 mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT);
Jamie Madill362876b2016-06-16 14:46:59 -0400878 BindResourceChannel(&mDirtyDepthAttachmentBinding, resource);
879 BindResourceChannel(&mDirtyStencilAttachmentBinding, resource);
Geoff Langab75a052014-10-15 12:56:37 -0400880 }
881 else
882 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400883 switch (binding)
884 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500885 case GL_DEPTH:
886 case GL_DEPTH_ATTACHMENT:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400887 mState.mDepthAttachment.attach(type, binding, textureIndex, resource);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500888 mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT);
Jamie Madill362876b2016-06-16 14:46:59 -0400889 BindResourceChannel(&mDirtyDepthAttachmentBinding, resource);
890 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500891 case GL_STENCIL:
892 case GL_STENCIL_ATTACHMENT:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400893 mState.mStencilAttachment.attach(type, binding, textureIndex, resource);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500894 mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT);
Jamie Madill362876b2016-06-16 14:46:59 -0400895 BindResourceChannel(&mDirtyStencilAttachmentBinding, resource);
896 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500897 case GL_BACK:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400898 mState.mColorAttachments[0].attach(type, binding, textureIndex, resource);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500899 mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0);
Jamie Madill362876b2016-06-16 14:46:59 -0400900 // No need for a resource binding for the default FBO, it's always complete.
901 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500902 default:
Jamie Madill2d06b732015-04-20 12:53:28 -0400903 {
904 size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
Jamie Madill48ef11b2016-04-27 15:21:52 -0400905 ASSERT(colorIndex < mState.mColorAttachments.size());
906 mState.mColorAttachments[colorIndex].attach(type, binding, textureIndex, resource);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500907 mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
Jamie Madill362876b2016-06-16 14:46:59 -0400908 BindResourceChannel(&mDirtyColorAttachmentBindings[colorIndex], resource);
Jamie Madill2d06b732015-04-20 12:53:28 -0400909 }
910 break;
911 }
Geoff Langab75a052014-10-15 12:56:37 -0400912 }
913}
914
Jamie Madill2d06b732015-04-20 12:53:28 -0400915void Framebuffer::resetAttachment(GLenum binding)
916{
917 setAttachment(GL_NONE, binding, ImageIndex::MakeInvalid(), nullptr);
918}
919
Jamie Madill362876b2016-06-16 14:46:59 -0400920void Framebuffer::syncState()
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500921{
922 if (mDirtyBits.any())
923 {
924 mImpl->syncState(mDirtyBits);
925 mDirtyBits.reset();
Jamie Madill362876b2016-06-16 14:46:59 -0400926 mCachedStatus.reset();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500927 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000928}
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500929
Jamie Madill362876b2016-06-16 14:46:59 -0400930void Framebuffer::signal(SignalToken token)
Jamie Madill51f40ec2016-06-15 14:06:00 -0400931{
Jamie Madill362876b2016-06-16 14:46:59 -0400932 // TOOD(jmadill): Make this only update individual attachments to do less work.
933 mCachedStatus.reset();
Jamie Madill51f40ec2016-06-15 14:06:00 -0400934}
935
Jamie Madill362876b2016-06-16 14:46:59 -0400936bool Framebuffer::complete(const ContextState &state)
Jamie Madill51f40ec2016-06-15 14:06:00 -0400937{
Jamie Madill362876b2016-06-16 14:46:59 -0400938 return (checkStatus(state) == GL_FRAMEBUFFER_COMPLETE);
Jamie Madill51f40ec2016-06-15 14:06:00 -0400939}
940
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500941} // namespace gl