blob: 53c1ab8c1e63b310f7b3dc0ba73cac3462b3c683 [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
Jamie Madill7d75e2b2015-04-30 09:42:18 -040096void FramebufferGL::onUpdateColorAttachment(size_t index)
Geoff Langf9a6f082015-01-22 13:32:49 -050097{
Geoff Lang4ad17092015-03-10 16:47:44 -040098 if (mFramebufferID != 0)
99 {
100 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400101 BindFramebufferAttachment(mFunctions,
102 GL_COLOR_ATTACHMENT0 + index,
103 mData.getColorAttachment(static_cast<unsigned int>(index)));
Geoff Lang4ad17092015-03-10 16:47:44 -0400104 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500105}
106
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400107void FramebufferGL::onUpdateDepthAttachment()
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);
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400112 BindFramebufferAttachment(mFunctions,
113 GL_DEPTH_ATTACHMENT,
114 mData.getDepthAttachment());
Geoff Lang4ad17092015-03-10 16:47:44 -0400115 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500116}
117
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400118void FramebufferGL::onUpdateStencilAttachment()
Geoff Langf9a6f082015-01-22 13:32:49 -0500119{
Geoff Lang4ad17092015-03-10 16:47:44 -0400120 if (mFramebufferID != 0)
121 {
122 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400123 BindFramebufferAttachment(mFunctions,
124 GL_STENCIL_ATTACHMENT,
125 mData.getStencilAttachment());
Geoff Lang4ad17092015-03-10 16:47:44 -0400126 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500127}
128
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400129void FramebufferGL::onUpdateDepthStencilAttachment()
Geoff Langf9a6f082015-01-22 13:32:49 -0500130{
Geoff Lang4ad17092015-03-10 16:47:44 -0400131 if (mFramebufferID != 0)
132 {
133 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400134 BindFramebufferAttachment(mFunctions,
135 GL_DEPTH_STENCIL_ATTACHMENT,
136 mData.getDepthStencilAttachment());
Geoff Lang4ad17092015-03-10 16:47:44 -0400137 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500138}
139
140void FramebufferGL::setDrawBuffers(size_t count, const GLenum *buffers)
141{
Geoff Lang4ad17092015-03-10 16:47:44 -0400142 if (mFramebufferID != 0)
143 {
144 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
145 mFunctions->drawBuffers(count, buffers);
146 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500147}
148
149void FramebufferGL::setReadBuffer(GLenum buffer)
150{
Geoff Lang4ad17092015-03-10 16:47:44 -0400151 if (mFramebufferID != 0)
152 {
153 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
154 mFunctions->readBuffer(buffer);
155 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500156}
157
158gl::Error FramebufferGL::invalidate(size_t count, const GLenum *attachments)
159{
Geoff Lang64a72442015-04-01 14:43:11 -0400160 // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is available.
161 if (mFunctions->invalidateFramebuffer)
162 {
163 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
164 mFunctions->invalidateFramebuffer(GL_FRAMEBUFFER, count, attachments);
165 }
166
Geoff Lang4ad17092015-03-10 16:47:44 -0400167 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500168}
169
170gl::Error FramebufferGL::invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area)
171{
Geoff Lang64a72442015-04-01 14:43:11 -0400172 // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is available.
173 if (mFunctions->invalidateSubFramebuffer)
174 {
175 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
176 mFunctions->invalidateSubFramebuffer(GL_FRAMEBUFFER, count, attachments, area.x, area.y, area.width, area.height);
177 }
178
Geoff Lang4ad17092015-03-10 16:47:44 -0400179 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500180}
181
Jamie Madilld1f5ef22015-04-01 14:17:06 -0400182gl::Error FramebufferGL::clear(const gl::Data &data, GLbitfield mask)
Geoff Langf9a6f082015-01-22 13:32:49 -0500183{
Jamie Madilld1f5ef22015-04-01 14:17:06 -0400184 mStateManager->setClearState(*data.state, mask);
Geoff Lang4ad17092015-03-10 16:47:44 -0400185 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
186 mFunctions->clear(mask);
187
188 return gl::Error(GL_NO_ERROR);
189}
190
191static GLbitfield GetClearBufferMask(GLenum buffer)
192{
193 switch (buffer)
194 {
195 case GL_COLOR: return GL_COLOR_BUFFER_BIT;
196 case GL_DEPTH: return GL_DEPTH_BUFFER_BIT;
197 case GL_STENCIL: return GL_STENCIL_BUFFER_BIT;
198 case GL_DEPTH_STENCIL: return GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT;
199 default: UNREACHABLE(); return 0;
200 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500201}
202
203gl::Error FramebufferGL::clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values)
204{
Geoff Lang4ad17092015-03-10 16:47:44 -0400205 mStateManager->setClearState(state, GetClearBufferMask(buffer));
206 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
207 mFunctions->clearBufferfv(buffer, drawbuffer, values);
208
209 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500210}
211
212gl::Error FramebufferGL::clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values)
213{
Geoff Lang4ad17092015-03-10 16:47:44 -0400214 mStateManager->setClearState(state, GetClearBufferMask(buffer));
215 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
216 mFunctions->clearBufferuiv(buffer, drawbuffer, values);
217
218 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500219}
220
221gl::Error FramebufferGL::clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values)
222{
Geoff Lang4ad17092015-03-10 16:47:44 -0400223 mStateManager->setClearState(state, GetClearBufferMask(buffer));
224 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
225 mFunctions->clearBufferiv(buffer, drawbuffer, values);
226
227 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500228}
229
230gl::Error FramebufferGL::clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
231{
Geoff Lang4ad17092015-03-10 16:47:44 -0400232 mStateManager->setClearState(state, GetClearBufferMask(buffer));
233 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
234 mFunctions->clearBufferfi(buffer, drawbuffer, depth, stencil);
235
236 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500237}
238
239GLenum FramebufferGL::getImplementationColorReadFormat() 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.format;
Geoff Langf9a6f082015-01-22 13:32:49 -0500245}
246
247GLenum FramebufferGL::getImplementationColorReadType() const
248{
Geoff Lang4ad17092015-03-10 16:47:44 -0400249 const gl::FramebufferAttachment *readAttachment = getData().getReadAttachment();
250 GLenum internalFormat = readAttachment->getInternalFormat();
251 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
252 return internalFormatInfo.type;
Geoff Langf9a6f082015-01-22 13:32:49 -0500253}
254
255gl::Error FramebufferGL::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const
256{
Jamie Madill87de3622015-03-16 10:41:44 -0400257 const gl::PixelPackState &packState = state.getPackState();
258
Geoff Lang4ad17092015-03-10 16:47:44 -0400259 // TODO: set pack state
Jamie Madill87de3622015-03-16 10:41:44 -0400260 if (packState.rowLength != 0 || packState.skipRows != 0 || packState.skipPixels != 0)
261 {
262 UNIMPLEMENTED();
263 return gl::Error(GL_INVALID_OPERATION, "invalid pixel store parameters in readPixels");
264 }
265
Geoff Lang4ad17092015-03-10 16:47:44 -0400266 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, mFramebufferID);
267 mFunctions->readPixels(area.x, area.y, area.width, area.height, format, type, pixels);
268
269 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500270}
271
272gl::Error FramebufferGL::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
273 GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer)
274{
Geoff Lang4ad17092015-03-10 16:47:44 -0400275 const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(sourceFramebuffer);
276
277 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
278 mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferID);
279
280 mFunctions->blitFramebuffer(sourceArea.x, sourceArea.y, sourceArea.x + sourceArea.width, sourceArea.y + sourceArea.height,
281 destArea.x, destArea.y, destArea.x + destArea.width, destArea.y + destArea.height,
282 mask, filter);
283
284 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500285}
286
287GLenum FramebufferGL::checkStatus() const
288{
Geoff Lang4ad17092015-03-10 16:47:44 -0400289 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
290 return mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
291}
292
293GLuint FramebufferGL::getFramebufferID() const
294{
295 return mFramebufferID;
Geoff Langf9a6f082015-01-22 13:32:49 -0500296}
297
298}