blob: a5f8087102f3c969c5ffa30f430bf56cda7beb14 [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
Jamie Madill48ef11b2016-04-27 15:21:52 -040042FramebufferState::FramebufferState()
Geoff Lang70d0f492015-12-10 17:45:46 -050043 : mLabel(),
44 mColorAttachments(1),
Corentin Wallez37c39792015-08-20 14:19:46 -040045 mDrawBufferStates(1, GL_NONE),
46 mReadBufferState(GL_COLOR_ATTACHMENT0_EXT)
47{
48 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
49}
50
Jamie Madill48ef11b2016-04-27 15:21:52 -040051FramebufferState::FramebufferState(const Caps &caps)
Geoff Lang70d0f492015-12-10 17:45:46 -050052 : mLabel(),
53 mColorAttachments(caps.maxColorAttachments),
Jamie Madilld1405e52015-03-05 15:41:39 -050054 mDrawBufferStates(caps.maxDrawBuffers, GL_NONE),
55 mReadBufferState(GL_COLOR_ATTACHMENT0_EXT)
56{
Geoff Langa15472a2015-08-11 11:48:03 -040057 ASSERT(mDrawBufferStates.size() > 0);
Jamie Madilld1405e52015-03-05 15:41:39 -050058 mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
59}
60
Jamie Madill48ef11b2016-04-27 15:21:52 -040061FramebufferState::~FramebufferState()
Jamie Madilld1405e52015-03-05 15:41:39 -050062{
Jamie Madilld1405e52015-03-05 15:41:39 -050063}
64
Jamie Madill48ef11b2016-04-27 15:21:52 -040065const std::string &FramebufferState::getLabel()
Geoff Lang70d0f492015-12-10 17:45:46 -050066{
67 return mLabel;
68}
69
Jamie Madill48ef11b2016-04-27 15:21:52 -040070const FramebufferAttachment *FramebufferState::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 Madill48ef11b2016-04-27 15:21:52 -040078const FramebufferAttachment *FramebufferState::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 Madill48ef11b2016-04-27 15:21:52 -040091const FramebufferAttachment *FramebufferState::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
Jamie Madill48ef11b2016-04-27 15:21:52 -0400104const FramebufferAttachment *FramebufferState::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 Madill48ef11b2016-04-27 15:21:52 -0400112const FramebufferAttachment *FramebufferState::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 Madill48ef11b2016-04-27 15:21:52 -0400117const FramebufferAttachment *FramebufferState::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 Madill48ef11b2016-04-27 15:21:52 -0400122const FramebufferAttachment *FramebufferState::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 Madill48ef11b2016-04-27 15:21:52 -0400136bool FramebufferState::attachmentsHaveSameDimensions() const
Jamie Madillcc86d642015-11-24 13:00:07 -0500137{
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)
Jamie Madill48ef11b2016-04-27 15:21:52 -0400173 : mState(caps), mImpl(factory->createFramebuffer(mState)), 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)
Jamie Madill48ef11b2016-04-27 15:21:52 -0400180 : mState(), mImpl(surface->createDefaultFramebuffer(mState)), mId(0)
Corentin Wallez37c39792015-08-20 14:19:46 -0400181{
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{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400192 mState.mLabel = label;
Geoff Lang70d0f492015-12-10 17:45:46 -0500193}
194
195const std::string &Framebuffer::getLabel() const
196{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400197 return mState.mLabel;
Geoff Lang70d0f492015-12-10 17:45:46 -0500198}
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{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400212 for (auto &colorAttachment : mState.mColorAttachments)
Jamie Madilld1405e52015-03-05 15:41:39 -0500213 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400214 DetachMatchingAttachment(&colorAttachment, resourceType, resourceId);
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000215 }
216
Jamie Madill48ef11b2016-04-27 15:21:52 -0400217 DetachMatchingAttachment(&mState.mDepthAttachment, resourceType, resourceId);
218 DetachMatchingAttachment(&mState.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 Madill48ef11b2016-04-27 15:21:52 -0400223 return mState.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 Madill48ef11b2016-04-27 15:21:52 -0400228 return mState.getDepthAttachment();
Geoff Lang646559f2013-08-15 11:08:15 -0400229}
230
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400231const FramebufferAttachment *Framebuffer::getStencilbuffer() const
232{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400233 return mState.getStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400234}
235
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400236const FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
237{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400238 return mState.getDepthStencilAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400239}
240
241const FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
daniel@transgaming.comd2b47022012-11-28 19:40:10 +0000242{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400243 return mState.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 Madill48ef11b2016-04-27 15:21:52 -0400248 return mState.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 Madill48ef11b2016-04-27 15:21:52 -0400253 const FramebufferAttachment *readAttachment = mState.getReadAttachment();
Jamie Madillb6bda4a2015-04-20 12:53:26 -0400254 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 Madill48ef11b2016-04-27 15:21:52 -0400259 return mState.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 Madill48ef11b2016-04-27 15:21:52 -0400266 return mState.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 Madill48ef11b2016-04-27 15:21:52 -0400274 return mState.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 Madill48ef11b2016-04-27 15:21:52 -0400277 return mState.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 Madill48ef11b2016-04-27 15:21:52 -0400280 return mState.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{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400293 return mState.mDrawBufferStates.size();
Geoff Langa15472a2015-08-11 11:48:03 -0400294}
295
296GLenum Framebuffer::getDrawBufferState(size_t drawBuffer) const
297{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400298 ASSERT(drawBuffer < mState.mDrawBufferStates.size());
299 return mState.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{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400304 return mState.getDrawBufferStates();
Jamie Madill1fbc59f2016-02-24 15:25:51 -0500305}
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 Madill48ef11b2016-04-27 15:21:52 -0400309 auto &drawStates = mState.mDrawBufferStates;
Jamie Madilld1405e52015-03-05 15:41:39 -0500310
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{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400319 ASSERT(drawBuffer < mState.mDrawBufferStates.size());
320 if (mState.mDrawBufferStates[drawBuffer] != GL_NONE)
Geoff Langa15472a2015-08-11 11:48:03 -0400321 {
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"
Jamie Madill48ef11b2016-04-27 15:21:52 -0400324 ASSERT(mState.mDrawBufferStates[drawBuffer] == GL_COLOR_ATTACHMENT0 + drawBuffer ||
325 (drawBuffer == 0 && mState.mDrawBufferStates[drawBuffer] == GL_BACK));
326 return getAttachment(mState.mDrawBufferStates[drawBuffer]);
Geoff Langa15472a2015-08-11 11:48:03 -0400327 }
328 else
329 {
330 return nullptr;
331 }
332}
333
334bool Framebuffer::hasEnabledDrawBuffer() const
335{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400336 for (size_t drawbufferIdx = 0; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
Geoff Langa15472a2015-08-11 11:48:03 -0400337 {
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 Madill48ef11b2016-04-27 15:21:52 -0400349 return mState.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 Madill48ef11b2016-04-27 15:21:52 -0400356 (buffer - GL_COLOR_ATTACHMENT0) < mState.mColorAttachments.size()));
357 mState.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{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400363 return mState.mColorAttachments.size();
Corentin Wallez37c39792015-08-20 14:19:46 -0400364}
365
Jamie Madill0df8fe42015-11-24 16:10:24 -0500366bool Framebuffer::hasDepth() const
367{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400368 return (mState.mDepthAttachment.isAttached() && mState.mDepthAttachment.getDepthSize() > 0);
Jamie Madill0df8fe42015-11-24 16:10:24 -0500369}
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 Madill48ef11b2016-04-27 15:21:52 -0400373 return (mState.mStencilAttachment.isAttached() &&
374 mState.mStencilAttachment.getStencilSize() > 0);
daniel@transgaming.coma27ff1e2010-08-24 19:20:11 +0000375}
376
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000377bool Framebuffer::usingExtendedDrawBuffers() const
378{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400379 for (size_t drawbufferIdx = 1; drawbufferIdx < mState.mDrawBufferStates.size(); ++drawbufferIdx)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000380 {
Geoff Langa15472a2015-08-11 11:48:03 -0400381 if (getDrawBuffer(drawbufferIdx) != nullptr)
shannonwoods@chromium.org24ac8502013-05-30 00:01:37 +0000382 {
383 return true;
384 }
385 }
386
387 return false;
388}
389
Jamie Madill9082b982016-04-27 15:21:51 -0400390GLenum Framebuffer::checkStatus(const ContextState &data) const
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000391{
Geoff Lang528ce3c2014-12-01 10:44:07 -0500392 // The default framebuffer *must* always be complete, though it may not be
393 // subject to the same rules as application FBOs. ie, it could have 0x0 size.
394 if (mId == 0)
395 {
396 return GL_FRAMEBUFFER_COMPLETE;
397 }
398
shannonwoods@chromium.orgf6fb9592013-05-30 00:09:40 +0000399 unsigned int colorbufferSize = 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000400 int samples = -1;
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000401 bool missingAttachment = true;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000402
Jamie Madill48ef11b2016-04-27 15:21:52 -0400403 for (const FramebufferAttachment &colorAttachment : mState.mColorAttachments)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000404 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400405 if (colorAttachment.isAttached())
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000406 {
Jamie Madill6b120b92015-11-24 13:00:07 -0500407 const Extents &size = colorAttachment.getSize();
408 if (size.width == 0 || size.height == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000409 {
410 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
411 }
daniel@transgaming.com01868132010-08-24 19:21:17 +0000412
Jamie Madill2d06b732015-04-20 12:53:28 -0400413 GLenum internalformat = colorAttachment.getInternalFormat();
Jamie Madill48faf802014-11-06 15:27:22 -0500414 const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400415 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill2d06b732015-04-20 12:53:28 -0400416 if (colorAttachment.type() == GL_TEXTURE)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000417 {
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400418 if (!formatCaps.renderable)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000419 {
Jamie Madill81176782015-11-24 16:10:23 -0500420 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000421 }
422
Geoff Lang5d601382014-07-22 15:14:06 -0400423 if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000424 {
425 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
426 }
Jamie Madill6b120b92015-11-24 13:00:07 -0500427
428 if (colorAttachment.layer() >= size.depth)
429 {
430 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
431 }
Jamie Madill3215b202015-12-15 16:41:39 -0500432
433 // ES3 specifies that cube map texture attachments must be cube complete.
434 // This language is missing from the ES2 spec, but we enforce it here because some
435 // desktop OpenGL drivers also enforce this validation.
436 // TODO(jmadill): Check if OpenGL ES2 drivers enforce cube completeness.
437 const Texture *texture = colorAttachment.getTexture();
438 ASSERT(texture);
439 if (texture->getTarget() == GL_TEXTURE_CUBE_MAP && !texture->isCubeComplete())
440 {
441 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
442 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000443 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400444 else if (colorAttachment.type() == GL_RENDERBUFFER)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000445 {
Geoff Lang5d601382014-07-22 15:14:06 -0400446 if (!formatCaps.renderable || formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400447 {
448 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
449 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000450 }
451
452 if (!missingAttachment)
453 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000454 // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
455 // all color attachments have the same number of samples for the FBO to be complete.
Jamie Madill2d06b732015-04-20 12:53:28 -0400456 if (colorAttachment.getSamples() != samples)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000457 {
458 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
459 }
460
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000461 // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
462 // in GLES 3.0, there is no such restriction
Jamie Madill48faf802014-11-06 15:27:22 -0500463 if (data.clientVersion < 3)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000464 {
Geoff Lang5d601382014-07-22 15:14:06 -0400465 if (formatInfo.pixelBytes != colorbufferSize)
shannon.woods%transgaming.com@gtempaccount.comc3471522013-04-13 03:34:52 +0000466 {
467 return GL_FRAMEBUFFER_UNSUPPORTED;
468 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000469 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000470 }
471 else
472 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400473 samples = colorAttachment.getSamples();
Geoff Lang5d601382014-07-22 15:14:06 -0400474 colorbufferSize = formatInfo.pixelBytes;
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000475 missingAttachment = false;
476 }
477 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000478 }
479
Jamie Madill48ef11b2016-04-27 15:21:52 -0400480 const FramebufferAttachment &depthAttachment = mState.mDepthAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -0400481 if (depthAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000482 {
Jamie Madill6b120b92015-11-24 13:00:07 -0500483 const Extents &size = depthAttachment.getSize();
484 if (size.width == 0 || size.height == 0)
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000485 {
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000486 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000487 }
488
Jamie Madill2d06b732015-04-20 12:53:28 -0400489 GLenum internalformat = depthAttachment.getInternalFormat();
Jamie Madill48faf802014-11-06 15:27:22 -0500490 const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400491 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill2d06b732015-04-20 12:53:28 -0400492 if (depthAttachment.type() == GL_TEXTURE)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000493 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000494 // depth texture attachments require OES/ANGLE_depth_texture
Jamie Madill48faf802014-11-06 15:27:22 -0500495 if (!data.extensions->depthTextures)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000496 {
497 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
498 }
499
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400500 if (!formatCaps.renderable)
Geoff Langcec35902014-04-16 10:52:36 -0400501 {
Jamie Madill81176782015-11-24 16:10:23 -0500502 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
Geoff Langcec35902014-04-16 10:52:36 -0400503 }
504
Geoff Lang5d601382014-07-22 15:14:06 -0400505 if (formatInfo.depthBits == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000506 {
507 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
508 }
509 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400510 else if (depthAttachment.type() == GL_RENDERBUFFER)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000511 {
Geoff Lang5d601382014-07-22 15:14:06 -0400512 if (!formatCaps.renderable || formatInfo.depthBits == 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400513 {
514 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
515 }
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000516 }
517
518 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000519 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400520 samples = depthAttachment.getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000521 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000522 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400523 else if (samples != depthAttachment.getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000524 {
525 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
526 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000527 }
528
Jamie Madill48ef11b2016-04-27 15:21:52 -0400529 const FramebufferAttachment &stencilAttachment = mState.mStencilAttachment;
Jamie Madill2d06b732015-04-20 12:53:28 -0400530 if (stencilAttachment.isAttached())
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000531 {
Jamie Madill6b120b92015-11-24 13:00:07 -0500532 const Extents &size = stencilAttachment.getSize();
533 if (size.width == 0 || size.height == 0)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000534 {
535 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
536 }
537
Jamie Madill2d06b732015-04-20 12:53:28 -0400538 GLenum internalformat = stencilAttachment.getInternalFormat();
Jamie Madill48faf802014-11-06 15:27:22 -0500539 const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
Geoff Lang5d601382014-07-22 15:14:06 -0400540 const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
Jamie Madill2d06b732015-04-20 12:53:28 -0400541 if (stencilAttachment.type() == GL_TEXTURE)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000542 {
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000543 // texture stencil attachments come along as part
544 // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
Jamie Madill48faf802014-11-06 15:27:22 -0500545 if (!data.extensions->depthTextures)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000546 {
547 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
548 }
549
Geoff Lang6cf8e1b2014-07-03 13:03:57 -0400550 if (!formatCaps.renderable)
Geoff Langcec35902014-04-16 10:52:36 -0400551 {
Jamie Madill81176782015-11-24 16:10:23 -0500552 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
Geoff Langcec35902014-04-16 10:52:36 -0400553 }
554
Geoff Lang5d601382014-07-22 15:14:06 -0400555 if (formatInfo.stencilBits == 0)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000556 {
557 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
558 }
559 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400560 else if (stencilAttachment.type() == GL_RENDERBUFFER)
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000561 {
Geoff Lang5d601382014-07-22 15:14:06 -0400562 if (!formatCaps.renderable || formatInfo.stencilBits == 0)
Jamie Madillbb94f342014-06-23 15:23:02 -0400563 {
564 return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
565 }
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000566 }
567
568 if (missingAttachment)
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000569 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400570 samples = stencilAttachment.getSamples();
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000571 missingAttachment = false;
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000572 }
Jamie Madill2d06b732015-04-20 12:53:28 -0400573 else if (samples != stencilAttachment.getSamples())
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000574 {
575 return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
576 }
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000577 }
578
daniel@transgaming.com6b7c84c2012-05-31 01:14:39 +0000579 // we need to have at least one attachment to be complete
580 if (missingAttachment)
581 {
582 return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
daniel@transgaming.comcdacc8e2010-07-28 19:20:50 +0000583 }
584
Jamie Madillcc86d642015-11-24 13:00:07 -0500585 // In ES 2.0, all color attachments must have the same width and height.
586 // In ES 3.0, there is no such restriction.
Jamie Madill48ef11b2016-04-27 15:21:52 -0400587 if (data.clientVersion < 3 && !mState.attachmentsHaveSameDimensions())
Jamie Madillcc86d642015-11-24 13:00:07 -0500588 {
589 return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
590 }
591
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500592 syncState();
Jamie Madillcc86d642015-11-24 13:00:07 -0500593 if (!mImpl->checkStatus())
594 {
595 return GL_FRAMEBUFFER_UNSUPPORTED;
596 }
597
598 return GL_FRAMEBUFFER_COMPLETE;
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000599}
daniel@transgaming.com9ecb9f92010-07-28 19:21:12 +0000600
Austin Kinross08332632015-05-05 13:35:47 -0700601Error Framebuffer::discard(size_t count, const GLenum *attachments)
602{
603 return mImpl->discard(count, attachments);
604}
605
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500606Error Framebuffer::invalidate(size_t count, const GLenum *attachments)
Jamie Madill2d96b9e2014-08-29 15:46:47 -0400607{
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500608 return mImpl->invalidate(count, attachments);
Jamie Madill2d96b9e2014-08-29 15:46:47 -0400609}
610
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500611Error Framebuffer::invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area)
Jamie Madill400a4412014-08-29 15:46:45 -0400612{
Geoff Lang9ad4bda2014-12-01 11:03:09 -0500613 return mImpl->invalidateSub(count, attachments, area);
Jamie Madill400a4412014-08-29 15:46:45 -0400614}
615
Jamie Madill9082b982016-04-27 15:21:51 -0400616Error Framebuffer::clear(const ContextState &data, GLbitfield mask)
Geoff Langb04dc822014-12-01 12:02:02 -0500617{
Jamie Madillc29968b2016-01-20 11:17:23 -0500618 if (data.state->isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500619 {
620 return gl::Error(GL_NO_ERROR);
621 }
622
Jamie Madillc29968b2016-01-20 11:17:23 -0500623 return mImpl->clear(data, mask);
Geoff Langb04dc822014-12-01 12:02:02 -0500624}
625
Jamie Madill9082b982016-04-27 15:21:51 -0400626Error Framebuffer::clearBufferfv(const ContextState &data,
Jamie Madill1b94d432015-08-07 13:23:23 -0400627 GLenum buffer,
628 GLint drawbuffer,
629 const GLfloat *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500630{
Jamie Madillc29968b2016-01-20 11:17:23 -0500631 if (data.state->isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500632 {
633 return gl::Error(GL_NO_ERROR);
634 }
635
Jamie Madillc29968b2016-01-20 11:17:23 -0500636 return mImpl->clearBufferfv(data, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500637}
638
Jamie Madill9082b982016-04-27 15:21:51 -0400639Error Framebuffer::clearBufferuiv(const ContextState &data,
Jamie Madill1b94d432015-08-07 13:23:23 -0400640 GLenum buffer,
641 GLint drawbuffer,
642 const GLuint *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500643{
Jamie Madillc29968b2016-01-20 11:17:23 -0500644 if (data.state->isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500645 {
646 return gl::Error(GL_NO_ERROR);
647 }
648
Jamie Madillc29968b2016-01-20 11:17:23 -0500649 return mImpl->clearBufferuiv(data, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500650}
651
Jamie Madill9082b982016-04-27 15:21:51 -0400652Error Framebuffer::clearBufferiv(const ContextState &data,
Jamie Madill1b94d432015-08-07 13:23:23 -0400653 GLenum buffer,
654 GLint drawbuffer,
655 const GLint *values)
Geoff Langb04dc822014-12-01 12:02:02 -0500656{
Jamie Madillc29968b2016-01-20 11:17:23 -0500657 if (data.state->isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500658 {
659 return gl::Error(GL_NO_ERROR);
660 }
661
Jamie Madillc29968b2016-01-20 11:17:23 -0500662 return mImpl->clearBufferiv(data, buffer, drawbuffer, values);
Geoff Langb04dc822014-12-01 12:02:02 -0500663}
664
Jamie Madill9082b982016-04-27 15:21:51 -0400665Error Framebuffer::clearBufferfi(const ContextState &data,
Jamie Madill1b94d432015-08-07 13:23:23 -0400666 GLenum buffer,
667 GLint drawbuffer,
668 GLfloat depth,
669 GLint stencil)
Geoff Langb04dc822014-12-01 12:02:02 -0500670{
Jamie Madillc29968b2016-01-20 11:17:23 -0500671 if (data.state->isRasterizerDiscardEnabled())
Jamie Madill984ef412015-11-24 16:10:21 -0500672 {
673 return gl::Error(GL_NO_ERROR);
674 }
675
Jamie Madillc29968b2016-01-20 11:17:23 -0500676 return mImpl->clearBufferfi(data, buffer, drawbuffer, depth, stencil);
Geoff Langb04dc822014-12-01 12:02:02 -0500677}
678
Geoff Langbce529e2014-12-01 12:48:41 -0500679GLenum Framebuffer::getImplementationColorReadFormat() const
680{
681 return mImpl->getImplementationColorReadFormat();
682}
683
684GLenum Framebuffer::getImplementationColorReadType() const
685{
686 return mImpl->getImplementationColorReadType();
687}
688
Jamie Madillc29968b2016-01-20 11:17:23 -0500689Error Framebuffer::readPixels(const State &state,
690 const Rectangle &area,
Jamie Madill1b94d432015-08-07 13:23:23 -0400691 GLenum format,
692 GLenum type,
693 GLvoid *pixels) const
Geoff Langbce529e2014-12-01 12:48:41 -0500694{
Geoff Lang520c4ae2015-05-05 13:12:36 -0400695 Error error = mImpl->readPixels(state, area, format, type, pixels);
696 if (error.isError())
697 {
698 return error;
699 }
700
701 Buffer *unpackBuffer = state.getUnpackState().pixelBuffer.get();
702 if (unpackBuffer)
703 {
704 unpackBuffer->onPixelUnpack();
705 }
706
707 return Error(GL_NO_ERROR);
Geoff Langbce529e2014-12-01 12:48:41 -0500708}
709
Jamie Madillc29968b2016-01-20 11:17:23 -0500710Error Framebuffer::blit(const State &state,
711 const Rectangle &sourceArea,
712 const Rectangle &destArea,
Geoff Lang242468f2015-09-24 14:15:41 -0400713 GLbitfield mask,
714 GLenum filter,
Jamie Madillc29968b2016-01-20 11:17:23 -0500715 const Framebuffer *sourceFramebuffer)
Geoff Lang54bd5a42014-12-01 12:51:04 -0500716{
717 return mImpl->blit(state, sourceArea, destArea, mask, filter, sourceFramebuffer);
718}
719
Jamie Madill9082b982016-04-27 15:21:51 -0400720int Framebuffer::getSamples(const ContextState &data) const
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000721{
Geoff Lang748f74e2014-12-01 11:25:34 -0500722 if (checkStatus(data) == GL_FRAMEBUFFER_COMPLETE)
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000723 {
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000724 // for a complete framebuffer, all attachments must have the same sample count
725 // in this case return the first nonzero sample size
Jamie Madill48ef11b2016-04-27 15:21:52 -0400726 for (const FramebufferAttachment &colorAttachment : mState.mColorAttachments)
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000727 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400728 if (colorAttachment.isAttached())
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000729 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400730 return colorAttachment.getSamples();
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000731 }
732 }
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000733 }
shannon.woods%transgaming.com@gtempaccount.comf30ccc22013-04-13 03:28:36 +0000734
735 return 0;
daniel@transgaming.com1f135d82010-08-24 19:20:36 +0000736}
737
Jamie Madille261b442014-06-25 12:42:21 -0400738bool Framebuffer::hasValidDepthStencil() const
739{
Jamie Madill48ef11b2016-04-27 15:21:52 -0400740 return mState.getDepthStencilAttachment() != nullptr;
Jamie Madille261b442014-06-25 12:42:21 -0400741}
742
Jamie Madill2d06b732015-04-20 12:53:28 -0400743void Framebuffer::setAttachment(GLenum type,
744 GLenum binding,
745 const ImageIndex &textureIndex,
746 FramebufferAttachmentObject *resource)
Geoff Langab75a052014-10-15 12:56:37 -0400747{
Jamie Madill2d06b732015-04-20 12:53:28 -0400748 if (binding == GL_DEPTH_STENCIL || binding == GL_DEPTH_STENCIL_ATTACHMENT)
Geoff Langab75a052014-10-15 12:56:37 -0400749 {
Geoff Langab75a052014-10-15 12:56:37 -0400750 // ensure this is a legitimate depth+stencil format
Jamie Madill375c37c2015-07-21 15:14:08 -0400751 FramebufferAttachmentObject *attachmentObj = resource;
752 if (resource)
Geoff Langab75a052014-10-15 12:56:37 -0400753 {
Jamie Madill375c37c2015-07-21 15:14:08 -0400754 FramebufferAttachment::Target target(binding, textureIndex);
755 GLenum internalFormat = resource->getAttachmentInternalFormat(target);
756 const InternalFormat &formatInfo = GetInternalFormatInfo(internalFormat);
757 if (formatInfo.depthBits == 0 || formatInfo.stencilBits == 0)
758 {
759 // Attaching nullptr detaches the current attachment.
760 attachmentObj = nullptr;
761 }
Geoff Langab75a052014-10-15 12:56:37 -0400762 }
Jamie Madill375c37c2015-07-21 15:14:08 -0400763
Jamie Madill48ef11b2016-04-27 15:21:52 -0400764 mState.mDepthAttachment.attach(type, binding, textureIndex, attachmentObj);
765 mState.mStencilAttachment.attach(type, binding, textureIndex, attachmentObj);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500766 mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT);
767 mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT);
Geoff Langab75a052014-10-15 12:56:37 -0400768 }
769 else
770 {
Jamie Madill2d06b732015-04-20 12:53:28 -0400771 switch (binding)
772 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500773 case GL_DEPTH:
774 case GL_DEPTH_ATTACHMENT:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400775 mState.mDepthAttachment.attach(type, binding, textureIndex, resource);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500776 mDirtyBits.set(DIRTY_BIT_DEPTH_ATTACHMENT);
Jamie Madill2d06b732015-04-20 12:53:28 -0400777 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500778 case GL_STENCIL:
779 case GL_STENCIL_ATTACHMENT:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400780 mState.mStencilAttachment.attach(type, binding, textureIndex, resource);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500781 mDirtyBits.set(DIRTY_BIT_STENCIL_ATTACHMENT);
Jamie Madill2d06b732015-04-20 12:53:28 -0400782 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500783 case GL_BACK:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400784 mState.mColorAttachments[0].attach(type, binding, textureIndex, resource);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500785 mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0);
Jamie Madill2d06b732015-04-20 12:53:28 -0400786 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500787 default:
Jamie Madill2d06b732015-04-20 12:53:28 -0400788 {
789 size_t colorIndex = binding - GL_COLOR_ATTACHMENT0;
Jamie Madill48ef11b2016-04-27 15:21:52 -0400790 ASSERT(colorIndex < mState.mColorAttachments.size());
791 mState.mColorAttachments[colorIndex].attach(type, binding, textureIndex, resource);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500792 mDirtyBits.set(DIRTY_BIT_COLOR_ATTACHMENT_0 + colorIndex);
Jamie Madill2d06b732015-04-20 12:53:28 -0400793 }
794 break;
795 }
Geoff Langab75a052014-10-15 12:56:37 -0400796 }
797}
798
Jamie Madill2d06b732015-04-20 12:53:28 -0400799void Framebuffer::resetAttachment(GLenum binding)
800{
801 setAttachment(GL_NONE, binding, ImageIndex::MakeInvalid(), nullptr);
802}
803
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500804void Framebuffer::syncState() const
805{
806 if (mDirtyBits.any())
807 {
808 mImpl->syncState(mDirtyBits);
809 mDirtyBits.reset();
810 }
daniel@transgaming.com4f39fd92010-03-08 20:26:45 +0000811}
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500812
813} // namespace gl