blob: 67c025cc1f1e95072e80a15bd86e7984af309411 [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 Madillc564c072017-06-01 12:45:42 -040013#include "libANGLE/Context.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),
Corentin Walleze7557742017-06-01 13:09:57 -040047 mIsDefault(isDefault),
48 mAppliedEnabledDrawBuffers(1)
Geoff Lang4ad17092015-03-10 16:47:44 -040049{
Corentin Wallez6ab01b92015-08-03 10:16:36 -070050 if (!mIsDefault)
Geoff Lang4ad17092015-03-10 16:47:44 -040051 {
52 mFunctions->genFramebuffers(1, &mFramebufferID);
53 }
54}
Geoff Langf9a6f082015-01-22 13:32:49 -050055
Corentin Wallez86f8dd72015-08-12 12:37:48 -070056FramebufferGL::FramebufferGL(GLuint id,
Jamie Madill48ef11b2016-04-27 15:21:52 -040057 const FramebufferState &state,
Corentin Wallez86f8dd72015-08-12 12:37:48 -070058 const FunctionsGL *functions,
Geoff Langafd7f0a2015-09-09 15:33:31 -040059 const WorkaroundsGL &workarounds,
Corentin Wallez26a717b2016-09-27 08:45:42 -070060 BlitGL *blitter,
Corentin Wallez86f8dd72015-08-12 12:37:48 -070061 StateManagerGL *stateManager)
Jamie Madill48ef11b2016-04-27 15:21:52 -040062 : FramebufferImpl(state),
Corentin Wallez86f8dd72015-08-12 12:37:48 -070063 mFunctions(functions),
64 mStateManager(stateManager),
Geoff Langafd7f0a2015-09-09 15:33:31 -040065 mWorkarounds(workarounds),
Corentin Wallez26a717b2016-09-27 08:45:42 -070066 mBlitter(blitter),
Corentin Wallez86f8dd72015-08-12 12:37:48 -070067 mFramebufferID(id),
Corentin Walleze7557742017-06-01 13:09:57 -040068 mIsDefault(true),
69 mAppliedEnabledDrawBuffers(1)
Corentin Wallez86f8dd72015-08-12 12:37:48 -070070{
71}
72
Geoff Langf9a6f082015-01-22 13:32:49 -050073FramebufferGL::~FramebufferGL()
Geoff Lang4ad17092015-03-10 16:47:44 -040074{
Geoff Lang1eb708e2015-05-04 14:58:23 -040075 mStateManager->deleteFramebuffer(mFramebufferID);
76 mFramebufferID = 0;
Geoff Lang4ad17092015-03-10 16:47:44 -040077}
78
Jamie Madill60ec6ea2016-01-22 15:27:19 -050079static void BindFramebufferAttachment(const FunctionsGL *functions,
80 GLenum attachmentPoint,
81 const FramebufferAttachment *attachment)
Geoff Lang4ad17092015-03-10 16:47:44 -040082{
83 if (attachment)
84 {
85 if (attachment->type() == GL_TEXTURE)
86 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -050087 const Texture *texture = attachment->getTexture();
Geoff Lang4ad17092015-03-10 16:47:44 -040088 const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
89
JiangYizhoubddc46b2016-12-09 09:50:51 +080090 if (texture->getTarget() == GL_TEXTURE_2D ||
91 texture->getTarget() == GL_TEXTURE_2D_MULTISAMPLE)
Geoff Lang4ad17092015-03-10 16:47:44 -040092 {
JiangYizhoubddc46b2016-12-09 09:50:51 +080093 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint,
94 texture->getTarget(), textureGL->getTextureID(),
95 attachment->mipLevel());
Geoff Lang4ad17092015-03-10 16:47:44 -040096 }
97 else if (texture->getTarget() == GL_TEXTURE_CUBE_MAP)
98 {
Jamie Madill231c7f52017-04-26 13:45:37 -040099 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint,
100 attachment->cubeMapFace(),
Geoff Lang4ad17092015-03-10 16:47:44 -0400101 textureGL->getTextureID(), attachment->mipLevel());
102 }
Jamie Madill231c7f52017-04-26 13:45:37 -0400103 else if (texture->getTarget() == GL_TEXTURE_2D_ARRAY ||
104 texture->getTarget() == GL_TEXTURE_3D)
Geoff Lang4ad17092015-03-10 16:47:44 -0400105 {
Jamie Madill231c7f52017-04-26 13:45:37 -0400106 functions->framebufferTextureLayer(GL_FRAMEBUFFER, attachmentPoint,
107 textureGL->getTextureID(),
Geoff Lang4ad17092015-03-10 16:47:44 -0400108 attachment->mipLevel(), attachment->layer());
109 }
110 else
111 {
112 UNREACHABLE();
113 }
114 }
115 else if (attachment->type() == GL_RENDERBUFFER)
116 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500117 const Renderbuffer *renderbuffer = attachment->getRenderbuffer();
Geoff Langcd69f1c2015-03-18 14:33:23 -0400118 const RenderbufferGL *renderbufferGL = GetImplAs<RenderbufferGL>(renderbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400119
Geoff Langcd69f1c2015-03-18 14:33:23 -0400120 functions->framebufferRenderbuffer(GL_FRAMEBUFFER, attachmentPoint, GL_RENDERBUFFER,
121 renderbufferGL->getRenderbufferID());
Geoff Lang4ad17092015-03-10 16:47:44 -0400122 }
123 else
124 {
125 UNREACHABLE();
126 }
127 }
128 else
129 {
130 // Unbind this attachment
131 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_2D, 0, 0);
132 }
133}
Geoff Langf9a6f082015-01-22 13:32:49 -0500134
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500135Error FramebufferGL::discard(size_t count, const GLenum *attachments)
Austin Kinross08332632015-05-05 13:35:47 -0700136{
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500137 // glInvalidateFramebuffer accepts the same enums as glDiscardFramebufferEXT
138 return invalidate(count, attachments);
Austin Kinross08332632015-05-05 13:35:47 -0700139}
140
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500141Error FramebufferGL::invalidate(size_t count, const GLenum *attachments)
Geoff Langf9a6f082015-01-22 13:32:49 -0500142{
Geoff Lang005a7012017-03-27 13:17:34 -0400143 const GLenum *finalAttachmentsPtr = attachments;
144
145 std::vector<GLenum> modifiedAttachments;
146 if (modifyInvalidateAttachmentsForEmulatedDefaultFBO(count, attachments, &modifiedAttachments))
147 {
148 finalAttachmentsPtr = modifiedAttachments.data();
149 }
150
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500151 // Since this function is just a hint, only call a native function if it exists.
Geoff Lang64a72442015-04-01 14:43:11 -0400152 if (mFunctions->invalidateFramebuffer)
153 {
154 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Geoff Lang005a7012017-03-27 13:17:34 -0400155 mFunctions->invalidateFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
156 finalAttachmentsPtr);
Geoff Lang64a72442015-04-01 14:43:11 -0400157 }
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500158 else if (mFunctions->discardFramebuffer)
159 {
160 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Geoff Lang005a7012017-03-27 13:17:34 -0400161 mFunctions->discardFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
162 finalAttachmentsPtr);
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500163 }
Geoff Lang64a72442015-04-01 14:43:11 -0400164
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500165 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500166}
167
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500168Error FramebufferGL::invalidateSub(size_t count,
169 const GLenum *attachments,
170 const gl::Rectangle &area)
Geoff Langf9a6f082015-01-22 13:32:49 -0500171{
Geoff Lang005a7012017-03-27 13:17:34 -0400172
173 const GLenum *finalAttachmentsPtr = attachments;
174
175 std::vector<GLenum> modifiedAttachments;
176 if (modifyInvalidateAttachmentsForEmulatedDefaultFBO(count, attachments, &modifiedAttachments))
177 {
178 finalAttachmentsPtr = modifiedAttachments.data();
179 }
180
Jamie Madill231c7f52017-04-26 13:45:37 -0400181 // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is
182 // available.
Geoff Lang64a72442015-04-01 14:43:11 -0400183 if (mFunctions->invalidateSubFramebuffer)
184 {
185 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700186 mFunctions->invalidateSubFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
Geoff Lang005a7012017-03-27 13:17:34 -0400187 finalAttachmentsPtr, area.x, area.y, area.width,
188 area.height);
Geoff Lang64a72442015-04-01 14:43:11 -0400189 }
190
He Yunchaoacd18982017-01-04 10:46:42 +0800191 return NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500192}
193
Jamie Madillc564c072017-06-01 12:45:42 -0400194Error FramebufferGL::clear(const gl::Context *context, GLbitfield mask)
Geoff Langf9a6f082015-01-22 13:32:49 -0500195{
Frank Henigman308d7452017-02-15 22:51:21 -0500196 syncClearState(context, mask);
Geoff Lang4ad17092015-03-10 16:47:44 -0400197 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
198 mFunctions->clear(mask);
199
He Yunchaoacd18982017-01-04 10:46:42 +0800200 return NoError();
Geoff Lang4ad17092015-03-10 16:47:44 -0400201}
202
Jamie Madillc564c072017-06-01 12:45:42 -0400203Error FramebufferGL::clearBufferfv(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500204 GLenum buffer,
205 GLint drawbuffer,
206 const GLfloat *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500207{
Frank Henigman308d7452017-02-15 22:51:21 -0500208 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400209 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
210 mFunctions->clearBufferfv(buffer, drawbuffer, values);
211
He Yunchaoacd18982017-01-04 10:46:42 +0800212 return NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500213}
214
Jamie Madillc564c072017-06-01 12:45:42 -0400215Error FramebufferGL::clearBufferuiv(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500216 GLenum buffer,
217 GLint drawbuffer,
218 const GLuint *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500219{
Frank Henigman308d7452017-02-15 22:51:21 -0500220 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400221 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
222 mFunctions->clearBufferuiv(buffer, drawbuffer, values);
223
He Yunchaoacd18982017-01-04 10:46:42 +0800224 return NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500225}
226
Jamie Madillc564c072017-06-01 12:45:42 -0400227Error FramebufferGL::clearBufferiv(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500228 GLenum buffer,
229 GLint drawbuffer,
230 const GLint *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500231{
Frank Henigman308d7452017-02-15 22:51:21 -0500232 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400233 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
234 mFunctions->clearBufferiv(buffer, drawbuffer, values);
235
He Yunchaoacd18982017-01-04 10:46:42 +0800236 return NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500237}
238
Jamie Madillc564c072017-06-01 12:45:42 -0400239Error FramebufferGL::clearBufferfi(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500240 GLenum buffer,
241 GLint drawbuffer,
242 GLfloat depth,
243 GLint stencil)
Geoff Langf9a6f082015-01-22 13:32:49 -0500244{
Frank Henigman308d7452017-02-15 22:51:21 -0500245 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400246 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
247 mFunctions->clearBufferfi(buffer, drawbuffer, depth, stencil);
248
He Yunchaoacd18982017-01-04 10:46:42 +0800249 return NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500250}
251
252GLenum FramebufferGL::getImplementationColorReadFormat() const
253{
Jamie Madilla3944d42016-07-22 22:13:26 -0400254 const auto *readAttachment = mState.getReadAttachment();
255 const Format &format = readAttachment->getFormat();
Geoff Langf607c602016-09-21 11:46:48 -0400256 return format.info->getReadPixelsFormat();
Geoff Langf9a6f082015-01-22 13:32:49 -0500257}
258
259GLenum FramebufferGL::getImplementationColorReadType() const
260{
Jamie Madilla3944d42016-07-22 22:13:26 -0400261 const auto *readAttachment = mState.getReadAttachment();
262 const Format &format = readAttachment->getFormat();
Geoff Langf607c602016-09-21 11:46:48 -0400263 return format.info->getReadPixelsType();
Geoff Langf9a6f082015-01-22 13:32:49 -0500264}
265
Jamie Madillc564c072017-06-01 12:45:42 -0400266Error FramebufferGL::readPixels(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500267 const gl::Rectangle &area,
268 GLenum format,
269 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400270 void *pixels) const
Geoff Langf9a6f082015-01-22 13:32:49 -0500271{
Geoff Langda34d002015-09-04 11:08:59 -0400272 // TODO: don't sync the pixel pack state here once the dirty bits contain the pixel pack buffer
273 // binding
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700274 const PixelPackState &packState = context->getGLState().getPackState();
Geoff Langda34d002015-09-04 11:08:59 -0400275 mStateManager->setPixelPackState(packState);
Jamie Madill87de3622015-03-16 10:41:44 -0400276
Geoff Langf607c602016-09-21 11:46:48 -0400277 nativegl::ReadPixelsFormat readPixelsFormat =
278 nativegl::GetReadPixelsFormat(mFunctions, mWorkarounds, format, type);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400279 GLenum readFormat = readPixelsFormat.format;
280 GLenum readType = readPixelsFormat.type;
Geoff Lang4ad17092015-03-10 16:47:44 -0400281
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400282 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, mFramebufferID);
283
284 if (mWorkarounds.packOverlappingRowsSeparatelyPackBuffer && packState.pixelBuffer.get() &&
285 packState.rowLength != 0 && packState.rowLength < area.width)
286 {
287 return readPixelsRowByRowWorkaround(area, readFormat, readType, packState, pixels);
288 }
289
290 if (mWorkarounds.packLastRowSeparatelyForPaddingInclusion)
291 {
Corentin Wallez886de362016-09-27 10:49:35 -0400292 gl::Extents size(area.width, area.height, 1);
293
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400294 bool apply;
Corentin Wallez886de362016-09-27 10:49:35 -0400295 ANGLE_TRY_RESULT(ShouldApplyLastRowPaddingWorkaround(size, packState, readFormat, readType,
296 false, pixels),
297 apply);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400298
299 if (apply)
300 {
301 return readPixelsPaddingWorkaround(area, readFormat, readType, packState, pixels);
302 }
303 }
304
305 mFunctions->readPixels(area.x, area.y, area.width, area.height, readFormat, readType, pixels);
306
307 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500308}
309
Jamie Madillc564c072017-06-01 12:45:42 -0400310Error FramebufferGL::blit(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500311 const gl::Rectangle &sourceArea,
312 const gl::Rectangle &destArea,
313 GLbitfield mask,
Jamie Madill8415b5f2016-04-26 13:41:39 -0400314 GLenum filter)
Geoff Langf9a6f082015-01-22 13:32:49 -0500315{
Jamie Madill231c7f52017-04-26 13:45:37 -0400316 const Framebuffer *sourceFramebuffer = context->getGLState().getReadFramebuffer();
317 const Framebuffer *destFramebuffer = context->getGLState().getDrawFramebuffer();
Geoff Lang4ad17092015-03-10 16:47:44 -0400318
Corentin Wallez6898b352016-11-10 11:41:15 -0500319 const FramebufferAttachment *colorReadAttachment = sourceFramebuffer->getReadColorbuffer();
Corentin Wallez4596a762016-12-20 14:50:18 -0500320
321 GLsizei readAttachmentSamples = 0;
322 if (colorReadAttachment != nullptr)
323 {
324 readAttachmentSamples = colorReadAttachment->getSamples();
325 }
Corentin Wallez6898b352016-11-10 11:41:15 -0500326
Corentin Wallez26a717b2016-09-27 08:45:42 -0700327 bool needManualColorBlit = false;
328
Corentin Wallez6898b352016-11-10 11:41:15 -0500329 // TODO(cwallez) when the filter is LINEAR and both source and destination are SRGB, we
330 // could avoid doing a manual blit.
331
332 // Prior to OpenGL 4.4 BlitFramebuffer (section 18.3.1 of GL 4.3 core profile) reads:
333 // When values are taken from the read buffer, no linearization is performed, even
334 // if the format of the buffer is SRGB.
335 // Starting from OpenGL 4.4 (section 18.3.1) it reads:
336 // When values are taken from the read buffer, if FRAMEBUFFER_SRGB is enabled and the
337 // value of FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING for the framebuffer attachment
338 // corresponding to the read buffer is SRGB, the red, green, and blue components are
339 // converted from the non-linear sRGB color space according [...].
Corentin Wallez26a717b2016-09-27 08:45:42 -0700340 {
Jamie Madill231c7f52017-04-26 13:45:37 -0400341 bool sourceSRGB =
342 colorReadAttachment != nullptr && colorReadAttachment->getColorEncoding() == GL_SRGB;
Corentin Wallez6898b352016-11-10 11:41:15 -0500343 needManualColorBlit =
344 needManualColorBlit || (sourceSRGB && mFunctions->isAtMostGL(gl::Version(4, 3)));
345 }
Corentin Wallez26a717b2016-09-27 08:45:42 -0700346
Corentin Wallez6898b352016-11-10 11:41:15 -0500347 // Prior to OpenGL 4.2 BlitFramebuffer (section 4.3.2 of GL 4.1 core profile) reads:
348 // Blit operations bypass the fragment pipeline. The only fragment operations which
349 // affect a blit are the pixel ownership test and scissor test.
350 // Starting from OpenGL 4.2 (section 4.3.2) it reads:
351 // When values are written to the draw buffers, blit operations bypass the fragment
352 // pipeline. The only fragment operations which affect a blit are the pixel ownership
353 // test, the scissor test and sRGB conversion.
354 if (!needManualColorBlit)
355 {
356 bool destSRGB = false;
357 for (size_t i = 0; i < destFramebuffer->getDrawbufferStateCount(); ++i)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700358 {
Corentin Wallez6898b352016-11-10 11:41:15 -0500359 const FramebufferAttachment *attachment = destFramebuffer->getDrawBuffer(i);
360 if (attachment && attachment->getColorEncoding() == GL_SRGB)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700361 {
Corentin Wallez6898b352016-11-10 11:41:15 -0500362 destSRGB = true;
363 break;
Corentin Wallez26a717b2016-09-27 08:45:42 -0700364 }
Corentin Wallez26a717b2016-09-27 08:45:42 -0700365 }
Corentin Wallez6898b352016-11-10 11:41:15 -0500366
367 needManualColorBlit =
368 needManualColorBlit || (destSRGB && mFunctions->isAtMostGL(gl::Version(4, 1)));
Corentin Wallez26a717b2016-09-27 08:45:42 -0700369 }
370
371 // Enable FRAMEBUFFER_SRGB if needed
Frank Henigman308d7452017-02-15 22:51:21 -0500372 mStateManager->setFramebufferSRGBEnabledForFramebuffer(context->getContextState(), true, this);
Corentin Wallez26a717b2016-09-27 08:45:42 -0700373
374 GLenum blitMask = mask;
Corentin Wallez6898b352016-11-10 11:41:15 -0500375 if (needManualColorBlit && (mask & GL_COLOR_BUFFER_BIT) && readAttachmentSamples <= 1)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700376 {
377 ANGLE_TRY(mBlitter->blitColorBufferWithShader(sourceFramebuffer, destFramebuffer,
378 sourceArea, destArea, filter));
379 blitMask &= ~GL_COLOR_BUFFER_BIT;
380 }
381
382 if (blitMask == 0)
383 {
384 return gl::NoError();
385 }
386
387 const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(sourceFramebuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400388 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
389 mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferID);
390
Jamie Madill2da819e2015-12-03 15:53:19 -0500391 mFunctions->blitFramebuffer(sourceArea.x, sourceArea.y, sourceArea.x1(), sourceArea.y1(),
Corentin Wallez26a717b2016-09-27 08:45:42 -0700392 destArea.x, destArea.y, destArea.x1(), destArea.y1(), blitMask,
393 filter);
Geoff Lang4ad17092015-03-10 16:47:44 -0400394
Corentin Wallez26a717b2016-09-27 08:45:42 -0700395 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500396}
397
JiangYizhoubddc46b2016-12-09 09:50:51 +0800398gl::Error FramebufferGL::getSamplePosition(size_t index, GLfloat *xy) const
399{
400 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
401 mFunctions->getMultisamplefv(GL_SAMPLE_POSITION, static_cast<GLuint>(index), xy);
402 return gl::NoError();
403}
404
Jamie Madillcc86d642015-11-24 13:00:07 -0500405bool FramebufferGL::checkStatus() const
Geoff Langf9a6f082015-01-22 13:32:49 -0500406{
Geoff Lang4ad17092015-03-10 16:47:44 -0400407 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Jamie Madillcc86d642015-11-24 13:00:07 -0500408 GLenum status = mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
409 if (status != GL_FRAMEBUFFER_COMPLETE)
410 {
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500411 WARN() << "GL framebuffer returned incomplete.";
Jamie Madillcc86d642015-11-24 13:00:07 -0500412 }
413 return (status == GL_FRAMEBUFFER_COMPLETE);
Geoff Lang4ad17092015-03-10 16:47:44 -0400414}
415
Jamie Madillc564c072017-06-01 12:45:42 -0400416void FramebufferGL::syncState(const gl::Context *context, const Framebuffer::DirtyBits &dirtyBits)
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500417{
418 // Don't need to sync state for the default FBO.
419 if (mIsDefault)
420 {
421 return;
422 }
423
424 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
425
Jamie Madill6de51852017-04-12 09:53:01 -0400426 for (auto dirtyBit : dirtyBits)
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500427 {
428 switch (dirtyBit)
429 {
430 case Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
431 BindFramebufferAttachment(mFunctions, GL_DEPTH_ATTACHMENT,
Jamie Madill48ef11b2016-04-27 15:21:52 -0400432 mState.getDepthAttachment());
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500433 break;
434 case Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
435 BindFramebufferAttachment(mFunctions, GL_STENCIL_ATTACHMENT,
Jamie Madill48ef11b2016-04-27 15:21:52 -0400436 mState.getStencilAttachment());
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500437 break;
438 case Framebuffer::DIRTY_BIT_DRAW_BUFFERS:
439 {
Jamie Madill48ef11b2016-04-27 15:21:52 -0400440 const auto &drawBuffers = mState.getDrawBufferStates();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500441 mFunctions->drawBuffers(static_cast<GLsizei>(drawBuffers.size()),
442 drawBuffers.data());
Corentin Walleze7557742017-06-01 13:09:57 -0400443 mAppliedEnabledDrawBuffers = mState.getEnabledDrawBuffers();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500444 break;
445 }
446 case Framebuffer::DIRTY_BIT_READ_BUFFER:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400447 mFunctions->readBuffer(mState.getReadBufferState());
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500448 break;
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800449 case Framebuffer::DIRTY_BIT_DEFAULT_WIDTH:
450 mFunctions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH,
451 mState.getDefaultWidth());
452 break;
453 case Framebuffer::DIRTY_BIT_DEFAULT_HEIGHT:
454 mFunctions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT,
455 mState.getDefaultHeight());
456 break;
457 case Framebuffer::DIRTY_BIT_DEFAULT_SAMPLES:
458 mFunctions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_SAMPLES,
459 mState.getDefaultSamples());
460 break;
461 case Framebuffer::DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS:
462 mFunctions->framebufferParameteri(GL_FRAMEBUFFER,
463 GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS,
464 mState.getDefaultFixedSampleLocations());
465 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500466 default:
467 {
468 ASSERT(Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0 &&
469 dirtyBit < Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX);
470 size_t index =
471 static_cast<size_t>(dirtyBit - Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
472 BindFramebufferAttachment(mFunctions,
473 static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + index),
Jamie Madill48ef11b2016-04-27 15:21:52 -0400474 mState.getColorAttachment(index));
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500475 break;
476 }
477 }
478 }
479}
480
Geoff Lang4ad17092015-03-10 16:47:44 -0400481GLuint FramebufferGL::getFramebufferID() const
482{
483 return mFramebufferID;
Geoff Langf9a6f082015-01-22 13:32:49 -0500484}
485
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700486bool FramebufferGL::isDefault() const
Geoff Langafd7f0a2015-09-09 15:33:31 -0400487{
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700488 return mIsDefault;
Geoff Langafd7f0a2015-09-09 15:33:31 -0400489}
490
Corentin Walleze7557742017-06-01 13:09:57 -0400491void FramebufferGL::maskOutInactiveOutputDrawBuffers(DrawBufferMask maxSet)
492{
493 auto targetAppliedDrawBuffers = mState.getEnabledDrawBuffers() & maxSet;
494 if (mAppliedEnabledDrawBuffers != targetAppliedDrawBuffers)
495 {
496 mAppliedEnabledDrawBuffers = targetAppliedDrawBuffers;
497
498 const auto &stateDrawBuffers = mState.getDrawBufferStates();
499 GLsizei drawBufferCount = static_cast<GLsizei>(stateDrawBuffers.size());
500 ASSERT(drawBufferCount <= IMPLEMENTATION_MAX_DRAW_BUFFERS);
501
502 GLenum drawBuffers[IMPLEMENTATION_MAX_DRAW_BUFFERS];
503 for (GLenum i = 0; static_cast<int>(i) < drawBufferCount; ++i)
504 {
505 drawBuffers[i] = targetAppliedDrawBuffers[i] ? stateDrawBuffers[i] : GL_NONE;
506 }
507
508 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
509 mFunctions->drawBuffers(drawBufferCount, drawBuffers);
510 }
511}
512
Jamie Madillc564c072017-06-01 12:45:42 -0400513void FramebufferGL::syncClearState(const gl::Context *context, GLbitfield mask)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400514{
Frank Henigmana3d333c2016-03-22 22:09:14 -0400515 if (mFunctions->standard == STANDARD_GL_DESKTOP)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400516 {
Frank Henigmana3d333c2016-03-22 22:09:14 -0400517 if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments &&
518 (mask & GL_COLOR_BUFFER_BIT) != 0 && !mIsDefault)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400519 {
Corentin Wallez26a717b2016-09-27 08:45:42 -0700520 bool hasSRGBAttachment = false;
Jamie Madill48ef11b2016-04-27 15:21:52 -0400521 for (const auto &attachment : mState.getColorAttachments())
Geoff Langafd7f0a2015-09-09 15:33:31 -0400522 {
Frank Henigmana3d333c2016-03-22 22:09:14 -0400523 if (attachment.isAttached() && attachment.getColorEncoding() == GL_SRGB)
524 {
Corentin Wallez26a717b2016-09-27 08:45:42 -0700525 hasSRGBAttachment = true;
Frank Henigmana3d333c2016-03-22 22:09:14 -0400526 break;
527 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400528 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400529
Frank Henigman308d7452017-02-15 22:51:21 -0500530 mStateManager->setFramebufferSRGBEnabled(context->getContextState(), hasSRGBAttachment);
Frank Henigmana3d333c2016-03-22 22:09:14 -0400531 }
532 else
533 {
Frank Henigman308d7452017-02-15 22:51:21 -0500534 mStateManager->setFramebufferSRGBEnabled(context->getContextState(), !mIsDefault);
Frank Henigmana3d333c2016-03-22 22:09:14 -0400535 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400536 }
537}
538
Jamie Madillc564c072017-06-01 12:45:42 -0400539void FramebufferGL::syncClearBufferState(const gl::Context *context,
540 GLenum buffer,
541 GLint drawBuffer)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400542{
543 if (mFunctions->standard == STANDARD_GL_DESKTOP)
544 {
545 if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments && buffer == GL_COLOR &&
546 !mIsDefault)
547 {
548 // If doing a clear on a color buffer, set SRGB blend enabled only if the color buffer
549 // is an SRGB format.
Jamie Madill48ef11b2016-04-27 15:21:52 -0400550 const auto &drawbufferState = mState.getDrawBufferStates();
551 const auto &colorAttachments = mState.getColorAttachments();
Geoff Langafd7f0a2015-09-09 15:33:31 -0400552
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500553 const FramebufferAttachment *attachment = nullptr;
Geoff Langafd7f0a2015-09-09 15:33:31 -0400554 if (drawbufferState[drawBuffer] >= GL_COLOR_ATTACHMENT0 &&
555 drawbufferState[drawBuffer] < GL_COLOR_ATTACHMENT0 + colorAttachments.size())
556 {
557 size_t attachmentIdx =
558 static_cast<size_t>(drawbufferState[drawBuffer] - GL_COLOR_ATTACHMENT0);
559 attachment = &colorAttachments[attachmentIdx];
560 }
561
562 if (attachment != nullptr)
563 {
Frank Henigman308d7452017-02-15 22:51:21 -0500564 mStateManager->setFramebufferSRGBEnabled(context->getContextState(),
565 attachment->getColorEncoding() == GL_SRGB);
Geoff Langafd7f0a2015-09-09 15:33:31 -0400566 }
567 }
568 else
569 {
Frank Henigman308d7452017-02-15 22:51:21 -0500570 mStateManager->setFramebufferSRGBEnabled(context->getContextState(), !mIsDefault);
Geoff Langafd7f0a2015-09-09 15:33:31 -0400571 }
572 }
573}
Geoff Lang005a7012017-03-27 13:17:34 -0400574
575bool FramebufferGL::modifyInvalidateAttachmentsForEmulatedDefaultFBO(
576 size_t count,
577 const GLenum *attachments,
578 std::vector<GLenum> *modifiedAttachments) const
579{
580 bool needsModification = mIsDefault && mFramebufferID != 0;
581 if (!needsModification)
582 {
583 return false;
584 }
585
586 modifiedAttachments->resize(count);
587 for (size_t i = 0; i < count; i++)
588 {
589 switch (attachments[i])
590 {
591 case GL_COLOR:
592 (*modifiedAttachments)[i] = GL_COLOR_ATTACHMENT0;
593 break;
594
595 case GL_DEPTH:
596 (*modifiedAttachments)[i] = GL_DEPTH_ATTACHMENT;
597 break;
598
599 case GL_STENCIL:
600 (*modifiedAttachments)[i] = GL_STENCIL_ATTACHMENT;
601 break;
602
603 default:
604 UNREACHABLE();
605 break;
606 }
607 }
608
609 return true;
610}
611
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400612gl::Error FramebufferGL::readPixelsRowByRowWorkaround(const gl::Rectangle &area,
613 GLenum format,
614 GLenum type,
615 const gl::PixelPackState &pack,
Jamie Madill876429b2017-04-20 15:46:24 -0400616 void *pixels) const
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400617{
618 intptr_t offset = reinterpret_cast<intptr_t>(pixels);
619
Geoff Langca271392017-04-05 12:30:00 -0400620 const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(format, type);
Jamie Madill231c7f52017-04-26 13:45:37 -0400621 GLuint rowBytes = 0;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400622 ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
623 rowBytes);
624 GLuint skipBytes = 0;
Corentin Wallez886de362016-09-27 10:49:35 -0400625 ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400626
627 gl::PixelPackState directPack;
628 directPack.pixelBuffer = pack.pixelBuffer;
629 directPack.alignment = 1;
630 mStateManager->setPixelPackState(directPack);
631 directPack.pixelBuffer.set(nullptr);
632
633 offset += skipBytes;
634 for (GLint row = 0; row < area.height; ++row)
635 {
636 mFunctions->readPixels(area.x, row + area.y, area.width, 1, format, type,
Jamie Madill876429b2017-04-20 15:46:24 -0400637 reinterpret_cast<void *>(offset));
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400638 offset += row * rowBytes;
639 }
640
641 return gl::NoError();
642}
643
644gl::Error FramebufferGL::readPixelsPaddingWorkaround(const gl::Rectangle &area,
645 GLenum format,
646 GLenum type,
647 const gl::PixelPackState &pack,
Jamie Madill876429b2017-04-20 15:46:24 -0400648 void *pixels) const
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400649{
Geoff Langca271392017-04-05 12:30:00 -0400650 const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(format, type);
Jamie Madill231c7f52017-04-26 13:45:37 -0400651 GLuint rowBytes = 0;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400652 ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
653 rowBytes);
654 GLuint skipBytes = 0;
Corentin Wallez886de362016-09-27 10:49:35 -0400655 ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400656
657 // Get all by the last row
658 if (area.height > 1)
659 {
660 mFunctions->readPixels(area.x, area.y, area.width, area.height - 1, format, type, pixels);
661 }
662
663 // Get the last row manually
664 gl::PixelPackState directPack;
665 directPack.pixelBuffer = pack.pixelBuffer;
666 directPack.alignment = 1;
667 mStateManager->setPixelPackState(directPack);
668 directPack.pixelBuffer.set(nullptr);
669
670 intptr_t lastRowOffset =
671 reinterpret_cast<intptr_t>(pixels) + skipBytes + (area.height - 1) * rowBytes;
672 mFunctions->readPixels(area.x, area.y + area.height - 1, area.width, 1, format, type,
Jamie Madill876429b2017-04-20 15:46:24 -0400673 reinterpret_cast<void *>(lastRowOffset));
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400674
675 return gl::NoError();
676}
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500677} // namespace rx