blob: 1f4f4e03fcd9b880216e9570568d5e0b5c97bbef [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 Langafd7f0a2015-09-09 15:33:31 -040021#include "libANGLE/renderer/gl/WorkaroundsGL.h"
Jamie Madillcc86d642015-11-24 13:00:07 -050022#include "platform/Platform.h"
Geoff Langf9a6f082015-01-22 13:32:49 -050023
24namespace rx
25{
26
Geoff Langafd7f0a2015-09-09 15:33:31 -040027FramebufferGL::FramebufferGL(const gl::Framebuffer::Data &data,
28 const FunctionsGL *functions,
29 StateManagerGL *stateManager,
30 const WorkaroundsGL &workarounds,
31 bool isDefault)
Geoff Lang4ad17092015-03-10 16:47:44 -040032 : FramebufferImpl(data),
33 mFunctions(functions),
34 mStateManager(stateManager),
Geoff Langafd7f0a2015-09-09 15:33:31 -040035 mWorkarounds(workarounds),
Corentin Wallez6ab01b92015-08-03 10:16:36 -070036 mFramebufferID(0),
37 mIsDefault(isDefault)
Geoff Lang4ad17092015-03-10 16:47:44 -040038{
Corentin Wallez6ab01b92015-08-03 10:16:36 -070039 if (!mIsDefault)
Geoff Lang4ad17092015-03-10 16:47:44 -040040 {
41 mFunctions->genFramebuffers(1, &mFramebufferID);
42 }
43}
Geoff Langf9a6f082015-01-22 13:32:49 -050044
Corentin Wallez86f8dd72015-08-12 12:37:48 -070045FramebufferGL::FramebufferGL(GLuint id,
46 const gl::Framebuffer::Data &data,
47 const FunctionsGL *functions,
Geoff Langafd7f0a2015-09-09 15:33:31 -040048 const WorkaroundsGL &workarounds,
Corentin Wallez86f8dd72015-08-12 12:37:48 -070049 StateManagerGL *stateManager)
50 : FramebufferImpl(data),
51 mFunctions(functions),
52 mStateManager(stateManager),
Geoff Langafd7f0a2015-09-09 15:33:31 -040053 mWorkarounds(workarounds),
Corentin Wallez86f8dd72015-08-12 12:37:48 -070054 mFramebufferID(id),
55 mIsDefault(true)
56{
57}
58
Geoff Langf9a6f082015-01-22 13:32:49 -050059FramebufferGL::~FramebufferGL()
Geoff Lang4ad17092015-03-10 16:47:44 -040060{
Geoff Lang1eb708e2015-05-04 14:58:23 -040061 mStateManager->deleteFramebuffer(mFramebufferID);
62 mFramebufferID = 0;
Geoff Lang4ad17092015-03-10 16:47:44 -040063}
64
65static void BindFramebufferAttachment(const FunctionsGL *functions, GLenum attachmentPoint,
66 const gl::FramebufferAttachment *attachment)
67{
68 if (attachment)
69 {
70 if (attachment->type() == GL_TEXTURE)
71 {
Jamie Madill5160ec12015-04-14 08:13:48 -040072 const gl::Texture *texture = attachment->getTexture();
Geoff Lang4ad17092015-03-10 16:47:44 -040073 const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
74
75 if (texture->getTarget() == GL_TEXTURE_2D)
76 {
77 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_2D,
78 textureGL->getTextureID(), attachment->mipLevel());
79 }
80 else if (texture->getTarget() == GL_TEXTURE_CUBE_MAP)
81 {
82 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, attachment->cubeMapFace(),
83 textureGL->getTextureID(), attachment->mipLevel());
84 }
85 else if (texture->getTarget() == GL_TEXTURE_2D_ARRAY || texture->getTarget() == GL_TEXTURE_3D)
86 {
87 functions->framebufferTextureLayer(GL_FRAMEBUFFER, attachmentPoint, textureGL->getTextureID(),
88 attachment->mipLevel(), attachment->layer());
89 }
90 else
91 {
92 UNREACHABLE();
93 }
94 }
95 else if (attachment->type() == GL_RENDERBUFFER)
96 {
Jamie Madill5160ec12015-04-14 08:13:48 -040097 const gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
Geoff Langcd69f1c2015-03-18 14:33:23 -040098 const RenderbufferGL *renderbufferGL = GetImplAs<RenderbufferGL>(renderbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -040099
Geoff Langcd69f1c2015-03-18 14:33:23 -0400100 functions->framebufferRenderbuffer(GL_FRAMEBUFFER, attachmentPoint, GL_RENDERBUFFER,
101 renderbufferGL->getRenderbufferID());
Geoff Lang4ad17092015-03-10 16:47:44 -0400102 }
103 else
104 {
105 UNREACHABLE();
106 }
107 }
108 else
109 {
110 // Unbind this attachment
111 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_2D, 0, 0);
112 }
113}
Geoff Langf9a6f082015-01-22 13:32:49 -0500114
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400115void FramebufferGL::onUpdateColorAttachment(size_t index)
Geoff Langf9a6f082015-01-22 13:32:49 -0500116{
Corentin Wallez6ab01b92015-08-03 10:16:36 -0700117 if (!mIsDefault)
Geoff Lang4ad17092015-03-10 16:47:44 -0400118 {
119 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700120 BindFramebufferAttachment(mFunctions, GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(index),
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400121 mData.getColorAttachment(static_cast<unsigned int>(index)));
Geoff Lang4ad17092015-03-10 16:47:44 -0400122 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500123}
124
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400125void FramebufferGL::onUpdateDepthAttachment()
Geoff Langf9a6f082015-01-22 13:32:49 -0500126{
Corentin Wallez6ab01b92015-08-03 10:16:36 -0700127 if (!mIsDefault)
Geoff Lang4ad17092015-03-10 16:47:44 -0400128 {
129 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400130 BindFramebufferAttachment(mFunctions,
131 GL_DEPTH_ATTACHMENT,
132 mData.getDepthAttachment());
Geoff Lang4ad17092015-03-10 16:47:44 -0400133 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500134}
135
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400136void FramebufferGL::onUpdateStencilAttachment()
Geoff Langf9a6f082015-01-22 13:32:49 -0500137{
Corentin Wallez6ab01b92015-08-03 10:16:36 -0700138 if (!mIsDefault)
Geoff Lang4ad17092015-03-10 16:47:44 -0400139 {
140 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400141 BindFramebufferAttachment(mFunctions,
142 GL_STENCIL_ATTACHMENT,
143 mData.getStencilAttachment());
Geoff Lang4ad17092015-03-10 16:47:44 -0400144 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500145}
146
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400147void FramebufferGL::onUpdateDepthStencilAttachment()
Geoff Langf9a6f082015-01-22 13:32:49 -0500148{
Corentin Wallez6ab01b92015-08-03 10:16:36 -0700149 if (!mIsDefault)
Geoff Lang4ad17092015-03-10 16:47:44 -0400150 {
151 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400152 BindFramebufferAttachment(mFunctions,
153 GL_DEPTH_STENCIL_ATTACHMENT,
154 mData.getDepthStencilAttachment());
Geoff Lang4ad17092015-03-10 16:47:44 -0400155 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500156}
157
158void FramebufferGL::setDrawBuffers(size_t count, const GLenum *buffers)
159{
Corentin Wallez6ab01b92015-08-03 10:16:36 -0700160 if (!mIsDefault)
Geoff Lang4ad17092015-03-10 16:47:44 -0400161 {
162 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700163 mFunctions->drawBuffers(static_cast<GLsizei>(count), buffers);
Geoff Lang4ad17092015-03-10 16:47:44 -0400164 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500165}
166
167void FramebufferGL::setReadBuffer(GLenum buffer)
168{
Corentin Wallez6ab01b92015-08-03 10:16:36 -0700169 if (!mIsDefault)
Geoff Lang4ad17092015-03-10 16:47:44 -0400170 {
171 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
172 mFunctions->readBuffer(buffer);
173 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500174}
175
Austin Kinross08332632015-05-05 13:35:47 -0700176gl::Error FramebufferGL::discard(size_t count, const GLenum *attachments)
177{
178 UNIMPLEMENTED();
179 return gl::Error(GL_INVALID_OPERATION);
180}
181
Geoff Langf9a6f082015-01-22 13:32:49 -0500182gl::Error FramebufferGL::invalidate(size_t count, const GLenum *attachments)
183{
Geoff Lang64a72442015-04-01 14:43:11 -0400184 // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is available.
185 if (mFunctions->invalidateFramebuffer)
186 {
187 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700188 mFunctions->invalidateFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count), attachments);
Geoff Lang64a72442015-04-01 14:43:11 -0400189 }
190
Geoff Lang4ad17092015-03-10 16:47:44 -0400191 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500192}
193
194gl::Error FramebufferGL::invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area)
195{
Geoff Lang64a72442015-04-01 14:43:11 -0400196 // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is available.
197 if (mFunctions->invalidateSubFramebuffer)
198 {
199 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700200 mFunctions->invalidateSubFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
201 attachments, area.x, area.y, area.width, area.height);
Geoff Lang64a72442015-04-01 14:43:11 -0400202 }
203
Geoff Lang4ad17092015-03-10 16:47:44 -0400204 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500205}
206
Jamie Madilld1f5ef22015-04-01 14:17:06 -0400207gl::Error FramebufferGL::clear(const gl::Data &data, GLbitfield mask)
Geoff Langf9a6f082015-01-22 13:32:49 -0500208{
Geoff Langafd7f0a2015-09-09 15:33:31 -0400209 syncClearState(mask);
Geoff Lang4ad17092015-03-10 16:47:44 -0400210 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
211 mFunctions->clear(mask);
212
213 return gl::Error(GL_NO_ERROR);
214}
215
Dian Xiang40281592015-11-19 18:24:44 -0800216gl::Error FramebufferGL::clearBufferfv(const gl::Data &data,
217 GLenum buffer,
218 GLint drawbuffer,
219 const GLfloat *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500220{
Geoff Langafd7f0a2015-09-09 15:33:31 -0400221 syncClearBufferState(buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400222 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
223 mFunctions->clearBufferfv(buffer, drawbuffer, values);
224
225 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500226}
227
Dian Xiang40281592015-11-19 18:24:44 -0800228gl::Error FramebufferGL::clearBufferuiv(const gl::Data &data,
229 GLenum buffer,
230 GLint drawbuffer,
231 const GLuint *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500232{
Geoff Langafd7f0a2015-09-09 15:33:31 -0400233 syncClearBufferState(buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400234 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
235 mFunctions->clearBufferuiv(buffer, drawbuffer, values);
236
237 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500238}
239
Dian Xiang40281592015-11-19 18:24:44 -0800240gl::Error FramebufferGL::clearBufferiv(const gl::Data &data,
241 GLenum buffer,
242 GLint drawbuffer,
243 const GLint *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500244{
Geoff Langafd7f0a2015-09-09 15:33:31 -0400245 syncClearBufferState(buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400246 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
247 mFunctions->clearBufferiv(buffer, drawbuffer, values);
248
249 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500250}
251
Dian Xiang40281592015-11-19 18:24:44 -0800252gl::Error FramebufferGL::clearBufferfi(const gl::Data &data,
253 GLenum buffer,
254 GLint drawbuffer,
255 GLfloat depth,
256 GLint stencil)
Geoff Langf9a6f082015-01-22 13:32:49 -0500257{
Geoff Langafd7f0a2015-09-09 15:33:31 -0400258 syncClearBufferState(buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400259 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
260 mFunctions->clearBufferfi(buffer, drawbuffer, depth, stencil);
261
262 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500263}
264
265GLenum FramebufferGL::getImplementationColorReadFormat() const
266{
Geoff Lang4ad17092015-03-10 16:47:44 -0400267 const gl::FramebufferAttachment *readAttachment = getData().getReadAttachment();
268 GLenum internalFormat = readAttachment->getInternalFormat();
269 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
270 return internalFormatInfo.format;
Geoff Langf9a6f082015-01-22 13:32:49 -0500271}
272
273GLenum FramebufferGL::getImplementationColorReadType() const
274{
Geoff Lang4ad17092015-03-10 16:47:44 -0400275 const gl::FramebufferAttachment *readAttachment = getData().getReadAttachment();
276 GLenum internalFormat = readAttachment->getInternalFormat();
277 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
278 return internalFormatInfo.type;
Geoff Langf9a6f082015-01-22 13:32:49 -0500279}
280
281gl::Error FramebufferGL::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const
282{
Geoff Langda34d002015-09-04 11:08:59 -0400283 // TODO: don't sync the pixel pack state here once the dirty bits contain the pixel pack buffer
284 // binding
Jamie Madill87de3622015-03-16 10:41:44 -0400285 const gl::PixelPackState &packState = state.getPackState();
Geoff Langda34d002015-09-04 11:08:59 -0400286 mStateManager->setPixelPackState(packState);
Jamie Madill87de3622015-03-16 10:41:44 -0400287
Geoff Lang4ad17092015-03-10 16:47:44 -0400288 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, mFramebufferID);
289 mFunctions->readPixels(area.x, area.y, area.width, area.height, format, type, pixels);
290
291 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500292}
293
294gl::Error FramebufferGL::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
295 GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer)
296{
Geoff Lang4ad17092015-03-10 16:47:44 -0400297 const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(sourceFramebuffer);
298
299 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
300 mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferID);
301
Jamie Madill2da819e2015-12-03 15:53:19 -0500302 mFunctions->blitFramebuffer(sourceArea.x, sourceArea.y, sourceArea.x1(), sourceArea.y1(),
303 destArea.x, destArea.y, destArea.x1(), destArea.y1(), mask, filter);
Geoff Lang4ad17092015-03-10 16:47:44 -0400304
305 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500306}
307
Jamie Madillcc86d642015-11-24 13:00:07 -0500308bool FramebufferGL::checkStatus() const
Geoff Langf9a6f082015-01-22 13:32:49 -0500309{
Geoff Lang4ad17092015-03-10 16:47:44 -0400310 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Jamie Madillcc86d642015-11-24 13:00:07 -0500311 GLenum status = mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
312 if (status != GL_FRAMEBUFFER_COMPLETE)
313 {
314 ANGLEPlatformCurrent()->logWarning("GL framebuffer returned incomplete.");
315 }
316 return (status == GL_FRAMEBUFFER_COMPLETE);
Geoff Lang4ad17092015-03-10 16:47:44 -0400317}
318
319GLuint FramebufferGL::getFramebufferID() const
320{
321 return mFramebufferID;
Geoff Langf9a6f082015-01-22 13:32:49 -0500322}
323
Geoff Langafd7f0a2015-09-09 15:33:31 -0400324void FramebufferGL::syncDrawState() const
325{
326 if (mFunctions->standard == STANDARD_GL_DESKTOP)
327 {
328 // Enable SRGB blending for all framebuffers except the default framebuffer on Desktop
329 // OpenGL.
330 // When SRGB blending is enabled, only SRGB capable formats will use it but the default
331 // framebuffer will always use it if it is enabled.
332 // TODO(geofflang): Update this when the framebuffer binding dirty changes, when it exists.
333 mStateManager->setFramebufferSRGBEnabled(!mIsDefault);
334 }
335}
336
337void FramebufferGL::syncClearState(GLbitfield mask)
338{
339 if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments &&
340 (mask & GL_COLOR_BUFFER_BIT) != 0 && !mIsDefault)
341 {
342 bool hasSRBAttachment = false;
343 for (const auto &attachment : mData.getColorAttachments())
344 {
345 if (attachment.isAttached() && attachment.getColorEncoding() == GL_SRGB)
346 {
347 hasSRBAttachment = true;
348 break;
349 }
350 }
351
352 mStateManager->setFramebufferSRGBEnabled(hasSRBAttachment);
353 }
354 else
355 {
356 mStateManager->setFramebufferSRGBEnabled(!mIsDefault);
357 }
358}
359
360void FramebufferGL::syncClearBufferState(GLenum buffer, GLint drawBuffer)
361{
362 if (mFunctions->standard == STANDARD_GL_DESKTOP)
363 {
364 if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments && buffer == GL_COLOR &&
365 !mIsDefault)
366 {
367 // If doing a clear on a color buffer, set SRGB blend enabled only if the color buffer
368 // is an SRGB format.
369 const auto &drawbufferState = mData.getDrawBufferStates();
370 const auto &colorAttachments = mData.getColorAttachments();
371
372 const gl::FramebufferAttachment *attachment = nullptr;
373 if (drawbufferState[drawBuffer] >= GL_COLOR_ATTACHMENT0 &&
374 drawbufferState[drawBuffer] < GL_COLOR_ATTACHMENT0 + colorAttachments.size())
375 {
376 size_t attachmentIdx =
377 static_cast<size_t>(drawbufferState[drawBuffer] - GL_COLOR_ATTACHMENT0);
378 attachment = &colorAttachments[attachmentIdx];
379 }
380
381 if (attachment != nullptr)
382 {
383 mStateManager->setFramebufferSRGBEnabled(attachment->getColorEncoding() == GL_SRGB);
384 }
385 }
386 else
387 {
388 mStateManager->setFramebufferSRGBEnabled(!mIsDefault);
389 }
390 }
391}
Geoff Langf9a6f082015-01-22 13:32:49 -0500392}