blob: 92e08cc06f3df250daca2c5af2a903ecd93e3956 [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"
Geoff Langf9a6f082015-01-22 13:32:49 -050022
23namespace rx
24{
25
Geoff Langafd7f0a2015-09-09 15:33:31 -040026FramebufferGL::FramebufferGL(const gl::Framebuffer::Data &data,
27 const FunctionsGL *functions,
28 StateManagerGL *stateManager,
29 const WorkaroundsGL &workarounds,
30 bool isDefault)
Geoff Lang4ad17092015-03-10 16:47:44 -040031 : FramebufferImpl(data),
32 mFunctions(functions),
33 mStateManager(stateManager),
Geoff Langafd7f0a2015-09-09 15:33:31 -040034 mWorkarounds(workarounds),
Corentin Wallez6ab01b92015-08-03 10:16:36 -070035 mFramebufferID(0),
36 mIsDefault(isDefault)
Geoff Lang4ad17092015-03-10 16:47:44 -040037{
Corentin Wallez6ab01b92015-08-03 10:16:36 -070038 if (!mIsDefault)
Geoff Lang4ad17092015-03-10 16:47:44 -040039 {
40 mFunctions->genFramebuffers(1, &mFramebufferID);
41 }
42}
Geoff Langf9a6f082015-01-22 13:32:49 -050043
Corentin Wallez86f8dd72015-08-12 12:37:48 -070044FramebufferGL::FramebufferGL(GLuint id,
45 const gl::Framebuffer::Data &data,
46 const FunctionsGL *functions,
Geoff Langafd7f0a2015-09-09 15:33:31 -040047 const WorkaroundsGL &workarounds,
Corentin Wallez86f8dd72015-08-12 12:37:48 -070048 StateManagerGL *stateManager)
49 : FramebufferImpl(data),
50 mFunctions(functions),
51 mStateManager(stateManager),
Geoff Langafd7f0a2015-09-09 15:33:31 -040052 mWorkarounds(workarounds),
Corentin Wallez86f8dd72015-08-12 12:37:48 -070053 mFramebufferID(id),
54 mIsDefault(true)
55{
56}
57
Geoff Langf9a6f082015-01-22 13:32:49 -050058FramebufferGL::~FramebufferGL()
Geoff Lang4ad17092015-03-10 16:47:44 -040059{
Geoff Lang1eb708e2015-05-04 14:58:23 -040060 mStateManager->deleteFramebuffer(mFramebufferID);
61 mFramebufferID = 0;
Geoff Lang4ad17092015-03-10 16:47:44 -040062}
63
64static void BindFramebufferAttachment(const FunctionsGL *functions, GLenum attachmentPoint,
65 const gl::FramebufferAttachment *attachment)
66{
67 if (attachment)
68 {
69 if (attachment->type() == GL_TEXTURE)
70 {
Jamie Madill5160ec12015-04-14 08:13:48 -040071 const gl::Texture *texture = attachment->getTexture();
Geoff Lang4ad17092015-03-10 16:47:44 -040072 const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
73
74 if (texture->getTarget() == GL_TEXTURE_2D)
75 {
76 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_2D,
77 textureGL->getTextureID(), attachment->mipLevel());
78 }
79 else if (texture->getTarget() == GL_TEXTURE_CUBE_MAP)
80 {
81 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, attachment->cubeMapFace(),
82 textureGL->getTextureID(), attachment->mipLevel());
83 }
84 else if (texture->getTarget() == GL_TEXTURE_2D_ARRAY || texture->getTarget() == GL_TEXTURE_3D)
85 {
86 functions->framebufferTextureLayer(GL_FRAMEBUFFER, attachmentPoint, textureGL->getTextureID(),
87 attachment->mipLevel(), attachment->layer());
88 }
89 else
90 {
91 UNREACHABLE();
92 }
93 }
94 else if (attachment->type() == GL_RENDERBUFFER)
95 {
Jamie Madill5160ec12015-04-14 08:13:48 -040096 const gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
Geoff Langcd69f1c2015-03-18 14:33:23 -040097 const RenderbufferGL *renderbufferGL = GetImplAs<RenderbufferGL>(renderbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -040098
Geoff Langcd69f1c2015-03-18 14:33:23 -040099 functions->framebufferRenderbuffer(GL_FRAMEBUFFER, attachmentPoint, GL_RENDERBUFFER,
100 renderbufferGL->getRenderbufferID());
Geoff Lang4ad17092015-03-10 16:47:44 -0400101 }
102 else
103 {
104 UNREACHABLE();
105 }
106 }
107 else
108 {
109 // Unbind this attachment
110 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_2D, 0, 0);
111 }
112}
Geoff Langf9a6f082015-01-22 13:32:49 -0500113
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400114void FramebufferGL::onUpdateColorAttachment(size_t index)
Geoff Langf9a6f082015-01-22 13:32:49 -0500115{
Corentin Wallez6ab01b92015-08-03 10:16:36 -0700116 if (!mIsDefault)
Geoff Lang4ad17092015-03-10 16:47:44 -0400117 {
118 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700119 BindFramebufferAttachment(mFunctions, GL_COLOR_ATTACHMENT0 + static_cast<GLenum>(index),
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400120 mData.getColorAttachment(static_cast<unsigned int>(index)));
Geoff Lang4ad17092015-03-10 16:47:44 -0400121 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500122}
123
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400124void FramebufferGL::onUpdateDepthAttachment()
Geoff Langf9a6f082015-01-22 13:32:49 -0500125{
Corentin Wallez6ab01b92015-08-03 10:16:36 -0700126 if (!mIsDefault)
Geoff Lang4ad17092015-03-10 16:47:44 -0400127 {
128 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400129 BindFramebufferAttachment(mFunctions,
130 GL_DEPTH_ATTACHMENT,
131 mData.getDepthAttachment());
Geoff Lang4ad17092015-03-10 16:47:44 -0400132 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500133}
134
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400135void FramebufferGL::onUpdateStencilAttachment()
Geoff Langf9a6f082015-01-22 13:32:49 -0500136{
Corentin Wallez6ab01b92015-08-03 10:16:36 -0700137 if (!mIsDefault)
Geoff Lang4ad17092015-03-10 16:47:44 -0400138 {
139 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400140 BindFramebufferAttachment(mFunctions,
141 GL_STENCIL_ATTACHMENT,
142 mData.getStencilAttachment());
Geoff Lang4ad17092015-03-10 16:47:44 -0400143 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500144}
145
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400146void FramebufferGL::onUpdateDepthStencilAttachment()
Geoff Langf9a6f082015-01-22 13:32:49 -0500147{
Corentin Wallez6ab01b92015-08-03 10:16:36 -0700148 if (!mIsDefault)
Geoff Lang4ad17092015-03-10 16:47:44 -0400149 {
150 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Jamie Madill7d75e2b2015-04-30 09:42:18 -0400151 BindFramebufferAttachment(mFunctions,
152 GL_DEPTH_STENCIL_ATTACHMENT,
153 mData.getDepthStencilAttachment());
Geoff Lang4ad17092015-03-10 16:47:44 -0400154 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500155}
156
157void FramebufferGL::setDrawBuffers(size_t count, const GLenum *buffers)
158{
Corentin Wallez6ab01b92015-08-03 10:16:36 -0700159 if (!mIsDefault)
Geoff Lang4ad17092015-03-10 16:47:44 -0400160 {
161 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700162 mFunctions->drawBuffers(static_cast<GLsizei>(count), buffers);
Geoff Lang4ad17092015-03-10 16:47:44 -0400163 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500164}
165
166void FramebufferGL::setReadBuffer(GLenum buffer)
167{
Corentin Wallez6ab01b92015-08-03 10:16:36 -0700168 if (!mIsDefault)
Geoff Lang4ad17092015-03-10 16:47:44 -0400169 {
170 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
171 mFunctions->readBuffer(buffer);
172 }
Geoff Langf9a6f082015-01-22 13:32:49 -0500173}
174
Austin Kinross08332632015-05-05 13:35:47 -0700175gl::Error FramebufferGL::discard(size_t count, const GLenum *attachments)
176{
177 UNIMPLEMENTED();
178 return gl::Error(GL_INVALID_OPERATION);
179}
180
Geoff Langf9a6f082015-01-22 13:32:49 -0500181gl::Error FramebufferGL::invalidate(size_t count, const GLenum *attachments)
182{
Geoff Lang64a72442015-04-01 14:43:11 -0400183 // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is available.
184 if (mFunctions->invalidateFramebuffer)
185 {
186 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700187 mFunctions->invalidateFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count), attachments);
Geoff Lang64a72442015-04-01 14:43:11 -0400188 }
189
Geoff Lang4ad17092015-03-10 16:47:44 -0400190 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500191}
192
193gl::Error FramebufferGL::invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area)
194{
Geoff Lang64a72442015-04-01 14:43:11 -0400195 // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is available.
196 if (mFunctions->invalidateSubFramebuffer)
197 {
198 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700199 mFunctions->invalidateSubFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
200 attachments, area.x, area.y, area.width, area.height);
Geoff Lang64a72442015-04-01 14:43:11 -0400201 }
202
Geoff Lang4ad17092015-03-10 16:47:44 -0400203 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500204}
205
Jamie Madilld1f5ef22015-04-01 14:17:06 -0400206gl::Error FramebufferGL::clear(const gl::Data &data, GLbitfield mask)
Geoff Langf9a6f082015-01-22 13:32:49 -0500207{
Geoff Langafd7f0a2015-09-09 15:33:31 -0400208 syncClearState(mask);
Geoff Lang4ad17092015-03-10 16:47:44 -0400209 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
210 mFunctions->clear(mask);
211
212 return gl::Error(GL_NO_ERROR);
213}
214
Geoff Langf9a6f082015-01-22 13:32:49 -0500215gl::Error FramebufferGL::clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values)
216{
Geoff Langafd7f0a2015-09-09 15:33:31 -0400217 syncClearBufferState(buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400218 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
219 mFunctions->clearBufferfv(buffer, drawbuffer, values);
220
221 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500222}
223
224gl::Error FramebufferGL::clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values)
225{
Geoff Langafd7f0a2015-09-09 15:33:31 -0400226 syncClearBufferState(buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400227 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
228 mFunctions->clearBufferuiv(buffer, drawbuffer, values);
229
230 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500231}
232
233gl::Error FramebufferGL::clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values)
234{
Geoff Langafd7f0a2015-09-09 15:33:31 -0400235 syncClearBufferState(buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400236 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
237 mFunctions->clearBufferiv(buffer, drawbuffer, values);
238
239 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500240}
241
242gl::Error FramebufferGL::clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
243{
Geoff Langafd7f0a2015-09-09 15:33:31 -0400244 syncClearBufferState(buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400245 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
246 mFunctions->clearBufferfi(buffer, drawbuffer, depth, stencil);
247
248 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500249}
250
251GLenum FramebufferGL::getImplementationColorReadFormat() const
252{
Geoff Lang4ad17092015-03-10 16:47:44 -0400253 const gl::FramebufferAttachment *readAttachment = getData().getReadAttachment();
254 GLenum internalFormat = readAttachment->getInternalFormat();
255 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
256 return internalFormatInfo.format;
Geoff Langf9a6f082015-01-22 13:32:49 -0500257}
258
259GLenum FramebufferGL::getImplementationColorReadType() const
260{
Geoff Lang4ad17092015-03-10 16:47:44 -0400261 const gl::FramebufferAttachment *readAttachment = getData().getReadAttachment();
262 GLenum internalFormat = readAttachment->getInternalFormat();
263 const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
264 return internalFormatInfo.type;
Geoff Langf9a6f082015-01-22 13:32:49 -0500265}
266
267gl::Error FramebufferGL::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const
268{
Geoff Langda34d002015-09-04 11:08:59 -0400269 // TODO: don't sync the pixel pack state here once the dirty bits contain the pixel pack buffer
270 // binding
Jamie Madill87de3622015-03-16 10:41:44 -0400271 const gl::PixelPackState &packState = state.getPackState();
Geoff Langda34d002015-09-04 11:08:59 -0400272 mStateManager->setPixelPackState(packState);
Jamie Madill87de3622015-03-16 10:41:44 -0400273
Geoff Lang4ad17092015-03-10 16:47:44 -0400274 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, mFramebufferID);
275 mFunctions->readPixels(area.x, area.y, area.width, area.height, format, type, pixels);
276
277 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500278}
279
280gl::Error FramebufferGL::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
281 GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer)
282{
Geoff Lang4ad17092015-03-10 16:47:44 -0400283 const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(sourceFramebuffer);
284
285 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
286 mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferID);
287
288 mFunctions->blitFramebuffer(sourceArea.x, sourceArea.y, sourceArea.x + sourceArea.width, sourceArea.y + sourceArea.height,
289 destArea.x, destArea.y, destArea.x + destArea.width, destArea.y + destArea.height,
290 mask, filter);
291
292 return gl::Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500293}
294
295GLenum FramebufferGL::checkStatus() const
296{
Geoff Lang4ad17092015-03-10 16:47:44 -0400297 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
298 return mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
299}
300
301GLuint FramebufferGL::getFramebufferID() const
302{
303 return mFramebufferID;
Geoff Langf9a6f082015-01-22 13:32:49 -0500304}
305
Geoff Langafd7f0a2015-09-09 15:33:31 -0400306void FramebufferGL::syncDrawState() const
307{
308 if (mFunctions->standard == STANDARD_GL_DESKTOP)
309 {
310 // Enable SRGB blending for all framebuffers except the default framebuffer on Desktop
311 // OpenGL.
312 // When SRGB blending is enabled, only SRGB capable formats will use it but the default
313 // framebuffer will always use it if it is enabled.
314 // TODO(geofflang): Update this when the framebuffer binding dirty changes, when it exists.
315 mStateManager->setFramebufferSRGBEnabled(!mIsDefault);
316 }
317}
318
319void FramebufferGL::syncClearState(GLbitfield mask)
320{
321 if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments &&
322 (mask & GL_COLOR_BUFFER_BIT) != 0 && !mIsDefault)
323 {
324 bool hasSRBAttachment = false;
325 for (const auto &attachment : mData.getColorAttachments())
326 {
327 if (attachment.isAttached() && attachment.getColorEncoding() == GL_SRGB)
328 {
329 hasSRBAttachment = true;
330 break;
331 }
332 }
333
334 mStateManager->setFramebufferSRGBEnabled(hasSRBAttachment);
335 }
336 else
337 {
338 mStateManager->setFramebufferSRGBEnabled(!mIsDefault);
339 }
340}
341
342void FramebufferGL::syncClearBufferState(GLenum buffer, GLint drawBuffer)
343{
344 if (mFunctions->standard == STANDARD_GL_DESKTOP)
345 {
346 if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments && buffer == GL_COLOR &&
347 !mIsDefault)
348 {
349 // If doing a clear on a color buffer, set SRGB blend enabled only if the color buffer
350 // is an SRGB format.
351 const auto &drawbufferState = mData.getDrawBufferStates();
352 const auto &colorAttachments = mData.getColorAttachments();
353
354 const gl::FramebufferAttachment *attachment = nullptr;
355 if (drawbufferState[drawBuffer] >= GL_COLOR_ATTACHMENT0 &&
356 drawbufferState[drawBuffer] < GL_COLOR_ATTACHMENT0 + colorAttachments.size())
357 {
358 size_t attachmentIdx =
359 static_cast<size_t>(drawbufferState[drawBuffer] - GL_COLOR_ATTACHMENT0);
360 attachment = &colorAttachments[attachmentIdx];
361 }
362
363 if (attachment != nullptr)
364 {
365 mStateManager->setFramebufferSRGBEnabled(attachment->getColorEncoding() == GL_SRGB);
366 }
367 }
368 else
369 {
370 mStateManager->setFramebufferSRGBEnabled(!mIsDefault);
371 }
372 }
373}
Geoff Langf9a6f082015-01-22 13:32:49 -0500374}