blob: 3def57b87e4e6870af97595ec96c8690fe37ba3d [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"
Geoff Langb5d8f232014-12-04 15:43:01 -050021#include "libANGLE/renderer/FramebufferImpl.h"
Jamie Madill48115b62015-03-16 10:46:57 -040022#include "libANGLE/renderer/ImplFactory.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050023#include "libANGLE/renderer/RenderbufferImpl.h"
Corentin Wallez37c39792015-08-20 14:19:46 -040024#include "libANGLE/renderer/SurfaceImpl.h"
Geoff Lang0b7eef72014-06-12 14:10:47 -040025
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000026namespace gl
27{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000028
Jamie Madilld1405e52015-03-05 15:41:39 -050029namespace
30{
Jamie Madill2d06b732015-04-20 12:53:28 -040031void DetachMatchingAttachment(FramebufferAttachment *attachment, GLenum matchType, GLuint matchId)
Jamie Madilld1405e52015-03-05 15:41:39 -050032{
Jamie Madill2d06b732015-04-20 12:53:28 -040033 if (attachment->isAttached() &&
34 attachment->type() == matchType &&
35 attachment->id() == matchId)
Jamie Madilld1405e52015-03-05 15:41:39 -050036 {
Jamie Madill2d06b732015-04-20 12:53:28 -040037 attachment->detach();
Jamie Madilld1405e52015-03-05 15:41:39 -050038 }
39}
40}
41
Corentin Wallez37c39792015-08-20 14:19:46 -040042Framebuffer::Data::Data()
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 Madilld1405e52015-03-05 15:41:39 -050051Framebuffer::Data::Data(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
61Framebuffer::Data::~Data()
62{
Jamie Madilld1405e52015-03-05 15:41:39 -050063}
64
Geoff Lang70d0f492015-12-10 17:45:46 -050065const std::string &Framebuffer::Data::getLabel()
66{
67 return mLabel;
68}
69
Jamie Madillb6bda4a2015-04-20 12:53:26 -040070const FramebufferAttachment *Framebuffer::Data::getReadAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -050071{
72 ASSERT(mReadBufferState == GL_BACK || (mReadBufferState >= GL_COLOR_ATTACHMENT0 && mReadBufferState <= GL_COLOR_ATTACHMENT15));
73 size_t readIndex = (mReadBufferState == GL_BACK ? 0 : static_cast<size_t>(mReadBufferState - GL_COLOR_ATTACHMENT0));
74 ASSERT(readIndex < mColorAttachments.size());
Jamie Madill2d06b732015-04-20 12:53:28 -040075 return mColorAttachments[readIndex].isAttached() ? &mColorAttachments[readIndex] : nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -050076}
77
Jamie Madillb6bda4a2015-04-20 12:53:26 -040078const FramebufferAttachment *Framebuffer::Data::getFirstColorAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -050079{
Jamie Madill2d06b732015-04-20 12:53:28 -040080 for (const FramebufferAttachment &colorAttachment : mColorAttachments)
Jamie Madill7147f012015-03-05 15:41:40 -050081 {
Jamie Madill2d06b732015-04-20 12:53:28 -040082 if (colorAttachment.isAttached())
Jamie Madill7147f012015-03-05 15:41:40 -050083 {
Jamie Madill2d06b732015-04-20 12:53:28 -040084 return &colorAttachment;
Jamie Madill7147f012015-03-05 15:41:40 -050085 }
86 }
87
88 return nullptr;
89}
90
Jamie Madillb6bda4a2015-04-20 12:53:26 -040091const FramebufferAttachment *Framebuffer::Data::getDepthOrStencilAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -050092{
Jamie Madill2d06b732015-04-20 12:53:28 -040093 if (mDepthAttachment.isAttached())
94 {
95 return &mDepthAttachment;
96 }
97 if (mStencilAttachment.isAttached())
98 {
99 return &mStencilAttachment;
100 }
101 return nullptr;
Jamie Madill7147f012015-03-05 15:41:40 -0500102}
103
Corentin Wallez37c39792015-08-20 14:19:46 -0400104const FramebufferAttachment *Framebuffer::Data::getColorAttachment(size_t colorAttachment) const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400105{
106 ASSERT(colorAttachment < mColorAttachments.size());
Jamie Madill2d06b732015-04-20 12:53:28 -0400107 return mColorAttachments[colorAttachment].isAttached() ?
108 &mColorAttachments[colorAttachment] :
109 nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400110}
111
Jamie Madille3ef7152015-04-28 16:55:17 +0000112const FramebufferAttachment *Framebuffer::Data::getDepthAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400113{
Jamie Madill2d06b732015-04-20 12:53:28 -0400114 return mDepthAttachment.isAttached() ? &mDepthAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400115}
116
Jamie Madille3ef7152015-04-28 16:55:17 +0000117const FramebufferAttachment *Framebuffer::Data::getStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400118{
Jamie Madill2d06b732015-04-20 12:53:28 -0400119 return mStencilAttachment.isAttached() ? &mStencilAttachment : nullptr;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400120}
121
Jamie Madille3ef7152015-04-28 16:55:17 +0000122const FramebufferAttachment *Framebuffer::Data::getDepthStencilAttachment() const
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400123{
124 // A valid depth-stencil attachment has the same resource bound to both the
125 // depth and stencil attachment points.
Jamie Madill2d06b732015-04-20 12:53:28 -0400126 if (mDepthAttachment.isAttached() && mStencilAttachment.isAttached() &&
127 mDepthAttachment.type() == mStencilAttachment.type() &&
128 mDepthAttachment.id() == mStencilAttachment.id())
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400129 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400130 return &mDepthAttachment;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400131 }
132
133 return nullptr;
134}
135
Jamie Madillcc86d642015-11-24 13:00:07 -0500136bool Framebuffer::Data::attachmentsHaveSameDimensions() const
137{
138 Optional<Extents> attachmentSize;
139
140 auto hasMismatchedSize = [&attachmentSize](const FramebufferAttachment &attachment)
141 {
142 if (!attachment.isAttached())
143 {
144 return false;
145 }
146
147 if (!attachmentSize.valid())
148 {
149 attachmentSize = attachment.getSize();
150 return false;
151 }
152
153 return (attachment.getSize() != attachmentSize.value());
154 };
155
156 for (const auto &attachment : mColorAttachments)
157 {
158 if (hasMismatchedSize(attachment))
159 {
160 return false;
161 }
162 }
163
164 if (hasMismatchedSize(mDepthAttachment))
165 {
166 return false;
167 }
168
169 return !hasMismatchedSize(mStencilAttachment);
170}
171
Jamie Madill48115b62015-03-16 10:46:57 -0400172Framebuffer::Framebuffer(const Caps &caps, rx::ImplFactory *factory, GLuint id)
Corentin Wallez37c39792015-08-20 14:19:46 -0400173 : mData(caps), mImpl(factory->createFramebuffer(mData)), mId(id)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000174{
Corentin Wallez37c39792015-08-20 14:19:46 -0400175 ASSERT(mId != 0);
176 ASSERT(mImpl != nullptr);
177}
178
179Framebuffer::Framebuffer(rx::SurfaceImpl *surface)
180 : mData(), mImpl(surface->createDefaultFramebuffer(mData)), mId(0)
181{
Geoff Langda88add2014-12-01 10:22:01 -0500182 ASSERT(mImpl != nullptr);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000183}
184
185Framebuffer::~Framebuffer()
186{
Geoff Langda88add2014-12-01 10:22:01 -0500187 SafeDelete(mImpl);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000188}
189
Geoff Lang70d0f492015-12-10 17:45:46 -0500190void Framebuffer::setLabel(const std::string &label)
191{
192 mData.mLabel = label;
193}
194
195const std::string &Framebuffer::getLabel() const
196{
197 return mData.mLabel;
198}
199
Jamie Madille261b442014-06-25 12:42:21 -0400200void Framebuffer::detachTexture(GLuint textureId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000201{
Jamie Madilld1405e52015-03-05 15:41:39 -0500202 detachResourceById(GL_TEXTURE, textureId);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000203}
204
Jamie Madille261b442014-06-25 12:42:21 -0400205void Framebuffer::detachRenderbuffer(GLuint renderbufferId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000206{
Jamie Madilld1405e52015-03-05 15:41:39 -0500207 detachResourceById(GL_RENDERBUFFER, renderbufferId);
208}
Jamie Madille261b442014-06-25 12:42:21 -0400209
Jamie Madilld1405e52015-03-05 15:41:39 -0500210void Framebuffer::detachResourceById(GLenum resourceType, GLuint resourceId)
211{
212 for (auto &colorAttachment : mData.mColorAttachments)
213 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400214 DetachMatchingAttachment(&colorAttachment, resourceType, resourceId);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000215 }
216
Jamie Madill2d06b732015-04-20 12:53:28 -0400217 DetachMatchingAttachment(&mData.mDepthAttachment, resourceType, resourceId);
218 DetachMatchingAttachment(&mData.mStencilAttachment, resourceType, resourceId);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000219}
220
Corentin Wallez37c39792015-08-20 14:19:46 -0400221const FramebufferAttachment *Framebuffer::getColorbuffer(size_t colorAttachment) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000222{
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400223 return mData.getColorAttachment(colorAttachment);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000224}
225
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400226const FramebufferAttachment *Framebuffer::getDepthbuffer() const
Geoff Lang646559f2013-08-15 11:08:15 -0400227{
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400228 return mData.getDepthAttachment();
Geoff Lang646559f2013-08-15 11:08:15 -0400229}
230
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400231const FramebufferAttachment *Framebuffer::getStencilbuffer() const
232{
233 return mData.getStencilAttachment();
234}
235
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400236const FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
237{
238 return mData.getDepthStencilAttachment();
239}
240
241const FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000242{
Jamie Madill7147f012015-03-05 15:41:40 -0500243 return mData.getDepthOrStencilAttachment();
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000244}
245
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400246const FramebufferAttachment *Framebuffer::getReadColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000247{
Jamie Madill7147f012015-03-05 15:41:40 -0500248 return mData.getReadAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000249}
250
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000251GLenum Framebuffer::getReadColorbufferType() const
252{
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400253 const FramebufferAttachment *readAttachment = mData.getReadAttachment();
254 return (readAttachment != nullptr ? readAttachment->type() : GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000255}
256
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400257const FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000258{
Jamie Madill7147f012015-03-05 15:41:40 -0500259 return mData.getFirstColorAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000260}
261
Jamie Madill2d06b732015-04-20 12:53:28 -0400262const FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000263{
Jamie Madille92a3542014-07-03 10:38:58 -0400264 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
265 {
Jamie Madille3ef7152015-04-28 16:55:17 +0000266 return mData.getColorAttachment(attachment - GL_COLOR_ATTACHMENT0);
Jamie Madille92a3542014-07-03 10:38:58 -0400267 }
268 else
269 {
270 switch (attachment)
271 {
Geoff Lang528ce3c2014-12-01 10:44:07 -0500272 case GL_COLOR:
273 case GL_BACK:
Jamie Madille3ef7152015-04-28 16:55:17 +0000274 return mData.getColorAttachment(0);
Geoff Lang528ce3c2014-12-01 10:44:07 -0500275 case GL_DEPTH:
Jamie Madille92a3542014-07-03 10:38:58 -0400276 case GL_DEPTH_ATTACHMENT:
Jamie Madille3ef7152015-04-28 16:55:17 +0000277 return mData.getDepthAttachment();
Geoff Lang528ce3c2014-12-01 10:44:07 -0500278 case GL_STENCIL:
Jamie Madille92a3542014-07-03 10:38:58 -0400279 case GL_STENCIL_ATTACHMENT:
Jamie Madille3ef7152015-04-28 16:55:17 +0000280 return mData.getStencilAttachment();
Geoff Lang528ce3c2014-12-01 10:44:07 -0500281 case GL_DEPTH_STENCIL:
Jamie Madille92a3542014-07-03 10:38:58 -0400282 case GL_DEPTH_STENCIL_ATTACHMENT:
283 return getDepthStencilBuffer();
284 default:
285 UNREACHABLE();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400286 return nullptr;
Jamie Madille92a3542014-07-03 10:38:58 -0400287 }
288 }
Geoff Lang55ba29c2013-07-11 16:57:53 -0400289}
290
Geoff Langa15472a2015-08-11 11:48:03 -0400291size_t Framebuffer::getDrawbufferStateCount() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000292{
Geoff Langa15472a2015-08-11 11:48:03 -0400293 return mData.mDrawBufferStates.size();
294}
295
296GLenum Framebuffer::getDrawBufferState(size_t drawBuffer) const
297{
298 ASSERT(drawBuffer < mData.mDrawBufferStates.size());
299 return mData.mDrawBufferStates[drawBuffer];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000300}
301
Geoff Lang164d54e2014-12-01 10:55:33 -0500302void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000303{
Jamie Madilld1405e52015-03-05 15:41:39 -0500304 auto &drawStates = mData.mDrawBufferStates;
305
306 ASSERT(count <= drawStates.size());
307 std::copy(buffers, buffers + count, drawStates.begin());
308 std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500309 mDirtyBits.set(DIRTY_BIT_DRAW_BUFFERS);
Geoff Lang9dd95802014-12-01 11:12:59 -0500310}
311
Geoff Langa15472a2015-08-11 11:48:03 -0400312const FramebufferAttachment *Framebuffer::getDrawBuffer(size_t drawBuffer) const
313{
314 ASSERT(drawBuffer < mData.mDrawBufferStates.size());
315 if (mData.mDrawBufferStates[drawBuffer] != GL_NONE)
316 {
317 // ES3 spec: "If the GL is bound to a draw framebuffer object, the ith buffer listed in bufs
318 // must be COLOR_ATTACHMENTi or NONE"
319 ASSERT(mData.mDrawBufferStates[drawBuffer] == GL_COLOR_ATTACHMENT0 + drawBuffer ||
320 (drawBuffer == 0 && mData.mDrawBufferStates[drawBuffer] == GL_BACK));
321 return getAttachment(mData.mDrawBufferStates[drawBuffer]);
322 }
323 else
324 {
325 return nullptr;
326 }
327}
328
329bool Framebuffer::hasEnabledDrawBuffer() const
330{
331 for (size_t drawbufferIdx = 0; drawbufferIdx < mData.mDrawBufferStates.size(); ++drawbufferIdx)
332 {
333 if (getDrawBuffer(drawbufferIdx) != nullptr)
334 {
335 return true;
336 }
337 }
338
339 return false;
340}
341
Geoff Lang9dd95802014-12-01 11:12:59 -0500342GLenum Framebuffer::getReadBufferState() const
343{
Jamie Madilld1405e52015-03-05 15:41:39 -0500344 return mData.mReadBufferState;
Geoff Lang9dd95802014-12-01 11:12:59 -0500345}
346
347void Framebuffer::setReadBuffer(GLenum buffer)
348{
Jamie Madillb885e572015-02-03 16:16:04 -0500349 ASSERT(buffer == GL_BACK || buffer == GL_NONE ||
350 (buffer >= GL_COLOR_ATTACHMENT0 &&
Jamie Madilld1405e52015-03-05 15:41:39 -0500351 (buffer - GL_COLOR_ATTACHMENT0) < mData.mColorAttachments.size()));
352 mData.mReadBufferState = buffer;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500353 mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000354}
355
Corentin Wallez37c39792015-08-20 14:19:46 -0400356size_t Framebuffer::getNumColorBuffers() const
357{
358 return mData.mColorAttachments.size();
359}
360
Jamie Madill0df8fe42015-11-24 16:10:24 -0500361bool Framebuffer::hasDepth() const
362{
363 return (mData.mDepthAttachment.isAttached() && mData.mDepthAttachment.getDepthSize() > 0);
364}
365
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000366bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000367{
Jamie Madill2d06b732015-04-20 12:53:28 -0400368 return (mData.mStencilAttachment.isAttached() && mData.mStencilAttachment.getStencilSize() > 0);
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000369}
370
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000371bool Framebuffer::usingExtendedDrawBuffers() const
372{
Geoff Langa15472a2015-08-11 11:48:03 -0400373 for (size_t drawbufferIdx = 1; drawbufferIdx < mData.mDrawBufferStates.size(); ++drawbufferIdx)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000374 {
Geoff Langa15472a2015-08-11 11:48:03 -0400375 if (getDrawBuffer(drawbufferIdx) != nullptr)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000376 {
377 return true;
378 }
379 }
380
381 return false;
382}
383
Geoff Lang748f74e2014-12-01 11:25:34 -0500384GLenum Framebuffer::checkStatus(const gl::Data &data) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000385{
Geoff Lang528ce3c2014-12-01 10:44:07 -0500386 // The default framebuffer *must* always be complete, though it may not be
387 // subject to the same rules as application FBOs. ie, it could have 0x0 size.
388 if (mId == 0)
389 {
390 return GL_FRAMEBUFFER_COMPLETE;
391 }
392
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000393 unsigned int colorbufferSize = 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000394 int samples = -1;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000395 bool missingAttachment = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000396
Jamie Madill2d06b732015-04-20 12:53:28 -0400397 for (const FramebufferAttachment &colorAttachment : mData.mColorAttachments)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000398 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400399 if (colorAttachment.isAttached())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000400 {
Jamie Madill6b120b92015-11-24 13:00:07 -0500401 const Extents &size = colorAttachment.getSize();
402 if (size.width == 0 || size.height == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000403 {
404 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
405 }
daniel@transgaming.com01868132010-08-24 19:21:17 +0000406
Jamie Madill2d06b732015-04-20 12:53:28 -0400407 GLenum internalformat = colorAttachment.getInternalFormat();
Jamie Madill48faf802014-11-06 15:27:22 -0500408 const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400409 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill2d06b732015-04-20 12:53:28 -0400410 if (colorAttachment.type() == GL_TEXTURE)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000411 {
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400412 if (!formatCaps.renderable)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000413 {
Jamie Madill81176782015-11-24 16:10:23 -0500414 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000415 }
416
Geoff Lang5d601382014-07-22 15:14:06 -0400417 if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000418 {
419 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
420 }
Jamie Madill6b120b92015-11-24 13:00:07 -0500421
422 if (colorAttachment.layer() >= size.depth)
423 {
424 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
425 }
Jamie Madill3215b202015-12-15 16:41:39 -0500426
427 // ES3 specifies that cube map texture attachments must be cube complete.
428 // This language is missing from the ES2 spec, but we enforce it here because some
429 // desktop OpenGL drivers also enforce this validation.
430 // TODO(jmadill): Check if OpenGL ES2 drivers enforce cube completeness.
431 const Texture *texture = colorAttachment.getTexture();
432 ASSERT(texture);
433 if (texture->getTarget() == GL_TEXTURE_CUBE_MAP && !texture->isCubeComplete())
434 {
435 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
436 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000437 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400438 else if (colorAttachment.type() == GL_RENDERBUFFER)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000439 {
Geoff Lang5d601382014-07-22 15:14:06 -0400440 if (!formatCaps.renderable || formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400441 {
442 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
443 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000444 }
445
446 if (!missingAttachment)
447 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000448 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
449 // all color attachments have the same number of samples for the FBO to be complete.
Jamie Madill2d06b732015-04-20 12:53:28 -0400450 if (colorAttachment.getSamples() != samples)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000451 {
452 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
453 }
454
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000455 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
456 // in GLES 3.0, there is no such restriction
Jamie Madill48faf802014-11-06 15:27:22 -0500457 if (data.clientVersion < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000458 {
Geoff Lang5d601382014-07-22 15:14:06 -0400459 if (formatInfo.pixelBytes != colorbufferSize)
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000460 {
461 return GL_FRAMEBUFFER_UNSUPPORTED;
462 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000463 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000464 }
465 else
466 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400467 samples = colorAttachment.getSamples();
Geoff Lang5d601382014-07-22 15:14:06 -0400468 colorbufferSize = formatInfo.pixelBytes;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000469 missingAttachment = false;
470 }
471 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000472 }
473
Jamie Madill2d06b732015-04-20 12:53:28 -0400474 const FramebufferAttachment &depthAttachment = mData.mDepthAttachment;
475 if (depthAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000476 {
Jamie Madill6b120b92015-11-24 13:00:07 -0500477 const Extents &size = depthAttachment.getSize();
478 if (size.width == 0 || size.height == 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000479 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000480 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000481 }
482
Jamie Madill2d06b732015-04-20 12:53:28 -0400483 GLenum internalformat = depthAttachment.getInternalFormat();
Jamie Madill48faf802014-11-06 15:27:22 -0500484 const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400485 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill2d06b732015-04-20 12:53:28 -0400486 if (depthAttachment.type() == GL_TEXTURE)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000487 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000488 // depth texture attachments require OES/ANGLE_depth_texture
Jamie Madill48faf802014-11-06 15:27:22 -0500489 if (!data.extensions->depthTextures)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000490 {
491 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
492 }
493
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400494 if (!formatCaps.renderable)
Geoff Langcec35902014-04-16 10:52:36 -0400495 {
Jamie Madill81176782015-11-24 16:10:23 -0500496 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
Geoff Langcec35902014-04-16 10:52:36 -0400497 }
498
Geoff Lang5d601382014-07-22 15:14:06 -0400499 if (formatInfo.depthBits == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000500 {
501 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
502 }
503 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400504 else if (depthAttachment.type() == GL_RENDERBUFFER)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000505 {
Geoff Lang5d601382014-07-22 15:14:06 -0400506 if (!formatCaps.renderable || formatInfo.depthBits == 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400507 {
508 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
509 }
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000510 }
511
512 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000513 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400514 samples = depthAttachment.getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000515 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000516 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400517 else if (samples != depthAttachment.getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000518 {
519 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
520 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000521 }
522
Jamie Madill2d06b732015-04-20 12:53:28 -0400523 const FramebufferAttachment &stencilAttachment = mData.mStencilAttachment;
524 if (stencilAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000525 {
Jamie Madill6b120b92015-11-24 13:00:07 -0500526 const Extents &size = stencilAttachment.getSize();
527 if (size.width == 0 || size.height == 0)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000528 {
529 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
530 }
531
Jamie Madill2d06b732015-04-20 12:53:28 -0400532 GLenum internalformat = stencilAttachment.getInternalFormat();
Jamie Madill48faf802014-11-06 15:27:22 -0500533 const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400534 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill2d06b732015-04-20 12:53:28 -0400535 if (stencilAttachment.type() == GL_TEXTURE)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000536 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000537 // texture stencil attachments come along as part
538 // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
Jamie Madill48faf802014-11-06 15:27:22 -0500539 if (!data.extensions->depthTextures)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000540 {
541 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
542 }
543
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400544 if (!formatCaps.renderable)
Geoff Langcec35902014-04-16 10:52:36 -0400545 {
Jamie Madill81176782015-11-24 16:10:23 -0500546 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
Geoff Langcec35902014-04-16 10:52:36 -0400547 }
548
Geoff Lang5d601382014-07-22 15:14:06 -0400549 if (formatInfo.stencilBits == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000550 {
551 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
552 }
553 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400554 else if (stencilAttachment.type() == GL_RENDERBUFFER)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000555 {
Geoff Lang5d601382014-07-22 15:14:06 -0400556 if (!formatCaps.renderable || formatInfo.stencilBits == 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400557 {
558 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
559 }
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000560 }
561
562 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000563 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400564 samples = stencilAttachment.getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000565 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000566 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400567 else if (samples != stencilAttachment.getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000568 {
569 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
570 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000571 }
572
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000573 // we need to have at least one attachment to be complete
574 if (missingAttachment)
575 {
576 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000577 }
578
Jamie Madillcc86d642015-11-24 13:00:07 -0500579 // In ES 2.0, all color attachments must have the same width and height.
580 // In ES 3.0, there is no such restriction.
581 if (data.clientVersion < 3 && !mData.attachmentsHaveSameDimensions())
582 {
583 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
584 }
585
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500586 syncState();
Jamie Madillcc86d642015-11-24 13:00:07 -0500587 if (!mImpl->checkStatus())
588 {
589 return GL_FRAMEBUFFER_UNSUPPORTED;
590 }
591
592 return GL_FRAMEBUFFER_COMPLETE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000593}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000594
Austin Kinross08332632015-05-05 13:35:47 -0700595Error Framebuffer::discard(size_t count, const GLenum *attachments)
596{
597 return mImpl->discard(count, attachments);
598}
599
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500600Error Framebuffer::invalidate(size_t count, const GLenum *attachments)
Jamie Madill2d96b9e2014-08-29 15:46:47 -0400601{
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500602 return mImpl->invalidate(count, attachments);
Jamie Madill2d96b9e2014-08-29 15:46:47 -0400603}
604
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500605Error Framebuffer::invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area)
Jamie Madill400a4412014-08-29 15:46:45 -0400606{
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500607 return mImpl->invalidateSub(count, attachments, area);
Jamie Madill400a4412014-08-29 15:46:45 -0400608}
609
Jamie Madillc29968b2016-01-20 11:17:23 -0500610Error Framebuffer::clear(const gl::Data &data, GLbitfield mask)
Geoff Langb04dc822014-12-01 12:02:02 -0500611{
Jamie Madillc29968b2016-01-20 11:17:23 -0500612 if (data.state->isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500613 {
614 return gl::Error(GL_NO_ERROR);
615 }
616
Jamie Madillc29968b2016-01-20 11:17:23 -0500617 return mImpl->clear(data, mask);
Geoff Langb04dc822014-12-01 12:02:02 -0500618}
619
Jamie Madillc29968b2016-01-20 11:17:23 -0500620Error Framebuffer::clearBufferfv(const gl::Data &data,
Jamie Madill1b94d432015-08-07 13:23:23 -0400621 GLenum buffer,
622 GLint drawbuffer,
623 const GLfloat *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500624{
Jamie Madillc29968b2016-01-20 11:17:23 -0500625 if (data.state->isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500626 {
627 return gl::Error(GL_NO_ERROR);
628 }
629
Jamie Madillc29968b2016-01-20 11:17:23 -0500630 return mImpl->clearBufferfv(data, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500631}
632
Jamie Madillc29968b2016-01-20 11:17:23 -0500633Error Framebuffer::clearBufferuiv(const gl::Data &data,
Jamie Madill1b94d432015-08-07 13:23:23 -0400634 GLenum buffer,
635 GLint drawbuffer,
636 const GLuint *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500637{
Jamie Madillc29968b2016-01-20 11:17:23 -0500638 if (data.state->isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500639 {
640 return gl::Error(GL_NO_ERROR);
641 }
642
Jamie Madillc29968b2016-01-20 11:17:23 -0500643 return mImpl->clearBufferuiv(data, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500644}
645
Jamie Madillc29968b2016-01-20 11:17:23 -0500646Error Framebuffer::clearBufferiv(const gl::Data &data,
Jamie Madill1b94d432015-08-07 13:23:23 -0400647 GLenum buffer,
648 GLint drawbuffer,
649 const GLint *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500650{
Jamie Madillc29968b2016-01-20 11:17:23 -0500651 if (data.state->isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500652 {
653 return gl::Error(GL_NO_ERROR);
654 }
655
Jamie Madillc29968b2016-01-20 11:17:23 -0500656 return mImpl->clearBufferiv(data, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500657}
658
Jamie Madillc29968b2016-01-20 11:17:23 -0500659Error Framebuffer::clearBufferfi(const gl::Data &data,
Jamie Madill1b94d432015-08-07 13:23:23 -0400660 GLenum buffer,
661 GLint drawbuffer,
662 GLfloat depth,
663 GLint stencil)
Geoff Langb04dc822014-12-01 12:02:02 -0500664{
Jamie Madillc29968b2016-01-20 11:17:23 -0500665 if (data.state->isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500666 {
667 return gl::Error(GL_NO_ERROR);
668 }
669
Jamie Madillc29968b2016-01-20 11:17:23 -0500670 return mImpl->clearBufferfi(data, buffer, drawbuffer, depth, stencil);
Geoff Langb04dc822014-12-01 12:02:02 -0500671}
672
Geoff Langbce529e2014-12-01 12:48:41 -0500673GLenum Framebuffer::getImplementationColorReadFormat() const
674{
675 return mImpl->getImplementationColorReadFormat();
676}
677
678GLenum Framebuffer::getImplementationColorReadType() const
679{
680 return mImpl->getImplementationColorReadType();
681}
682
Jamie Madillc29968b2016-01-20 11:17:23 -0500683Error Framebuffer::readPixels(const State &state,
684 const Rectangle &area,
Jamie Madill1b94d432015-08-07 13:23:23 -0400685 GLenum format,
686 GLenum type,
687 GLvoid *pixels) const
Geoff Langbce529e2014-12-01 12:48:41 -0500688{
Geoff Lang520c4ae2015-05-05 13:12:36 -0400689 Error error = mImpl->readPixels(state, area, format, type, pixels);
690 if (error.isError())
691 {
692 return error;
693 }
694
695 Buffer *unpackBuffer = state.getUnpackState().pixelBuffer.get();
696 if (unpackBuffer)
697 {
698 unpackBuffer->onPixelUnpack();
699 }
700
701 return Error(GL_NO_ERROR);
Geoff Langbce529e2014-12-01 12:48:41 -0500702}
703
Jamie Madillc29968b2016-01-20 11:17:23 -0500704Error Framebuffer::blit(const State &state,
705 const Rectangle &sourceArea,
706 const Rectangle &destArea,
Geoff Lang242468f2015-09-24 14:15:41 -0400707 GLbitfield mask,
708 GLenum filter,
Jamie Madillc29968b2016-01-20 11:17:23 -0500709 const Framebuffer *sourceFramebuffer)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500710{
711 return mImpl->blit(state, sourceArea, destArea, mask, filter, sourceFramebuffer);
712}
713
Jamie Madill48faf802014-11-06 15:27:22 -0500714int Framebuffer::getSamples(const gl::Data &data) const
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000715{
Geoff Lang748f74e2014-12-01 11:25:34 -0500716 if (checkStatus(data) == GL_FRAMEBUFFER_COMPLETE)
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000717 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000718 // for a complete framebuffer, all attachments must have the same sample count
719 // in this case return the first nonzero sample size
Jamie Madill2d06b732015-04-20 12:53:28 -0400720 for (const FramebufferAttachment &colorAttachment : mData.mColorAttachments)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000721 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400722 if (colorAttachment.isAttached())
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000723 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400724 return colorAttachment.getSamples();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000725 }
726 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000727 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000728
729 return 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000730}
731
Jamie Madille261b442014-06-25 12:42:21 -0400732bool Framebuffer::hasValidDepthStencil() const
733{
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400734 return mData.getDepthStencilAttachment() != nullptr;
Jamie Madille261b442014-06-25 12:42:21 -0400735}
736
Jamie Madill2d06b732015-04-20 12:53:28 -0400737void Framebuffer::setAttachment(GLenum type,
738 GLenum binding,
739 const ImageIndex &textureIndex,
740 FramebufferAttachmentObject *resource)
Geoff Langab75a052014-10-15 12:56:37 -0400741{
Jamie Madill2d06b732015-04-20 12:53:28 -0400742 if (binding == GL_DEPTH_STENCIL || binding == GL_DEPTH_STENCIL_ATTACHMENT)
Geoff Langab75a052014-10-15 12:56:37 -0400743 {
Geoff Langab75a052014-10-15 12:56:37 -0400744 // ensure this is a legitimate depth+stencil format
Jamie Madill375c37c2015-07-21 15:14:08 -0400745 FramebufferAttachmentObject *attachmentObj = resource;
746 if (resource)
Geoff Langab75a052014-10-15 12:56:37 -0400747 {
Jamie Madill375c37c2015-07-21 15:14:08 -0400748 FramebufferAttachment::Target target(binding, textureIndex);
749 GLenum internalFormat = resource->getAttachmentInternalFormat(target);
750 const InternalFormat &formatInfo = GetInternalFormatInfo(internalFormat);
751 if (formatInfo.depthBits == 0 || formatInfo.stencilBits == 0)
752 {
753 // Attaching nullptr detaches the current attachment.
754 attachmentObj = nullptr;
755 }
Geoff Langab75a052014-10-15 12:56:37 -0400756 }
Jamie Madill375c37c2015-07-21 15:14:08 -0400757
758 mData.mDepthAttachment.attach(type, binding, textureIndex, attachmentObj);
759 mData.mStencilAttachment.attach(type, binding, textureIndex, attachmentObj);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500760 mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT);
761 mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT);
Geoff Langab75a052014-10-15 12:56:37 -0400762 }
763 else
764 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400765 switch (binding)
766 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500767 case GL_DEPTH:
768 case GL_DEPTH_ATTACHMENT:
769 mData.mDepthAttachment.attach(type, binding, textureIndex, resource);
770 mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT);
Jamie Madill2d06b732015-04-20 12:53:28 -0400771 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500772 case GL_STENCIL:
773 case GL_STENCIL_ATTACHMENT:
774 mData.mStencilAttachment.attach(type, binding, textureIndex, resource);
775 mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT);
Jamie Madill2d06b732015-04-20 12:53:28 -0400776 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500777 case GL_BACK:
778 mData.mColorAttachments[0].attach(type, binding, textureIndex, resource);
779 mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0);
Jamie Madill2d06b732015-04-20 12:53:28 -0400780 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500781 default:
Jamie Madill2d06b732015-04-20 12:53:28 -0400782 {
783 size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
784 ASSERT(colorIndex < mData.mColorAttachments.size());
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400785 mData.mColorAttachments[colorIndex].attach(type, binding, textureIndex, resource);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500786 mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
Jamie Madill2d06b732015-04-20 12:53:28 -0400787 }
788 break;
789 }
Geoff Langab75a052014-10-15 12:56:37 -0400790 }
791}
792
Jamie Madill2d06b732015-04-20 12:53:28 -0400793void Framebuffer::resetAttachment(GLenum binding)
794{
795 setAttachment(GL_NONE, binding, ImageIndex::MakeInvalid(), nullptr);
796}
797
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500798void Framebuffer::syncState() const
799{
800 if (mDirtyBits.any())
801 {
802 mImpl->syncState(mDirtyBits);
803 mDirtyBits.reset();
804 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000805}
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500806
807} // namespace gl