blob: daa89bf4242fa69d45e051adbc5e320763b4f09d [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
Jamie Madill60ec6ea2016-01-22 15:27:19 -050011#include "common/BitSetIterator.h"
Geoff Langf9a6f082015-01-22 13:32:49 -050012#include "common/debug.h"
Jamie Madill9082b982016-04-27 15:21:51 -040013#include "libANGLE/ContextState.h"
Jamie Madill87de3622015-03-16 10:41:44 -040014#include "libANGLE/State.h"
Geoff Lang4ad17092015-03-10 16:47:44 -040015#include "libANGLE/FramebufferAttachment.h"
16#include "libANGLE/angletypes.h"
17#include "libANGLE/formatutils.h"
Jamie Madill8415b5f2016-04-26 13:41:39 -040018#include "libANGLE/renderer/ContextImpl.h"
Corentin Wallez26a717b2016-09-27 08:45:42 -070019#include "libANGLE/renderer/gl/BlitGL.h"
Geoff Lang4ad17092015-03-10 16:47:44 -040020#include "libANGLE/renderer/gl/FunctionsGL.h"
Jacek Cabanfa60f692015-04-27 18:23:44 +020021#include "libANGLE/renderer/gl/RenderbufferGL.h"
Geoff Lang4ad17092015-03-10 16:47:44 -040022#include "libANGLE/renderer/gl/StateManagerGL.h"
23#include "libANGLE/renderer/gl/TextureGL.h"
Geoff Langafd7f0a2015-09-09 15:33:31 -040024#include "libANGLE/renderer/gl/WorkaroundsGL.h"
Geoff Langf607c602016-09-21 11:46:48 -040025#include "libANGLE/renderer/gl/formatutilsgl.h"
Corentin Wallez886de362016-09-27 10:49:35 -040026#include "libANGLE/renderer/gl/renderergl_utils.h"
Jamie Madillcc86d642015-11-24 13:00:07 -050027#include "platform/Platform.h"
Geoff Langf9a6f082015-01-22 13:32:49 -050028
Jamie Madill60ec6ea2016-01-22 15:27:19 -050029using namespace gl;
Corentin Wallez9a8d3662016-09-22 12:18:29 -040030using angle::CheckedNumeric;
Jamie Madill60ec6ea2016-01-22 15:27:19 -050031
Geoff Langf9a6f082015-01-22 13:32:49 -050032namespace rx
33{
34
Jamie Madill48ef11b2016-04-27 15:21:52 -040035FramebufferGL::FramebufferGL(const FramebufferState &state,
Geoff Langafd7f0a2015-09-09 15:33:31 -040036 const FunctionsGL *functions,
37 StateManagerGL *stateManager,
38 const WorkaroundsGL &workarounds,
Corentin Wallez26a717b2016-09-27 08:45:42 -070039 BlitGL *blitter,
Geoff Langafd7f0a2015-09-09 15:33:31 -040040 bool isDefault)
Jamie Madill48ef11b2016-04-27 15:21:52 -040041 : FramebufferImpl(state),
Geoff Lang4ad17092015-03-10 16:47:44 -040042 mFunctions(functions),
43 mStateManager(stateManager),
Geoff Langafd7f0a2015-09-09 15:33:31 -040044 mWorkarounds(workarounds),
Corentin Wallez26a717b2016-09-27 08:45:42 -070045 mBlitter(blitter),
Corentin Wallez6ab01b92015-08-03 10:16:36 -070046 mFramebufferID(0),
47 mIsDefault(isDefault)
Geoff Lang4ad17092015-03-10 16:47:44 -040048{
Corentin Wallez6ab01b92015-08-03 10:16:36 -070049 if (!mIsDefault)
Geoff Lang4ad17092015-03-10 16:47:44 -040050 {
51 mFunctions->genFramebuffers(1, &mFramebufferID);
52 }
53}
Geoff Langf9a6f082015-01-22 13:32:49 -050054
Corentin Wallez86f8dd72015-08-12 12:37:48 -070055FramebufferGL::FramebufferGL(GLuint id,
Jamie Madill48ef11b2016-04-27 15:21:52 -040056 const FramebufferState &state,
Corentin Wallez86f8dd72015-08-12 12:37:48 -070057 const FunctionsGL *functions,
Geoff Langafd7f0a2015-09-09 15:33:31 -040058 const WorkaroundsGL &workarounds,
Corentin Wallez26a717b2016-09-27 08:45:42 -070059 BlitGL *blitter,
Corentin Wallez86f8dd72015-08-12 12:37:48 -070060 StateManagerGL *stateManager)
Jamie Madill48ef11b2016-04-27 15:21:52 -040061 : FramebufferImpl(state),
Corentin Wallez86f8dd72015-08-12 12:37:48 -070062 mFunctions(functions),
63 mStateManager(stateManager),
Geoff Langafd7f0a2015-09-09 15:33:31 -040064 mWorkarounds(workarounds),
Corentin Wallez26a717b2016-09-27 08:45:42 -070065 mBlitter(blitter),
Corentin Wallez86f8dd72015-08-12 12:37:48 -070066 mFramebufferID(id),
67 mIsDefault(true)
68{
69}
70
Geoff Langf9a6f082015-01-22 13:32:49 -050071FramebufferGL::~FramebufferGL()
Geoff Lang4ad17092015-03-10 16:47:44 -040072{
Geoff Lang1eb708e2015-05-04 14:58:23 -040073 mStateManager->deleteFramebuffer(mFramebufferID);
74 mFramebufferID = 0;
Geoff Lang4ad17092015-03-10 16:47:44 -040075}
76
Jamie Madill60ec6ea2016-01-22 15:27:19 -050077static void BindFramebufferAttachment(const FunctionsGL *functions,
78 GLenum attachmentPoint,
79 const FramebufferAttachment *attachment)
Geoff Lang4ad17092015-03-10 16:47:44 -040080{
81 if (attachment)
82 {
83 if (attachment->type() == GL_TEXTURE)
84 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -050085 const Texture *texture = attachment->getTexture();
Geoff Lang4ad17092015-03-10 16:47:44 -040086 const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
87
88 if (texture->getTarget() == GL_TEXTURE_2D)
89 {
90 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_2D,
91 textureGL->getTextureID(), attachment->mipLevel());
92 }
93 else if (texture->getTarget() == GL_TEXTURE_CUBE_MAP)
94 {
95 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, attachment->cubeMapFace(),
96 textureGL->getTextureID(), attachment->mipLevel());
97 }
98 else if (texture->getTarget() == GL_TEXTURE_2D_ARRAY || texture->getTarget() == GL_TEXTURE_3D)
99 {
100 functions->framebufferTextureLayer(GL_FRAMEBUFFER, attachmentPoint, textureGL->getTextureID(),
101 attachment->mipLevel(), attachment->layer());
102 }
103 else
104 {
105 UNREACHABLE();
106 }
107 }
108 else if (attachment->type() == GL_RENDERBUFFER)
109 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500110 const Renderbuffer *renderbuffer = attachment->getRenderbuffer();
Geoff Langcd69f1c2015-03-18 14:33:23 -0400111 const RenderbufferGL *renderbufferGL = GetImplAs<RenderbufferGL>(renderbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400112
Geoff Langcd69f1c2015-03-18 14:33:23 -0400113 functions->framebufferRenderbuffer(GL_FRAMEBUFFER, attachmentPoint, GL_RENDERBUFFER,
114 renderbufferGL->getRenderbufferID());
Geoff Lang4ad17092015-03-10 16:47:44 -0400115 }
116 else
117 {
118 UNREACHABLE();
119 }
120 }
121 else
122 {
123 // Unbind this attachment
124 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_2D, 0, 0);
125 }
126}
Geoff Langf9a6f082015-01-22 13:32:49 -0500127
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500128Error FramebufferGL::discard(size_t count, const GLenum *attachments)
Austin Kinross08332632015-05-05 13:35:47 -0700129{
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500130 // glInvalidateFramebuffer accepts the same enums as glDiscardFramebufferEXT
131 return invalidate(count, attachments);
Austin Kinross08332632015-05-05 13:35:47 -0700132}
133
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500134Error FramebufferGL::invalidate(size_t count, const GLenum *attachments)
Geoff Langf9a6f082015-01-22 13:32:49 -0500135{
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500136 // Since this function is just a hint, only call a native function if it exists.
Geoff Lang64a72442015-04-01 14:43:11 -0400137 if (mFunctions->invalidateFramebuffer)
138 {
139 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700140 mFunctions->invalidateFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count), attachments);
Geoff Lang64a72442015-04-01 14:43:11 -0400141 }
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500142 else if (mFunctions->discardFramebuffer)
143 {
144 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
145 mFunctions->discardFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count), attachments);
146 }
Geoff Lang64a72442015-04-01 14:43:11 -0400147
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500148 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500149}
150
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500151Error FramebufferGL::invalidateSub(size_t count,
152 const GLenum *attachments,
153 const gl::Rectangle &area)
Geoff Langf9a6f082015-01-22 13:32:49 -0500154{
Geoff Lang64a72442015-04-01 14:43:11 -0400155 // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is available.
156 if (mFunctions->invalidateSubFramebuffer)
157 {
158 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700159 mFunctions->invalidateSubFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
160 attachments, area.x, area.y, area.width, area.height);
Geoff Lang64a72442015-04-01 14:43:11 -0400161 }
162
He Yunchaoacd18982017-01-04 10:46:42 +0800163 return NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500164}
165
Jamie Madill8415b5f2016-04-26 13:41:39 -0400166Error FramebufferGL::clear(ContextImpl *context, GLbitfield mask)
Geoff Langf9a6f082015-01-22 13:32:49 -0500167{
Geoff Langafd7f0a2015-09-09 15:33:31 -0400168 syncClearState(mask);
Geoff Lang4ad17092015-03-10 16:47:44 -0400169 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
170 mFunctions->clear(mask);
171
He Yunchaoacd18982017-01-04 10:46:42 +0800172 return NoError();
Geoff Lang4ad17092015-03-10 16:47:44 -0400173}
174
Jamie Madill8415b5f2016-04-26 13:41:39 -0400175Error FramebufferGL::clearBufferfv(ContextImpl *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500176 GLenum buffer,
177 GLint drawbuffer,
178 const GLfloat *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500179{
Geoff Langafd7f0a2015-09-09 15:33:31 -0400180 syncClearBufferState(buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400181 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
182 mFunctions->clearBufferfv(buffer, drawbuffer, values);
183
He Yunchaoacd18982017-01-04 10:46:42 +0800184 return NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500185}
186
Jamie Madill8415b5f2016-04-26 13:41:39 -0400187Error FramebufferGL::clearBufferuiv(ContextImpl *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500188 GLenum buffer,
189 GLint drawbuffer,
190 const GLuint *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500191{
Geoff Langafd7f0a2015-09-09 15:33:31 -0400192 syncClearBufferState(buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400193 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
194 mFunctions->clearBufferuiv(buffer, drawbuffer, values);
195
He Yunchaoacd18982017-01-04 10:46:42 +0800196 return NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500197}
198
Jamie Madill8415b5f2016-04-26 13:41:39 -0400199Error FramebufferGL::clearBufferiv(ContextImpl *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500200 GLenum buffer,
201 GLint drawbuffer,
202 const GLint *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500203{
Geoff Langafd7f0a2015-09-09 15:33:31 -0400204 syncClearBufferState(buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400205 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
206 mFunctions->clearBufferiv(buffer, drawbuffer, values);
207
He Yunchaoacd18982017-01-04 10:46:42 +0800208 return NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500209}
210
Jamie Madill8415b5f2016-04-26 13:41:39 -0400211Error FramebufferGL::clearBufferfi(ContextImpl *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500212 GLenum buffer,
213 GLint drawbuffer,
214 GLfloat depth,
215 GLint stencil)
Geoff Langf9a6f082015-01-22 13:32:49 -0500216{
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->clearBufferfi(buffer, drawbuffer, depth, stencil);
220
He Yunchaoacd18982017-01-04 10:46:42 +0800221 return NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500222}
223
224GLenum FramebufferGL::getImplementationColorReadFormat() const
225{
Jamie Madilla3944d42016-07-22 22:13:26 -0400226 const auto *readAttachment = mState.getReadAttachment();
227 const Format &format = readAttachment->getFormat();
Geoff Langf607c602016-09-21 11:46:48 -0400228 return format.info->getReadPixelsFormat();
Geoff Langf9a6f082015-01-22 13:32:49 -0500229}
230
231GLenum FramebufferGL::getImplementationColorReadType() const
232{
Jamie Madilla3944d42016-07-22 22:13:26 -0400233 const auto *readAttachment = mState.getReadAttachment();
234 const Format &format = readAttachment->getFormat();
Geoff Langf607c602016-09-21 11:46:48 -0400235 return format.info->getReadPixelsType();
Geoff Langf9a6f082015-01-22 13:32:49 -0500236}
237
Jamie Madill8415b5f2016-04-26 13:41:39 -0400238Error FramebufferGL::readPixels(ContextImpl *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500239 const gl::Rectangle &area,
240 GLenum format,
241 GLenum type,
242 GLvoid *pixels) const
Geoff Langf9a6f082015-01-22 13:32:49 -0500243{
Geoff Langda34d002015-09-04 11:08:59 -0400244 // TODO: don't sync the pixel pack state here once the dirty bits contain the pixel pack buffer
245 // binding
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700246 const PixelPackState &packState = context->getGLState().getPackState();
Geoff Langda34d002015-09-04 11:08:59 -0400247 mStateManager->setPixelPackState(packState);
Jamie Madill87de3622015-03-16 10:41:44 -0400248
Geoff Langf607c602016-09-21 11:46:48 -0400249 nativegl::ReadPixelsFormat readPixelsFormat =
250 nativegl::GetReadPixelsFormat(mFunctions, mWorkarounds, format, type);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400251 GLenum readFormat = readPixelsFormat.format;
252 GLenum readType = readPixelsFormat.type;
Geoff Lang4ad17092015-03-10 16:47:44 -0400253
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400254 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, mFramebufferID);
255
256 if (mWorkarounds.packOverlappingRowsSeparatelyPackBuffer && packState.pixelBuffer.get() &&
257 packState.rowLength != 0 && packState.rowLength < area.width)
258 {
259 return readPixelsRowByRowWorkaround(area, readFormat, readType, packState, pixels);
260 }
261
262 if (mWorkarounds.packLastRowSeparatelyForPaddingInclusion)
263 {
Corentin Wallez886de362016-09-27 10:49:35 -0400264 gl::Extents size(area.width, area.height, 1);
265
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400266 bool apply;
Corentin Wallez886de362016-09-27 10:49:35 -0400267 ANGLE_TRY_RESULT(ShouldApplyLastRowPaddingWorkaround(size, packState, readFormat, readType,
268 false, pixels),
269 apply);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400270
271 if (apply)
272 {
273 return readPixelsPaddingWorkaround(area, readFormat, readType, packState, pixels);
274 }
275 }
276
277 mFunctions->readPixels(area.x, area.y, area.width, area.height, readFormat, readType, pixels);
278
279 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500280}
281
Jamie Madill8415b5f2016-04-26 13:41:39 -0400282Error FramebufferGL::blit(ContextImpl *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500283 const gl::Rectangle &sourceArea,
284 const gl::Rectangle &destArea,
285 GLbitfield mask,
Jamie Madill8415b5f2016-04-26 13:41:39 -0400286 GLenum filter)
Geoff Langf9a6f082015-01-22 13:32:49 -0500287{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700288 const Framebuffer *sourceFramebuffer = context->getGLState().getReadFramebuffer();
Corentin Wallez26a717b2016-09-27 08:45:42 -0700289 const Framebuffer *destFramebuffer = context->getGLState().getDrawFramebuffer();
Geoff Lang4ad17092015-03-10 16:47:44 -0400290
Corentin Wallez6898b352016-11-10 11:41:15 -0500291 const FramebufferAttachment *colorReadAttachment = sourceFramebuffer->getReadColorbuffer();
Corentin Wallez4596a762016-12-20 14:50:18 -0500292
293 GLsizei readAttachmentSamples = 0;
294 if (colorReadAttachment != nullptr)
295 {
296 readAttachmentSamples = colorReadAttachment->getSamples();
297 }
Corentin Wallez6898b352016-11-10 11:41:15 -0500298
Corentin Wallez26a717b2016-09-27 08:45:42 -0700299 bool needManualColorBlit = false;
300
Corentin Wallez6898b352016-11-10 11:41:15 -0500301 // TODO(cwallez) when the filter is LINEAR and both source and destination are SRGB, we
302 // could avoid doing a manual blit.
303
304 // Prior to OpenGL 4.4 BlitFramebuffer (section 18.3.1 of GL 4.3 core profile) reads:
305 // When values are taken from the read buffer, no linearization is performed, even
306 // if the format of the buffer is SRGB.
307 // Starting from OpenGL 4.4 (section 18.3.1) it reads:
308 // When values are taken from the read buffer, if FRAMEBUFFER_SRGB is enabled and the
309 // value of FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING for the framebuffer attachment
310 // corresponding to the read buffer is SRGB, the red, green, and blue components are
311 // converted from the non-linear sRGB color space according [...].
Corentin Wallez26a717b2016-09-27 08:45:42 -0700312 {
Corentin Wallez6898b352016-11-10 11:41:15 -0500313 bool sourceSRGB = colorReadAttachment != nullptr &&
314 colorReadAttachment->getColorEncoding() == GL_SRGB;
315 needManualColorBlit =
316 needManualColorBlit || (sourceSRGB && mFunctions->isAtMostGL(gl::Version(4, 3)));
317 }
Corentin Wallez26a717b2016-09-27 08:45:42 -0700318
Corentin Wallez6898b352016-11-10 11:41:15 -0500319 // Prior to OpenGL 4.2 BlitFramebuffer (section 4.3.2 of GL 4.1 core profile) reads:
320 // Blit operations bypass the fragment pipeline. The only fragment operations which
321 // affect a blit are the pixel ownership test and scissor test.
322 // Starting from OpenGL 4.2 (section 4.3.2) it reads:
323 // When values are written to the draw buffers, blit operations bypass the fragment
324 // pipeline. The only fragment operations which affect a blit are the pixel ownership
325 // test, the scissor test and sRGB conversion.
326 if (!needManualColorBlit)
327 {
328 bool destSRGB = false;
329 for (size_t i = 0; i < destFramebuffer->getDrawbufferStateCount(); ++i)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700330 {
Corentin Wallez6898b352016-11-10 11:41:15 -0500331 const FramebufferAttachment *attachment = destFramebuffer->getDrawBuffer(i);
332 if (attachment && attachment->getColorEncoding() == GL_SRGB)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700333 {
Corentin Wallez6898b352016-11-10 11:41:15 -0500334 destSRGB = true;
335 break;
Corentin Wallez26a717b2016-09-27 08:45:42 -0700336 }
Corentin Wallez26a717b2016-09-27 08:45:42 -0700337 }
Corentin Wallez6898b352016-11-10 11:41:15 -0500338
339 needManualColorBlit =
340 needManualColorBlit || (destSRGB && mFunctions->isAtMostGL(gl::Version(4, 1)));
Corentin Wallez26a717b2016-09-27 08:45:42 -0700341 }
342
343 // Enable FRAMEBUFFER_SRGB if needed
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700344 mStateManager->setFramebufferSRGBEnabledForFramebuffer(true, this);
Corentin Wallez26a717b2016-09-27 08:45:42 -0700345
346 GLenum blitMask = mask;
Corentin Wallez6898b352016-11-10 11:41:15 -0500347 if (needManualColorBlit && (mask & GL_COLOR_BUFFER_BIT) && readAttachmentSamples <= 1)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700348 {
349 ANGLE_TRY(mBlitter->blitColorBufferWithShader(sourceFramebuffer, destFramebuffer,
350 sourceArea, destArea, filter));
351 blitMask &= ~GL_COLOR_BUFFER_BIT;
352 }
353
354 if (blitMask == 0)
355 {
356 return gl::NoError();
357 }
358
359 const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(sourceFramebuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400360 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
361 mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferID);
362
Jamie Madill2da819e2015-12-03 15:53:19 -0500363 mFunctions->blitFramebuffer(sourceArea.x, sourceArea.y, sourceArea.x1(), sourceArea.y1(),
Corentin Wallez26a717b2016-09-27 08:45:42 -0700364 destArea.x, destArea.y, destArea.x1(), destArea.y1(), blitMask,
365 filter);
Geoff Lang4ad17092015-03-10 16:47:44 -0400366
Corentin Wallez26a717b2016-09-27 08:45:42 -0700367 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500368}
369
Jamie Madillcc86d642015-11-24 13:00:07 -0500370bool FramebufferGL::checkStatus() const
Geoff Langf9a6f082015-01-22 13:32:49 -0500371{
Geoff Lang4ad17092015-03-10 16:47:44 -0400372 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Jamie Madillcc86d642015-11-24 13:00:07 -0500373 GLenum status = mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
374 if (status != GL_FRAMEBUFFER_COMPLETE)
375 {
376 ANGLEPlatformCurrent()->logWarning("GL framebuffer returned incomplete.");
377 }
378 return (status == GL_FRAMEBUFFER_COMPLETE);
Geoff Lang4ad17092015-03-10 16:47:44 -0400379}
380
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500381void FramebufferGL::syncState(const Framebuffer::DirtyBits &dirtyBits)
382{
383 // Don't need to sync state for the default FBO.
384 if (mIsDefault)
385 {
386 return;
387 }
388
389 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
390
391 for (auto dirtyBit : angle::IterateBitSet(dirtyBits))
392 {
393 switch (dirtyBit)
394 {
395 case Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
396 BindFramebufferAttachment(mFunctions, GL_DEPTH_ATTACHMENT,
Jamie Madill48ef11b2016-04-27 15:21:52 -0400397 mState.getDepthAttachment());
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500398 break;
399 case Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
400 BindFramebufferAttachment(mFunctions, GL_STENCIL_ATTACHMENT,
Jamie Madill48ef11b2016-04-27 15:21:52 -0400401 mState.getStencilAttachment());
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500402 break;
403 case Framebuffer::DIRTY_BIT_DRAW_BUFFERS:
404 {
Jamie Madill48ef11b2016-04-27 15:21:52 -0400405 const auto &drawBuffers = mState.getDrawBufferStates();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500406 mFunctions->drawBuffers(static_cast<GLsizei>(drawBuffers.size()),
407 drawBuffers.data());
408 break;
409 }
410 case Framebuffer::DIRTY_BIT_READ_BUFFER:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400411 mFunctions->readBuffer(mState.getReadBufferState());
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500412 break;
413 default:
414 {
415 ASSERT(Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0 &&
416 dirtyBit < Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX);
417 size_t index =
418 static_cast<size_t>(dirtyBit - Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
419 BindFramebufferAttachment(mFunctions,
420 static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + index),
Jamie Madill48ef11b2016-04-27 15:21:52 -0400421 mState.getColorAttachment(index));
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500422 break;
423 }
424 }
425 }
426}
427
Geoff Lang4ad17092015-03-10 16:47:44 -0400428GLuint FramebufferGL::getFramebufferID() const
429{
430 return mFramebufferID;
Geoff Langf9a6f082015-01-22 13:32:49 -0500431}
432
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700433bool FramebufferGL::isDefault() const
Geoff Langafd7f0a2015-09-09 15:33:31 -0400434{
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700435 return mIsDefault;
Geoff Langafd7f0a2015-09-09 15:33:31 -0400436}
437
438void FramebufferGL::syncClearState(GLbitfield mask)
439{
Frank Henigmana3d333c2016-03-22 22:09:14 -0400440 if (mFunctions->standard == STANDARD_GL_DESKTOP)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400441 {
Frank Henigmana3d333c2016-03-22 22:09:14 -0400442 if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments &&
443 (mask & GL_COLOR_BUFFER_BIT) != 0 && !mIsDefault)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400444 {
Corentin Wallez26a717b2016-09-27 08:45:42 -0700445 bool hasSRGBAttachment = false;
Jamie Madill48ef11b2016-04-27 15:21:52 -0400446 for (const auto &attachment : mState.getColorAttachments())
Geoff Langafd7f0a2015-09-09 15:33:31 -0400447 {
Frank Henigmana3d333c2016-03-22 22:09:14 -0400448 if (attachment.isAttached() && attachment.getColorEncoding() == GL_SRGB)
449 {
Corentin Wallez26a717b2016-09-27 08:45:42 -0700450 hasSRGBAttachment = true;
Frank Henigmana3d333c2016-03-22 22:09:14 -0400451 break;
452 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400453 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400454
Corentin Wallez26a717b2016-09-27 08:45:42 -0700455 mStateManager->setFramebufferSRGBEnabled(hasSRGBAttachment);
Frank Henigmana3d333c2016-03-22 22:09:14 -0400456 }
457 else
458 {
459 mStateManager->setFramebufferSRGBEnabled(!mIsDefault);
460 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400461 }
462}
463
464void FramebufferGL::syncClearBufferState(GLenum buffer, GLint drawBuffer)
465{
466 if (mFunctions->standard == STANDARD_GL_DESKTOP)
467 {
468 if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments && buffer == GL_COLOR &&
469 !mIsDefault)
470 {
471 // If doing a clear on a color buffer, set SRGB blend enabled only if the color buffer
472 // is an SRGB format.
Jamie Madill48ef11b2016-04-27 15:21:52 -0400473 const auto &drawbufferState = mState.getDrawBufferStates();
474 const auto &colorAttachments = mState.getColorAttachments();
Geoff Langafd7f0a2015-09-09 15:33:31 -0400475
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500476 const FramebufferAttachment *attachment = nullptr;
Geoff Langafd7f0a2015-09-09 15:33:31 -0400477 if (drawbufferState[drawBuffer] >= GL_COLOR_ATTACHMENT0 &&
478 drawbufferState[drawBuffer] < GL_COLOR_ATTACHMENT0 + colorAttachments.size())
479 {
480 size_t attachmentIdx =
481 static_cast<size_t>(drawbufferState[drawBuffer] - GL_COLOR_ATTACHMENT0);
482 attachment = &colorAttachments[attachmentIdx];
483 }
484
485 if (attachment != nullptr)
486 {
487 mStateManager->setFramebufferSRGBEnabled(attachment->getColorEncoding() == GL_SRGB);
488 }
489 }
490 else
491 {
492 mStateManager->setFramebufferSRGBEnabled(!mIsDefault);
493 }
494 }
495}
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400496gl::Error FramebufferGL::readPixelsRowByRowWorkaround(const gl::Rectangle &area,
497 GLenum format,
498 GLenum type,
499 const gl::PixelPackState &pack,
500 GLvoid *pixels) const
501{
502 intptr_t offset = reinterpret_cast<intptr_t>(pixels);
503
504 const gl::InternalFormat &glFormat =
505 gl::GetInternalFormatInfo(gl::GetSizedInternalFormat(format, type));
506 GLuint rowBytes = 0;
507 ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
508 rowBytes);
509 GLuint skipBytes = 0;
Corentin Wallez886de362016-09-27 10:49:35 -0400510 ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400511
512 gl::PixelPackState directPack;
513 directPack.pixelBuffer = pack.pixelBuffer;
514 directPack.alignment = 1;
515 mStateManager->setPixelPackState(directPack);
516 directPack.pixelBuffer.set(nullptr);
517
518 offset += skipBytes;
519 for (GLint row = 0; row < area.height; ++row)
520 {
521 mFunctions->readPixels(area.x, row + area.y, area.width, 1, format, type,
522 reinterpret_cast<GLvoid *>(offset));
523 offset += row * rowBytes;
524 }
525
526 return gl::NoError();
527}
528
529gl::Error FramebufferGL::readPixelsPaddingWorkaround(const gl::Rectangle &area,
530 GLenum format,
531 GLenum type,
532 const gl::PixelPackState &pack,
533 GLvoid *pixels) const
534{
535 const gl::InternalFormat &glFormat =
536 gl::GetInternalFormatInfo(gl::GetSizedInternalFormat(format, type));
537 GLuint rowBytes = 0;
538 ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
539 rowBytes);
540 GLuint skipBytes = 0;
Corentin Wallez886de362016-09-27 10:49:35 -0400541 ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400542
543 // Get all by the last row
544 if (area.height > 1)
545 {
546 mFunctions->readPixels(area.x, area.y, area.width, area.height - 1, format, type, pixels);
547 }
548
549 // Get the last row manually
550 gl::PixelPackState directPack;
551 directPack.pixelBuffer = pack.pixelBuffer;
552 directPack.alignment = 1;
553 mStateManager->setPixelPackState(directPack);
554 directPack.pixelBuffer.set(nullptr);
555
556 intptr_t lastRowOffset =
557 reinterpret_cast<intptr_t>(pixels) + skipBytes + (area.height - 1) * rowBytes;
558 mFunctions->readPixels(area.x, area.y + area.height - 1, area.width, 1, format, type,
559 reinterpret_cast<GLvoid *>(lastRowOffset));
560
561 return gl::NoError();
562}
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500563} // namespace rx