blob: 4bb21385491380611332dddb87e63b731d7174e8 [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{
99 ASSERT(mReadBufferState == GL_BACK || (mReadBufferState >= GL_COLOR_ATTACHMENT0 && mReadBufferState <= GL_COLOR_ATTACHMENT15));
100 size_t readIndex = (mReadBufferState == GL_BACK ? 0 : static_cast<size_t>(mReadBufferState - GL_COLOR_ATTACHMENT0));
101 ASSERT(readIndex < mColorAttachments.size());
Jamie Madill2d06b732015-04-20 12:53:28 -0400102 return mColorAttachments[readIndex].isAttached() ? &mColorAttachments[readIndex] : nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500103}
104
Jamie Madill48ef11b2016-04-27 15:21:52 -0400105const FramebufferAttachment *FramebufferState::getFirstColorAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500106{
Jamie Madill2d06b732015-04-20 12:53:28 -0400107 for (const FramebufferAttachment &colorAttachment : mColorAttachments)
Jamie Madill7147f012015-03-05 15:41:40 -0500108 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400109 if (colorAttachment.isAttached())
Jamie Madill7147f012015-03-05 15:41:40 -0500110 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400111 return &colorAttachment;
Jamie Madill7147f012015-03-05 15:41:40 -0500112 }
113 }
114
115 return nullptr;
116}
117
Jamie Madill48ef11b2016-04-27 15:21:52 -0400118const FramebufferAttachment *FramebufferState::getDepthOrStencilAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500119{
Jamie Madill2d06b732015-04-20 12:53:28 -0400120 if (mDepthAttachment.isAttached())
121 {
122 return &mDepthAttachment;
123 }
124 if (mStencilAttachment.isAttached())
125 {
126 return &mStencilAttachment;
127 }
128 return nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500129}
130
Jamie Madill48ef11b2016-04-27 15:21:52 -0400131const FramebufferAttachment *FramebufferState::getColorAttachment(size_t colorAttachment) const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400132{
133 ASSERT(colorAttachment < mColorAttachments.size());
Jamie Madill2d06b732015-04-20 12:53:28 -0400134 return mColorAttachments[colorAttachment].isAttached() ?
135 &mColorAttachments[colorAttachment] :
136 nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400137}
138
Jamie Madill48ef11b2016-04-27 15:21:52 -0400139const FramebufferAttachment *FramebufferState::getDepthAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400140{
Jamie Madill2d06b732015-04-20 12:53:28 -0400141 return mDepthAttachment.isAttached() ? &mDepthAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400142}
143
Jamie Madill48ef11b2016-04-27 15:21:52 -0400144const FramebufferAttachment *FramebufferState::getStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400145{
Jamie Madill2d06b732015-04-20 12:53:28 -0400146 return mStencilAttachment.isAttached() ? &mStencilAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400147}
148
Jamie Madill48ef11b2016-04-27 15:21:52 -0400149const FramebufferAttachment *FramebufferState::getDepthStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400150{
151 // A valid depth-stencil attachment has the same resource bound to both the
152 // depth and stencil attachment points.
Jamie Madill2d06b732015-04-20 12:53:28 -0400153 if (mDepthAttachment.isAttached() && mStencilAttachment.isAttached() &&
154 mDepthAttachment.type() == mStencilAttachment.type() &&
155 mDepthAttachment.id() == mStencilAttachment.id())
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400156 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400157 return &mDepthAttachment;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400158 }
159
160 return nullptr;
161}
162
Jamie Madill48ef11b2016-04-27 15:21:52 -0400163bool FramebufferState::attachmentsHaveSameDimensions() const
Jamie Madillcc86d642015-11-24 13:00:07 -0500164{
165 Optional<Extents> attachmentSize;
166
167 auto hasMismatchedSize = [&attachmentSize](const FramebufferAttachment &attachment)
168 {
169 if (!attachment.isAttached())
170 {
171 return false;
172 }
173
174 if (!attachmentSize.valid())
175 {
176 attachmentSize = attachment.getSize();
177 return false;
178 }
179
180 return (attachment.getSize() != attachmentSize.value());
181 };
182
183 for (const auto &attachment : mColorAttachments)
184 {
185 if (hasMismatchedSize(attachment))
186 {
187 return false;
188 }
189 }
190
191 if (hasMismatchedSize(mDepthAttachment))
192 {
193 return false;
194 }
195
196 return !hasMismatchedSize(mStencilAttachment);
197}
198
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400199const gl::FramebufferAttachment *FramebufferState::getDrawBuffer(size_t drawBufferIdx) const
200{
201 ASSERT(drawBufferIdx < mDrawBufferStates.size());
202 if (mDrawBufferStates[drawBufferIdx] != GL_NONE)
203 {
204 // ES3 spec: "If the GL is bound to a draw framebuffer object, the ith buffer listed in bufs
205 // must be COLOR_ATTACHMENTi or NONE"
206 ASSERT(mDrawBufferStates[drawBufferIdx] == GL_COLOR_ATTACHMENT0 + drawBufferIdx ||
207 (drawBufferIdx == 0 && mDrawBufferStates[drawBufferIdx] == GL_BACK));
208 return getAttachment(mDrawBufferStates[drawBufferIdx]);
209 }
210 else
211 {
212 return nullptr;
213 }
214}
215
216size_t FramebufferState::getDrawBufferCount() const
217{
218 return mDrawBufferStates.size();
219}
220
Geoff Langb21e20d2016-07-19 15:35:41 -0400221bool FramebufferState::colorAttachmentsAreUniqueImages() const
222{
223 for (size_t firstAttachmentIdx = 0; firstAttachmentIdx < mColorAttachments.size();
224 firstAttachmentIdx++)
225 {
226 const gl::FramebufferAttachment &firstAttachment = mColorAttachments[firstAttachmentIdx];
227 if (!firstAttachment.isAttached())
228 {
229 continue;
230 }
231
232 for (size_t secondAttachmentIdx = firstAttachmentIdx + 1;
233 secondAttachmentIdx < mColorAttachments.size(); secondAttachmentIdx++)
234 {
235 const gl::FramebufferAttachment &secondAttachment =
236 mColorAttachments[secondAttachmentIdx];
237 if (!secondAttachment.isAttached())
238 {
239 continue;
240 }
241
242 if (firstAttachment == secondAttachment)
243 {
244 return false;
245 }
246 }
247 }
248
249 return true;
250}
251
Jamie Madill7aea7e02016-05-10 10:39:45 -0400252Framebuffer::Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id)
Jamie Madill362876b2016-06-16 14:46:59 -0400253 : mState(caps),
254 mImpl(factory->createFramebuffer(mState)),
255 mId(id),
256 mCachedStatus(),
257 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
258 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000259{
Corentin Wallez37c39792015-08-20 14:19:46 -0400260 ASSERT(mId != 0);
261 ASSERT(mImpl != nullptr);
Jamie Madill362876b2016-06-16 14:46:59 -0400262 ASSERT(mState.mColorAttachments.size() == static_cast<size_t>(caps.maxColorAttachments));
263
264 for (size_t colorIndex = 0; colorIndex < mState.mColorAttachments.size(); ++colorIndex)
265 {
266 mDirtyColorAttachmentBindings.push_back(ChannelBinding(
267 this, static_cast<SignalToken>(DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex)));
268 }
Corentin Wallez37c39792015-08-20 14:19:46 -0400269}
270
271Framebuffer::Framebuffer(rx::SurfaceImpl *surface)
Jamie Madill362876b2016-06-16 14:46:59 -0400272 : mState(),
273 mImpl(surface->createDefaultFramebuffer(mState)),
274 mId(0),
275 mCachedStatus(GL_FRAMEBUFFER_COMPLETE),
276 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
277 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
Corentin Wallez37c39792015-08-20 14:19:46 -0400278{
Geoff Langda88add2014-12-01 10:22:01 -0500279 ASSERT(mImpl != nullptr);
Jamie Madill362876b2016-06-16 14:46:59 -0400280 mDirtyColorAttachmentBindings.push_back(
281 ChannelBinding(this, static_cast<SignalToken>(DIRTY_BIT_COLOR_ATTACHMENT_0)));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000282}
283
284Framebuffer::~Framebuffer()
285{
Geoff Langda88add2014-12-01 10:22:01 -0500286 SafeDelete(mImpl);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000287}
288
Geoff Lang70d0f492015-12-10 17:45:46 -0500289void Framebuffer::setLabel(const std::string &label)
290{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400291 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -0500292}
293
294const std::string &Framebuffer::getLabel() const
295{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400296 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -0500297}
298
Jamie Madille261b442014-06-25 12:42:21 -0400299void Framebuffer::detachTexture(GLuint textureId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000300{
Jamie Madilld1405e52015-03-05 15:41:39 -0500301 detachResourceById(GL_TEXTURE, textureId);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000302}
303
Jamie Madille261b442014-06-25 12:42:21 -0400304void Framebuffer::detachRenderbuffer(GLuint renderbufferId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000305{
Jamie Madilld1405e52015-03-05 15:41:39 -0500306 detachResourceById(GL_RENDERBUFFER, renderbufferId);
307}
Jamie Madille261b442014-06-25 12:42:21 -0400308
Jamie Madilld1405e52015-03-05 15:41:39 -0500309void Framebuffer::detachResourceById(GLenum resourceType, GLuint resourceId)
310{
Jamie Madill362876b2016-06-16 14:46:59 -0400311 for (size_t colorIndex = 0; colorIndex < mState.mColorAttachments.size(); ++colorIndex)
Jamie Madilld1405e52015-03-05 15:41:39 -0500312 {
Jamie Madill362876b2016-06-16 14:46:59 -0400313 detachMatchingAttachment(&mState.mColorAttachments[colorIndex], resourceType, resourceId,
314 DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000315 }
316
Jamie Madill362876b2016-06-16 14:46:59 -0400317 detachMatchingAttachment(&mState.mDepthAttachment, resourceType, resourceId,
318 DIRTY_BIT_DEPTH_ATTACHMENT);
319 detachMatchingAttachment(&mState.mStencilAttachment, resourceType, resourceId,
320 DIRTY_BIT_STENCIL_ATTACHMENT);
321}
322
323void Framebuffer::detachMatchingAttachment(FramebufferAttachment *attachment,
324 GLenum matchType,
325 GLuint matchId,
326 size_t dirtyBit)
327{
328 if (attachment->isAttached() && attachment->type() == matchType && attachment->id() == matchId)
329 {
330 attachment->detach();
331 mDirtyBits.set(dirtyBit);
332 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000333}
334
Corentin Wallez37c39792015-08-20 14:19:46 -0400335const FramebufferAttachment *Framebuffer::getColorbuffer(size_t colorAttachment) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000336{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400337 return mState.getColorAttachment(colorAttachment);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000338}
339
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400340const FramebufferAttachment *Framebuffer::getDepthbuffer() const
Geoff Lang646559f2013-08-15 11:08:15 -0400341{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400342 return mState.getDepthAttachment();
Geoff Lang646559f2013-08-15 11:08:15 -0400343}
344
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400345const FramebufferAttachment *Framebuffer::getStencilbuffer() const
346{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400347 return mState.getStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400348}
349
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400350const FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
351{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400352 return mState.getDepthStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400353}
354
355const FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000356{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400357 return mState.getDepthOrStencilAttachment();
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000358}
359
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400360const FramebufferAttachment *Framebuffer::getReadColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000361{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400362 return mState.getReadAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000363}
364
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000365GLenum Framebuffer::getReadColorbufferType() const
366{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400367 const FramebufferAttachment *readAttachment = mState.getReadAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400368 return (readAttachment != nullptr ? readAttachment->type() : GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000369}
370
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400371const FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000372{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400373 return mState.getFirstColorAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000374}
375
Jamie Madill2d06b732015-04-20 12:53:28 -0400376const FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000377{
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400378 return mState.getAttachment(attachment);
Geoff Lang55ba29c2013-07-11 16:57:53 -0400379}
380
Geoff Langa15472a2015-08-11 11:48:03 -0400381size_t Framebuffer::getDrawbufferStateCount() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000382{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400383 return mState.mDrawBufferStates.size();
Geoff Langa15472a2015-08-11 11:48:03 -0400384}
385
386GLenum Framebuffer::getDrawBufferState(size_t drawBuffer) const
387{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400388 ASSERT(drawBuffer < mState.mDrawBufferStates.size());
389 return mState.mDrawBufferStates[drawBuffer];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000390}
391
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500392const std::vector<GLenum> &Framebuffer::getDrawBufferStates() const
393{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400394 return mState.getDrawBufferStates();
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500395}
396
Geoff Lang164d54e2014-12-01 10:55:33 -0500397void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000398{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400399 auto &drawStates = mState.mDrawBufferStates;
Jamie Madilld1405e52015-03-05 15:41:39 -0500400
401 ASSERT(count <= drawStates.size());
402 std::copy(buffers, buffers + count, drawStates.begin());
403 std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500404 mDirtyBits.set(DIRTY_BIT_DRAW_BUFFERS);
Geoff Lang9dd95802014-12-01 11:12:59 -0500405}
406
Geoff Langa15472a2015-08-11 11:48:03 -0400407const FramebufferAttachment *Framebuffer::getDrawBuffer(size_t drawBuffer) const
408{
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400409 return mState.getDrawBuffer(drawBuffer);
Geoff Langa15472a2015-08-11 11:48:03 -0400410}
411
412bool Framebuffer::hasEnabledDrawBuffer() const
413{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400414 for (size_t drawbufferIdx = 0; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
Geoff Langa15472a2015-08-11 11:48:03 -0400415 {
416 if (getDrawBuffer(drawbufferIdx) != nullptr)
417 {
418 return true;
419 }
420 }
421
422 return false;
423}
424
Geoff Lang9dd95802014-12-01 11:12:59 -0500425GLenum Framebuffer::getReadBufferState() const
426{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400427 return mState.mReadBufferState;
Geoff Lang9dd95802014-12-01 11:12:59 -0500428}
429
430void Framebuffer::setReadBuffer(GLenum buffer)
431{
Jamie Madillb885e572015-02-03 16:16:04 -0500432 ASSERT(buffer == GL_BACK || buffer == GL_NONE ||
433 (buffer >= GL_COLOR_ATTACHMENT0 &&
Jamie Madill48ef11b2016-04-27 15:21:52 -0400434 (buffer - GL_COLOR_ATTACHMENT0) < mState.mColorAttachments.size()));
435 mState.mReadBufferState = buffer;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500436 mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000437}
438
Corentin Wallez37c39792015-08-20 14:19:46 -0400439size_t Framebuffer::getNumColorBuffers() const
440{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400441 return mState.mColorAttachments.size();
Corentin Wallez37c39792015-08-20 14:19:46 -0400442}
443
Jamie Madill0df8fe42015-11-24 16:10:24 -0500444bool Framebuffer::hasDepth() const
445{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400446 return (mState.mDepthAttachment.isAttached() && mState.mDepthAttachment.getDepthSize() > 0);
Jamie Madill0df8fe42015-11-24 16:10:24 -0500447}
448
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000449bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000450{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400451 return (mState.mStencilAttachment.isAttached() &&
452 mState.mStencilAttachment.getStencilSize() > 0);
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000453}
454
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000455bool Framebuffer::usingExtendedDrawBuffers() const
456{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400457 for (size_t drawbufferIdx = 1; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000458 {
Geoff Langa15472a2015-08-11 11:48:03 -0400459 if (getDrawBuffer(drawbufferIdx) != nullptr)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000460 {
461 return true;
462 }
463 }
464
465 return false;
466}
467
Jamie Madill51f40ec2016-06-15 14:06:00 -0400468GLenum Framebuffer::checkStatus(const ContextState &state)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000469{
Geoff Lang528ce3c2014-12-01 10:44:07 -0500470 // The default framebuffer *must* always be complete, though it may not be
471 // subject to the same rules as application FBOs. ie, it could have 0x0 size.
472 if (mId == 0)
473 {
474 return GL_FRAMEBUFFER_COMPLETE;
475 }
476
Jamie Madill362876b2016-06-16 14:46:59 -0400477 if (hasAnyDirtyBit() || !mCachedStatus.valid())
478 {
479 mCachedStatus = checkStatusImpl(state);
480 }
481
482 return mCachedStatus.value();
483}
484
485GLenum Framebuffer::checkStatusImpl(const ContextState &state)
486{
487 ASSERT(mId != 0);
488
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000489 unsigned int colorbufferSize = 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000490 int samples = -1;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000491 bool missingAttachment = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000492
Jamie Madill48ef11b2016-04-27 15:21:52 -0400493 for (const FramebufferAttachment &colorAttachment : mState.mColorAttachments)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000494 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400495 if (colorAttachment.isAttached())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000496 {
Jamie Madill6b120b92015-11-24 13:00:07 -0500497 const Extents &size = colorAttachment.getSize();
498 if (size.width == 0 || size.height == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000499 {
500 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
501 }
daniel@transgaming.com01868132010-08-24 19:21:17 +0000502
Jamie Madilla3944d42016-07-22 22:13:26 -0400503 const Format &format = colorAttachment.getFormat();
504 const TextureCaps &formatCaps = state.getTextureCap(format.asSized());
Jamie Madill2d06b732015-04-20 12:53:28 -0400505 if (colorAttachment.type() == GL_TEXTURE)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000506 {
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400507 if (!formatCaps.renderable)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000508 {
Jamie Madill81176782015-11-24 16:10:23 -0500509 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000510 }
511
Jamie Madilla3944d42016-07-22 22:13:26 -0400512 if (format.info->depthBits > 0 || format.info->stencilBits > 0)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000513 {
514 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
515 }
Jamie Madill6b120b92015-11-24 13:00:07 -0500516
517 if (colorAttachment.layer() >= size.depth)
518 {
519 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
520 }
Jamie Madill3215b202015-12-15 16:41:39 -0500521
522 // ES3 specifies that cube map texture attachments must be cube complete.
523 // This language is missing from the ES2 spec, but we enforce it here because some
524 // desktop OpenGL drivers also enforce this validation.
525 // TODO(jmadill): Check if OpenGL ES2 drivers enforce cube completeness.
526 const Texture *texture = colorAttachment.getTexture();
527 ASSERT(texture);
Olli Etuahoe8528d82016-05-16 17:50:52 +0300528 if (texture->getTarget() == GL_TEXTURE_CUBE_MAP &&
529 !texture->getTextureState().isCubeComplete())
Jamie Madill3215b202015-12-15 16:41:39 -0500530 {
531 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
532 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000533 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400534 else if (colorAttachment.type() == GL_RENDERBUFFER)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000535 {
Jamie Madilla3944d42016-07-22 22:13:26 -0400536 if (!formatCaps.renderable || format.info->depthBits > 0 ||
537 format.info->stencilBits > 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400538 {
539 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
540 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000541 }
542
543 if (!missingAttachment)
544 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000545 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
546 // all color attachments have the same number of samples for the FBO to be complete.
Jamie Madill2d06b732015-04-20 12:53:28 -0400547 if (colorAttachment.getSamples() != samples)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000548 {
549 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
550 }
551
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000552 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
553 // in GLES 3.0, there is no such restriction
Martin Radev1be913c2016-07-11 17:59:16 +0300554 if (state.getClientMajorVersion() < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000555 {
Jamie Madilla3944d42016-07-22 22:13:26 -0400556 if (format.info->pixelBytes != colorbufferSize)
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000557 {
558 return GL_FRAMEBUFFER_UNSUPPORTED;
559 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000560 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000561 }
562 else
563 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400564 samples = colorAttachment.getSamples();
Jamie Madilla3944d42016-07-22 22:13:26 -0400565 colorbufferSize = format.info->pixelBytes;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000566 missingAttachment = false;
567 }
568 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000569 }
570
Jamie Madill48ef11b2016-04-27 15:21:52 -0400571 const FramebufferAttachment &depthAttachment = mState.mDepthAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -0400572 if (depthAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000573 {
Jamie Madill6b120b92015-11-24 13:00:07 -0500574 const Extents &size = depthAttachment.getSize();
575 if (size.width == 0 || size.height == 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000576 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000577 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000578 }
579
Jamie Madilla3944d42016-07-22 22:13:26 -0400580 const Format &format = depthAttachment.getFormat();
581 const TextureCaps &formatCaps = state.getTextureCap(format.asSized());
Jamie Madill2d06b732015-04-20 12:53:28 -0400582 if (depthAttachment.type() == GL_TEXTURE)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000583 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000584 // depth texture attachments require OES/ANGLE_depth_texture
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700585 if (!state.getExtensions().depthTextures)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000586 {
587 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
588 }
589
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400590 if (!formatCaps.renderable)
Geoff Langcec35902014-04-16 10:52:36 -0400591 {
Jamie Madill81176782015-11-24 16:10:23 -0500592 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
Geoff Langcec35902014-04-16 10:52:36 -0400593 }
594
Jamie Madilla3944d42016-07-22 22:13:26 -0400595 if (format.info->depthBits == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000596 {
597 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
598 }
599 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400600 else if (depthAttachment.type() == GL_RENDERBUFFER)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000601 {
Jamie Madilla3944d42016-07-22 22:13:26 -0400602 if (!formatCaps.renderable || format.info->depthBits == 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400603 {
604 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
605 }
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000606 }
607
608 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000609 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400610 samples = depthAttachment.getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000611 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000612 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400613 else if (samples != depthAttachment.getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000614 {
Sami Väisänena797e062016-05-12 15:23:40 +0300615 // CHROMIUM_framebuffer_mixed_samples allows a framebuffer to be
616 // considered complete when its depth or stencil samples are a
617 // multiple of the number of color samples.
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700618 const bool mixedSamples = state.getExtensions().framebufferMixedSamples;
Sami Väisänena797e062016-05-12 15:23:40 +0300619 if (!mixedSamples)
620 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
621
622 const int colorSamples = samples ? samples : 1;
623 const int depthSamples = depthAttachment.getSamples();
624 if ((depthSamples % colorSamples) != 0)
625 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000626 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000627 }
628
Jamie Madill48ef11b2016-04-27 15:21:52 -0400629 const FramebufferAttachment &stencilAttachment = mState.mStencilAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -0400630 if (stencilAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000631 {
Jamie Madill6b120b92015-11-24 13:00:07 -0500632 const Extents &size = stencilAttachment.getSize();
633 if (size.width == 0 || size.height == 0)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000634 {
635 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
636 }
637
Jamie Madilla3944d42016-07-22 22:13:26 -0400638 const Format &format = stencilAttachment.getFormat();
639 const TextureCaps &formatCaps = state.getTextureCap(format.asSized());
Jamie Madill2d06b732015-04-20 12:53:28 -0400640 if (stencilAttachment.type() == GL_TEXTURE)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000641 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000642 // texture stencil attachments come along as part
643 // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700644 if (!state.getExtensions().depthTextures)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000645 {
646 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
647 }
648
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400649 if (!formatCaps.renderable)
Geoff Langcec35902014-04-16 10:52:36 -0400650 {
Jamie Madill81176782015-11-24 16:10:23 -0500651 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
Geoff Langcec35902014-04-16 10:52:36 -0400652 }
653
Jamie Madilla3944d42016-07-22 22:13:26 -0400654 if (format.info->stencilBits == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000655 {
656 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
657 }
658 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400659 else if (stencilAttachment.type() == GL_RENDERBUFFER)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000660 {
Jamie Madilla3944d42016-07-22 22:13:26 -0400661 if (!formatCaps.renderable || format.info->stencilBits == 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400662 {
663 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
664 }
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000665 }
666
667 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000668 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400669 samples = stencilAttachment.getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000670 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000671 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400672 else if (samples != stencilAttachment.getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000673 {
Sami Väisänena797e062016-05-12 15:23:40 +0300674 // see the comments in depth attachment check.
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700675 const bool mixedSamples = state.getExtensions().framebufferMixedSamples;
Sami Väisänena797e062016-05-12 15:23:40 +0300676 if (!mixedSamples)
677 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
678
679 const int colorSamples = samples ? samples : 1;
680 const int stencilSamples = stencilAttachment.getSamples();
681 if ((stencilSamples % colorSamples) != 0)
682 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000683 }
Corentin Wallez086d59a2016-04-29 09:06:49 -0400684
685 // Starting from ES 3.0 stencil and depth, if present, should be the same image
Martin Radev1be913c2016-07-11 17:59:16 +0300686 if (state.getClientMajorVersion() >= 3 && depthAttachment.isAttached() &&
Corentin Wallez086d59a2016-04-29 09:06:49 -0400687 stencilAttachment != depthAttachment)
688 {
689 return GL_FRAMEBUFFER_UNSUPPORTED;
690 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000691 }
692
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000693 // we need to have at least one attachment to be complete
694 if (missingAttachment)
695 {
696 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000697 }
698
Jamie Madillcc86d642015-11-24 13:00:07 -0500699 // In ES 2.0, all color attachments must have the same width and height.
700 // In ES 3.0, there is no such restriction.
Martin Radev1be913c2016-07-11 17:59:16 +0300701 if (state.getClientMajorVersion() < 3 && !mState.attachmentsHaveSameDimensions())
Jamie Madillcc86d642015-11-24 13:00:07 -0500702 {
703 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
704 }
705
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500706 syncState();
Jamie Madillcc86d642015-11-24 13:00:07 -0500707 if (!mImpl->checkStatus())
708 {
709 return GL_FRAMEBUFFER_UNSUPPORTED;
710 }
711
712 return GL_FRAMEBUFFER_COMPLETE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000713}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000714
Austin Kinross08332632015-05-05 13:35:47 -0700715Error Framebuffer::discard(size_t count, const GLenum *attachments)
716{
717 return mImpl->discard(count, attachments);
718}
719
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500720Error Framebuffer::invalidate(size_t count, const GLenum *attachments)
Jamie Madill2d96b9e2014-08-29 15:46:47 -0400721{
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500722 return mImpl->invalidate(count, attachments);
Jamie Madill2d96b9e2014-08-29 15:46:47 -0400723}
724
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500725Error Framebuffer::invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area)
Jamie Madill400a4412014-08-29 15:46:45 -0400726{
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500727 return mImpl->invalidateSub(count, attachments, area);
Jamie Madill400a4412014-08-29 15:46:45 -0400728}
729
Jamie Madill8415b5f2016-04-26 13:41:39 -0400730Error Framebuffer::clear(rx::ContextImpl *context, GLbitfield mask)
Geoff Langb04dc822014-12-01 12:02:02 -0500731{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700732 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500733 {
Jamie Madill362876b2016-06-16 14:46:59 -0400734 return gl::NoError();
Jamie Madill984ef412015-11-24 16:10:21 -0500735 }
736
Jamie Madill8415b5f2016-04-26 13:41:39 -0400737 return mImpl->clear(context, mask);
Geoff Langb04dc822014-12-01 12:02:02 -0500738}
739
Jamie Madill8415b5f2016-04-26 13:41:39 -0400740Error Framebuffer::clearBufferfv(rx::ContextImpl *context,
Jamie Madill1b94d432015-08-07 13:23:23 -0400741 GLenum buffer,
742 GLint drawbuffer,
743 const GLfloat *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500744{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700745 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500746 {
Jamie Madill362876b2016-06-16 14:46:59 -0400747 return gl::NoError();
Jamie Madill984ef412015-11-24 16:10:21 -0500748 }
749
Jamie Madill8415b5f2016-04-26 13:41:39 -0400750 return mImpl->clearBufferfv(context, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500751}
752
Jamie Madill8415b5f2016-04-26 13:41:39 -0400753Error Framebuffer::clearBufferuiv(rx::ContextImpl *context,
Jamie Madill1b94d432015-08-07 13:23:23 -0400754 GLenum buffer,
755 GLint drawbuffer,
756 const GLuint *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500757{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700758 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500759 {
Jamie Madill362876b2016-06-16 14:46:59 -0400760 return gl::NoError();
Jamie Madill984ef412015-11-24 16:10:21 -0500761 }
762
Jamie Madill8415b5f2016-04-26 13:41:39 -0400763 return mImpl->clearBufferuiv(context, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500764}
765
Jamie Madill8415b5f2016-04-26 13:41:39 -0400766Error Framebuffer::clearBufferiv(rx::ContextImpl *context,
Jamie Madill1b94d432015-08-07 13:23:23 -0400767 GLenum buffer,
768 GLint drawbuffer,
769 const GLint *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500770{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700771 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500772 {
Jamie Madill362876b2016-06-16 14:46:59 -0400773 return gl::NoError();
Jamie Madill984ef412015-11-24 16:10:21 -0500774 }
775
Jamie Madill8415b5f2016-04-26 13:41:39 -0400776 return mImpl->clearBufferiv(context, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500777}
778
Jamie Madill8415b5f2016-04-26 13:41:39 -0400779Error Framebuffer::clearBufferfi(rx::ContextImpl *context,
Jamie Madill1b94d432015-08-07 13:23:23 -0400780 GLenum buffer,
781 GLint drawbuffer,
782 GLfloat depth,
783 GLint stencil)
Geoff Langb04dc822014-12-01 12:02:02 -0500784{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700785 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500786 {
Jamie Madill362876b2016-06-16 14:46:59 -0400787 return gl::NoError();
Jamie Madill984ef412015-11-24 16:10:21 -0500788 }
789
Jamie Madill8415b5f2016-04-26 13:41:39 -0400790 return mImpl->clearBufferfi(context, buffer, drawbuffer, depth, stencil);
Geoff Langb04dc822014-12-01 12:02:02 -0500791}
792
Geoff Langbce529e2014-12-01 12:48:41 -0500793GLenum Framebuffer::getImplementationColorReadFormat() const
794{
795 return mImpl->getImplementationColorReadFormat();
796}
797
798GLenum Framebuffer::getImplementationColorReadType() const
799{
800 return mImpl->getImplementationColorReadType();
801}
802
Jamie Madill8415b5f2016-04-26 13:41:39 -0400803Error Framebuffer::readPixels(rx::ContextImpl *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500804 const Rectangle &area,
Jamie Madill1b94d432015-08-07 13:23:23 -0400805 GLenum format,
806 GLenum type,
807 GLvoid *pixels) const
Geoff Langbce529e2014-12-01 12:48:41 -0500808{
Jamie Madill362876b2016-06-16 14:46:59 -0400809 ANGLE_TRY(mImpl->readPixels(context, area, format, type, pixels));
Geoff Lang520c4ae2015-05-05 13:12:36 -0400810
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700811 Buffer *unpackBuffer = context->getGLState().getUnpackState().pixelBuffer.get();
Geoff Lang520c4ae2015-05-05 13:12:36 -0400812 if (unpackBuffer)
813 {
814 unpackBuffer->onPixelUnpack();
815 }
816
Jamie Madill362876b2016-06-16 14:46:59 -0400817 return NoError();
Geoff Langbce529e2014-12-01 12:48:41 -0500818}
819
Jamie Madill8415b5f2016-04-26 13:41:39 -0400820Error Framebuffer::blit(rx::ContextImpl *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500821 const Rectangle &sourceArea,
822 const Rectangle &destArea,
Geoff Lang242468f2015-09-24 14:15:41 -0400823 GLbitfield mask,
Jamie Madill8415b5f2016-04-26 13:41:39 -0400824 GLenum filter)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500825{
Jamie Madill8415b5f2016-04-26 13:41:39 -0400826 return mImpl->blit(context, sourceArea, destArea, mask, filter);
Geoff Lang54bd5a42014-12-01 12:51:04 -0500827}
828
Jamie Madill51f40ec2016-06-15 14:06:00 -0400829int Framebuffer::getSamples(const ContextState &state)
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000830{
Jamie Madill362876b2016-06-16 14:46:59 -0400831 if (complete(state))
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000832 {
Jamie Madill362876b2016-06-16 14:46:59 -0400833 // For a complete framebuffer, all attachments must have the same sample count.
834 // In this case return the first nonzero sample size.
835 const auto *firstColorAttachment = mState.getFirstColorAttachment();
836 if (firstColorAttachment)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000837 {
Jamie Madill362876b2016-06-16 14:46:59 -0400838 ASSERT(firstColorAttachment->isAttached());
839 return firstColorAttachment->getSamples();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000840 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000841 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000842
843 return 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000844}
845
Jamie Madille261b442014-06-25 12:42:21 -0400846bool Framebuffer::hasValidDepthStencil() const
847{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400848 return mState.getDepthStencilAttachment() != nullptr;
Jamie Madille261b442014-06-25 12:42:21 -0400849}
850
Jamie Madill2d06b732015-04-20 12:53:28 -0400851void Framebuffer::setAttachment(GLenum type,
852 GLenum binding,
853 const ImageIndex &textureIndex,
854 FramebufferAttachmentObject *resource)
Geoff Langab75a052014-10-15 12:56:37 -0400855{
Jamie Madill2d06b732015-04-20 12:53:28 -0400856 if (binding == GL_DEPTH_STENCIL || binding == GL_DEPTH_STENCIL_ATTACHMENT)
Geoff Langab75a052014-10-15 12:56:37 -0400857 {
Geoff Langab75a052014-10-15 12:56:37 -0400858 // ensure this is a legitimate depth+stencil format
Jamie Madill375c37c2015-07-21 15:14:08 -0400859 FramebufferAttachmentObject *attachmentObj = resource;
860 if (resource)
Geoff Langab75a052014-10-15 12:56:37 -0400861 {
Jamie Madill375c37c2015-07-21 15:14:08 -0400862 FramebufferAttachment::Target target(binding, textureIndex);
Jamie Madilla3944d42016-07-22 22:13:26 -0400863 const Format &format = resource->getAttachmentFormat(target);
864 if (format.info->depthBits == 0 || format.info->stencilBits == 0)
Jamie Madill375c37c2015-07-21 15:14:08 -0400865 {
866 // Attaching nullptr detaches the current attachment.
867 attachmentObj = nullptr;
868 }
Geoff Langab75a052014-10-15 12:56:37 -0400869 }
Jamie Madill375c37c2015-07-21 15:14:08 -0400870
Jamie Madill48ef11b2016-04-27 15:21:52 -0400871 mState.mDepthAttachment.attach(type, binding, textureIndex, attachmentObj);
872 mState.mStencilAttachment.attach(type, binding, textureIndex, attachmentObj);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500873 mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT);
874 mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT);
Jamie Madill362876b2016-06-16 14:46:59 -0400875 BindResourceChannel(&mDirtyDepthAttachmentBinding, resource);
876 BindResourceChannel(&mDirtyStencilAttachmentBinding, resource);
Geoff Langab75a052014-10-15 12:56:37 -0400877 }
878 else
879 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400880 switch (binding)
881 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500882 case GL_DEPTH:
883 case GL_DEPTH_ATTACHMENT:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400884 mState.mDepthAttachment.attach(type, binding, textureIndex, resource);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500885 mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT);
Jamie Madill362876b2016-06-16 14:46:59 -0400886 BindResourceChannel(&mDirtyDepthAttachmentBinding, resource);
887 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500888 case GL_STENCIL:
889 case GL_STENCIL_ATTACHMENT:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400890 mState.mStencilAttachment.attach(type, binding, textureIndex, resource);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500891 mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT);
Jamie Madill362876b2016-06-16 14:46:59 -0400892 BindResourceChannel(&mDirtyStencilAttachmentBinding, resource);
893 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500894 case GL_BACK:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400895 mState.mColorAttachments[0].attach(type, binding, textureIndex, resource);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500896 mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0);
Jamie Madill362876b2016-06-16 14:46:59 -0400897 // No need for a resource binding for the default FBO, it's always complete.
898 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500899 default:
Jamie Madill2d06b732015-04-20 12:53:28 -0400900 {
901 size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
Jamie Madill48ef11b2016-04-27 15:21:52 -0400902 ASSERT(colorIndex < mState.mColorAttachments.size());
903 mState.mColorAttachments[colorIndex].attach(type, binding, textureIndex, resource);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500904 mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
Jamie Madill362876b2016-06-16 14:46:59 -0400905 BindResourceChannel(&mDirtyColorAttachmentBindings[colorIndex], resource);
Jamie Madill2d06b732015-04-20 12:53:28 -0400906 }
907 break;
908 }
Geoff Langab75a052014-10-15 12:56:37 -0400909 }
910}
911
Jamie Madill2d06b732015-04-20 12:53:28 -0400912void Framebuffer::resetAttachment(GLenum binding)
913{
914 setAttachment(GL_NONE, binding, ImageIndex::MakeInvalid(), nullptr);
915}
916
Jamie Madill362876b2016-06-16 14:46:59 -0400917void Framebuffer::syncState()
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500918{
919 if (mDirtyBits.any())
920 {
921 mImpl->syncState(mDirtyBits);
922 mDirtyBits.reset();
Jamie Madill362876b2016-06-16 14:46:59 -0400923 mCachedStatus.reset();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500924 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000925}
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500926
Jamie Madill362876b2016-06-16 14:46:59 -0400927void Framebuffer::signal(SignalToken token)
Jamie Madill51f40ec2016-06-15 14:06:00 -0400928{
Jamie Madill362876b2016-06-16 14:46:59 -0400929 // TOOD(jmadill): Make this only update individual attachments to do less work.
930 mCachedStatus.reset();
Jamie Madill51f40ec2016-06-15 14:06:00 -0400931}
932
Jamie Madill362876b2016-06-16 14:46:59 -0400933bool Framebuffer::complete(const ContextState &state)
Jamie Madill51f40ec2016-06-15 14:06:00 -0400934{
Jamie Madill362876b2016-06-16 14:46:59 -0400935 return (checkStatus(state) == GL_FRAMEBUFFER_COMPLETE);
Jamie Madill51f40ec2016-06-15 14:06:00 -0400936}
937
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500938} // namespace gl