blob: 03be38be9e82098c34e2056edc1a932be60c6290 [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
Geoff Lang61107632018-05-09 11:32:46 -0400183FramebufferGL::FramebufferGL(const gl::FramebufferState &data, GLuint id, bool isDefault)
184 : FramebufferImpl(data),
Martin Radev878c8b12017-07-28 09:51:04 +0300185 mFramebufferID(id),
Geoff Lang61107632018-05-09 11:32:46 -0400186 mIsDefault(isDefault),
Martin Radev878c8b12017-07-28 09:51:04 +0300187 mAppliedEnabledDrawBuffers(1)
188{
189}
190
191FramebufferGL::~FramebufferGL()
192{
Geoff Lang61107632018-05-09 11:32:46 -0400193 ASSERT(mFramebufferID == 0);
194}
195
196void FramebufferGL::destroy(const gl::Context *context)
197{
198 StateManagerGL *stateManager = GetStateManagerGL(context);
199 stateManager->deleteFramebuffer(mFramebufferID);
Martin Radev878c8b12017-07-28 09:51:04 +0300200 mFramebufferID = 0;
201}
202
Jamie Madill4928b7c2017-06-20 12:57:39 -0400203Error FramebufferGL::discard(const gl::Context *context, size_t count, const GLenum *attachments)
Austin Kinross08332632015-05-05 13:35:47 -0700204{
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500205 // glInvalidateFramebuffer accepts the same enums as glDiscardFramebufferEXT
Jamie Madill4928b7c2017-06-20 12:57:39 -0400206 return invalidate(context, count, attachments);
Austin Kinross08332632015-05-05 13:35:47 -0700207}
208
Jamie Madill4928b7c2017-06-20 12:57:39 -0400209Error FramebufferGL::invalidate(const gl::Context *context, size_t count, const GLenum *attachments)
Geoff Langf9a6f082015-01-22 13:32:49 -0500210{
Geoff Lang005a7012017-03-27 13:17:34 -0400211 const GLenum *finalAttachmentsPtr = attachments;
212
213 std::vector<GLenum> modifiedAttachments;
214 if (modifyInvalidateAttachmentsForEmulatedDefaultFBO(count, attachments, &modifiedAttachments))
215 {
216 finalAttachmentsPtr = modifiedAttachments.data();
217 }
218
Geoff Lang61107632018-05-09 11:32:46 -0400219 const FunctionsGL *functions = GetFunctionsGL(context);
220 StateManagerGL *stateManager = GetStateManagerGL(context);
221
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500222 // Since this function is just a hint, only call a native function if it exists.
Geoff Lang61107632018-05-09 11:32:46 -0400223 if (functions->invalidateFramebuffer)
Geoff Lang64a72442015-04-01 14:43:11 -0400224 {
Geoff Lang61107632018-05-09 11:32:46 -0400225 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
226 functions->invalidateFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
227 finalAttachmentsPtr);
Geoff Lang64a72442015-04-01 14:43:11 -0400228 }
Geoff Lang61107632018-05-09 11:32:46 -0400229 else if (functions->discardFramebufferEXT)
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500230 {
Geoff Lang61107632018-05-09 11:32:46 -0400231 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
232 functions->discardFramebufferEXT(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
233 finalAttachmentsPtr);
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500234 }
Geoff Lang64a72442015-04-01 14:43:11 -0400235
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500236 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500237}
238
Jamie Madill4928b7c2017-06-20 12:57:39 -0400239Error FramebufferGL::invalidateSub(const gl::Context *context,
240 size_t count,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500241 const GLenum *attachments,
242 const gl::Rectangle &area)
Geoff Langf9a6f082015-01-22 13:32:49 -0500243{
Geoff Lang005a7012017-03-27 13:17:34 -0400244
245 const GLenum *finalAttachmentsPtr = attachments;
246
247 std::vector<GLenum> modifiedAttachments;
248 if (modifyInvalidateAttachmentsForEmulatedDefaultFBO(count, attachments, &modifiedAttachments))
249 {
250 finalAttachmentsPtr = modifiedAttachments.data();
251 }
252
Geoff Lang61107632018-05-09 11:32:46 -0400253 const FunctionsGL *functions = GetFunctionsGL(context);
254 StateManagerGL *stateManager = GetStateManagerGL(context);
255
Jamie Madill231c7f52017-04-26 13:45:37 -0400256 // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is
257 // available.
Geoff Lang61107632018-05-09 11:32:46 -0400258 if (functions->invalidateSubFramebuffer)
Geoff Lang64a72442015-04-01 14:43:11 -0400259 {
Geoff Lang61107632018-05-09 11:32:46 -0400260 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
261 functions->invalidateSubFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
262 finalAttachmentsPtr, area.x, area.y, area.width,
263 area.height);
Geoff Lang64a72442015-04-01 14:43:11 -0400264 }
265
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500266 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500267}
268
Jamie Madillc564c072017-06-01 12:45:42 -0400269Error FramebufferGL::clear(const gl::Context *context, GLbitfield mask)
Geoff Langf9a6f082015-01-22 13:32:49 -0500270{
Geoff Lang61107632018-05-09 11:32:46 -0400271 const FunctionsGL *functions = GetFunctionsGL(context);
272 StateManagerGL *stateManager = GetStateManagerGL(context);
273
Frank Henigman308d7452017-02-15 22:51:21 -0500274 syncClearState(context, mask);
Geoff Lang61107632018-05-09 11:32:46 -0400275 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300276
Martin Radev61e710b2017-09-05 11:59:52 +0300277 if (!RequiresMultiviewClear(mState, context->getGLState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300278 {
Geoff Lang61107632018-05-09 11:32:46 -0400279 functions->clear(mask);
Martin Radevb0761932017-07-25 17:42:25 +0300280 }
281 else
282 {
Geoff Lang61107632018-05-09 11:32:46 -0400283 ClearMultiviewGL *multiviewClearer = GetMultiviewClearer(context);
284 multiviewClearer->clearMultiviewFBO(mState, context->getGLState().getScissor(),
285 ClearMultiviewGL::ClearCommandType::Clear, mask,
286 GL_NONE, 0, nullptr, 0.0f, 0);
Martin Radevb0761932017-07-25 17:42:25 +0300287 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400288
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500289 return gl::NoError();
Geoff Lang4ad17092015-03-10 16:47:44 -0400290}
291
Jamie Madillc564c072017-06-01 12:45:42 -0400292Error FramebufferGL::clearBufferfv(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500293 GLenum buffer,
294 GLint drawbuffer,
295 const GLfloat *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500296{
Geoff Lang61107632018-05-09 11:32:46 -0400297 const FunctionsGL *functions = GetFunctionsGL(context);
298 StateManagerGL *stateManager = GetStateManagerGL(context);
299
Frank Henigman308d7452017-02-15 22:51:21 -0500300 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang61107632018-05-09 11:32:46 -0400301 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300302
Martin Radev61e710b2017-09-05 11:59:52 +0300303 if (!RequiresMultiviewClear(mState, context->getGLState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300304 {
Geoff Lang61107632018-05-09 11:32:46 -0400305 functions->clearBufferfv(buffer, drawbuffer, values);
Martin Radevb0761932017-07-25 17:42:25 +0300306 }
307 else
308 {
Geoff Lang61107632018-05-09 11:32:46 -0400309 ClearMultiviewGL *multiviewClearer = GetMultiviewClearer(context);
310 multiviewClearer->clearMultiviewFBO(mState, context->getGLState().getScissor(),
311 ClearMultiviewGL::ClearCommandType::ClearBufferfv,
312 static_cast<GLbitfield>(0u), buffer, drawbuffer,
313 reinterpret_cast<const uint8_t *>(values), 0.0f, 0);
Martin Radevb0761932017-07-25 17:42:25 +0300314 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400315
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500316 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500317}
318
Jamie Madillc564c072017-06-01 12:45:42 -0400319Error FramebufferGL::clearBufferuiv(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500320 GLenum buffer,
321 GLint drawbuffer,
322 const GLuint *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500323{
Geoff Lang61107632018-05-09 11:32:46 -0400324 const FunctionsGL *functions = GetFunctionsGL(context);
325 StateManagerGL *stateManager = GetStateManagerGL(context);
326
Frank Henigman308d7452017-02-15 22:51:21 -0500327 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang61107632018-05-09 11:32:46 -0400328 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300329
Martin Radev61e710b2017-09-05 11:59:52 +0300330 if (!RequiresMultiviewClear(mState, context->getGLState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300331 {
Geoff Lang61107632018-05-09 11:32:46 -0400332 functions->clearBufferuiv(buffer, drawbuffer, values);
Martin Radevb0761932017-07-25 17:42:25 +0300333 }
334 else
335 {
Geoff Lang61107632018-05-09 11:32:46 -0400336 ClearMultiviewGL *multiviewClearer = GetMultiviewClearer(context);
337 multiviewClearer->clearMultiviewFBO(mState, context->getGLState().getScissor(),
338 ClearMultiviewGL::ClearCommandType::ClearBufferuiv,
339 static_cast<GLbitfield>(0u), buffer, drawbuffer,
340 reinterpret_cast<const uint8_t *>(values), 0.0f, 0);
Martin Radevb0761932017-07-25 17:42:25 +0300341 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400342
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500343 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500344}
345
Jamie Madillc564c072017-06-01 12:45:42 -0400346Error FramebufferGL::clearBufferiv(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500347 GLenum buffer,
348 GLint drawbuffer,
349 const GLint *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500350{
Geoff Lang61107632018-05-09 11:32:46 -0400351 const FunctionsGL *functions = GetFunctionsGL(context);
352 StateManagerGL *stateManager = GetStateManagerGL(context);
353
Frank Henigman308d7452017-02-15 22:51:21 -0500354 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang61107632018-05-09 11:32:46 -0400355 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300356
Martin Radev61e710b2017-09-05 11:59:52 +0300357 if (!RequiresMultiviewClear(mState, context->getGLState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300358 {
Geoff Lang61107632018-05-09 11:32:46 -0400359 functions->clearBufferiv(buffer, drawbuffer, values);
Martin Radevb0761932017-07-25 17:42:25 +0300360 }
361 else
362 {
Geoff Lang61107632018-05-09 11:32:46 -0400363 ClearMultiviewGL *multiviewClearer = GetMultiviewClearer(context);
364 multiviewClearer->clearMultiviewFBO(mState, context->getGLState().getScissor(),
365 ClearMultiviewGL::ClearCommandType::ClearBufferiv,
366 static_cast<GLbitfield>(0u), buffer, drawbuffer,
367 reinterpret_cast<const uint8_t *>(values), 0.0f, 0);
Martin Radevb0761932017-07-25 17:42:25 +0300368 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400369
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500370 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500371}
372
Jamie Madillc564c072017-06-01 12:45:42 -0400373Error FramebufferGL::clearBufferfi(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500374 GLenum buffer,
375 GLint drawbuffer,
376 GLfloat depth,
377 GLint stencil)
Geoff Langf9a6f082015-01-22 13:32:49 -0500378{
Geoff Lang61107632018-05-09 11:32:46 -0400379 const FunctionsGL *functions = GetFunctionsGL(context);
380 StateManagerGL *stateManager = GetStateManagerGL(context);
381
Frank Henigman308d7452017-02-15 22:51:21 -0500382 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang61107632018-05-09 11:32:46 -0400383 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300384
Martin Radev61e710b2017-09-05 11:59:52 +0300385 if (!RequiresMultiviewClear(mState, context->getGLState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300386 {
Geoff Lang61107632018-05-09 11:32:46 -0400387 functions->clearBufferfi(buffer, drawbuffer, depth, stencil);
Martin Radevb0761932017-07-25 17:42:25 +0300388 }
Martin Radev5e424fa2017-08-09 16:25:36 +0300389 else
390 {
Geoff Lang61107632018-05-09 11:32:46 -0400391 ClearMultiviewGL *multiviewClearer = GetMultiviewClearer(context);
392 multiviewClearer->clearMultiviewFBO(mState, context->getGLState().getScissor(),
393 ClearMultiviewGL::ClearCommandType::ClearBufferfi,
394 static_cast<GLbitfield>(0u), buffer, drawbuffer,
395 nullptr, depth, stencil);
Martin Radev5e424fa2017-08-09 16:25:36 +0300396 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400397
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500398 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500399}
400
Jamie Madill4928b7c2017-06-20 12:57:39 -0400401GLenum FramebufferGL::getImplementationColorReadFormat(const gl::Context *context) const
Geoff Langf9a6f082015-01-22 13:32:49 -0500402{
Jamie Madilla3944d42016-07-22 22:13:26 -0400403 const auto *readAttachment = mState.getReadAttachment();
404 const Format &format = readAttachment->getFormat();
Geoff Langf607c602016-09-21 11:46:48 -0400405 return format.info->getReadPixelsFormat();
Geoff Langf9a6f082015-01-22 13:32:49 -0500406}
407
Jamie Madill4928b7c2017-06-20 12:57:39 -0400408GLenum FramebufferGL::getImplementationColorReadType(const gl::Context *context) const
Geoff Langf9a6f082015-01-22 13:32:49 -0500409{
Jamie Madilla3944d42016-07-22 22:13:26 -0400410 const auto *readAttachment = mState.getReadAttachment();
411 const Format &format = readAttachment->getFormat();
Geoff Langc71ea662017-09-26 17:06:02 -0400412 return format.info->getReadPixelsType(context->getClientVersion());
Geoff Langf9a6f082015-01-22 13:32:49 -0500413}
414
Jamie Madillc564c072017-06-01 12:45:42 -0400415Error FramebufferGL::readPixels(const gl::Context *context,
Frank Henigmanfa36c332017-06-09 18:44:45 -0400416 const gl::Rectangle &origArea,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500417 GLenum format,
418 GLenum type,
Jamie Madilld4826152017-09-21 11:18:59 -0400419 void *ptrOrOffset)
Geoff Langf9a6f082015-01-22 13:32:49 -0500420{
Geoff Lang61107632018-05-09 11:32:46 -0400421 const FunctionsGL *functions = GetFunctionsGL(context);
422 StateManagerGL *stateManager = GetStateManagerGL(context);
423 const WorkaroundsGL &workarounds = GetWorkaroundsGL(context);
424
Frank Henigmanfa36c332017-06-09 18:44:45 -0400425 // Clip read area to framebuffer.
426 const gl::Extents fbSize = getState().getReadAttachment()->getSize();
427 const gl::Rectangle fbRect(0, 0, fbSize.width, fbSize.height);
428 gl::Rectangle area;
429 if (!ClipRectangle(origArea, fbRect, &area))
430 {
431 // nothing to read
432 return gl::NoError();
433 }
434
Corentin Wallezcda6af12017-10-30 19:20:37 -0400435 PixelPackState packState = context->getGLState().getPackState();
Corentin Wallez336129f2017-10-17 15:55:40 -0400436 const gl::Buffer *packBuffer =
437 context->getGLState().getTargetBuffer(gl::BufferBinding::PixelPack);
Jamie Madill87de3622015-03-16 10:41:44 -0400438
Geoff Langf607c602016-09-21 11:46:48 -0400439 nativegl::ReadPixelsFormat readPixelsFormat =
Geoff Lang61107632018-05-09 11:32:46 -0400440 nativegl::GetReadPixelsFormat(functions, workarounds, format, type);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400441 GLenum readFormat = readPixelsFormat.format;
442 GLenum readType = readPixelsFormat.type;
Geoff Lang4ad17092015-03-10 16:47:44 -0400443
Geoff Lang61107632018-05-09 11:32:46 -0400444 stateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, mFramebufferID);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400445
Geoff Lang61107632018-05-09 11:32:46 -0400446 bool useOverlappingRowsWorkaround = workarounds.packOverlappingRowsSeparatelyPackBuffer &&
Corentin Wallezcda6af12017-10-30 19:20:37 -0400447 packBuffer && packState.rowLength != 0 &&
Frank Henigmanfa36c332017-06-09 18:44:45 -0400448 packState.rowLength < area.width;
449
450 GLubyte *pixels = reinterpret_cast<GLubyte *>(ptrOrOffset);
451 int leftClip = area.x - origArea.x;
452 int topClip = area.y - origArea.y;
453 if (leftClip || topClip)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400454 {
Frank Henigmanfa36c332017-06-09 18:44:45 -0400455 // Adjust destination to match portion clipped off left and/or top.
456 const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(readFormat, readType);
457
458 GLuint rowBytes = 0;
459 ANGLE_TRY_RESULT(glFormat.computeRowPitch(readType, origArea.width, packState.alignment,
460 packState.rowLength),
461 rowBytes);
462 pixels += leftClip * glFormat.pixelBytes + topClip * rowBytes;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400463 }
464
Frank Henigmanfa36c332017-06-09 18:44:45 -0400465 if (packState.rowLength == 0 && area.width != origArea.width)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400466 {
Frank Henigmanfa36c332017-06-09 18:44:45 -0400467 // No rowLength was specified so it will derive from read width, but clipping changed the
468 // read width. Use the original width so we fill the user's buffer as they intended.
469 packState.rowLength = origArea.width;
470 }
Corentin Wallez886de362016-09-27 10:49:35 -0400471
Frank Henigmanfa36c332017-06-09 18:44:45 -0400472 // We want to use rowLength, but that might not be supported.
473 bool cannotSetDesiredRowLength =
474 packState.rowLength && !GetImplAs<ContextGL>(context)->getNativeExtensions().packSubimage;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400475
Frank Henigmanfa36c332017-06-09 18:44:45 -0400476 gl::Error retVal = gl::NoError();
477 if (cannotSetDesiredRowLength || useOverlappingRowsWorkaround)
478 {
479 retVal = readPixelsRowByRow(context, area, readFormat, readType, packState, pixels);
480 }
481 else
482 {
483 gl::ErrorOrResult<bool> useLastRowPaddingWorkaround = false;
Geoff Lang61107632018-05-09 11:32:46 -0400484 if (workarounds.packLastRowSeparatelyForPaddingInclusion)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400485 {
Corentin Wallezcda6af12017-10-30 19:20:37 -0400486 useLastRowPaddingWorkaround = ShouldApplyLastRowPaddingWorkaround(
487 gl::Extents(area.width, area.height, 1), packState, packBuffer, readFormat,
488 readType, false, pixels);
Frank Henigmanfa36c332017-06-09 18:44:45 -0400489 }
490
491 if (useLastRowPaddingWorkaround.isError())
492 {
493 retVal = useLastRowPaddingWorkaround.getError();
494 }
495 else
496 {
497 retVal = readPixelsAllAtOnce(context, area, readFormat, readType, packState, pixels,
498 useLastRowPaddingWorkaround.getResult());
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400499 }
500 }
501
Frank Henigmanfa36c332017-06-09 18:44:45 -0400502 return retVal;
Geoff Langf9a6f082015-01-22 13:32:49 -0500503}
504
Jamie Madillc564c072017-06-01 12:45:42 -0400505Error FramebufferGL::blit(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500506 const gl::Rectangle &sourceArea,
507 const gl::Rectangle &destArea,
508 GLbitfield mask,
Jamie Madill8415b5f2016-04-26 13:41:39 -0400509 GLenum filter)
Geoff Langf9a6f082015-01-22 13:32:49 -0500510{
Geoff Lang61107632018-05-09 11:32:46 -0400511 const FunctionsGL *functions = GetFunctionsGL(context);
512 StateManagerGL *stateManager = GetStateManagerGL(context);
513
Jamie Madill231c7f52017-04-26 13:45:37 -0400514 const Framebuffer *sourceFramebuffer = context->getGLState().getReadFramebuffer();
515 const Framebuffer *destFramebuffer = context->getGLState().getDrawFramebuffer();
Geoff Lang4ad17092015-03-10 16:47:44 -0400516
Corentin Wallez6898b352016-11-10 11:41:15 -0500517 const FramebufferAttachment *colorReadAttachment = sourceFramebuffer->getReadColorbuffer();
Corentin Wallez4596a762016-12-20 14:50:18 -0500518
519 GLsizei readAttachmentSamples = 0;
520 if (colorReadAttachment != nullptr)
521 {
522 readAttachmentSamples = colorReadAttachment->getSamples();
523 }
Corentin Wallez6898b352016-11-10 11:41:15 -0500524
Corentin Wallez26a717b2016-09-27 08:45:42 -0700525 bool needManualColorBlit = false;
526
Corentin Wallez6898b352016-11-10 11:41:15 -0500527 // TODO(cwallez) when the filter is LINEAR and both source and destination are SRGB, we
528 // could avoid doing a manual blit.
529
530 // Prior to OpenGL 4.4 BlitFramebuffer (section 18.3.1 of GL 4.3 core profile) reads:
531 // When values are taken from the read buffer, no linearization is performed, even
532 // if the format of the buffer is SRGB.
533 // Starting from OpenGL 4.4 (section 18.3.1) it reads:
534 // When values are taken from the read buffer, if FRAMEBUFFER_SRGB is enabled and the
535 // value of FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING for the framebuffer attachment
536 // corresponding to the read buffer is SRGB, the red, green, and blue components are
537 // converted from the non-linear sRGB color space according [...].
Corentin Wallez26a717b2016-09-27 08:45:42 -0700538 {
Jamie Madill231c7f52017-04-26 13:45:37 -0400539 bool sourceSRGB =
540 colorReadAttachment != nullptr && colorReadAttachment->getColorEncoding() == GL_SRGB;
Corentin Wallez6898b352016-11-10 11:41:15 -0500541 needManualColorBlit =
Geoff Lang61107632018-05-09 11:32:46 -0400542 needManualColorBlit || (sourceSRGB && functions->isAtMostGL(gl::Version(4, 3)));
Corentin Wallez6898b352016-11-10 11:41:15 -0500543 }
Corentin Wallez26a717b2016-09-27 08:45:42 -0700544
Corentin Wallez6898b352016-11-10 11:41:15 -0500545 // Prior to OpenGL 4.2 BlitFramebuffer (section 4.3.2 of GL 4.1 core profile) reads:
546 // Blit operations bypass the fragment pipeline. The only fragment operations which
547 // affect a blit are the pixel ownership test and scissor test.
548 // Starting from OpenGL 4.2 (section 4.3.2) it reads:
549 // When values are written to the draw buffers, blit operations bypass the fragment
550 // pipeline. The only fragment operations which affect a blit are the pixel ownership
551 // test, the scissor test and sRGB conversion.
552 if (!needManualColorBlit)
553 {
554 bool destSRGB = false;
555 for (size_t i = 0; i < destFramebuffer->getDrawbufferStateCount(); ++i)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700556 {
Corentin Wallez6898b352016-11-10 11:41:15 -0500557 const FramebufferAttachment *attachment = destFramebuffer->getDrawBuffer(i);
558 if (attachment && attachment->getColorEncoding() == GL_SRGB)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700559 {
Corentin Wallez6898b352016-11-10 11:41:15 -0500560 destSRGB = true;
561 break;
Corentin Wallez26a717b2016-09-27 08:45:42 -0700562 }
Corentin Wallez26a717b2016-09-27 08:45:42 -0700563 }
Corentin Wallez6898b352016-11-10 11:41:15 -0500564
565 needManualColorBlit =
Geoff Lang61107632018-05-09 11:32:46 -0400566 needManualColorBlit || (destSRGB && functions->isAtMostGL(gl::Version(4, 1)));
Corentin Wallez26a717b2016-09-27 08:45:42 -0700567 }
568
569 // Enable FRAMEBUFFER_SRGB if needed
Geoff Lang61107632018-05-09 11:32:46 -0400570 stateManager->setFramebufferSRGBEnabledForFramebuffer(context, true, this);
Corentin Wallez26a717b2016-09-27 08:45:42 -0700571
572 GLenum blitMask = mask;
Corentin Wallez6898b352016-11-10 11:41:15 -0500573 if (needManualColorBlit && (mask & GL_COLOR_BUFFER_BIT) && readAttachmentSamples <= 1)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700574 {
Geoff Lang61107632018-05-09 11:32:46 -0400575 BlitGL *blitter = GetBlitGL(context);
576 ANGLE_TRY(blitter->blitColorBufferWithShader(sourceFramebuffer, destFramebuffer, sourceArea,
577 destArea, filter));
Corentin Wallez26a717b2016-09-27 08:45:42 -0700578 blitMask &= ~GL_COLOR_BUFFER_BIT;
579 }
580
581 if (blitMask == 0)
582 {
583 return gl::NoError();
584 }
585
586 const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(sourceFramebuffer);
Geoff Lang61107632018-05-09 11:32:46 -0400587 stateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
588 stateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferID);
Geoff Lang4ad17092015-03-10 16:47:44 -0400589
Geoff Lang61107632018-05-09 11:32:46 -0400590 functions->blitFramebuffer(sourceArea.x, sourceArea.y, sourceArea.x1(), sourceArea.y1(),
591 destArea.x, destArea.y, destArea.x1(), destArea.y1(), blitMask,
592 filter);
Geoff Lang4ad17092015-03-10 16:47:44 -0400593
Corentin Wallez26a717b2016-09-27 08:45:42 -0700594 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500595}
596
Geoff Lang13455072018-05-09 11:24:43 -0400597gl::Error FramebufferGL::getSamplePosition(const gl::Context *context,
598 size_t index,
599 GLfloat *xy) const
JiangYizhoubddc46b2016-12-09 09:50:51 +0800600{
Geoff Lang61107632018-05-09 11:32:46 -0400601 const FunctionsGL *functions = GetFunctionsGL(context);
602 StateManagerGL *stateManager = GetStateManagerGL(context);
603
604 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
605 functions->getMultisamplefv(GL_SAMPLE_POSITION, static_cast<GLuint>(index), xy);
JiangYizhoubddc46b2016-12-09 09:50:51 +0800606 return gl::NoError();
607}
608
Kenneth Russellce8602a2017-10-03 18:23:08 -0700609bool FramebufferGL::checkStatus(const gl::Context *context) const
Geoff Langf9a6f082015-01-22 13:32:49 -0500610{
Geoff Lang61107632018-05-09 11:32:46 -0400611 const FunctionsGL *functions = GetFunctionsGL(context);
612 StateManagerGL *stateManager = GetStateManagerGL(context);
613
614 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
615 GLenum status = functions->checkFramebufferStatus(GL_FRAMEBUFFER);
Jamie Madillcc86d642015-11-24 13:00:07 -0500616 if (status != GL_FRAMEBUFFER_COMPLETE)
617 {
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500618 WARN() << "GL framebuffer returned incomplete.";
Jamie Madillcc86d642015-11-24 13:00:07 -0500619 }
620 return (status == GL_FRAMEBUFFER_COMPLETE);
Geoff Lang4ad17092015-03-10 16:47:44 -0400621}
622
Jamie Madill19fa1c62018-03-08 09:47:21 -0500623gl::Error FramebufferGL::syncState(const gl::Context *context,
624 const Framebuffer::DirtyBits &dirtyBits)
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500625{
626 // Don't need to sync state for the default FBO.
627 if (mIsDefault)
628 {
Jamie Madill19fa1c62018-03-08 09:47:21 -0500629 return gl::NoError();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500630 }
631
Geoff Lang61107632018-05-09 11:32:46 -0400632 const FunctionsGL *functions = GetFunctionsGL(context);
633 StateManagerGL *stateManager = GetStateManagerGL(context);
634
635 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500636
Martin Radev7c2e6a92017-08-28 11:13:16 +0300637 // A pointer to one of the attachments for which the texture or the render buffer is not zero.
638 const FramebufferAttachment *attachment = nullptr;
Martin Radev878c8b12017-07-28 09:51:04 +0300639
Jamie Madill6de51852017-04-12 09:53:01 -0400640 for (auto dirtyBit : dirtyBits)
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500641 {
642 switch (dirtyBit)
643 {
644 case Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
Martin Radev7c2e6a92017-08-28 11:13:16 +0300645 {
646 const FramebufferAttachment *newAttachment = mState.getDepthAttachment();
Geoff Lang61107632018-05-09 11:32:46 -0400647 BindFramebufferAttachment(functions, GL_DEPTH_ATTACHMENT, newAttachment);
Martin Radev7c2e6a92017-08-28 11:13:16 +0300648 if (newAttachment)
649 {
650 attachment = newAttachment;
651 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500652 break;
Martin Radev7c2e6a92017-08-28 11:13:16 +0300653 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500654 case Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
Martin Radev7c2e6a92017-08-28 11:13:16 +0300655 {
656 const FramebufferAttachment *newAttachment = mState.getStencilAttachment();
Geoff Lang61107632018-05-09 11:32:46 -0400657 BindFramebufferAttachment(functions, GL_STENCIL_ATTACHMENT, newAttachment);
Martin Radev7c2e6a92017-08-28 11:13:16 +0300658 if (newAttachment)
659 {
660 attachment = newAttachment;
661 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500662 break;
Martin Radev7c2e6a92017-08-28 11:13:16 +0300663 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500664 case Framebuffer::DIRTY_BIT_DRAW_BUFFERS:
665 {
Jamie Madill48ef11b2016-04-27 15:21:52 -0400666 const auto &drawBuffers = mState.getDrawBufferStates();
Geoff Lang61107632018-05-09 11:32:46 -0400667 functions->drawBuffers(static_cast<GLsizei>(drawBuffers.size()),
668 drawBuffers.data());
Corentin Walleze7557742017-06-01 13:09:57 -0400669 mAppliedEnabledDrawBuffers = mState.getEnabledDrawBuffers();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500670 break;
671 }
672 case Framebuffer::DIRTY_BIT_READ_BUFFER:
Geoff Lang61107632018-05-09 11:32:46 -0400673 functions->readBuffer(mState.getReadBufferState());
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500674 break;
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800675 case Framebuffer::DIRTY_BIT_DEFAULT_WIDTH:
Geoff Lang61107632018-05-09 11:32:46 -0400676 functions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH,
677 mState.getDefaultWidth());
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800678 break;
679 case Framebuffer::DIRTY_BIT_DEFAULT_HEIGHT:
Geoff Lang61107632018-05-09 11:32:46 -0400680 functions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT,
681 mState.getDefaultHeight());
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800682 break;
683 case Framebuffer::DIRTY_BIT_DEFAULT_SAMPLES:
Geoff Lang61107632018-05-09 11:32:46 -0400684 functions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_SAMPLES,
685 mState.getDefaultSamples());
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800686 break;
687 case Framebuffer::DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS:
Geoff Lang61107632018-05-09 11:32:46 -0400688 functions->framebufferParameteri(
Geoff Lang92019432017-11-20 13:09:34 -0500689 GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS,
690 gl::ConvertToGLBoolean(mState.getDefaultFixedSampleLocations()));
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800691 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500692 default:
693 {
694 ASSERT(Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0 &&
695 dirtyBit < Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX);
696 size_t index =
697 static_cast<size_t>(dirtyBit - Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
Martin Radev7c2e6a92017-08-28 11:13:16 +0300698 const FramebufferAttachment *newAttachment = mState.getColorAttachment(index);
699 BindFramebufferAttachment(
Geoff Lang61107632018-05-09 11:32:46 -0400700 functions, static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + index), newAttachment);
Martin Radev7c2e6a92017-08-28 11:13:16 +0300701 if (newAttachment)
702 {
703 attachment = newAttachment;
704 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500705 break;
706 }
707 }
708 }
Martin Radev878c8b12017-07-28 09:51:04 +0300709
Martin Radev7c2e6a92017-08-28 11:13:16 +0300710 if (attachment)
Martin Radev878c8b12017-07-28 09:51:04 +0300711 {
Martin Radev7c2e6a92017-08-28 11:13:16 +0300712 const bool isSideBySide =
713 (attachment->getMultiviewLayout() == GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE);
Geoff Lang61107632018-05-09 11:32:46 -0400714 stateManager->setSideBySide(isSideBySide);
715 stateManager->setViewportOffsets(attachment->getMultiviewViewportOffsets());
716 stateManager->updateMultiviewBaseViewLayerIndexUniform(context->getGLState().getProgram(),
717 getState());
Martin Radev878c8b12017-07-28 09:51:04 +0300718 }
Jamie Madill19fa1c62018-03-08 09:47:21 -0500719
720 return gl::NoError();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500721}
722
Geoff Lang4ad17092015-03-10 16:47:44 -0400723GLuint FramebufferGL::getFramebufferID() const
724{
725 return mFramebufferID;
Geoff Langf9a6f082015-01-22 13:32:49 -0500726}
727
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700728bool FramebufferGL::isDefault() const
Geoff Langafd7f0a2015-09-09 15:33:31 -0400729{
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700730 return mIsDefault;
Geoff Langafd7f0a2015-09-09 15:33:31 -0400731}
732
Geoff Lang61107632018-05-09 11:32:46 -0400733void FramebufferGL::maskOutInactiveOutputDrawBuffers(const gl::Context *context,
734 GLenum binding,
735 DrawBufferMask maxSet)
Corentin Walleze7557742017-06-01 13:09:57 -0400736{
Geoff Lang61107632018-05-09 11:32:46 -0400737
Corentin Walleze7557742017-06-01 13:09:57 -0400738 auto targetAppliedDrawBuffers = mState.getEnabledDrawBuffers() & maxSet;
739 if (mAppliedEnabledDrawBuffers != targetAppliedDrawBuffers)
740 {
741 mAppliedEnabledDrawBuffers = targetAppliedDrawBuffers;
742
743 const auto &stateDrawBuffers = mState.getDrawBufferStates();
744 GLsizei drawBufferCount = static_cast<GLsizei>(stateDrawBuffers.size());
745 ASSERT(drawBufferCount <= IMPLEMENTATION_MAX_DRAW_BUFFERS);
746
747 GLenum drawBuffers[IMPLEMENTATION_MAX_DRAW_BUFFERS];
748 for (GLenum i = 0; static_cast<int>(i) < drawBufferCount; ++i)
749 {
750 drawBuffers[i] = targetAppliedDrawBuffers[i] ? stateDrawBuffers[i] : GL_NONE;
751 }
752
Geoff Lang61107632018-05-09 11:32:46 -0400753 const FunctionsGL *functions = GetFunctionsGL(context);
754 StateManagerGL *stateManager = GetStateManagerGL(context);
755
756 stateManager->bindFramebuffer(binding, mFramebufferID);
757 functions->drawBuffers(drawBufferCount, drawBuffers);
Corentin Walleze7557742017-06-01 13:09:57 -0400758 }
759}
760
Jamie Madillc564c072017-06-01 12:45:42 -0400761void FramebufferGL::syncClearState(const gl::Context *context, GLbitfield mask)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400762{
Geoff Lang61107632018-05-09 11:32:46 -0400763 const FunctionsGL *functions = GetFunctionsGL(context);
764
765 if (functions->standard == STANDARD_GL_DESKTOP)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400766 {
Geoff Lang61107632018-05-09 11:32:46 -0400767 StateManagerGL *stateManager = GetStateManagerGL(context);
768 const WorkaroundsGL &workarounds = GetWorkaroundsGL(context);
769
770 if (workarounds.doesSRGBClearsOnLinearFramebufferAttachments &&
Frank Henigmana3d333c2016-03-22 22:09:14 -0400771 (mask & GL_COLOR_BUFFER_BIT) != 0 && !mIsDefault)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400772 {
Corentin Wallez26a717b2016-09-27 08:45:42 -0700773 bool hasSRGBAttachment = false;
Jamie Madill48ef11b2016-04-27 15:21:52 -0400774 for (const auto &attachment : mState.getColorAttachments())
Geoff Langafd7f0a2015-09-09 15:33:31 -0400775 {
Frank Henigmana3d333c2016-03-22 22:09:14 -0400776 if (attachment.isAttached() && attachment.getColorEncoding() == GL_SRGB)
777 {
Corentin Wallez26a717b2016-09-27 08:45:42 -0700778 hasSRGBAttachment = true;
Frank Henigmana3d333c2016-03-22 22:09:14 -0400779 break;
780 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400781 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400782
Geoff Lang61107632018-05-09 11:32:46 -0400783 stateManager->setFramebufferSRGBEnabled(context, hasSRGBAttachment);
Frank Henigmana3d333c2016-03-22 22:09:14 -0400784 }
785 else
786 {
Geoff Lang61107632018-05-09 11:32:46 -0400787 stateManager->setFramebufferSRGBEnabled(context, !mIsDefault);
Frank Henigmana3d333c2016-03-22 22:09:14 -0400788 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400789 }
790}
791
Jamie Madillc564c072017-06-01 12:45:42 -0400792void FramebufferGL::syncClearBufferState(const gl::Context *context,
793 GLenum buffer,
794 GLint drawBuffer)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400795{
Geoff Lang61107632018-05-09 11:32:46 -0400796 const FunctionsGL *functions = GetFunctionsGL(context);
797
798 if (functions->standard == STANDARD_GL_DESKTOP)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400799 {
Geoff Lang61107632018-05-09 11:32:46 -0400800 StateManagerGL *stateManager = GetStateManagerGL(context);
801 const WorkaroundsGL &workarounds = GetWorkaroundsGL(context);
802
803 if (workarounds.doesSRGBClearsOnLinearFramebufferAttachments && buffer == GL_COLOR &&
Geoff Langafd7f0a2015-09-09 15:33:31 -0400804 !mIsDefault)
805 {
806 // If doing a clear on a color buffer, set SRGB blend enabled only if the color buffer
807 // is an SRGB format.
Jamie Madill48ef11b2016-04-27 15:21:52 -0400808 const auto &drawbufferState = mState.getDrawBufferStates();
809 const auto &colorAttachments = mState.getColorAttachments();
Geoff Langafd7f0a2015-09-09 15:33:31 -0400810
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500811 const FramebufferAttachment *attachment = nullptr;
Geoff Langafd7f0a2015-09-09 15:33:31 -0400812 if (drawbufferState[drawBuffer] >= GL_COLOR_ATTACHMENT0 &&
813 drawbufferState[drawBuffer] < GL_COLOR_ATTACHMENT0 + colorAttachments.size())
814 {
815 size_t attachmentIdx =
816 static_cast<size_t>(drawbufferState[drawBuffer] - GL_COLOR_ATTACHMENT0);
817 attachment = &colorAttachments[attachmentIdx];
818 }
819
820 if (attachment != nullptr)
821 {
Geoff Lang61107632018-05-09 11:32:46 -0400822 stateManager->setFramebufferSRGBEnabled(context,
823 attachment->getColorEncoding() == GL_SRGB);
Geoff Langafd7f0a2015-09-09 15:33:31 -0400824 }
825 }
826 else
827 {
Geoff Lang61107632018-05-09 11:32:46 -0400828 stateManager->setFramebufferSRGBEnabled(context, !mIsDefault);
Geoff Langafd7f0a2015-09-09 15:33:31 -0400829 }
830 }
831}
Geoff Lang005a7012017-03-27 13:17:34 -0400832
833bool FramebufferGL::modifyInvalidateAttachmentsForEmulatedDefaultFBO(
834 size_t count,
835 const GLenum *attachments,
836 std::vector<GLenum> *modifiedAttachments) const
837{
838 bool needsModification = mIsDefault && mFramebufferID != 0;
839 if (!needsModification)
840 {
841 return false;
842 }
843
844 modifiedAttachments->resize(count);
845 for (size_t i = 0; i < count; i++)
846 {
847 switch (attachments[i])
848 {
849 case GL_COLOR:
850 (*modifiedAttachments)[i] = GL_COLOR_ATTACHMENT0;
851 break;
852
853 case GL_DEPTH:
854 (*modifiedAttachments)[i] = GL_DEPTH_ATTACHMENT;
855 break;
856
857 case GL_STENCIL:
858 (*modifiedAttachments)[i] = GL_STENCIL_ATTACHMENT;
859 break;
860
861 default:
862 UNREACHABLE();
863 break;
864 }
865 }
866
867 return true;
868}
869
Frank Henigmanfa36c332017-06-09 18:44:45 -0400870gl::Error FramebufferGL::readPixelsRowByRow(const gl::Context *context,
871 const gl::Rectangle &area,
872 GLenum format,
873 GLenum type,
874 const gl::PixelPackState &pack,
875 GLubyte *pixels) const
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400876{
Geoff Lang61107632018-05-09 11:32:46 -0400877 const FunctionsGL *functions = GetFunctionsGL(context);
878 StateManagerGL *stateManager = GetStateManagerGL(context);
879
Geoff Langca271392017-04-05 12:30:00 -0400880 const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(format, type);
Frank Henigmanfa36c332017-06-09 18:44:45 -0400881
882 GLuint rowBytes = 0;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400883 ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
884 rowBytes);
885 GLuint skipBytes = 0;
Corentin Wallez886de362016-09-27 10:49:35 -0400886 ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400887
888 gl::PixelPackState directPack;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400889 directPack.alignment = 1;
Geoff Lang61107632018-05-09 11:32:46 -0400890 stateManager->setPixelPackState(directPack);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400891
Frank Henigmanfa36c332017-06-09 18:44:45 -0400892 pixels += skipBytes;
893 for (GLint y = area.y; y < area.y + area.height; ++y)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400894 {
Geoff Lang61107632018-05-09 11:32:46 -0400895 functions->readPixels(area.x, y, area.width, 1, format, type, pixels);
Frank Henigmanfa36c332017-06-09 18:44:45 -0400896 pixels += rowBytes;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400897 }
898
899 return gl::NoError();
900}
901
Frank Henigmanfa36c332017-06-09 18:44:45 -0400902gl::Error FramebufferGL::readPixelsAllAtOnce(const gl::Context *context,
903 const gl::Rectangle &area,
904 GLenum format,
905 GLenum type,
906 const gl::PixelPackState &pack,
907 GLubyte *pixels,
908 bool readLastRowSeparately) const
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400909{
Geoff Lang61107632018-05-09 11:32:46 -0400910 const FunctionsGL *functions = GetFunctionsGL(context);
911 StateManagerGL *stateManager = GetStateManagerGL(context);
912
Frank Henigmanfa36c332017-06-09 18:44:45 -0400913 GLint height = area.height - readLastRowSeparately;
914 if (height > 0)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400915 {
Geoff Lang61107632018-05-09 11:32:46 -0400916 stateManager->setPixelPackState(pack);
917 functions->readPixels(area.x, area.y, area.width, height, format, type, pixels);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400918 }
919
Frank Henigmanfa36c332017-06-09 18:44:45 -0400920 if (readLastRowSeparately)
921 {
922 const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(format, type);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400923
Frank Henigmanfa36c332017-06-09 18:44:45 -0400924 GLuint rowBytes = 0;
925 ANGLE_TRY_RESULT(glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength),
926 rowBytes);
927 GLuint skipBytes = 0;
928 ANGLE_TRY_RESULT(glFormat.computeSkipBytes(rowBytes, 0, pack, false), skipBytes);
929
930 gl::PixelPackState directPack;
Frank Henigmanfa36c332017-06-09 18:44:45 -0400931 directPack.alignment = 1;
Geoff Lang61107632018-05-09 11:32:46 -0400932 stateManager->setPixelPackState(directPack);
Frank Henigmanfa36c332017-06-09 18:44:45 -0400933
934 pixels += skipBytes + (area.height - 1) * rowBytes;
Geoff Lang61107632018-05-09 11:32:46 -0400935 functions->readPixels(area.x, area.y + area.height - 1, area.width, 1, format, type,
936 pixels);
Frank Henigmanfa36c332017-06-09 18:44:45 -0400937 }
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400938
939 return gl::NoError();
940}
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500941} // namespace rx