blob: 78a06a8676f32ef57087bc6d0c2def045016d651 [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
12#include "common/utilities.h"
13#include "libANGLE/Config.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050014#include "libANGLE/Context.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050015#include "libANGLE/FramebufferAttachment.h"
Jamie Madillc46f45d2015-03-31 13:20:55 -040016#include "libANGLE/Renderbuffer.h"
17#include "libANGLE/Surface.h"
18#include "libANGLE/Texture.h"
19#include "libANGLE/formatutils.h"
Geoff Langb5d8f232014-12-04 15:43:01 -050020#include "libANGLE/renderer/FramebufferImpl.h"
Jamie Madill48115b62015-03-16 10:46:57 -040021#include "libANGLE/renderer/ImplFactory.h"
Geoff Lang2b5420c2014-11-19 14:20:15 -050022#include "libANGLE/renderer/RenderbufferImpl.h"
23#include "libANGLE/renderer/Workarounds.h"
Geoff Lang0b7eef72014-06-12 14:10:47 -040024
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +000025namespace gl
26{
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +000027
Jamie Madilld1405e52015-03-05 15:41:39 -050028namespace
29{
Jamie Madillaed081c2015-04-21 13:55:21 +000030void DeleteMatchingAttachment(FramebufferAttachment *&attachment, GLenum matchType, GLuint matchId)
Jamie Madilld1405e52015-03-05 15:41:39 -050031{
Jamie Madillaed081c2015-04-21 13:55:21 +000032 if (attachment && attachment->type() == matchType && attachment->id() == matchId)
Jamie Madilld1405e52015-03-05 15:41:39 -050033 {
Jamie Madillaed081c2015-04-21 13:55:21 +000034 SafeDelete(attachment);
Jamie Madilld1405e52015-03-05 15:41:39 -050035 }
36}
37}
38
39Framebuffer::Data::Data(const Caps &caps)
Jamie Madillaed081c2015-04-21 13:55:21 +000040 : mColorAttachments(caps.maxColorAttachments, nullptr),
41 mDepthAttachment(nullptr),
42 mStencilAttachment(nullptr),
Jamie Madilld1405e52015-03-05 15:41:39 -050043 mDrawBufferStates(caps.maxDrawBuffers, GL_NONE),
44 mReadBufferState(GL_COLOR_ATTACHMENT0_EXT)
45{
46 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
47}
48
49Framebuffer::Data::~Data()
50{
Jamie Madillaed081c2015-04-21 13:55:21 +000051 for (auto &colorAttachment : mColorAttachments)
52 {
53 SafeDelete(colorAttachment);
54 }
55 SafeDelete(mDepthAttachment);
56 SafeDelete(mStencilAttachment);
Jamie Madilld1405e52015-03-05 15:41:39 -050057}
58
Jamie Madillb6bda4a2015-04-20 12:53:26 -040059const FramebufferAttachment *Framebuffer::Data::getReadAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -050060{
61 ASSERT(mReadBufferState == GL_BACK || (mReadBufferState >= GL_COLOR_ATTACHMENT0 && mReadBufferState <= GL_COLOR_ATTACHMENT15));
62 size_t readIndex = (mReadBufferState == GL_BACK ? 0 : static_cast<size_t>(mReadBufferState - GL_COLOR_ATTACHMENT0));
63 ASSERT(readIndex < mColorAttachments.size());
Jamie Madillaed081c2015-04-21 13:55:21 +000064 return mColorAttachments[readIndex];
Jamie Madill7147f012015-03-05 15:41:40 -050065}
66
Jamie Madillb6bda4a2015-04-20 12:53:26 -040067const FramebufferAttachment *Framebuffer::Data::getFirstColorAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -050068{
Jamie Madillaed081c2015-04-21 13:55:21 +000069 for (FramebufferAttachment *colorAttachment : mColorAttachments)
Jamie Madill7147f012015-03-05 15:41:40 -050070 {
Jamie Madillaed081c2015-04-21 13:55:21 +000071 if (colorAttachment != nullptr)
Jamie Madill7147f012015-03-05 15:41:40 -050072 {
Jamie Madillaed081c2015-04-21 13:55:21 +000073 return colorAttachment;
Jamie Madill7147f012015-03-05 15:41:40 -050074 }
75 }
76
77 return nullptr;
78}
79
Jamie Madillb6bda4a2015-04-20 12:53:26 -040080const FramebufferAttachment *Framebuffer::Data::getDepthOrStencilAttachment() const
Jamie Madill7147f012015-03-05 15:41:40 -050081{
Jamie Madillaed081c2015-04-21 13:55:21 +000082 return (mDepthAttachment != nullptr ? mDepthAttachment : mStencilAttachment);
Jamie Madill7147f012015-03-05 15:41:40 -050083}
84
Jamie Madill34771622015-04-21 13:54:34 +000085FramebufferAttachment *Framebuffer::Data::getColorAttachment(unsigned int colorAttachment)
Jamie Madillb6bda4a2015-04-20 12:53:26 -040086{
87 ASSERT(colorAttachment < mColorAttachments.size());
Jamie Madillaed081c2015-04-21 13:55:21 +000088 return mColorAttachments[colorAttachment];
Jamie Madillb6bda4a2015-04-20 12:53:26 -040089}
90
Jamie Madill34771622015-04-21 13:54:34 +000091const FramebufferAttachment *Framebuffer::Data::getColorAttachment(unsigned int colorAttachment) const
92{
93 return const_cast<Framebuffer::Data *>(this)->getColorAttachment(colorAttachment);
94}
95
96FramebufferAttachment *Framebuffer::Data::getDepthAttachment()
Jamie Madillb6bda4a2015-04-20 12:53:26 -040097{
Jamie Madillaed081c2015-04-21 13:55:21 +000098 return mDepthAttachment;
Jamie Madillb6bda4a2015-04-20 12:53:26 -040099}
100
Jamie Madill34771622015-04-21 13:54:34 +0000101const FramebufferAttachment *Framebuffer::Data::getDepthAttachment() const
102{
103 return const_cast<Framebuffer::Data *>(this)->getDepthAttachment();
104}
105
106FramebufferAttachment *Framebuffer::Data::getStencilAttachment()
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400107{
Jamie Madillaed081c2015-04-21 13:55:21 +0000108 return mStencilAttachment;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400109}
110
Jamie Madill34771622015-04-21 13:54:34 +0000111const FramebufferAttachment *Framebuffer::Data::getStencilAttachment() const
112{
113 return const_cast<Framebuffer::Data *>(this)->getStencilAttachment();
114}
115
116FramebufferAttachment *Framebuffer::Data::getDepthStencilAttachment()
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400117{
118 // A valid depth-stencil attachment has the same resource bound to both the
119 // depth and stencil attachment points.
Jamie Madillaed081c2015-04-21 13:55:21 +0000120 if (mDepthAttachment && mStencilAttachment &&
121 mDepthAttachment->type() == mStencilAttachment->type() &&
122 mDepthAttachment->id() == mStencilAttachment->id())
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400123 {
Jamie Madillaed081c2015-04-21 13:55:21 +0000124 return mDepthAttachment;
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400125 }
126
127 return nullptr;
128}
129
Jamie Madill34771622015-04-21 13:54:34 +0000130const FramebufferAttachment *Framebuffer::Data::getDepthStencilAttachment() const
131{
132 return const_cast<Framebuffer::Data *>(this)->getDepthStencilAttachment();
133}
134
Jamie Madill48115b62015-03-16 10:46:57 -0400135Framebuffer::Framebuffer(const Caps &caps, rx::ImplFactory *factory, GLuint id)
Jamie Madilld1405e52015-03-05 15:41:39 -0500136 : mData(caps),
Geoff Lang4ad17092015-03-10 16:47:44 -0400137 mImpl(nullptr),
Jamie Madilld1405e52015-03-05 15:41:39 -0500138 mId(id)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000139{
Geoff Lang4ad17092015-03-10 16:47:44 -0400140 if (mId == 0)
141 {
142 mImpl = factory->createDefaultFramebuffer(mData);
143 }
144 else
145 {
146 mImpl = factory->createFramebuffer(mData);
147 }
Geoff Langda88add2014-12-01 10:22:01 -0500148 ASSERT(mImpl != nullptr);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000149}
150
151Framebuffer::~Framebuffer()
152{
Geoff Langda88add2014-12-01 10:22:01 -0500153 SafeDelete(mImpl);
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000154}
155
Jamie Madille261b442014-06-25 12:42:21 -0400156void Framebuffer::detachTexture(GLuint textureId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000157{
Jamie Madilld1405e52015-03-05 15:41:39 -0500158 detachResourceById(GL_TEXTURE, textureId);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000159}
160
Jamie Madille261b442014-06-25 12:42:21 -0400161void Framebuffer::detachRenderbuffer(GLuint renderbufferId)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000162{
Jamie Madilld1405e52015-03-05 15:41:39 -0500163 detachResourceById(GL_RENDERBUFFER, renderbufferId);
164}
Jamie Madille261b442014-06-25 12:42:21 -0400165
Jamie Madilld1405e52015-03-05 15:41:39 -0500166void Framebuffer::detachResourceById(GLenum resourceType, GLuint resourceId)
167{
168 for (auto &colorAttachment : mData.mColorAttachments)
169 {
Jamie Madillaed081c2015-04-21 13:55:21 +0000170 DeleteMatchingAttachment(colorAttachment, resourceType, resourceId);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000171 }
172
Jamie Madillaed081c2015-04-21 13:55:21 +0000173 DeleteMatchingAttachment(mData.mDepthAttachment, resourceType, resourceId);
174 DeleteMatchingAttachment(mData.mStencilAttachment, resourceType, resourceId);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000175}
176
Jamie Madill34771622015-04-21 13:54:34 +0000177FramebufferAttachment *Framebuffer::getColorbuffer(unsigned int colorAttachment)
178{
179 return mData.getColorAttachment(colorAttachment);
180}
181
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400182const FramebufferAttachment *Framebuffer::getColorbuffer(unsigned int colorAttachment) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000183{
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400184 return mData.getColorAttachment(colorAttachment);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000185}
186
Jamie Madill34771622015-04-21 13:54:34 +0000187FramebufferAttachment *Framebuffer::getDepthbuffer()
188{
189 return mData.getDepthAttachment();
190}
191
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400192const FramebufferAttachment *Framebuffer::getDepthbuffer() const
Geoff Lang646559f2013-08-15 11:08:15 -0400193{
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400194 return mData.getDepthAttachment();
Geoff Lang646559f2013-08-15 11:08:15 -0400195}
196
Jamie Madill34771622015-04-21 13:54:34 +0000197FramebufferAttachment *Framebuffer::getStencilbuffer()
198{
199 return mData.getStencilAttachment();
200}
201
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400202const FramebufferAttachment *Framebuffer::getStencilbuffer() const
203{
204 return mData.getStencilAttachment();
205}
206
Jamie Madill34771622015-04-21 13:54:34 +0000207FramebufferAttachment *Framebuffer::getDepthStencilBuffer()
208{
209 return mData.getDepthStencilAttachment();
210}
211
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400212const FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
213{
214 return mData.getDepthStencilAttachment();
215}
216
217const FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000218{
Jamie Madill7147f012015-03-05 15:41:40 -0500219 return mData.getDepthOrStencilAttachment();
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000220}
221
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400222const FramebufferAttachment *Framebuffer::getReadColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000223{
Jamie Madill7147f012015-03-05 15:41:40 -0500224 return mData.getReadAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000225}
226
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000227GLenum Framebuffer::getReadColorbufferType() const
228{
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400229 const FramebufferAttachment *readAttachment = mData.getReadAttachment();
230 return (readAttachment != nullptr ? readAttachment->type() : GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comf6863e02013-04-13 03:34:00 +0000231}
232
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400233const FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000234{
Jamie Madill7147f012015-03-05 15:41:40 -0500235 return mData.getFirstColorAttachment();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000236}
237
Jamie Madillaed081c2015-04-21 13:55:21 +0000238FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000239{
Jamie Madille92a3542014-07-03 10:38:58 -0400240 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
241 {
Jamie Madill34771622015-04-21 13:54:34 +0000242 return getColorbuffer(attachment - GL_COLOR_ATTACHMENT0);
Jamie Madille92a3542014-07-03 10:38:58 -0400243 }
244 else
245 {
246 switch (attachment)
247 {
Geoff Lang528ce3c2014-12-01 10:44:07 -0500248 case GL_COLOR:
249 case GL_BACK:
Jamie Madill34771622015-04-21 13:54:34 +0000250 return getColorbuffer(0);
Geoff Lang528ce3c2014-12-01 10:44:07 -0500251 case GL_DEPTH:
Jamie Madille92a3542014-07-03 10:38:58 -0400252 case GL_DEPTH_ATTACHMENT:
Jamie Madill34771622015-04-21 13:54:34 +0000253 return getDepthbuffer();
Geoff Lang528ce3c2014-12-01 10:44:07 -0500254 case GL_STENCIL:
Jamie Madille92a3542014-07-03 10:38:58 -0400255 case GL_STENCIL_ATTACHMENT:
Jamie Madill34771622015-04-21 13:54:34 +0000256 return getStencilbuffer();
Geoff Lang528ce3c2014-12-01 10:44:07 -0500257 case GL_DEPTH_STENCIL:
Jamie Madille92a3542014-07-03 10:38:58 -0400258 case GL_DEPTH_STENCIL_ATTACHMENT:
259 return getDepthStencilBuffer();
260 default:
261 UNREACHABLE();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400262 return nullptr;
Jamie Madille92a3542014-07-03 10:38:58 -0400263 }
264 }
Geoff Lang55ba29c2013-07-11 16:57:53 -0400265}
266
Jamie Madillaed081c2015-04-21 13:55:21 +0000267const FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const
268{
269 return const_cast<Framebuffer*>(this)->getAttachment(attachment);
270}
271
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000272GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const
273{
Jamie Madilld1405e52015-03-05 15:41:39 -0500274 ASSERT(colorAttachment < mData.mDrawBufferStates.size());
275 return mData.mDrawBufferStates[colorAttachment];
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000276}
277
Geoff Lang164d54e2014-12-01 10:55:33 -0500278void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000279{
Jamie Madilld1405e52015-03-05 15:41:39 -0500280 auto &drawStates = mData.mDrawBufferStates;
281
282 ASSERT(count <= drawStates.size());
283 std::copy(buffers, buffers + count, drawStates.begin());
284 std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE);
Geoff Lang9dd95802014-12-01 11:12:59 -0500285 mImpl->setDrawBuffers(count, buffers);
286}
287
288GLenum Framebuffer::getReadBufferState() const
289{
Jamie Madilld1405e52015-03-05 15:41:39 -0500290 return mData.mReadBufferState;
Geoff Lang9dd95802014-12-01 11:12:59 -0500291}
292
293void Framebuffer::setReadBuffer(GLenum buffer)
294{
Jamie Madillb885e572015-02-03 16:16:04 -0500295 ASSERT(buffer == GL_BACK || buffer == GL_NONE ||
296 (buffer >= GL_COLOR_ATTACHMENT0 &&
Jamie Madilld1405e52015-03-05 15:41:39 -0500297 (buffer - GL_COLOR_ATTACHMENT0) < mData.mColorAttachments.size()));
298 mData.mReadBufferState = buffer;
Geoff Lang9dd95802014-12-01 11:12:59 -0500299 mImpl->setReadBuffer(buffer);
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000300}
301
shannon.woods%transgaming.com@gtempaccount.comdae24092013-04-13 03:31:31 +0000302bool Framebuffer::isEnabledColorAttachment(unsigned int colorAttachment) const
303{
Jamie Madilld1405e52015-03-05 15:41:39 -0500304 ASSERT(colorAttachment < mData.mColorAttachments.size());
Jamie Madillaed081c2015-04-21 13:55:21 +0000305 return (mData.mColorAttachments[colorAttachment] &&
Jamie Madilld1405e52015-03-05 15:41:39 -0500306 mData.mDrawBufferStates[colorAttachment] != GL_NONE);
shannon.woods%transgaming.com@gtempaccount.comdae24092013-04-13 03:31:31 +0000307}
308
309bool Framebuffer::hasEnabledColorAttachment() const
310{
Jamie Madilld1405e52015-03-05 15:41:39 -0500311 for (size_t colorAttachment = 0; colorAttachment < mData.mColorAttachments.size(); ++colorAttachment)
shannon.woods%transgaming.com@gtempaccount.comdae24092013-04-13 03:31:31 +0000312 {
313 if (isEnabledColorAttachment(colorAttachment))
314 {
315 return true;
316 }
317 }
318
319 return false;
320}
321
shannon.woods%transgaming.com@gtempaccount.com3b57b4f2013-04-13 03:28:29 +0000322bool Framebuffer::hasStencil() const
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000323{
Jamie Madillaed081c2015-04-21 13:55:21 +0000324 return (mData.mStencilAttachment && mData.mStencilAttachment->getStencilSize() > 0);
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000325}
326
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000327bool Framebuffer::usingExtendedDrawBuffers() const
328{
Jamie Madilld1405e52015-03-05 15:41:39 -0500329 for (size_t colorAttachment = 1; colorAttachment < mData.mColorAttachments.size(); ++colorAttachment)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000330 {
331 if (isEnabledColorAttachment(colorAttachment))
332 {
333 return true;
334 }
335 }
336
337 return false;
338}
339
Geoff Lang748f74e2014-12-01 11:25:34 -0500340GLenum Framebuffer::checkStatus(const gl::Data &data) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000341{
Geoff Lang528ce3c2014-12-01 10:44:07 -0500342 // The default framebuffer *must* always be complete, though it may not be
343 // subject to the same rules as application FBOs. ie, it could have 0x0 size.
344 if (mId == 0)
345 {
346 return GL_FRAMEBUFFER_COMPLETE;
347 }
348
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000349 int width = 0;
350 int height = 0;
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000351 unsigned int colorbufferSize = 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000352 int samples = -1;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000353 bool missingAttachment = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000354
Jamie Madillaed081c2015-04-21 13:55:21 +0000355 for (const FramebufferAttachment *colorAttachment : mData.mColorAttachments)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000356 {
Jamie Madillaed081c2015-04-21 13:55:21 +0000357 if (colorAttachment != nullptr)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000358 {
Jamie Madillaed081c2015-04-21 13:55:21 +0000359 if (colorAttachment->getWidth() == 0 || colorAttachment->getHeight() == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000360 {
361 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
362 }
daniel@transgaming.com01868132010-08-24 19:21:17 +0000363
Jamie Madillaed081c2015-04-21 13:55:21 +0000364 GLenum internalformat = colorAttachment->getInternalFormat();
Jamie Madill48faf802014-11-06 15:27:22 -0500365 const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400366 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madillaed081c2015-04-21 13:55:21 +0000367 if (colorAttachment->type() == GL_TEXTURE)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000368 {
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400369 if (!formatCaps.renderable)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000370 {
371 return GL_FRAMEBUFFER_UNSUPPORTED;
372 }
373
Geoff Lang5d601382014-07-22 15:14:06 -0400374 if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000375 {
376 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
377 }
378 }
Jamie Madillaed081c2015-04-21 13:55:21 +0000379 else if (colorAttachment->type() == GL_RENDERBUFFER)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000380 {
Geoff Lang5d601382014-07-22 15:14:06 -0400381 if (!formatCaps.renderable || formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400382 {
383 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
384 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000385 }
386
387 if (!missingAttachment)
388 {
389 // all color attachments must have the same width and height
Jamie Madillaed081c2015-04-21 13:55:21 +0000390 if (colorAttachment->getWidth() != width || colorAttachment->getHeight() != height)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000391 {
392 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
393 }
394
395 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
396 // all color attachments have the same number of samples for the FBO to be complete.
Jamie Madillaed081c2015-04-21 13:55:21 +0000397 if (colorAttachment->getSamples() != samples)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000398 {
399 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
400 }
401
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000402 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
403 // in GLES 3.0, there is no such restriction
Jamie Madill48faf802014-11-06 15:27:22 -0500404 if (data.clientVersion < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000405 {
Geoff Lang5d601382014-07-22 15:14:06 -0400406 if (formatInfo.pixelBytes != colorbufferSize)
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000407 {
408 return GL_FRAMEBUFFER_UNSUPPORTED;
409 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000410 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000411 }
412 else
413 {
Jamie Madillaed081c2015-04-21 13:55:21 +0000414 width = colorAttachment->getWidth();
415 height = colorAttachment->getHeight();
416 samples = colorAttachment->getSamples();
Geoff Lang5d601382014-07-22 15:14:06 -0400417 colorbufferSize = formatInfo.pixelBytes;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000418 missingAttachment = false;
419 }
420 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000421 }
422
Jamie Madillaed081c2015-04-21 13:55:21 +0000423 const FramebufferAttachment *depthAttachment = mData.mDepthAttachment;
424 if (depthAttachment != nullptr)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000425 {
Jamie Madillaed081c2015-04-21 13:55:21 +0000426 if (depthAttachment->getWidth() == 0 || depthAttachment->getHeight() == 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000427 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000428 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000429 }
430
Jamie Madillaed081c2015-04-21 13:55:21 +0000431 GLenum internalformat = depthAttachment->getInternalFormat();
Jamie Madill48faf802014-11-06 15:27:22 -0500432 const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400433 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madillaed081c2015-04-21 13:55:21 +0000434 if (depthAttachment->type() == GL_TEXTURE)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000435 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000436 // depth texture attachments require OES/ANGLE_depth_texture
Jamie Madill48faf802014-11-06 15:27:22 -0500437 if (!data.extensions->depthTextures)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000438 {
439 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
440 }
441
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400442 if (!formatCaps.renderable)
Geoff Langcec35902014-04-16 10:52:36 -0400443 {
444 return GL_FRAMEBUFFER_UNSUPPORTED;
445 }
446
Geoff Lang5d601382014-07-22 15:14:06 -0400447 if (formatInfo.depthBits == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000448 {
449 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
450 }
451 }
Jamie Madillaed081c2015-04-21 13:55:21 +0000452 else if (depthAttachment->type() == GL_RENDERBUFFER)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000453 {
Geoff Lang5d601382014-07-22 15:14:06 -0400454 if (!formatCaps.renderable || formatInfo.depthBits == 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400455 {
456 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
457 }
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000458 }
459
460 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000461 {
Jamie Madillaed081c2015-04-21 13:55:21 +0000462 width = depthAttachment->getWidth();
463 height = depthAttachment->getHeight();
464 samples = depthAttachment->getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000465 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000466 }
Jamie Madillaed081c2015-04-21 13:55:21 +0000467 else if (width != depthAttachment->getWidth() || height != depthAttachment->getHeight())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000468 {
469 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
470 }
Jamie Madillaed081c2015-04-21 13:55:21 +0000471 else if (samples != depthAttachment->getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000472 {
473 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
474 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000475 }
476
Jamie Madillaed081c2015-04-21 13:55:21 +0000477 const FramebufferAttachment *stencilAttachment = mData.mStencilAttachment;
478 if (stencilAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000479 {
Jamie Madillaed081c2015-04-21 13:55:21 +0000480 if (stencilAttachment->getWidth() == 0 || stencilAttachment->getHeight() == 0)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000481 {
482 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
483 }
484
Jamie Madillaed081c2015-04-21 13:55:21 +0000485 GLenum internalformat = stencilAttachment->getInternalFormat();
Jamie Madill48faf802014-11-06 15:27:22 -0500486 const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400487 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madillaed081c2015-04-21 13:55:21 +0000488 if (stencilAttachment->type() == GL_TEXTURE)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000489 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000490 // texture stencil attachments come along as part
491 // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
Jamie Madill48faf802014-11-06 15:27:22 -0500492 if (!data.extensions->depthTextures)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000493 {
494 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
495 }
496
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400497 if (!formatCaps.renderable)
Geoff Langcec35902014-04-16 10:52:36 -0400498 {
499 return GL_FRAMEBUFFER_UNSUPPORTED;
500 }
501
Geoff Lang5d601382014-07-22 15:14:06 -0400502 if (formatInfo.stencilBits == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000503 {
504 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
505 }
506 }
Jamie Madillaed081c2015-04-21 13:55:21 +0000507 else if (stencilAttachment->type() == GL_RENDERBUFFER)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000508 {
Geoff Lang5d601382014-07-22 15:14:06 -0400509 if (!formatCaps.renderable || formatInfo.stencilBits == 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400510 {
511 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
512 }
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000513 }
514
515 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000516 {
Jamie Madillaed081c2015-04-21 13:55:21 +0000517 width = stencilAttachment->getWidth();
518 height = stencilAttachment->getHeight();
519 samples = stencilAttachment->getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000520 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000521 }
Jamie Madillaed081c2015-04-21 13:55:21 +0000522 else if (width != stencilAttachment->getWidth() || height != stencilAttachment->getHeight())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000523 {
524 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
525 }
Jamie Madillaed081c2015-04-21 13:55:21 +0000526 else if (samples != stencilAttachment->getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000527 {
528 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
529 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000530 }
531
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000532 // if we have both a depth and stencil buffer, they must refer to the same object
533 // since we only support packed_depth_stencil and not separate depth and stencil
Jamie Madillaed081c2015-04-21 13:55:21 +0000534 if (depthAttachment && stencilAttachment && !hasValidDepthStencil())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000535 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000536 return GL_FRAMEBUFFER_UNSUPPORTED;
537 }
538
539 // we need to have at least one attachment to be complete
540 if (missingAttachment)
541 {
542 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000543 }
544
Geoff Lang748f74e2014-12-01 11:25:34 -0500545 return mImpl->checkStatus();
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000546}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000547
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500548Error Framebuffer::invalidate(size_t count, const GLenum *attachments)
Jamie Madill2d96b9e2014-08-29 15:46:47 -0400549{
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500550 return mImpl->invalidate(count, attachments);
Jamie Madill2d96b9e2014-08-29 15:46:47 -0400551}
552
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500553Error Framebuffer::invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area)
Jamie Madill400a4412014-08-29 15:46:45 -0400554{
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500555 return mImpl->invalidateSub(count, attachments, area);
Jamie Madill400a4412014-08-29 15:46:45 -0400556}
557
Jamie Madilld1f5ef22015-04-01 14:17:06 -0400558Error Framebuffer::clear(const gl::Data &data, GLbitfield mask)
Geoff Langb04dc822014-12-01 12:02:02 -0500559{
Jamie Madilld1f5ef22015-04-01 14:17:06 -0400560 return mImpl->clear(data, mask);
Geoff Langb04dc822014-12-01 12:02:02 -0500561}
562
563Error Framebuffer::clearBufferfv(const State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values)
564{
565 return mImpl->clearBufferfv(state, buffer, drawbuffer, values);
566}
567
568Error Framebuffer::clearBufferuiv(const State &state, GLenum buffer, GLint drawbuffer, const GLuint *values)
569{
570 return mImpl->clearBufferuiv(state, buffer, drawbuffer, values);
571}
572
573Error Framebuffer::clearBufferiv(const State &state, GLenum buffer, GLint drawbuffer, const GLint *values)
574{
575 return mImpl->clearBufferiv(state, buffer, drawbuffer, values);
576}
577
578Error Framebuffer::clearBufferfi(const State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
579{
580 return mImpl->clearBufferfi(state, buffer, drawbuffer, depth, stencil);
581}
582
Geoff Langbce529e2014-12-01 12:48:41 -0500583GLenum Framebuffer::getImplementationColorReadFormat() const
584{
585 return mImpl->getImplementationColorReadFormat();
586}
587
588GLenum Framebuffer::getImplementationColorReadType() const
589{
590 return mImpl->getImplementationColorReadType();
591}
592
593Error Framebuffer::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const
594{
595 return mImpl->readPixels(state, area, format, type, pixels);
596}
597
Geoff Lang54bd5a42014-12-01 12:51:04 -0500598Error Framebuffer::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
599 GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer)
600{
601 return mImpl->blit(state, sourceArea, destArea, mask, filter, sourceFramebuffer);
602}
603
Jamie Madill48faf802014-11-06 15:27:22 -0500604int Framebuffer::getSamples(const gl::Data &data) const
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000605{
Geoff Lang748f74e2014-12-01 11:25:34 -0500606 if (checkStatus(data) == GL_FRAMEBUFFER_COMPLETE)
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000607 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000608 // for a complete framebuffer, all attachments must have the same sample count
609 // in this case return the first nonzero sample size
Jamie Madillaed081c2015-04-21 13:55:21 +0000610 for (const FramebufferAttachment *colorAttachment : mData.mColorAttachments)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000611 {
Jamie Madillaed081c2015-04-21 13:55:21 +0000612 if (colorAttachment != nullptr)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000613 {
Jamie Madillaed081c2015-04-21 13:55:21 +0000614 return colorAttachment->getSamples();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000615 }
616 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000617 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000618
619 return 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000620}
621
Jamie Madille261b442014-06-25 12:42:21 -0400622bool Framebuffer::hasValidDepthStencil() const
623{
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400624 return mData.getDepthStencilAttachment() != nullptr;
Jamie Madille261b442014-06-25 12:42:21 -0400625}
626
Jamie Madillaed081c2015-04-21 13:55:21 +0000627void Framebuffer::setTextureAttachment(GLenum attachment, Texture *texture, const ImageIndex &imageIndex)
Geoff Langab75a052014-10-15 12:56:37 -0400628{
Jamie Madillaed081c2015-04-21 13:55:21 +0000629 setAttachment(attachment, new FramebufferAttachment(GL_TEXTURE, attachment, imageIndex, texture));
630}
631
632void Framebuffer::setRenderbufferAttachment(GLenum attachment, Renderbuffer *renderbuffer)
633{
634 setAttachment(attachment, new FramebufferAttachment(GL_RENDERBUFFER, attachment, ImageIndex::MakeInvalid(), renderbuffer));
635}
636
637void Framebuffer::setNULLAttachment(GLenum attachment)
638{
639 setAttachment(attachment, NULL);
640}
641
642void Framebuffer::setAttachment(GLenum attachment, FramebufferAttachment *attachmentObj)
643{
644 if (attachment >= GL_COLOR_ATTACHMENT0 && attachment < (GL_COLOR_ATTACHMENT0 + mData.mColorAttachments.size()))
Geoff Langab75a052014-10-15 12:56:37 -0400645 {
Jamie Madillaed081c2015-04-21 13:55:21 +0000646 size_t colorAttachment = attachment - GL_COLOR_ATTACHMENT0;
647 SafeDelete(mData.mColorAttachments[colorAttachment]);
648 mData.mColorAttachments[colorAttachment] = attachmentObj;
649 mImpl->setColorAttachment(colorAttachment, attachmentObj);
650 }
651 else if (attachment == GL_BACK)
652 {
653 SafeDelete(mData.mColorAttachments[0]);
654 mData.mColorAttachments[0] = attachmentObj;
655 mImpl->setColorAttachment(0, attachmentObj);
656 }
657 else if (attachment == GL_DEPTH_ATTACHMENT || attachment == GL_DEPTH)
658 {
659 SafeDelete(mData.mDepthAttachment);
660 mData.mDepthAttachment = attachmentObj;
661 mImpl->setDepthAttachment(attachmentObj);
662 }
663 else if (attachment == GL_STENCIL_ATTACHMENT || attachment == GL_STENCIL)
664 {
665 SafeDelete(mData.mStencilAttachment);
666 mData.mStencilAttachment = attachmentObj;
667 mImpl->setStencilAttachment(attachmentObj);
668 }
669 else if (attachment == GL_DEPTH_STENCIL_ATTACHMENT || attachment == GL_DEPTH_STENCIL)
670 {
671 SafeDelete(mData.mDepthAttachment);
672 SafeDelete(mData.mStencilAttachment);
673
Geoff Langab75a052014-10-15 12:56:37 -0400674 // ensure this is a legitimate depth+stencil format
Jamie Madillaed081c2015-04-21 13:55:21 +0000675 if (attachmentObj && attachmentObj->getDepthSize() > 0 && attachmentObj->getStencilSize() > 0)
Geoff Langab75a052014-10-15 12:56:37 -0400676 {
Jamie Madillaed081c2015-04-21 13:55:21 +0000677 mData.mDepthAttachment = attachmentObj;
678 mImpl->setDepthAttachment(attachmentObj);
679
680 // Make a new attachment object to ensure we do not double-delete
681 // See angle issue 686
682 if (attachmentObj->type() == GL_TEXTURE)
683 {
684 mData.mStencilAttachment = new FramebufferAttachment(GL_TEXTURE,
685 GL_DEPTH_STENCIL_ATTACHMENT,
686 attachmentObj->getTextureImageIndex(),
687 attachmentObj->getTexture());
688 mImpl->setStencilAttachment(mData.mStencilAttachment);
689 }
690 else if (attachmentObj->type() == GL_RENDERBUFFER)
691 {
692 mData.mStencilAttachment = new FramebufferAttachment(GL_RENDERBUFFER,
693 GL_DEPTH_STENCIL_ATTACHMENT,
694 ImageIndex::MakeInvalid(),
695 attachmentObj->getRenderbuffer());
696 mImpl->setStencilAttachment(mData.mStencilAttachment);
697 }
698 else
699 {
700 UNREACHABLE();
701 }
Geoff Langab75a052014-10-15 12:56:37 -0400702 }
703 }
704 else
705 {
Jamie Madillaed081c2015-04-21 13:55:21 +0000706 UNREACHABLE();
Geoff Langab75a052014-10-15 12:56:37 -0400707 }
708}
709
Jamie Madill48115b62015-03-16 10:46:57 -0400710DefaultFramebuffer::DefaultFramebuffer(const Caps &caps, rx::ImplFactory *factory, egl::Surface *surface)
711 : Framebuffer(caps, factory, 0)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000712{
Jamie Madillc46f45d2015-03-31 13:20:55 -0400713 const egl::Config *config = surface->getConfig();
Jamie Madilld1405e52015-03-05 15:41:39 -0500714
Jamie Madillaed081c2015-04-21 13:55:21 +0000715 setAttachment(GL_BACK, new FramebufferAttachment(GL_FRAMEBUFFER_DEFAULT, GL_BACK, ImageIndex::MakeInvalid(), surface));
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000716
Jamie Madillc46f45d2015-03-31 13:20:55 -0400717 if (config->depthSize > 0)
Jamie Madille92a3542014-07-03 10:38:58 -0400718 {
Jamie Madillaed081c2015-04-21 13:55:21 +0000719 setAttachment(GL_DEPTH, new FramebufferAttachment(GL_FRAMEBUFFER_DEFAULT, GL_DEPTH, ImageIndex::MakeInvalid(), surface));
Jamie Madille92a3542014-07-03 10:38:58 -0400720 }
Jamie Madillc46f45d2015-03-31 13:20:55 -0400721 if (config->stencilSize > 0)
Geoff Lang528ce3c2014-12-01 10:44:07 -0500722 {
Jamie Madillaed081c2015-04-21 13:55:21 +0000723 setAttachment(GL_STENCIL, new FramebufferAttachment(GL_FRAMEBUFFER_DEFAULT, GL_STENCIL, ImageIndex::MakeInvalid(), surface));
Geoff Lang528ce3c2014-12-01 10:44:07 -0500724 }
725
Geoff Lang9dd95802014-12-01 11:12:59 -0500726 GLenum drawBufferState = GL_BACK;
727 setDrawBuffers(1, &drawBufferState);
728
729 setReadBuffer(GL_BACK);
Jamie Madille92a3542014-07-03 10:38:58 -0400730}
731
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000732}