blob: c3f78900168578cbad78bc9dc7e3031319835071 [file] [log] [blame]
Geoff Langf9a6f082015-01-22 13:32:49 -05001//
2// Copyright 2015 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// FramebufferGL.cpp: Implements the class methods for FramebufferGL.
8
9#include "libANGLE/renderer/gl/FramebufferGL.h"
10
11#include "common/debug.h"
Jamie Madilld1f5ef22015-04-01 14:17:06 -040012#include "libANGLE/Data.h"
Jamie Madill87de3622015-03-16 10:41:44 -040013#include "libANGLE/State.h"
Geoff Lang4ad17092015-03-10 16:47:44 -040014#include "libANGLE/FramebufferAttachment.h"
15#include "libANGLE/angletypes.h"
16#include "libANGLE/formatutils.h"
17#include "libANGLE/renderer/gl/FunctionsGL.h"
Jacek Cabanfa60f692015-04-27 18:23:44 +020018#include "libANGLE/renderer/gl/RenderbufferGL.h"
Geoff Lang4ad17092015-03-10 16:47:44 -040019#include "libANGLE/renderer/gl/StateManagerGL.h"
20#include "libANGLE/renderer/gl/TextureGL.h"
Geoff Langf9a6f082015-01-22 13:32:49 -050021
22namespace rx
23{
24
Geoff Lang4ad17092015-03-10 16:47:44 -040025FramebufferGL::FramebufferGL(const gl::Framebuffer::Data &data, const FunctionsGL *functions, StateManagerGL *stateManager, bool isDefault)
26 : FramebufferImpl(data),
27 mFunctions(functions),
28 mStateManager(stateManager),
29 mFramebufferID(0)
30{
31 if (!isDefault)
32 {
33 mFunctions->genFramebuffers(1, &mFramebufferID);
34 }
35}
Geoff Langf9a6f082015-01-22 13:32:49 -050036
37FramebufferGL::~FramebufferGL()
Geoff Lang4ad17092015-03-10 16:47:44 -040038{
Geoff Lang1eb708e2015-05-04 14:58:23 -040039 mStateManager->deleteFramebuffer(mFramebufferID);
40 mFramebufferID = 0;
Geoff Lang4ad17092015-03-10 16:47:44 -040041}
42
43static void BindFramebufferAttachment(const FunctionsGL *functions, GLenum attachmentPoint,
44 const gl::FramebufferAttachment *attachment)
45{
46 if (attachment)
47 {
48 if (attachment->type() == GL_TEXTURE)
49 {
Jamie Madill5160ec12015-04-14 08:13:48 -040050 const gl::Texture *texture = attachment->getTexture();
Geoff Lang4ad17092015-03-10 16:47:44 -040051 const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
52
53 if (texture->getTarget() == GL_TEXTURE_2D)
54 {
55 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_2D,
56 textureGL->getTextureID(), attachment->mipLevel());
57 }
58 else if (texture->getTarget() == GL_TEXTURE_CUBE_MAP)
59 {
60 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, attachment->cubeMapFace(),
61 textureGL->getTextureID(), attachment->mipLevel());
62 }
63 else if (texture->getTarget() == GL_TEXTURE_2D_ARRAY || texture->getTarget() == GL_TEXTURE_3D)
64 {
65 functions->framebufferTextureLayer(GL_FRAMEBUFFER, attachmentPoint, textureGL->getTextureID(),
66 attachment->mipLevel(), attachment->layer());
67 }
68 else
69 {
70 UNREACHABLE();
71 }
72 }
73 else if (attachment->type() == GL_RENDERBUFFER)
74 {
Jamie Madill5160ec12015-04-14 08:13:48 -040075 const gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
Geoff Langcd69f1c2015-03-18 14:33:23 -040076 const RenderbufferGL *renderbufferGL = GetImplAs<RenderbufferGL>(renderbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -040077
Geoff Langcd69f1c2015-03-18 14:33:23 -040078 functions->framebufferRenderbuffer(GL_FRAMEBUFFER, attachmentPoint, GL_RENDERBUFFER,
79 renderbufferGL->getRenderbufferID());
Geoff Lang4ad17092015-03-10 16:47:44 -040080 }
81 else
82 {
83 UNREACHABLE();
84 }
85 }
86 else
87 {
88 // Unbind this attachment
89 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_2D, 0, 0);
90 }
91}
Geoff Langf9a6f082015-01-22 13:32:49 -050092
Jamie Madill7d75e2b2015-04-30 09:42:18 -040093void FramebufferGL::onUpdateColorAttachment(size_t index)
Geoff Langf9a6f082015-01-22 13:32:49 -050094{
Geoff Lang4ad17092015-03-10 16:47:44 -040095 if (mFramebufferID != 0)
96 {
97 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Jamie Madill7d75e2b2015-04-30 09:42:18 -040098 BindFramebufferAttachment(mFunctions,
99 GL_COLOR_ATTACHMENT0 + index,
100 mData.getColorAttachment(static_cast<unsigned int>(index)));
Geoff Lang4ad17092015-03-10 16:47:44 -0400101 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500102}
103
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400104void FramebufferGL::onUpdateDepthAttachment()
Geoff Langf9a6f082015-01-22 13:32:49 -0500105{
Geoff Lang4ad17092015-03-10 16:47:44 -0400106 if (mFramebufferID != 0)
107 {
108 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400109 BindFramebufferAttachment(mFunctions,
110 GL_DEPTH_ATTACHMENT,
111 mData.getDepthAttachment());
Geoff Lang4ad17092015-03-10 16:47:44 -0400112 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500113}
114
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400115void FramebufferGL::onUpdateStencilAttachment()
Geoff Langf9a6f082015-01-22 13:32:49 -0500116{
Geoff Lang4ad17092015-03-10 16:47:44 -0400117 if (mFramebufferID != 0)
118 {
119 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400120 BindFramebufferAttachment(mFunctions,
121 GL_STENCIL_ATTACHMENT,
122 mData.getStencilAttachment());
Geoff Lang4ad17092015-03-10 16:47:44 -0400123 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500124}
125
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400126void FramebufferGL::onUpdateDepthStencilAttachment()
Geoff Langf9a6f082015-01-22 13:32:49 -0500127{
Geoff Lang4ad17092015-03-10 16:47:44 -0400128 if (mFramebufferID != 0)
129 {
130 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400131 BindFramebufferAttachment(mFunctions,
132 GL_DEPTH_STENCIL_ATTACHMENT,
133 mData.getDepthStencilAttachment());
Geoff Lang4ad17092015-03-10 16:47:44 -0400134 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500135}
136
137void FramebufferGL::setDrawBuffers(size_t count, const GLenum *buffers)
138{
Geoff Lang4ad17092015-03-10 16:47:44 -0400139 if (mFramebufferID != 0)
140 {
141 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
142 mFunctions->drawBuffers(count, buffers);
143 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500144}
145
146void FramebufferGL::setReadBuffer(GLenum buffer)
147{
Geoff Lang4ad17092015-03-10 16:47:44 -0400148 if (mFramebufferID != 0)
149 {
150 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
151 mFunctions->readBuffer(buffer);
152 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500153}
154
155gl::Error FramebufferGL::invalidate(size_t count, const GLenum *attachments)
156{
Geoff Lang64a72442015-04-01 14:43:11 -0400157 // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is available.
158 if (mFunctions->invalidateFramebuffer)
159 {
160 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
161 mFunctions->invalidateFramebuffer(GL_FRAMEBUFFER, count, attachments);
162 }
163
Geoff Lang4ad17092015-03-10 16:47:44 -0400164 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500165}
166
167gl::Error FramebufferGL::invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area)
168{
Geoff Lang64a72442015-04-01 14:43:11 -0400169 // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is available.
170 if (mFunctions->invalidateSubFramebuffer)
171 {
172 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
173 mFunctions->invalidateSubFramebuffer(GL_FRAMEBUFFER, count, attachments, area.x, area.y, area.width, area.height);
174 }
175
Geoff Lang4ad17092015-03-10 16:47:44 -0400176 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500177}
178
Jamie Madilld1f5ef22015-04-01 14:17:06 -0400179gl::Error FramebufferGL::clear(const gl::Data &data, GLbitfield mask)
Geoff Langf9a6f082015-01-22 13:32:49 -0500180{
Jamie Madilld1f5ef22015-04-01 14:17:06 -0400181 mStateManager->setClearState(*data.state, mask);
Geoff Lang4ad17092015-03-10 16:47:44 -0400182 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
183 mFunctions->clear(mask);
184
185 return gl::Error(GL_NO_ERROR);
186}
187
188static GLbitfield GetClearBufferMask(GLenum buffer)
189{
190 switch (buffer)
191 {
192 case GL_COLOR: return GL_COLOR_BUFFER_BIT;
193 case GL_DEPTH: return GL_DEPTH_BUFFER_BIT;
194 case GL_STENCIL: return GL_STENCIL_BUFFER_BIT;
195 case GL_DEPTH_STENCIL: return GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
196 default: UNREACHABLE(); return 0;
197 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500198}
199
200gl::Error FramebufferGL::clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values)
201{
Geoff Lang4ad17092015-03-10 16:47:44 -0400202 mStateManager->setClearState(state, GetClearBufferMask(buffer));
203 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
204 mFunctions->clearBufferfv(buffer, drawbuffer, values);
205
206 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500207}
208
209gl::Error FramebufferGL::clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values)
210{
Geoff Lang4ad17092015-03-10 16:47:44 -0400211 mStateManager->setClearState(state, GetClearBufferMask(buffer));
212 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
213 mFunctions->clearBufferuiv(buffer, drawbuffer, values);
214
215 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500216}
217
218gl::Error FramebufferGL::clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values)
219{
Geoff Lang4ad17092015-03-10 16:47:44 -0400220 mStateManager->setClearState(state, GetClearBufferMask(buffer));
221 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
222 mFunctions->clearBufferiv(buffer, drawbuffer, values);
223
224 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500225}
226
227gl::Error FramebufferGL::clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
228{
Geoff Lang4ad17092015-03-10 16:47:44 -0400229 mStateManager->setClearState(state, GetClearBufferMask(buffer));
230 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
231 mFunctions->clearBufferfi(buffer, drawbuffer, depth, stencil);
232
233 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500234}
235
236GLenum FramebufferGL::getImplementationColorReadFormat() const
237{
Geoff Lang4ad17092015-03-10 16:47:44 -0400238 const gl::FramebufferAttachment *readAttachment = getData().getReadAttachment();
239 GLenum internalFormat = readAttachment->getInternalFormat();
240 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
241 return internalFormatInfo.format;
Geoff Langf9a6f082015-01-22 13:32:49 -0500242}
243
244GLenum FramebufferGL::getImplementationColorReadType() const
245{
Geoff Lang4ad17092015-03-10 16:47:44 -0400246 const gl::FramebufferAttachment *readAttachment = getData().getReadAttachment();
247 GLenum internalFormat = readAttachment->getInternalFormat();
248 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
249 return internalFormatInfo.type;
Geoff Langf9a6f082015-01-22 13:32:49 -0500250}
251
252gl::Error FramebufferGL::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const
253{
Jamie Madill87de3622015-03-16 10:41:44 -0400254 const gl::PixelPackState &packState = state.getPackState();
255
Geoff Lang4ad17092015-03-10 16:47:44 -0400256 // TODO: set pack state
Jamie Madill87de3622015-03-16 10:41:44 -0400257 if (packState.rowLength != 0 || packState.skipRows != 0 || packState.skipPixels != 0)
258 {
259 UNIMPLEMENTED();
260 return gl::Error(GL_INVALID_OPERATION, "invalid pixel store parameters in readPixels");
261 }
262
Geoff Lang4ad17092015-03-10 16:47:44 -0400263 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, mFramebufferID);
264 mFunctions->readPixels(area.x, area.y, area.width, area.height, format, type, pixels);
265
266 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500267}
268
269gl::Error FramebufferGL::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
270 GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer)
271{
Geoff Lang4ad17092015-03-10 16:47:44 -0400272 const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(sourceFramebuffer);
273
274 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
275 mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferID);
276
277 mFunctions->blitFramebuffer(sourceArea.x, sourceArea.y, sourceArea.x + sourceArea.width, sourceArea.y + sourceArea.height,
278 destArea.x, destArea.y, destArea.x + destArea.width, destArea.y + destArea.height,
279 mask, filter);
280
281 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500282}
283
284GLenum FramebufferGL::checkStatus() const
285{
Geoff Lang4ad17092015-03-10 16:47:44 -0400286 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
287 return mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
288}
289
290GLuint FramebufferGL::getFramebufferID() const
291{
292 return mFramebufferID;
Geoff Langf9a6f082015-01-22 13:32:49 -0500293}
294
295}