blob: 15f23d473342f2c6d0e31f6ad2c23fce564fc96d [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 Madill20e005b2017-04-07 14:19:22 -040011#include "common/bitset_utils.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"
Geoff Lang4ad17092015-03-10 16:47:44 -040014#include "libANGLE/FramebufferAttachment.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040015#include "libANGLE/State.h"
Geoff Lang4ad17092015-03-10 16:47:44 -040016#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
JiangYizhoubddc46b2016-12-09 09:50:51 +080088 if (texture->getTarget() == GL_TEXTURE_2D ||
89 texture->getTarget() == GL_TEXTURE_2D_MULTISAMPLE)
Geoff Lang4ad17092015-03-10 16:47:44 -040090 {
JiangYizhoubddc46b2016-12-09 09:50:51 +080091 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint,
92 texture->getTarget(), textureGL->getTextureID(),
93 attachment->mipLevel());
Geoff Lang4ad17092015-03-10 16:47:44 -040094 }
95 else if (texture->getTarget() == GL_TEXTURE_CUBE_MAP)
96 {
Jamie Madill231c7f52017-04-26 13:45:37 -040097 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint,
98 attachment->cubeMapFace(),
Geoff Lang4ad17092015-03-10 16:47:44 -040099 textureGL->getTextureID(), attachment->mipLevel());
100 }
Jamie Madill231c7f52017-04-26 13:45:37 -0400101 else if (texture->getTarget() == GL_TEXTURE_2D_ARRAY ||
102 texture->getTarget() == GL_TEXTURE_3D)
Geoff Lang4ad17092015-03-10 16:47:44 -0400103 {
Jamie Madill231c7f52017-04-26 13:45:37 -0400104 functions->framebufferTextureLayer(GL_FRAMEBUFFER, attachmentPoint,
105 textureGL->getTextureID(),
Geoff Lang4ad17092015-03-10 16:47:44 -0400106 attachment->mipLevel(), attachment->layer());
107 }
108 else
109 {
110 UNREACHABLE();
111 }
112 }
113 else if (attachment->type() == GL_RENDERBUFFER)
114 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500115 const Renderbuffer *renderbuffer = attachment->getRenderbuffer();
Geoff Langcd69f1c2015-03-18 14:33:23 -0400116 const RenderbufferGL *renderbufferGL = GetImplAs<RenderbufferGL>(renderbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400117
Geoff Langcd69f1c2015-03-18 14:33:23 -0400118 functions->framebufferRenderbuffer(GL_FRAMEBUFFER, attachmentPoint, GL_RENDERBUFFER,
119 renderbufferGL->getRenderbufferID());
Geoff Lang4ad17092015-03-10 16:47:44 -0400120 }
121 else
122 {
123 UNREACHABLE();
124 }
125 }
126 else
127 {
128 // Unbind this attachment
129 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_2D, 0, 0);
130 }
131}
Geoff Langf9a6f082015-01-22 13:32:49 -0500132
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500133Error FramebufferGL::discard(size_t count, const GLenum *attachments)
Austin Kinross08332632015-05-05 13:35:47 -0700134{
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500135 // glInvalidateFramebuffer accepts the same enums as glDiscardFramebufferEXT
136 return invalidate(count, attachments);
Austin Kinross08332632015-05-05 13:35:47 -0700137}
138
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500139Error FramebufferGL::invalidate(size_t count, const GLenum *attachments)
Geoff Langf9a6f082015-01-22 13:32:49 -0500140{
Geoff Lang005a7012017-03-27 13:17:34 -0400141 const GLenum *finalAttachmentsPtr = attachments;
142
143 std::vector<GLenum> modifiedAttachments;
144 if (modifyInvalidateAttachmentsForEmulatedDefaultFBO(count, attachments, &modifiedAttachments))
145 {
146 finalAttachmentsPtr = modifiedAttachments.data();
147 }
148
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500149 // Since this function is just a hint, only call a native function if it exists.
Geoff Lang64a72442015-04-01 14:43:11 -0400150 if (mFunctions->invalidateFramebuffer)
151 {
152 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Geoff Lang005a7012017-03-27 13:17:34 -0400153 mFunctions->invalidateFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
154 finalAttachmentsPtr);
Geoff Lang64a72442015-04-01 14:43:11 -0400155 }
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500156 else if (mFunctions->discardFramebuffer)
157 {
158 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Geoff Lang005a7012017-03-27 13:17:34 -0400159 mFunctions->discardFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
160 finalAttachmentsPtr);
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500161 }
Geoff Lang64a72442015-04-01 14:43:11 -0400162
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500163 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500164}
165
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500166Error FramebufferGL::invalidateSub(size_t count,
167 const GLenum *attachments,
168 const gl::Rectangle &area)
Geoff Langf9a6f082015-01-22 13:32:49 -0500169{
Geoff Lang005a7012017-03-27 13:17:34 -0400170
171 const GLenum *finalAttachmentsPtr = attachments;
172
173 std::vector<GLenum> modifiedAttachments;
174 if (modifyInvalidateAttachmentsForEmulatedDefaultFBO(count, attachments, &modifiedAttachments))
175 {
176 finalAttachmentsPtr = modifiedAttachments.data();
177 }
178
Jamie Madill231c7f52017-04-26 13:45:37 -0400179 // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is
180 // available.
Geoff Lang64a72442015-04-01 14:43:11 -0400181 if (mFunctions->invalidateSubFramebuffer)
182 {
183 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700184 mFunctions->invalidateSubFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
Geoff Lang005a7012017-03-27 13:17:34 -0400185 finalAttachmentsPtr, area.x, area.y, area.width,
186 area.height);
Geoff Lang64a72442015-04-01 14:43:11 -0400187 }
188
He Yunchaoacd18982017-01-04 10:46:42 +0800189 return NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500190}
191
Jamie Madill8415b5f2016-04-26 13:41:39 -0400192Error FramebufferGL::clear(ContextImpl *context, GLbitfield mask)
Geoff Langf9a6f082015-01-22 13:32:49 -0500193{
Frank Henigman308d7452017-02-15 22:51:21 -0500194 syncClearState(context, mask);
Geoff Lang4ad17092015-03-10 16:47:44 -0400195 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
196 mFunctions->clear(mask);
197
He Yunchaoacd18982017-01-04 10:46:42 +0800198 return NoError();
Geoff Lang4ad17092015-03-10 16:47:44 -0400199}
200
Jamie Madill8415b5f2016-04-26 13:41:39 -0400201Error FramebufferGL::clearBufferfv(ContextImpl *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500202 GLenum buffer,
203 GLint drawbuffer,
204 const GLfloat *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500205{
Frank Henigman308d7452017-02-15 22:51:21 -0500206 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400207 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
208 mFunctions->clearBufferfv(buffer, drawbuffer, values);
209
He Yunchaoacd18982017-01-04 10:46:42 +0800210 return NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500211}
212
Jamie Madill8415b5f2016-04-26 13:41:39 -0400213Error FramebufferGL::clearBufferuiv(ContextImpl *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500214 GLenum buffer,
215 GLint drawbuffer,
216 const GLuint *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500217{
Frank Henigman308d7452017-02-15 22:51:21 -0500218 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400219 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
220 mFunctions->clearBufferuiv(buffer, drawbuffer, values);
221
He Yunchaoacd18982017-01-04 10:46:42 +0800222 return NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500223}
224
Jamie Madill8415b5f2016-04-26 13:41:39 -0400225Error FramebufferGL::clearBufferiv(ContextImpl *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500226 GLenum buffer,
227 GLint drawbuffer,
228 const GLint *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500229{
Frank Henigman308d7452017-02-15 22:51:21 -0500230 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400231 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
232 mFunctions->clearBufferiv(buffer, drawbuffer, values);
233
He Yunchaoacd18982017-01-04 10:46:42 +0800234 return NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500235}
236
Jamie Madill8415b5f2016-04-26 13:41:39 -0400237Error FramebufferGL::clearBufferfi(ContextImpl *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500238 GLenum buffer,
239 GLint drawbuffer,
240 GLfloat depth,
241 GLint stencil)
Geoff Langf9a6f082015-01-22 13:32:49 -0500242{
Frank Henigman308d7452017-02-15 22:51:21 -0500243 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400244 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
245 mFunctions->clearBufferfi(buffer, drawbuffer, depth, stencil);
246
He Yunchaoacd18982017-01-04 10:46:42 +0800247 return NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500248}
249
250GLenum FramebufferGL::getImplementationColorReadFormat() const
251{
Jamie Madilla3944d42016-07-22 22:13:26 -0400252 const auto *readAttachment = mState.getReadAttachment();
253 const Format &format = readAttachment->getFormat();
Geoff Langf607c602016-09-21 11:46:48 -0400254 return format.info->getReadPixelsFormat();
Geoff Langf9a6f082015-01-22 13:32:49 -0500255}
256
257GLenum FramebufferGL::getImplementationColorReadType() const
258{
Jamie Madilla3944d42016-07-22 22:13:26 -0400259 const auto *readAttachment = mState.getReadAttachment();
260 const Format &format = readAttachment->getFormat();
Geoff Langf607c602016-09-21 11:46:48 -0400261 return format.info->getReadPixelsType();
Geoff Langf9a6f082015-01-22 13:32:49 -0500262}
263
Jamie Madill8415b5f2016-04-26 13:41:39 -0400264Error FramebufferGL::readPixels(ContextImpl *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500265 const gl::Rectangle &area,
266 GLenum format,
267 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400268 void *pixels) const
Geoff Langf9a6f082015-01-22 13:32:49 -0500269{
Geoff Langda34d002015-09-04 11:08:59 -0400270 // TODO: don't sync the pixel pack state here once the dirty bits contain the pixel pack buffer
271 // binding
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700272 const PixelPackState &packState = context->getGLState().getPackState();
Geoff Langda34d002015-09-04 11:08:59 -0400273 mStateManager->setPixelPackState(packState);
Jamie Madill87de3622015-03-16 10:41:44 -0400274
Geoff Langf607c602016-09-21 11:46:48 -0400275 nativegl::ReadPixelsFormat readPixelsFormat =
276 nativegl::GetReadPixelsFormat(mFunctions, mWorkarounds, format, type);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400277 GLenum readFormat = readPixelsFormat.format;
278 GLenum readType = readPixelsFormat.type;
Geoff Lang4ad17092015-03-10 16:47:44 -0400279
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400280 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, mFramebufferID);
281
282 if (mWorkarounds.packOverlappingRowsSeparatelyPackBuffer && packState.pixelBuffer.get() &&
283 packState.rowLength != 0 && packState.rowLength < area.width)
284 {
285 return readPixelsRowByRowWorkaround(area, readFormat, readType, packState, pixels);
286 }
287
288 if (mWorkarounds.packLastRowSeparatelyForPaddingInclusion)
289 {
Corentin Wallez886de362016-09-27 10:49:35 -0400290 gl::Extents size(area.width, area.height, 1);
291
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400292 bool apply;
Corentin Wallez886de362016-09-27 10:49:35 -0400293 ANGLE_TRY_RESULT(ShouldApplyLastRowPaddingWorkaround(size, packState, readFormat, readType,
294 false, pixels),
295 apply);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400296
297 if (apply)
298 {
299 return readPixelsPaddingWorkaround(area, readFormat, readType, packState, pixels);
300 }
301 }
302
303 mFunctions->readPixels(area.x, area.y, area.width, area.height, readFormat, readType, pixels);
304
305 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500306}
307
Jamie Madill8415b5f2016-04-26 13:41:39 -0400308Error FramebufferGL::blit(ContextImpl *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500309 const gl::Rectangle &sourceArea,
310 const gl::Rectangle &destArea,
311 GLbitfield mask,
Jamie Madill8415b5f2016-04-26 13:41:39 -0400312 GLenum filter)
Geoff Langf9a6f082015-01-22 13:32:49 -0500313{
Jamie Madill231c7f52017-04-26 13:45:37 -0400314 const Framebuffer *sourceFramebuffer = context->getGLState().getReadFramebuffer();
315 const Framebuffer *destFramebuffer = context->getGLState().getDrawFramebuffer();
Geoff Lang4ad17092015-03-10 16:47:44 -0400316
Corentin Wallez6898b352016-11-10 11:41:15 -0500317 const FramebufferAttachment *colorReadAttachment = sourceFramebuffer->getReadColorbuffer();
Corentin Wallez4596a762016-12-20 14:50:18 -0500318
319 GLsizei readAttachmentSamples = 0;
320 if (colorReadAttachment != nullptr)
321 {
322 readAttachmentSamples = colorReadAttachment->getSamples();
323 }
Corentin Wallez6898b352016-11-10 11:41:15 -0500324
Corentin Wallez26a717b2016-09-27 08:45:42 -0700325 bool needManualColorBlit = false;
326
Corentin Wallez6898b352016-11-10 11:41:15 -0500327 // TODO(cwallez) when the filter is LINEAR and both source and destination are SRGB, we
328 // could avoid doing a manual blit.
329
330 // Prior to OpenGL 4.4 BlitFramebuffer (section 18.3.1 of GL 4.3 core profile) reads:
331 // When values are taken from the read buffer, no linearization is performed, even
332 // if the format of the buffer is SRGB.
333 // Starting from OpenGL 4.4 (section 18.3.1) it reads:
334 // When values are taken from the read buffer, if FRAMEBUFFER_SRGB is enabled and the
335 // value of FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING for the framebuffer attachment
336 // corresponding to the read buffer is SRGB, the red, green, and blue components are
337 // converted from the non-linear sRGB color space according [...].
Corentin Wallez26a717b2016-09-27 08:45:42 -0700338 {
Jamie Madill231c7f52017-04-26 13:45:37 -0400339 bool sourceSRGB =
340 colorReadAttachment != nullptr && colorReadAttachment->getColorEncoding() == GL_SRGB;
Corentin Wallez6898b352016-11-10 11:41:15 -0500341 needManualColorBlit =
342 needManualColorBlit || (sourceSRGB && mFunctions->isAtMostGL(gl::Version(4, 3)));
343 }
Corentin Wallez26a717b2016-09-27 08:45:42 -0700344
Corentin Wallez6898b352016-11-10 11:41:15 -0500345 // Prior to OpenGL 4.2 BlitFramebuffer (section 4.3.2 of GL 4.1 core profile) reads:
346 // Blit operations bypass the fragment pipeline. The only fragment operations which
347 // affect a blit are the pixel ownership test and scissor test.
348 // Starting from OpenGL 4.2 (section 4.3.2) it reads:
349 // When values are written to the draw buffers, blit operations bypass the fragment
350 // pipeline. The only fragment operations which affect a blit are the pixel ownership
351 // test, the scissor test and sRGB conversion.
352 if (!needManualColorBlit)
353 {
354 bool destSRGB = false;
355 for (size_t i = 0; i < destFramebuffer->getDrawbufferStateCount(); ++i)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700356 {
Corentin Wallez6898b352016-11-10 11:41:15 -0500357 const FramebufferAttachment *attachment = destFramebuffer->getDrawBuffer(i);
358 if (attachment && attachment->getColorEncoding() == GL_SRGB)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700359 {
Corentin Wallez6898b352016-11-10 11:41:15 -0500360 destSRGB = true;
361 break;
Corentin Wallez26a717b2016-09-27 08:45:42 -0700362 }
Corentin Wallez26a717b2016-09-27 08:45:42 -0700363 }
Corentin Wallez6898b352016-11-10 11:41:15 -0500364
365 needManualColorBlit =
366 needManualColorBlit || (destSRGB && mFunctions->isAtMostGL(gl::Version(4, 1)));
Corentin Wallez26a717b2016-09-27 08:45:42 -0700367 }
368
369 // Enable FRAMEBUFFER_SRGB if needed
Frank Henigman308d7452017-02-15 22:51:21 -0500370 mStateManager->setFramebufferSRGBEnabledForFramebuffer(context->getContextState(), true, this);
Corentin Wallez26a717b2016-09-27 08:45:42 -0700371
372 GLenum blitMask = mask;
Corentin Wallez6898b352016-11-10 11:41:15 -0500373 if (needManualColorBlit && (mask & GL_COLOR_BUFFER_BIT) && readAttachmentSamples <= 1)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700374 {
375 ANGLE_TRY(mBlitter->blitColorBufferWithShader(sourceFramebuffer, destFramebuffer,
376 sourceArea, destArea, filter));
377 blitMask &= ~GL_COLOR_BUFFER_BIT;
378 }
379
380 if (blitMask == 0)
381 {
382 return gl::NoError();
383 }
384
385 const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(sourceFramebuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400386 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
387 mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferID);
388
Jamie Madill2da819e2015-12-03 15:53:19 -0500389 mFunctions->blitFramebuffer(sourceArea.x, sourceArea.y, sourceArea.x1(), sourceArea.y1(),
Corentin Wallez26a717b2016-09-27 08:45:42 -0700390 destArea.x, destArea.y, destArea.x1(), destArea.y1(), blitMask,
391 filter);
Geoff Lang4ad17092015-03-10 16:47:44 -0400392
Corentin Wallez26a717b2016-09-27 08:45:42 -0700393 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500394}
395
JiangYizhoubddc46b2016-12-09 09:50:51 +0800396gl::Error FramebufferGL::getSamplePosition(size_t index, GLfloat *xy) const
397{
398 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
399 mFunctions->getMultisamplefv(GL_SAMPLE_POSITION, static_cast<GLuint>(index), xy);
400 return gl::NoError();
401}
402
Jamie Madillcc86d642015-11-24 13:00:07 -0500403bool FramebufferGL::checkStatus() const
Geoff Langf9a6f082015-01-22 13:32:49 -0500404{
Geoff Lang4ad17092015-03-10 16:47:44 -0400405 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Jamie Madillcc86d642015-11-24 13:00:07 -0500406 GLenum status = mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
407 if (status != GL_FRAMEBUFFER_COMPLETE)
408 {
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500409 WARN() << "GL framebuffer returned incomplete.";
Jamie Madillcc86d642015-11-24 13:00:07 -0500410 }
411 return (status == GL_FRAMEBUFFER_COMPLETE);
Geoff Lang4ad17092015-03-10 16:47:44 -0400412}
413
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400414void FramebufferGL::syncState(ContextImpl *contextImpl, const Framebuffer::DirtyBits &dirtyBits)
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500415{
416 // Don't need to sync state for the default FBO.
417 if (mIsDefault)
418 {
419 return;
420 }
421
422 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
423
Jamie Madill6de51852017-04-12 09:53:01 -0400424 for (auto dirtyBit : dirtyBits)
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500425 {
426 switch (dirtyBit)
427 {
428 case Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
429 BindFramebufferAttachment(mFunctions, GL_DEPTH_ATTACHMENT,
Jamie Madill48ef11b2016-04-27 15:21:52 -0400430 mState.getDepthAttachment());
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500431 break;
432 case Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
433 BindFramebufferAttachment(mFunctions, GL_STENCIL_ATTACHMENT,
Jamie Madill48ef11b2016-04-27 15:21:52 -0400434 mState.getStencilAttachment());
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500435 break;
436 case Framebuffer::DIRTY_BIT_DRAW_BUFFERS:
437 {
Jamie Madill48ef11b2016-04-27 15:21:52 -0400438 const auto &drawBuffers = mState.getDrawBufferStates();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500439 mFunctions->drawBuffers(static_cast<GLsizei>(drawBuffers.size()),
440 drawBuffers.data());
441 break;
442 }
443 case Framebuffer::DIRTY_BIT_READ_BUFFER:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400444 mFunctions->readBuffer(mState.getReadBufferState());
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500445 break;
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800446 case Framebuffer::DIRTY_BIT_DEFAULT_WIDTH:
447 mFunctions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH,
448 mState.getDefaultWidth());
449 break;
450 case Framebuffer::DIRTY_BIT_DEFAULT_HEIGHT:
451 mFunctions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT,
452 mState.getDefaultHeight());
453 break;
454 case Framebuffer::DIRTY_BIT_DEFAULT_SAMPLES:
455 mFunctions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_SAMPLES,
456 mState.getDefaultSamples());
457 break;
458 case Framebuffer::DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS:
459 mFunctions->framebufferParameteri(GL_FRAMEBUFFER,
460 GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS,
461 mState.getDefaultFixedSampleLocations());
462 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500463 default:
464 {
465 ASSERT(Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0 &&
466 dirtyBit < Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX);
467 size_t index =
468 static_cast<size_t>(dirtyBit - Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
469 BindFramebufferAttachment(mFunctions,
470 static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + index),
Jamie Madill48ef11b2016-04-27 15:21:52 -0400471 mState.getColorAttachment(index));
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500472 break;
473 }
474 }
475 }
476}
477
Geoff Lang4ad17092015-03-10 16:47:44 -0400478GLuint FramebufferGL::getFramebufferID() const
479{
480 return mFramebufferID;
Geoff Langf9a6f082015-01-22 13:32:49 -0500481}
482
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700483bool FramebufferGL::isDefault() const
Geoff Langafd7f0a2015-09-09 15:33:31 -0400484{
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700485 return mIsDefault;
Geoff Langafd7f0a2015-09-09 15:33:31 -0400486}
487
Frank Henigman308d7452017-02-15 22:51:21 -0500488void FramebufferGL::syncClearState(ContextImpl *context, GLbitfield mask)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400489{
Frank Henigmana3d333c2016-03-22 22:09:14 -0400490 if (mFunctions->standard == STANDARD_GL_DESKTOP)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400491 {
Frank Henigmana3d333c2016-03-22 22:09:14 -0400492 if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments &&
493 (mask & GL_COLOR_BUFFER_BIT) != 0 && !mIsDefault)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400494 {
Corentin Wallez26a717b2016-09-27 08:45:42 -0700495 bool hasSRGBAttachment = false;
Jamie Madill48ef11b2016-04-27 15:21:52 -0400496 for (const auto &attachment : mState.getColorAttachments())
Geoff Langafd7f0a2015-09-09 15:33:31 -0400497 {
Frank Henigmana3d333c2016-03-22 22:09:14 -0400498 if (attachment.isAttached() && attachment.getColorEncoding() == GL_SRGB)
499 {
Corentin Wallez26a717b2016-09-27 08:45:42 -0700500 hasSRGBAttachment = true;
Frank Henigmana3d333c2016-03-22 22:09:14 -0400501 break;
502 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400503 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400504
Frank Henigman308d7452017-02-15 22:51:21 -0500505 mStateManager->setFramebufferSRGBEnabled(context->getContextState(), hasSRGBAttachment);
Frank Henigmana3d333c2016-03-22 22:09:14 -0400506 }
507 else
508 {
Frank Henigman308d7452017-02-15 22:51:21 -0500509 mStateManager->setFramebufferSRGBEnabled(context->getContextState(), !mIsDefault);
Frank Henigmana3d333c2016-03-22 22:09:14 -0400510 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400511 }
512}
513
Frank Henigman308d7452017-02-15 22:51:21 -0500514void FramebufferGL::syncClearBufferState(ContextImpl *context, GLenum buffer, GLint drawBuffer)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400515{
516 if (mFunctions->standard == STANDARD_GL_DESKTOP)
517 {
518 if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments && buffer == GL_COLOR &&
519 !mIsDefault)
520 {
521 // If doing a clear on a color buffer, set SRGB blend enabled only if the color buffer
522 // is an SRGB format.
Jamie Madill48ef11b2016-04-27 15:21:52 -0400523 const auto &drawbufferState = mState.getDrawBufferStates();
524 const auto &colorAttachments = mState.getColorAttachments();
Geoff Langafd7f0a2015-09-09 15:33:31 -0400525
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500526 const FramebufferAttachment *attachment = nullptr;
Geoff Langafd7f0a2015-09-09 15:33:31 -0400527 if (drawbufferState[drawBuffer] >= GL_COLOR_ATTACHMENT0 &&
528 drawbufferState[drawBuffer] < GL_COLOR_ATTACHMENT0 + colorAttachments.size())
529 {
530 size_t attachmentIdx =
531 static_cast<size_t>(drawbufferState[drawBuffer] - GL_COLOR_ATTACHMENT0);
532 attachment = &colorAttachments[attachmentIdx];
533 }
534
535 if (attachment != nullptr)
536 {
Frank Henigman308d7452017-02-15 22:51:21 -0500537 mStateManager->setFramebufferSRGBEnabled(context->getContextState(),
538 attachment->getColorEncoding() == GL_SRGB);
Geoff Langafd7f0a2015-09-09 15:33:31 -0400539 }
540 }
541 else
542 {
Frank Henigman308d7452017-02-15 22:51:21 -0500543 mStateManager->setFramebufferSRGBEnabled(context->getContextState(), !mIsDefault);
Geoff Langafd7f0a2015-09-09 15:33:31 -0400544 }
545 }
546}
Geoff Lang005a7012017-03-27 13:17:34 -0400547
548bool FramebufferGL::modifyInvalidateAttachmentsForEmulatedDefaultFBO(
549 size_t count,
550 const GLenum *attachments,
551 std::vector<GLenum> *modifiedAttachments) const
552{
553 bool needsModification = mIsDefault && mFramebufferID != 0;
554 if (!needsModification)
555 {
556 return false;
557 }
558
559 modifiedAttachments->resize(count);
560 for (size_t i = 0; i < count; i++)
561 {
562 switch (attachments[i])
563 {
564 case GL_COLOR:
565 (*modifiedAttachments)[i] = GL_COLOR_ATTACHMENT0;
566 break;
567
568 case GL_DEPTH:
569 (*modifiedAttachments)[i] = GL_DEPTH_ATTACHMENT;
570 break;
571
572 case GL_STENCIL:
573 (*modifiedAttachments)[i] = GL_STENCIL_ATTACHMENT;
574 break;
575
576 default:
577 UNREACHABLE();
578 break;
579 }
580 }
581
582 return true;
583}
584
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400585gl::Error FramebufferGL::readPixelsRowByRowWorkaround(const gl::Rectangle &area,
586 GLenum format,
587 GLenum type,
588 const gl::PixelPackState &pack,
Jamie Madill876429b2017-04-20 15:46:24 -0400589 void *pixels) const
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400590{
591 intptr_t offset = reinterpret_cast<intptr_t>(pixels);
592
Geoff Langca271392017-04-05 12:30:00 -0400593 const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(format, type);
Jamie Madill231c7f52017-04-26 13:45:37 -0400594 GLuint rowBytes = 0;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400595 ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
596 rowBytes);
597 GLuint skipBytes = 0;
Corentin Wallez886de362016-09-27 10:49:35 -0400598 ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400599
600 gl::PixelPackState directPack;
601 directPack.pixelBuffer = pack.pixelBuffer;
602 directPack.alignment = 1;
603 mStateManager->setPixelPackState(directPack);
604 directPack.pixelBuffer.set(nullptr);
605
606 offset += skipBytes;
607 for (GLint row = 0; row < area.height; ++row)
608 {
609 mFunctions->readPixels(area.x, row + area.y, area.width, 1, format, type,
Jamie Madill876429b2017-04-20 15:46:24 -0400610 reinterpret_cast<void *>(offset));
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400611 offset += row * rowBytes;
612 }
613
614 return gl::NoError();
615}
616
617gl::Error FramebufferGL::readPixelsPaddingWorkaround(const gl::Rectangle &area,
618 GLenum format,
619 GLenum type,
620 const gl::PixelPackState &pack,
Jamie Madill876429b2017-04-20 15:46:24 -0400621 void *pixels) const
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400622{
Geoff Langca271392017-04-05 12:30:00 -0400623 const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(format, type);
Jamie Madill231c7f52017-04-26 13:45:37 -0400624 GLuint rowBytes = 0;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400625 ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
626 rowBytes);
627 GLuint skipBytes = 0;
Corentin Wallez886de362016-09-27 10:49:35 -0400628 ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400629
630 // Get all by the last row
631 if (area.height > 1)
632 {
633 mFunctions->readPixels(area.x, area.y, area.width, area.height - 1, format, type, pixels);
634 }
635
636 // Get the last row manually
637 gl::PixelPackState directPack;
638 directPack.pixelBuffer = pack.pixelBuffer;
639 directPack.alignment = 1;
640 mStateManager->setPixelPackState(directPack);
641 directPack.pixelBuffer.set(nullptr);
642
643 intptr_t lastRowOffset =
644 reinterpret_cast<intptr_t>(pixels) + skipBytes + (area.height - 1) * rowBytes;
645 mFunctions->readPixels(area.x, area.y + area.height - 1, area.width, 1, format, type,
Jamie Madill876429b2017-04-20 15:46:24 -0400646 reinterpret_cast<void *>(lastRowOffset));
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400647
648 return gl::NoError();
649}
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500650} // namespace rx