blob: 99ad76f2b04e669c1295bc82e5204d61af46ff09 [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 Madill87de3622015-03-16 10:41:44 -040012#include "libANGLE/State.h"
Geoff Lang4ad17092015-03-10 16:47:44 -040013#include "libANGLE/FramebufferAttachment.h"
14#include "libANGLE/angletypes.h"
15#include "libANGLE/formatutils.h"
16#include "libANGLE/renderer/gl/FunctionsGL.h"
17#include "libANGLE/renderer/gl/RenderBufferGL.h"
18#include "libANGLE/renderer/gl/StateManagerGL.h"
19#include "libANGLE/renderer/gl/TextureGL.h"
Geoff Langf9a6f082015-01-22 13:32:49 -050020
21namespace rx
22{
23
Geoff Lang4ad17092015-03-10 16:47:44 -040024FramebufferGL::FramebufferGL(const gl::Framebuffer::Data &data, const FunctionsGL *functions, StateManagerGL *stateManager, bool isDefault)
25 : FramebufferImpl(data),
26 mFunctions(functions),
27 mStateManager(stateManager),
28 mFramebufferID(0)
29{
30 if (!isDefault)
31 {
32 mFunctions->genFramebuffers(1, &mFramebufferID);
33 }
34}
Geoff Langf9a6f082015-01-22 13:32:49 -050035
36FramebufferGL::~FramebufferGL()
Geoff Lang4ad17092015-03-10 16:47:44 -040037{
38 if (mFramebufferID != 0)
39 {
40 mFunctions->deleteFramebuffers(1, &mFramebufferID);
41 mFramebufferID = 0;
42 }
43}
44
45static void BindFramebufferAttachment(const FunctionsGL *functions, GLenum attachmentPoint,
46 const gl::FramebufferAttachment *attachment)
47{
48 if (attachment)
49 {
50 if (attachment->type() == GL_TEXTURE)
51 {
52 const gl::Texture *texture = GetAs<gl::TextureAttachment>(attachment)->getTexture();
53 const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
54
55 if (texture->getTarget() == GL_TEXTURE_2D)
56 {
57 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_2D,
58 textureGL->getTextureID(), attachment->mipLevel());
59 }
60 else if (texture->getTarget() == GL_TEXTURE_CUBE_MAP)
61 {
62 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, attachment->cubeMapFace(),
63 textureGL->getTextureID(), attachment->mipLevel());
64 }
65 else if (texture->getTarget() == GL_TEXTURE_2D_ARRAY || texture->getTarget() == GL_TEXTURE_3D)
66 {
67 functions->framebufferTextureLayer(GL_FRAMEBUFFER, attachmentPoint, textureGL->getTextureID(),
68 attachment->mipLevel(), attachment->layer());
69 }
70 else
71 {
72 UNREACHABLE();
73 }
74 }
75 else if (attachment->type() == GL_RENDERBUFFER)
76 {
Geoff Langcd69f1c2015-03-18 14:33:23 -040077 const gl::Renderbuffer *renderbuffer = GetAs<gl::RenderbufferAttachment>(attachment)->getRenderbuffer();
78 const RenderbufferGL *renderbufferGL = GetImplAs<RenderbufferGL>(renderbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -040079
Geoff Langcd69f1c2015-03-18 14:33:23 -040080 functions->framebufferRenderbuffer(GL_FRAMEBUFFER, attachmentPoint, GL_RENDERBUFFER,
81 renderbufferGL->getRenderbufferID());
Geoff Lang4ad17092015-03-10 16:47:44 -040082 }
83 else
84 {
85 UNREACHABLE();
86 }
87 }
88 else
89 {
90 // Unbind this attachment
91 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_2D, 0, 0);
92 }
93}
Geoff Langf9a6f082015-01-22 13:32:49 -050094
95void FramebufferGL::setColorAttachment(size_t index, const gl::FramebufferAttachment *attachment)
96{
Geoff Lang4ad17092015-03-10 16:47:44 -040097 if (mFramebufferID != 0)
98 {
99 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
100 BindFramebufferAttachment(mFunctions, GL_COLOR_ATTACHMENT0 + index, attachment);
101 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500102}
103
Jamie Madillf90353e2015-03-05 19:37:58 -0500104void FramebufferGL::setDepthAttachment(const gl::FramebufferAttachment *attachment)
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);
109 BindFramebufferAttachment(mFunctions, GL_DEPTH_ATTACHMENT, attachment);
110 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500111}
112
113void FramebufferGL::setStencilAttachment(const gl::FramebufferAttachment *attachment)
114{
Geoff Lang4ad17092015-03-10 16:47:44 -0400115 if (mFramebufferID != 0)
116 {
117 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
118 BindFramebufferAttachment(mFunctions, GL_STENCIL_ATTACHMENT, attachment);
119 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500120}
121
122void FramebufferGL::setDepthStencilAttachment(const gl::FramebufferAttachment *attachment)
123{
Geoff Lang4ad17092015-03-10 16:47:44 -0400124 if (mFramebufferID != 0)
125 {
126 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
127 BindFramebufferAttachment(mFunctions, GL_DEPTH_STENCIL_ATTACHMENT, attachment);
128 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500129}
130
131void FramebufferGL::setDrawBuffers(size_t count, const GLenum *buffers)
132{
Geoff Lang4ad17092015-03-10 16:47:44 -0400133 if (mFramebufferID != 0)
134 {
135 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
136 mFunctions->drawBuffers(count, buffers);
137 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500138}
139
140void FramebufferGL::setReadBuffer(GLenum buffer)
141{
Geoff Lang4ad17092015-03-10 16:47:44 -0400142 if (mFramebufferID != 0)
143 {
144 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
145 mFunctions->readBuffer(buffer);
146 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500147}
148
149gl::Error FramebufferGL::invalidate(size_t count, const GLenum *attachments)
150{
Geoff Lang4ad17092015-03-10 16:47:44 -0400151 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
152 mFunctions->invalidateFramebuffer(GL_FRAMEBUFFER, count, attachments);
153 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500154}
155
156gl::Error FramebufferGL::invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area)
157{
Geoff Lang4ad17092015-03-10 16:47:44 -0400158 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
159 mFunctions->invalidateSubFramebuffer(GL_FRAMEBUFFER, count, attachments, area.x, area.y, area.width, area.height);
160 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500161}
162
163gl::Error FramebufferGL::clear(const gl::State &state, GLbitfield mask)
164{
Geoff Lang4ad17092015-03-10 16:47:44 -0400165 mStateManager->setClearState(state, mask);
166 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
167 mFunctions->clear(mask);
168
169 return gl::Error(GL_NO_ERROR);
170}
171
172static GLbitfield GetClearBufferMask(GLenum buffer)
173{
174 switch (buffer)
175 {
176 case GL_COLOR: return GL_COLOR_BUFFER_BIT;
177 case GL_DEPTH: return GL_DEPTH_BUFFER_BIT;
178 case GL_STENCIL: return GL_STENCIL_BUFFER_BIT;
179 case GL_DEPTH_STENCIL: return GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
180 default: UNREACHABLE(); return 0;
181 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500182}
183
184gl::Error FramebufferGL::clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values)
185{
Geoff Lang4ad17092015-03-10 16:47:44 -0400186 mStateManager->setClearState(state, GetClearBufferMask(buffer));
187 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
188 mFunctions->clearBufferfv(buffer, drawbuffer, values);
189
190 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500191}
192
193gl::Error FramebufferGL::clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values)
194{
Geoff Lang4ad17092015-03-10 16:47:44 -0400195 mStateManager->setClearState(state, GetClearBufferMask(buffer));
196 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
197 mFunctions->clearBufferuiv(buffer, drawbuffer, values);
198
199 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500200}
201
202gl::Error FramebufferGL::clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values)
203{
Geoff Lang4ad17092015-03-10 16:47:44 -0400204 mStateManager->setClearState(state, GetClearBufferMask(buffer));
205 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
206 mFunctions->clearBufferiv(buffer, drawbuffer, values);
207
208 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500209}
210
211gl::Error FramebufferGL::clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
212{
Geoff Lang4ad17092015-03-10 16:47:44 -0400213 mStateManager->setClearState(state, GetClearBufferMask(buffer));
214 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
215 mFunctions->clearBufferfi(buffer, drawbuffer, depth, stencil);
216
217 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500218}
219
220GLenum FramebufferGL::getImplementationColorReadFormat() const
221{
Geoff Lang4ad17092015-03-10 16:47:44 -0400222 const gl::FramebufferAttachment *readAttachment = getData().getReadAttachment();
223 GLenum internalFormat = readAttachment->getInternalFormat();
224 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
225 return internalFormatInfo.format;
Geoff Langf9a6f082015-01-22 13:32:49 -0500226}
227
228GLenum FramebufferGL::getImplementationColorReadType() const
229{
Geoff Lang4ad17092015-03-10 16:47:44 -0400230 const gl::FramebufferAttachment *readAttachment = getData().getReadAttachment();
231 GLenum internalFormat = readAttachment->getInternalFormat();
232 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
233 return internalFormatInfo.type;
Geoff Langf9a6f082015-01-22 13:32:49 -0500234}
235
236gl::Error FramebufferGL::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const
237{
Jamie Madill87de3622015-03-16 10:41:44 -0400238 const gl::PixelPackState &packState = state.getPackState();
239
Geoff Lang4ad17092015-03-10 16:47:44 -0400240 // TODO: set pack state
Jamie Madill87de3622015-03-16 10:41:44 -0400241 if (packState.rowLength != 0 || packState.skipRows != 0 || packState.skipPixels != 0)
242 {
243 UNIMPLEMENTED();
244 return gl::Error(GL_INVALID_OPERATION, "invalid pixel store parameters in readPixels");
245 }
246
Geoff Lang4ad17092015-03-10 16:47:44 -0400247 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, mFramebufferID);
248 mFunctions->readPixels(area.x, area.y, area.width, area.height, format, type, pixels);
249
250 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500251}
252
253gl::Error FramebufferGL::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
254 GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer)
255{
Geoff Lang4ad17092015-03-10 16:47:44 -0400256 const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(sourceFramebuffer);
257
258 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
259 mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferID);
260
261 mFunctions->blitFramebuffer(sourceArea.x, sourceArea.y, sourceArea.x + sourceArea.width, sourceArea.y + sourceArea.height,
262 destArea.x, destArea.y, destArea.x + destArea.width, destArea.y + destArea.height,
263 mask, filter);
264
265 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500266}
267
268GLenum FramebufferGL::checkStatus() const
269{
Geoff Lang4ad17092015-03-10 16:47:44 -0400270 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
271 return mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
272}
273
274GLuint FramebufferGL::getFramebufferID() const
275{
276 return mFramebufferID;
Geoff Langf9a6f082015-01-22 13:32:49 -0500277}
278
279}