blob: 009b75ada7496b35407a6f6dd3aba5a9c8298bf5 [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 Radev61e710b2017-09-05 11:59:52 +0300107bool AreAllLayersActive(const FramebufferAttachment &attachment)
Martin Radevb0761932017-07-25 17:42:25 +0300108{
Martin Radev61e710b2017-09-05 11:59:52 +0300109 int baseViewIndex = attachment.getBaseViewIndex();
110 if (baseViewIndex != 0)
111 {
112 return false;
113 }
114 const ImageIndex &imageIndex = attachment.getTextureImageIndex();
115 int numLayers =
116 static_cast<int>(attachment.getTexture()->getDepth(imageIndex.type, imageIndex.mipIndex));
117 return (attachment.getNumViews() == numLayers);
118}
119
120bool RequiresMultiviewClear(const FramebufferState &state, bool scissorTestEnabled)
121{
122 // Get one attachment and check whether all layers are attached.
123 const FramebufferAttachment *attachment = nullptr;
124 bool allTextureArraysAreFullyAttached = true;
125 for (const FramebufferAttachment &colorAttachment : state.getColorAttachments())
126 {
127 if (colorAttachment.isAttached())
128 {
129 if (colorAttachment.getMultiviewLayout() == GL_NONE)
130 {
131 return false;
132 }
133 attachment = &colorAttachment;
134 allTextureArraysAreFullyAttached =
135 allTextureArraysAreFullyAttached && AreAllLayersActive(*attachment);
136 }
137 }
138
139 const FramebufferAttachment *depthAttachment = state.getDepthAttachment();
140 if (depthAttachment)
141 {
142 if (depthAttachment->getMultiviewLayout() == GL_NONE)
143 {
144 return false;
145 }
146 attachment = depthAttachment;
147 allTextureArraysAreFullyAttached =
148 allTextureArraysAreFullyAttached && AreAllLayersActive(*attachment);
149 }
150 const FramebufferAttachment *stencilAttachment = state.getStencilAttachment();
151 if (stencilAttachment)
152 {
153 if (stencilAttachment->getMultiviewLayout() == GL_NONE)
154 {
155 return false;
156 }
157 attachment = stencilAttachment;
158 allTextureArraysAreFullyAttached =
159 allTextureArraysAreFullyAttached && AreAllLayersActive(*attachment);
160 }
161
Martin Radev5e424fa2017-08-09 16:25:36 +0300162 if (attachment == nullptr)
163 {
164 return false;
165 }
166 switch (attachment->getMultiviewLayout())
167 {
168 case GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE:
Martin Radev61e710b2017-09-05 11:59:52 +0300169 // If all layers of each texture array are active, then there is no need to issue a
170 // special multiview clear.
171 return !allTextureArraysAreFullyAttached;
Martin Radev5e424fa2017-08-09 16:25:36 +0300172 case GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE:
173 return (scissorTestEnabled == true);
Martin Radev5e424fa2017-08-09 16:25:36 +0300174 default:
175 UNREACHABLE();
176 }
177 return false;
Martin Radevb0761932017-07-25 17:42:25 +0300178}
179
Martin Radev878c8b12017-07-28 09:51:04 +0300180} // namespace
181
182FramebufferGL::FramebufferGL(const FramebufferState &state,
183 const FunctionsGL *functions,
184 StateManagerGL *stateManager,
185 const WorkaroundsGL &workarounds,
186 BlitGL *blitter,
Martin Radev5e424fa2017-08-09 16:25:36 +0300187 ClearMultiviewGL *multiviewClearer,
Martin Radev878c8b12017-07-28 09:51:04 +0300188 bool isDefault)
189 : FramebufferImpl(state),
190 mFunctions(functions),
191 mStateManager(stateManager),
192 mWorkarounds(workarounds),
193 mBlitter(blitter),
Martin Radev5e424fa2017-08-09 16:25:36 +0300194 mMultiviewClearer(multiviewClearer),
Martin Radev878c8b12017-07-28 09:51:04 +0300195 mFramebufferID(0),
196 mIsDefault(isDefault),
197 mAppliedEnabledDrawBuffers(1)
198{
199 if (!mIsDefault)
200 {
201 mFunctions->genFramebuffers(1, &mFramebufferID);
202 }
203}
204
205FramebufferGL::FramebufferGL(GLuint id,
206 const FramebufferState &state,
207 const FunctionsGL *functions,
208 const WorkaroundsGL &workarounds,
209 BlitGL *blitter,
Martin Radev5e424fa2017-08-09 16:25:36 +0300210 ClearMultiviewGL *multiviewClearer,
Martin Radev878c8b12017-07-28 09:51:04 +0300211 StateManagerGL *stateManager)
212 : FramebufferImpl(state),
213 mFunctions(functions),
214 mStateManager(stateManager),
215 mWorkarounds(workarounds),
216 mBlitter(blitter),
Martin Radev5e424fa2017-08-09 16:25:36 +0300217 mMultiviewClearer(multiviewClearer),
Martin Radev878c8b12017-07-28 09:51:04 +0300218 mFramebufferID(id),
219 mIsDefault(true),
220 mAppliedEnabledDrawBuffers(1)
221{
222}
223
224FramebufferGL::~FramebufferGL()
225{
226 mStateManager->deleteFramebuffer(mFramebufferID);
227 mFramebufferID = 0;
228}
229
Jamie Madill4928b7c2017-06-20 12:57:39 -0400230Error FramebufferGL::discard(const gl::Context *context, size_t count, const GLenum *attachments)
Austin Kinross08332632015-05-05 13:35:47 -0700231{
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500232 // glInvalidateFramebuffer accepts the same enums as glDiscardFramebufferEXT
Jamie Madill4928b7c2017-06-20 12:57:39 -0400233 return invalidate(context, count, attachments);
Austin Kinross08332632015-05-05 13:35:47 -0700234}
235
Jamie Madill4928b7c2017-06-20 12:57:39 -0400236Error FramebufferGL::invalidate(const gl::Context *context, size_t count, const GLenum *attachments)
Geoff Langf9a6f082015-01-22 13:32:49 -0500237{
Geoff Lang005a7012017-03-27 13:17:34 -0400238 const GLenum *finalAttachmentsPtr = attachments;
239
240 std::vector<GLenum> modifiedAttachments;
241 if (modifyInvalidateAttachmentsForEmulatedDefaultFBO(count, attachments, &modifiedAttachments))
242 {
243 finalAttachmentsPtr = modifiedAttachments.data();
244 }
245
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500246 // Since this function is just a hint, only call a native function if it exists.
Geoff Lang64a72442015-04-01 14:43:11 -0400247 if (mFunctions->invalidateFramebuffer)
248 {
249 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Geoff Lang005a7012017-03-27 13:17:34 -0400250 mFunctions->invalidateFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
251 finalAttachmentsPtr);
Geoff Lang64a72442015-04-01 14:43:11 -0400252 }
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500253 else if (mFunctions->discardFramebuffer)
254 {
255 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Geoff Lang005a7012017-03-27 13:17:34 -0400256 mFunctions->discardFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
257 finalAttachmentsPtr);
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500258 }
Geoff Lang64a72442015-04-01 14:43:11 -0400259
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500260 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500261}
262
Jamie Madill4928b7c2017-06-20 12:57:39 -0400263Error FramebufferGL::invalidateSub(const gl::Context *context,
264 size_t count,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500265 const GLenum *attachments,
266 const gl::Rectangle &area)
Geoff Langf9a6f082015-01-22 13:32:49 -0500267{
Geoff Lang005a7012017-03-27 13:17:34 -0400268
269 const GLenum *finalAttachmentsPtr = attachments;
270
271 std::vector<GLenum> modifiedAttachments;
272 if (modifyInvalidateAttachmentsForEmulatedDefaultFBO(count, attachments, &modifiedAttachments))
273 {
274 finalAttachmentsPtr = modifiedAttachments.data();
275 }
276
Jamie Madill231c7f52017-04-26 13:45:37 -0400277 // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is
278 // available.
Geoff Lang64a72442015-04-01 14:43:11 -0400279 if (mFunctions->invalidateSubFramebuffer)
280 {
281 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Cooper Partin4d61f7e2015-08-12 10:56:50 -0700282 mFunctions->invalidateSubFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
Geoff Lang005a7012017-03-27 13:17:34 -0400283 finalAttachmentsPtr, area.x, area.y, area.width,
284 area.height);
Geoff Lang64a72442015-04-01 14:43:11 -0400285 }
286
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500287 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500288}
289
Jamie Madillc564c072017-06-01 12:45:42 -0400290Error FramebufferGL::clear(const gl::Context *context, GLbitfield mask)
Geoff Langf9a6f082015-01-22 13:32:49 -0500291{
Frank Henigman308d7452017-02-15 22:51:21 -0500292 syncClearState(context, mask);
Geoff Lang4ad17092015-03-10 16:47:44 -0400293 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300294
Martin Radev61e710b2017-09-05 11:59:52 +0300295 if (!RequiresMultiviewClear(mState, context->getGLState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300296 {
Martin Radev5e424fa2017-08-09 16:25:36 +0300297 mFunctions->clear(mask);
Martin Radevb0761932017-07-25 17:42:25 +0300298 }
299 else
300 {
Martin Radev5e424fa2017-08-09 16:25:36 +0300301 mMultiviewClearer->clearMultiviewFBO(mState, context->getGLState().getScissor(),
302 ClearMultiviewGL::ClearCommandType::Clear, mask,
303 GL_NONE, 0, nullptr, 0.0f, 0);
Martin Radevb0761932017-07-25 17:42:25 +0300304 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400305
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500306 return gl::NoError();
Geoff Lang4ad17092015-03-10 16:47:44 -0400307}
308
Jamie Madillc564c072017-06-01 12:45:42 -0400309Error FramebufferGL::clearBufferfv(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500310 GLenum buffer,
311 GLint drawbuffer,
312 const GLfloat *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500313{
Frank Henigman308d7452017-02-15 22:51:21 -0500314 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400315 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300316
Martin Radev61e710b2017-09-05 11:59:52 +0300317 if (!RequiresMultiviewClear(mState, context->getGLState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300318 {
Martin Radev5e424fa2017-08-09 16:25:36 +0300319 mFunctions->clearBufferfv(buffer, drawbuffer, values);
Martin Radevb0761932017-07-25 17:42:25 +0300320 }
321 else
322 {
Martin Radev5e424fa2017-08-09 16:25:36 +0300323 mMultiviewClearer->clearMultiviewFBO(mState, context->getGLState().getScissor(),
324 ClearMultiviewGL::ClearCommandType::ClearBufferfv,
325 static_cast<GLbitfield>(0u), buffer, drawbuffer,
326 reinterpret_cast<const uint8_t *>(values), 0.0f, 0);
Martin Radevb0761932017-07-25 17:42:25 +0300327 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400328
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500329 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500330}
331
Jamie Madillc564c072017-06-01 12:45:42 -0400332Error FramebufferGL::clearBufferuiv(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500333 GLenum buffer,
334 GLint drawbuffer,
335 const GLuint *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500336{
Frank Henigman308d7452017-02-15 22:51:21 -0500337 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400338 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300339
Martin Radev61e710b2017-09-05 11:59:52 +0300340 if (!RequiresMultiviewClear(mState, context->getGLState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300341 {
Martin Radev5e424fa2017-08-09 16:25:36 +0300342 mFunctions->clearBufferuiv(buffer, drawbuffer, values);
Martin Radevb0761932017-07-25 17:42:25 +0300343 }
344 else
345 {
Martin Radev5e424fa2017-08-09 16:25:36 +0300346 mMultiviewClearer->clearMultiviewFBO(mState, context->getGLState().getScissor(),
347 ClearMultiviewGL::ClearCommandType::ClearBufferuiv,
348 static_cast<GLbitfield>(0u), buffer, drawbuffer,
349 reinterpret_cast<const uint8_t *>(values), 0.0f, 0);
Martin Radevb0761932017-07-25 17:42:25 +0300350 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400351
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500352 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500353}
354
Jamie Madillc564c072017-06-01 12:45:42 -0400355Error FramebufferGL::clearBufferiv(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500356 GLenum buffer,
357 GLint drawbuffer,
358 const GLint *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500359{
Frank Henigman308d7452017-02-15 22:51:21 -0500360 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400361 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300362
Martin Radev61e710b2017-09-05 11:59:52 +0300363 if (!RequiresMultiviewClear(mState, context->getGLState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300364 {
Martin Radev5e424fa2017-08-09 16:25:36 +0300365 mFunctions->clearBufferiv(buffer, drawbuffer, values);
Martin Radevb0761932017-07-25 17:42:25 +0300366 }
367 else
368 {
Martin Radev5e424fa2017-08-09 16:25:36 +0300369 mMultiviewClearer->clearMultiviewFBO(mState, context->getGLState().getScissor(),
370 ClearMultiviewGL::ClearCommandType::ClearBufferiv,
371 static_cast<GLbitfield>(0u), buffer, drawbuffer,
372 reinterpret_cast<const uint8_t *>(values), 0.0f, 0);
Martin Radevb0761932017-07-25 17:42:25 +0300373 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400374
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500375 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500376}
377
Jamie Madillc564c072017-06-01 12:45:42 -0400378Error FramebufferGL::clearBufferfi(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500379 GLenum buffer,
380 GLint drawbuffer,
381 GLfloat depth,
382 GLint stencil)
Geoff Langf9a6f082015-01-22 13:32:49 -0500383{
Frank Henigman308d7452017-02-15 22:51:21 -0500384 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400385 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300386
Martin Radev61e710b2017-09-05 11:59:52 +0300387 if (!RequiresMultiviewClear(mState, context->getGLState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300388 {
389 mFunctions->clearBufferfi(buffer, drawbuffer, depth, stencil);
390 }
Martin Radev5e424fa2017-08-09 16:25:36 +0300391 else
392 {
393 mMultiviewClearer->clearMultiviewFBO(mState, context->getGLState().getScissor(),
394 ClearMultiviewGL::ClearCommandType::ClearBufferfi,
395 static_cast<GLbitfield>(0u), buffer, drawbuffer,
396 nullptr, depth, stencil);
397 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400398
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500399 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500400}
401
Jamie Madill4928b7c2017-06-20 12:57:39 -0400402GLenum FramebufferGL::getImplementationColorReadFormat(const gl::Context *context) const
Geoff Langf9a6f082015-01-22 13:32:49 -0500403{
Jamie Madilla3944d42016-07-22 22:13:26 -0400404 const auto *readAttachment = mState.getReadAttachment();
405 const Format &format = readAttachment->getFormat();
Geoff Langf607c602016-09-21 11:46:48 -0400406 return format.info->getReadPixelsFormat();
Geoff Langf9a6f082015-01-22 13:32:49 -0500407}
408
Jamie Madill4928b7c2017-06-20 12:57:39 -0400409GLenum FramebufferGL::getImplementationColorReadType(const gl::Context *context) const
Geoff Langf9a6f082015-01-22 13:32:49 -0500410{
Jamie Madilla3944d42016-07-22 22:13:26 -0400411 const auto *readAttachment = mState.getReadAttachment();
412 const Format &format = readAttachment->getFormat();
Geoff Langf607c602016-09-21 11:46:48 -0400413 return format.info->getReadPixelsType();
Geoff Langf9a6f082015-01-22 13:32:49 -0500414}
415
Jamie Madillc564c072017-06-01 12:45:42 -0400416Error FramebufferGL::readPixels(const gl::Context *context,
Frank Henigmanfa36c332017-06-09 18:44:45 -0400417 const gl::Rectangle &origArea,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500418 GLenum format,
419 GLenum type,
Frank Henigmanfa36c332017-06-09 18:44:45 -0400420 void *ptrOrOffset) const
Geoff Langf9a6f082015-01-22 13:32:49 -0500421{
Frank Henigmanfa36c332017-06-09 18:44:45 -0400422 // Clip read area to framebuffer.
423 const gl::Extents fbSize = getState().getReadAttachment()->getSize();
424 const gl::Rectangle fbRect(0, 0, fbSize.width, fbSize.height);
425 gl::Rectangle area;
426 if (!ClipRectangle(origArea, fbRect, &area))
427 {
428 // nothing to read
429 return gl::NoError();
430 }
431
432 PixelPackState packState;
433 packState.copyFrom(context, context->getGLState().getPackState());
Jamie Madill87de3622015-03-16 10:41:44 -0400434
Geoff Langf607c602016-09-21 11:46:48 -0400435 nativegl::ReadPixelsFormat readPixelsFormat =
436 nativegl::GetReadPixelsFormat(mFunctions, mWorkarounds, format, type);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400437 GLenum readFormat = readPixelsFormat.format;
438 GLenum readType = readPixelsFormat.type;
Geoff Lang4ad17092015-03-10 16:47:44 -0400439
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400440 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, mFramebufferID);
441
Frank Henigmanfa36c332017-06-09 18:44:45 -0400442 bool useOverlappingRowsWorkaround = mWorkarounds.packOverlappingRowsSeparatelyPackBuffer &&
443 packState.pixelBuffer.get() && packState.rowLength != 0 &&
444 packState.rowLength < area.width;
445
446 GLubyte *pixels = reinterpret_cast<GLubyte *>(ptrOrOffset);
447 int leftClip = area.x - origArea.x;
448 int topClip = area.y - origArea.y;
449 if (leftClip || topClip)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400450 {
Frank Henigmanfa36c332017-06-09 18:44:45 -0400451 // Adjust destination to match portion clipped off left and/or top.
452 const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(readFormat, readType);
453
454 GLuint rowBytes = 0;
455 ANGLE_TRY_RESULT(glFormat.computeRowPitch(readType, origArea.width, packState.alignment,
456 packState.rowLength),
457 rowBytes);
458 pixels += leftClip * glFormat.pixelBytes + topClip * rowBytes;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400459 }
460
Frank Henigmanfa36c332017-06-09 18:44:45 -0400461 if (packState.rowLength == 0 && area.width != origArea.width)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400462 {
Frank Henigmanfa36c332017-06-09 18:44:45 -0400463 // No rowLength was specified so it will derive from read width, but clipping changed the
464 // read width. Use the original width so we fill the user's buffer as they intended.
465 packState.rowLength = origArea.width;
466 }
Corentin Wallez886de362016-09-27 10:49:35 -0400467
Frank Henigmanfa36c332017-06-09 18:44:45 -0400468 // We want to use rowLength, but that might not be supported.
469 bool cannotSetDesiredRowLength =
470 packState.rowLength && !GetImplAs<ContextGL>(context)->getNativeExtensions().packSubimage;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400471
Frank Henigmanfa36c332017-06-09 18:44:45 -0400472 gl::Error retVal = gl::NoError();
473 if (cannotSetDesiredRowLength || useOverlappingRowsWorkaround)
474 {
475 retVal = readPixelsRowByRow(context, area, readFormat, readType, packState, pixels);
476 }
477 else
478 {
479 gl::ErrorOrResult<bool> useLastRowPaddingWorkaround = false;
480 if (mWorkarounds.packLastRowSeparatelyForPaddingInclusion)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400481 {
Frank Henigmanfa36c332017-06-09 18:44:45 -0400482 useLastRowPaddingWorkaround =
483 ShouldApplyLastRowPaddingWorkaround(gl::Extents(area.width, area.height, 1),
484 packState, readFormat, readType, false, pixels);
485 }
486
487 if (useLastRowPaddingWorkaround.isError())
488 {
489 retVal = useLastRowPaddingWorkaround.getError();
490 }
491 else
492 {
493 retVal = readPixelsAllAtOnce(context, area, readFormat, readType, packState, pixels,
494 useLastRowPaddingWorkaround.getResult());
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400495 }
496 }
497
Frank Henigmanfa36c332017-06-09 18:44:45 -0400498 packState.pixelBuffer.set(context, nullptr);
499 return retVal;
Geoff Langf9a6f082015-01-22 13:32:49 -0500500}
501
Jamie Madillc564c072017-06-01 12:45:42 -0400502Error FramebufferGL::blit(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500503 const gl::Rectangle &sourceArea,
504 const gl::Rectangle &destArea,
505 GLbitfield mask,
Jamie Madill8415b5f2016-04-26 13:41:39 -0400506 GLenum filter)
Geoff Langf9a6f082015-01-22 13:32:49 -0500507{
Jamie Madill231c7f52017-04-26 13:45:37 -0400508 const Framebuffer *sourceFramebuffer = context->getGLState().getReadFramebuffer();
509 const Framebuffer *destFramebuffer = context->getGLState().getDrawFramebuffer();
Geoff Lang4ad17092015-03-10 16:47:44 -0400510
Corentin Wallez6898b352016-11-10 11:41:15 -0500511 const FramebufferAttachment *colorReadAttachment = sourceFramebuffer->getReadColorbuffer();
Corentin Wallez4596a762016-12-20 14:50:18 -0500512
513 GLsizei readAttachmentSamples = 0;
514 if (colorReadAttachment != nullptr)
515 {
516 readAttachmentSamples = colorReadAttachment->getSamples();
517 }
Corentin Wallez6898b352016-11-10 11:41:15 -0500518
Corentin Wallez26a717b2016-09-27 08:45:42 -0700519 bool needManualColorBlit = false;
520
Corentin Wallez6898b352016-11-10 11:41:15 -0500521 // TODO(cwallez) when the filter is LINEAR and both source and destination are SRGB, we
522 // could avoid doing a manual blit.
523
524 // Prior to OpenGL 4.4 BlitFramebuffer (section 18.3.1 of GL 4.3 core profile) reads:
525 // When values are taken from the read buffer, no linearization is performed, even
526 // if the format of the buffer is SRGB.
527 // Starting from OpenGL 4.4 (section 18.3.1) it reads:
528 // When values are taken from the read buffer, if FRAMEBUFFER_SRGB is enabled and the
529 // value of FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING for the framebuffer attachment
530 // corresponding to the read buffer is SRGB, the red, green, and blue components are
531 // converted from the non-linear sRGB color space according [...].
Corentin Wallez26a717b2016-09-27 08:45:42 -0700532 {
Jamie Madill231c7f52017-04-26 13:45:37 -0400533 bool sourceSRGB =
534 colorReadAttachment != nullptr && colorReadAttachment->getColorEncoding() == GL_SRGB;
Corentin Wallez6898b352016-11-10 11:41:15 -0500535 needManualColorBlit =
536 needManualColorBlit || (sourceSRGB && mFunctions->isAtMostGL(gl::Version(4, 3)));
537 }
Corentin Wallez26a717b2016-09-27 08:45:42 -0700538
Corentin Wallez6898b352016-11-10 11:41:15 -0500539 // Prior to OpenGL 4.2 BlitFramebuffer (section 4.3.2 of GL 4.1 core profile) reads:
540 // Blit operations bypass the fragment pipeline. The only fragment operations which
541 // affect a blit are the pixel ownership test and scissor test.
542 // Starting from OpenGL 4.2 (section 4.3.2) it reads:
543 // When values are written to the draw buffers, blit operations bypass the fragment
544 // pipeline. The only fragment operations which affect a blit are the pixel ownership
545 // test, the scissor test and sRGB conversion.
546 if (!needManualColorBlit)
547 {
548 bool destSRGB = false;
549 for (size_t i = 0; i < destFramebuffer->getDrawbufferStateCount(); ++i)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700550 {
Corentin Wallez6898b352016-11-10 11:41:15 -0500551 const FramebufferAttachment *attachment = destFramebuffer->getDrawBuffer(i);
552 if (attachment && attachment->getColorEncoding() == GL_SRGB)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700553 {
Corentin Wallez6898b352016-11-10 11:41:15 -0500554 destSRGB = true;
555 break;
Corentin Wallez26a717b2016-09-27 08:45:42 -0700556 }
Corentin Wallez26a717b2016-09-27 08:45:42 -0700557 }
Corentin Wallez6898b352016-11-10 11:41:15 -0500558
559 needManualColorBlit =
560 needManualColorBlit || (destSRGB && mFunctions->isAtMostGL(gl::Version(4, 1)));
Corentin Wallez26a717b2016-09-27 08:45:42 -0700561 }
562
563 // Enable FRAMEBUFFER_SRGB if needed
Jamie Madill4928b7c2017-06-20 12:57:39 -0400564 mStateManager->setFramebufferSRGBEnabledForFramebuffer(context, true, this);
Corentin Wallez26a717b2016-09-27 08:45:42 -0700565
566 GLenum blitMask = mask;
Corentin Wallez6898b352016-11-10 11:41:15 -0500567 if (needManualColorBlit && (mask & GL_COLOR_BUFFER_BIT) && readAttachmentSamples <= 1)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700568 {
569 ANGLE_TRY(mBlitter->blitColorBufferWithShader(sourceFramebuffer, destFramebuffer,
570 sourceArea, destArea, filter));
571 blitMask &= ~GL_COLOR_BUFFER_BIT;
572 }
573
574 if (blitMask == 0)
575 {
576 return gl::NoError();
577 }
578
579 const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(sourceFramebuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400580 mStateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
581 mStateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferID);
582
Jamie Madill2da819e2015-12-03 15:53:19 -0500583 mFunctions->blitFramebuffer(sourceArea.x, sourceArea.y, sourceArea.x1(), sourceArea.y1(),
Corentin Wallez26a717b2016-09-27 08:45:42 -0700584 destArea.x, destArea.y, destArea.x1(), destArea.y1(), blitMask,
585 filter);
Geoff Lang4ad17092015-03-10 16:47:44 -0400586
Corentin Wallez26a717b2016-09-27 08:45:42 -0700587 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500588}
589
JiangYizhoubddc46b2016-12-09 09:50:51 +0800590gl::Error FramebufferGL::getSamplePosition(size_t index, GLfloat *xy) const
591{
592 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
593 mFunctions->getMultisamplefv(GL_SAMPLE_POSITION, static_cast<GLuint>(index), xy);
594 return gl::NoError();
595}
596
Jamie Madillcc86d642015-11-24 13:00:07 -0500597bool FramebufferGL::checkStatus() const
Geoff Langf9a6f082015-01-22 13:32:49 -0500598{
Geoff Lang4ad17092015-03-10 16:47:44 -0400599 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Jamie Madillcc86d642015-11-24 13:00:07 -0500600 GLenum status = mFunctions->checkFramebufferStatus(GL_FRAMEBUFFER);
601 if (status != GL_FRAMEBUFFER_COMPLETE)
602 {
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500603 WARN() << "GL framebuffer returned incomplete.";
Jamie Madillcc86d642015-11-24 13:00:07 -0500604 }
605 return (status == GL_FRAMEBUFFER_COMPLETE);
Geoff Lang4ad17092015-03-10 16:47:44 -0400606}
607
Jamie Madillc564c072017-06-01 12:45:42 -0400608void FramebufferGL::syncState(const gl::Context *context, const Framebuffer::DirtyBits &dirtyBits)
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500609{
610 // Don't need to sync state for the default FBO.
611 if (mIsDefault)
612 {
613 return;
614 }
615
616 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
617
Martin Radev7c2e6a92017-08-28 11:13:16 +0300618 // A pointer to one of the attachments for which the texture or the render buffer is not zero.
619 const FramebufferAttachment *attachment = nullptr;
Martin Radev878c8b12017-07-28 09:51:04 +0300620
Jamie Madill6de51852017-04-12 09:53:01 -0400621 for (auto dirtyBit : dirtyBits)
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500622 {
623 switch (dirtyBit)
624 {
625 case Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
Martin Radev7c2e6a92017-08-28 11:13:16 +0300626 {
627 const FramebufferAttachment *newAttachment = mState.getDepthAttachment();
628 BindFramebufferAttachment(mFunctions, GL_DEPTH_ATTACHMENT, newAttachment);
629 if (newAttachment)
630 {
631 attachment = newAttachment;
632 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500633 break;
Martin Radev7c2e6a92017-08-28 11:13:16 +0300634 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500635 case Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
Martin Radev7c2e6a92017-08-28 11:13:16 +0300636 {
637 const FramebufferAttachment *newAttachment = mState.getStencilAttachment();
638 BindFramebufferAttachment(mFunctions, GL_STENCIL_ATTACHMENT, newAttachment);
639 if (newAttachment)
640 {
641 attachment = newAttachment;
642 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500643 break;
Martin Radev7c2e6a92017-08-28 11:13:16 +0300644 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500645 case Framebuffer::DIRTY_BIT_DRAW_BUFFERS:
646 {
Jamie Madill48ef11b2016-04-27 15:21:52 -0400647 const auto &drawBuffers = mState.getDrawBufferStates();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500648 mFunctions->drawBuffers(static_cast<GLsizei>(drawBuffers.size()),
649 drawBuffers.data());
Corentin Walleze7557742017-06-01 13:09:57 -0400650 mAppliedEnabledDrawBuffers = mState.getEnabledDrawBuffers();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500651 break;
652 }
653 case Framebuffer::DIRTY_BIT_READ_BUFFER:
Jamie Madill48ef11b2016-04-27 15:21:52 -0400654 mFunctions->readBuffer(mState.getReadBufferState());
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500655 break;
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800656 case Framebuffer::DIRTY_BIT_DEFAULT_WIDTH:
657 mFunctions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH,
658 mState.getDefaultWidth());
659 break;
660 case Framebuffer::DIRTY_BIT_DEFAULT_HEIGHT:
661 mFunctions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT,
662 mState.getDefaultHeight());
663 break;
664 case Framebuffer::DIRTY_BIT_DEFAULT_SAMPLES:
665 mFunctions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_SAMPLES,
666 mState.getDefaultSamples());
667 break;
668 case Framebuffer::DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS:
669 mFunctions->framebufferParameteri(GL_FRAMEBUFFER,
670 GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS,
671 mState.getDefaultFixedSampleLocations());
672 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500673 default:
674 {
675 ASSERT(Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0 &&
676 dirtyBit < Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX);
677 size_t index =
678 static_cast<size_t>(dirtyBit - Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
Martin Radev7c2e6a92017-08-28 11:13:16 +0300679 const FramebufferAttachment *newAttachment = mState.getColorAttachment(index);
680 BindFramebufferAttachment(
681 mFunctions, static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + index), newAttachment);
682 if (newAttachment)
683 {
684 attachment = newAttachment;
685 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500686 break;
687 }
688 }
689 }
Martin Radev878c8b12017-07-28 09:51:04 +0300690
Martin Radev7c2e6a92017-08-28 11:13:16 +0300691 if (attachment)
Martin Radev878c8b12017-07-28 09:51:04 +0300692 {
Martin Radev7c2e6a92017-08-28 11:13:16 +0300693 const bool isSideBySide =
694 (attachment->getMultiviewLayout() == GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE);
Martin Radev878c8b12017-07-28 09:51:04 +0300695 mStateManager->setSideBySide(isSideBySide);
Martin Radev7c2e6a92017-08-28 11:13:16 +0300696 mStateManager->setViewportOffsets(attachment->getMultiviewViewportOffsets());
Martin Radev4e619f52017-08-09 11:50:06 +0300697 mStateManager->updateMultiviewBaseViewLayerIndexUniform(context->getGLState().getProgram(),
698 getState());
Martin Radev878c8b12017-07-28 09:51:04 +0300699 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500700}
701
Geoff Lang4ad17092015-03-10 16:47:44 -0400702GLuint FramebufferGL::getFramebufferID() const
703{
704 return mFramebufferID;
Geoff Langf9a6f082015-01-22 13:32:49 -0500705}
706
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700707bool FramebufferGL::isDefault() const
Geoff Langafd7f0a2015-09-09 15:33:31 -0400708{
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700709 return mIsDefault;
Geoff Langafd7f0a2015-09-09 15:33:31 -0400710}
711
Corentin Walleze7557742017-06-01 13:09:57 -0400712void FramebufferGL::maskOutInactiveOutputDrawBuffers(DrawBufferMask maxSet)
713{
714 auto targetAppliedDrawBuffers = mState.getEnabledDrawBuffers() & maxSet;
715 if (mAppliedEnabledDrawBuffers != targetAppliedDrawBuffers)
716 {
717 mAppliedEnabledDrawBuffers = targetAppliedDrawBuffers;
718
719 const auto &stateDrawBuffers = mState.getDrawBufferStates();
720 GLsizei drawBufferCount = static_cast<GLsizei>(stateDrawBuffers.size());
721 ASSERT(drawBufferCount <= IMPLEMENTATION_MAX_DRAW_BUFFERS);
722
723 GLenum drawBuffers[IMPLEMENTATION_MAX_DRAW_BUFFERS];
724 for (GLenum i = 0; static_cast<int>(i) < drawBufferCount; ++i)
725 {
726 drawBuffers[i] = targetAppliedDrawBuffers[i] ? stateDrawBuffers[i] : GL_NONE;
727 }
728
729 mStateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
730 mFunctions->drawBuffers(drawBufferCount, drawBuffers);
731 }
732}
733
Jamie Madillc564c072017-06-01 12:45:42 -0400734void FramebufferGL::syncClearState(const gl::Context *context, GLbitfield mask)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400735{
Frank Henigmana3d333c2016-03-22 22:09:14 -0400736 if (mFunctions->standard == STANDARD_GL_DESKTOP)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400737 {
Frank Henigmana3d333c2016-03-22 22:09:14 -0400738 if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments &&
739 (mask & GL_COLOR_BUFFER_BIT) != 0 && !mIsDefault)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400740 {
Corentin Wallez26a717b2016-09-27 08:45:42 -0700741 bool hasSRGBAttachment = false;
Jamie Madill48ef11b2016-04-27 15:21:52 -0400742 for (const auto &attachment : mState.getColorAttachments())
Geoff Langafd7f0a2015-09-09 15:33:31 -0400743 {
Frank Henigmana3d333c2016-03-22 22:09:14 -0400744 if (attachment.isAttached() && attachment.getColorEncoding() == GL_SRGB)
745 {
Corentin Wallez26a717b2016-09-27 08:45:42 -0700746 hasSRGBAttachment = true;
Frank Henigmana3d333c2016-03-22 22:09:14 -0400747 break;
748 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400749 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400750
Jamie Madill4928b7c2017-06-20 12:57:39 -0400751 mStateManager->setFramebufferSRGBEnabled(context, hasSRGBAttachment);
Frank Henigmana3d333c2016-03-22 22:09:14 -0400752 }
753 else
754 {
Jamie Madill4928b7c2017-06-20 12:57:39 -0400755 mStateManager->setFramebufferSRGBEnabled(context, !mIsDefault);
Frank Henigmana3d333c2016-03-22 22:09:14 -0400756 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400757 }
758}
759
Jamie Madillc564c072017-06-01 12:45:42 -0400760void FramebufferGL::syncClearBufferState(const gl::Context *context,
761 GLenum buffer,
762 GLint drawBuffer)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400763{
764 if (mFunctions->standard == STANDARD_GL_DESKTOP)
765 {
766 if (mWorkarounds.doesSRGBClearsOnLinearFramebufferAttachments && buffer == GL_COLOR &&
767 !mIsDefault)
768 {
769 // If doing a clear on a color buffer, set SRGB blend enabled only if the color buffer
770 // is an SRGB format.
Jamie Madill48ef11b2016-04-27 15:21:52 -0400771 const auto &drawbufferState = mState.getDrawBufferStates();
772 const auto &colorAttachments = mState.getColorAttachments();
Geoff Langafd7f0a2015-09-09 15:33:31 -0400773
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500774 const FramebufferAttachment *attachment = nullptr;
Geoff Langafd7f0a2015-09-09 15:33:31 -0400775 if (drawbufferState[drawBuffer] >= GL_COLOR_ATTACHMENT0 &&
776 drawbufferState[drawBuffer] < GL_COLOR_ATTACHMENT0 + colorAttachments.size())
777 {
778 size_t attachmentIdx =
779 static_cast<size_t>(drawbufferState[drawBuffer] - GL_COLOR_ATTACHMENT0);
780 attachment = &colorAttachments[attachmentIdx];
781 }
782
783 if (attachment != nullptr)
784 {
Jamie Madill4928b7c2017-06-20 12:57:39 -0400785 mStateManager->setFramebufferSRGBEnabled(context,
Frank Henigman308d7452017-02-15 22:51:21 -0500786 attachment->getColorEncoding() == GL_SRGB);
Geoff Langafd7f0a2015-09-09 15:33:31 -0400787 }
788 }
789 else
790 {
Jamie Madill4928b7c2017-06-20 12:57:39 -0400791 mStateManager->setFramebufferSRGBEnabled(context, !mIsDefault);
Geoff Langafd7f0a2015-09-09 15:33:31 -0400792 }
793 }
794}
Geoff Lang005a7012017-03-27 13:17:34 -0400795
796bool FramebufferGL::modifyInvalidateAttachmentsForEmulatedDefaultFBO(
797 size_t count,
798 const GLenum *attachments,
799 std::vector<GLenum> *modifiedAttachments) const
800{
801 bool needsModification = mIsDefault && mFramebufferID != 0;
802 if (!needsModification)
803 {
804 return false;
805 }
806
807 modifiedAttachments->resize(count);
808 for (size_t i = 0; i < count; i++)
809 {
810 switch (attachments[i])
811 {
812 case GL_COLOR:
813 (*modifiedAttachments)[i] = GL_COLOR_ATTACHMENT0;
814 break;
815
816 case GL_DEPTH:
817 (*modifiedAttachments)[i] = GL_DEPTH_ATTACHMENT;
818 break;
819
820 case GL_STENCIL:
821 (*modifiedAttachments)[i] = GL_STENCIL_ATTACHMENT;
822 break;
823
824 default:
825 UNREACHABLE();
826 break;
827 }
828 }
829
830 return true;
831}
832
Frank Henigmanfa36c332017-06-09 18:44:45 -0400833gl::Error FramebufferGL::readPixelsRowByRow(const gl::Context *context,
834 const gl::Rectangle &area,
835 GLenum format,
836 GLenum type,
837 const gl::PixelPackState &pack,
838 GLubyte *pixels) const
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400839{
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400840
Geoff Langca271392017-04-05 12:30:00 -0400841 const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(format, type);
Frank Henigmanfa36c332017-06-09 18:44:45 -0400842
843 GLuint rowBytes = 0;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400844 ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
845 rowBytes);
846 GLuint skipBytes = 0;
Corentin Wallez886de362016-09-27 10:49:35 -0400847 ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400848
849 gl::PixelPackState directPack;
Jamie Madill4928b7c2017-06-20 12:57:39 -0400850 directPack.pixelBuffer.set(context, pack.pixelBuffer.get());
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400851 directPack.alignment = 1;
852 mStateManager->setPixelPackState(directPack);
Jamie Madill4928b7c2017-06-20 12:57:39 -0400853 directPack.pixelBuffer.set(context, nullptr);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400854
Frank Henigmanfa36c332017-06-09 18:44:45 -0400855 pixels += skipBytes;
856 for (GLint y = area.y; y < area.y + area.height; ++y)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400857 {
Frank Henigmanfa36c332017-06-09 18:44:45 -0400858 mFunctions->readPixels(area.x, y, area.width, 1, format, type, pixels);
859 pixels += rowBytes;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400860 }
861
862 return gl::NoError();
863}
864
Frank Henigmanfa36c332017-06-09 18:44:45 -0400865gl::Error FramebufferGL::readPixelsAllAtOnce(const gl::Context *context,
866 const gl::Rectangle &area,
867 GLenum format,
868 GLenum type,
869 const gl::PixelPackState &pack,
870 GLubyte *pixels,
871 bool readLastRowSeparately) const
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400872{
Frank Henigmanfa36c332017-06-09 18:44:45 -0400873 GLint height = area.height - readLastRowSeparately;
874 if (height > 0)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400875 {
Frank Henigmanfa36c332017-06-09 18:44:45 -0400876 mStateManager->setPixelPackState(pack);
877 mFunctions->readPixels(area.x, area.y, area.width, height, format, type, pixels);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400878 }
879
Frank Henigmanfa36c332017-06-09 18:44:45 -0400880 if (readLastRowSeparately)
881 {
882 const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(format, type);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400883
Frank Henigmanfa36c332017-06-09 18:44:45 -0400884 GLuint rowBytes = 0;
885 ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
886 rowBytes);
887 GLuint skipBytes = 0;
888 ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
889
890 gl::PixelPackState directPack;
891 directPack.pixelBuffer.set(context, pack.pixelBuffer.get());
892 directPack.alignment = 1;
893 mStateManager->setPixelPackState(directPack);
894 directPack.pixelBuffer.set(context, nullptr);
895
896 pixels += skipBytes + (area.height - 1) * rowBytes;
897 mFunctions->readPixels(area.x, area.y + area.height - 1, area.width, 1, format, type,
898 pixels);
899 }
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400900
901 return gl::NoError();
902}
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500903} // namespace rx