blob: 7e300b6eae912526cb61e7dfad34581a6849b2a0 [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{
130 UNIMPLEMENTED();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500131 return Error(GL_INVALID_OPERATION);
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 Lang64a72442015-04-01 14:43:11 -0400136 // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is available.
137 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 }
142
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500143 return Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500144}
145
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500146Error FramebufferGL::invalidateSub(size_t count,
147 const GLenum *attachments,
148 const gl::Rectangle &area)
Geoff Langf9a6f082015-01-22 13:32:49 -0500149{
Geoff Lang64a72442015-04-01 14:43:11 -0400150 // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is available.
151 if (mFunctions->invalidateSubFramebuffer)
152 {
153 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700154 mFunctions->invalidateSubFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
155 attachments, area.x, area.y, area.width, area.height);
Geoff Lang64a72442015-04-01 14:43:11 -0400156 }
157
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500158 return Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500159}
160
Jamie Madill8415b5f2016-04-26 13:41:39 -0400161Error FramebufferGL::clear(ContextImpl *context, GLbitfield mask)
Geoff Langf9a6f082015-01-22 13:32:49 -0500162{
Geoff Langafd7f0a2015-09-09 15:33:31 -0400163 syncClearState(mask);
Geoff Lang4ad17092015-03-10 16:47:44 -0400164 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
165 mFunctions->clear(mask);
166
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500167 return Error(GL_NO_ERROR);
Geoff Lang4ad17092015-03-10 16:47:44 -0400168}
169
Jamie Madill8415b5f2016-04-26 13:41:39 -0400170Error FramebufferGL::clearBufferfv(ContextImpl *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500171 GLenum buffer,
172 GLint drawbuffer,
173 const GLfloat *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500174{
Geoff Langafd7f0a2015-09-09 15:33:31 -0400175 syncClearBufferState(buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400176 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
177 mFunctions->clearBufferfv(buffer, drawbuffer, values);
178
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500179 return Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500180}
181
Jamie Madill8415b5f2016-04-26 13:41:39 -0400182Error FramebufferGL::clearBufferuiv(ContextImpl *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500183 GLenum buffer,
184 GLint drawbuffer,
185 const GLuint *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500186{
Geoff Langafd7f0a2015-09-09 15:33:31 -0400187 syncClearBufferState(buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400188 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
189 mFunctions->clearBufferuiv(buffer, drawbuffer, values);
190
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500191 return Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500192}
193
Jamie Madill8415b5f2016-04-26 13:41:39 -0400194Error FramebufferGL::clearBufferiv(ContextImpl *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500195 GLenum buffer,
196 GLint drawbuffer,
197 const GLint *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500198{
Geoff Langafd7f0a2015-09-09 15:33:31 -0400199 syncClearBufferState(buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400200 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
201 mFunctions->clearBufferiv(buffer, drawbuffer, values);
202
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500203 return Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500204}
205
Jamie Madill8415b5f2016-04-26 13:41:39 -0400206Error FramebufferGL::clearBufferfi(ContextImpl *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500207 GLenum buffer,
208 GLint drawbuffer,
209 GLfloat depth,
210 GLint stencil)
Geoff Langf9a6f082015-01-22 13:32:49 -0500211{
Geoff Langafd7f0a2015-09-09 15:33:31 -0400212 syncClearBufferState(buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400213 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
214 mFunctions->clearBufferfi(buffer, drawbuffer, depth, stencil);
215
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500216 return Error(GL_NO_ERROR);
Geoff Langf9a6f082015-01-22 13:32:49 -0500217}
218
219GLenum FramebufferGL::getImplementationColorReadFormat() const
220{
Jamie Madilla3944d42016-07-22 22:13:26 -0400221 const auto *readAttachment = mState.getReadAttachment();
222 const Format &format = readAttachment->getFormat();
Geoff Langf607c602016-09-21 11:46:48 -0400223 return format.info->getReadPixelsFormat();
Geoff Langf9a6f082015-01-22 13:32:49 -0500224}
225
226GLenum FramebufferGL::getImplementationColorReadType() const
227{
Jamie Madilla3944d42016-07-22 22:13:26 -0400228 const auto *readAttachment = mState.getReadAttachment();
229 const Format &format = readAttachment->getFormat();
Geoff Langf607c602016-09-21 11:46:48 -0400230 return format.info->getReadPixelsType();
Geoff Langf9a6f082015-01-22 13:32:49 -0500231}
232
Jamie Madill8415b5f2016-04-26 13:41:39 -0400233Error FramebufferGL::readPixels(ContextImpl *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500234 const gl::Rectangle &area,
235 GLenum format,
236 GLenum type,
237 GLvoid *pixels) const
Geoff Langf9a6f082015-01-22 13:32:49 -0500238{
Geoff Langda34d002015-09-04 11:08:59 -0400239 // TODO: don't sync the pixel pack state here once the dirty bits contain the pixel pack buffer
240 // binding
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700241 const PixelPackState &packState = context->getGLState().getPackState();
Geoff Langda34d002015-09-04 11:08:59 -0400242 mStateManager->setPixelPackState(packState);
Jamie Madill87de3622015-03-16 10:41:44 -0400243
Geoff Langf607c602016-09-21 11:46:48 -0400244 nativegl::ReadPixelsFormat readPixelsFormat =
245 nativegl::GetReadPixelsFormat(mFunctions, mWorkarounds, format, type);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400246 GLenum readFormat = readPixelsFormat.format;
247 GLenum readType = readPixelsFormat.type;
Geoff Lang4ad17092015-03-10 16:47:44 -0400248
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400249 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, mFramebufferID);
250
251 if (mWorkarounds.packOverlappingRowsSeparatelyPackBuffer && packState.pixelBuffer.get() &&
252 packState.rowLength != 0 && packState.rowLength < area.width)
253 {
254 return readPixelsRowByRowWorkaround(area, readFormat, readType, packState, pixels);
255 }
256
257 if (mWorkarounds.packLastRowSeparatelyForPaddingInclusion)
258 {
Corentin Wallez886de362016-09-27 10:49:35 -0400259 gl::Extents size(area.width, area.height, 1);
260
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400261 bool apply;
Corentin Wallez886de362016-09-27 10:49:35 -0400262 ANGLE_TRY_RESULT(ShouldApplyLastRowPaddingWorkaround(size, packState, readFormat, readType,
263 false, pixels),
264 apply);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400265
266 if (apply)
267 {
268 return readPixelsPaddingWorkaround(area, readFormat, readType, packState, pixels);
269 }
270 }
271
272 mFunctions->readPixels(area.x, area.y, area.width, area.height, readFormat, readType, pixels);
273
274 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500275}
276
Jamie Madill8415b5f2016-04-26 13:41:39 -0400277Error FramebufferGL::blit(ContextImpl *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500278 const gl::Rectangle &sourceArea,
279 const gl::Rectangle &destArea,
280 GLbitfield mask,
Jamie Madill8415b5f2016-04-26 13:41:39 -0400281 GLenum filter)
Geoff Langf9a6f082015-01-22 13:32:49 -0500282{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700283 const Framebuffer *sourceFramebuffer = context->getGLState().getReadFramebuffer();
Corentin Wallez26a717b2016-09-27 08:45:42 -0700284 const Framebuffer *destFramebuffer = context->getGLState().getDrawFramebuffer();
Geoff Lang4ad17092015-03-10 16:47:44 -0400285
Corentin Wallez6898b352016-11-10 11:41:15 -0500286 const FramebufferAttachment *colorReadAttachment = sourceFramebuffer->getReadColorbuffer();
287 GLsizei readAttachmentSamples = colorReadAttachment->getSamples();
288
Corentin Wallez26a717b2016-09-27 08:45:42 -0700289 bool needManualColorBlit = false;
290
Corentin Wallez6898b352016-11-10 11:41:15 -0500291 // TODO(cwallez) when the filter is LINEAR and both source and destination are SRGB, we
292 // could avoid doing a manual blit.
293
294 // Prior to OpenGL 4.4 BlitFramebuffer (section 18.3.1 of GL 4.3 core profile) reads:
295 // When values are taken from the read buffer, no linearization is performed, even
296 // if the format of the buffer is SRGB.
297 // Starting from OpenGL 4.4 (section 18.3.1) it reads:
298 // When values are taken from the read buffer, if FRAMEBUFFER_SRGB is enabled and the
299 // value of FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING for the framebuffer attachment
300 // corresponding to the read buffer is SRGB, the red, green, and blue components are
301 // converted from the non-linear sRGB color space according [...].
Corentin Wallez26a717b2016-09-27 08:45:42 -0700302 {
Corentin Wallez6898b352016-11-10 11:41:15 -0500303 bool sourceSRGB = colorReadAttachment != nullptr &&
304 colorReadAttachment->getColorEncoding() == GL_SRGB;
305 needManualColorBlit =
306 needManualColorBlit || (sourceSRGB && mFunctions->isAtMostGL(gl::Version(4, 3)));
307 }
Corentin Wallez26a717b2016-09-27 08:45:42 -0700308
Corentin Wallez6898b352016-11-10 11:41:15 -0500309 // Prior to OpenGL 4.2 BlitFramebuffer (section 4.3.2 of GL 4.1 core profile) reads:
310 // Blit operations bypass the fragment pipeline. The only fragment operations which
311 // affect a blit are the pixel ownership test and scissor test.
312 // Starting from OpenGL 4.2 (section 4.3.2) it reads:
313 // When values are written to the draw buffers, blit operations bypass the fragment
314 // pipeline. The only fragment operations which affect a blit are the pixel ownership
315 // test, the scissor test and sRGB conversion.
316 if (!needManualColorBlit)
317 {
318 bool destSRGB = false;
319 for (size_t i = 0; i < destFramebuffer->getDrawbufferStateCount(); ++i)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700320 {
Corentin Wallez6898b352016-11-10 11:41:15 -0500321 const FramebufferAttachment *attachment = destFramebuffer->getDrawBuffer(i);
322 if (attachment && attachment->getColorEncoding() == GL_SRGB)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700323 {
Corentin Wallez6898b352016-11-10 11:41:15 -0500324 destSRGB = true;
325 break;
Corentin Wallez26a717b2016-09-27 08:45:42 -0700326 }
Corentin Wallez26a717b2016-09-27 08:45:42 -0700327 }
Corentin Wallez6898b352016-11-10 11:41:15 -0500328
329 needManualColorBlit =
330 needManualColorBlit || (destSRGB && mFunctions->isAtMostGL(gl::Version(4, 1)));
Corentin Wallez26a717b2016-09-27 08:45:42 -0700331 }
332
333 // Enable FRAMEBUFFER_SRGB if needed
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700334 mStateManager->setFramebufferSRGBEnabledForFramebuffer(true, this);
Corentin Wallez26a717b2016-09-27 08:45:42 -0700335
336 GLenum blitMask = mask;
Corentin Wallez6898b352016-11-10 11:41:15 -0500337 if (needManualColorBlit && (mask & GL_COLOR_BUFFER_BIT) && readAttachmentSamples <= 1)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700338 {
339 ANGLE_TRY(mBlitter->blitColorBufferWithShader(sourceFramebuffer, destFramebuffer,
340 sourceArea, destArea, filter));
341 blitMask &= ~GL_COLOR_BUFFER_BIT;
342 }
343
344 if (blitMask == 0)
345 {
346 return gl::NoError();
347 }
348
349 const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(sourceFramebuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400350 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
351 mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferID);
352
Jamie Madill2da819e2015-12-03 15:53:19 -0500353 mFunctions->blitFramebuffer(sourceArea.x, sourceArea.y, sourceArea.x1(), sourceArea.y1(),
Corentin Wallez26a717b2016-09-27 08:45:42 -0700354 destArea.x, destArea.y, destArea.x1(), destArea.y1(), blitMask,
355 filter);
Geoff Lang4ad17092015-03-10 16:47:44 -0400356
Corentin Wallez26a717b2016-09-27 08:45:42 -0700357 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500358}
359
Jamie Madillcc86d642015-11-24 13:00:07 -0500360bool FramebufferGL::checkStatus() const
Geoff Langf9a6f082015-01-22 13:32:49 -0500361{
Geoff Lang4ad17092015-03-10 16:47:44 -0400362 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Jamie Madillcc86d642015-11-24 13:00:07 -0500363 GLenum status = mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
364 if (status != GL_FRAMEBUFFER_COMPLETE)
365 {
366 ANGLEPlatformCurrent()->logWarning("GL framebuffer returned incomplete.");
367 }
368 return (status == GL_FRAMEBUFFER_COMPLETE);
Geoff Lang4ad17092015-03-10 16:47:44 -0400369}
370
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500371void FramebufferGL::syncState(const Framebuffer::DirtyBits &dirtyBits)
372{
373 // Don't need to sync state for the default FBO.
374 if (mIsDefault)
375 {
376 return;
377 }
378
379 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
380
381 for (auto dirtyBit : angle::IterateBitSet(dirtyBits))
382 {
383 switch (dirtyBit)
384 {
385 case Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
386 BindFramebufferAttachment(mFunctions, GL_DEPTH_ATTACHMENT,
Jamie Madill48ef11b2016-04-27 15:21:52 -0400387 mState.getDepthAttachment());
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500388 break;
389 case Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
390 BindFramebufferAttachment(mFunctions, GL_STENCIL_ATTACHMENT,
Jamie Madill48ef11b2016-04-27 15:21:52 -0400391 mState.getStencilAttachment());
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500392 break;
393 case Framebuffer::DIRTY_BIT_DRAW_BUFFERS:
394 {
Jamie Madill48ef11b2016-04-27 15:21:52 -0400395 const auto &drawBuffers = mState.getDrawBufferStates();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500396 mFunctions->drawBuffers(static_cast<GLsizei>(drawBuffers.size()),
397 drawBuffers.data());
398 break;
399 }
400 case Framebuffer::DIRTY_BIT_READ_BUFFER:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400401 mFunctions->readBuffer(mState.getReadBufferState());
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500402 break;
403 default:
404 {
405 ASSERT(Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0 &&
406 dirtyBit < Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX);
407 size_t index =
408 static_cast<size_t>(dirtyBit - Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
409 BindFramebufferAttachment(mFunctions,
410 static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + index),
Jamie Madill48ef11b2016-04-27 15:21:52 -0400411 mState.getColorAttachment(index));
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500412 break;
413 }
414 }
415 }
416}
417
Geoff Lang4ad17092015-03-10 16:47:44 -0400418GLuint FramebufferGL::getFramebufferID() const
419{
420 return mFramebufferID;
Geoff Langf9a6f082015-01-22 13:32:49 -0500421}
422
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700423bool FramebufferGL::isDefault() const
Geoff Langafd7f0a2015-09-09 15:33:31 -0400424{
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700425 return mIsDefault;
Geoff Langafd7f0a2015-09-09 15:33:31 -0400426}
427
428void FramebufferGL::syncClearState(GLbitfield mask)
429{
Frank Henigmana3d333c2016-03-22 22:09:14 -0400430 if (mFunctions->standard == STANDARD_GL_DESKTOP)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400431 {
Frank Henigmana3d333c2016-03-22 22:09:14 -0400432 if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments &&
433 (mask & GL_COLOR_BUFFER_BIT) != 0 && !mIsDefault)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400434 {
Corentin Wallez26a717b2016-09-27 08:45:42 -0700435 bool hasSRGBAttachment = false;
Jamie Madill48ef11b2016-04-27 15:21:52 -0400436 for (const auto &attachment : mState.getColorAttachments())
Geoff Langafd7f0a2015-09-09 15:33:31 -0400437 {
Frank Henigmana3d333c2016-03-22 22:09:14 -0400438 if (attachment.isAttached() && attachment.getColorEncoding() == GL_SRGB)
439 {
Corentin Wallez26a717b2016-09-27 08:45:42 -0700440 hasSRGBAttachment = true;
Frank Henigmana3d333c2016-03-22 22:09:14 -0400441 break;
442 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400443 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400444
Corentin Wallez26a717b2016-09-27 08:45:42 -0700445 mStateManager->setFramebufferSRGBEnabled(hasSRGBAttachment);
Frank Henigmana3d333c2016-03-22 22:09:14 -0400446 }
447 else
448 {
449 mStateManager->setFramebufferSRGBEnabled(!mIsDefault);
450 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400451 }
452}
453
454void FramebufferGL::syncClearBufferState(GLenum buffer, GLint drawBuffer)
455{
456 if (mFunctions->standard == STANDARD_GL_DESKTOP)
457 {
458 if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments && buffer == GL_COLOR &&
459 !mIsDefault)
460 {
461 // If doing a clear on a color buffer, set SRGB blend enabled only if the color buffer
462 // is an SRGB format.
Jamie Madill48ef11b2016-04-27 15:21:52 -0400463 const auto &drawbufferState = mState.getDrawBufferStates();
464 const auto &colorAttachments = mState.getColorAttachments();
Geoff Langafd7f0a2015-09-09 15:33:31 -0400465
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500466 const FramebufferAttachment *attachment = nullptr;
Geoff Langafd7f0a2015-09-09 15:33:31 -0400467 if (drawbufferState[drawBuffer] >= GL_COLOR_ATTACHMENT0 &&
468 drawbufferState[drawBuffer] < GL_COLOR_ATTACHMENT0 + colorAttachments.size())
469 {
470 size_t attachmentIdx =
471 static_cast<size_t>(drawbufferState[drawBuffer] - GL_COLOR_ATTACHMENT0);
472 attachment = &colorAttachments[attachmentIdx];
473 }
474
475 if (attachment != nullptr)
476 {
477 mStateManager->setFramebufferSRGBEnabled(attachment->getColorEncoding() == GL_SRGB);
478 }
479 }
480 else
481 {
482 mStateManager->setFramebufferSRGBEnabled(!mIsDefault);
483 }
484 }
485}
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400486gl::Error FramebufferGL::readPixelsRowByRowWorkaround(const gl::Rectangle &area,
487 GLenum format,
488 GLenum type,
489 const gl::PixelPackState &pack,
490 GLvoid *pixels) const
491{
492 intptr_t offset = reinterpret_cast<intptr_t>(pixels);
493
494 const gl::InternalFormat &glFormat =
495 gl::GetInternalFormatInfo(gl::GetSizedInternalFormat(format, type));
496 GLuint rowBytes = 0;
497 ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
498 rowBytes);
499 GLuint skipBytes = 0;
Corentin Wallez886de362016-09-27 10:49:35 -0400500 ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400501
502 gl::PixelPackState directPack;
503 directPack.pixelBuffer = pack.pixelBuffer;
504 directPack.alignment = 1;
505 mStateManager->setPixelPackState(directPack);
506 directPack.pixelBuffer.set(nullptr);
507
508 offset += skipBytes;
509 for (GLint row = 0; row < area.height; ++row)
510 {
511 mFunctions->readPixels(area.x, row + area.y, area.width, 1, format, type,
512 reinterpret_cast<GLvoid *>(offset));
513 offset += row * rowBytes;
514 }
515
516 return gl::NoError();
517}
518
519gl::Error FramebufferGL::readPixelsPaddingWorkaround(const gl::Rectangle &area,
520 GLenum format,
521 GLenum type,
522 const gl::PixelPackState &pack,
523 GLvoid *pixels) const
524{
525 const gl::InternalFormat &glFormat =
526 gl::GetInternalFormatInfo(gl::GetSizedInternalFormat(format, type));
527 GLuint rowBytes = 0;
528 ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
529 rowBytes);
530 GLuint skipBytes = 0;
Corentin Wallez886de362016-09-27 10:49:35 -0400531 ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400532
533 // Get all by the last row
534 if (area.height > 1)
535 {
536 mFunctions->readPixels(area.x, area.y, area.width, area.height - 1, format, type, pixels);
537 }
538
539 // Get the last row manually
540 gl::PixelPackState directPack;
541 directPack.pixelBuffer = pack.pixelBuffer;
542 directPack.alignment = 1;
543 mStateManager->setPixelPackState(directPack);
544 directPack.pixelBuffer.set(nullptr);
545
546 intptr_t lastRowOffset =
547 reinterpret_cast<intptr_t>(pixels) + skipBytes + (area.height - 1) * rowBytes;
548 mFunctions->readPixels(area.x, area.y + area.height - 1, area.width, 1, format, type,
549 reinterpret_cast<GLvoid *>(lastRowOffset));
550
551 return gl::NoError();
552}
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500553} // namespace rx