blob: 391a4c496bda0aeb164ff23c556532e4b80055f8 [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
Jamie Madill48ef11b2016-04-27 15:21:52 -040070const FramebufferAttachment *FramebufferState::getReadAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -050071{
72 ASSERT(mReadBufferState == GL_BACK || (mReadBufferState >= GL_COLOR_ATTACHMENT0 && mReadBufferState <= GL_COLOR_ATTACHMENT15));
73 size_t readIndex = (mReadBufferState == GL_BACK ? 0 : static_cast<size_t>(mReadBufferState - GL_COLOR_ATTACHMENT0));
74 ASSERT(readIndex < mColorAttachments.size());
Jamie Madill2d06b732015-04-20 12:53:28 -040075 return mColorAttachments[readIndex].isAttached() ? &mColorAttachments[readIndex] : nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -050076}
77
Jamie Madill48ef11b2016-04-27 15:21:52 -040078const FramebufferAttachment *FramebufferState::getFirstColorAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -050079{
Jamie Madill2d06b732015-04-20 12:53:28 -040080 for (const FramebufferAttachment &colorAttachment : mColorAttachments)
Jamie Madill7147f012015-03-05 15:41:40 -050081 {
Jamie Madill2d06b732015-04-20 12:53:28 -040082 if (colorAttachment.isAttached())
Jamie Madill7147f012015-03-05 15:41:40 -050083 {
Jamie Madill2d06b732015-04-20 12:53:28 -040084 return &colorAttachment;
Jamie Madill7147f012015-03-05 15:41:40 -050085 }
86 }
87
88 return nullptr;
89}
90
Jamie Madill48ef11b2016-04-27 15:21:52 -040091const FramebufferAttachment *FramebufferState::getDepthOrStencilAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -050092{
Jamie Madill2d06b732015-04-20 12:53:28 -040093 if (mDepthAttachment.isAttached())
94 {
95 return &mDepthAttachment;
96 }
97 if (mStencilAttachment.isAttached())
98 {
99 return &mStencilAttachment;
100 }
101 return nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500102}
103
Jamie Madill48ef11b2016-04-27 15:21:52 -0400104const FramebufferAttachment *FramebufferState::getColorAttachment(size_t colorAttachment) const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400105{
106 ASSERT(colorAttachment < mColorAttachments.size());
Jamie Madill2d06b732015-04-20 12:53:28 -0400107 return mColorAttachments[colorAttachment].isAttached() ?
108 &mColorAttachments[colorAttachment] :
109 nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400110}
111
Jamie Madill48ef11b2016-04-27 15:21:52 -0400112const FramebufferAttachment *FramebufferState::getDepthAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400113{
Jamie Madill2d06b732015-04-20 12:53:28 -0400114 return mDepthAttachment.isAttached() ? &mDepthAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400115}
116
Jamie Madill48ef11b2016-04-27 15:21:52 -0400117const FramebufferAttachment *FramebufferState::getStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400118{
Jamie Madill2d06b732015-04-20 12:53:28 -0400119 return mStencilAttachment.isAttached() ? &mStencilAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400120}
121
Jamie Madill48ef11b2016-04-27 15:21:52 -0400122const FramebufferAttachment *FramebufferState::getDepthStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400123{
124 // A valid depth-stencil attachment has the same resource bound to both the
125 // depth and stencil attachment points.
Jamie Madill2d06b732015-04-20 12:53:28 -0400126 if (mDepthAttachment.isAttached() && mStencilAttachment.isAttached() &&
127 mDepthAttachment.type() == mStencilAttachment.type() &&
128 mDepthAttachment.id() == mStencilAttachment.id())
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400129 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400130 return &mDepthAttachment;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400131 }
132
133 return nullptr;
134}
135
Jamie Madill48ef11b2016-04-27 15:21:52 -0400136bool FramebufferState::attachmentsHaveSameDimensions() const
Jamie Madillcc86d642015-11-24 13:00:07 -0500137{
138 Optional<Extents> attachmentSize;
139
140 auto hasMismatchedSize = [&attachmentSize](const FramebufferAttachment &attachment)
141 {
142 if (!attachment.isAttached())
143 {
144 return false;
145 }
146
147 if (!attachmentSize.valid())
148 {
149 attachmentSize = attachment.getSize();
150 return false;
151 }
152
153 return (attachment.getSize() != attachmentSize.value());
154 };
155
156 for (const auto &attachment : mColorAttachments)
157 {
158 if (hasMismatchedSize(attachment))
159 {
160 return false;
161 }
162 }
163
164 if (hasMismatchedSize(mDepthAttachment))
165 {
166 return false;
167 }
168
169 return !hasMismatchedSize(mStencilAttachment);
170}
171
Jamie Madill7aea7e02016-05-10 10:39:45 -0400172Framebuffer::Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id)
Jamie Madill362876b2016-06-16 14:46:59 -0400173 : mState(caps),
174 mImpl(factory->createFramebuffer(mState)),
175 mId(id),
176 mCachedStatus(),
177 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
178 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000179{
Corentin Wallez37c39792015-08-20 14:19:46 -0400180 ASSERT(mId != 0);
181 ASSERT(mImpl != nullptr);
Jamie Madill362876b2016-06-16 14:46:59 -0400182 ASSERT(mState.mColorAttachments.size() == static_cast<size_t>(caps.maxColorAttachments));
183
184 for (size_t colorIndex = 0; colorIndex < mState.mColorAttachments.size(); ++colorIndex)
185 {
186 mDirtyColorAttachmentBindings.push_back(ChannelBinding(
187 this, static_cast<SignalToken>(DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex)));
188 }
Corentin Wallez37c39792015-08-20 14:19:46 -0400189}
190
191Framebuffer::Framebuffer(rx::SurfaceImpl *surface)
Jamie Madill362876b2016-06-16 14:46:59 -0400192 : mState(),
193 mImpl(surface->createDefaultFramebuffer(mState)),
194 mId(0),
195 mCachedStatus(GL_FRAMEBUFFER_COMPLETE),
196 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
197 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
Corentin Wallez37c39792015-08-20 14:19:46 -0400198{
Geoff Langda88add2014-12-01 10:22:01 -0500199 ASSERT(mImpl != nullptr);
Jamie Madill362876b2016-06-16 14:46:59 -0400200 mDirtyColorAttachmentBindings.push_back(
201 ChannelBinding(this, static_cast<SignalToken>(DIRTY_BIT_COLOR_ATTACHMENT_0)));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000202}
203
204Framebuffer::~Framebuffer()
205{
Geoff Langda88add2014-12-01 10:22:01 -0500206 SafeDelete(mImpl);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000207}
208
Geoff Lang70d0f492015-12-10 17:45:46 -0500209void Framebuffer::setLabel(const std::string &label)
210{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400211 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -0500212}
213
214const std::string &Framebuffer::getLabel() const
215{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400216 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -0500217}
218
Jamie Madille261b442014-06-25 12:42:21 -0400219void Framebuffer::detachTexture(GLuint textureId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000220{
Jamie Madilld1405e52015-03-05 15:41:39 -0500221 detachResourceById(GL_TEXTURE, textureId);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000222}
223
Jamie Madille261b442014-06-25 12:42:21 -0400224void Framebuffer::detachRenderbuffer(GLuint renderbufferId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000225{
Jamie Madilld1405e52015-03-05 15:41:39 -0500226 detachResourceById(GL_RENDERBUFFER, renderbufferId);
227}
Jamie Madille261b442014-06-25 12:42:21 -0400228
Jamie Madilld1405e52015-03-05 15:41:39 -0500229void Framebuffer::detachResourceById(GLenum resourceType, GLuint resourceId)
230{
Jamie Madill362876b2016-06-16 14:46:59 -0400231 for (size_t colorIndex = 0; colorIndex < mState.mColorAttachments.size(); ++colorIndex)
Jamie Madilld1405e52015-03-05 15:41:39 -0500232 {
Jamie Madill362876b2016-06-16 14:46:59 -0400233 detachMatchingAttachment(&mState.mColorAttachments[colorIndex], resourceType, resourceId,
234 DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000235 }
236
Jamie Madill362876b2016-06-16 14:46:59 -0400237 detachMatchingAttachment(&mState.mDepthAttachment, resourceType, resourceId,
238 DIRTY_BIT_DEPTH_ATTACHMENT);
239 detachMatchingAttachment(&mState.mStencilAttachment, resourceType, resourceId,
240 DIRTY_BIT_STENCIL_ATTACHMENT);
241}
242
243void Framebuffer::detachMatchingAttachment(FramebufferAttachment *attachment,
244 GLenum matchType,
245 GLuint matchId,
246 size_t dirtyBit)
247{
248 if (attachment->isAttached() && attachment->type() == matchType && attachment->id() == matchId)
249 {
250 attachment->detach();
251 mDirtyBits.set(dirtyBit);
252 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000253}
254
Corentin Wallez37c39792015-08-20 14:19:46 -0400255const FramebufferAttachment *Framebuffer::getColorbuffer(size_t colorAttachment) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000256{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400257 return mState.getColorAttachment(colorAttachment);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000258}
259
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400260const FramebufferAttachment *Framebuffer::getDepthbuffer() const
Geoff Lang646559f2013-08-15 11:08:15 -0400261{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400262 return mState.getDepthAttachment();
Geoff Lang646559f2013-08-15 11:08:15 -0400263}
264
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400265const FramebufferAttachment *Framebuffer::getStencilbuffer() const
266{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400267 return mState.getStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400268}
269
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400270const FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
271{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400272 return mState.getDepthStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400273}
274
275const FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000276{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400277 return mState.getDepthOrStencilAttachment();
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000278}
279
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400280const FramebufferAttachment *Framebuffer::getReadColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000281{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400282 return mState.getReadAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000283}
284
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000285GLenum Framebuffer::getReadColorbufferType() const
286{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400287 const FramebufferAttachment *readAttachment = mState.getReadAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400288 return (readAttachment != nullptr ? readAttachment->type() : GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000289}
290
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400291const FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000292{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400293 return mState.getFirstColorAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000294}
295
Jamie Madill2d06b732015-04-20 12:53:28 -0400296const FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000297{
Jamie Madille92a3542014-07-03 10:38:58 -0400298 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
299 {
Jamie Madill48ef11b2016-04-27 15:21:52 -0400300 return mState.getColorAttachment(attachment - GL_COLOR_ATTACHMENT0);
Jamie Madille92a3542014-07-03 10:38:58 -0400301 }
302 else
303 {
304 switch (attachment)
305 {
Geoff Lang528ce3c2014-12-01 10:44:07 -0500306 case GL_COLOR:
307 case GL_BACK:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400308 return mState.getColorAttachment(0);
Geoff Lang528ce3c2014-12-01 10:44:07 -0500309 case GL_DEPTH:
Jamie Madille92a3542014-07-03 10:38:58 -0400310 case GL_DEPTH_ATTACHMENT:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400311 return mState.getDepthAttachment();
Geoff Lang528ce3c2014-12-01 10:44:07 -0500312 case GL_STENCIL:
Jamie Madille92a3542014-07-03 10:38:58 -0400313 case GL_STENCIL_ATTACHMENT:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400314 return mState.getStencilAttachment();
Geoff Lang528ce3c2014-12-01 10:44:07 -0500315 case GL_DEPTH_STENCIL:
Jamie Madille92a3542014-07-03 10:38:58 -0400316 case GL_DEPTH_STENCIL_ATTACHMENT:
317 return getDepthStencilBuffer();
318 default:
319 UNREACHABLE();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400320 return nullptr;
Jamie Madille92a3542014-07-03 10:38:58 -0400321 }
322 }
Geoff Lang55ba29c2013-07-11 16:57:53 -0400323}
324
Geoff Langa15472a2015-08-11 11:48:03 -0400325size_t Framebuffer::getDrawbufferStateCount() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000326{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400327 return mState.mDrawBufferStates.size();
Geoff Langa15472a2015-08-11 11:48:03 -0400328}
329
330GLenum Framebuffer::getDrawBufferState(size_t drawBuffer) const
331{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400332 ASSERT(drawBuffer < mState.mDrawBufferStates.size());
333 return mState.mDrawBufferStates[drawBuffer];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000334}
335
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500336const std::vector<GLenum> &Framebuffer::getDrawBufferStates() const
337{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400338 return mState.getDrawBufferStates();
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500339}
340
Geoff Lang164d54e2014-12-01 10:55:33 -0500341void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000342{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400343 auto &drawStates = mState.mDrawBufferStates;
Jamie Madilld1405e52015-03-05 15:41:39 -0500344
345 ASSERT(count <= drawStates.size());
346 std::copy(buffers, buffers + count, drawStates.begin());
347 std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500348 mDirtyBits.set(DIRTY_BIT_DRAW_BUFFERS);
Geoff Lang9dd95802014-12-01 11:12:59 -0500349}
350
Geoff Langa15472a2015-08-11 11:48:03 -0400351const FramebufferAttachment *Framebuffer::getDrawBuffer(size_t drawBuffer) const
352{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400353 ASSERT(drawBuffer < mState.mDrawBufferStates.size());
354 if (mState.mDrawBufferStates[drawBuffer] != GL_NONE)
Geoff Langa15472a2015-08-11 11:48:03 -0400355 {
356 // ES3 spec: "If the GL is bound to a draw framebuffer object, the ith buffer listed in bufs
357 // must be COLOR_ATTACHMENTi or NONE"
Jamie Madill48ef11b2016-04-27 15:21:52 -0400358 ASSERT(mState.mDrawBufferStates[drawBuffer] == GL_COLOR_ATTACHMENT0 + drawBuffer ||
359 (drawBuffer == 0 && mState.mDrawBufferStates[drawBuffer] == GL_BACK));
360 return getAttachment(mState.mDrawBufferStates[drawBuffer]);
Geoff Langa15472a2015-08-11 11:48:03 -0400361 }
362 else
363 {
364 return nullptr;
365 }
366}
367
368bool Framebuffer::hasEnabledDrawBuffer() const
369{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400370 for (size_t drawbufferIdx = 0; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
Geoff Langa15472a2015-08-11 11:48:03 -0400371 {
372 if (getDrawBuffer(drawbufferIdx) != nullptr)
373 {
374 return true;
375 }
376 }
377
378 return false;
379}
380
Geoff Lang9dd95802014-12-01 11:12:59 -0500381GLenum Framebuffer::getReadBufferState() const
382{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400383 return mState.mReadBufferState;
Geoff Lang9dd95802014-12-01 11:12:59 -0500384}
385
386void Framebuffer::setReadBuffer(GLenum buffer)
387{
Jamie Madillb885e572015-02-03 16:16:04 -0500388 ASSERT(buffer == GL_BACK || buffer == GL_NONE ||
389 (buffer >= GL_COLOR_ATTACHMENT0 &&
Jamie Madill48ef11b2016-04-27 15:21:52 -0400390 (buffer - GL_COLOR_ATTACHMENT0) < mState.mColorAttachments.size()));
391 mState.mReadBufferState = buffer;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500392 mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000393}
394
Corentin Wallez37c39792015-08-20 14:19:46 -0400395size_t Framebuffer::getNumColorBuffers() const
396{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400397 return mState.mColorAttachments.size();
Corentin Wallez37c39792015-08-20 14:19:46 -0400398}
399
Jamie Madill0df8fe42015-11-24 16:10:24 -0500400bool Framebuffer::hasDepth() const
401{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400402 return (mState.mDepthAttachment.isAttached() && mState.mDepthAttachment.getDepthSize() > 0);
Jamie Madill0df8fe42015-11-24 16:10:24 -0500403}
404
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000405bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000406{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400407 return (mState.mStencilAttachment.isAttached() &&
408 mState.mStencilAttachment.getStencilSize() > 0);
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000409}
410
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000411bool Framebuffer::usingExtendedDrawBuffers() const
412{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400413 for (size_t drawbufferIdx = 1; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000414 {
Geoff Langa15472a2015-08-11 11:48:03 -0400415 if (getDrawBuffer(drawbufferIdx) != nullptr)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000416 {
417 return true;
418 }
419 }
420
421 return false;
422}
423
Jamie Madill51f40ec2016-06-15 14:06:00 -0400424GLenum Framebuffer::checkStatus(const ContextState &state)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000425{
Geoff Lang528ce3c2014-12-01 10:44:07 -0500426 // The default framebuffer *must* always be complete, though it may not be
427 // subject to the same rules as application FBOs. ie, it could have 0x0 size.
428 if (mId == 0)
429 {
430 return GL_FRAMEBUFFER_COMPLETE;
431 }
432
Jamie Madill362876b2016-06-16 14:46:59 -0400433 if (hasAnyDirtyBit() || !mCachedStatus.valid())
434 {
435 mCachedStatus = checkStatusImpl(state);
436 }
437
438 return mCachedStatus.value();
439}
440
441GLenum Framebuffer::checkStatusImpl(const ContextState &state)
442{
443 ASSERT(mId != 0);
444
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000445 unsigned int colorbufferSize = 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000446 int samples = -1;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000447 bool missingAttachment = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000448
Jamie Madill48ef11b2016-04-27 15:21:52 -0400449 for (const FramebufferAttachment &colorAttachment : mState.mColorAttachments)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000450 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400451 if (colorAttachment.isAttached())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000452 {
Jamie Madill6b120b92015-11-24 13:00:07 -0500453 const Extents &size = colorAttachment.getSize();
454 if (size.width == 0 || size.height == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000455 {
456 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
457 }
daniel@transgaming.com01868132010-08-24 19:21:17 +0000458
Jamie Madill2d06b732015-04-20 12:53:28 -0400459 GLenum internalformat = colorAttachment.getInternalFormat();
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700460 const TextureCaps &formatCaps = state.getTextureCap(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400461 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill2d06b732015-04-20 12:53:28 -0400462 if (colorAttachment.type() == GL_TEXTURE)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000463 {
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400464 if (!formatCaps.renderable)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000465 {
Jamie Madill81176782015-11-24 16:10:23 -0500466 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000467 }
468
Geoff Lang5d601382014-07-22 15:14:06 -0400469 if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000470 {
471 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
472 }
Jamie Madill6b120b92015-11-24 13:00:07 -0500473
474 if (colorAttachment.layer() >= size.depth)
475 {
476 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
477 }
Jamie Madill3215b202015-12-15 16:41:39 -0500478
479 // ES3 specifies that cube map texture attachments must be cube complete.
480 // This language is missing from the ES2 spec, but we enforce it here because some
481 // desktop OpenGL drivers also enforce this validation.
482 // TODO(jmadill): Check if OpenGL ES2 drivers enforce cube completeness.
483 const Texture *texture = colorAttachment.getTexture();
484 ASSERT(texture);
Olli Etuahoe8528d82016-05-16 17:50:52 +0300485 if (texture->getTarget() == GL_TEXTURE_CUBE_MAP &&
486 !texture->getTextureState().isCubeComplete())
Jamie Madill3215b202015-12-15 16:41:39 -0500487 {
488 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
489 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000490 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400491 else if (colorAttachment.type() == GL_RENDERBUFFER)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000492 {
Geoff Lang5d601382014-07-22 15:14:06 -0400493 if (!formatCaps.renderable || formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400494 {
495 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
496 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000497 }
498
499 if (!missingAttachment)
500 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000501 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
502 // all color attachments have the same number of samples for the FBO to be complete.
Jamie Madill2d06b732015-04-20 12:53:28 -0400503 if (colorAttachment.getSamples() != samples)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000504 {
505 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
506 }
507
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000508 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
509 // in GLES 3.0, there is no such restriction
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700510 if (state.getClientVersion() < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000511 {
Geoff Lang5d601382014-07-22 15:14:06 -0400512 if (formatInfo.pixelBytes != colorbufferSize)
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000513 {
514 return GL_FRAMEBUFFER_UNSUPPORTED;
515 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000516 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000517 }
518 else
519 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400520 samples = colorAttachment.getSamples();
Geoff Lang5d601382014-07-22 15:14:06 -0400521 colorbufferSize = formatInfo.pixelBytes;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000522 missingAttachment = false;
523 }
524 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000525 }
526
Jamie Madill48ef11b2016-04-27 15:21:52 -0400527 const FramebufferAttachment &depthAttachment = mState.mDepthAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -0400528 if (depthAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000529 {
Jamie Madill6b120b92015-11-24 13:00:07 -0500530 const Extents &size = depthAttachment.getSize();
531 if (size.width == 0 || size.height == 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000532 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000533 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000534 }
535
Jamie Madill2d06b732015-04-20 12:53:28 -0400536 GLenum internalformat = depthAttachment.getInternalFormat();
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700537 const TextureCaps &formatCaps = state.getTextureCap(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400538 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill2d06b732015-04-20 12:53:28 -0400539 if (depthAttachment.type() == GL_TEXTURE)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000540 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000541 // depth texture attachments require OES/ANGLE_depth_texture
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700542 if (!state.getExtensions().depthTextures)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000543 {
544 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
545 }
546
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400547 if (!formatCaps.renderable)
Geoff Langcec35902014-04-16 10:52:36 -0400548 {
Jamie Madill81176782015-11-24 16:10:23 -0500549 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
Geoff Langcec35902014-04-16 10:52:36 -0400550 }
551
Geoff Lang5d601382014-07-22 15:14:06 -0400552 if (formatInfo.depthBits == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000553 {
554 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
555 }
556 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400557 else if (depthAttachment.type() == GL_RENDERBUFFER)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000558 {
Geoff Lang5d601382014-07-22 15:14:06 -0400559 if (!formatCaps.renderable || formatInfo.depthBits == 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400560 {
561 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
562 }
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000563 }
564
565 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000566 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400567 samples = depthAttachment.getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000568 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000569 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400570 else if (samples != depthAttachment.getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000571 {
Sami Väisänena797e062016-05-12 15:23:40 +0300572 // CHROMIUM_framebuffer_mixed_samples allows a framebuffer to be
573 // considered complete when its depth or stencil samples are a
574 // multiple of the number of color samples.
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700575 const bool mixedSamples = state.getExtensions().framebufferMixedSamples;
Sami Väisänena797e062016-05-12 15:23:40 +0300576 if (!mixedSamples)
577 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
578
579 const int colorSamples = samples ? samples : 1;
580 const int depthSamples = depthAttachment.getSamples();
581 if ((depthSamples % colorSamples) != 0)
582 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000583 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000584 }
585
Jamie Madill48ef11b2016-04-27 15:21:52 -0400586 const FramebufferAttachment &stencilAttachment = mState.mStencilAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -0400587 if (stencilAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000588 {
Jamie Madill6b120b92015-11-24 13:00:07 -0500589 const Extents &size = stencilAttachment.getSize();
590 if (size.width == 0 || size.height == 0)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000591 {
592 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
593 }
594
Jamie Madill2d06b732015-04-20 12:53:28 -0400595 GLenum internalformat = stencilAttachment.getInternalFormat();
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700596 const TextureCaps &formatCaps = state.getTextureCap(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400597 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill2d06b732015-04-20 12:53:28 -0400598 if (stencilAttachment.type() == GL_TEXTURE)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000599 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000600 // texture stencil attachments come along as part
601 // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700602 if (!state.getExtensions().depthTextures)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000603 {
604 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
605 }
606
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400607 if (!formatCaps.renderable)
Geoff Langcec35902014-04-16 10:52:36 -0400608 {
Jamie Madill81176782015-11-24 16:10:23 -0500609 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
Geoff Langcec35902014-04-16 10:52:36 -0400610 }
611
Geoff Lang5d601382014-07-22 15:14:06 -0400612 if (formatInfo.stencilBits == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000613 {
614 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
615 }
616 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400617 else if (stencilAttachment.type() == GL_RENDERBUFFER)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000618 {
Geoff Lang5d601382014-07-22 15:14:06 -0400619 if (!formatCaps.renderable || formatInfo.stencilBits == 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400620 {
621 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
622 }
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000623 }
624
625 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000626 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400627 samples = stencilAttachment.getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000628 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000629 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400630 else if (samples != stencilAttachment.getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000631 {
Sami Väisänena797e062016-05-12 15:23:40 +0300632 // see the comments in depth attachment check.
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700633 const bool mixedSamples = state.getExtensions().framebufferMixedSamples;
Sami Väisänena797e062016-05-12 15:23:40 +0300634 if (!mixedSamples)
635 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
636
637 const int colorSamples = samples ? samples : 1;
638 const int stencilSamples = stencilAttachment.getSamples();
639 if ((stencilSamples % colorSamples) != 0)
640 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000641 }
Corentin Wallez086d59a2016-04-29 09:06:49 -0400642
643 // Starting from ES 3.0 stencil and depth, if present, should be the same image
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700644 if (state.getClientVersion() >= 3 && depthAttachment.isAttached() &&
Corentin Wallez086d59a2016-04-29 09:06:49 -0400645 stencilAttachment != depthAttachment)
646 {
647 return GL_FRAMEBUFFER_UNSUPPORTED;
648 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000649 }
650
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000651 // we need to have at least one attachment to be complete
652 if (missingAttachment)
653 {
654 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000655 }
656
Jamie Madillcc86d642015-11-24 13:00:07 -0500657 // In ES 2.0, all color attachments must have the same width and height.
658 // In ES 3.0, there is no such restriction.
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700659 if (state.getClientVersion() < 3 && !mState.attachmentsHaveSameDimensions())
Jamie Madillcc86d642015-11-24 13:00:07 -0500660 {
661 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
662 }
663
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500664 syncState();
Jamie Madillcc86d642015-11-24 13:00:07 -0500665 if (!mImpl->checkStatus())
666 {
667 return GL_FRAMEBUFFER_UNSUPPORTED;
668 }
669
670 return GL_FRAMEBUFFER_COMPLETE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000671}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000672
Austin Kinross08332632015-05-05 13:35:47 -0700673Error Framebuffer::discard(size_t count, const GLenum *attachments)
674{
675 return mImpl->discard(count, attachments);
676}
677
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500678Error Framebuffer::invalidate(size_t count, const GLenum *attachments)
Jamie Madill2d96b9e2014-08-29 15:46:47 -0400679{
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500680 return mImpl->invalidate(count, attachments);
Jamie Madill2d96b9e2014-08-29 15:46:47 -0400681}
682
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500683Error Framebuffer::invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area)
Jamie Madill400a4412014-08-29 15:46:45 -0400684{
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500685 return mImpl->invalidateSub(count, attachments, area);
Jamie Madill400a4412014-08-29 15:46:45 -0400686}
687
Jamie Madill8415b5f2016-04-26 13:41:39 -0400688Error Framebuffer::clear(rx::ContextImpl *context, GLbitfield mask)
Geoff Langb04dc822014-12-01 12:02:02 -0500689{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700690 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500691 {
Jamie Madill362876b2016-06-16 14:46:59 -0400692 return gl::NoError();
Jamie Madill984ef412015-11-24 16:10:21 -0500693 }
694
Jamie Madill8415b5f2016-04-26 13:41:39 -0400695 return mImpl->clear(context, mask);
Geoff Langb04dc822014-12-01 12:02:02 -0500696}
697
Jamie Madill8415b5f2016-04-26 13:41:39 -0400698Error Framebuffer::clearBufferfv(rx::ContextImpl *context,
Jamie Madill1b94d432015-08-07 13:23:23 -0400699 GLenum buffer,
700 GLint drawbuffer,
701 const GLfloat *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500702{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700703 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500704 {
Jamie Madill362876b2016-06-16 14:46:59 -0400705 return gl::NoError();
Jamie Madill984ef412015-11-24 16:10:21 -0500706 }
707
Jamie Madill8415b5f2016-04-26 13:41:39 -0400708 return mImpl->clearBufferfv(context, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500709}
710
Jamie Madill8415b5f2016-04-26 13:41:39 -0400711Error Framebuffer::clearBufferuiv(rx::ContextImpl *context,
Jamie Madill1b94d432015-08-07 13:23:23 -0400712 GLenum buffer,
713 GLint drawbuffer,
714 const GLuint *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500715{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700716 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500717 {
Jamie Madill362876b2016-06-16 14:46:59 -0400718 return gl::NoError();
Jamie Madill984ef412015-11-24 16:10:21 -0500719 }
720
Jamie Madill8415b5f2016-04-26 13:41:39 -0400721 return mImpl->clearBufferuiv(context, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500722}
723
Jamie Madill8415b5f2016-04-26 13:41:39 -0400724Error Framebuffer::clearBufferiv(rx::ContextImpl *context,
Jamie Madill1b94d432015-08-07 13:23:23 -0400725 GLenum buffer,
726 GLint drawbuffer,
727 const GLint *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500728{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700729 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500730 {
Jamie Madill362876b2016-06-16 14:46:59 -0400731 return gl::NoError();
Jamie Madill984ef412015-11-24 16:10:21 -0500732 }
733
Jamie Madill8415b5f2016-04-26 13:41:39 -0400734 return mImpl->clearBufferiv(context, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500735}
736
Jamie Madill8415b5f2016-04-26 13:41:39 -0400737Error Framebuffer::clearBufferfi(rx::ContextImpl *context,
Jamie Madill1b94d432015-08-07 13:23:23 -0400738 GLenum buffer,
739 GLint drawbuffer,
740 GLfloat depth,
741 GLint stencil)
Geoff Langb04dc822014-12-01 12:02:02 -0500742{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700743 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500744 {
Jamie Madill362876b2016-06-16 14:46:59 -0400745 return gl::NoError();
Jamie Madill984ef412015-11-24 16:10:21 -0500746 }
747
Jamie Madill8415b5f2016-04-26 13:41:39 -0400748 return mImpl->clearBufferfi(context, buffer, drawbuffer, depth, stencil);
Geoff Langb04dc822014-12-01 12:02:02 -0500749}
750
Geoff Langbce529e2014-12-01 12:48:41 -0500751GLenum Framebuffer::getImplementationColorReadFormat() const
752{
753 return mImpl->getImplementationColorReadFormat();
754}
755
756GLenum Framebuffer::getImplementationColorReadType() const
757{
758 return mImpl->getImplementationColorReadType();
759}
760
Jamie Madill8415b5f2016-04-26 13:41:39 -0400761Error Framebuffer::readPixels(rx::ContextImpl *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500762 const Rectangle &area,
Jamie Madill1b94d432015-08-07 13:23:23 -0400763 GLenum format,
764 GLenum type,
765 GLvoid *pixels) const
Geoff Langbce529e2014-12-01 12:48:41 -0500766{
Jamie Madill362876b2016-06-16 14:46:59 -0400767 ANGLE_TRY(mImpl->readPixels(context, area, format, type, pixels));
Geoff Lang520c4ae2015-05-05 13:12:36 -0400768
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700769 Buffer *unpackBuffer = context->getGLState().getUnpackState().pixelBuffer.get();
Geoff Lang520c4ae2015-05-05 13:12:36 -0400770 if (unpackBuffer)
771 {
772 unpackBuffer->onPixelUnpack();
773 }
774
Jamie Madill362876b2016-06-16 14:46:59 -0400775 return NoError();
Geoff Langbce529e2014-12-01 12:48:41 -0500776}
777
Jamie Madill8415b5f2016-04-26 13:41:39 -0400778Error Framebuffer::blit(rx::ContextImpl *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500779 const Rectangle &sourceArea,
780 const Rectangle &destArea,
Geoff Lang242468f2015-09-24 14:15:41 -0400781 GLbitfield mask,
Jamie Madill8415b5f2016-04-26 13:41:39 -0400782 GLenum filter)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500783{
Jamie Madill8415b5f2016-04-26 13:41:39 -0400784 return mImpl->blit(context, sourceArea, destArea, mask, filter);
Geoff Lang54bd5a42014-12-01 12:51:04 -0500785}
786
Jamie Madill51f40ec2016-06-15 14:06:00 -0400787int Framebuffer::getSamples(const ContextState &state)
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000788{
Jamie Madill362876b2016-06-16 14:46:59 -0400789 if (complete(state))
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000790 {
Jamie Madill362876b2016-06-16 14:46:59 -0400791 // For a complete framebuffer, all attachments must have the same sample count.
792 // In this case return the first nonzero sample size.
793 const auto *firstColorAttachment = mState.getFirstColorAttachment();
794 if (firstColorAttachment)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000795 {
Jamie Madill362876b2016-06-16 14:46:59 -0400796 ASSERT(firstColorAttachment->isAttached());
797 return firstColorAttachment->getSamples();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000798 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000799 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000800
801 return 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000802}
803
Jamie Madille261b442014-06-25 12:42:21 -0400804bool Framebuffer::hasValidDepthStencil() const
805{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400806 return mState.getDepthStencilAttachment() != nullptr;
Jamie Madille261b442014-06-25 12:42:21 -0400807}
808
Jamie Madill2d06b732015-04-20 12:53:28 -0400809void Framebuffer::setAttachment(GLenum type,
810 GLenum binding,
811 const ImageIndex &textureIndex,
812 FramebufferAttachmentObject *resource)
Geoff Langab75a052014-10-15 12:56:37 -0400813{
Jamie Madill2d06b732015-04-20 12:53:28 -0400814 if (binding == GL_DEPTH_STENCIL || binding == GL_DEPTH_STENCIL_ATTACHMENT)
Geoff Langab75a052014-10-15 12:56:37 -0400815 {
Geoff Langab75a052014-10-15 12:56:37 -0400816 // ensure this is a legitimate depth+stencil format
Jamie Madill375c37c2015-07-21 15:14:08 -0400817 FramebufferAttachmentObject *attachmentObj = resource;
818 if (resource)
Geoff Langab75a052014-10-15 12:56:37 -0400819 {
Jamie Madill375c37c2015-07-21 15:14:08 -0400820 FramebufferAttachment::Target target(binding, textureIndex);
821 GLenum internalFormat = resource->getAttachmentInternalFormat(target);
822 const InternalFormat &formatInfo = GetInternalFormatInfo(internalFormat);
823 if (formatInfo.depthBits == 0 || formatInfo.stencilBits == 0)
824 {
825 // Attaching nullptr detaches the current attachment.
826 attachmentObj = nullptr;
827 }
Geoff Langab75a052014-10-15 12:56:37 -0400828 }
Jamie Madill375c37c2015-07-21 15:14:08 -0400829
Jamie Madill48ef11b2016-04-27 15:21:52 -0400830 mState.mDepthAttachment.attach(type, binding, textureIndex, attachmentObj);
831 mState.mStencilAttachment.attach(type, binding, textureIndex, attachmentObj);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500832 mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT);
833 mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT);
Jamie Madill362876b2016-06-16 14:46:59 -0400834 BindResourceChannel(&mDirtyDepthAttachmentBinding, resource);
835 BindResourceChannel(&mDirtyStencilAttachmentBinding, resource);
Geoff Langab75a052014-10-15 12:56:37 -0400836 }
837 else
838 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400839 switch (binding)
840 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500841 case GL_DEPTH:
842 case GL_DEPTH_ATTACHMENT:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400843 mState.mDepthAttachment.attach(type, binding, textureIndex, resource);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500844 mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT);
Jamie Madill362876b2016-06-16 14:46:59 -0400845 BindResourceChannel(&mDirtyDepthAttachmentBinding, resource);
846 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500847 case GL_STENCIL:
848 case GL_STENCIL_ATTACHMENT:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400849 mState.mStencilAttachment.attach(type, binding, textureIndex, resource);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500850 mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT);
Jamie Madill362876b2016-06-16 14:46:59 -0400851 BindResourceChannel(&mDirtyStencilAttachmentBinding, resource);
852 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500853 case GL_BACK:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400854 mState.mColorAttachments[0].attach(type, binding, textureIndex, resource);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500855 mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0);
Jamie Madill362876b2016-06-16 14:46:59 -0400856 // No need for a resource binding for the default FBO, it's always complete.
857 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500858 default:
Jamie Madill2d06b732015-04-20 12:53:28 -0400859 {
860 size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
Jamie Madill48ef11b2016-04-27 15:21:52 -0400861 ASSERT(colorIndex < mState.mColorAttachments.size());
862 mState.mColorAttachments[colorIndex].attach(type, binding, textureIndex, resource);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500863 mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
Jamie Madill362876b2016-06-16 14:46:59 -0400864 BindResourceChannel(&mDirtyColorAttachmentBindings[colorIndex], resource);
Jamie Madill2d06b732015-04-20 12:53:28 -0400865 }
866 break;
867 }
Geoff Langab75a052014-10-15 12:56:37 -0400868 }
869}
870
Jamie Madill2d06b732015-04-20 12:53:28 -0400871void Framebuffer::resetAttachment(GLenum binding)
872{
873 setAttachment(GL_NONE, binding, ImageIndex::MakeInvalid(), nullptr);
874}
875
Jamie Madill362876b2016-06-16 14:46:59 -0400876void Framebuffer::syncState()
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500877{
878 if (mDirtyBits.any())
879 {
880 mImpl->syncState(mDirtyBits);
881 mDirtyBits.reset();
Jamie Madill362876b2016-06-16 14:46:59 -0400882 mCachedStatus.reset();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500883 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000884}
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500885
Jamie Madill362876b2016-06-16 14:46:59 -0400886void Framebuffer::signal(SignalToken token)
Jamie Madill51f40ec2016-06-15 14:06:00 -0400887{
Jamie Madill362876b2016-06-16 14:46:59 -0400888 // TOOD(jmadill): Make this only update individual attachments to do less work.
889 mCachedStatus.reset();
Jamie Madill51f40ec2016-06-15 14:06:00 -0400890}
891
Jamie Madill362876b2016-06-16 14:46:59 -0400892bool Framebuffer::complete(const ContextState &state)
Jamie Madill51f40ec2016-06-15 14:06:00 -0400893{
Jamie Madill362876b2016-06-16 14:46:59 -0400894 return (checkStatus(state) == GL_FRAMEBUFFER_COMPLETE);
Jamie Madill51f40ec2016-06-15 14:06:00 -0400895}
896
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500897} // namespace gl