blob: 0c661add5eb5358630030ed022084e5587541a03 [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
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000027namespace gl
28{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000029
Jamie Madilld1405e52015-03-05 15:41:39 -050030namespace
31{
Jamie Madill2d06b732015-04-20 12:53:28 -040032void DetachMatchingAttachment(FramebufferAttachment *attachment, GLenum matchType, GLuint matchId)
Jamie Madilld1405e52015-03-05 15:41:39 -050033{
Jamie Madill2d06b732015-04-20 12:53:28 -040034 if (attachment->isAttached() &&
35 attachment->type() == matchType &&
36 attachment->id() == matchId)
Jamie Madilld1405e52015-03-05 15:41:39 -050037 {
Jamie Madill2d06b732015-04-20 12:53:28 -040038 attachment->detach();
Jamie Madilld1405e52015-03-05 15:41:39 -050039 }
40}
41}
42
Jamie Madill48ef11b2016-04-27 15:21:52 -040043FramebufferState::FramebufferState()
Geoff Lang70d0f492015-12-10 17:45:46 -050044 : mLabel(),
45 mColorAttachments(1),
Corentin Wallez37c39792015-08-20 14:19:46 -040046 mDrawBufferStates(1, GL_NONE),
47 mReadBufferState(GL_COLOR_ATTACHMENT0_EXT)
48{
49 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
50}
51
Jamie Madill48ef11b2016-04-27 15:21:52 -040052FramebufferState::FramebufferState(const Caps &caps)
Geoff Lang70d0f492015-12-10 17:45:46 -050053 : mLabel(),
54 mColorAttachments(caps.maxColorAttachments),
Jamie Madilld1405e52015-03-05 15:41:39 -050055 mDrawBufferStates(caps.maxDrawBuffers, GL_NONE),
56 mReadBufferState(GL_COLOR_ATTACHMENT0_EXT)
57{
Geoff Langa15472a2015-08-11 11:48:03 -040058 ASSERT(mDrawBufferStates.size() > 0);
Jamie Madilld1405e52015-03-05 15:41:39 -050059 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
60}
61
Jamie Madill48ef11b2016-04-27 15:21:52 -040062FramebufferState::~FramebufferState()
Jamie Madilld1405e52015-03-05 15:41:39 -050063{
Jamie Madilld1405e52015-03-05 15:41:39 -050064}
65
Jamie Madill48ef11b2016-04-27 15:21:52 -040066const std::string &FramebufferState::getLabel()
Geoff Lang70d0f492015-12-10 17:45:46 -050067{
68 return mLabel;
69}
70
Jamie Madill48ef11b2016-04-27 15:21:52 -040071const FramebufferAttachment *FramebufferState::getReadAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -050072{
73 ASSERT(mReadBufferState == GL_BACK || (mReadBufferState >= GL_COLOR_ATTACHMENT0 && mReadBufferState <= GL_COLOR_ATTACHMENT15));
74 size_t readIndex = (mReadBufferState == GL_BACK ? 0 : static_cast<size_t>(mReadBufferState - GL_COLOR_ATTACHMENT0));
75 ASSERT(readIndex < mColorAttachments.size());
Jamie Madill2d06b732015-04-20 12:53:28 -040076 return mColorAttachments[readIndex].isAttached() ? &mColorAttachments[readIndex] : nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -050077}
78
Jamie Madill48ef11b2016-04-27 15:21:52 -040079const FramebufferAttachment *FramebufferState::getFirstColorAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -050080{
Jamie Madill2d06b732015-04-20 12:53:28 -040081 for (const FramebufferAttachment &colorAttachment : mColorAttachments)
Jamie Madill7147f012015-03-05 15:41:40 -050082 {
Jamie Madill2d06b732015-04-20 12:53:28 -040083 if (colorAttachment.isAttached())
Jamie Madill7147f012015-03-05 15:41:40 -050084 {
Jamie Madill2d06b732015-04-20 12:53:28 -040085 return &colorAttachment;
Jamie Madill7147f012015-03-05 15:41:40 -050086 }
87 }
88
89 return nullptr;
90}
91
Jamie Madill48ef11b2016-04-27 15:21:52 -040092const FramebufferAttachment *FramebufferState::getDepthOrStencilAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -050093{
Jamie Madill2d06b732015-04-20 12:53:28 -040094 if (mDepthAttachment.isAttached())
95 {
96 return &mDepthAttachment;
97 }
98 if (mStencilAttachment.isAttached())
99 {
100 return &mStencilAttachment;
101 }
102 return nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500103}
104
Jamie Madill48ef11b2016-04-27 15:21:52 -0400105const FramebufferAttachment *FramebufferState::getColorAttachment(size_t colorAttachment) const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400106{
107 ASSERT(colorAttachment < mColorAttachments.size());
Jamie Madill2d06b732015-04-20 12:53:28 -0400108 return mColorAttachments[colorAttachment].isAttached() ?
109 &mColorAttachments[colorAttachment] :
110 nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400111}
112
Jamie Madill48ef11b2016-04-27 15:21:52 -0400113const FramebufferAttachment *FramebufferState::getDepthAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400114{
Jamie Madill2d06b732015-04-20 12:53:28 -0400115 return mDepthAttachment.isAttached() ? &mDepthAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400116}
117
Jamie Madill48ef11b2016-04-27 15:21:52 -0400118const FramebufferAttachment *FramebufferState::getStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400119{
Jamie Madill2d06b732015-04-20 12:53:28 -0400120 return mStencilAttachment.isAttached() ? &mStencilAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400121}
122
Jamie Madill48ef11b2016-04-27 15:21:52 -0400123const FramebufferAttachment *FramebufferState::getDepthStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400124{
125 // A valid depth-stencil attachment has the same resource bound to both the
126 // depth and stencil attachment points.
Jamie Madill2d06b732015-04-20 12:53:28 -0400127 if (mDepthAttachment.isAttached() && mStencilAttachment.isAttached() &&
128 mDepthAttachment.type() == mStencilAttachment.type() &&
129 mDepthAttachment.id() == mStencilAttachment.id())
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400130 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400131 return &mDepthAttachment;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400132 }
133
134 return nullptr;
135}
136
Jamie Madill48ef11b2016-04-27 15:21:52 -0400137bool FramebufferState::attachmentsHaveSameDimensions() const
Jamie Madillcc86d642015-11-24 13:00:07 -0500138{
139 Optional<Extents> attachmentSize;
140
141 auto hasMismatchedSize = [&attachmentSize](const FramebufferAttachment &attachment)
142 {
143 if (!attachment.isAttached())
144 {
145 return false;
146 }
147
148 if (!attachmentSize.valid())
149 {
150 attachmentSize = attachment.getSize();
151 return false;
152 }
153
154 return (attachment.getSize() != attachmentSize.value());
155 };
156
157 for (const auto &attachment : mColorAttachments)
158 {
159 if (hasMismatchedSize(attachment))
160 {
161 return false;
162 }
163 }
164
165 if (hasMismatchedSize(mDepthAttachment))
166 {
167 return false;
168 }
169
170 return !hasMismatchedSize(mStencilAttachment);
171}
172
Jamie Madill7aea7e02016-05-10 10:39:45 -0400173Framebuffer::Framebuffer(const Caps &caps, rx::GLImplFactory *factory, GLuint id)
Jamie Madill48ef11b2016-04-27 15:21:52 -0400174 : mState(caps), mImpl(factory->createFramebuffer(mState)), mId(id)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000175{
Corentin Wallez37c39792015-08-20 14:19:46 -0400176 ASSERT(mId != 0);
177 ASSERT(mImpl != nullptr);
178}
179
180Framebuffer::Framebuffer(rx::SurfaceImpl *surface)
Jamie Madill48ef11b2016-04-27 15:21:52 -0400181 : mState(), mImpl(surface->createDefaultFramebuffer(mState)), mId(0)
Corentin Wallez37c39792015-08-20 14:19:46 -0400182{
Geoff Langda88add2014-12-01 10:22:01 -0500183 ASSERT(mImpl != nullptr);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000184}
185
186Framebuffer::~Framebuffer()
187{
Geoff Langda88add2014-12-01 10:22:01 -0500188 SafeDelete(mImpl);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000189}
190
Geoff Lang70d0f492015-12-10 17:45:46 -0500191void Framebuffer::setLabel(const std::string &label)
192{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400193 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -0500194}
195
196const std::string &Framebuffer::getLabel() const
197{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400198 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -0500199}
200
Jamie Madille261b442014-06-25 12:42:21 -0400201void Framebuffer::detachTexture(GLuint textureId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000202{
Jamie Madilld1405e52015-03-05 15:41:39 -0500203 detachResourceById(GL_TEXTURE, textureId);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000204}
205
Jamie Madille261b442014-06-25 12:42:21 -0400206void Framebuffer::detachRenderbuffer(GLuint renderbufferId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000207{
Jamie Madilld1405e52015-03-05 15:41:39 -0500208 detachResourceById(GL_RENDERBUFFER, renderbufferId);
209}
Jamie Madille261b442014-06-25 12:42:21 -0400210
Jamie Madilld1405e52015-03-05 15:41:39 -0500211void Framebuffer::detachResourceById(GLenum resourceType, GLuint resourceId)
212{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400213 for (auto &colorAttachment : mState.mColorAttachments)
Jamie Madilld1405e52015-03-05 15:41:39 -0500214 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400215 DetachMatchingAttachment(&colorAttachment, resourceType, resourceId);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000216 }
217
Jamie Madill48ef11b2016-04-27 15:21:52 -0400218 DetachMatchingAttachment(&mState.mDepthAttachment, resourceType, resourceId);
219 DetachMatchingAttachment(&mState.mStencilAttachment, resourceType, resourceId);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000220}
221
Corentin Wallez37c39792015-08-20 14:19:46 -0400222const FramebufferAttachment *Framebuffer::getColorbuffer(size_t colorAttachment) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000223{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400224 return mState.getColorAttachment(colorAttachment);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000225}
226
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400227const FramebufferAttachment *Framebuffer::getDepthbuffer() const
Geoff Lang646559f2013-08-15 11:08:15 -0400228{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400229 return mState.getDepthAttachment();
Geoff Lang646559f2013-08-15 11:08:15 -0400230}
231
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400232const FramebufferAttachment *Framebuffer::getStencilbuffer() const
233{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400234 return mState.getStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400235}
236
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400237const FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
238{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400239 return mState.getDepthStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400240}
241
242const FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000243{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400244 return mState.getDepthOrStencilAttachment();
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000245}
246
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400247const FramebufferAttachment *Framebuffer::getReadColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000248{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400249 return mState.getReadAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000250}
251
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000252GLenum Framebuffer::getReadColorbufferType() const
253{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400254 const FramebufferAttachment *readAttachment = mState.getReadAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400255 return (readAttachment != nullptr ? readAttachment->type() : GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000256}
257
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400258const FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000259{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400260 return mState.getFirstColorAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000261}
262
Jamie Madill2d06b732015-04-20 12:53:28 -0400263const FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000264{
Jamie Madille92a3542014-07-03 10:38:58 -0400265 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
266 {
Jamie Madill48ef11b2016-04-27 15:21:52 -0400267 return mState.getColorAttachment(attachment - GL_COLOR_ATTACHMENT0);
Jamie Madille92a3542014-07-03 10:38:58 -0400268 }
269 else
270 {
271 switch (attachment)
272 {
Geoff Lang528ce3c2014-12-01 10:44:07 -0500273 case GL_COLOR:
274 case GL_BACK:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400275 return mState.getColorAttachment(0);
Geoff Lang528ce3c2014-12-01 10:44:07 -0500276 case GL_DEPTH:
Jamie Madille92a3542014-07-03 10:38:58 -0400277 case GL_DEPTH_ATTACHMENT:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400278 return mState.getDepthAttachment();
Geoff Lang528ce3c2014-12-01 10:44:07 -0500279 case GL_STENCIL:
Jamie Madille92a3542014-07-03 10:38:58 -0400280 case GL_STENCIL_ATTACHMENT:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400281 return mState.getStencilAttachment();
Geoff Lang528ce3c2014-12-01 10:44:07 -0500282 case GL_DEPTH_STENCIL:
Jamie Madille92a3542014-07-03 10:38:58 -0400283 case GL_DEPTH_STENCIL_ATTACHMENT:
284 return getDepthStencilBuffer();
285 default:
286 UNREACHABLE();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400287 return nullptr;
Jamie Madille92a3542014-07-03 10:38:58 -0400288 }
289 }
Geoff Lang55ba29c2013-07-11 16:57:53 -0400290}
291
Geoff Langa15472a2015-08-11 11:48:03 -0400292size_t Framebuffer::getDrawbufferStateCount() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000293{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400294 return mState.mDrawBufferStates.size();
Geoff Langa15472a2015-08-11 11:48:03 -0400295}
296
297GLenum Framebuffer::getDrawBufferState(size_t drawBuffer) const
298{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400299 ASSERT(drawBuffer < mState.mDrawBufferStates.size());
300 return mState.mDrawBufferStates[drawBuffer];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000301}
302
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500303const std::vector<GLenum> &Framebuffer::getDrawBufferStates() const
304{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400305 return mState.getDrawBufferStates();
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500306}
307
Geoff Lang164d54e2014-12-01 10:55:33 -0500308void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000309{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400310 auto &drawStates = mState.mDrawBufferStates;
Jamie Madilld1405e52015-03-05 15:41:39 -0500311
312 ASSERT(count <= drawStates.size());
313 std::copy(buffers, buffers + count, drawStates.begin());
314 std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500315 mDirtyBits.set(DIRTY_BIT_DRAW_BUFFERS);
Geoff Lang9dd95802014-12-01 11:12:59 -0500316}
317
Geoff Langa15472a2015-08-11 11:48:03 -0400318const FramebufferAttachment *Framebuffer::getDrawBuffer(size_t drawBuffer) const
319{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400320 ASSERT(drawBuffer < mState.mDrawBufferStates.size());
321 if (mState.mDrawBufferStates[drawBuffer] != GL_NONE)
Geoff Langa15472a2015-08-11 11:48:03 -0400322 {
323 // ES3 spec: "If the GL is bound to a draw framebuffer object, the ith buffer listed in bufs
324 // must be COLOR_ATTACHMENTi or NONE"
Jamie Madill48ef11b2016-04-27 15:21:52 -0400325 ASSERT(mState.mDrawBufferStates[drawBuffer] == GL_COLOR_ATTACHMENT0 + drawBuffer ||
326 (drawBuffer == 0 && mState.mDrawBufferStates[drawBuffer] == GL_BACK));
327 return getAttachment(mState.mDrawBufferStates[drawBuffer]);
Geoff Langa15472a2015-08-11 11:48:03 -0400328 }
329 else
330 {
331 return nullptr;
332 }
333}
334
335bool Framebuffer::hasEnabledDrawBuffer() const
336{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400337 for (size_t drawbufferIdx = 0; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
Geoff Langa15472a2015-08-11 11:48:03 -0400338 {
339 if (getDrawBuffer(drawbufferIdx) != nullptr)
340 {
341 return true;
342 }
343 }
344
345 return false;
346}
347
Geoff Lang9dd95802014-12-01 11:12:59 -0500348GLenum Framebuffer::getReadBufferState() const
349{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400350 return mState.mReadBufferState;
Geoff Lang9dd95802014-12-01 11:12:59 -0500351}
352
353void Framebuffer::setReadBuffer(GLenum buffer)
354{
Jamie Madillb885e572015-02-03 16:16:04 -0500355 ASSERT(buffer == GL_BACK || buffer == GL_NONE ||
356 (buffer >= GL_COLOR_ATTACHMENT0 &&
Jamie Madill48ef11b2016-04-27 15:21:52 -0400357 (buffer - GL_COLOR_ATTACHMENT0) < mState.mColorAttachments.size()));
358 mState.mReadBufferState = buffer;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500359 mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000360}
361
Corentin Wallez37c39792015-08-20 14:19:46 -0400362size_t Framebuffer::getNumColorBuffers() const
363{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400364 return mState.mColorAttachments.size();
Corentin Wallez37c39792015-08-20 14:19:46 -0400365}
366
Jamie Madill0df8fe42015-11-24 16:10:24 -0500367bool Framebuffer::hasDepth() const
368{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400369 return (mState.mDepthAttachment.isAttached() && mState.mDepthAttachment.getDepthSize() > 0);
Jamie Madill0df8fe42015-11-24 16:10:24 -0500370}
371
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000372bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000373{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400374 return (mState.mStencilAttachment.isAttached() &&
375 mState.mStencilAttachment.getStencilSize() > 0);
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000376}
377
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000378bool Framebuffer::usingExtendedDrawBuffers() const
379{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400380 for (size_t drawbufferIdx = 1; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000381 {
Geoff Langa15472a2015-08-11 11:48:03 -0400382 if (getDrawBuffer(drawbufferIdx) != nullptr)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000383 {
384 return true;
385 }
386 }
387
388 return false;
389}
390
Jamie Madill9082b982016-04-27 15:21:51 -0400391GLenum Framebuffer::checkStatus(const ContextState &data) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000392{
Geoff Lang528ce3c2014-12-01 10:44:07 -0500393 // The default framebuffer *must* always be complete, though it may not be
394 // subject to the same rules as application FBOs. ie, it could have 0x0 size.
395 if (mId == 0)
396 {
397 return GL_FRAMEBUFFER_COMPLETE;
398 }
399
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000400 unsigned int colorbufferSize = 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000401 int samples = -1;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000402 bool missingAttachment = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000403
Jamie Madill48ef11b2016-04-27 15:21:52 -0400404 for (const FramebufferAttachment &colorAttachment : mState.mColorAttachments)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000405 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400406 if (colorAttachment.isAttached())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000407 {
Jamie Madill6b120b92015-11-24 13:00:07 -0500408 const Extents &size = colorAttachment.getSize();
409 if (size.width == 0 || size.height == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000410 {
411 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
412 }
daniel@transgaming.com01868132010-08-24 19:21:17 +0000413
Jamie Madill2d06b732015-04-20 12:53:28 -0400414 GLenum internalformat = colorAttachment.getInternalFormat();
Jamie Madill48faf802014-11-06 15:27:22 -0500415 const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400416 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill2d06b732015-04-20 12:53:28 -0400417 if (colorAttachment.type() == GL_TEXTURE)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000418 {
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400419 if (!formatCaps.renderable)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000420 {
Jamie Madill81176782015-11-24 16:10:23 -0500421 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000422 }
423
Geoff Lang5d601382014-07-22 15:14:06 -0400424 if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000425 {
426 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
427 }
Jamie Madill6b120b92015-11-24 13:00:07 -0500428
429 if (colorAttachment.layer() >= size.depth)
430 {
431 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
432 }
Jamie Madill3215b202015-12-15 16:41:39 -0500433
434 // ES3 specifies that cube map texture attachments must be cube complete.
435 // This language is missing from the ES2 spec, but we enforce it here because some
436 // desktop OpenGL drivers also enforce this validation.
437 // TODO(jmadill): Check if OpenGL ES2 drivers enforce cube completeness.
438 const Texture *texture = colorAttachment.getTexture();
439 ASSERT(texture);
Olli Etuahoe8528d82016-05-16 17:50:52 +0300440 if (texture->getTarget() == GL_TEXTURE_CUBE_MAP &&
441 !texture->getTextureState().isCubeComplete())
Jamie Madill3215b202015-12-15 16:41:39 -0500442 {
443 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
444 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000445 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400446 else if (colorAttachment.type() == GL_RENDERBUFFER)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000447 {
Geoff Lang5d601382014-07-22 15:14:06 -0400448 if (!formatCaps.renderable || formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400449 {
450 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
451 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000452 }
453
454 if (!missingAttachment)
455 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000456 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
457 // all color attachments have the same number of samples for the FBO to be complete.
Jamie Madill2d06b732015-04-20 12:53:28 -0400458 if (colorAttachment.getSamples() != samples)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000459 {
460 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
461 }
462
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000463 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
464 // in GLES 3.0, there is no such restriction
Jamie Madill48faf802014-11-06 15:27:22 -0500465 if (data.clientVersion < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000466 {
Geoff Lang5d601382014-07-22 15:14:06 -0400467 if (formatInfo.pixelBytes != colorbufferSize)
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000468 {
469 return GL_FRAMEBUFFER_UNSUPPORTED;
470 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000471 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000472 }
473 else
474 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400475 samples = colorAttachment.getSamples();
Geoff Lang5d601382014-07-22 15:14:06 -0400476 colorbufferSize = formatInfo.pixelBytes;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000477 missingAttachment = false;
478 }
479 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000480 }
481
Jamie Madill48ef11b2016-04-27 15:21:52 -0400482 const FramebufferAttachment &depthAttachment = mState.mDepthAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -0400483 if (depthAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000484 {
Jamie Madill6b120b92015-11-24 13:00:07 -0500485 const Extents &size = depthAttachment.getSize();
486 if (size.width == 0 || size.height == 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000487 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000488 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000489 }
490
Jamie Madill2d06b732015-04-20 12:53:28 -0400491 GLenum internalformat = depthAttachment.getInternalFormat();
Jamie Madill48faf802014-11-06 15:27:22 -0500492 const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400493 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill2d06b732015-04-20 12:53:28 -0400494 if (depthAttachment.type() == GL_TEXTURE)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000495 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000496 // depth texture attachments require OES/ANGLE_depth_texture
Jamie Madill48faf802014-11-06 15:27:22 -0500497 if (!data.extensions->depthTextures)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000498 {
499 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
500 }
501
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400502 if (!formatCaps.renderable)
Geoff Langcec35902014-04-16 10:52:36 -0400503 {
Jamie Madill81176782015-11-24 16:10:23 -0500504 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
Geoff Langcec35902014-04-16 10:52:36 -0400505 }
506
Geoff Lang5d601382014-07-22 15:14:06 -0400507 if (formatInfo.depthBits == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000508 {
509 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
510 }
511 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400512 else if (depthAttachment.type() == GL_RENDERBUFFER)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000513 {
Geoff Lang5d601382014-07-22 15:14:06 -0400514 if (!formatCaps.renderable || formatInfo.depthBits == 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400515 {
516 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
517 }
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000518 }
519
520 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000521 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400522 samples = depthAttachment.getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000523 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000524 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400525 else if (samples != depthAttachment.getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000526 {
Sami Väisänena797e062016-05-12 15:23:40 +0300527 // CHROMIUM_framebuffer_mixed_samples allows a framebuffer to be
528 // considered complete when its depth or stencil samples are a
529 // multiple of the number of color samples.
530 const bool mixedSamples = data.extensions->framebufferMixedSamples;
531 if (!mixedSamples)
532 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
533
534 const int colorSamples = samples ? samples : 1;
535 const int depthSamples = depthAttachment.getSamples();
536 if ((depthSamples % colorSamples) != 0)
537 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000538 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000539 }
540
Jamie Madill48ef11b2016-04-27 15:21:52 -0400541 const FramebufferAttachment &stencilAttachment = mState.mStencilAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -0400542 if (stencilAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000543 {
Jamie Madill6b120b92015-11-24 13:00:07 -0500544 const Extents &size = stencilAttachment.getSize();
545 if (size.width == 0 || size.height == 0)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000546 {
547 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
548 }
549
Jamie Madill2d06b732015-04-20 12:53:28 -0400550 GLenum internalformat = stencilAttachment.getInternalFormat();
Jamie Madill48faf802014-11-06 15:27:22 -0500551 const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400552 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill2d06b732015-04-20 12:53:28 -0400553 if (stencilAttachment.type() == GL_TEXTURE)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000554 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000555 // texture stencil attachments come along as part
556 // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
Jamie Madill48faf802014-11-06 15:27:22 -0500557 if (!data.extensions->depthTextures)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000558 {
559 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
560 }
561
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400562 if (!formatCaps.renderable)
Geoff Langcec35902014-04-16 10:52:36 -0400563 {
Jamie Madill81176782015-11-24 16:10:23 -0500564 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
Geoff Langcec35902014-04-16 10:52:36 -0400565 }
566
Geoff Lang5d601382014-07-22 15:14:06 -0400567 if (formatInfo.stencilBits == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000568 {
569 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
570 }
571 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400572 else if (stencilAttachment.type() == GL_RENDERBUFFER)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000573 {
Geoff Lang5d601382014-07-22 15:14:06 -0400574 if (!formatCaps.renderable || formatInfo.stencilBits == 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400575 {
576 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
577 }
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000578 }
579
580 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000581 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400582 samples = stencilAttachment.getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000583 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000584 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400585 else if (samples != stencilAttachment.getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000586 {
Sami Väisänena797e062016-05-12 15:23:40 +0300587 // see the comments in depth attachment check.
588 const bool mixedSamples = data.extensions->framebufferMixedSamples;
589 if (!mixedSamples)
590 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
591
592 const int colorSamples = samples ? samples : 1;
593 const int stencilSamples = stencilAttachment.getSamples();
594 if ((stencilSamples % colorSamples) != 0)
595 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000596 }
Corentin Wallez086d59a2016-04-29 09:06:49 -0400597
598 // Starting from ES 3.0 stencil and depth, if present, should be the same image
599 if (data.clientVersion >= 3 && depthAttachment.isAttached() &&
600 stencilAttachment != depthAttachment)
601 {
602 return GL_FRAMEBUFFER_UNSUPPORTED;
603 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000604 }
605
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000606 // we need to have at least one attachment to be complete
607 if (missingAttachment)
608 {
609 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000610 }
611
Jamie Madillcc86d642015-11-24 13:00:07 -0500612 // In ES 2.0, all color attachments must have the same width and height.
613 // In ES 3.0, there is no such restriction.
Jamie Madill48ef11b2016-04-27 15:21:52 -0400614 if (data.clientVersion < 3 && !mState.attachmentsHaveSameDimensions())
Jamie Madillcc86d642015-11-24 13:00:07 -0500615 {
616 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
617 }
618
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500619 syncState();
Jamie Madillcc86d642015-11-24 13:00:07 -0500620 if (!mImpl->checkStatus())
621 {
622 return GL_FRAMEBUFFER_UNSUPPORTED;
623 }
624
625 return GL_FRAMEBUFFER_COMPLETE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000626}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000627
Austin Kinross08332632015-05-05 13:35:47 -0700628Error Framebuffer::discard(size_t count, const GLenum *attachments)
629{
630 return mImpl->discard(count, attachments);
631}
632
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500633Error Framebuffer::invalidate(size_t count, const GLenum *attachments)
Jamie Madill2d96b9e2014-08-29 15:46:47 -0400634{
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500635 return mImpl->invalidate(count, attachments);
Jamie Madill2d96b9e2014-08-29 15:46:47 -0400636}
637
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500638Error Framebuffer::invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area)
Jamie Madill400a4412014-08-29 15:46:45 -0400639{
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500640 return mImpl->invalidateSub(count, attachments, area);
Jamie Madill400a4412014-08-29 15:46:45 -0400641}
642
Jamie Madill8415b5f2016-04-26 13:41:39 -0400643Error Framebuffer::clear(rx::ContextImpl *context, GLbitfield mask)
Geoff Langb04dc822014-12-01 12:02:02 -0500644{
Jamie Madill8415b5f2016-04-26 13:41:39 -0400645 if (context->getState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500646 {
647 return gl::Error(GL_NO_ERROR);
648 }
649
Jamie Madill8415b5f2016-04-26 13:41:39 -0400650 return mImpl->clear(context, mask);
Geoff Langb04dc822014-12-01 12:02:02 -0500651}
652
Jamie Madill8415b5f2016-04-26 13:41:39 -0400653Error Framebuffer::clearBufferfv(rx::ContextImpl *context,
Jamie Madill1b94d432015-08-07 13:23:23 -0400654 GLenum buffer,
655 GLint drawbuffer,
656 const GLfloat *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500657{
Jamie Madill8415b5f2016-04-26 13:41:39 -0400658 if (context->getState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500659 {
660 return gl::Error(GL_NO_ERROR);
661 }
662
Jamie Madill8415b5f2016-04-26 13:41:39 -0400663 return mImpl->clearBufferfv(context, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500664}
665
Jamie Madill8415b5f2016-04-26 13:41:39 -0400666Error Framebuffer::clearBufferuiv(rx::ContextImpl *context,
Jamie Madill1b94d432015-08-07 13:23:23 -0400667 GLenum buffer,
668 GLint drawbuffer,
669 const GLuint *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500670{
Jamie Madill8415b5f2016-04-26 13:41:39 -0400671 if (context->getState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500672 {
673 return gl::Error(GL_NO_ERROR);
674 }
675
Jamie Madill8415b5f2016-04-26 13:41:39 -0400676 return mImpl->clearBufferuiv(context, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500677}
678
Jamie Madill8415b5f2016-04-26 13:41:39 -0400679Error Framebuffer::clearBufferiv(rx::ContextImpl *context,
Jamie Madill1b94d432015-08-07 13:23:23 -0400680 GLenum buffer,
681 GLint drawbuffer,
682 const GLint *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500683{
Jamie Madill8415b5f2016-04-26 13:41:39 -0400684 if (context->getState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500685 {
686 return gl::Error(GL_NO_ERROR);
687 }
688
Jamie Madill8415b5f2016-04-26 13:41:39 -0400689 return mImpl->clearBufferiv(context, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500690}
691
Jamie Madill8415b5f2016-04-26 13:41:39 -0400692Error Framebuffer::clearBufferfi(rx::ContextImpl *context,
Jamie Madill1b94d432015-08-07 13:23:23 -0400693 GLenum buffer,
694 GLint drawbuffer,
695 GLfloat depth,
696 GLint stencil)
Geoff Langb04dc822014-12-01 12:02:02 -0500697{
Jamie Madill8415b5f2016-04-26 13:41:39 -0400698 if (context->getState().isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500699 {
700 return gl::Error(GL_NO_ERROR);
701 }
702
Jamie Madill8415b5f2016-04-26 13:41:39 -0400703 return mImpl->clearBufferfi(context, buffer, drawbuffer, depth, stencil);
Geoff Langb04dc822014-12-01 12:02:02 -0500704}
705
Geoff Langbce529e2014-12-01 12:48:41 -0500706GLenum Framebuffer::getImplementationColorReadFormat() const
707{
708 return mImpl->getImplementationColorReadFormat();
709}
710
711GLenum Framebuffer::getImplementationColorReadType() const
712{
713 return mImpl->getImplementationColorReadType();
714}
715
Jamie Madill8415b5f2016-04-26 13:41:39 -0400716Error Framebuffer::readPixels(rx::ContextImpl *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500717 const Rectangle &area,
Jamie Madill1b94d432015-08-07 13:23:23 -0400718 GLenum format,
719 GLenum type,
720 GLvoid *pixels) const
Geoff Langbce529e2014-12-01 12:48:41 -0500721{
Jamie Madill8415b5f2016-04-26 13:41:39 -0400722 Error error = mImpl->readPixels(context, area, format, type, pixels);
Geoff Lang520c4ae2015-05-05 13:12:36 -0400723 if (error.isError())
724 {
725 return error;
726 }
727
Jamie Madill8415b5f2016-04-26 13:41:39 -0400728 Buffer *unpackBuffer = context->getState().getUnpackState().pixelBuffer.get();
Geoff Lang520c4ae2015-05-05 13:12:36 -0400729 if (unpackBuffer)
730 {
731 unpackBuffer->onPixelUnpack();
732 }
733
734 return Error(GL_NO_ERROR);
Geoff Langbce529e2014-12-01 12:48:41 -0500735}
736
Jamie Madill8415b5f2016-04-26 13:41:39 -0400737Error Framebuffer::blit(rx::ContextImpl *context,
Jamie Madillc29968b2016-01-20 11:17:23 -0500738 const Rectangle &sourceArea,
739 const Rectangle &destArea,
Geoff Lang242468f2015-09-24 14:15:41 -0400740 GLbitfield mask,
Jamie Madill8415b5f2016-04-26 13:41:39 -0400741 GLenum filter)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500742{
Jamie Madill8415b5f2016-04-26 13:41:39 -0400743 return mImpl->blit(context, sourceArea, destArea, mask, filter);
Geoff Lang54bd5a42014-12-01 12:51:04 -0500744}
745
Jamie Madill9082b982016-04-27 15:21:51 -0400746int Framebuffer::getSamples(const ContextState &data) const
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000747{
Geoff Lang748f74e2014-12-01 11:25:34 -0500748 if (checkStatus(data) == GL_FRAMEBUFFER_COMPLETE)
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000749 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000750 // for a complete framebuffer, all attachments must have the same sample count
751 // in this case return the first nonzero sample size
Jamie Madill48ef11b2016-04-27 15:21:52 -0400752 for (const FramebufferAttachment &colorAttachment : mState.mColorAttachments)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000753 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400754 if (colorAttachment.isAttached())
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000755 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400756 return colorAttachment.getSamples();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000757 }
758 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000759 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000760
761 return 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000762}
763
Jamie Madille261b442014-06-25 12:42:21 -0400764bool Framebuffer::hasValidDepthStencil() const
765{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400766 return mState.getDepthStencilAttachment() != nullptr;
Jamie Madille261b442014-06-25 12:42:21 -0400767}
768
Jamie Madill2d06b732015-04-20 12:53:28 -0400769void Framebuffer::setAttachment(GLenum type,
770 GLenum binding,
771 const ImageIndex &textureIndex,
772 FramebufferAttachmentObject *resource)
Geoff Langab75a052014-10-15 12:56:37 -0400773{
Jamie Madill2d06b732015-04-20 12:53:28 -0400774 if (binding == GL_DEPTH_STENCIL || binding == GL_DEPTH_STENCIL_ATTACHMENT)
Geoff Langab75a052014-10-15 12:56:37 -0400775 {
Geoff Langab75a052014-10-15 12:56:37 -0400776 // ensure this is a legitimate depth+stencil format
Jamie Madill375c37c2015-07-21 15:14:08 -0400777 FramebufferAttachmentObject *attachmentObj = resource;
778 if (resource)
Geoff Langab75a052014-10-15 12:56:37 -0400779 {
Jamie Madill375c37c2015-07-21 15:14:08 -0400780 FramebufferAttachment::Target target(binding, textureIndex);
781 GLenum internalFormat = resource->getAttachmentInternalFormat(target);
782 const InternalFormat &formatInfo = GetInternalFormatInfo(internalFormat);
783 if (formatInfo.depthBits == 0 || formatInfo.stencilBits == 0)
784 {
785 // Attaching nullptr detaches the current attachment.
786 attachmentObj = nullptr;
787 }
Geoff Langab75a052014-10-15 12:56:37 -0400788 }
Jamie Madill375c37c2015-07-21 15:14:08 -0400789
Jamie Madill48ef11b2016-04-27 15:21:52 -0400790 mState.mDepthAttachment.attach(type, binding, textureIndex, attachmentObj);
791 mState.mStencilAttachment.attach(type, binding, textureIndex, attachmentObj);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500792 mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT);
793 mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT);
Geoff Langab75a052014-10-15 12:56:37 -0400794 }
795 else
796 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400797 switch (binding)
798 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500799 case GL_DEPTH:
800 case GL_DEPTH_ATTACHMENT:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400801 mState.mDepthAttachment.attach(type, binding, textureIndex, resource);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500802 mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT);
Jamie Madill2d06b732015-04-20 12:53:28 -0400803 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500804 case GL_STENCIL:
805 case GL_STENCIL_ATTACHMENT:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400806 mState.mStencilAttachment.attach(type, binding, textureIndex, resource);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500807 mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT);
Jamie Madill2d06b732015-04-20 12:53:28 -0400808 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500809 case GL_BACK:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400810 mState.mColorAttachments[0].attach(type, binding, textureIndex, resource);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500811 mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0);
Jamie Madill2d06b732015-04-20 12:53:28 -0400812 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500813 default:
Jamie Madill2d06b732015-04-20 12:53:28 -0400814 {
815 size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
Jamie Madill48ef11b2016-04-27 15:21:52 -0400816 ASSERT(colorIndex < mState.mColorAttachments.size());
817 mState.mColorAttachments[colorIndex].attach(type, binding, textureIndex, resource);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500818 mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
Jamie Madill2d06b732015-04-20 12:53:28 -0400819 }
820 break;
821 }
Geoff Langab75a052014-10-15 12:56:37 -0400822 }
823}
824
Jamie Madill2d06b732015-04-20 12:53:28 -0400825void Framebuffer::resetAttachment(GLenum binding)
826{
827 setAttachment(GL_NONE, binding, ImageIndex::MakeInvalid(), nullptr);
828}
829
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500830void Framebuffer::syncState() const
831{
832 if (mDirtyBits.any())
833 {
834 mImpl->syncState(mDirtyBits);
835 mDirtyBits.reset();
836 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000837}
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500838
839} // namespace gl