blob: 732275ba0635f9fb04c06db7fafec9ccc60c5b79 [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
Austin Kinross08332632015-05-05 13:35:47 -0700155gl::Error FramebufferGL::discard(size_t count, const GLenum *attachments)
156{
157 UNIMPLEMENTED();
158 return gl::Error(GL_INVALID_OPERATION);
159}
160
Geoff Langf9a6f082015-01-22 13:32:49 -0500161gl::Error FramebufferGL::invalidate(size_t count, const GLenum *attachments)
162{
Geoff Lang64a72442015-04-01 14:43:11 -0400163 // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is available.
164 if (mFunctions->invalidateFramebuffer)
165 {
166 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
167 mFunctions->invalidateFramebuffer(GL_FRAMEBUFFER, count, attachments);
168 }
169
Geoff Lang4ad17092015-03-10 16:47:44 -0400170 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500171}
172
173gl::Error FramebufferGL::invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area)
174{
Geoff Lang64a72442015-04-01 14:43:11 -0400175 // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is available.
176 if (mFunctions->invalidateSubFramebuffer)
177 {
178 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
179 mFunctions->invalidateSubFramebuffer(GL_FRAMEBUFFER, count, attachments, area.x, area.y, area.width, area.height);
180 }
181
Geoff Lang4ad17092015-03-10 16:47:44 -0400182 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500183}
184
Jamie Madilld1f5ef22015-04-01 14:17:06 -0400185gl::Error FramebufferGL::clear(const gl::Data &data, GLbitfield mask)
Geoff Langf9a6f082015-01-22 13:32:49 -0500186{
Jamie Madilld1f5ef22015-04-01 14:17:06 -0400187 mStateManager->setClearState(*data.state, mask);
Geoff Lang4ad17092015-03-10 16:47:44 -0400188 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
189 mFunctions->clear(mask);
190
191 return gl::Error(GL_NO_ERROR);
192}
193
194static GLbitfield GetClearBufferMask(GLenum buffer)
195{
196 switch (buffer)
197 {
198 case GL_COLOR: return GL_COLOR_BUFFER_BIT;
199 case GL_DEPTH: return GL_DEPTH_BUFFER_BIT;
200 case GL_STENCIL: return GL_STENCIL_BUFFER_BIT;
201 case GL_DEPTH_STENCIL: return GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
202 default: UNREACHABLE(); return 0;
203 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500204}
205
206gl::Error FramebufferGL::clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values)
207{
Geoff Lang4ad17092015-03-10 16:47:44 -0400208 mStateManager->setClearState(state, GetClearBufferMask(buffer));
209 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
210 mFunctions->clearBufferfv(buffer, drawbuffer, values);
211
212 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500213}
214
215gl::Error FramebufferGL::clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values)
216{
Geoff Lang4ad17092015-03-10 16:47:44 -0400217 mStateManager->setClearState(state, GetClearBufferMask(buffer));
218 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
219 mFunctions->clearBufferuiv(buffer, drawbuffer, values);
220
221 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500222}
223
224gl::Error FramebufferGL::clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values)
225{
Geoff Lang4ad17092015-03-10 16:47:44 -0400226 mStateManager->setClearState(state, GetClearBufferMask(buffer));
227 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
228 mFunctions->clearBufferiv(buffer, drawbuffer, values);
229
230 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500231}
232
233gl::Error FramebufferGL::clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
234{
Geoff Lang4ad17092015-03-10 16:47:44 -0400235 mStateManager->setClearState(state, GetClearBufferMask(buffer));
236 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
237 mFunctions->clearBufferfi(buffer, drawbuffer, depth, stencil);
238
239 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500240}
241
242GLenum FramebufferGL::getImplementationColorReadFormat() const
243{
Geoff Lang4ad17092015-03-10 16:47:44 -0400244 const gl::FramebufferAttachment *readAttachment = getData().getReadAttachment();
245 GLenum internalFormat = readAttachment->getInternalFormat();
246 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
247 return internalFormatInfo.format;
Geoff Langf9a6f082015-01-22 13:32:49 -0500248}
249
250GLenum FramebufferGL::getImplementationColorReadType() const
251{
Geoff Lang4ad17092015-03-10 16:47:44 -0400252 const gl::FramebufferAttachment *readAttachment = getData().getReadAttachment();
253 GLenum internalFormat = readAttachment->getInternalFormat();
254 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
255 return internalFormatInfo.type;
Geoff Langf9a6f082015-01-22 13:32:49 -0500256}
257
258gl::Error FramebufferGL::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const
259{
Jamie Madill87de3622015-03-16 10:41:44 -0400260 const gl::PixelPackState &packState = state.getPackState();
261
Geoff Lang4ad17092015-03-10 16:47:44 -0400262 // TODO: set pack state
Jamie Madill87de3622015-03-16 10:41:44 -0400263 if (packState.rowLength != 0 || packState.skipRows != 0 || packState.skipPixels != 0)
264 {
265 UNIMPLEMENTED();
266 return gl::Error(GL_INVALID_OPERATION, "invalid pixel store parameters in readPixels");
267 }
268
Geoff Lang4ad17092015-03-10 16:47:44 -0400269 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, mFramebufferID);
270 mFunctions->readPixels(area.x, area.y, area.width, area.height, format, type, pixels);
271
272 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500273}
274
275gl::Error FramebufferGL::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
276 GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer)
277{
Geoff Lang4ad17092015-03-10 16:47:44 -0400278 const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(sourceFramebuffer);
279
280 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
281 mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferID);
282
283 mFunctions->blitFramebuffer(sourceArea.x, sourceArea.y, sourceArea.x + sourceArea.width, sourceArea.y + sourceArea.height,
284 destArea.x, destArea.y, destArea.x + destArea.width, destArea.y + destArea.height,
285 mask, filter);
286
287 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500288}
289
290GLenum FramebufferGL::checkStatus() const
291{
Geoff Lang4ad17092015-03-10 16:47:44 -0400292 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
293 return mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
294}
295
296GLuint FramebufferGL::getFramebufferID() const
297{
298 return mFramebufferID;
Geoff Langf9a6f082015-01-22 13:32:49 -0500299}
300
301}