blob: 685fd04855bb740d31bddde9cb83fd9e4eea3017 [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"
18#include "libANGLE/renderer/gl/RenderBufferGL.h"
19#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 {
53 const gl::Texture *texture = GetAs<gl::TextureAttachment>(attachment)->getTexture();
54 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 {
Geoff Langcd69f1c2015-03-18 14:33:23 -040078 const gl::Renderbuffer *renderbuffer = GetAs<gl::RenderbufferAttachment>(attachment)->getRenderbuffer();
79 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 Lang4ad17092015-03-10 16:47:44 -0400152 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
153 mFunctions->invalidateFramebuffer(GL_FRAMEBUFFER, count, attachments);
154 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500155}
156
157gl::Error FramebufferGL::invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area)
158{
Geoff Lang4ad17092015-03-10 16:47:44 -0400159 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
160 mFunctions->invalidateSubFramebuffer(GL_FRAMEBUFFER, count, attachments, area.x, area.y, area.width, area.height);
161 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500162}
163
Jamie Madilld1f5ef22015-04-01 14:17:06 -0400164gl::Error FramebufferGL::clear(const gl::Data &data, GLbitfield mask)
Geoff Langf9a6f082015-01-22 13:32:49 -0500165{
Jamie Madilld1f5ef22015-04-01 14:17:06 -0400166 mStateManager->setClearState(*data.state, mask);
Geoff Lang4ad17092015-03-10 16:47:44 -0400167 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
168 mFunctions->clear(mask);
169
170 return gl::Error(GL_NO_ERROR);
171}
172
173static GLbitfield GetClearBufferMask(GLenum buffer)
174{
175 switch (buffer)
176 {
177 case GL_COLOR: return GL_COLOR_BUFFER_BIT;
178 case GL_DEPTH: return GL_DEPTH_BUFFER_BIT;
179 case GL_STENCIL: return GL_STENCIL_BUFFER_BIT;
180 case GL_DEPTH_STENCIL: return GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
181 default: UNREACHABLE(); return 0;
182 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500183}
184
185gl::Error FramebufferGL::clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values)
186{
Geoff Lang4ad17092015-03-10 16:47:44 -0400187 mStateManager->setClearState(state, GetClearBufferMask(buffer));
188 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
189 mFunctions->clearBufferfv(buffer, drawbuffer, values);
190
191 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500192}
193
194gl::Error FramebufferGL::clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values)
195{
Geoff Lang4ad17092015-03-10 16:47:44 -0400196 mStateManager->setClearState(state, GetClearBufferMask(buffer));
197 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
198 mFunctions->clearBufferuiv(buffer, drawbuffer, values);
199
200 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500201}
202
203gl::Error FramebufferGL::clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values)
204{
Geoff Lang4ad17092015-03-10 16:47:44 -0400205 mStateManager->setClearState(state, GetClearBufferMask(buffer));
206 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
207 mFunctions->clearBufferiv(buffer, drawbuffer, values);
208
209 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500210}
211
212gl::Error FramebufferGL::clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
213{
Geoff Lang4ad17092015-03-10 16:47:44 -0400214 mStateManager->setClearState(state, GetClearBufferMask(buffer));
215 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
216 mFunctions->clearBufferfi(buffer, drawbuffer, depth, stencil);
217
218 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500219}
220
221GLenum FramebufferGL::getImplementationColorReadFormat() const
222{
Geoff Lang4ad17092015-03-10 16:47:44 -0400223 const gl::FramebufferAttachment *readAttachment = getData().getReadAttachment();
224 GLenum internalFormat = readAttachment->getInternalFormat();
225 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
226 return internalFormatInfo.format;
Geoff Langf9a6f082015-01-22 13:32:49 -0500227}
228
229GLenum FramebufferGL::getImplementationColorReadType() const
230{
Geoff Lang4ad17092015-03-10 16:47:44 -0400231 const gl::FramebufferAttachment *readAttachment = getData().getReadAttachment();
232 GLenum internalFormat = readAttachment->getInternalFormat();
233 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
234 return internalFormatInfo.type;
Geoff Langf9a6f082015-01-22 13:32:49 -0500235}
236
237gl::Error FramebufferGL::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const
238{
Jamie Madill87de3622015-03-16 10:41:44 -0400239 const gl::PixelPackState &packState = state.getPackState();
240
Geoff Lang4ad17092015-03-10 16:47:44 -0400241 // TODO: set pack state
Jamie Madill87de3622015-03-16 10:41:44 -0400242 if (packState.rowLength != 0 || packState.skipRows != 0 || packState.skipPixels != 0)
243 {
244 UNIMPLEMENTED();
245 return gl::Error(GL_INVALID_OPERATION, "invalid pixel store parameters in readPixels");
246 }
247
Geoff Lang4ad17092015-03-10 16:47:44 -0400248 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, mFramebufferID);
249 mFunctions->readPixels(area.x, area.y, area.width, area.height, format, type, pixels);
250
251 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500252}
253
254gl::Error FramebufferGL::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
255 GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer)
256{
Geoff Lang4ad17092015-03-10 16:47:44 -0400257 const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(sourceFramebuffer);
258
259 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
260 mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferID);
261
262 mFunctions->blitFramebuffer(sourceArea.x, sourceArea.y, sourceArea.x + sourceArea.width, sourceArea.y + sourceArea.height,
263 destArea.x, destArea.y, destArea.x + destArea.width, destArea.y + destArea.height,
264 mask, filter);
265
266 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500267}
268
269GLenum FramebufferGL::checkStatus() const
270{
Geoff Lang4ad17092015-03-10 16:47:44 -0400271 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
272 return mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
273}
274
275GLuint FramebufferGL::getFramebufferID() const
276{
277 return mFramebufferID;
Geoff Langf9a6f082015-01-22 13:32:49 -0500278}
279
280}