blob: 6efe5379dc9087e01a0d92157cc174291e3db0ee [file] [log] [blame]
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00001//
Geoff Langcec35902014-04-16 10:52:36 -04002// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +00003// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// Framebuffer.cpp: Implements the gl::Framebuffer class. Implements GL framebuffer
8// objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105.
9
Geoff Lang2b5420c2014-11-19 14:20:15 -050010#include "libANGLE/Framebuffer.h"
Jamie Madillc46f45d2015-03-31 13:20:55 -040011
Jamie Madillcc86d642015-11-24 13:00:07 -050012#include "common/Optional.h"
Jamie Madillc46f45d2015-03-31 13:20:55 -040013#include "common/utilities.h"
14#include "libANGLE/Config.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050015#include "libANGLE/Context.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050016#include "libANGLE/FramebufferAttachment.h"
Jamie Madillc46f45d2015-03-31 13:20:55 -040017#include "libANGLE/Renderbuffer.h"
18#include "libANGLE/Surface.h"
19#include "libANGLE/Texture.h"
20#include "libANGLE/formatutils.h"
Jamie Madill8415b5f2016-04-26 13:41:39 -040021#include "libANGLE/renderer/ContextImpl.h"
Geoff Langb5d8f232014-12-04 15:43:01 -050022#include "libANGLE/renderer/FramebufferImpl.h"
Jamie Madill7aea7e02016-05-10 10:39:45 -040023#include "libANGLE/renderer/GLImplFactory.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050024#include "libANGLE/renderer/RenderbufferImpl.h"
Corentin Wallez37c39792015-08-20 14:19:46 -040025#include "libANGLE/renderer/SurfaceImpl.h"
Geoff Lang0b7eef72014-06-12 14:10:47 -040026
Jamie Madill362876b2016-06-16 14:46:59 -040027using namespace angle;
28
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000029namespace gl
30{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000031
Jamie Madilld1405e52015-03-05 15:41:39 -050032namespace
33{
Jamie Madill362876b2016-06-16 14:46:59 -040034
35void BindResourceChannel(ChannelBinding *binding, FramebufferAttachmentObject *resource)
Jamie Madilld1405e52015-03-05 15:41:39 -050036{
Jamie Madill362876b2016-06-16 14:46:59 -040037 binding->bind(resource ? resource->getDirtyChannel() : nullptr);
Jamie Madilld1405e52015-03-05 15:41:39 -050038}
Jamie Madill362876b2016-06-16 14:46:59 -040039
40} // anonymous namespace
Jamie Madilld1405e52015-03-05 15:41:39 -050041
Jamie Madill48ef11b2016-04-27 15:21:52 -040042FramebufferState::FramebufferState()
Geoff Lang70d0f492015-12-10 17:45:46 -050043 : mLabel(),
44 mColorAttachments(1),
Corentin Wallez37c39792015-08-20 14:19:46 -040045 mDrawBufferStates(1, GL_NONE),
46 mReadBufferState(GL_COLOR_ATTACHMENT0_EXT)
47{
48 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
49}
50
Jamie Madill48ef11b2016-04-27 15:21:52 -040051FramebufferState::FramebufferState(const Caps &caps)
Geoff Lang70d0f492015-12-10 17:45:46 -050052 : mLabel(),
53 mColorAttachments(caps.maxColorAttachments),
Jamie Madilld1405e52015-03-05 15:41:39 -050054 mDrawBufferStates(caps.maxDrawBuffers, GL_NONE),
55 mReadBufferState(GL_COLOR_ATTACHMENT0_EXT)
56{
Geoff Langa15472a2015-08-11 11:48:03 -040057 ASSERT(mDrawBufferStates.size() > 0);
Jamie Madilld1405e52015-03-05 15:41:39 -050058 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
59}
60
Jamie Madill48ef11b2016-04-27 15:21:52 -040061FramebufferState::~FramebufferState()
Jamie Madilld1405e52015-03-05 15:41:39 -050062{
Jamie Madilld1405e52015-03-05 15:41:39 -050063}
64
Jamie Madill48ef11b2016-04-27 15:21:52 -040065const std::string &FramebufferState::getLabel()
Geoff Lang70d0f492015-12-10 17:45:46 -050066{
67 return mLabel;
68}
69
Geoff Lang4b7f12b2016-06-21 16:47:07 -040070const FramebufferAttachment *FramebufferState::getAttachment(GLenum attachment) const
71{
72 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
73 {
74 return getColorAttachment(attachment - GL_COLOR_ATTACHMENT0);
75 }
76
77 switch (attachment)
78 {
79 case GL_COLOR:
80 case GL_BACK:
81 return getColorAttachment(0);
82 case GL_DEPTH:
83 case GL_DEPTH_ATTACHMENT:
84 return getDepthAttachment();
85 case GL_STENCIL:
86 case GL_STENCIL_ATTACHMENT:
87 return getStencilAttachment();
88 case GL_DEPTH_STENCIL:
89 case GL_DEPTH_STENCIL_ATTACHMENT:
90 return getDepthStencilAttachment();
91 default:
92 UNREACHABLE();
93 return nullptr;
94 }
95}
96
Jamie Madill48ef11b2016-04-27 15:21:52 -040097const FramebufferAttachment *FramebufferState::getReadAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -050098{
Antoine Labour2ec65dc2016-11-30 16:28:58 -080099 if (mReadBufferState == GL_NONE)
100 {
101 return nullptr;
102 }
Jamie Madill7147f012015-03-05 15:41:40 -0500103 ASSERT(mReadBufferState == GL_BACK || (mReadBufferState >= GL_COLOR_ATTACHMENT0 && mReadBufferState <= GL_COLOR_ATTACHMENT15));
104 size_t readIndex = (mReadBufferState == GL_BACK ? 0 : static_cast<size_t>(mReadBufferState - GL_COLOR_ATTACHMENT0));
105 ASSERT(readIndex < mColorAttachments.size());
Jamie Madill2d06b732015-04-20 12:53:28 -0400106 return mColorAttachments[readIndex].isAttached() ? &mColorAttachments[readIndex] : nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500107}
108
Jamie Madill48ef11b2016-04-27 15:21:52 -0400109const FramebufferAttachment *FramebufferState::getFirstColorAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500110{
Jamie Madill2d06b732015-04-20 12:53:28 -0400111 for (const FramebufferAttachment &colorAttachment : mColorAttachments)
Jamie Madill7147f012015-03-05 15:41:40 -0500112 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400113 if (colorAttachment.isAttached())
Jamie Madill7147f012015-03-05 15:41:40 -0500114 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400115 return &colorAttachment;
Jamie Madill7147f012015-03-05 15:41:40 -0500116 }
117 }
118
119 return nullptr;
120}
121
Jamie Madill48ef11b2016-04-27 15:21:52 -0400122const FramebufferAttachment *FramebufferState::getDepthOrStencilAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -0500123{
Jamie Madill2d06b732015-04-20 12:53:28 -0400124 if (mDepthAttachment.isAttached())
125 {
126 return &mDepthAttachment;
127 }
128 if (mStencilAttachment.isAttached())
129 {
130 return &mStencilAttachment;
131 }
132 return nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500133}
134
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500135const FramebufferAttachment *FramebufferState::getStencilOrDepthStencilAttachment() const
136{
137 if (mStencilAttachment.isAttached())
138 {
139 return &mStencilAttachment;
140 }
141 return getDepthStencilAttachment();
142}
143
Jamie Madill48ef11b2016-04-27 15:21:52 -0400144const FramebufferAttachment *FramebufferState::getColorAttachment(size_t colorAttachment) const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400145{
146 ASSERT(colorAttachment < mColorAttachments.size());
Jamie Madill2d06b732015-04-20 12:53:28 -0400147 return mColorAttachments[colorAttachment].isAttached() ?
148 &mColorAttachments[colorAttachment] :
149 nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400150}
151
Jamie Madill48ef11b2016-04-27 15:21:52 -0400152const FramebufferAttachment *FramebufferState::getDepthAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400153{
Jamie Madill2d06b732015-04-20 12:53:28 -0400154 return mDepthAttachment.isAttached() ? &mDepthAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400155}
156
Jamie Madill48ef11b2016-04-27 15:21:52 -0400157const FramebufferAttachment *FramebufferState::getStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400158{
Jamie Madill2d06b732015-04-20 12:53:28 -0400159 return mStencilAttachment.isAttached() ? &mStencilAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400160}
161
Jamie Madill48ef11b2016-04-27 15:21:52 -0400162const FramebufferAttachment *FramebufferState::getDepthStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400163{
164 // A valid depth-stencil attachment has the same resource bound to both the
165 // depth and stencil attachment points.
Jamie Madill2d06b732015-04-20 12:53:28 -0400166 if (mDepthAttachment.isAttached() && mStencilAttachment.isAttached() &&
Jamie Madill44f26482016-11-18 12:49:15 -0500167 mDepthAttachment == mStencilAttachment)
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400168 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400169 return &mDepthAttachment;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400170 }
171
172 return nullptr;
173}
174
Jamie Madill48ef11b2016-04-27 15:21:52 -0400175bool FramebufferState::attachmentsHaveSameDimensions() const
Jamie Madillcc86d642015-11-24 13:00:07 -0500176{
177 Optional<Extents> attachmentSize;
178
179 auto hasMismatchedSize = [&attachmentSize](const FramebufferAttachment &attachment)
180 {
181 if (!attachment.isAttached())
182 {
183 return false;
184 }
185
186 if (!attachmentSize.valid())
187 {
188 attachmentSize = attachment.getSize();
189 return false;
190 }
191
192 return (attachment.getSize() != attachmentSize.value());
193 };
194
195 for (const auto &attachment : mColorAttachments)
196 {
197 if (hasMismatchedSize(attachment))
198 {
199 return false;
200 }
201 }
202
203 if (hasMismatchedSize(mDepthAttachment))
204 {
205 return false;
206 }
207
208 return !hasMismatchedSize(mStencilAttachment);
209}
210
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400211const gl::FramebufferAttachment *FramebufferState::getDrawBuffer(size_t drawBufferIdx) const
212{
213 ASSERT(drawBufferIdx < mDrawBufferStates.size());
214 if (mDrawBufferStates[drawBufferIdx] != GL_NONE)
215 {
216 // ES3 spec: "If the GL is bound to a draw framebuffer object, the ith buffer listed in bufs
217 // must be COLOR_ATTACHMENTi or NONE"
218 ASSERT(mDrawBufferStates[drawBufferIdx] == GL_COLOR_ATTACHMENT0 + drawBufferIdx ||
219 (drawBufferIdx == 0 && mDrawBufferStates[drawBufferIdx] == GL_BACK));
220 return getAttachment(mDrawBufferStates[drawBufferIdx]);
221 }
222 else
223 {
224 return nullptr;
225 }
226}
227
228size_t FramebufferState::getDrawBufferCount() const
229{
230 return mDrawBufferStates.size();
231}
232
Geoff Langb21e20d2016-07-19 15:35:41 -0400233bool FramebufferState::colorAttachmentsAreUniqueImages() const
234{
235 for (size_t firstAttachmentIdx = 0; firstAttachmentIdx < mColorAttachments.size();
236 firstAttachmentIdx++)
237 {
238 const gl::FramebufferAttachment &firstAttachment = mColorAttachments[firstAttachmentIdx];
239 if (!firstAttachment.isAttached())
240 {
241 continue;
242 }
243
244 for (size_t secondAttachmentIdx = firstAttachmentIdx + 1;
245 secondAttachmentIdx < mColorAttachments.size(); secondAttachmentIdx++)
246 {
247 const gl::FramebufferAttachment &secondAttachment =
248 mColorAttachments[secondAttachmentIdx];
249 if (!secondAttachment.isAttached())
250 {
251 continue;
252 }
253
254 if (firstAttachment == secondAttachment)
255 {
256 return false;
257 }
258 }
259 }
260
261 return true;
262}
263
Jamie Madill7aea7e02016-05-10 10:39:45 -0400264Framebuffer::Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id)
Jamie Madill362876b2016-06-16 14:46:59 -0400265 : mState(caps),
266 mImpl(factory->createFramebuffer(mState)),
267 mId(id),
268 mCachedStatus(),
269 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
270 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000271{
Corentin Wallez37c39792015-08-20 14:19:46 -0400272 ASSERT(mId != 0);
273 ASSERT(mImpl != nullptr);
Jamie Madill362876b2016-06-16 14:46:59 -0400274 ASSERT(mState.mColorAttachments.size() == static_cast<size_t>(caps.maxColorAttachments));
275
276 for (size_t colorIndex = 0; colorIndex < mState.mColorAttachments.size(); ++colorIndex)
277 {
278 mDirtyColorAttachmentBindings.push_back(ChannelBinding(
279 this, static_cast<SignalToken>(DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex)));
280 }
Corentin Wallez37c39792015-08-20 14:19:46 -0400281}
282
283Framebuffer::Framebuffer(rx::SurfaceImpl *surface)
Jamie Madill362876b2016-06-16 14:46:59 -0400284 : mState(),
285 mImpl(surface->createDefaultFramebuffer(mState)),
286 mId(0),
287 mCachedStatus(GL_FRAMEBUFFER_COMPLETE),
288 mDirtyDepthAttachmentBinding(this, DIRTY_BIT_DEPTH_ATTACHMENT),
289 mDirtyStencilAttachmentBinding(this, DIRTY_BIT_STENCIL_ATTACHMENT)
Corentin Wallez37c39792015-08-20 14:19:46 -0400290{
Geoff Langda88add2014-12-01 10:22:01 -0500291 ASSERT(mImpl != nullptr);
Jamie Madill362876b2016-06-16 14:46:59 -0400292 mDirtyColorAttachmentBindings.push_back(
293 ChannelBinding(this, static_cast<SignalToken>(DIRTY_BIT_COLOR_ATTACHMENT_0)));
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000294}
295
296Framebuffer::~Framebuffer()
297{
Geoff Langda88add2014-12-01 10:22:01 -0500298 SafeDelete(mImpl);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000299}
300
Geoff Lang70d0f492015-12-10 17:45:46 -0500301void Framebuffer::setLabel(const std::string &label)
302{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400303 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -0500304}
305
306const std::string &Framebuffer::getLabel() const
307{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400308 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -0500309}
310
Jamie Madille261b442014-06-25 12:42:21 -0400311void Framebuffer::detachTexture(GLuint textureId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000312{
Jamie Madilld1405e52015-03-05 15:41:39 -0500313 detachResourceById(GL_TEXTURE, textureId);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000314}
315
Jamie Madille261b442014-06-25 12:42:21 -0400316void Framebuffer::detachRenderbuffer(GLuint renderbufferId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000317{
Jamie Madilld1405e52015-03-05 15:41:39 -0500318 detachResourceById(GL_RENDERBUFFER, renderbufferId);
319}
Jamie Madille261b442014-06-25 12:42:21 -0400320
Jamie Madilld1405e52015-03-05 15:41:39 -0500321void Framebuffer::detachResourceById(GLenum resourceType, GLuint resourceId)
322{
Jamie Madill362876b2016-06-16 14:46:59 -0400323 for (size_t colorIndex = 0; colorIndex < mState.mColorAttachments.size(); ++colorIndex)
Jamie Madilld1405e52015-03-05 15:41:39 -0500324 {
Jamie Madill362876b2016-06-16 14:46:59 -0400325 detachMatchingAttachment(&mState.mColorAttachments[colorIndex], resourceType, resourceId,
326 DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000327 }
328
Jamie Madill362876b2016-06-16 14:46:59 -0400329 detachMatchingAttachment(&mState.mDepthAttachment, resourceType, resourceId,
330 DIRTY_BIT_DEPTH_ATTACHMENT);
331 detachMatchingAttachment(&mState.mStencilAttachment, resourceType, resourceId,
332 DIRTY_BIT_STENCIL_ATTACHMENT);
333}
334
335void Framebuffer::detachMatchingAttachment(FramebufferAttachment *attachment,
336 GLenum matchType,
337 GLuint matchId,
338 size_t dirtyBit)
339{
340 if (attachment->isAttached() && attachment->type() == matchType && attachment->id() == matchId)
341 {
342 attachment->detach();
343 mDirtyBits.set(dirtyBit);
344 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000345}
346
Corentin Wallez37c39792015-08-20 14:19:46 -0400347const FramebufferAttachment *Framebuffer::getColorbuffer(size_t colorAttachment) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000348{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400349 return mState.getColorAttachment(colorAttachment);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000350}
351
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400352const FramebufferAttachment *Framebuffer::getDepthbuffer() const
Geoff Lang646559f2013-08-15 11:08:15 -0400353{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400354 return mState.getDepthAttachment();
Geoff Lang646559f2013-08-15 11:08:15 -0400355}
356
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400357const FramebufferAttachment *Framebuffer::getStencilbuffer() const
358{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400359 return mState.getStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400360}
361
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400362const FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
363{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400364 return mState.getDepthStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400365}
366
367const FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000368{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400369 return mState.getDepthOrStencilAttachment();
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000370}
371
Corentin Wallezb1d0a2552016-12-19 16:15:54 -0500372const FramebufferAttachment *Framebuffer::getStencilOrDepthStencilAttachment() const
373{
374 return mState.getStencilOrDepthStencilAttachment();
375}
376
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400377const FramebufferAttachment *Framebuffer::getReadColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000378{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400379 return mState.getReadAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000380}
381
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000382GLenum Framebuffer::getReadColorbufferType() const
383{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400384 const FramebufferAttachment *readAttachment = mState.getReadAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400385 return (readAttachment != nullptr ? readAttachment->type() : GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000386}
387
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400388const FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000389{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400390 return mState.getFirstColorAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000391}
392
Jamie Madill2d06b732015-04-20 12:53:28 -0400393const FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000394{
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400395 return mState.getAttachment(attachment);
Geoff Lang55ba29c2013-07-11 16:57:53 -0400396}
397
Geoff Langa15472a2015-08-11 11:48:03 -0400398size_t Framebuffer::getDrawbufferStateCount() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000399{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400400 return mState.mDrawBufferStates.size();
Geoff Langa15472a2015-08-11 11:48:03 -0400401}
402
403GLenum Framebuffer::getDrawBufferState(size_t drawBuffer) const
404{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400405 ASSERT(drawBuffer < mState.mDrawBufferStates.size());
406 return mState.mDrawBufferStates[drawBuffer];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000407}
408
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500409const std::vector<GLenum> &Framebuffer::getDrawBufferStates() const
410{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400411 return mState.getDrawBufferStates();
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500412}
413
Geoff Lang164d54e2014-12-01 10:55:33 -0500414void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000415{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400416 auto &drawStates = mState.mDrawBufferStates;
Jamie Madilld1405e52015-03-05 15:41:39 -0500417
418 ASSERT(count <= drawStates.size());
419 std::copy(buffers, buffers + count, drawStates.begin());
420 std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500421 mDirtyBits.set(DIRTY_BIT_DRAW_BUFFERS);
Geoff Lang9dd95802014-12-01 11:12:59 -0500422}
423
Geoff Langa15472a2015-08-11 11:48:03 -0400424const FramebufferAttachment *Framebuffer::getDrawBuffer(size_t drawBuffer) const
425{
Geoff Lang4b7f12b2016-06-21 16:47:07 -0400426 return mState.getDrawBuffer(drawBuffer);
Geoff Langa15472a2015-08-11 11:48:03 -0400427}
428
429bool Framebuffer::hasEnabledDrawBuffer() const
430{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400431 for (size_t drawbufferIdx = 0; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
Geoff Langa15472a2015-08-11 11:48:03 -0400432 {
433 if (getDrawBuffer(drawbufferIdx) != nullptr)
434 {
435 return true;
436 }
437 }
438
439 return false;
440}
441
Geoff Lang9dd95802014-12-01 11:12:59 -0500442GLenum Framebuffer::getReadBufferState() const
443{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400444 return mState.mReadBufferState;
Geoff Lang9dd95802014-12-01 11:12:59 -0500445}
446
447void Framebuffer::setReadBuffer(GLenum buffer)
448{
Jamie Madillb885e572015-02-03 16:16:04 -0500449 ASSERT(buffer == GL_BACK || buffer == GL_NONE ||
450 (buffer >= GL_COLOR_ATTACHMENT0 &&
Jamie Madill48ef11b2016-04-27 15:21:52 -0400451 (buffer - GL_COLOR_ATTACHMENT0) < mState.mColorAttachments.size()));
452 mState.mReadBufferState = buffer;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500453 mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000454}
455
Corentin Wallez37c39792015-08-20 14:19:46 -0400456size_t Framebuffer::getNumColorBuffers() const
457{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400458 return mState.mColorAttachments.size();
Corentin Wallez37c39792015-08-20 14:19:46 -0400459}
460
Jamie Madill0df8fe42015-11-24 16:10:24 -0500461bool Framebuffer::hasDepth() const
462{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400463 return (mState.mDepthAttachment.isAttached() && mState.mDepthAttachment.getDepthSize() > 0);
Jamie Madill0df8fe42015-11-24 16:10:24 -0500464}
465
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000466bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000467{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400468 return (mState.mStencilAttachment.isAttached() &&
469 mState.mStencilAttachment.getStencilSize() > 0);
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000470}
471
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000472bool Framebuffer::usingExtendedDrawBuffers() const
473{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400474 for (size_t drawbufferIdx = 1; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000475 {
Geoff Langa15472a2015-08-11 11:48:03 -0400476 if (getDrawBuffer(drawbufferIdx) != nullptr)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000477 {
478 return true;
479 }
480 }
481
482 return false;
483}
484
Jamie Madill51f40ec2016-06-15 14:06:00 -0400485GLenum Framebuffer::checkStatus(const ContextState &state)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000486{
Geoff Lang528ce3c2014-12-01 10:44:07 -0500487 // The default framebuffer *must* always be complete, though it may not be
488 // subject to the same rules as application FBOs. ie, it could have 0x0 size.
489 if (mId == 0)
490 {
491 return GL_FRAMEBUFFER_COMPLETE;
492 }
493
Jamie Madill362876b2016-06-16 14:46:59 -0400494 if (hasAnyDirtyBit() || !mCachedStatus.valid())
495 {
496 mCachedStatus = checkStatusImpl(state);
497 }
498
499 return mCachedStatus.value();
500}
501
502GLenum Framebuffer::checkStatusImpl(const ContextState &state)
503{
504 ASSERT(mId != 0);
505
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000506 unsigned int colorbufferSize = 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000507 int samples = -1;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000508 bool missingAttachment = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000509
Jamie Madill48ef11b2016-04-27 15:21:52 -0400510 for (const FramebufferAttachment &colorAttachment : mState.mColorAttachments)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000511 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400512 if (colorAttachment.isAttached())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000513 {
Jamie Madill6b120b92015-11-24 13:00:07 -0500514 const Extents &size = colorAttachment.getSize();
515 if (size.width == 0 || size.height == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000516 {
517 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
518 }
daniel@transgaming.com01868132010-08-24 19:21:17 +0000519
Jamie Madilla3944d42016-07-22 22:13:26 -0400520 const Format &format = colorAttachment.getFormat();
521 const TextureCaps &formatCaps = state.getTextureCap(format.asSized());
Jamie Madill2d06b732015-04-20 12:53:28 -0400522 if (colorAttachment.type() == GL_TEXTURE)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000523 {
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400524 if (!formatCaps.renderable)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000525 {
Jamie Madill81176782015-11-24 16:10:23 -0500526 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000527 }
528
Jamie Madilla3944d42016-07-22 22:13:26 -0400529 if (format.info->depthBits > 0 || format.info->stencilBits > 0)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000530 {
531 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
532 }
Jamie Madill6b120b92015-11-24 13:00:07 -0500533
534 if (colorAttachment.layer() >= size.depth)
535 {
536 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
537 }
Jamie Madill3215b202015-12-15 16:41:39 -0500538
539 // ES3 specifies that cube map texture attachments must be cube complete.
540 // This language is missing from the ES2 spec, but we enforce it here because some
541 // desktop OpenGL drivers also enforce this validation.
542 // TODO(jmadill): Check if OpenGL ES2 drivers enforce cube completeness.
543 const Texture *texture = colorAttachment.getTexture();
544 ASSERT(texture);
Olli Etuahoe8528d82016-05-16 17:50:52 +0300545 if (texture->getTarget() == GL_TEXTURE_CUBE_MAP &&
546 !texture->getTextureState().isCubeComplete())
Jamie Madill3215b202015-12-15 16:41:39 -0500547 {
548 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
549 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000550 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400551 else if (colorAttachment.type() == GL_RENDERBUFFER)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000552 {
Jamie Madilla3944d42016-07-22 22:13:26 -0400553 if (!formatCaps.renderable || format.info->depthBits > 0 ||
554 format.info->stencilBits > 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400555 {
556 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
557 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000558 }
559
560 if (!missingAttachment)
561 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000562 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
563 // all color attachments have the same number of samples for the FBO to be complete.
Jamie Madill2d06b732015-04-20 12:53:28 -0400564 if (colorAttachment.getSamples() != samples)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000565 {
566 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
567 }
568
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000569 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
570 // in GLES 3.0, there is no such restriction
Martin Radev1be913c2016-07-11 17:59:16 +0300571 if (state.getClientMajorVersion() < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000572 {
Jamie Madilla3944d42016-07-22 22:13:26 -0400573 if (format.info->pixelBytes != colorbufferSize)
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000574 {
575 return GL_FRAMEBUFFER_UNSUPPORTED;
576 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000577 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000578 }
579 else
580 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400581 samples = colorAttachment.getSamples();
Jamie Madilla3944d42016-07-22 22:13:26 -0400582 colorbufferSize = format.info->pixelBytes;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000583 missingAttachment = false;
584 }
585 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000586 }
587
Jamie Madill48ef11b2016-04-27 15:21:52 -0400588 const FramebufferAttachment &depthAttachment = mState.mDepthAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -0400589 if (depthAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000590 {
Jamie Madill6b120b92015-11-24 13:00:07 -0500591 const Extents &size = depthAttachment.getSize();
592 if (size.width == 0 || size.height == 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000593 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000594 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000595 }
596
Jamie Madilla3944d42016-07-22 22:13:26 -0400597 const Format &format = depthAttachment.getFormat();
598 const TextureCaps &formatCaps = state.getTextureCap(format.asSized());
Jamie Madill2d06b732015-04-20 12:53:28 -0400599 if (depthAttachment.type() == GL_TEXTURE)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000600 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000601 // depth texture attachments require 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
Jamie Madilla3944d42016-07-22 22:13:26 -0400612 if (format.info->depthBits == 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 (depthAttachment.type() == GL_RENDERBUFFER)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000618 {
Jamie Madilla3944d42016-07-22 22:13:26 -0400619 if (!formatCaps.renderable || format.info->depthBits == 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 = depthAttachment.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 != depthAttachment.getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000631 {
Sami Väisänena797e062016-05-12 15:23:40 +0300632 // CHROMIUM_framebuffer_mixed_samples allows a framebuffer to be
633 // considered complete when its depth or stencil samples are a
634 // multiple of the number of color samples.
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700635 const bool mixedSamples = state.getExtensions().framebufferMixedSamples;
Sami Väisänena797e062016-05-12 15:23:40 +0300636 if (!mixedSamples)
637 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
638
639 const int colorSamples = samples ? samples : 1;
640 const int depthSamples = depthAttachment.getSamples();
641 if ((depthSamples % colorSamples) != 0)
642 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000643 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000644 }
645
Jamie Madill48ef11b2016-04-27 15:21:52 -0400646 const FramebufferAttachment &stencilAttachment = mState.mStencilAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -0400647 if (stencilAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000648 {
Jamie Madill6b120b92015-11-24 13:00:07 -0500649 const Extents &size = stencilAttachment.getSize();
650 if (size.width == 0 || size.height == 0)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000651 {
652 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
653 }
654
Jamie Madilla3944d42016-07-22 22:13:26 -0400655 const Format &format = stencilAttachment.getFormat();
656 const TextureCaps &formatCaps = state.getTextureCap(format.asSized());
Jamie Madill2d06b732015-04-20 12:53:28 -0400657 if (stencilAttachment.type() == GL_TEXTURE)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000658 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000659 // texture stencil attachments come along as part
660 // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700661 if (!state.getExtensions().depthTextures)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000662 {
663 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
664 }
665
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400666 if (!formatCaps.renderable)
Geoff Langcec35902014-04-16 10:52:36 -0400667 {
Jamie Madill81176782015-11-24 16:10:23 -0500668 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
Geoff Langcec35902014-04-16 10:52:36 -0400669 }
670
Jamie Madilla3944d42016-07-22 22:13:26 -0400671 if (format.info->stencilBits == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000672 {
673 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
674 }
675 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400676 else if (stencilAttachment.type() == GL_RENDERBUFFER)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000677 {
Jamie Madilla3944d42016-07-22 22:13:26 -0400678 if (!formatCaps.renderable || format.info->stencilBits == 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400679 {
680 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
681 }
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000682 }
683
684 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000685 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400686 samples = stencilAttachment.getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000687 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000688 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400689 else if (samples != stencilAttachment.getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000690 {
Sami Väisänena797e062016-05-12 15:23:40 +0300691 // see the comments in depth attachment check.
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700692 const bool mixedSamples = state.getExtensions().framebufferMixedSamples;
Sami Väisänena797e062016-05-12 15:23:40 +0300693 if (!mixedSamples)
694 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
695
696 const int colorSamples = samples ? samples : 1;
697 const int stencilSamples = stencilAttachment.getSamples();
698 if ((stencilSamples % colorSamples) != 0)
699 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000700 }
Corentin Wallez086d59a2016-04-29 09:06:49 -0400701
702 // Starting from ES 3.0 stencil and depth, if present, should be the same image
Martin Radev1be913c2016-07-11 17:59:16 +0300703 if (state.getClientMajorVersion() >= 3 && depthAttachment.isAttached() &&
Corentin Wallez086d59a2016-04-29 09:06:49 -0400704 stencilAttachment != depthAttachment)
705 {
706 return GL_FRAMEBUFFER_UNSUPPORTED;
707 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000708 }
709
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000710 // we need to have at least one attachment to be complete
711 if (missingAttachment)
712 {
713 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000714 }
715
Jamie Madillcc86d642015-11-24 13:00:07 -0500716 // In ES 2.0, all color attachments must have the same width and height.
717 // In ES 3.0, there is no such restriction.
Martin Radev1be913c2016-07-11 17:59:16 +0300718 if (state.getClientMajorVersion() < 3 && !mState.attachmentsHaveSameDimensions())
Jamie Madillcc86d642015-11-24 13:00:07 -0500719 {
720 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
721 }
722
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500723 syncState();
Jamie Madillcc86d642015-11-24 13:00:07 -0500724 if (!mImpl->checkStatus())
725 {
726 return GL_FRAMEBUFFER_UNSUPPORTED;
727 }
728
729 return GL_FRAMEBUFFER_COMPLETE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000730}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000731
Austin Kinross08332632015-05-05 13:35:47 -0700732Error Framebuffer::discard(size_t count, const GLenum *attachments)
733{
734 return mImpl->discard(count, attachments);
735}
736
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500737Error Framebuffer::invalidate(size_t count, const GLenum *attachments)
Jamie Madill2d96b9e2014-08-29 15:46:47 -0400738{
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500739 return mImpl->invalidate(count, attachments);
Jamie Madill2d96b9e2014-08-29 15:46:47 -0400740}
741
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500742Error Framebuffer::invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area)
Jamie Madill400a4412014-08-29 15:46:45 -0400743{
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500744 return mImpl->invalidateSub(count, attachments, area);
Jamie Madill400a4412014-08-29 15:46:45 -0400745}
746
Jamie Madill8415b5f2016-04-26 13:41:39 -0400747Error Framebuffer::clear(rx::ContextImpl *context, GLbitfield mask)
Geoff Langb04dc822014-12-01 12:02:02 -0500748{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700749 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500750 {
Jamie Madill362876b2016-06-16 14:46:59 -0400751 return gl::NoError();
Jamie Madill984ef412015-11-24 16:10:21 -0500752 }
753
Jamie Madill8415b5f2016-04-26 13:41:39 -0400754 return mImpl->clear(context, mask);
Geoff Langb04dc822014-12-01 12:02:02 -0500755}
756
Jamie Madill8415b5f2016-04-26 13:41:39 -0400757Error Framebuffer::clearBufferfv(rx::ContextImpl *context,
Jamie Madill1b94d432015-08-07 13:23:23 -0400758 GLenum buffer,
759 GLint drawbuffer,
760 const GLfloat *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500761{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700762 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500763 {
Jamie Madill362876b2016-06-16 14:46:59 -0400764 return gl::NoError();
Jamie Madill984ef412015-11-24 16:10:21 -0500765 }
766
Jamie Madill8415b5f2016-04-26 13:41:39 -0400767 return mImpl->clearBufferfv(context, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500768}
769
Jamie Madill8415b5f2016-04-26 13:41:39 -0400770Error Framebuffer::clearBufferuiv(rx::ContextImpl *context,
Jamie Madill1b94d432015-08-07 13:23:23 -0400771 GLenum buffer,
772 GLint drawbuffer,
773 const GLuint *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500774{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700775 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500776 {
Jamie Madill362876b2016-06-16 14:46:59 -0400777 return gl::NoError();
Jamie Madill984ef412015-11-24 16:10:21 -0500778 }
779
Jamie Madill8415b5f2016-04-26 13:41:39 -0400780 return mImpl->clearBufferuiv(context, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500781}
782
Jamie Madill8415b5f2016-04-26 13:41:39 -0400783Error Framebuffer::clearBufferiv(rx::ContextImpl *context,
Jamie Madill1b94d432015-08-07 13:23:23 -0400784 GLenum buffer,
785 GLint drawbuffer,
786 const GLint *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500787{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700788 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500789 {
Jamie Madill362876b2016-06-16 14:46:59 -0400790 return gl::NoError();
Jamie Madill984ef412015-11-24 16:10:21 -0500791 }
792
Jamie Madill8415b5f2016-04-26 13:41:39 -0400793 return mImpl->clearBufferiv(context, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500794}
795
Jamie Madill8415b5f2016-04-26 13:41:39 -0400796Error Framebuffer::clearBufferfi(rx::ContextImpl *context,
Jamie Madill1b94d432015-08-07 13:23:23 -0400797 GLenum buffer,
798 GLint drawbuffer,
799 GLfloat depth,
800 GLint stencil)
Geoff Langb04dc822014-12-01 12:02:02 -0500801{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700802 if (context->getGLState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500803 {
Jamie Madill362876b2016-06-16 14:46:59 -0400804 return gl::NoError();
Jamie Madill984ef412015-11-24 16:10:21 -0500805 }
806
Jamie Madill8415b5f2016-04-26 13:41:39 -0400807 return mImpl->clearBufferfi(context, buffer, drawbuffer, depth, stencil);
Geoff Langb04dc822014-12-01 12:02:02 -0500808}
809
Geoff Langbce529e2014-12-01 12:48:41 -0500810GLenum Framebuffer::getImplementationColorReadFormat() const
811{
812 return mImpl->getImplementationColorReadFormat();
813}
814
815GLenum Framebuffer::getImplementationColorReadType() const
816{
817 return mImpl->getImplementationColorReadType();
818}
819
Jamie Madill8415b5f2016-04-26 13:41:39 -0400820Error Framebuffer::readPixels(rx::ContextImpl *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500821 const Rectangle &area,
Jamie Madill1b94d432015-08-07 13:23:23 -0400822 GLenum format,
823 GLenum type,
824 GLvoid *pixels) const
Geoff Langbce529e2014-12-01 12:48:41 -0500825{
Jamie Madill362876b2016-06-16 14:46:59 -0400826 ANGLE_TRY(mImpl->readPixels(context, area, format, type, pixels));
Geoff Lang520c4ae2015-05-05 13:12:36 -0400827
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700828 Buffer *unpackBuffer = context->getGLState().getUnpackState().pixelBuffer.get();
Geoff Lang520c4ae2015-05-05 13:12:36 -0400829 if (unpackBuffer)
830 {
831 unpackBuffer->onPixelUnpack();
832 }
833
Jamie Madill362876b2016-06-16 14:46:59 -0400834 return NoError();
Geoff Langbce529e2014-12-01 12:48:41 -0500835}
836
Jamie Madill8415b5f2016-04-26 13:41:39 -0400837Error Framebuffer::blit(rx::ContextImpl *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500838 const Rectangle &sourceArea,
839 const Rectangle &destArea,
Geoff Lang242468f2015-09-24 14:15:41 -0400840 GLbitfield mask,
Jamie Madill8415b5f2016-04-26 13:41:39 -0400841 GLenum filter)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500842{
He Yunchao6be602d2016-12-22 14:33:07 +0800843 GLbitfield blitMask = mask;
844
845 // Note that blitting is called against draw framebuffer.
846 // See the code in gl::Context::blitFramebuffer.
847 if ((mask & GL_COLOR_BUFFER_BIT) && !hasEnabledDrawBuffer())
848 {
849 blitMask &= ~GL_COLOR_BUFFER_BIT;
850 }
851
852 if ((mask & GL_STENCIL_BUFFER_BIT) && mState.getStencilAttachment() == nullptr)
853 {
854 blitMask &= ~GL_STENCIL_BUFFER_BIT;
855 }
856
857 if ((mask & GL_DEPTH_BUFFER_BIT) && mState.getDepthAttachment() == nullptr)
858 {
859 blitMask &= ~GL_DEPTH_BUFFER_BIT;
860 }
861
862 if (!blitMask)
863 {
864 return NoError();
865 }
866
867 return mImpl->blit(context, sourceArea, destArea, blitMask, filter);
Geoff Lang54bd5a42014-12-01 12:51:04 -0500868}
869
Jamie Madill51f40ec2016-06-15 14:06:00 -0400870int Framebuffer::getSamples(const ContextState &state)
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000871{
Jamie Madill362876b2016-06-16 14:46:59 -0400872 if (complete(state))
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000873 {
Jamie Madill362876b2016-06-16 14:46:59 -0400874 // For a complete framebuffer, all attachments must have the same sample count.
875 // In this case return the first nonzero sample size.
876 const auto *firstColorAttachment = mState.getFirstColorAttachment();
877 if (firstColorAttachment)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000878 {
Jamie Madill362876b2016-06-16 14:46:59 -0400879 ASSERT(firstColorAttachment->isAttached());
880 return firstColorAttachment->getSamples();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000881 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000882 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000883
884 return 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000885}
886
Jamie Madille261b442014-06-25 12:42:21 -0400887bool Framebuffer::hasValidDepthStencil() const
888{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400889 return mState.getDepthStencilAttachment() != nullptr;
Jamie Madille261b442014-06-25 12:42:21 -0400890}
891
Jamie Madill2d06b732015-04-20 12:53:28 -0400892void Framebuffer::setAttachment(GLenum type,
893 GLenum binding,
894 const ImageIndex &textureIndex,
895 FramebufferAttachmentObject *resource)
Geoff Langab75a052014-10-15 12:56:37 -0400896{
Jamie Madill2d06b732015-04-20 12:53:28 -0400897 if (binding == GL_DEPTH_STENCIL || binding == GL_DEPTH_STENCIL_ATTACHMENT)
Geoff Langab75a052014-10-15 12:56:37 -0400898 {
Geoff Langab75a052014-10-15 12:56:37 -0400899 // ensure this is a legitimate depth+stencil format
Jamie Madill375c37c2015-07-21 15:14:08 -0400900 FramebufferAttachmentObject *attachmentObj = resource;
901 if (resource)
Geoff Langab75a052014-10-15 12:56:37 -0400902 {
Jamie Madill375c37c2015-07-21 15:14:08 -0400903 FramebufferAttachment::Target target(binding, textureIndex);
Jamie Madilla3944d42016-07-22 22:13:26 -0400904 const Format &format = resource->getAttachmentFormat(target);
905 if (format.info->depthBits == 0 || format.info->stencilBits == 0)
Jamie Madill375c37c2015-07-21 15:14:08 -0400906 {
907 // Attaching nullptr detaches the current attachment.
908 attachmentObj = nullptr;
909 }
Geoff Langab75a052014-10-15 12:56:37 -0400910 }
Jamie Madill375c37c2015-07-21 15:14:08 -0400911
Jamie Madill48ef11b2016-04-27 15:21:52 -0400912 mState.mDepthAttachment.attach(type, binding, textureIndex, attachmentObj);
913 mState.mStencilAttachment.attach(type, binding, textureIndex, attachmentObj);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500914 mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT);
915 mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT);
Jamie Madill362876b2016-06-16 14:46:59 -0400916 BindResourceChannel(&mDirtyDepthAttachmentBinding, resource);
917 BindResourceChannel(&mDirtyStencilAttachmentBinding, resource);
Geoff Langab75a052014-10-15 12:56:37 -0400918 }
919 else
920 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400921 switch (binding)
922 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500923 case GL_DEPTH:
924 case GL_DEPTH_ATTACHMENT:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400925 mState.mDepthAttachment.attach(type, binding, textureIndex, resource);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500926 mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT);
Jamie Madill362876b2016-06-16 14:46:59 -0400927 BindResourceChannel(&mDirtyDepthAttachmentBinding, resource);
928 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500929 case GL_STENCIL:
930 case GL_STENCIL_ATTACHMENT:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400931 mState.mStencilAttachment.attach(type, binding, textureIndex, resource);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500932 mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT);
Jamie Madill362876b2016-06-16 14:46:59 -0400933 BindResourceChannel(&mDirtyStencilAttachmentBinding, resource);
934 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500935 case GL_BACK:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400936 mState.mColorAttachments[0].attach(type, binding, textureIndex, resource);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500937 mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0);
Jamie Madill362876b2016-06-16 14:46:59 -0400938 // No need for a resource binding for the default FBO, it's always complete.
939 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500940 default:
Jamie Madill2d06b732015-04-20 12:53:28 -0400941 {
942 size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
Jamie Madill48ef11b2016-04-27 15:21:52 -0400943 ASSERT(colorIndex < mState.mColorAttachments.size());
944 mState.mColorAttachments[colorIndex].attach(type, binding, textureIndex, resource);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500945 mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
Jamie Madill362876b2016-06-16 14:46:59 -0400946 BindResourceChannel(&mDirtyColorAttachmentBindings[colorIndex], resource);
Jamie Madill2d06b732015-04-20 12:53:28 -0400947 }
948 break;
949 }
Geoff Langab75a052014-10-15 12:56:37 -0400950 }
951}
952
Jamie Madill2d06b732015-04-20 12:53:28 -0400953void Framebuffer::resetAttachment(GLenum binding)
954{
955 setAttachment(GL_NONE, binding, ImageIndex::MakeInvalid(), nullptr);
956}
957
Jamie Madill362876b2016-06-16 14:46:59 -0400958void Framebuffer::syncState()
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500959{
960 if (mDirtyBits.any())
961 {
962 mImpl->syncState(mDirtyBits);
963 mDirtyBits.reset();
Jamie Madill362876b2016-06-16 14:46:59 -0400964 mCachedStatus.reset();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500965 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000966}
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500967
Jamie Madill362876b2016-06-16 14:46:59 -0400968void Framebuffer::signal(SignalToken token)
Jamie Madill51f40ec2016-06-15 14:06:00 -0400969{
Jamie Madill362876b2016-06-16 14:46:59 -0400970 // TOOD(jmadill): Make this only update individual attachments to do less work.
971 mCachedStatus.reset();
Jamie Madill51f40ec2016-06-15 14:06:00 -0400972}
973
Jamie Madill362876b2016-06-16 14:46:59 -0400974bool Framebuffer::complete(const ContextState &state)
Jamie Madill51f40ec2016-06-15 14:06:00 -0400975{
Jamie Madill362876b2016-06-16 14:46:59 -0400976 return (checkStatus(state) == GL_FRAMEBUFFER_COMPLETE);
Jamie Madill51f40ec2016-06-15 14:06:00 -0400977}
978
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500979} // namespace gl