blob: e75692aff2b48ccb61195af9f48da23e1c17f858 [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{
39 if (mFramebufferID != 0)
40 {
41 mFunctions->deleteFramebuffers(1, &mFramebufferID);
42 mFramebufferID = 0;
43 }
44}
45
46static void BindFramebufferAttachment(const FunctionsGL *functions, GLenum attachmentPoint,
47 const gl::FramebufferAttachment *attachment)
48{
49 if (attachment)
50 {
51 if (attachment->type() == GL_TEXTURE)
52 {
Jamie Madill5160ec12015-04-14 08:13:48 -040053 const gl::Texture *texture = attachment->getTexture();
Geoff Lang4ad17092015-03-10 16:47:44 -040054 const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
55
56 if (texture->getTarget() == GL_TEXTURE_2D)
57 {
58 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_2D,
59 textureGL->getTextureID(), attachment->mipLevel());
60 }
61 else if (texture->getTarget() == GL_TEXTURE_CUBE_MAP)
62 {
63 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, attachment->cubeMapFace(),
64 textureGL->getTextureID(), attachment->mipLevel());
65 }
66 else if (texture->getTarget() == GL_TEXTURE_2D_ARRAY || texture->getTarget() == GL_TEXTURE_3D)
67 {
68 functions->framebufferTextureLayer(GL_FRAMEBUFFER, attachmentPoint, textureGL->getTextureID(),
69 attachment->mipLevel(), attachment->layer());
70 }
71 else
72 {
73 UNREACHABLE();
74 }
75 }
76 else if (attachment->type() == GL_RENDERBUFFER)
77 {
Jamie Madill5160ec12015-04-14 08:13:48 -040078 const gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
Geoff Langcd69f1c2015-03-18 14:33:23 -040079 const RenderbufferGL *renderbufferGL = GetImplAs<RenderbufferGL>(renderbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -040080
Geoff Langcd69f1c2015-03-18 14:33:23 -040081 functions->framebufferRenderbuffer(GL_FRAMEBUFFER, attachmentPoint, GL_RENDERBUFFER,
82 renderbufferGL->getRenderbufferID());
Geoff Lang4ad17092015-03-10 16:47:44 -040083 }
84 else
85 {
86 UNREACHABLE();
87 }
88 }
89 else
90 {
91 // Unbind this attachment
92 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_2D, 0, 0);
93 }
94}
Geoff Langf9a6f082015-01-22 13:32:49 -050095
96void FramebufferGL::setColorAttachment(size_t index, const gl::FramebufferAttachment *attachment)
97{
Geoff Lang4ad17092015-03-10 16:47:44 -040098 if (mFramebufferID != 0)
99 {
100 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
101 BindFramebufferAttachment(mFunctions, GL_COLOR_ATTACHMENT0 + index, attachment);
102 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500103}
104
Jamie Madillf90353e2015-03-05 19:37:58 -0500105void FramebufferGL::setDepthAttachment(const gl::FramebufferAttachment *attachment)
Geoff Langf9a6f082015-01-22 13:32:49 -0500106{
Geoff Lang4ad17092015-03-10 16:47:44 -0400107 if (mFramebufferID != 0)
108 {
109 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
110 BindFramebufferAttachment(mFunctions, GL_DEPTH_ATTACHMENT, attachment);
111 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500112}
113
114void FramebufferGL::setStencilAttachment(const gl::FramebufferAttachment *attachment)
115{
Geoff Lang4ad17092015-03-10 16:47:44 -0400116 if (mFramebufferID != 0)
117 {
118 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
119 BindFramebufferAttachment(mFunctions, GL_STENCIL_ATTACHMENT, attachment);
120 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500121}
122
123void FramebufferGL::setDepthStencilAttachment(const gl::FramebufferAttachment *attachment)
124{
Geoff Lang4ad17092015-03-10 16:47:44 -0400125 if (mFramebufferID != 0)
126 {
127 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
128 BindFramebufferAttachment(mFunctions, GL_DEPTH_STENCIL_ATTACHMENT, attachment);
129 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500130}
131
132void FramebufferGL::setDrawBuffers(size_t count, const GLenum *buffers)
133{
Geoff Lang4ad17092015-03-10 16:47:44 -0400134 if (mFramebufferID != 0)
135 {
136 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
137 mFunctions->drawBuffers(count, buffers);
138 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500139}
140
141void FramebufferGL::setReadBuffer(GLenum buffer)
142{
Geoff Lang4ad17092015-03-10 16:47:44 -0400143 if (mFramebufferID != 0)
144 {
145 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
146 mFunctions->readBuffer(buffer);
147 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500148}
149
150gl::Error FramebufferGL::invalidate(size_t count, const GLenum *attachments)
151{
Geoff Lang64a72442015-04-01 14:43:11 -0400152 // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is available.
153 if (mFunctions->invalidateFramebuffer)
154 {
155 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
156 mFunctions->invalidateFramebuffer(GL_FRAMEBUFFER, count, attachments);
157 }
158
Geoff Lang4ad17092015-03-10 16:47:44 -0400159 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500160}
161
162gl::Error FramebufferGL::invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area)
163{
Geoff Lang64a72442015-04-01 14:43:11 -0400164 // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is available.
165 if (mFunctions->invalidateSubFramebuffer)
166 {
167 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
168 mFunctions->invalidateSubFramebuffer(GL_FRAMEBUFFER, count, attachments, area.x, area.y, area.width, area.height);
169 }
170
Geoff Lang4ad17092015-03-10 16:47:44 -0400171 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500172}
173
Jamie Madilld1f5ef22015-04-01 14:17:06 -0400174gl::Error FramebufferGL::clear(const gl::Data &data, GLbitfield mask)
Geoff Langf9a6f082015-01-22 13:32:49 -0500175{
Jamie Madilld1f5ef22015-04-01 14:17:06 -0400176 mStateManager->setClearState(*data.state, mask);
Geoff Lang4ad17092015-03-10 16:47:44 -0400177 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
178 mFunctions->clear(mask);
179
180 return gl::Error(GL_NO_ERROR);
181}
182
183static GLbitfield GetClearBufferMask(GLenum buffer)
184{
185 switch (buffer)
186 {
187 case GL_COLOR: return GL_COLOR_BUFFER_BIT;
188 case GL_DEPTH: return GL_DEPTH_BUFFER_BIT;
189 case GL_STENCIL: return GL_STENCIL_BUFFER_BIT;
190 case GL_DEPTH_STENCIL: return GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
191 default: UNREACHABLE(); return 0;
192 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500193}
194
195gl::Error FramebufferGL::clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values)
196{
Geoff Lang4ad17092015-03-10 16:47:44 -0400197 mStateManager->setClearState(state, GetClearBufferMask(buffer));
198 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
199 mFunctions->clearBufferfv(buffer, drawbuffer, values);
200
201 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500202}
203
204gl::Error FramebufferGL::clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values)
205{
Geoff Lang4ad17092015-03-10 16:47:44 -0400206 mStateManager->setClearState(state, GetClearBufferMask(buffer));
207 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
208 mFunctions->clearBufferuiv(buffer, drawbuffer, values);
209
210 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500211}
212
213gl::Error FramebufferGL::clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values)
214{
Geoff Lang4ad17092015-03-10 16:47:44 -0400215 mStateManager->setClearState(state, GetClearBufferMask(buffer));
216 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
217 mFunctions->clearBufferiv(buffer, drawbuffer, values);
218
219 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500220}
221
222gl::Error FramebufferGL::clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
223{
Geoff Lang4ad17092015-03-10 16:47:44 -0400224 mStateManager->setClearState(state, GetClearBufferMask(buffer));
225 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
226 mFunctions->clearBufferfi(buffer, drawbuffer, depth, stencil);
227
228 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500229}
230
231GLenum FramebufferGL::getImplementationColorReadFormat() const
232{
Geoff Lang4ad17092015-03-10 16:47:44 -0400233 const gl::FramebufferAttachment *readAttachment = getData().getReadAttachment();
234 GLenum internalFormat = readAttachment->getInternalFormat();
235 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
236 return internalFormatInfo.format;
Geoff Langf9a6f082015-01-22 13:32:49 -0500237}
238
239GLenum FramebufferGL::getImplementationColorReadType() const
240{
Geoff Lang4ad17092015-03-10 16:47:44 -0400241 const gl::FramebufferAttachment *readAttachment = getData().getReadAttachment();
242 GLenum internalFormat = readAttachment->getInternalFormat();
243 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
244 return internalFormatInfo.type;
Geoff Langf9a6f082015-01-22 13:32:49 -0500245}
246
247gl::Error FramebufferGL::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const
248{
Jamie Madill87de3622015-03-16 10:41:44 -0400249 const gl::PixelPackState &packState = state.getPackState();
250
Geoff Lang4ad17092015-03-10 16:47:44 -0400251 // TODO: set pack state
Jamie Madill87de3622015-03-16 10:41:44 -0400252 if (packState.rowLength != 0 || packState.skipRows != 0 || packState.skipPixels != 0)
253 {
254 UNIMPLEMENTED();
255 return gl::Error(GL_INVALID_OPERATION, "invalid pixel store parameters in readPixels");
256 }
257
Geoff Lang4ad17092015-03-10 16:47:44 -0400258 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, mFramebufferID);
259 mFunctions->readPixels(area.x, area.y, area.width, area.height, format, type, pixels);
260
261 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500262}
263
264gl::Error FramebufferGL::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
265 GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer)
266{
Geoff Lang4ad17092015-03-10 16:47:44 -0400267 const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(sourceFramebuffer);
268
269 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
270 mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferID);
271
272 mFunctions->blitFramebuffer(sourceArea.x, sourceArea.y, sourceArea.x + sourceArea.width, sourceArea.y + sourceArea.height,
273 destArea.x, destArea.y, destArea.x + destArea.width, destArea.y + destArea.height,
274 mask, filter);
275
276 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500277}
278
279GLenum FramebufferGL::checkStatus() const
280{
Geoff Lang4ad17092015-03-10 16:47:44 -0400281 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
282 return mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
283}
284
285GLuint FramebufferGL::getFramebufferID() const
286{
287 return mFramebufferID;
Geoff Langf9a6f082015-01-22 13:32:49 -0500288}
289
290}