blob: 5432e4a499786641692acea312204b3fd9202420 [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"
Geoff Lang92019432017-11-20 13:09:34 -050018#include "libANGLE/queryconversions.h"
Jamie Madill8415b5f2016-04-26 13:41:39 -040019#include "libANGLE/renderer/ContextImpl.h"
Corentin Wallez26a717b2016-09-27 08:45:42 -070020#include "libANGLE/renderer/gl/BlitGL.h"
Martin Radev5e424fa2017-08-09 16:25:36 +030021#include "libANGLE/renderer/gl/ClearMultiviewGL.h"
Frank Henigmanfa36c332017-06-09 18:44:45 -040022#include "libANGLE/renderer/gl/ContextGL.h"
Geoff Lang4ad17092015-03-10 16:47:44 -040023#include "libANGLE/renderer/gl/FunctionsGL.h"
Jacek Cabanfa60f692015-04-27 18:23:44 +020024#include "libANGLE/renderer/gl/RenderbufferGL.h"
Geoff Lang4ad17092015-03-10 16:47:44 -040025#include "libANGLE/renderer/gl/StateManagerGL.h"
26#include "libANGLE/renderer/gl/TextureGL.h"
Geoff Langafd7f0a2015-09-09 15:33:31 -040027#include "libANGLE/renderer/gl/WorkaroundsGL.h"
Geoff Langf607c602016-09-21 11:46:48 -040028#include "libANGLE/renderer/gl/formatutilsgl.h"
Corentin Wallez886de362016-09-27 10:49:35 -040029#include "libANGLE/renderer/gl/renderergl_utils.h"
Jamie Madillcc86d642015-11-24 13:00:07 -050030#include "platform/Platform.h"
Geoff Langf9a6f082015-01-22 13:32:49 -050031
Jamie Madill60ec6ea2016-01-22 15:27:19 -050032using namespace gl;
Corentin Wallez9a8d3662016-09-22 12:18:29 -040033using angle::CheckedNumeric;
Jamie Madill60ec6ea2016-01-22 15:27:19 -050034
Geoff Langf9a6f082015-01-22 13:32:49 -050035namespace rx
36{
37
Martin Radev878c8b12017-07-28 09:51:04 +030038namespace
Geoff Lang4ad17092015-03-10 16:47:44 -040039{
Geoff Langf9a6f082015-01-22 13:32:49 -050040
Martin Radev878c8b12017-07-28 09:51:04 +030041void BindFramebufferAttachment(const FunctionsGL *functions,
42 GLenum attachmentPoint,
43 const FramebufferAttachment *attachment)
Geoff Lang4ad17092015-03-10 16:47:44 -040044{
45 if (attachment)
46 {
47 if (attachment->type() == GL_TEXTURE)
48 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -050049 const Texture *texture = attachment->getTexture();
Geoff Lang4ad17092015-03-10 16:47:44 -040050 const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
51
Corentin Wallez99d492c2018-02-27 15:17:10 -050052 if (texture->getType() == TextureType::_2D ||
53 texture->getType() == TextureType::_2DMultisample ||
54 texture->getType() == TextureType::Rectangle)
Geoff Lang4ad17092015-03-10 16:47:44 -040055 {
JiangYizhoubddc46b2016-12-09 09:50:51 +080056 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint,
Corentin Wallez99d492c2018-02-27 15:17:10 -050057 ToGLenum(texture->getType()),
Geoff Lang4ad17092015-03-10 16:47:44 -040058 textureGL->getTextureID(), attachment->mipLevel());
59 }
Corentin Wallez99d492c2018-02-27 15:17:10 -050060 else if (texture->getType() == TextureType::CubeMap)
61 {
62 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint,
63 ToGLenum(attachment->cubeMapFace()),
64 textureGL->getTextureID(), attachment->mipLevel());
65 }
66 else if (texture->getType() == TextureType::_2DArray ||
67 texture->getType() == TextureType::_3D)
Geoff Lang4ad17092015-03-10 16:47:44 -040068 {
Martin Radev5e424fa2017-08-09 16:25:36 +030069 if (attachment->getMultiviewLayout() == GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE)
70 {
71 ASSERT(functions->framebufferTexture);
72 functions->framebufferTexture(GL_FRAMEBUFFER, attachmentPoint,
73 textureGL->getTextureID(),
74 attachment->mipLevel());
75 }
76 else
77 {
78 functions->framebufferTextureLayer(GL_FRAMEBUFFER, attachmentPoint,
79 textureGL->getTextureID(),
80 attachment->mipLevel(), attachment->layer());
81 }
Geoff Lang4ad17092015-03-10 16:47:44 -040082 }
83 else
84 {
85 UNREACHABLE();
86 }
87 }
88 else if (attachment->type() == GL_RENDERBUFFER)
89 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -050090 const Renderbuffer *renderbuffer = attachment->getRenderbuffer();
Geoff Langcd69f1c2015-03-18 14:33:23 -040091 const RenderbufferGL *renderbufferGL = GetImplAs<RenderbufferGL>(renderbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -040092
Geoff Langcd69f1c2015-03-18 14:33:23 -040093 functions->framebufferRenderbuffer(GL_FRAMEBUFFER, attachmentPoint, GL_RENDERBUFFER,
94 renderbufferGL->getRenderbufferID());
Geoff Lang4ad17092015-03-10 16:47:44 -040095 }
96 else
97 {
98 UNREACHABLE();
99 }
100 }
101 else
102 {
103 // Unbind this attachment
104 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_2D, 0, 0);
105 }
106}
Geoff Langf9a6f082015-01-22 13:32:49 -0500107
Martin Radev61e710b2017-09-05 11:59:52 +0300108bool AreAllLayersActive(const FramebufferAttachment &attachment)
Martin Radevb0761932017-07-25 17:42:25 +0300109{
Martin Radev61e710b2017-09-05 11:59:52 +0300110 int baseViewIndex = attachment.getBaseViewIndex();
111 if (baseViewIndex != 0)
112 {
113 return false;
114 }
115 const ImageIndex &imageIndex = attachment.getTextureImageIndex();
Jamie Madillcc129372018-04-12 09:13:18 -0400116 int numLayers = static_cast<int>(
117 attachment.getTexture()->getDepth(imageIndex.getTarget(), imageIndex.getLevelIndex()));
Martin Radev61e710b2017-09-05 11:59:52 +0300118 return (attachment.getNumViews() == numLayers);
119}
120
121bool RequiresMultiviewClear(const FramebufferState &state, bool scissorTestEnabled)
122{
123 // Get one attachment and check whether all layers are attached.
124 const FramebufferAttachment *attachment = nullptr;
125 bool allTextureArraysAreFullyAttached = true;
126 for (const FramebufferAttachment &colorAttachment : state.getColorAttachments())
127 {
128 if (colorAttachment.isAttached())
129 {
130 if (colorAttachment.getMultiviewLayout() == GL_NONE)
131 {
132 return false;
133 }
134 attachment = &colorAttachment;
135 allTextureArraysAreFullyAttached =
136 allTextureArraysAreFullyAttached && AreAllLayersActive(*attachment);
137 }
138 }
139
140 const FramebufferAttachment *depthAttachment = state.getDepthAttachment();
141 if (depthAttachment)
142 {
143 if (depthAttachment->getMultiviewLayout() == GL_NONE)
144 {
145 return false;
146 }
147 attachment = depthAttachment;
148 allTextureArraysAreFullyAttached =
149 allTextureArraysAreFullyAttached && AreAllLayersActive(*attachment);
150 }
151 const FramebufferAttachment *stencilAttachment = state.getStencilAttachment();
152 if (stencilAttachment)
153 {
154 if (stencilAttachment->getMultiviewLayout() == GL_NONE)
155 {
156 return false;
157 }
158 attachment = stencilAttachment;
159 allTextureArraysAreFullyAttached =
160 allTextureArraysAreFullyAttached && AreAllLayersActive(*attachment);
161 }
162
Martin Radev5e424fa2017-08-09 16:25:36 +0300163 if (attachment == nullptr)
164 {
165 return false;
166 }
167 switch (attachment->getMultiviewLayout())
168 {
169 case GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE:
Martin Radev61e710b2017-09-05 11:59:52 +0300170 // If all layers of each texture array are active, then there is no need to issue a
171 // special multiview clear.
172 return !allTextureArraysAreFullyAttached;
Martin Radev5e424fa2017-08-09 16:25:36 +0300173 case GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE:
174 return (scissorTestEnabled == true);
Martin Radev5e424fa2017-08-09 16:25:36 +0300175 default:
176 UNREACHABLE();
177 }
178 return false;
Martin Radevb0761932017-07-25 17:42:25 +0300179}
180
Martin Radev878c8b12017-07-28 09:51:04 +0300181} // namespace
182
183FramebufferGL::FramebufferGL(const FramebufferState &state,
184 const FunctionsGL *functions,
185 StateManagerGL *stateManager,
186 const WorkaroundsGL &workarounds,
187 BlitGL *blitter,
Martin Radev5e424fa2017-08-09 16:25:36 +0300188 ClearMultiviewGL *multiviewClearer,
Martin Radev878c8b12017-07-28 09:51:04 +0300189 bool isDefault)
190 : FramebufferImpl(state),
191 mFunctions(functions),
192 mStateManager(stateManager),
193 mWorkarounds(workarounds),
194 mBlitter(blitter),
Martin Radev5e424fa2017-08-09 16:25:36 +0300195 mMultiviewClearer(multiviewClearer),
Martin Radev878c8b12017-07-28 09:51:04 +0300196 mFramebufferID(0),
197 mIsDefault(isDefault),
198 mAppliedEnabledDrawBuffers(1)
199{
200 if (!mIsDefault)
201 {
202 mFunctions->genFramebuffers(1, &mFramebufferID);
203 }
204}
205
206FramebufferGL::FramebufferGL(GLuint id,
207 const FramebufferState &state,
208 const FunctionsGL *functions,
209 const WorkaroundsGL &workarounds,
210 BlitGL *blitter,
Martin Radev5e424fa2017-08-09 16:25:36 +0300211 ClearMultiviewGL *multiviewClearer,
Martin Radev878c8b12017-07-28 09:51:04 +0300212 StateManagerGL *stateManager)
213 : FramebufferImpl(state),
214 mFunctions(functions),
215 mStateManager(stateManager),
216 mWorkarounds(workarounds),
217 mBlitter(blitter),
Martin Radev5e424fa2017-08-09 16:25:36 +0300218 mMultiviewClearer(multiviewClearer),
Martin Radev878c8b12017-07-28 09:51:04 +0300219 mFramebufferID(id),
220 mIsDefault(true),
221 mAppliedEnabledDrawBuffers(1)
222{
223}
224
225FramebufferGL::~FramebufferGL()
226{
227 mStateManager->deleteFramebuffer(mFramebufferID);
228 mFramebufferID = 0;
229}
230
Jamie Madill4928b7c2017-06-20 12:57:39 -0400231Error FramebufferGL::discard(const gl::Context *context, size_t count, const GLenum *attachments)
Austin Kinross08332632015-05-05 13:35:47 -0700232{
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500233 // glInvalidateFramebuffer accepts the same enums as glDiscardFramebufferEXT
Jamie Madill4928b7c2017-06-20 12:57:39 -0400234 return invalidate(context, count, attachments);
Austin Kinross08332632015-05-05 13:35:47 -0700235}
236
Jamie Madill4928b7c2017-06-20 12:57:39 -0400237Error FramebufferGL::invalidate(const gl::Context *context, size_t count, const GLenum *attachments)
Geoff Langf9a6f082015-01-22 13:32:49 -0500238{
Geoff Lang005a7012017-03-27 13:17:34 -0400239 const GLenum *finalAttachmentsPtr = attachments;
240
241 std::vector<GLenum> modifiedAttachments;
242 if (modifyInvalidateAttachmentsForEmulatedDefaultFBO(count, attachments, &modifiedAttachments))
243 {
244 finalAttachmentsPtr = modifiedAttachments.data();
245 }
246
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500247 // Since this function is just a hint, only call a native function if it exists.
Geoff Lang64a72442015-04-01 14:43:11 -0400248 if (mFunctions->invalidateFramebuffer)
249 {
250 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Geoff Lang005a7012017-03-27 13:17:34 -0400251 mFunctions->invalidateFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
252 finalAttachmentsPtr);
Geoff Lang64a72442015-04-01 14:43:11 -0400253 }
Jamie Madill29ddcc92017-10-21 16:10:02 -0400254 else if (mFunctions->discardFramebufferEXT)
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500255 {
256 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Jamie Madill29ddcc92017-10-21 16:10:02 -0400257 mFunctions->discardFramebufferEXT(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
258 finalAttachmentsPtr);
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500259 }
Geoff Lang64a72442015-04-01 14:43:11 -0400260
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500261 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500262}
263
Jamie Madill4928b7c2017-06-20 12:57:39 -0400264Error FramebufferGL::invalidateSub(const gl::Context *context,
265 size_t count,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500266 const GLenum *attachments,
267 const gl::Rectangle &area)
Geoff Langf9a6f082015-01-22 13:32:49 -0500268{
Geoff Lang005a7012017-03-27 13:17:34 -0400269
270 const GLenum *finalAttachmentsPtr = attachments;
271
272 std::vector<GLenum> modifiedAttachments;
273 if (modifyInvalidateAttachmentsForEmulatedDefaultFBO(count, attachments, &modifiedAttachments))
274 {
275 finalAttachmentsPtr = modifiedAttachments.data();
276 }
277
Jamie Madill231c7f52017-04-26 13:45:37 -0400278 // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is
279 // available.
Geoff Lang64a72442015-04-01 14:43:11 -0400280 if (mFunctions->invalidateSubFramebuffer)
281 {
282 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700283 mFunctions->invalidateSubFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
Geoff Lang005a7012017-03-27 13:17:34 -0400284 finalAttachmentsPtr, area.x, area.y, area.width,
285 area.height);
Geoff Lang64a72442015-04-01 14:43:11 -0400286 }
287
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500288 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500289}
290
Jamie Madillc564c072017-06-01 12:45:42 -0400291Error FramebufferGL::clear(const gl::Context *context, GLbitfield mask)
Geoff Langf9a6f082015-01-22 13:32:49 -0500292{
Frank Henigman308d7452017-02-15 22:51:21 -0500293 syncClearState(context, mask);
Geoff Lang4ad17092015-03-10 16:47:44 -0400294 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300295
Martin Radev61e710b2017-09-05 11:59:52 +0300296 if (!RequiresMultiviewClear(mState, context->getGLState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300297 {
Martin Radev5e424fa2017-08-09 16:25:36 +0300298 mFunctions->clear(mask);
Martin Radevb0761932017-07-25 17:42:25 +0300299 }
300 else
301 {
Martin Radev5e424fa2017-08-09 16:25:36 +0300302 mMultiviewClearer->clearMultiviewFBO(mState, context->getGLState().getScissor(),
303 ClearMultiviewGL::ClearCommandType::Clear, mask,
304 GL_NONE, 0, nullptr, 0.0f, 0);
Martin Radevb0761932017-07-25 17:42:25 +0300305 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400306
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500307 return gl::NoError();
Geoff Lang4ad17092015-03-10 16:47:44 -0400308}
309
Jamie Madillc564c072017-06-01 12:45:42 -0400310Error FramebufferGL::clearBufferfv(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500311 GLenum buffer,
312 GLint drawbuffer,
313 const GLfloat *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500314{
Frank Henigman308d7452017-02-15 22:51:21 -0500315 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400316 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300317
Martin Radev61e710b2017-09-05 11:59:52 +0300318 if (!RequiresMultiviewClear(mState, context->getGLState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300319 {
Martin Radev5e424fa2017-08-09 16:25:36 +0300320 mFunctions->clearBufferfv(buffer, drawbuffer, values);
Martin Radevb0761932017-07-25 17:42:25 +0300321 }
322 else
323 {
Martin Radev5e424fa2017-08-09 16:25:36 +0300324 mMultiviewClearer->clearMultiviewFBO(mState, context->getGLState().getScissor(),
325 ClearMultiviewGL::ClearCommandType::ClearBufferfv,
326 static_cast<GLbitfield>(0u), buffer, drawbuffer,
327 reinterpret_cast<const uint8_t *>(values), 0.0f, 0);
Martin Radevb0761932017-07-25 17:42:25 +0300328 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400329
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500330 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500331}
332
Jamie Madillc564c072017-06-01 12:45:42 -0400333Error FramebufferGL::clearBufferuiv(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500334 GLenum buffer,
335 GLint drawbuffer,
336 const GLuint *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500337{
Frank Henigman308d7452017-02-15 22:51:21 -0500338 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400339 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300340
Martin Radev61e710b2017-09-05 11:59:52 +0300341 if (!RequiresMultiviewClear(mState, context->getGLState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300342 {
Martin Radev5e424fa2017-08-09 16:25:36 +0300343 mFunctions->clearBufferuiv(buffer, drawbuffer, values);
Martin Radevb0761932017-07-25 17:42:25 +0300344 }
345 else
346 {
Martin Radev5e424fa2017-08-09 16:25:36 +0300347 mMultiviewClearer->clearMultiviewFBO(mState, context->getGLState().getScissor(),
348 ClearMultiviewGL::ClearCommandType::ClearBufferuiv,
349 static_cast<GLbitfield>(0u), buffer, drawbuffer,
350 reinterpret_cast<const uint8_t *>(values), 0.0f, 0);
Martin Radevb0761932017-07-25 17:42:25 +0300351 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400352
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500353 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500354}
355
Jamie Madillc564c072017-06-01 12:45:42 -0400356Error FramebufferGL::clearBufferiv(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500357 GLenum buffer,
358 GLint drawbuffer,
359 const GLint *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500360{
Frank Henigman308d7452017-02-15 22:51:21 -0500361 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400362 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300363
Martin Radev61e710b2017-09-05 11:59:52 +0300364 if (!RequiresMultiviewClear(mState, context->getGLState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300365 {
Martin Radev5e424fa2017-08-09 16:25:36 +0300366 mFunctions->clearBufferiv(buffer, drawbuffer, values);
Martin Radevb0761932017-07-25 17:42:25 +0300367 }
368 else
369 {
Martin Radev5e424fa2017-08-09 16:25:36 +0300370 mMultiviewClearer->clearMultiviewFBO(mState, context->getGLState().getScissor(),
371 ClearMultiviewGL::ClearCommandType::ClearBufferiv,
372 static_cast<GLbitfield>(0u), buffer, drawbuffer,
373 reinterpret_cast<const uint8_t *>(values), 0.0f, 0);
Martin Radevb0761932017-07-25 17:42:25 +0300374 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400375
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500376 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500377}
378
Jamie Madillc564c072017-06-01 12:45:42 -0400379Error FramebufferGL::clearBufferfi(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500380 GLenum buffer,
381 GLint drawbuffer,
382 GLfloat depth,
383 GLint stencil)
Geoff Langf9a6f082015-01-22 13:32:49 -0500384{
Frank Henigman308d7452017-02-15 22:51:21 -0500385 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400386 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300387
Martin Radev61e710b2017-09-05 11:59:52 +0300388 if (!RequiresMultiviewClear(mState, context->getGLState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300389 {
390 mFunctions->clearBufferfi(buffer, drawbuffer, depth, stencil);
391 }
Martin Radev5e424fa2017-08-09 16:25:36 +0300392 else
393 {
394 mMultiviewClearer->clearMultiviewFBO(mState, context->getGLState().getScissor(),
395 ClearMultiviewGL::ClearCommandType::ClearBufferfi,
396 static_cast<GLbitfield>(0u), buffer, drawbuffer,
397 nullptr, depth, stencil);
398 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400399
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500400 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500401}
402
Jamie Madill4928b7c2017-06-20 12:57:39 -0400403GLenum FramebufferGL::getImplementationColorReadFormat(const gl::Context *context) const
Geoff Langf9a6f082015-01-22 13:32:49 -0500404{
Jamie Madilla3944d42016-07-22 22:13:26 -0400405 const auto *readAttachment = mState.getReadAttachment();
406 const Format &format = readAttachment->getFormat();
Geoff Langf607c602016-09-21 11:46:48 -0400407 return format.info->getReadPixelsFormat();
Geoff Langf9a6f082015-01-22 13:32:49 -0500408}
409
Jamie Madill4928b7c2017-06-20 12:57:39 -0400410GLenum FramebufferGL::getImplementationColorReadType(const gl::Context *context) const
Geoff Langf9a6f082015-01-22 13:32:49 -0500411{
Jamie Madilla3944d42016-07-22 22:13:26 -0400412 const auto *readAttachment = mState.getReadAttachment();
413 const Format &format = readAttachment->getFormat();
Geoff Langc71ea662017-09-26 17:06:02 -0400414 return format.info->getReadPixelsType(context->getClientVersion());
Geoff Langf9a6f082015-01-22 13:32:49 -0500415}
416
Jamie Madillc564c072017-06-01 12:45:42 -0400417Error FramebufferGL::readPixels(const gl::Context *context,
Frank Henigmanfa36c332017-06-09 18:44:45 -0400418 const gl::Rectangle &origArea,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500419 GLenum format,
420 GLenum type,
Jamie Madilld4826152017-09-21 11:18:59 -0400421 void *ptrOrOffset)
Geoff Langf9a6f082015-01-22 13:32:49 -0500422{
Frank Henigmanfa36c332017-06-09 18:44:45 -0400423 // Clip read area to framebuffer.
424 const gl::Extents fbSize = getState().getReadAttachment()->getSize();
425 const gl::Rectangle fbRect(0, 0, fbSize.width, fbSize.height);
426 gl::Rectangle area;
427 if (!ClipRectangle(origArea, fbRect, &area))
428 {
429 // nothing to read
430 return gl::NoError();
431 }
432
Corentin Wallezcda6af12017-10-30 19:20:37 -0400433 PixelPackState packState = context->getGLState().getPackState();
Corentin Wallez336129f2017-10-17 15:55:40 -0400434 const gl::Buffer *packBuffer =
435 context->getGLState().getTargetBuffer(gl::BufferBinding::PixelPack);
Jamie Madill87de3622015-03-16 10:41:44 -0400436
Geoff Langf607c602016-09-21 11:46:48 -0400437 nativegl::ReadPixelsFormat readPixelsFormat =
438 nativegl::GetReadPixelsFormat(mFunctions, mWorkarounds, format, type);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400439 GLenum readFormat = readPixelsFormat.format;
440 GLenum readType = readPixelsFormat.type;
Geoff Lang4ad17092015-03-10 16:47:44 -0400441
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400442 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, mFramebufferID);
443
Frank Henigmanfa36c332017-06-09 18:44:45 -0400444 bool useOverlappingRowsWorkaround = mWorkarounds.packOverlappingRowsSeparatelyPackBuffer &&
Corentin Wallezcda6af12017-10-30 19:20:37 -0400445 packBuffer && packState.rowLength != 0 &&
Frank Henigmanfa36c332017-06-09 18:44:45 -0400446 packState.rowLength < area.width;
447
448 GLubyte *pixels = reinterpret_cast<GLubyte *>(ptrOrOffset);
449 int leftClip = area.x - origArea.x;
450 int topClip = area.y - origArea.y;
451 if (leftClip || topClip)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400452 {
Frank Henigmanfa36c332017-06-09 18:44:45 -0400453 // Adjust destination to match portion clipped off left and/or top.
454 const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(readFormat, readType);
455
456 GLuint rowBytes = 0;
457 ANGLE_TRY_RESULT(glFormat.computeRowPitch(readType, origArea.width, packState.alignment,
458 packState.rowLength),
459 rowBytes);
460 pixels += leftClip * glFormat.pixelBytes + topClip * rowBytes;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400461 }
462
Frank Henigmanfa36c332017-06-09 18:44:45 -0400463 if (packState.rowLength == 0 && area.width != origArea.width)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400464 {
Frank Henigmanfa36c332017-06-09 18:44:45 -0400465 // No rowLength was specified so it will derive from read width, but clipping changed the
466 // read width. Use the original width so we fill the user's buffer as they intended.
467 packState.rowLength = origArea.width;
468 }
Corentin Wallez886de362016-09-27 10:49:35 -0400469
Frank Henigmanfa36c332017-06-09 18:44:45 -0400470 // We want to use rowLength, but that might not be supported.
471 bool cannotSetDesiredRowLength =
472 packState.rowLength && !GetImplAs<ContextGL>(context)->getNativeExtensions().packSubimage;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400473
Frank Henigmanfa36c332017-06-09 18:44:45 -0400474 gl::Error retVal = gl::NoError();
475 if (cannotSetDesiredRowLength || useOverlappingRowsWorkaround)
476 {
477 retVal = readPixelsRowByRow(context, area, readFormat, readType, packState, pixels);
478 }
479 else
480 {
481 gl::ErrorOrResult<bool> useLastRowPaddingWorkaround = false;
482 if (mWorkarounds.packLastRowSeparatelyForPaddingInclusion)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400483 {
Corentin Wallezcda6af12017-10-30 19:20:37 -0400484 useLastRowPaddingWorkaround = ShouldApplyLastRowPaddingWorkaround(
485 gl::Extents(area.width, area.height, 1), packState, packBuffer, readFormat,
486 readType, false, pixels);
Frank Henigmanfa36c332017-06-09 18:44:45 -0400487 }
488
489 if (useLastRowPaddingWorkaround.isError())
490 {
491 retVal = useLastRowPaddingWorkaround.getError();
492 }
493 else
494 {
495 retVal = readPixelsAllAtOnce(context, area, readFormat, readType, packState, pixels,
496 useLastRowPaddingWorkaround.getResult());
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400497 }
498 }
499
Frank Henigmanfa36c332017-06-09 18:44:45 -0400500 return retVal;
Geoff Langf9a6f082015-01-22 13:32:49 -0500501}
502
Jamie Madillc564c072017-06-01 12:45:42 -0400503Error FramebufferGL::blit(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500504 const gl::Rectangle &sourceArea,
505 const gl::Rectangle &destArea,
506 GLbitfield mask,
Jamie Madill8415b5f2016-04-26 13:41:39 -0400507 GLenum filter)
Geoff Langf9a6f082015-01-22 13:32:49 -0500508{
Jamie Madill231c7f52017-04-26 13:45:37 -0400509 const Framebuffer *sourceFramebuffer = context->getGLState().getReadFramebuffer();
510 const Framebuffer *destFramebuffer = context->getGLState().getDrawFramebuffer();
Geoff Lang4ad17092015-03-10 16:47:44 -0400511
Corentin Wallez6898b352016-11-10 11:41:15 -0500512 const FramebufferAttachment *colorReadAttachment = sourceFramebuffer->getReadColorbuffer();
Corentin Wallez4596a762016-12-20 14:50:18 -0500513
514 GLsizei readAttachmentSamples = 0;
515 if (colorReadAttachment != nullptr)
516 {
517 readAttachmentSamples = colorReadAttachment->getSamples();
518 }
Corentin Wallez6898b352016-11-10 11:41:15 -0500519
Corentin Wallez26a717b2016-09-27 08:45:42 -0700520 bool needManualColorBlit = false;
521
Corentin Wallez6898b352016-11-10 11:41:15 -0500522 // TODO(cwallez) when the filter is LINEAR and both source and destination are SRGB, we
523 // could avoid doing a manual blit.
524
525 // Prior to OpenGL 4.4 BlitFramebuffer (section 18.3.1 of GL 4.3 core profile) reads:
526 // When values are taken from the read buffer, no linearization is performed, even
527 // if the format of the buffer is SRGB.
528 // Starting from OpenGL 4.4 (section 18.3.1) it reads:
529 // When values are taken from the read buffer, if FRAMEBUFFER_SRGB is enabled and the
530 // value of FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING for the framebuffer attachment
531 // corresponding to the read buffer is SRGB, the red, green, and blue components are
532 // converted from the non-linear sRGB color space according [...].
Corentin Wallez26a717b2016-09-27 08:45:42 -0700533 {
Jamie Madill231c7f52017-04-26 13:45:37 -0400534 bool sourceSRGB =
535 colorReadAttachment != nullptr && colorReadAttachment->getColorEncoding() == GL_SRGB;
Corentin Wallez6898b352016-11-10 11:41:15 -0500536 needManualColorBlit =
537 needManualColorBlit || (sourceSRGB && mFunctions->isAtMostGL(gl::Version(4, 3)));
538 }
Corentin Wallez26a717b2016-09-27 08:45:42 -0700539
Corentin Wallez6898b352016-11-10 11:41:15 -0500540 // Prior to OpenGL 4.2 BlitFramebuffer (section 4.3.2 of GL 4.1 core profile) reads:
541 // Blit operations bypass the fragment pipeline. The only fragment operations which
542 // affect a blit are the pixel ownership test and scissor test.
543 // Starting from OpenGL 4.2 (section 4.3.2) it reads:
544 // When values are written to the draw buffers, blit operations bypass the fragment
545 // pipeline. The only fragment operations which affect a blit are the pixel ownership
546 // test, the scissor test and sRGB conversion.
547 if (!needManualColorBlit)
548 {
549 bool destSRGB = false;
550 for (size_t i = 0; i < destFramebuffer->getDrawbufferStateCount(); ++i)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700551 {
Corentin Wallez6898b352016-11-10 11:41:15 -0500552 const FramebufferAttachment *attachment = destFramebuffer->getDrawBuffer(i);
553 if (attachment && attachment->getColorEncoding() == GL_SRGB)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700554 {
Corentin Wallez6898b352016-11-10 11:41:15 -0500555 destSRGB = true;
556 break;
Corentin Wallez26a717b2016-09-27 08:45:42 -0700557 }
Corentin Wallez26a717b2016-09-27 08:45:42 -0700558 }
Corentin Wallez6898b352016-11-10 11:41:15 -0500559
560 needManualColorBlit =
561 needManualColorBlit || (destSRGB && mFunctions->isAtMostGL(gl::Version(4, 1)));
Corentin Wallez26a717b2016-09-27 08:45:42 -0700562 }
563
564 // Enable FRAMEBUFFER_SRGB if needed
Jamie Madill4928b7c2017-06-20 12:57:39 -0400565 mStateManager->setFramebufferSRGBEnabledForFramebuffer(context, true, this);
Corentin Wallez26a717b2016-09-27 08:45:42 -0700566
567 GLenum blitMask = mask;
Corentin Wallez6898b352016-11-10 11:41:15 -0500568 if (needManualColorBlit && (mask & GL_COLOR_BUFFER_BIT) && readAttachmentSamples <= 1)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700569 {
570 ANGLE_TRY(mBlitter->blitColorBufferWithShader(sourceFramebuffer, destFramebuffer,
571 sourceArea, destArea, filter));
572 blitMask &= ~GL_COLOR_BUFFER_BIT;
573 }
574
575 if (blitMask == 0)
576 {
577 return gl::NoError();
578 }
579
580 const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(sourceFramebuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400581 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
582 mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferID);
583
Jamie Madill2da819e2015-12-03 15:53:19 -0500584 mFunctions->blitFramebuffer(sourceArea.x, sourceArea.y, sourceArea.x1(), sourceArea.y1(),
Corentin Wallez26a717b2016-09-27 08:45:42 -0700585 destArea.x, destArea.y, destArea.x1(), destArea.y1(), blitMask,
586 filter);
Geoff Lang4ad17092015-03-10 16:47:44 -0400587
Corentin Wallez26a717b2016-09-27 08:45:42 -0700588 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500589}
590
JiangYizhoubddc46b2016-12-09 09:50:51 +0800591gl::Error FramebufferGL::getSamplePosition(size_t index, GLfloat *xy) const
592{
593 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
594 mFunctions->getMultisamplefv(GL_SAMPLE_POSITION, static_cast<GLuint>(index), xy);
595 return gl::NoError();
596}
597
Kenneth Russellce8602a2017-10-03 18:23:08 -0700598bool FramebufferGL::checkStatus(const gl::Context *context) const
Geoff Langf9a6f082015-01-22 13:32:49 -0500599{
Geoff Lang4ad17092015-03-10 16:47:44 -0400600 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Jamie Madillcc86d642015-11-24 13:00:07 -0500601 GLenum status = mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
602 if (status != GL_FRAMEBUFFER_COMPLETE)
603 {
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500604 WARN() << "GL framebuffer returned incomplete.";
Jamie Madillcc86d642015-11-24 13:00:07 -0500605 }
606 return (status == GL_FRAMEBUFFER_COMPLETE);
Geoff Lang4ad17092015-03-10 16:47:44 -0400607}
608
Jamie Madill19fa1c62018-03-08 09:47:21 -0500609gl::Error FramebufferGL::syncState(const gl::Context *context,
610 const Framebuffer::DirtyBits &dirtyBits)
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500611{
612 // Don't need to sync state for the default FBO.
613 if (mIsDefault)
614 {
Jamie Madill19fa1c62018-03-08 09:47:21 -0500615 return gl::NoError();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500616 }
617
618 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
619
Martin Radev7c2e6a92017-08-28 11:13:16 +0300620 // A pointer to one of the attachments for which the texture or the render buffer is not zero.
621 const FramebufferAttachment *attachment = nullptr;
Martin Radev878c8b12017-07-28 09:51:04 +0300622
Jamie Madill6de51852017-04-12 09:53:01 -0400623 for (auto dirtyBit : dirtyBits)
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500624 {
625 switch (dirtyBit)
626 {
627 case Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
Martin Radev7c2e6a92017-08-28 11:13:16 +0300628 {
629 const FramebufferAttachment *newAttachment = mState.getDepthAttachment();
630 BindFramebufferAttachment(mFunctions, GL_DEPTH_ATTACHMENT, newAttachment);
631 if (newAttachment)
632 {
633 attachment = newAttachment;
634 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500635 break;
Martin Radev7c2e6a92017-08-28 11:13:16 +0300636 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500637 case Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
Martin Radev7c2e6a92017-08-28 11:13:16 +0300638 {
639 const FramebufferAttachment *newAttachment = mState.getStencilAttachment();
640 BindFramebufferAttachment(mFunctions, GL_STENCIL_ATTACHMENT, newAttachment);
641 if (newAttachment)
642 {
643 attachment = newAttachment;
644 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500645 break;
Martin Radev7c2e6a92017-08-28 11:13:16 +0300646 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500647 case Framebuffer::DIRTY_BIT_DRAW_BUFFERS:
648 {
Jamie Madill48ef11b2016-04-27 15:21:52 -0400649 const auto &drawBuffers = mState.getDrawBufferStates();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500650 mFunctions->drawBuffers(static_cast<GLsizei>(drawBuffers.size()),
651 drawBuffers.data());
Corentin Walleze7557742017-06-01 13:09:57 -0400652 mAppliedEnabledDrawBuffers = mState.getEnabledDrawBuffers();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500653 break;
654 }
655 case Framebuffer::DIRTY_BIT_READ_BUFFER:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400656 mFunctions->readBuffer(mState.getReadBufferState());
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500657 break;
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800658 case Framebuffer::DIRTY_BIT_DEFAULT_WIDTH:
659 mFunctions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH,
660 mState.getDefaultWidth());
661 break;
662 case Framebuffer::DIRTY_BIT_DEFAULT_HEIGHT:
663 mFunctions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT,
664 mState.getDefaultHeight());
665 break;
666 case Framebuffer::DIRTY_BIT_DEFAULT_SAMPLES:
667 mFunctions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_SAMPLES,
668 mState.getDefaultSamples());
669 break;
670 case Framebuffer::DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS:
Geoff Lang92019432017-11-20 13:09:34 -0500671 mFunctions->framebufferParameteri(
672 GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS,
673 gl::ConvertToGLBoolean(mState.getDefaultFixedSampleLocations()));
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800674 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500675 default:
676 {
677 ASSERT(Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0 &&
678 dirtyBit < Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX);
679 size_t index =
680 static_cast<size_t>(dirtyBit - Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
Martin Radev7c2e6a92017-08-28 11:13:16 +0300681 const FramebufferAttachment *newAttachment = mState.getColorAttachment(index);
682 BindFramebufferAttachment(
683 mFunctions, static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + index), newAttachment);
684 if (newAttachment)
685 {
686 attachment = newAttachment;
687 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500688 break;
689 }
690 }
691 }
Martin Radev878c8b12017-07-28 09:51:04 +0300692
Martin Radev7c2e6a92017-08-28 11:13:16 +0300693 if (attachment)
Martin Radev878c8b12017-07-28 09:51:04 +0300694 {
Martin Radev7c2e6a92017-08-28 11:13:16 +0300695 const bool isSideBySide =
696 (attachment->getMultiviewLayout() == GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE);
Martin Radev878c8b12017-07-28 09:51:04 +0300697 mStateManager->setSideBySide(isSideBySide);
Martin Radev7c2e6a92017-08-28 11:13:16 +0300698 mStateManager->setViewportOffsets(attachment->getMultiviewViewportOffsets());
Martin Radev4e619f52017-08-09 11:50:06 +0300699 mStateManager->updateMultiviewBaseViewLayerIndexUniform(context->getGLState().getProgram(),
700 getState());
Martin Radev878c8b12017-07-28 09:51:04 +0300701 }
Jamie Madill19fa1c62018-03-08 09:47:21 -0500702
703 return gl::NoError();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500704}
705
Geoff Lang4ad17092015-03-10 16:47:44 -0400706GLuint FramebufferGL::getFramebufferID() const
707{
708 return mFramebufferID;
Geoff Langf9a6f082015-01-22 13:32:49 -0500709}
710
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700711bool FramebufferGL::isDefault() const
Geoff Langafd7f0a2015-09-09 15:33:31 -0400712{
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700713 return mIsDefault;
Geoff Langafd7f0a2015-09-09 15:33:31 -0400714}
715
Geoff Lang809b13e2017-11-07 15:33:46 -0500716void FramebufferGL::maskOutInactiveOutputDrawBuffers(GLenum binding, DrawBufferMask maxSet)
Corentin Walleze7557742017-06-01 13:09:57 -0400717{
718 auto targetAppliedDrawBuffers = mState.getEnabledDrawBuffers() & maxSet;
719 if (mAppliedEnabledDrawBuffers != targetAppliedDrawBuffers)
720 {
721 mAppliedEnabledDrawBuffers = targetAppliedDrawBuffers;
722
723 const auto &stateDrawBuffers = mState.getDrawBufferStates();
724 GLsizei drawBufferCount = static_cast<GLsizei>(stateDrawBuffers.size());
725 ASSERT(drawBufferCount <= IMPLEMENTATION_MAX_DRAW_BUFFERS);
726
727 GLenum drawBuffers[IMPLEMENTATION_MAX_DRAW_BUFFERS];
728 for (GLenum i = 0; static_cast<int>(i) < drawBufferCount; ++i)
729 {
730 drawBuffers[i] = targetAppliedDrawBuffers[i] ? stateDrawBuffers[i] : GL_NONE;
731 }
732
Geoff Lang809b13e2017-11-07 15:33:46 -0500733 mStateManager->bindFramebuffer(binding, mFramebufferID);
Corentin Walleze7557742017-06-01 13:09:57 -0400734 mFunctions->drawBuffers(drawBufferCount, drawBuffers);
735 }
736}
737
Jamie Madillc564c072017-06-01 12:45:42 -0400738void FramebufferGL::syncClearState(const gl::Context *context, GLbitfield mask)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400739{
Frank Henigmana3d333c2016-03-22 22:09:14 -0400740 if (mFunctions->standard == STANDARD_GL_DESKTOP)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400741 {
Frank Henigmana3d333c2016-03-22 22:09:14 -0400742 if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments &&
743 (mask & GL_COLOR_BUFFER_BIT) != 0 && !mIsDefault)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400744 {
Corentin Wallez26a717b2016-09-27 08:45:42 -0700745 bool hasSRGBAttachment = false;
Jamie Madill48ef11b2016-04-27 15:21:52 -0400746 for (const auto &attachment : mState.getColorAttachments())
Geoff Langafd7f0a2015-09-09 15:33:31 -0400747 {
Frank Henigmana3d333c2016-03-22 22:09:14 -0400748 if (attachment.isAttached() && attachment.getColorEncoding() == GL_SRGB)
749 {
Corentin Wallez26a717b2016-09-27 08:45:42 -0700750 hasSRGBAttachment = true;
Frank Henigmana3d333c2016-03-22 22:09:14 -0400751 break;
752 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400753 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400754
Jamie Madill4928b7c2017-06-20 12:57:39 -0400755 mStateManager->setFramebufferSRGBEnabled(context, hasSRGBAttachment);
Frank Henigmana3d333c2016-03-22 22:09:14 -0400756 }
757 else
758 {
Jamie Madill4928b7c2017-06-20 12:57:39 -0400759 mStateManager->setFramebufferSRGBEnabled(context, !mIsDefault);
Frank Henigmana3d333c2016-03-22 22:09:14 -0400760 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400761 }
762}
763
Jamie Madillc564c072017-06-01 12:45:42 -0400764void FramebufferGL::syncClearBufferState(const gl::Context *context,
765 GLenum buffer,
766 GLint drawBuffer)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400767{
768 if (mFunctions->standard == STANDARD_GL_DESKTOP)
769 {
770 if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments && buffer == GL_COLOR &&
771 !mIsDefault)
772 {
773 // If doing a clear on a color buffer, set SRGB blend enabled only if the color buffer
774 // is an SRGB format.
Jamie Madill48ef11b2016-04-27 15:21:52 -0400775 const auto &drawbufferState = mState.getDrawBufferStates();
776 const auto &colorAttachments = mState.getColorAttachments();
Geoff Langafd7f0a2015-09-09 15:33:31 -0400777
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500778 const FramebufferAttachment *attachment = nullptr;
Geoff Langafd7f0a2015-09-09 15:33:31 -0400779 if (drawbufferState[drawBuffer] >= GL_COLOR_ATTACHMENT0 &&
780 drawbufferState[drawBuffer] < GL_COLOR_ATTACHMENT0 + colorAttachments.size())
781 {
782 size_t attachmentIdx =
783 static_cast<size_t>(drawbufferState[drawBuffer] - GL_COLOR_ATTACHMENT0);
784 attachment = &colorAttachments[attachmentIdx];
785 }
786
787 if (attachment != nullptr)
788 {
Jamie Madill4928b7c2017-06-20 12:57:39 -0400789 mStateManager->setFramebufferSRGBEnabled(context,
Frank Henigman308d7452017-02-15 22:51:21 -0500790 attachment->getColorEncoding() == GL_SRGB);
Geoff Langafd7f0a2015-09-09 15:33:31 -0400791 }
792 }
793 else
794 {
Jamie Madill4928b7c2017-06-20 12:57:39 -0400795 mStateManager->setFramebufferSRGBEnabled(context, !mIsDefault);
Geoff Langafd7f0a2015-09-09 15:33:31 -0400796 }
797 }
798}
Geoff Lang005a7012017-03-27 13:17:34 -0400799
800bool FramebufferGL::modifyInvalidateAttachmentsForEmulatedDefaultFBO(
801 size_t count,
802 const GLenum *attachments,
803 std::vector<GLenum> *modifiedAttachments) const
804{
805 bool needsModification = mIsDefault && mFramebufferID != 0;
806 if (!needsModification)
807 {
808 return false;
809 }
810
811 modifiedAttachments->resize(count);
812 for (size_t i = 0; i < count; i++)
813 {
814 switch (attachments[i])
815 {
816 case GL_COLOR:
817 (*modifiedAttachments)[i] = GL_COLOR_ATTACHMENT0;
818 break;
819
820 case GL_DEPTH:
821 (*modifiedAttachments)[i] = GL_DEPTH_ATTACHMENT;
822 break;
823
824 case GL_STENCIL:
825 (*modifiedAttachments)[i] = GL_STENCIL_ATTACHMENT;
826 break;
827
828 default:
829 UNREACHABLE();
830 break;
831 }
832 }
833
834 return true;
835}
836
Frank Henigmanfa36c332017-06-09 18:44:45 -0400837gl::Error FramebufferGL::readPixelsRowByRow(const gl::Context *context,
838 const gl::Rectangle &area,
839 GLenum format,
840 GLenum type,
841 const gl::PixelPackState &pack,
842 GLubyte *pixels) const
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400843{
Geoff Langca271392017-04-05 12:30:00 -0400844 const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(format, type);
Frank Henigmanfa36c332017-06-09 18:44:45 -0400845
846 GLuint rowBytes = 0;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400847 ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
848 rowBytes);
849 GLuint skipBytes = 0;
Corentin Wallez886de362016-09-27 10:49:35 -0400850 ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400851
852 gl::PixelPackState directPack;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400853 directPack.alignment = 1;
854 mStateManager->setPixelPackState(directPack);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400855
Frank Henigmanfa36c332017-06-09 18:44:45 -0400856 pixels += skipBytes;
857 for (GLint y = area.y; y < area.y + area.height; ++y)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400858 {
Frank Henigmanfa36c332017-06-09 18:44:45 -0400859 mFunctions->readPixels(area.x, y, area.width, 1, format, type, pixels);
860 pixels += rowBytes;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400861 }
862
863 return gl::NoError();
864}
865
Frank Henigmanfa36c332017-06-09 18:44:45 -0400866gl::Error FramebufferGL::readPixelsAllAtOnce(const gl::Context *context,
867 const gl::Rectangle &area,
868 GLenum format,
869 GLenum type,
870 const gl::PixelPackState &pack,
871 GLubyte *pixels,
872 bool readLastRowSeparately) const
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400873{
Frank Henigmanfa36c332017-06-09 18:44:45 -0400874 GLint height = area.height - readLastRowSeparately;
875 if (height > 0)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400876 {
Frank Henigmanfa36c332017-06-09 18:44:45 -0400877 mStateManager->setPixelPackState(pack);
878 mFunctions->readPixels(area.x, area.y, area.width, height, format, type, pixels);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400879 }
880
Frank Henigmanfa36c332017-06-09 18:44:45 -0400881 if (readLastRowSeparately)
882 {
883 const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(format, type);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400884
Frank Henigmanfa36c332017-06-09 18:44:45 -0400885 GLuint rowBytes = 0;
886 ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
887 rowBytes);
888 GLuint skipBytes = 0;
889 ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
890
891 gl::PixelPackState directPack;
Frank Henigmanfa36c332017-06-09 18:44:45 -0400892 directPack.alignment = 1;
893 mStateManager->setPixelPackState(directPack);
Frank Henigmanfa36c332017-06-09 18:44:45 -0400894
895 pixels += skipBytes + (area.height - 1) * rowBytes;
896 mFunctions->readPixels(area.x, area.y + area.height - 1, area.width, 1, format, type,
897 pixels);
898 }
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400899
900 return gl::NoError();
901}
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500902} // namespace rx