blob: 9fde07c7d641b94d8f924f66a050a1e1b98bd36e [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
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500163 return Error(GL_NO_ERROR);
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
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500172 return Error(GL_NO_ERROR);
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
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500184 return Error(GL_NO_ERROR);
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
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500196 return Error(GL_NO_ERROR);
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
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500208 return Error(GL_NO_ERROR);
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
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500221 return Error(GL_NO_ERROR);
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();
292 GLsizei readAttachmentSamples = colorReadAttachment->getSamples();
293
Corentin Wallez26a717b2016-09-27 08:45:42 -0700294 bool needManualColorBlit = false;
295
Corentin Wallez6898b352016-11-10 11:41:15 -0500296 // TODO(cwallez) when the filter is LINEAR and both source and destination are SRGB, we
297 // could avoid doing a manual blit.
298
299 // Prior to OpenGL 4.4 BlitFramebuffer (section 18.3.1 of GL 4.3 core profile) reads:
300 // When values are taken from the read buffer, no linearization is performed, even
301 // if the format of the buffer is SRGB.
302 // Starting from OpenGL 4.4 (section 18.3.1) it reads:
303 // When values are taken from the read buffer, if FRAMEBUFFER_SRGB is enabled and the
304 // value of FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING for the framebuffer attachment
305 // corresponding to the read buffer is SRGB, the red, green, and blue components are
306 // converted from the non-linear sRGB color space according [...].
Corentin Wallez26a717b2016-09-27 08:45:42 -0700307 {
Corentin Wallez6898b352016-11-10 11:41:15 -0500308 bool sourceSRGB = colorReadAttachment != nullptr &&
309 colorReadAttachment->getColorEncoding() == GL_SRGB;
310 needManualColorBlit =
311 needManualColorBlit || (sourceSRGB && mFunctions->isAtMostGL(gl::Version(4, 3)));
312 }
Corentin Wallez26a717b2016-09-27 08:45:42 -0700313
Corentin Wallez6898b352016-11-10 11:41:15 -0500314 // Prior to OpenGL 4.2 BlitFramebuffer (section 4.3.2 of GL 4.1 core profile) reads:
315 // Blit operations bypass the fragment pipeline. The only fragment operations which
316 // affect a blit are the pixel ownership test and scissor test.
317 // Starting from OpenGL 4.2 (section 4.3.2) it reads:
318 // When values are written to the draw buffers, blit operations bypass the fragment
319 // pipeline. The only fragment operations which affect a blit are the pixel ownership
320 // test, the scissor test and sRGB conversion.
321 if (!needManualColorBlit)
322 {
323 bool destSRGB = false;
324 for (size_t i = 0; i < destFramebuffer->getDrawbufferStateCount(); ++i)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700325 {
Corentin Wallez6898b352016-11-10 11:41:15 -0500326 const FramebufferAttachment *attachment = destFramebuffer->getDrawBuffer(i);
327 if (attachment && attachment->getColorEncoding() == GL_SRGB)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700328 {
Corentin Wallez6898b352016-11-10 11:41:15 -0500329 destSRGB = true;
330 break;
Corentin Wallez26a717b2016-09-27 08:45:42 -0700331 }
Corentin Wallez26a717b2016-09-27 08:45:42 -0700332 }
Corentin Wallez6898b352016-11-10 11:41:15 -0500333
334 needManualColorBlit =
335 needManualColorBlit || (destSRGB && mFunctions->isAtMostGL(gl::Version(4, 1)));
Corentin Wallez26a717b2016-09-27 08:45:42 -0700336 }
337
338 // Enable FRAMEBUFFER_SRGB if needed
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700339 mStateManager->setFramebufferSRGBEnabledForFramebuffer(true, this);
Corentin Wallez26a717b2016-09-27 08:45:42 -0700340
341 GLenum blitMask = mask;
Corentin Wallez6898b352016-11-10 11:41:15 -0500342 if (needManualColorBlit && (mask & GL_COLOR_BUFFER_BIT) && readAttachmentSamples <= 1)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700343 {
344 ANGLE_TRY(mBlitter->blitColorBufferWithShader(sourceFramebuffer, destFramebuffer,
345 sourceArea, destArea, filter));
346 blitMask &= ~GL_COLOR_BUFFER_BIT;
347 }
348
349 if (blitMask == 0)
350 {
351 return gl::NoError();
352 }
353
354 const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(sourceFramebuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400355 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
356 mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferID);
357
Jamie Madill2da819e2015-12-03 15:53:19 -0500358 mFunctions->blitFramebuffer(sourceArea.x, sourceArea.y, sourceArea.x1(), sourceArea.y1(),
Corentin Wallez26a717b2016-09-27 08:45:42 -0700359 destArea.x, destArea.y, destArea.x1(), destArea.y1(), blitMask,
360 filter);
Geoff Lang4ad17092015-03-10 16:47:44 -0400361
Corentin Wallez26a717b2016-09-27 08:45:42 -0700362 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500363}
364
Jamie Madillcc86d642015-11-24 13:00:07 -0500365bool FramebufferGL::checkStatus() const
Geoff Langf9a6f082015-01-22 13:32:49 -0500366{
Geoff Lang4ad17092015-03-10 16:47:44 -0400367 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Jamie Madillcc86d642015-11-24 13:00:07 -0500368 GLenum status = mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
369 if (status != GL_FRAMEBUFFER_COMPLETE)
370 {
371 ANGLEPlatformCurrent()->logWarning("GL framebuffer returned incomplete.");
372 }
373 return (status == GL_FRAMEBUFFER_COMPLETE);
Geoff Lang4ad17092015-03-10 16:47:44 -0400374}
375
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500376void FramebufferGL::syncState(const Framebuffer::DirtyBits &dirtyBits)
377{
378 // Don't need to sync state for the default FBO.
379 if (mIsDefault)
380 {
381 return;
382 }
383
384 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
385
386 for (auto dirtyBit : angle::IterateBitSet(dirtyBits))
387 {
388 switch (dirtyBit)
389 {
390 case Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
391 BindFramebufferAttachment(mFunctions, GL_DEPTH_ATTACHMENT,
Jamie Madill48ef11b2016-04-27 15:21:52 -0400392 mState.getDepthAttachment());
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500393 break;
394 case Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
395 BindFramebufferAttachment(mFunctions, GL_STENCIL_ATTACHMENT,
Jamie Madill48ef11b2016-04-27 15:21:52 -0400396 mState.getStencilAttachment());
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500397 break;
398 case Framebuffer::DIRTY_BIT_DRAW_BUFFERS:
399 {
Jamie Madill48ef11b2016-04-27 15:21:52 -0400400 const auto &drawBuffers = mState.getDrawBufferStates();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500401 mFunctions->drawBuffers(static_cast<GLsizei>(drawBuffers.size()),
402 drawBuffers.data());
403 break;
404 }
405 case Framebuffer::DIRTY_BIT_READ_BUFFER:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400406 mFunctions->readBuffer(mState.getReadBufferState());
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500407 break;
408 default:
409 {
410 ASSERT(Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0 &&
411 dirtyBit < Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX);
412 size_t index =
413 static_cast<size_t>(dirtyBit - Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
414 BindFramebufferAttachment(mFunctions,
415 static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + index),
Jamie Madill48ef11b2016-04-27 15:21:52 -0400416 mState.getColorAttachment(index));
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500417 break;
418 }
419 }
420 }
421}
422
Geoff Lang4ad17092015-03-10 16:47:44 -0400423GLuint FramebufferGL::getFramebufferID() const
424{
425 return mFramebufferID;
Geoff Langf9a6f082015-01-22 13:32:49 -0500426}
427
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700428bool FramebufferGL::isDefault() const
Geoff Langafd7f0a2015-09-09 15:33:31 -0400429{
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700430 return mIsDefault;
Geoff Langafd7f0a2015-09-09 15:33:31 -0400431}
432
433void FramebufferGL::syncClearState(GLbitfield mask)
434{
Frank Henigmana3d333c2016-03-22 22:09:14 -0400435 if (mFunctions->standard == STANDARD_GL_DESKTOP)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400436 {
Frank Henigmana3d333c2016-03-22 22:09:14 -0400437 if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments &&
438 (mask & GL_COLOR_BUFFER_BIT) != 0 && !mIsDefault)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400439 {
Corentin Wallez26a717b2016-09-27 08:45:42 -0700440 bool hasSRGBAttachment = false;
Jamie Madill48ef11b2016-04-27 15:21:52 -0400441 for (const auto &attachment : mState.getColorAttachments())
Geoff Langafd7f0a2015-09-09 15:33:31 -0400442 {
Frank Henigmana3d333c2016-03-22 22:09:14 -0400443 if (attachment.isAttached() && attachment.getColorEncoding() == GL_SRGB)
444 {
Corentin Wallez26a717b2016-09-27 08:45:42 -0700445 hasSRGBAttachment = true;
Frank Henigmana3d333c2016-03-22 22:09:14 -0400446 break;
447 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400448 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400449
Corentin Wallez26a717b2016-09-27 08:45:42 -0700450 mStateManager->setFramebufferSRGBEnabled(hasSRGBAttachment);
Frank Henigmana3d333c2016-03-22 22:09:14 -0400451 }
452 else
453 {
454 mStateManager->setFramebufferSRGBEnabled(!mIsDefault);
455 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400456 }
457}
458
459void FramebufferGL::syncClearBufferState(GLenum buffer, GLint drawBuffer)
460{
461 if (mFunctions->standard == STANDARD_GL_DESKTOP)
462 {
463 if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments && buffer == GL_COLOR &&
464 !mIsDefault)
465 {
466 // If doing a clear on a color buffer, set SRGB blend enabled only if the color buffer
467 // is an SRGB format.
Jamie Madill48ef11b2016-04-27 15:21:52 -0400468 const auto &drawbufferState = mState.getDrawBufferStates();
469 const auto &colorAttachments = mState.getColorAttachments();
Geoff Langafd7f0a2015-09-09 15:33:31 -0400470
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500471 const FramebufferAttachment *attachment = nullptr;
Geoff Langafd7f0a2015-09-09 15:33:31 -0400472 if (drawbufferState[drawBuffer] >= GL_COLOR_ATTACHMENT0 &&
473 drawbufferState[drawBuffer] < GL_COLOR_ATTACHMENT0 + colorAttachments.size())
474 {
475 size_t attachmentIdx =
476 static_cast<size_t>(drawbufferState[drawBuffer] - GL_COLOR_ATTACHMENT0);
477 attachment = &colorAttachments[attachmentIdx];
478 }
479
480 if (attachment != nullptr)
481 {
482 mStateManager->setFramebufferSRGBEnabled(attachment->getColorEncoding() == GL_SRGB);
483 }
484 }
485 else
486 {
487 mStateManager->setFramebufferSRGBEnabled(!mIsDefault);
488 }
489 }
490}
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400491gl::Error FramebufferGL::readPixelsRowByRowWorkaround(const gl::Rectangle &area,
492 GLenum format,
493 GLenum type,
494 const gl::PixelPackState &pack,
495 GLvoid *pixels) const
496{
497 intptr_t offset = reinterpret_cast<intptr_t>(pixels);
498
499 const gl::InternalFormat &glFormat =
500 gl::GetInternalFormatInfo(gl::GetSizedInternalFormat(format, type));
501 GLuint rowBytes = 0;
502 ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
503 rowBytes);
504 GLuint skipBytes = 0;
Corentin Wallez886de362016-09-27 10:49:35 -0400505 ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400506
507 gl::PixelPackState directPack;
508 directPack.pixelBuffer = pack.pixelBuffer;
509 directPack.alignment = 1;
510 mStateManager->setPixelPackState(directPack);
511 directPack.pixelBuffer.set(nullptr);
512
513 offset += skipBytes;
514 for (GLint row = 0; row < area.height; ++row)
515 {
516 mFunctions->readPixels(area.x, row + area.y, area.width, 1, format, type,
517 reinterpret_cast<GLvoid *>(offset));
518 offset += row * rowBytes;
519 }
520
521 return gl::NoError();
522}
523
524gl::Error FramebufferGL::readPixelsPaddingWorkaround(const gl::Rectangle &area,
525 GLenum format,
526 GLenum type,
527 const gl::PixelPackState &pack,
528 GLvoid *pixels) const
529{
530 const gl::InternalFormat &glFormat =
531 gl::GetInternalFormatInfo(gl::GetSizedInternalFormat(format, type));
532 GLuint rowBytes = 0;
533 ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
534 rowBytes);
535 GLuint skipBytes = 0;
Corentin Wallez886de362016-09-27 10:49:35 -0400536 ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400537
538 // Get all by the last row
539 if (area.height > 1)
540 {
541 mFunctions->readPixels(area.x, area.y, area.width, area.height - 1, format, type, pixels);
542 }
543
544 // Get the last row manually
545 gl::PixelPackState directPack;
546 directPack.pixelBuffer = pack.pixelBuffer;
547 directPack.alignment = 1;
548 mStateManager->setPixelPackState(directPack);
549 directPack.pixelBuffer.set(nullptr);
550
551 intptr_t lastRowOffset =
552 reinterpret_cast<intptr_t>(pixels) + skipBytes + (area.height - 1) * rowBytes;
553 mFunctions->readPixels(area.x, area.y + area.height - 1, area.width, 1, format, type,
554 reinterpret_cast<GLvoid *>(lastRowOffset));
555
556 return gl::NoError();
557}
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500558} // namespace rx