blob: cd22e88528c6e8c0db98db9bab5ccbd0eb199e9f [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"
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
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 {
97 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, attachment->cubeMapFace(),
98 textureGL->getTextureID(), attachment->mipLevel());
99 }
100 else if (texture->getTarget() == GL_TEXTURE_2D_ARRAY || texture->getTarget() == GL_TEXTURE_3D)
101 {
102 functions->framebufferTextureLayer(GL_FRAMEBUFFER, attachmentPoint, textureGL->getTextureID(),
103 attachment->mipLevel(), attachment->layer());
104 }
105 else
106 {
107 UNREACHABLE();
108 }
109 }
110 else if (attachment->type() == GL_RENDERBUFFER)
111 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500112 const Renderbuffer *renderbuffer = attachment->getRenderbuffer();
Geoff Langcd69f1c2015-03-18 14:33:23 -0400113 const RenderbufferGL *renderbufferGL = GetImplAs<RenderbufferGL>(renderbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400114
Geoff Langcd69f1c2015-03-18 14:33:23 -0400115 functions->framebufferRenderbuffer(GL_FRAMEBUFFER, attachmentPoint, GL_RENDERBUFFER,
116 renderbufferGL->getRenderbufferID());
Geoff Lang4ad17092015-03-10 16:47:44 -0400117 }
118 else
119 {
120 UNREACHABLE();
121 }
122 }
123 else
124 {
125 // Unbind this attachment
126 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_2D, 0, 0);
127 }
128}
Geoff Langf9a6f082015-01-22 13:32:49 -0500129
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500130Error FramebufferGL::discard(size_t count, const GLenum *attachments)
Austin Kinross08332632015-05-05 13:35:47 -0700131{
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500132 // glInvalidateFramebuffer accepts the same enums as glDiscardFramebufferEXT
133 return invalidate(count, attachments);
Austin Kinross08332632015-05-05 13:35:47 -0700134}
135
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500136Error FramebufferGL::invalidate(size_t count, const GLenum *attachments)
Geoff Langf9a6f082015-01-22 13:32:49 -0500137{
Geoff Lang005a7012017-03-27 13:17:34 -0400138 const GLenum *finalAttachmentsPtr = attachments;
139
140 std::vector<GLenum> modifiedAttachments;
141 if (modifyInvalidateAttachmentsForEmulatedDefaultFBO(count, attachments, &modifiedAttachments))
142 {
143 finalAttachmentsPtr = modifiedAttachments.data();
144 }
145
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500146 // Since this function is just a hint, only call a native function if it exists.
Geoff Lang64a72442015-04-01 14:43:11 -0400147 if (mFunctions->invalidateFramebuffer)
148 {
149 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Geoff Lang005a7012017-03-27 13:17:34 -0400150 mFunctions->invalidateFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
151 finalAttachmentsPtr);
Geoff Lang64a72442015-04-01 14:43:11 -0400152 }
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500153 else if (mFunctions->discardFramebuffer)
154 {
155 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Geoff Lang005a7012017-03-27 13:17:34 -0400156 mFunctions->discardFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
157 finalAttachmentsPtr);
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500158 }
Geoff Lang64a72442015-04-01 14:43:11 -0400159
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500160 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500161}
162
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500163Error FramebufferGL::invalidateSub(size_t count,
164 const GLenum *attachments,
165 const gl::Rectangle &area)
Geoff Langf9a6f082015-01-22 13:32:49 -0500166{
Geoff Lang005a7012017-03-27 13:17:34 -0400167
168 const GLenum *finalAttachmentsPtr = attachments;
169
170 std::vector<GLenum> modifiedAttachments;
171 if (modifyInvalidateAttachmentsForEmulatedDefaultFBO(count, attachments, &modifiedAttachments))
172 {
173 finalAttachmentsPtr = modifiedAttachments.data();
174 }
175
Geoff Lang64a72442015-04-01 14:43:11 -0400176 // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is available.
177 if (mFunctions->invalidateSubFramebuffer)
178 {
179 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700180 mFunctions->invalidateSubFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
Geoff Lang005a7012017-03-27 13:17:34 -0400181 finalAttachmentsPtr, area.x, area.y, area.width,
182 area.height);
Geoff Lang64a72442015-04-01 14:43:11 -0400183 }
184
He Yunchaoacd18982017-01-04 10:46:42 +0800185 return NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500186}
187
Jamie Madill8415b5f2016-04-26 13:41:39 -0400188Error FramebufferGL::clear(ContextImpl *context, GLbitfield mask)
Geoff Langf9a6f082015-01-22 13:32:49 -0500189{
Frank Henigman308d7452017-02-15 22:51:21 -0500190 syncClearState(context, mask);
Geoff Lang4ad17092015-03-10 16:47:44 -0400191 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
192 mFunctions->clear(mask);
193
He Yunchaoacd18982017-01-04 10:46:42 +0800194 return NoError();
Geoff Lang4ad17092015-03-10 16:47:44 -0400195}
196
Jamie Madill8415b5f2016-04-26 13:41:39 -0400197Error FramebufferGL::clearBufferfv(ContextImpl *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500198 GLenum buffer,
199 GLint drawbuffer,
200 const GLfloat *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500201{
Frank Henigman308d7452017-02-15 22:51:21 -0500202 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400203 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
204 mFunctions->clearBufferfv(buffer, drawbuffer, values);
205
He Yunchaoacd18982017-01-04 10:46:42 +0800206 return NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500207}
208
Jamie Madill8415b5f2016-04-26 13:41:39 -0400209Error FramebufferGL::clearBufferuiv(ContextImpl *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500210 GLenum buffer,
211 GLint drawbuffer,
212 const GLuint *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500213{
Frank Henigman308d7452017-02-15 22:51:21 -0500214 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400215 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
216 mFunctions->clearBufferuiv(buffer, drawbuffer, values);
217
He Yunchaoacd18982017-01-04 10:46:42 +0800218 return NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500219}
220
Jamie Madill8415b5f2016-04-26 13:41:39 -0400221Error FramebufferGL::clearBufferiv(ContextImpl *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500222 GLenum buffer,
223 GLint drawbuffer,
224 const GLint *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500225{
Frank Henigman308d7452017-02-15 22:51:21 -0500226 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400227 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
228 mFunctions->clearBufferiv(buffer, drawbuffer, values);
229
He Yunchaoacd18982017-01-04 10:46:42 +0800230 return NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500231}
232
Jamie Madill8415b5f2016-04-26 13:41:39 -0400233Error FramebufferGL::clearBufferfi(ContextImpl *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500234 GLenum buffer,
235 GLint drawbuffer,
236 GLfloat depth,
237 GLint stencil)
Geoff Langf9a6f082015-01-22 13:32:49 -0500238{
Frank Henigman308d7452017-02-15 22:51:21 -0500239 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400240 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
241 mFunctions->clearBufferfi(buffer, drawbuffer, depth, stencil);
242
He Yunchaoacd18982017-01-04 10:46:42 +0800243 return NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500244}
245
246GLenum FramebufferGL::getImplementationColorReadFormat() const
247{
Jamie Madilla3944d42016-07-22 22:13:26 -0400248 const auto *readAttachment = mState.getReadAttachment();
249 const Format &format = readAttachment->getFormat();
Geoff Langf607c602016-09-21 11:46:48 -0400250 return format.info->getReadPixelsFormat();
Geoff Langf9a6f082015-01-22 13:32:49 -0500251}
252
253GLenum FramebufferGL::getImplementationColorReadType() const
254{
Jamie Madilla3944d42016-07-22 22:13:26 -0400255 const auto *readAttachment = mState.getReadAttachment();
256 const Format &format = readAttachment->getFormat();
Geoff Langf607c602016-09-21 11:46:48 -0400257 return format.info->getReadPixelsType();
Geoff Langf9a6f082015-01-22 13:32:49 -0500258}
259
Jamie Madill8415b5f2016-04-26 13:41:39 -0400260Error FramebufferGL::readPixels(ContextImpl *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500261 const gl::Rectangle &area,
262 GLenum format,
263 GLenum type,
Jamie Madill876429b2017-04-20 15:46:24 -0400264 void *pixels) const
Geoff Langf9a6f082015-01-22 13:32:49 -0500265{
Geoff Langda34d002015-09-04 11:08:59 -0400266 // TODO: don't sync the pixel pack state here once the dirty bits contain the pixel pack buffer
267 // binding
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700268 const PixelPackState &packState = context->getGLState().getPackState();
Geoff Langda34d002015-09-04 11:08:59 -0400269 mStateManager->setPixelPackState(packState);
Jamie Madill87de3622015-03-16 10:41:44 -0400270
Geoff Langf607c602016-09-21 11:46:48 -0400271 nativegl::ReadPixelsFormat readPixelsFormat =
272 nativegl::GetReadPixelsFormat(mFunctions, mWorkarounds, format, type);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400273 GLenum readFormat = readPixelsFormat.format;
274 GLenum readType = readPixelsFormat.type;
Geoff Lang4ad17092015-03-10 16:47:44 -0400275
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400276 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, mFramebufferID);
277
278 if (mWorkarounds.packOverlappingRowsSeparatelyPackBuffer && packState.pixelBuffer.get() &&
279 packState.rowLength != 0 && packState.rowLength < area.width)
280 {
281 return readPixelsRowByRowWorkaround(area, readFormat, readType, packState, pixels);
282 }
283
284 if (mWorkarounds.packLastRowSeparatelyForPaddingInclusion)
285 {
Corentin Wallez886de362016-09-27 10:49:35 -0400286 gl::Extents size(area.width, area.height, 1);
287
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400288 bool apply;
Corentin Wallez886de362016-09-27 10:49:35 -0400289 ANGLE_TRY_RESULT(ShouldApplyLastRowPaddingWorkaround(size, packState, readFormat, readType,
290 false, pixels),
291 apply);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400292
293 if (apply)
294 {
295 return readPixelsPaddingWorkaround(area, readFormat, readType, packState, pixels);
296 }
297 }
298
299 mFunctions->readPixels(area.x, area.y, area.width, area.height, readFormat, readType, pixels);
300
301 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500302}
303
Jamie Madill8415b5f2016-04-26 13:41:39 -0400304Error FramebufferGL::blit(ContextImpl *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500305 const gl::Rectangle &sourceArea,
306 const gl::Rectangle &destArea,
307 GLbitfield mask,
Jamie Madill8415b5f2016-04-26 13:41:39 -0400308 GLenum filter)
Geoff Langf9a6f082015-01-22 13:32:49 -0500309{
Jamie Madilldfde6ab2016-06-09 07:07:18 -0700310 const Framebuffer *sourceFramebuffer = context->getGLState().getReadFramebuffer();
Corentin Wallez26a717b2016-09-27 08:45:42 -0700311 const Framebuffer *destFramebuffer = context->getGLState().getDrawFramebuffer();
Geoff Lang4ad17092015-03-10 16:47:44 -0400312
Corentin Wallez6898b352016-11-10 11:41:15 -0500313 const FramebufferAttachment *colorReadAttachment = sourceFramebuffer->getReadColorbuffer();
Corentin Wallez4596a762016-12-20 14:50:18 -0500314
315 GLsizei readAttachmentSamples = 0;
316 if (colorReadAttachment != nullptr)
317 {
318 readAttachmentSamples = colorReadAttachment->getSamples();
319 }
Corentin Wallez6898b352016-11-10 11:41:15 -0500320
Corentin Wallez26a717b2016-09-27 08:45:42 -0700321 bool needManualColorBlit = false;
322
Corentin Wallez6898b352016-11-10 11:41:15 -0500323 // TODO(cwallez) when the filter is LINEAR and both source and destination are SRGB, we
324 // could avoid doing a manual blit.
325
326 // Prior to OpenGL 4.4 BlitFramebuffer (section 18.3.1 of GL 4.3 core profile) reads:
327 // When values are taken from the read buffer, no linearization is performed, even
328 // if the format of the buffer is SRGB.
329 // Starting from OpenGL 4.4 (section 18.3.1) it reads:
330 // When values are taken from the read buffer, if FRAMEBUFFER_SRGB is enabled and the
331 // value of FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING for the framebuffer attachment
332 // corresponding to the read buffer is SRGB, the red, green, and blue components are
333 // converted from the non-linear sRGB color space according [...].
Corentin Wallez26a717b2016-09-27 08:45:42 -0700334 {
Corentin Wallez6898b352016-11-10 11:41:15 -0500335 bool sourceSRGB = colorReadAttachment != nullptr &&
336 colorReadAttachment->getColorEncoding() == GL_SRGB;
337 needManualColorBlit =
338 needManualColorBlit || (sourceSRGB && mFunctions->isAtMostGL(gl::Version(4, 3)));
339 }
Corentin Wallez26a717b2016-09-27 08:45:42 -0700340
Corentin Wallez6898b352016-11-10 11:41:15 -0500341 // Prior to OpenGL 4.2 BlitFramebuffer (section 4.3.2 of GL 4.1 core profile) reads:
342 // Blit operations bypass the fragment pipeline. The only fragment operations which
343 // affect a blit are the pixel ownership test and scissor test.
344 // Starting from OpenGL 4.2 (section 4.3.2) it reads:
345 // When values are written to the draw buffers, blit operations bypass the fragment
346 // pipeline. The only fragment operations which affect a blit are the pixel ownership
347 // test, the scissor test and sRGB conversion.
348 if (!needManualColorBlit)
349 {
350 bool destSRGB = false;
351 for (size_t i = 0; i < destFramebuffer->getDrawbufferStateCount(); ++i)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700352 {
Corentin Wallez6898b352016-11-10 11:41:15 -0500353 const FramebufferAttachment *attachment = destFramebuffer->getDrawBuffer(i);
354 if (attachment && attachment->getColorEncoding() == GL_SRGB)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700355 {
Corentin Wallez6898b352016-11-10 11:41:15 -0500356 destSRGB = true;
357 break;
Corentin Wallez26a717b2016-09-27 08:45:42 -0700358 }
Corentin Wallez26a717b2016-09-27 08:45:42 -0700359 }
Corentin Wallez6898b352016-11-10 11:41:15 -0500360
361 needManualColorBlit =
362 needManualColorBlit || (destSRGB && mFunctions->isAtMostGL(gl::Version(4, 1)));
Corentin Wallez26a717b2016-09-27 08:45:42 -0700363 }
364
365 // Enable FRAMEBUFFER_SRGB if needed
Frank Henigman308d7452017-02-15 22:51:21 -0500366 mStateManager->setFramebufferSRGBEnabledForFramebuffer(context->getContextState(), true, this);
Corentin Wallez26a717b2016-09-27 08:45:42 -0700367
368 GLenum blitMask = mask;
Corentin Wallez6898b352016-11-10 11:41:15 -0500369 if (needManualColorBlit && (mask & GL_COLOR_BUFFER_BIT) && readAttachmentSamples <= 1)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700370 {
371 ANGLE_TRY(mBlitter->blitColorBufferWithShader(sourceFramebuffer, destFramebuffer,
372 sourceArea, destArea, filter));
373 blitMask &= ~GL_COLOR_BUFFER_BIT;
374 }
375
376 if (blitMask == 0)
377 {
378 return gl::NoError();
379 }
380
381 const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(sourceFramebuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400382 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
383 mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferID);
384
Jamie Madill2da819e2015-12-03 15:53:19 -0500385 mFunctions->blitFramebuffer(sourceArea.x, sourceArea.y, sourceArea.x1(), sourceArea.y1(),
Corentin Wallez26a717b2016-09-27 08:45:42 -0700386 destArea.x, destArea.y, destArea.x1(), destArea.y1(), blitMask,
387 filter);
Geoff Lang4ad17092015-03-10 16:47:44 -0400388
Corentin Wallez26a717b2016-09-27 08:45:42 -0700389 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500390}
391
JiangYizhoubddc46b2016-12-09 09:50:51 +0800392gl::Error FramebufferGL::getSamplePosition(size_t index, GLfloat *xy) const
393{
394 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
395 mFunctions->getMultisamplefv(GL_SAMPLE_POSITION, static_cast<GLuint>(index), xy);
396 return gl::NoError();
397}
398
Jamie Madillcc86d642015-11-24 13:00:07 -0500399bool FramebufferGL::checkStatus() const
Geoff Langf9a6f082015-01-22 13:32:49 -0500400{
Geoff Lang4ad17092015-03-10 16:47:44 -0400401 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Jamie Madillcc86d642015-11-24 13:00:07 -0500402 GLenum status = mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
403 if (status != GL_FRAMEBUFFER_COMPLETE)
404 {
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500405 WARN() << "GL framebuffer returned incomplete.";
Jamie Madillcc86d642015-11-24 13:00:07 -0500406 }
407 return (status == GL_FRAMEBUFFER_COMPLETE);
Geoff Lang4ad17092015-03-10 16:47:44 -0400408}
409
Jamie Madilldd43e6c2017-03-24 14:18:49 -0400410void FramebufferGL::syncState(ContextImpl *contextImpl, const Framebuffer::DirtyBits &dirtyBits)
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500411{
412 // Don't need to sync state for the default FBO.
413 if (mIsDefault)
414 {
415 return;
416 }
417
418 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
419
Jamie Madill6de51852017-04-12 09:53:01 -0400420 for (auto dirtyBit : dirtyBits)
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500421 {
422 switch (dirtyBit)
423 {
424 case Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
425 BindFramebufferAttachment(mFunctions, GL_DEPTH_ATTACHMENT,
Jamie Madill48ef11b2016-04-27 15:21:52 -0400426 mState.getDepthAttachment());
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500427 break;
428 case Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
429 BindFramebufferAttachment(mFunctions, GL_STENCIL_ATTACHMENT,
Jamie Madill48ef11b2016-04-27 15:21:52 -0400430 mState.getStencilAttachment());
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500431 break;
432 case Framebuffer::DIRTY_BIT_DRAW_BUFFERS:
433 {
Jamie Madill48ef11b2016-04-27 15:21:52 -0400434 const auto &drawBuffers = mState.getDrawBufferStates();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500435 mFunctions->drawBuffers(static_cast<GLsizei>(drawBuffers.size()),
436 drawBuffers.data());
437 break;
438 }
439 case Framebuffer::DIRTY_BIT_READ_BUFFER:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400440 mFunctions->readBuffer(mState.getReadBufferState());
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500441 break;
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800442 case Framebuffer::DIRTY_BIT_DEFAULT_WIDTH:
443 mFunctions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH,
444 mState.getDefaultWidth());
445 break;
446 case Framebuffer::DIRTY_BIT_DEFAULT_HEIGHT:
447 mFunctions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT,
448 mState.getDefaultHeight());
449 break;
450 case Framebuffer::DIRTY_BIT_DEFAULT_SAMPLES:
451 mFunctions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_SAMPLES,
452 mState.getDefaultSamples());
453 break;
454 case Framebuffer::DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS:
455 mFunctions->framebufferParameteri(GL_FRAMEBUFFER,
456 GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS,
457 mState.getDefaultFixedSampleLocations());
458 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500459 default:
460 {
461 ASSERT(Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0 &&
462 dirtyBit < Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX);
463 size_t index =
464 static_cast<size_t>(dirtyBit - Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
465 BindFramebufferAttachment(mFunctions,
466 static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + index),
Jamie Madill48ef11b2016-04-27 15:21:52 -0400467 mState.getColorAttachment(index));
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500468 break;
469 }
470 }
471 }
472}
473
Geoff Lang4ad17092015-03-10 16:47:44 -0400474GLuint FramebufferGL::getFramebufferID() const
475{
476 return mFramebufferID;
Geoff Langf9a6f082015-01-22 13:32:49 -0500477}
478
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700479bool FramebufferGL::isDefault() const
Geoff Langafd7f0a2015-09-09 15:33:31 -0400480{
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700481 return mIsDefault;
Geoff Langafd7f0a2015-09-09 15:33:31 -0400482}
483
Frank Henigman308d7452017-02-15 22:51:21 -0500484void FramebufferGL::syncClearState(ContextImpl *context, GLbitfield mask)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400485{
Frank Henigmana3d333c2016-03-22 22:09:14 -0400486 if (mFunctions->standard == STANDARD_GL_DESKTOP)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400487 {
Frank Henigmana3d333c2016-03-22 22:09:14 -0400488 if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments &&
489 (mask & GL_COLOR_BUFFER_BIT) != 0 && !mIsDefault)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400490 {
Corentin Wallez26a717b2016-09-27 08:45:42 -0700491 bool hasSRGBAttachment = false;
Jamie Madill48ef11b2016-04-27 15:21:52 -0400492 for (const auto &attachment : mState.getColorAttachments())
Geoff Langafd7f0a2015-09-09 15:33:31 -0400493 {
Frank Henigmana3d333c2016-03-22 22:09:14 -0400494 if (attachment.isAttached() && attachment.getColorEncoding() == GL_SRGB)
495 {
Corentin Wallez26a717b2016-09-27 08:45:42 -0700496 hasSRGBAttachment = true;
Frank Henigmana3d333c2016-03-22 22:09:14 -0400497 break;
498 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400499 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400500
Frank Henigman308d7452017-02-15 22:51:21 -0500501 mStateManager->setFramebufferSRGBEnabled(context->getContextState(), hasSRGBAttachment);
Frank Henigmana3d333c2016-03-22 22:09:14 -0400502 }
503 else
504 {
Frank Henigman308d7452017-02-15 22:51:21 -0500505 mStateManager->setFramebufferSRGBEnabled(context->getContextState(), !mIsDefault);
Frank Henigmana3d333c2016-03-22 22:09:14 -0400506 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400507 }
508}
509
Frank Henigman308d7452017-02-15 22:51:21 -0500510void FramebufferGL::syncClearBufferState(ContextImpl *context, GLenum buffer, GLint drawBuffer)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400511{
512 if (mFunctions->standard == STANDARD_GL_DESKTOP)
513 {
514 if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments && buffer == GL_COLOR &&
515 !mIsDefault)
516 {
517 // If doing a clear on a color buffer, set SRGB blend enabled only if the color buffer
518 // is an SRGB format.
Jamie Madill48ef11b2016-04-27 15:21:52 -0400519 const auto &drawbufferState = mState.getDrawBufferStates();
520 const auto &colorAttachments = mState.getColorAttachments();
Geoff Langafd7f0a2015-09-09 15:33:31 -0400521
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500522 const FramebufferAttachment *attachment = nullptr;
Geoff Langafd7f0a2015-09-09 15:33:31 -0400523 if (drawbufferState[drawBuffer] >= GL_COLOR_ATTACHMENT0 &&
524 drawbufferState[drawBuffer] < GL_COLOR_ATTACHMENT0 + colorAttachments.size())
525 {
526 size_t attachmentIdx =
527 static_cast<size_t>(drawbufferState[drawBuffer] - GL_COLOR_ATTACHMENT0);
528 attachment = &colorAttachments[attachmentIdx];
529 }
530
531 if (attachment != nullptr)
532 {
Frank Henigman308d7452017-02-15 22:51:21 -0500533 mStateManager->setFramebufferSRGBEnabled(context->getContextState(),
534 attachment->getColorEncoding() == GL_SRGB);
Geoff Langafd7f0a2015-09-09 15:33:31 -0400535 }
536 }
537 else
538 {
Frank Henigman308d7452017-02-15 22:51:21 -0500539 mStateManager->setFramebufferSRGBEnabled(context->getContextState(), !mIsDefault);
Geoff Langafd7f0a2015-09-09 15:33:31 -0400540 }
541 }
542}
Geoff Lang005a7012017-03-27 13:17:34 -0400543
544bool FramebufferGL::modifyInvalidateAttachmentsForEmulatedDefaultFBO(
545 size_t count,
546 const GLenum *attachments,
547 std::vector<GLenum> *modifiedAttachments) const
548{
549 bool needsModification = mIsDefault && mFramebufferID != 0;
550 if (!needsModification)
551 {
552 return false;
553 }
554
555 modifiedAttachments->resize(count);
556 for (size_t i = 0; i < count; i++)
557 {
558 switch (attachments[i])
559 {
560 case GL_COLOR:
561 (*modifiedAttachments)[i] = GL_COLOR_ATTACHMENT0;
562 break;
563
564 case GL_DEPTH:
565 (*modifiedAttachments)[i] = GL_DEPTH_ATTACHMENT;
566 break;
567
568 case GL_STENCIL:
569 (*modifiedAttachments)[i] = GL_STENCIL_ATTACHMENT;
570 break;
571
572 default:
573 UNREACHABLE();
574 break;
575 }
576 }
577
578 return true;
579}
580
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400581gl::Error FramebufferGL::readPixelsRowByRowWorkaround(const gl::Rectangle &area,
582 GLenum format,
583 GLenum type,
584 const gl::PixelPackState &pack,
Jamie Madill876429b2017-04-20 15:46:24 -0400585 void *pixels) const
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400586{
587 intptr_t offset = reinterpret_cast<intptr_t>(pixels);
588
Geoff Langca271392017-04-05 12:30:00 -0400589 const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(format, type);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400590 GLuint rowBytes = 0;
591 ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
592 rowBytes);
593 GLuint skipBytes = 0;
Corentin Wallez886de362016-09-27 10:49:35 -0400594 ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400595
596 gl::PixelPackState directPack;
597 directPack.pixelBuffer = pack.pixelBuffer;
598 directPack.alignment = 1;
599 mStateManager->setPixelPackState(directPack);
600 directPack.pixelBuffer.set(nullptr);
601
602 offset += skipBytes;
603 for (GLint row = 0; row < area.height; ++row)
604 {
605 mFunctions->readPixels(area.x, row + area.y, area.width, 1, format, type,
Jamie Madill876429b2017-04-20 15:46:24 -0400606 reinterpret_cast<void *>(offset));
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400607 offset += row * rowBytes;
608 }
609
610 return gl::NoError();
611}
612
613gl::Error FramebufferGL::readPixelsPaddingWorkaround(const gl::Rectangle &area,
614 GLenum format,
615 GLenum type,
616 const gl::PixelPackState &pack,
Jamie Madill876429b2017-04-20 15:46:24 -0400617 void *pixels) const
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400618{
Geoff Langca271392017-04-05 12:30:00 -0400619 const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(format, type);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400620 GLuint rowBytes = 0;
621 ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
622 rowBytes);
623 GLuint skipBytes = 0;
Corentin Wallez886de362016-09-27 10:49:35 -0400624 ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400625
626 // Get all by the last row
627 if (area.height > 1)
628 {
629 mFunctions->readPixels(area.x, area.y, area.width, area.height - 1, format, type, pixels);
630 }
631
632 // Get the last row manually
633 gl::PixelPackState directPack;
634 directPack.pixelBuffer = pack.pixelBuffer;
635 directPack.alignment = 1;
636 mStateManager->setPixelPackState(directPack);
637 directPack.pixelBuffer.set(nullptr);
638
639 intptr_t lastRowOffset =
640 reinterpret_cast<intptr_t>(pixels) + skipBytes + (area.height - 1) * rowBytes;
641 mFunctions->readPixels(area.x, area.y + area.height - 1, area.width, 1, format, type,
Jamie Madill876429b2017-04-20 15:46:24 -0400642 reinterpret_cast<void *>(lastRowOffset));
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400643
644 return gl::NoError();
645}
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500646} // namespace rx