blob: c846245b1db5ffb97db95fb4c08a11c83fd7924c [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"
Martin Radev5e424fa2017-08-09 16:25:36 +030020#include "libANGLE/renderer/gl/ClearMultiviewGL.h"
Frank Henigmanfa36c332017-06-09 18:44:45 -040021#include "libANGLE/renderer/gl/ContextGL.h"
Geoff Lang4ad17092015-03-10 16:47:44 -040022#include "libANGLE/renderer/gl/FunctionsGL.h"
Jacek Cabanfa60f692015-04-27 18:23:44 +020023#include "libANGLE/renderer/gl/RenderbufferGL.h"
Geoff Lang4ad17092015-03-10 16:47:44 -040024#include "libANGLE/renderer/gl/StateManagerGL.h"
25#include "libANGLE/renderer/gl/TextureGL.h"
Geoff Langafd7f0a2015-09-09 15:33:31 -040026#include "libANGLE/renderer/gl/WorkaroundsGL.h"
Geoff Langf607c602016-09-21 11:46:48 -040027#include "libANGLE/renderer/gl/formatutilsgl.h"
Corentin Wallez886de362016-09-27 10:49:35 -040028#include "libANGLE/renderer/gl/renderergl_utils.h"
Jamie Madillcc86d642015-11-24 13:00:07 -050029#include "platform/Platform.h"
Geoff Langf9a6f082015-01-22 13:32:49 -050030
Jamie Madill60ec6ea2016-01-22 15:27:19 -050031using namespace gl;
Corentin Wallez9a8d3662016-09-22 12:18:29 -040032using angle::CheckedNumeric;
Jamie Madill60ec6ea2016-01-22 15:27:19 -050033
Geoff Langf9a6f082015-01-22 13:32:49 -050034namespace rx
35{
36
Martin Radev878c8b12017-07-28 09:51:04 +030037namespace
Geoff Lang4ad17092015-03-10 16:47:44 -040038{
Geoff Langf9a6f082015-01-22 13:32:49 -050039
Martin Radev878c8b12017-07-28 09:51:04 +030040void BindFramebufferAttachment(const FunctionsGL *functions,
41 GLenum attachmentPoint,
42 const FramebufferAttachment *attachment)
Geoff Lang4ad17092015-03-10 16:47:44 -040043{
44 if (attachment)
45 {
46 if (attachment->type() == GL_TEXTURE)
47 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -050048 const Texture *texture = attachment->getTexture();
Geoff Lang4ad17092015-03-10 16:47:44 -040049 const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
50
JiangYizhoubddc46b2016-12-09 09:50:51 +080051 if (texture->getTarget() == GL_TEXTURE_2D ||
Corentin Wallez13c0dd42017-07-04 18:27:01 -040052 texture->getTarget() == GL_TEXTURE_2D_MULTISAMPLE ||
53 texture->getTarget() == GL_TEXTURE_RECTANGLE_ANGLE)
Geoff Lang4ad17092015-03-10 16:47:44 -040054 {
JiangYizhoubddc46b2016-12-09 09:50:51 +080055 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint,
56 texture->getTarget(), textureGL->getTextureID(),
57 attachment->mipLevel());
Geoff Lang4ad17092015-03-10 16:47:44 -040058 }
59 else if (texture->getTarget() == GL_TEXTURE_CUBE_MAP)
60 {
Jamie Madill231c7f52017-04-26 13:45:37 -040061 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint,
62 attachment->cubeMapFace(),
Geoff Lang4ad17092015-03-10 16:47:44 -040063 textureGL->getTextureID(), attachment->mipLevel());
64 }
Jamie Madill231c7f52017-04-26 13:45:37 -040065 else if (texture->getTarget() == GL_TEXTURE_2D_ARRAY ||
66 texture->getTarget() == GL_TEXTURE_3D)
Geoff Lang4ad17092015-03-10 16:47:44 -040067 {
Martin Radev5e424fa2017-08-09 16:25:36 +030068 if (attachment->getMultiviewLayout() == GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE)
69 {
70 ASSERT(functions->framebufferTexture);
71 functions->framebufferTexture(GL_FRAMEBUFFER, attachmentPoint,
72 textureGL->getTextureID(),
73 attachment->mipLevel());
74 }
75 else
76 {
77 functions->framebufferTextureLayer(GL_FRAMEBUFFER, attachmentPoint,
78 textureGL->getTextureID(),
79 attachment->mipLevel(), attachment->layer());
80 }
Geoff Lang4ad17092015-03-10 16:47:44 -040081 }
82 else
83 {
84 UNREACHABLE();
85 }
86 }
87 else if (attachment->type() == GL_RENDERBUFFER)
88 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -050089 const Renderbuffer *renderbuffer = attachment->getRenderbuffer();
Geoff Langcd69f1c2015-03-18 14:33:23 -040090 const RenderbufferGL *renderbufferGL = GetImplAs<RenderbufferGL>(renderbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -040091
Geoff Langcd69f1c2015-03-18 14:33:23 -040092 functions->framebufferRenderbuffer(GL_FRAMEBUFFER, attachmentPoint, GL_RENDERBUFFER,
93 renderbufferGL->getRenderbufferID());
Geoff Lang4ad17092015-03-10 16:47:44 -040094 }
95 else
96 {
97 UNREACHABLE();
98 }
99 }
100 else
101 {
102 // Unbind this attachment
103 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_2D, 0, 0);
104 }
105}
Geoff Langf9a6f082015-01-22 13:32:49 -0500106
Martin Radev878c8b12017-07-28 09:51:04 +0300107void RetrieveMultiviewFieldsFromAttachment(const gl::FramebufferAttachment *attachment,
108 const std::vector<gl::Offset> **viewportOffsets,
Martin Radev4e619f52017-08-09 11:50:06 +0300109 GLenum *multiviewLayout,
110 int *baseViewIndex)
Martin Radev878c8b12017-07-28 09:51:04 +0300111{
112 if (attachment)
113 {
114 *viewportOffsets = &attachment->getMultiviewViewportOffsets();
115 *multiviewLayout = attachment->getMultiviewLayout();
Martin Radev4e619f52017-08-09 11:50:06 +0300116 *baseViewIndex = attachment->getBaseViewIndex();
Martin Radev878c8b12017-07-28 09:51:04 +0300117 }
118}
119
Martin Radev5e424fa2017-08-09 16:25:36 +0300120bool RequiresMultiviewClear(const FramebufferAttachment *attachment, bool scissorTestEnabled)
Martin Radevb0761932017-07-25 17:42:25 +0300121{
Martin Radev5e424fa2017-08-09 16:25:36 +0300122 if (attachment == nullptr)
123 {
124 return false;
125 }
126 switch (attachment->getMultiviewLayout())
127 {
128 case GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE:
129 // TODO(mradev): Optimize this for layered FBOs in which all of the layers in each
130 // attachment are active.
131 return true;
132 case GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE:
133 return (scissorTestEnabled == true);
134 case GL_NONE:
135 return false;
136 default:
137 UNREACHABLE();
138 }
139 return false;
Martin Radevb0761932017-07-25 17:42:25 +0300140}
141
Martin Radev878c8b12017-07-28 09:51:04 +0300142} // namespace
143
144FramebufferGL::FramebufferGL(const FramebufferState &state,
145 const FunctionsGL *functions,
146 StateManagerGL *stateManager,
147 const WorkaroundsGL &workarounds,
148 BlitGL *blitter,
Martin Radev5e424fa2017-08-09 16:25:36 +0300149 ClearMultiviewGL *multiviewClearer,
Martin Radev878c8b12017-07-28 09:51:04 +0300150 bool isDefault)
151 : FramebufferImpl(state),
152 mFunctions(functions),
153 mStateManager(stateManager),
154 mWorkarounds(workarounds),
155 mBlitter(blitter),
Martin Radev5e424fa2017-08-09 16:25:36 +0300156 mMultiviewClearer(multiviewClearer),
Martin Radev878c8b12017-07-28 09:51:04 +0300157 mFramebufferID(0),
158 mIsDefault(isDefault),
159 mAppliedEnabledDrawBuffers(1)
160{
161 if (!mIsDefault)
162 {
163 mFunctions->genFramebuffers(1, &mFramebufferID);
164 }
165}
166
167FramebufferGL::FramebufferGL(GLuint id,
168 const FramebufferState &state,
169 const FunctionsGL *functions,
170 const WorkaroundsGL &workarounds,
171 BlitGL *blitter,
Martin Radev5e424fa2017-08-09 16:25:36 +0300172 ClearMultiviewGL *multiviewClearer,
Martin Radev878c8b12017-07-28 09:51:04 +0300173 StateManagerGL *stateManager)
174 : FramebufferImpl(state),
175 mFunctions(functions),
176 mStateManager(stateManager),
177 mWorkarounds(workarounds),
178 mBlitter(blitter),
Martin Radev5e424fa2017-08-09 16:25:36 +0300179 mMultiviewClearer(multiviewClearer),
Martin Radev878c8b12017-07-28 09:51:04 +0300180 mFramebufferID(id),
181 mIsDefault(true),
182 mAppliedEnabledDrawBuffers(1)
183{
184}
185
186FramebufferGL::~FramebufferGL()
187{
188 mStateManager->deleteFramebuffer(mFramebufferID);
189 mFramebufferID = 0;
190}
191
Jamie Madill4928b7c2017-06-20 12:57:39 -0400192Error FramebufferGL::discard(const gl::Context *context, size_t count, const GLenum *attachments)
Austin Kinross08332632015-05-05 13:35:47 -0700193{
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500194 // glInvalidateFramebuffer accepts the same enums as glDiscardFramebufferEXT
Jamie Madill4928b7c2017-06-20 12:57:39 -0400195 return invalidate(context, count, attachments);
Austin Kinross08332632015-05-05 13:35:47 -0700196}
197
Jamie Madill4928b7c2017-06-20 12:57:39 -0400198Error FramebufferGL::invalidate(const gl::Context *context, size_t count, const GLenum *attachments)
Geoff Langf9a6f082015-01-22 13:32:49 -0500199{
Geoff Lang005a7012017-03-27 13:17:34 -0400200 const GLenum *finalAttachmentsPtr = attachments;
201
202 std::vector<GLenum> modifiedAttachments;
203 if (modifyInvalidateAttachmentsForEmulatedDefaultFBO(count, attachments, &modifiedAttachments))
204 {
205 finalAttachmentsPtr = modifiedAttachments.data();
206 }
207
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500208 // Since this function is just a hint, only call a native function if it exists.
Geoff Lang64a72442015-04-01 14:43:11 -0400209 if (mFunctions->invalidateFramebuffer)
210 {
211 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Geoff Lang005a7012017-03-27 13:17:34 -0400212 mFunctions->invalidateFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
213 finalAttachmentsPtr);
Geoff Lang64a72442015-04-01 14:43:11 -0400214 }
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500215 else if (mFunctions->discardFramebuffer)
216 {
217 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Geoff Lang005a7012017-03-27 13:17:34 -0400218 mFunctions->discardFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
219 finalAttachmentsPtr);
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500220 }
Geoff Lang64a72442015-04-01 14:43:11 -0400221
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500222 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500223}
224
Jamie Madill4928b7c2017-06-20 12:57:39 -0400225Error FramebufferGL::invalidateSub(const gl::Context *context,
226 size_t count,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500227 const GLenum *attachments,
228 const gl::Rectangle &area)
Geoff Langf9a6f082015-01-22 13:32:49 -0500229{
Geoff Lang005a7012017-03-27 13:17:34 -0400230
231 const GLenum *finalAttachmentsPtr = attachments;
232
233 std::vector<GLenum> modifiedAttachments;
234 if (modifyInvalidateAttachmentsForEmulatedDefaultFBO(count, attachments, &modifiedAttachments))
235 {
236 finalAttachmentsPtr = modifiedAttachments.data();
237 }
238
Jamie Madill231c7f52017-04-26 13:45:37 -0400239 // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is
240 // available.
Geoff Lang64a72442015-04-01 14:43:11 -0400241 if (mFunctions->invalidateSubFramebuffer)
242 {
243 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700244 mFunctions->invalidateSubFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
Geoff Lang005a7012017-03-27 13:17:34 -0400245 finalAttachmentsPtr, area.x, area.y, area.width,
246 area.height);
Geoff Lang64a72442015-04-01 14:43:11 -0400247 }
248
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500249 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500250}
251
Jamie Madillc564c072017-06-01 12:45:42 -0400252Error FramebufferGL::clear(const gl::Context *context, GLbitfield mask)
Geoff Langf9a6f082015-01-22 13:32:49 -0500253{
Frank Henigman308d7452017-02-15 22:51:21 -0500254 syncClearState(context, mask);
Geoff Lang4ad17092015-03-10 16:47:44 -0400255 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300256
Martin Radev5e424fa2017-08-09 16:25:36 +0300257 const auto &firstAttachment = mState.getFirstNonNullAttachment();
258 if (!RequiresMultiviewClear(firstAttachment, context->getGLState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300259 {
Martin Radev5e424fa2017-08-09 16:25:36 +0300260 mFunctions->clear(mask);
Martin Radevb0761932017-07-25 17:42:25 +0300261 }
262 else
263 {
Martin Radev5e424fa2017-08-09 16:25:36 +0300264 mMultiviewClearer->clearMultiviewFBO(mState, context->getGLState().getScissor(),
265 ClearMultiviewGL::ClearCommandType::Clear, mask,
266 GL_NONE, 0, nullptr, 0.0f, 0);
Martin Radevb0761932017-07-25 17:42:25 +0300267 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400268
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500269 return gl::NoError();
Geoff Lang4ad17092015-03-10 16:47:44 -0400270}
271
Jamie Madillc564c072017-06-01 12:45:42 -0400272Error FramebufferGL::clearBufferfv(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500273 GLenum buffer,
274 GLint drawbuffer,
275 const GLfloat *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500276{
Frank Henigman308d7452017-02-15 22:51:21 -0500277 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400278 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300279
Martin Radev5e424fa2017-08-09 16:25:36 +0300280 const auto &firstAttachment = mState.getFirstNonNullAttachment();
281 if (!RequiresMultiviewClear(firstAttachment, context->getGLState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300282 {
Martin Radev5e424fa2017-08-09 16:25:36 +0300283 mFunctions->clearBufferfv(buffer, drawbuffer, values);
Martin Radevb0761932017-07-25 17:42:25 +0300284 }
285 else
286 {
Martin Radev5e424fa2017-08-09 16:25:36 +0300287 mMultiviewClearer->clearMultiviewFBO(mState, context->getGLState().getScissor(),
288 ClearMultiviewGL::ClearCommandType::ClearBufferfv,
289 static_cast<GLbitfield>(0u), buffer, drawbuffer,
290 reinterpret_cast<const uint8_t *>(values), 0.0f, 0);
Martin Radevb0761932017-07-25 17:42:25 +0300291 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400292
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500293 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500294}
295
Jamie Madillc564c072017-06-01 12:45:42 -0400296Error FramebufferGL::clearBufferuiv(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500297 GLenum buffer,
298 GLint drawbuffer,
299 const GLuint *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500300{
Frank Henigman308d7452017-02-15 22:51:21 -0500301 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400302 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300303
Martin Radev5e424fa2017-08-09 16:25:36 +0300304 const auto &firstAttachment = mState.getFirstNonNullAttachment();
305 if (!RequiresMultiviewClear(firstAttachment, context->getGLState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300306 {
Martin Radev5e424fa2017-08-09 16:25:36 +0300307 mFunctions->clearBufferuiv(buffer, drawbuffer, values);
Martin Radevb0761932017-07-25 17:42:25 +0300308 }
309 else
310 {
Martin Radev5e424fa2017-08-09 16:25:36 +0300311 mMultiviewClearer->clearMultiviewFBO(mState, context->getGLState().getScissor(),
312 ClearMultiviewGL::ClearCommandType::ClearBufferuiv,
313 static_cast<GLbitfield>(0u), buffer, drawbuffer,
314 reinterpret_cast<const uint8_t *>(values), 0.0f, 0);
Martin Radevb0761932017-07-25 17:42:25 +0300315 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400316
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500317 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500318}
319
Jamie Madillc564c072017-06-01 12:45:42 -0400320Error FramebufferGL::clearBufferiv(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500321 GLenum buffer,
322 GLint drawbuffer,
323 const GLint *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500324{
Frank Henigman308d7452017-02-15 22:51:21 -0500325 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400326 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300327
Martin Radev5e424fa2017-08-09 16:25:36 +0300328 const auto &firstAttachment = mState.getFirstNonNullAttachment();
329 if (!RequiresMultiviewClear(firstAttachment, context->getGLState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300330 {
Martin Radev5e424fa2017-08-09 16:25:36 +0300331 mFunctions->clearBufferiv(buffer, drawbuffer, values);
Martin Radevb0761932017-07-25 17:42:25 +0300332 }
333 else
334 {
Martin Radev5e424fa2017-08-09 16:25:36 +0300335 mMultiviewClearer->clearMultiviewFBO(mState, context->getGLState().getScissor(),
336 ClearMultiviewGL::ClearCommandType::ClearBufferiv,
337 static_cast<GLbitfield>(0u), buffer, drawbuffer,
338 reinterpret_cast<const uint8_t *>(values), 0.0f, 0);
Martin Radevb0761932017-07-25 17:42:25 +0300339 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400340
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500341 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500342}
343
Jamie Madillc564c072017-06-01 12:45:42 -0400344Error FramebufferGL::clearBufferfi(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500345 GLenum buffer,
346 GLint drawbuffer,
347 GLfloat depth,
348 GLint stencil)
Geoff Langf9a6f082015-01-22 13:32:49 -0500349{
Frank Henigman308d7452017-02-15 22:51:21 -0500350 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400351 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300352
Martin Radev5e424fa2017-08-09 16:25:36 +0300353 const auto &firstAttachment = mState.getFirstNonNullAttachment();
354 if (!RequiresMultiviewClear(firstAttachment, context->getGLState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300355 {
356 mFunctions->clearBufferfi(buffer, drawbuffer, depth, stencil);
357 }
Martin Radev5e424fa2017-08-09 16:25:36 +0300358 else
359 {
360 mMultiviewClearer->clearMultiviewFBO(mState, context->getGLState().getScissor(),
361 ClearMultiviewGL::ClearCommandType::ClearBufferfi,
362 static_cast<GLbitfield>(0u), buffer, drawbuffer,
363 nullptr, depth, stencil);
364 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400365
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500366 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500367}
368
Jamie Madill4928b7c2017-06-20 12:57:39 -0400369GLenum FramebufferGL::getImplementationColorReadFormat(const gl::Context *context) const
Geoff Langf9a6f082015-01-22 13:32:49 -0500370{
Jamie Madilla3944d42016-07-22 22:13:26 -0400371 const auto *readAttachment = mState.getReadAttachment();
372 const Format &format = readAttachment->getFormat();
Geoff Langf607c602016-09-21 11:46:48 -0400373 return format.info->getReadPixelsFormat();
Geoff Langf9a6f082015-01-22 13:32:49 -0500374}
375
Jamie Madill4928b7c2017-06-20 12:57:39 -0400376GLenum FramebufferGL::getImplementationColorReadType(const gl::Context *context) const
Geoff Langf9a6f082015-01-22 13:32:49 -0500377{
Jamie Madilla3944d42016-07-22 22:13:26 -0400378 const auto *readAttachment = mState.getReadAttachment();
379 const Format &format = readAttachment->getFormat();
Geoff Langf607c602016-09-21 11:46:48 -0400380 return format.info->getReadPixelsType();
Geoff Langf9a6f082015-01-22 13:32:49 -0500381}
382
Jamie Madillc564c072017-06-01 12:45:42 -0400383Error FramebufferGL::readPixels(const gl::Context *context,
Frank Henigmanfa36c332017-06-09 18:44:45 -0400384 const gl::Rectangle &origArea,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500385 GLenum format,
386 GLenum type,
Frank Henigmanfa36c332017-06-09 18:44:45 -0400387 void *ptrOrOffset) const
Geoff Langf9a6f082015-01-22 13:32:49 -0500388{
Frank Henigmanfa36c332017-06-09 18:44:45 -0400389 // Clip read area to framebuffer.
390 const gl::Extents fbSize = getState().getReadAttachment()->getSize();
391 const gl::Rectangle fbRect(0, 0, fbSize.width, fbSize.height);
392 gl::Rectangle area;
393 if (!ClipRectangle(origArea, fbRect, &area))
394 {
395 // nothing to read
396 return gl::NoError();
397 }
398
399 PixelPackState packState;
400 packState.copyFrom(context, context->getGLState().getPackState());
Jamie Madill87de3622015-03-16 10:41:44 -0400401
Geoff Langf607c602016-09-21 11:46:48 -0400402 nativegl::ReadPixelsFormat readPixelsFormat =
403 nativegl::GetReadPixelsFormat(mFunctions, mWorkarounds, format, type);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400404 GLenum readFormat = readPixelsFormat.format;
405 GLenum readType = readPixelsFormat.type;
Geoff Lang4ad17092015-03-10 16:47:44 -0400406
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400407 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, mFramebufferID);
408
Frank Henigmanfa36c332017-06-09 18:44:45 -0400409 bool useOverlappingRowsWorkaround = mWorkarounds.packOverlappingRowsSeparatelyPackBuffer &&
410 packState.pixelBuffer.get() && packState.rowLength != 0 &&
411 packState.rowLength < area.width;
412
413 GLubyte *pixels = reinterpret_cast<GLubyte *>(ptrOrOffset);
414 int leftClip = area.x - origArea.x;
415 int topClip = area.y - origArea.y;
416 if (leftClip || topClip)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400417 {
Frank Henigmanfa36c332017-06-09 18:44:45 -0400418 // Adjust destination to match portion clipped off left and/or top.
419 const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(readFormat, readType);
420
421 GLuint rowBytes = 0;
422 ANGLE_TRY_RESULT(glFormat.computeRowPitch(readType, origArea.width, packState.alignment,
423 packState.rowLength),
424 rowBytes);
425 pixels += leftClip * glFormat.pixelBytes + topClip * rowBytes;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400426 }
427
Frank Henigmanfa36c332017-06-09 18:44:45 -0400428 if (packState.rowLength == 0 && area.width != origArea.width)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400429 {
Frank Henigmanfa36c332017-06-09 18:44:45 -0400430 // No rowLength was specified so it will derive from read width, but clipping changed the
431 // read width. Use the original width so we fill the user's buffer as they intended.
432 packState.rowLength = origArea.width;
433 }
Corentin Wallez886de362016-09-27 10:49:35 -0400434
Frank Henigmanfa36c332017-06-09 18:44:45 -0400435 // We want to use rowLength, but that might not be supported.
436 bool cannotSetDesiredRowLength =
437 packState.rowLength && !GetImplAs<ContextGL>(context)->getNativeExtensions().packSubimage;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400438
Frank Henigmanfa36c332017-06-09 18:44:45 -0400439 gl::Error retVal = gl::NoError();
440 if (cannotSetDesiredRowLength || useOverlappingRowsWorkaround)
441 {
442 retVal = readPixelsRowByRow(context, area, readFormat, readType, packState, pixels);
443 }
444 else
445 {
446 gl::ErrorOrResult<bool> useLastRowPaddingWorkaround = false;
447 if (mWorkarounds.packLastRowSeparatelyForPaddingInclusion)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400448 {
Frank Henigmanfa36c332017-06-09 18:44:45 -0400449 useLastRowPaddingWorkaround =
450 ShouldApplyLastRowPaddingWorkaround(gl::Extents(area.width, area.height, 1),
451 packState, readFormat, readType, false, pixels);
452 }
453
454 if (useLastRowPaddingWorkaround.isError())
455 {
456 retVal = useLastRowPaddingWorkaround.getError();
457 }
458 else
459 {
460 retVal = readPixelsAllAtOnce(context, area, readFormat, readType, packState, pixels,
461 useLastRowPaddingWorkaround.getResult());
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400462 }
463 }
464
Frank Henigmanfa36c332017-06-09 18:44:45 -0400465 packState.pixelBuffer.set(context, nullptr);
466 return retVal;
Geoff Langf9a6f082015-01-22 13:32:49 -0500467}
468
Jamie Madillc564c072017-06-01 12:45:42 -0400469Error FramebufferGL::blit(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500470 const gl::Rectangle &sourceArea,
471 const gl::Rectangle &destArea,
472 GLbitfield mask,
Jamie Madill8415b5f2016-04-26 13:41:39 -0400473 GLenum filter)
Geoff Langf9a6f082015-01-22 13:32:49 -0500474{
Jamie Madill231c7f52017-04-26 13:45:37 -0400475 const Framebuffer *sourceFramebuffer = context->getGLState().getReadFramebuffer();
476 const Framebuffer *destFramebuffer = context->getGLState().getDrawFramebuffer();
Geoff Lang4ad17092015-03-10 16:47:44 -0400477
Corentin Wallez6898b352016-11-10 11:41:15 -0500478 const FramebufferAttachment *colorReadAttachment = sourceFramebuffer->getReadColorbuffer();
Corentin Wallez4596a762016-12-20 14:50:18 -0500479
480 GLsizei readAttachmentSamples = 0;
481 if (colorReadAttachment != nullptr)
482 {
483 readAttachmentSamples = colorReadAttachment->getSamples();
484 }
Corentin Wallez6898b352016-11-10 11:41:15 -0500485
Corentin Wallez26a717b2016-09-27 08:45:42 -0700486 bool needManualColorBlit = false;
487
Corentin Wallez6898b352016-11-10 11:41:15 -0500488 // TODO(cwallez) when the filter is LINEAR and both source and destination are SRGB, we
489 // could avoid doing a manual blit.
490
491 // Prior to OpenGL 4.4 BlitFramebuffer (section 18.3.1 of GL 4.3 core profile) reads:
492 // When values are taken from the read buffer, no linearization is performed, even
493 // if the format of the buffer is SRGB.
494 // Starting from OpenGL 4.4 (section 18.3.1) it reads:
495 // When values are taken from the read buffer, if FRAMEBUFFER_SRGB is enabled and the
496 // value of FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING for the framebuffer attachment
497 // corresponding to the read buffer is SRGB, the red, green, and blue components are
498 // converted from the non-linear sRGB color space according [...].
Corentin Wallez26a717b2016-09-27 08:45:42 -0700499 {
Jamie Madill231c7f52017-04-26 13:45:37 -0400500 bool sourceSRGB =
501 colorReadAttachment != nullptr && colorReadAttachment->getColorEncoding() == GL_SRGB;
Corentin Wallez6898b352016-11-10 11:41:15 -0500502 needManualColorBlit =
503 needManualColorBlit || (sourceSRGB && mFunctions->isAtMostGL(gl::Version(4, 3)));
504 }
Corentin Wallez26a717b2016-09-27 08:45:42 -0700505
Corentin Wallez6898b352016-11-10 11:41:15 -0500506 // Prior to OpenGL 4.2 BlitFramebuffer (section 4.3.2 of GL 4.1 core profile) reads:
507 // Blit operations bypass the fragment pipeline. The only fragment operations which
508 // affect a blit are the pixel ownership test and scissor test.
509 // Starting from OpenGL 4.2 (section 4.3.2) it reads:
510 // When values are written to the draw buffers, blit operations bypass the fragment
511 // pipeline. The only fragment operations which affect a blit are the pixel ownership
512 // test, the scissor test and sRGB conversion.
513 if (!needManualColorBlit)
514 {
515 bool destSRGB = false;
516 for (size_t i = 0; i < destFramebuffer->getDrawbufferStateCount(); ++i)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700517 {
Corentin Wallez6898b352016-11-10 11:41:15 -0500518 const FramebufferAttachment *attachment = destFramebuffer->getDrawBuffer(i);
519 if (attachment && attachment->getColorEncoding() == GL_SRGB)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700520 {
Corentin Wallez6898b352016-11-10 11:41:15 -0500521 destSRGB = true;
522 break;
Corentin Wallez26a717b2016-09-27 08:45:42 -0700523 }
Corentin Wallez26a717b2016-09-27 08:45:42 -0700524 }
Corentin Wallez6898b352016-11-10 11:41:15 -0500525
526 needManualColorBlit =
527 needManualColorBlit || (destSRGB && mFunctions->isAtMostGL(gl::Version(4, 1)));
Corentin Wallez26a717b2016-09-27 08:45:42 -0700528 }
529
530 // Enable FRAMEBUFFER_SRGB if needed
Jamie Madill4928b7c2017-06-20 12:57:39 -0400531 mStateManager->setFramebufferSRGBEnabledForFramebuffer(context, true, this);
Corentin Wallez26a717b2016-09-27 08:45:42 -0700532
533 GLenum blitMask = mask;
Corentin Wallez6898b352016-11-10 11:41:15 -0500534 if (needManualColorBlit && (mask & GL_COLOR_BUFFER_BIT) && readAttachmentSamples <= 1)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700535 {
536 ANGLE_TRY(mBlitter->blitColorBufferWithShader(sourceFramebuffer, destFramebuffer,
537 sourceArea, destArea, filter));
538 blitMask &= ~GL_COLOR_BUFFER_BIT;
539 }
540
541 if (blitMask == 0)
542 {
543 return gl::NoError();
544 }
545
546 const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(sourceFramebuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400547 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
548 mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferID);
549
Jamie Madill2da819e2015-12-03 15:53:19 -0500550 mFunctions->blitFramebuffer(sourceArea.x, sourceArea.y, sourceArea.x1(), sourceArea.y1(),
Corentin Wallez26a717b2016-09-27 08:45:42 -0700551 destArea.x, destArea.y, destArea.x1(), destArea.y1(), blitMask,
552 filter);
Geoff Lang4ad17092015-03-10 16:47:44 -0400553
Corentin Wallez26a717b2016-09-27 08:45:42 -0700554 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500555}
556
JiangYizhoubddc46b2016-12-09 09:50:51 +0800557gl::Error FramebufferGL::getSamplePosition(size_t index, GLfloat *xy) const
558{
559 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
560 mFunctions->getMultisamplefv(GL_SAMPLE_POSITION, static_cast<GLuint>(index), xy);
561 return gl::NoError();
562}
563
Jamie Madillcc86d642015-11-24 13:00:07 -0500564bool FramebufferGL::checkStatus() const
Geoff Langf9a6f082015-01-22 13:32:49 -0500565{
Geoff Lang4ad17092015-03-10 16:47:44 -0400566 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Jamie Madillcc86d642015-11-24 13:00:07 -0500567 GLenum status = mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
568 if (status != GL_FRAMEBUFFER_COMPLETE)
569 {
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500570 WARN() << "GL framebuffer returned incomplete.";
Jamie Madillcc86d642015-11-24 13:00:07 -0500571 }
572 return (status == GL_FRAMEBUFFER_COMPLETE);
Geoff Lang4ad17092015-03-10 16:47:44 -0400573}
574
Jamie Madillc564c072017-06-01 12:45:42 -0400575void FramebufferGL::syncState(const gl::Context *context, const Framebuffer::DirtyBits &dirtyBits)
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500576{
577 // Don't need to sync state for the default FBO.
578 if (mIsDefault)
579 {
580 return;
581 }
582
583 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
584
Martin Radev878c8b12017-07-28 09:51:04 +0300585 const std::vector<gl::Offset> *attachmentViewportOffsets = nullptr;
586 GLenum multiviewLayout = GL_NONE;
Martin Radev4e619f52017-08-09 11:50:06 +0300587 int baseViewIndex = -1;
Martin Radev878c8b12017-07-28 09:51:04 +0300588 bool isAttachmentModified = false;
589
Jamie Madill6de51852017-04-12 09:53:01 -0400590 for (auto dirtyBit : dirtyBits)
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500591 {
592 switch (dirtyBit)
593 {
594 case Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
595 BindFramebufferAttachment(mFunctions, GL_DEPTH_ATTACHMENT,
Jamie Madill48ef11b2016-04-27 15:21:52 -0400596 mState.getDepthAttachment());
Martin Radev878c8b12017-07-28 09:51:04 +0300597 RetrieveMultiviewFieldsFromAttachment(mState.getDepthAttachment(),
Martin Radev4e619f52017-08-09 11:50:06 +0300598 &attachmentViewportOffsets, &multiviewLayout,
599 &baseViewIndex);
Martin Radev878c8b12017-07-28 09:51:04 +0300600 isAttachmentModified = true;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500601 break;
602 case Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
603 BindFramebufferAttachment(mFunctions, GL_STENCIL_ATTACHMENT,
Jamie Madill48ef11b2016-04-27 15:21:52 -0400604 mState.getStencilAttachment());
Martin Radev878c8b12017-07-28 09:51:04 +0300605 RetrieveMultiviewFieldsFromAttachment(mState.getStencilAttachment(),
Martin Radev4e619f52017-08-09 11:50:06 +0300606 &attachmentViewportOffsets, &multiviewLayout,
607 &baseViewIndex);
Martin Radev878c8b12017-07-28 09:51:04 +0300608 isAttachmentModified = true;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500609 break;
610 case Framebuffer::DIRTY_BIT_DRAW_BUFFERS:
611 {
Jamie Madill48ef11b2016-04-27 15:21:52 -0400612 const auto &drawBuffers = mState.getDrawBufferStates();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500613 mFunctions->drawBuffers(static_cast<GLsizei>(drawBuffers.size()),
614 drawBuffers.data());
Corentin Walleze7557742017-06-01 13:09:57 -0400615 mAppliedEnabledDrawBuffers = mState.getEnabledDrawBuffers();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500616 break;
617 }
618 case Framebuffer::DIRTY_BIT_READ_BUFFER:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400619 mFunctions->readBuffer(mState.getReadBufferState());
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500620 break;
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800621 case Framebuffer::DIRTY_BIT_DEFAULT_WIDTH:
622 mFunctions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH,
623 mState.getDefaultWidth());
624 break;
625 case Framebuffer::DIRTY_BIT_DEFAULT_HEIGHT:
626 mFunctions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT,
627 mState.getDefaultHeight());
628 break;
629 case Framebuffer::DIRTY_BIT_DEFAULT_SAMPLES:
630 mFunctions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_SAMPLES,
631 mState.getDefaultSamples());
632 break;
633 case Framebuffer::DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS:
634 mFunctions->framebufferParameteri(GL_FRAMEBUFFER,
635 GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS,
636 mState.getDefaultFixedSampleLocations());
637 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500638 default:
639 {
640 ASSERT(Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0 &&
641 dirtyBit < Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX);
642 size_t index =
643 static_cast<size_t>(dirtyBit - Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
644 BindFramebufferAttachment(mFunctions,
645 static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + index),
Jamie Madill48ef11b2016-04-27 15:21:52 -0400646 mState.getColorAttachment(index));
Martin Radev878c8b12017-07-28 09:51:04 +0300647 RetrieveMultiviewFieldsFromAttachment(mState.getColorAttachment(index),
Martin Radev4e619f52017-08-09 11:50:06 +0300648 &attachmentViewportOffsets, &multiviewLayout,
649 &baseViewIndex);
Martin Radev878c8b12017-07-28 09:51:04 +0300650 isAttachmentModified = true;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500651 break;
652 }
653 }
654 }
Martin Radev878c8b12017-07-28 09:51:04 +0300655
Martin Radev5e424fa2017-08-09 16:25:36 +0300656 // TODO(mradev): Handle case in which a texture is detached in a multi-view context.
Martin Radev878c8b12017-07-28 09:51:04 +0300657 if (isAttachmentModified)
658 {
659 const bool isSideBySide = multiviewLayout == GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE;
660 mStateManager->setSideBySide(isSideBySide);
Martin Radev878c8b12017-07-28 09:51:04 +0300661 if (attachmentViewportOffsets != nullptr)
662 {
663 mStateManager->setViewportOffsets(*attachmentViewportOffsets);
664 }
665 else
666 {
667 mStateManager->setViewportOffsets(
668 FramebufferAttachment::GetDefaultViewportOffsetVector());
669 }
Martin Radev4e619f52017-08-09 11:50:06 +0300670
671 mStateManager->updateMultiviewBaseViewLayerIndexUniform(context->getGLState().getProgram(),
672 getState());
Martin Radev878c8b12017-07-28 09:51:04 +0300673 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500674}
675
Geoff Lang4ad17092015-03-10 16:47:44 -0400676GLuint FramebufferGL::getFramebufferID() const
677{
678 return mFramebufferID;
Geoff Langf9a6f082015-01-22 13:32:49 -0500679}
680
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700681bool FramebufferGL::isDefault() const
Geoff Langafd7f0a2015-09-09 15:33:31 -0400682{
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700683 return mIsDefault;
Geoff Langafd7f0a2015-09-09 15:33:31 -0400684}
685
Corentin Walleze7557742017-06-01 13:09:57 -0400686void FramebufferGL::maskOutInactiveOutputDrawBuffers(DrawBufferMask maxSet)
687{
688 auto targetAppliedDrawBuffers = mState.getEnabledDrawBuffers() & maxSet;
689 if (mAppliedEnabledDrawBuffers != targetAppliedDrawBuffers)
690 {
691 mAppliedEnabledDrawBuffers = targetAppliedDrawBuffers;
692
693 const auto &stateDrawBuffers = mState.getDrawBufferStates();
694 GLsizei drawBufferCount = static_cast<GLsizei>(stateDrawBuffers.size());
695 ASSERT(drawBufferCount <= IMPLEMENTATION_MAX_DRAW_BUFFERS);
696
697 GLenum drawBuffers[IMPLEMENTATION_MAX_DRAW_BUFFERS];
698 for (GLenum i = 0; static_cast<int>(i) < drawBufferCount; ++i)
699 {
700 drawBuffers[i] = targetAppliedDrawBuffers[i] ? stateDrawBuffers[i] : GL_NONE;
701 }
702
703 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
704 mFunctions->drawBuffers(drawBufferCount, drawBuffers);
705 }
706}
707
Jamie Madillc564c072017-06-01 12:45:42 -0400708void FramebufferGL::syncClearState(const gl::Context *context, GLbitfield mask)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400709{
Frank Henigmana3d333c2016-03-22 22:09:14 -0400710 if (mFunctions->standard == STANDARD_GL_DESKTOP)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400711 {
Frank Henigmana3d333c2016-03-22 22:09:14 -0400712 if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments &&
713 (mask & GL_COLOR_BUFFER_BIT) != 0 && !mIsDefault)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400714 {
Corentin Wallez26a717b2016-09-27 08:45:42 -0700715 bool hasSRGBAttachment = false;
Jamie Madill48ef11b2016-04-27 15:21:52 -0400716 for (const auto &attachment : mState.getColorAttachments())
Geoff Langafd7f0a2015-09-09 15:33:31 -0400717 {
Frank Henigmana3d333c2016-03-22 22:09:14 -0400718 if (attachment.isAttached() && attachment.getColorEncoding() == GL_SRGB)
719 {
Corentin Wallez26a717b2016-09-27 08:45:42 -0700720 hasSRGBAttachment = true;
Frank Henigmana3d333c2016-03-22 22:09:14 -0400721 break;
722 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400723 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400724
Jamie Madill4928b7c2017-06-20 12:57:39 -0400725 mStateManager->setFramebufferSRGBEnabled(context, hasSRGBAttachment);
Frank Henigmana3d333c2016-03-22 22:09:14 -0400726 }
727 else
728 {
Jamie Madill4928b7c2017-06-20 12:57:39 -0400729 mStateManager->setFramebufferSRGBEnabled(context, !mIsDefault);
Frank Henigmana3d333c2016-03-22 22:09:14 -0400730 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400731 }
732}
733
Jamie Madillc564c072017-06-01 12:45:42 -0400734void FramebufferGL::syncClearBufferState(const gl::Context *context,
735 GLenum buffer,
736 GLint drawBuffer)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400737{
738 if (mFunctions->standard == STANDARD_GL_DESKTOP)
739 {
740 if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments && buffer == GL_COLOR &&
741 !mIsDefault)
742 {
743 // If doing a clear on a color buffer, set SRGB blend enabled only if the color buffer
744 // is an SRGB format.
Jamie Madill48ef11b2016-04-27 15:21:52 -0400745 const auto &drawbufferState = mState.getDrawBufferStates();
746 const auto &colorAttachments = mState.getColorAttachments();
Geoff Langafd7f0a2015-09-09 15:33:31 -0400747
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500748 const FramebufferAttachment *attachment = nullptr;
Geoff Langafd7f0a2015-09-09 15:33:31 -0400749 if (drawbufferState[drawBuffer] >= GL_COLOR_ATTACHMENT0 &&
750 drawbufferState[drawBuffer] < GL_COLOR_ATTACHMENT0 + colorAttachments.size())
751 {
752 size_t attachmentIdx =
753 static_cast<size_t>(drawbufferState[drawBuffer] - GL_COLOR_ATTACHMENT0);
754 attachment = &colorAttachments[attachmentIdx];
755 }
756
757 if (attachment != nullptr)
758 {
Jamie Madill4928b7c2017-06-20 12:57:39 -0400759 mStateManager->setFramebufferSRGBEnabled(context,
Frank Henigman308d7452017-02-15 22:51:21 -0500760 attachment->getColorEncoding() == GL_SRGB);
Geoff Langafd7f0a2015-09-09 15:33:31 -0400761 }
762 }
763 else
764 {
Jamie Madill4928b7c2017-06-20 12:57:39 -0400765 mStateManager->setFramebufferSRGBEnabled(context, !mIsDefault);
Geoff Langafd7f0a2015-09-09 15:33:31 -0400766 }
767 }
768}
Geoff Lang005a7012017-03-27 13:17:34 -0400769
770bool FramebufferGL::modifyInvalidateAttachmentsForEmulatedDefaultFBO(
771 size_t count,
772 const GLenum *attachments,
773 std::vector<GLenum> *modifiedAttachments) const
774{
775 bool needsModification = mIsDefault && mFramebufferID != 0;
776 if (!needsModification)
777 {
778 return false;
779 }
780
781 modifiedAttachments->resize(count);
782 for (size_t i = 0; i < count; i++)
783 {
784 switch (attachments[i])
785 {
786 case GL_COLOR:
787 (*modifiedAttachments)[i] = GL_COLOR_ATTACHMENT0;
788 break;
789
790 case GL_DEPTH:
791 (*modifiedAttachments)[i] = GL_DEPTH_ATTACHMENT;
792 break;
793
794 case GL_STENCIL:
795 (*modifiedAttachments)[i] = GL_STENCIL_ATTACHMENT;
796 break;
797
798 default:
799 UNREACHABLE();
800 break;
801 }
802 }
803
804 return true;
805}
806
Frank Henigmanfa36c332017-06-09 18:44:45 -0400807gl::Error FramebufferGL::readPixelsRowByRow(const gl::Context *context,
808 const gl::Rectangle &area,
809 GLenum format,
810 GLenum type,
811 const gl::PixelPackState &pack,
812 GLubyte *pixels) const
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400813{
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400814
Geoff Langca271392017-04-05 12:30:00 -0400815 const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(format, type);
Frank Henigmanfa36c332017-06-09 18:44:45 -0400816
817 GLuint rowBytes = 0;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400818 ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
819 rowBytes);
820 GLuint skipBytes = 0;
Corentin Wallez886de362016-09-27 10:49:35 -0400821 ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400822
823 gl::PixelPackState directPack;
Jamie Madill4928b7c2017-06-20 12:57:39 -0400824 directPack.pixelBuffer.set(context, pack.pixelBuffer.get());
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400825 directPack.alignment = 1;
826 mStateManager->setPixelPackState(directPack);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400827 directPack.pixelBuffer.set(context, nullptr);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400828
Frank Henigmanfa36c332017-06-09 18:44:45 -0400829 pixels += skipBytes;
830 for (GLint y = area.y; y < area.y + area.height; ++y)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400831 {
Frank Henigmanfa36c332017-06-09 18:44:45 -0400832 mFunctions->readPixels(area.x, y, area.width, 1, format, type, pixels);
833 pixels += rowBytes;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400834 }
835
836 return gl::NoError();
837}
838
Frank Henigmanfa36c332017-06-09 18:44:45 -0400839gl::Error FramebufferGL::readPixelsAllAtOnce(const gl::Context *context,
840 const gl::Rectangle &area,
841 GLenum format,
842 GLenum type,
843 const gl::PixelPackState &pack,
844 GLubyte *pixels,
845 bool readLastRowSeparately) const
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400846{
Frank Henigmanfa36c332017-06-09 18:44:45 -0400847 GLint height = area.height - readLastRowSeparately;
848 if (height > 0)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400849 {
Frank Henigmanfa36c332017-06-09 18:44:45 -0400850 mStateManager->setPixelPackState(pack);
851 mFunctions->readPixels(area.x, area.y, area.width, height, format, type, pixels);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400852 }
853
Frank Henigmanfa36c332017-06-09 18:44:45 -0400854 if (readLastRowSeparately)
855 {
856 const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(format, type);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400857
Frank Henigmanfa36c332017-06-09 18:44:45 -0400858 GLuint rowBytes = 0;
859 ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
860 rowBytes);
861 GLuint skipBytes = 0;
862 ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
863
864 gl::PixelPackState directPack;
865 directPack.pixelBuffer.set(context, pack.pixelBuffer.get());
866 directPack.alignment = 1;
867 mStateManager->setPixelPackState(directPack);
868 directPack.pixelBuffer.set(context, nullptr);
869
870 pixels += skipBytes + (area.height - 1) * rowBytes;
871 mFunctions->readPixels(area.x, area.y + area.height - 1, area.width, 1, format, type,
872 pixels);
873 }
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400874
875 return gl::NoError();
876}
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500877} // namespace rx