blob: 08497e9ae3662ea8d3dee6d71cd61c3e0e83eebc [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 {
77 // TODO: support RenderbufferGL
78 UNIMPLEMENTED();
79
80 //const gl::Renderbuffer *renderbuffer = GetAs<gl::RenderbufferAttachment>(attachment)->getRenderbuffer();
81 //const RenderbufferGL *renderbufferGL = GetImplAs<RenderbufferGL>(renderbuffer);
82
83 //functions->framebufferRenderbuffer(GL_FRAMEBUFFER, attachmentPoint, GL_RENDERBUFFER,
84 // renderbufferGL->getRenderbufferID());
85 }
86 else
87 {
88 UNREACHABLE();
89 }
90 }
91 else
92 {
93 // Unbind this attachment
94 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_2D, 0, 0);
95 }
96}
Geoff Langf9a6f082015-01-22 13:32:49 -050097
98void FramebufferGL::setColorAttachment(size_t index, const gl::FramebufferAttachment *attachment)
99{
Geoff Lang4ad17092015-03-10 16:47:44 -0400100 if (mFramebufferID != 0)
101 {
102 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
103 BindFramebufferAttachment(mFunctions, GL_COLOR_ATTACHMENT0 + index, attachment);
104 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500105}
106
Jamie Madillf90353e2015-03-05 19:37:58 -0500107void FramebufferGL::setDepthAttachment(const gl::FramebufferAttachment *attachment)
Geoff Langf9a6f082015-01-22 13:32:49 -0500108{
Geoff Lang4ad17092015-03-10 16:47:44 -0400109 if (mFramebufferID != 0)
110 {
111 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
112 BindFramebufferAttachment(mFunctions, GL_DEPTH_ATTACHMENT, attachment);
113 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500114}
115
116void FramebufferGL::setStencilAttachment(const gl::FramebufferAttachment *attachment)
117{
Geoff Lang4ad17092015-03-10 16:47:44 -0400118 if (mFramebufferID != 0)
119 {
120 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
121 BindFramebufferAttachment(mFunctions, GL_STENCIL_ATTACHMENT, attachment);
122 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500123}
124
125void FramebufferGL::setDepthStencilAttachment(const gl::FramebufferAttachment *attachment)
126{
Geoff Lang4ad17092015-03-10 16:47:44 -0400127 if (mFramebufferID != 0)
128 {
129 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
130 BindFramebufferAttachment(mFunctions, GL_DEPTH_STENCIL_ATTACHMENT, attachment);
131 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500132}
133
134void FramebufferGL::setDrawBuffers(size_t count, const GLenum *buffers)
135{
Geoff Lang4ad17092015-03-10 16:47:44 -0400136 if (mFramebufferID != 0)
137 {
138 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
139 mFunctions->drawBuffers(count, buffers);
140 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500141}
142
143void FramebufferGL::setReadBuffer(GLenum buffer)
144{
Geoff Lang4ad17092015-03-10 16:47:44 -0400145 if (mFramebufferID != 0)
146 {
147 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
148 mFunctions->readBuffer(buffer);
149 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500150}
151
152gl::Error FramebufferGL::invalidate(size_t count, const GLenum *attachments)
153{
Geoff Lang4ad17092015-03-10 16:47:44 -0400154 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
155 mFunctions->invalidateFramebuffer(GL_FRAMEBUFFER, count, attachments);
156 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500157}
158
159gl::Error FramebufferGL::invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area)
160{
Geoff Lang4ad17092015-03-10 16:47:44 -0400161 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
162 mFunctions->invalidateSubFramebuffer(GL_FRAMEBUFFER, count, attachments, area.x, area.y, area.width, area.height);
163 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500164}
165
166gl::Error FramebufferGL::clear(const gl::State &state, GLbitfield mask)
167{
Geoff Lang4ad17092015-03-10 16:47:44 -0400168 mStateManager->setClearState(state, mask);
169 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
170 mFunctions->clear(mask);
171
172 return gl::Error(GL_NO_ERROR);
173}
174
175static GLbitfield GetClearBufferMask(GLenum buffer)
176{
177 switch (buffer)
178 {
179 case GL_COLOR: return GL_COLOR_BUFFER_BIT;
180 case GL_DEPTH: return GL_DEPTH_BUFFER_BIT;
181 case GL_STENCIL: return GL_STENCIL_BUFFER_BIT;
182 case GL_DEPTH_STENCIL: return GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
183 default: UNREACHABLE(); return 0;
184 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500185}
186
187gl::Error FramebufferGL::clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values)
188{
Geoff Lang4ad17092015-03-10 16:47:44 -0400189 mStateManager->setClearState(state, GetClearBufferMask(buffer));
190 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
191 mFunctions->clearBufferfv(buffer, drawbuffer, values);
192
193 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500194}
195
196gl::Error FramebufferGL::clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values)
197{
Geoff Lang4ad17092015-03-10 16:47:44 -0400198 mStateManager->setClearState(state, GetClearBufferMask(buffer));
199 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
200 mFunctions->clearBufferuiv(buffer, drawbuffer, values);
201
202 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500203}
204
205gl::Error FramebufferGL::clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values)
206{
Geoff Lang4ad17092015-03-10 16:47:44 -0400207 mStateManager->setClearState(state, GetClearBufferMask(buffer));
208 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
209 mFunctions->clearBufferiv(buffer, drawbuffer, values);
210
211 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500212}
213
214gl::Error FramebufferGL::clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
215{
Geoff Lang4ad17092015-03-10 16:47:44 -0400216 mStateManager->setClearState(state, GetClearBufferMask(buffer));
217 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
218 mFunctions->clearBufferfi(buffer, drawbuffer, depth, stencil);
219
220 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500221}
222
223GLenum FramebufferGL::getImplementationColorReadFormat() const
224{
Geoff Lang4ad17092015-03-10 16:47:44 -0400225 const gl::FramebufferAttachment *readAttachment = getData().getReadAttachment();
226 GLenum internalFormat = readAttachment->getInternalFormat();
227 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
228 return internalFormatInfo.format;
Geoff Langf9a6f082015-01-22 13:32:49 -0500229}
230
231GLenum FramebufferGL::getImplementationColorReadType() 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.type;
Geoff Langf9a6f082015-01-22 13:32:49 -0500237}
238
239gl::Error FramebufferGL::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const
240{
Jamie Madill87de3622015-03-16 10:41:44 -0400241 const gl::PixelPackState &packState = state.getPackState();
242
Geoff Lang4ad17092015-03-10 16:47:44 -0400243 // TODO: set pack state
Jamie Madill87de3622015-03-16 10:41:44 -0400244 if (packState.rowLength != 0 || packState.skipRows != 0 || packState.skipPixels != 0)
245 {
246 UNIMPLEMENTED();
247 return gl::Error(GL_INVALID_OPERATION, "invalid pixel store parameters in readPixels");
248 }
249
Geoff Lang4ad17092015-03-10 16:47:44 -0400250 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, mFramebufferID);
251 mFunctions->readPixels(area.x, area.y, area.width, area.height, format, type, pixels);
252
253 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500254}
255
256gl::Error FramebufferGL::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
257 GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer)
258{
Geoff Lang4ad17092015-03-10 16:47:44 -0400259 const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(sourceFramebuffer);
260
261 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
262 mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferID);
263
264 mFunctions->blitFramebuffer(sourceArea.x, sourceArea.y, sourceArea.x + sourceArea.width, sourceArea.y + sourceArea.height,
265 destArea.x, destArea.y, destArea.x + destArea.width, destArea.y + destArea.height,
266 mask, filter);
267
268 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500269}
270
271GLenum FramebufferGL::checkStatus() const
272{
Geoff Lang4ad17092015-03-10 16:47:44 -0400273 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
274 return mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
275}
276
277GLuint FramebufferGL::getFramebufferID() const
278{
279 return mFramebufferID;
Geoff Langf9a6f082015-01-22 13:32:49 -0500280}
281
282}