blob: 04cd30ed114d97b346dbc29004049a0a99b38dd0 [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
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500302const std::vector<GLenum> &Framebuffer::getDrawBufferStates() const
303{
304 return mData.getDrawBufferStates();
305}
306
Geoff Lang164d54e2014-12-01 10:55:33 -0500307void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000308{
Jamie Madilld1405e52015-03-05 15:41:39 -0500309 auto &drawStates = mData.mDrawBufferStates;
310
311 ASSERT(count <= drawStates.size());
312 std::copy(buffers, buffers + count, drawStates.begin());
313 std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500314 mDirtyBits.set(DIRTY_BIT_DRAW_BUFFERS);
Geoff Lang9dd95802014-12-01 11:12:59 -0500315}
316
Geoff Langa15472a2015-08-11 11:48:03 -0400317const FramebufferAttachment *Framebuffer::getDrawBuffer(size_t drawBuffer) const
318{
319 ASSERT(drawBuffer < mData.mDrawBufferStates.size());
320 if (mData.mDrawBufferStates[drawBuffer] != GL_NONE)
321 {
322 // ES3 spec: "If the GL is bound to a draw framebuffer object, the ith buffer listed in bufs
323 // must be COLOR_ATTACHMENTi or NONE"
324 ASSERT(mData.mDrawBufferStates[drawBuffer] == GL_COLOR_ATTACHMENT0 + drawBuffer ||
325 (drawBuffer == 0 && mData.mDrawBufferStates[drawBuffer] == GL_BACK));
326 return getAttachment(mData.mDrawBufferStates[drawBuffer]);
327 }
328 else
329 {
330 return nullptr;
331 }
332}
333
334bool Framebuffer::hasEnabledDrawBuffer() const
335{
336 for (size_t drawbufferIdx = 0; drawbufferIdx < mData.mDrawBufferStates.size(); ++drawbufferIdx)
337 {
338 if (getDrawBuffer(drawbufferIdx) != nullptr)
339 {
340 return true;
341 }
342 }
343
344 return false;
345}
346
Geoff Lang9dd95802014-12-01 11:12:59 -0500347GLenum Framebuffer::getReadBufferState() const
348{
Jamie Madilld1405e52015-03-05 15:41:39 -0500349 return mData.mReadBufferState;
Geoff Lang9dd95802014-12-01 11:12:59 -0500350}
351
352void Framebuffer::setReadBuffer(GLenum buffer)
353{
Jamie Madillb885e572015-02-03 16:16:04 -0500354 ASSERT(buffer == GL_BACK || buffer == GL_NONE ||
355 (buffer >= GL_COLOR_ATTACHMENT0 &&
Jamie Madilld1405e52015-03-05 15:41:39 -0500356 (buffer - GL_COLOR_ATTACHMENT0) < mData.mColorAttachments.size()));
357 mData.mReadBufferState = buffer;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500358 mDirtyBits.set(DIRTY_BIT_READ_BUFFER);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000359}
360
Corentin Wallez37c39792015-08-20 14:19:46 -0400361size_t Framebuffer::getNumColorBuffers() const
362{
363 return mData.mColorAttachments.size();
364}
365
Jamie Madill0df8fe42015-11-24 16:10:24 -0500366bool Framebuffer::hasDepth() const
367{
368 return (mData.mDepthAttachment.isAttached() && mData.mDepthAttachment.getDepthSize() > 0);
369}
370
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000371bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000372{
Jamie Madill2d06b732015-04-20 12:53:28 -0400373 return (mData.mStencilAttachment.isAttached() && mData.mStencilAttachment.getStencilSize() > 0);
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000374}
375
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000376bool Framebuffer::usingExtendedDrawBuffers() const
377{
Geoff Langa15472a2015-08-11 11:48:03 -0400378 for (size_t drawbufferIdx = 1; drawbufferIdx < mData.mDrawBufferStates.size(); ++drawbufferIdx)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000379 {
Geoff Langa15472a2015-08-11 11:48:03 -0400380 if (getDrawBuffer(drawbufferIdx) != nullptr)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000381 {
382 return true;
383 }
384 }
385
386 return false;
387}
388
Jamie Madill9082b982016-04-27 15:21:51 -0400389GLenum Framebuffer::checkStatus(const ContextState &data) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000390{
Geoff Lang528ce3c2014-12-01 10:44:07 -0500391 // The default framebuffer *must* always be complete, though it may not be
392 // subject to the same rules as application FBOs. ie, it could have 0x0 size.
393 if (mId == 0)
394 {
395 return GL_FRAMEBUFFER_COMPLETE;
396 }
397
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000398 unsigned int colorbufferSize = 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000399 int samples = -1;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000400 bool missingAttachment = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000401
Jamie Madill2d06b732015-04-20 12:53:28 -0400402 for (const FramebufferAttachment &colorAttachment : mData.mColorAttachments)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000403 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400404 if (colorAttachment.isAttached())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000405 {
Jamie Madill6b120b92015-11-24 13:00:07 -0500406 const Extents &size = colorAttachment.getSize();
407 if (size.width == 0 || size.height == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000408 {
409 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
410 }
daniel@transgaming.com01868132010-08-24 19:21:17 +0000411
Jamie Madill2d06b732015-04-20 12:53:28 -0400412 GLenum internalformat = colorAttachment.getInternalFormat();
Jamie Madill48faf802014-11-06 15:27:22 -0500413 const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400414 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill2d06b732015-04-20 12:53:28 -0400415 if (colorAttachment.type() == GL_TEXTURE)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000416 {
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400417 if (!formatCaps.renderable)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000418 {
Jamie Madill81176782015-11-24 16:10:23 -0500419 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000420 }
421
Geoff Lang5d601382014-07-22 15:14:06 -0400422 if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000423 {
424 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
425 }
Jamie Madill6b120b92015-11-24 13:00:07 -0500426
427 if (colorAttachment.layer() >= size.depth)
428 {
429 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
430 }
Jamie Madill3215b202015-12-15 16:41:39 -0500431
432 // ES3 specifies that cube map texture attachments must be cube complete.
433 // This language is missing from the ES2 spec, but we enforce it here because some
434 // desktop OpenGL drivers also enforce this validation.
435 // TODO(jmadill): Check if OpenGL ES2 drivers enforce cube completeness.
436 const Texture *texture = colorAttachment.getTexture();
437 ASSERT(texture);
438 if (texture->getTarget() == GL_TEXTURE_CUBE_MAP && !texture->isCubeComplete())
439 {
440 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
441 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000442 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400443 else if (colorAttachment.type() == GL_RENDERBUFFER)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000444 {
Geoff Lang5d601382014-07-22 15:14:06 -0400445 if (!formatCaps.renderable || formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400446 {
447 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
448 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000449 }
450
451 if (!missingAttachment)
452 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000453 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
454 // all color attachments have the same number of samples for the FBO to be complete.
Jamie Madill2d06b732015-04-20 12:53:28 -0400455 if (colorAttachment.getSamples() != samples)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000456 {
457 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
458 }
459
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000460 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
461 // in GLES 3.0, there is no such restriction
Jamie Madill48faf802014-11-06 15:27:22 -0500462 if (data.clientVersion < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000463 {
Geoff Lang5d601382014-07-22 15:14:06 -0400464 if (formatInfo.pixelBytes != colorbufferSize)
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000465 {
466 return GL_FRAMEBUFFER_UNSUPPORTED;
467 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000468 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000469 }
470 else
471 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400472 samples = colorAttachment.getSamples();
Geoff Lang5d601382014-07-22 15:14:06 -0400473 colorbufferSize = formatInfo.pixelBytes;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000474 missingAttachment = false;
475 }
476 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000477 }
478
Jamie Madill2d06b732015-04-20 12:53:28 -0400479 const FramebufferAttachment &depthAttachment = mData.mDepthAttachment;
480 if (depthAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000481 {
Jamie Madill6b120b92015-11-24 13:00:07 -0500482 const Extents &size = depthAttachment.getSize();
483 if (size.width == 0 || size.height == 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000484 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000485 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000486 }
487
Jamie Madill2d06b732015-04-20 12:53:28 -0400488 GLenum internalformat = depthAttachment.getInternalFormat();
Jamie Madill48faf802014-11-06 15:27:22 -0500489 const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400490 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill2d06b732015-04-20 12:53:28 -0400491 if (depthAttachment.type() == GL_TEXTURE)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000492 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000493 // depth texture attachments require OES/ANGLE_depth_texture
Jamie Madill48faf802014-11-06 15:27:22 -0500494 if (!data.extensions->depthTextures)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000495 {
496 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
497 }
498
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400499 if (!formatCaps.renderable)
Geoff Langcec35902014-04-16 10:52:36 -0400500 {
Jamie Madill81176782015-11-24 16:10:23 -0500501 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
Geoff Langcec35902014-04-16 10:52:36 -0400502 }
503
Geoff Lang5d601382014-07-22 15:14:06 -0400504 if (formatInfo.depthBits == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000505 {
506 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
507 }
508 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400509 else if (depthAttachment.type() == GL_RENDERBUFFER)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000510 {
Geoff Lang5d601382014-07-22 15:14:06 -0400511 if (!formatCaps.renderable || formatInfo.depthBits == 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400512 {
513 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
514 }
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000515 }
516
517 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000518 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400519 samples = depthAttachment.getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000520 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000521 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400522 else if (samples != depthAttachment.getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000523 {
524 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
525 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000526 }
527
Jamie Madill2d06b732015-04-20 12:53:28 -0400528 const FramebufferAttachment &stencilAttachment = mData.mStencilAttachment;
529 if (stencilAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000530 {
Jamie Madill6b120b92015-11-24 13:00:07 -0500531 const Extents &size = stencilAttachment.getSize();
532 if (size.width == 0 || size.height == 0)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000533 {
534 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
535 }
536
Jamie Madill2d06b732015-04-20 12:53:28 -0400537 GLenum internalformat = stencilAttachment.getInternalFormat();
Jamie Madill48faf802014-11-06 15:27:22 -0500538 const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400539 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill2d06b732015-04-20 12:53:28 -0400540 if (stencilAttachment.type() == GL_TEXTURE)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000541 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000542 // texture stencil attachments come along as part
543 // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
Jamie Madill48faf802014-11-06 15:27:22 -0500544 if (!data.extensions->depthTextures)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000545 {
546 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
547 }
548
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400549 if (!formatCaps.renderable)
Geoff Langcec35902014-04-16 10:52:36 -0400550 {
Jamie Madill81176782015-11-24 16:10:23 -0500551 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
Geoff Langcec35902014-04-16 10:52:36 -0400552 }
553
Geoff Lang5d601382014-07-22 15:14:06 -0400554 if (formatInfo.stencilBits == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000555 {
556 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
557 }
558 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400559 else if (stencilAttachment.type() == GL_RENDERBUFFER)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000560 {
Geoff Lang5d601382014-07-22 15:14:06 -0400561 if (!formatCaps.renderable || formatInfo.stencilBits == 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400562 {
563 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
564 }
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000565 }
566
567 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000568 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400569 samples = stencilAttachment.getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000570 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000571 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400572 else if (samples != stencilAttachment.getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000573 {
574 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
575 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000576 }
577
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000578 // we need to have at least one attachment to be complete
579 if (missingAttachment)
580 {
581 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000582 }
583
Jamie Madillcc86d642015-11-24 13:00:07 -0500584 // In ES 2.0, all color attachments must have the same width and height.
585 // In ES 3.0, there is no such restriction.
586 if (data.clientVersion < 3 && !mData.attachmentsHaveSameDimensions())
587 {
588 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
589 }
590
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500591 syncState();
Jamie Madillcc86d642015-11-24 13:00:07 -0500592 if (!mImpl->checkStatus())
593 {
594 return GL_FRAMEBUFFER_UNSUPPORTED;
595 }
596
597 return GL_FRAMEBUFFER_COMPLETE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000598}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000599
Austin Kinross08332632015-05-05 13:35:47 -0700600Error Framebuffer::discard(size_t count, const GLenum *attachments)
601{
602 return mImpl->discard(count, attachments);
603}
604
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500605Error Framebuffer::invalidate(size_t count, const GLenum *attachments)
Jamie Madill2d96b9e2014-08-29 15:46:47 -0400606{
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500607 return mImpl->invalidate(count, attachments);
Jamie Madill2d96b9e2014-08-29 15:46:47 -0400608}
609
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500610Error Framebuffer::invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area)
Jamie Madill400a4412014-08-29 15:46:45 -0400611{
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500612 return mImpl->invalidateSub(count, attachments, area);
Jamie Madill400a4412014-08-29 15:46:45 -0400613}
614
Jamie Madill9082b982016-04-27 15:21:51 -0400615Error Framebuffer::clear(const ContextState &data, GLbitfield mask)
Geoff Langb04dc822014-12-01 12:02:02 -0500616{
Jamie Madillc29968b2016-01-20 11:17:23 -0500617 if (data.state->isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500618 {
619 return gl::Error(GL_NO_ERROR);
620 }
621
Jamie Madillc29968b2016-01-20 11:17:23 -0500622 return mImpl->clear(data, mask);
Geoff Langb04dc822014-12-01 12:02:02 -0500623}
624
Jamie Madill9082b982016-04-27 15:21:51 -0400625Error Framebuffer::clearBufferfv(const ContextState &data,
Jamie Madill1b94d432015-08-07 13:23:23 -0400626 GLenum buffer,
627 GLint drawbuffer,
628 const GLfloat *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500629{
Jamie Madillc29968b2016-01-20 11:17:23 -0500630 if (data.state->isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500631 {
632 return gl::Error(GL_NO_ERROR);
633 }
634
Jamie Madillc29968b2016-01-20 11:17:23 -0500635 return mImpl->clearBufferfv(data, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500636}
637
Jamie Madill9082b982016-04-27 15:21:51 -0400638Error Framebuffer::clearBufferuiv(const ContextState &data,
Jamie Madill1b94d432015-08-07 13:23:23 -0400639 GLenum buffer,
640 GLint drawbuffer,
641 const GLuint *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500642{
Jamie Madillc29968b2016-01-20 11:17:23 -0500643 if (data.state->isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500644 {
645 return gl::Error(GL_NO_ERROR);
646 }
647
Jamie Madillc29968b2016-01-20 11:17:23 -0500648 return mImpl->clearBufferuiv(data, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500649}
650
Jamie Madill9082b982016-04-27 15:21:51 -0400651Error Framebuffer::clearBufferiv(const ContextState &data,
Jamie Madill1b94d432015-08-07 13:23:23 -0400652 GLenum buffer,
653 GLint drawbuffer,
654 const GLint *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500655{
Jamie Madillc29968b2016-01-20 11:17:23 -0500656 if (data.state->isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500657 {
658 return gl::Error(GL_NO_ERROR);
659 }
660
Jamie Madillc29968b2016-01-20 11:17:23 -0500661 return mImpl->clearBufferiv(data, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500662}
663
Jamie Madill9082b982016-04-27 15:21:51 -0400664Error Framebuffer::clearBufferfi(const ContextState &data,
Jamie Madill1b94d432015-08-07 13:23:23 -0400665 GLenum buffer,
666 GLint drawbuffer,
667 GLfloat depth,
668 GLint stencil)
Geoff Langb04dc822014-12-01 12:02:02 -0500669{
Jamie Madillc29968b2016-01-20 11:17:23 -0500670 if (data.state->isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500671 {
672 return gl::Error(GL_NO_ERROR);
673 }
674
Jamie Madillc29968b2016-01-20 11:17:23 -0500675 return mImpl->clearBufferfi(data, buffer, drawbuffer, depth, stencil);
Geoff Langb04dc822014-12-01 12:02:02 -0500676}
677
Geoff Langbce529e2014-12-01 12:48:41 -0500678GLenum Framebuffer::getImplementationColorReadFormat() const
679{
680 return mImpl->getImplementationColorReadFormat();
681}
682
683GLenum Framebuffer::getImplementationColorReadType() const
684{
685 return mImpl->getImplementationColorReadType();
686}
687
Jamie Madillc29968b2016-01-20 11:17:23 -0500688Error Framebuffer::readPixels(const State &state,
689 const Rectangle &area,
Jamie Madill1b94d432015-08-07 13:23:23 -0400690 GLenum format,
691 GLenum type,
692 GLvoid *pixels) const
Geoff Langbce529e2014-12-01 12:48:41 -0500693{
Geoff Lang520c4ae2015-05-05 13:12:36 -0400694 Error error = mImpl->readPixels(state, area, format, type, pixels);
695 if (error.isError())
696 {
697 return error;
698 }
699
700 Buffer *unpackBuffer = state.getUnpackState().pixelBuffer.get();
701 if (unpackBuffer)
702 {
703 unpackBuffer->onPixelUnpack();
704 }
705
706 return Error(GL_NO_ERROR);
Geoff Langbce529e2014-12-01 12:48:41 -0500707}
708
Jamie Madillc29968b2016-01-20 11:17:23 -0500709Error Framebuffer::blit(const State &state,
710 const Rectangle &sourceArea,
711 const Rectangle &destArea,
Geoff Lang242468f2015-09-24 14:15:41 -0400712 GLbitfield mask,
713 GLenum filter,
Jamie Madillc29968b2016-01-20 11:17:23 -0500714 const Framebuffer *sourceFramebuffer)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500715{
716 return mImpl->blit(state, sourceArea, destArea, mask, filter, sourceFramebuffer);
717}
718
Jamie Madill9082b982016-04-27 15:21:51 -0400719int Framebuffer::getSamples(const ContextState &data) const
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000720{
Geoff Lang748f74e2014-12-01 11:25:34 -0500721 if (checkStatus(data) == GL_FRAMEBUFFER_COMPLETE)
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000722 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000723 // for a complete framebuffer, all attachments must have the same sample count
724 // in this case return the first nonzero sample size
Jamie Madill2d06b732015-04-20 12:53:28 -0400725 for (const FramebufferAttachment &colorAttachment : mData.mColorAttachments)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000726 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400727 if (colorAttachment.isAttached())
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000728 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400729 return colorAttachment.getSamples();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000730 }
731 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000732 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000733
734 return 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000735}
736
Jamie Madille261b442014-06-25 12:42:21 -0400737bool Framebuffer::hasValidDepthStencil() const
738{
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400739 return mData.getDepthStencilAttachment() != nullptr;
Jamie Madille261b442014-06-25 12:42:21 -0400740}
741
Jamie Madill2d06b732015-04-20 12:53:28 -0400742void Framebuffer::setAttachment(GLenum type,
743 GLenum binding,
744 const ImageIndex &textureIndex,
745 FramebufferAttachmentObject *resource)
Geoff Langab75a052014-10-15 12:56:37 -0400746{
Jamie Madill2d06b732015-04-20 12:53:28 -0400747 if (binding == GL_DEPTH_STENCIL || binding == GL_DEPTH_STENCIL_ATTACHMENT)
Geoff Langab75a052014-10-15 12:56:37 -0400748 {
Geoff Langab75a052014-10-15 12:56:37 -0400749 // ensure this is a legitimate depth+stencil format
Jamie Madill375c37c2015-07-21 15:14:08 -0400750 FramebufferAttachmentObject *attachmentObj = resource;
751 if (resource)
Geoff Langab75a052014-10-15 12:56:37 -0400752 {
Jamie Madill375c37c2015-07-21 15:14:08 -0400753 FramebufferAttachment::Target target(binding, textureIndex);
754 GLenum internalFormat = resource->getAttachmentInternalFormat(target);
755 const InternalFormat &formatInfo = GetInternalFormatInfo(internalFormat);
756 if (formatInfo.depthBits == 0 || formatInfo.stencilBits == 0)
757 {
758 // Attaching nullptr detaches the current attachment.
759 attachmentObj = nullptr;
760 }
Geoff Langab75a052014-10-15 12:56:37 -0400761 }
Jamie Madill375c37c2015-07-21 15:14:08 -0400762
763 mData.mDepthAttachment.attach(type, binding, textureIndex, attachmentObj);
764 mData.mStencilAttachment.attach(type, binding, textureIndex, attachmentObj);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500765 mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT);
766 mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT);
Geoff Langab75a052014-10-15 12:56:37 -0400767 }
768 else
769 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400770 switch (binding)
771 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500772 case GL_DEPTH:
773 case GL_DEPTH_ATTACHMENT:
774 mData.mDepthAttachment.attach(type, binding, textureIndex, resource);
775 mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT);
Jamie Madill2d06b732015-04-20 12:53:28 -0400776 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500777 case GL_STENCIL:
778 case GL_STENCIL_ATTACHMENT:
779 mData.mStencilAttachment.attach(type, binding, textureIndex, resource);
780 mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT);
Jamie Madill2d06b732015-04-20 12:53:28 -0400781 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500782 case GL_BACK:
783 mData.mColorAttachments[0].attach(type, binding, textureIndex, resource);
784 mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0);
Jamie Madill2d06b732015-04-20 12:53:28 -0400785 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500786 default:
Jamie Madill2d06b732015-04-20 12:53:28 -0400787 {
788 size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
789 ASSERT(colorIndex < mData.mColorAttachments.size());
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400790 mData.mColorAttachments[colorIndex].attach(type, binding, textureIndex, resource);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500791 mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
Jamie Madill2d06b732015-04-20 12:53:28 -0400792 }
793 break;
794 }
Geoff Langab75a052014-10-15 12:56:37 -0400795 }
796}
797
Jamie Madill2d06b732015-04-20 12:53:28 -0400798void Framebuffer::resetAttachment(GLenum binding)
799{
800 setAttachment(GL_NONE, binding, ImageIndex::MakeInvalid(), nullptr);
801}
802
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500803void Framebuffer::syncState() const
804{
805 if (mDirtyBits.any())
806 {
807 mImpl->syncState(mDirtyBits);
808 mDirtyBits.reset();
809 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000810}
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500811
812} // namespace gl