blob: 2a253dd3250ffc7a90c96f790a85918ddd760e8d [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 }
Jiawei Shaoa8802472018-05-28 11:17:47 +080060 else if (attachment->isLayered())
61 {
62 TextureType textureType = texture->getType();
63 ASSERT(textureType == TextureType::_2DArray || textureType == TextureType::_3D ||
64 textureType == TextureType::CubeMap);
65 functions->framebufferTexture(GL_FRAMEBUFFER, attachmentPoint,
66 textureGL->getTextureID(), attachment->mipLevel());
67 }
Corentin Wallez99d492c2018-02-27 15:17:10 -050068 else if (texture->getType() == TextureType::CubeMap)
69 {
70 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint,
71 ToGLenum(attachment->cubeMapFace()),
72 textureGL->getTextureID(), attachment->mipLevel());
73 }
74 else if (texture->getType() == TextureType::_2DArray ||
75 texture->getType() == TextureType::_3D)
Geoff Lang4ad17092015-03-10 16:47:44 -040076 {
Martin Radev5e424fa2017-08-09 16:25:36 +030077 if (attachment->getMultiviewLayout() == GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE)
78 {
79 ASSERT(functions->framebufferTexture);
80 functions->framebufferTexture(GL_FRAMEBUFFER, attachmentPoint,
81 textureGL->getTextureID(),
82 attachment->mipLevel());
83 }
84 else
85 {
86 functions->framebufferTextureLayer(GL_FRAMEBUFFER, attachmentPoint,
87 textureGL->getTextureID(),
88 attachment->mipLevel(), attachment->layer());
89 }
Geoff Lang4ad17092015-03-10 16:47:44 -040090 }
91 else
92 {
93 UNREACHABLE();
94 }
95 }
96 else if (attachment->type() == GL_RENDERBUFFER)
97 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -050098 const Renderbuffer *renderbuffer = attachment->getRenderbuffer();
Geoff Langcd69f1c2015-03-18 14:33:23 -040099 const RenderbufferGL *renderbufferGL = GetImplAs<RenderbufferGL>(renderbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400100
Geoff Langcd69f1c2015-03-18 14:33:23 -0400101 functions->framebufferRenderbuffer(GL_FRAMEBUFFER, attachmentPoint, GL_RENDERBUFFER,
102 renderbufferGL->getRenderbufferID());
Geoff Lang4ad17092015-03-10 16:47:44 -0400103 }
104 else
105 {
106 UNREACHABLE();
107 }
108 }
109 else
110 {
111 // Unbind this attachment
112 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_2D, 0, 0);
113 }
114}
Geoff Langf9a6f082015-01-22 13:32:49 -0500115
Martin Radev61e710b2017-09-05 11:59:52 +0300116bool AreAllLayersActive(const FramebufferAttachment &attachment)
Martin Radevb0761932017-07-25 17:42:25 +0300117{
Martin Radev61e710b2017-09-05 11:59:52 +0300118 int baseViewIndex = attachment.getBaseViewIndex();
119 if (baseViewIndex != 0)
120 {
121 return false;
122 }
123 const ImageIndex &imageIndex = attachment.getTextureImageIndex();
Jamie Madillcc129372018-04-12 09:13:18 -0400124 int numLayers = static_cast<int>(
125 attachment.getTexture()->getDepth(imageIndex.getTarget(), imageIndex.getLevelIndex()));
Martin Radev61e710b2017-09-05 11:59:52 +0300126 return (attachment.getNumViews() == numLayers);
127}
128
129bool RequiresMultiviewClear(const FramebufferState &state, bool scissorTestEnabled)
130{
131 // Get one attachment and check whether all layers are attached.
132 const FramebufferAttachment *attachment = nullptr;
133 bool allTextureArraysAreFullyAttached = true;
134 for (const FramebufferAttachment &colorAttachment : state.getColorAttachments())
135 {
136 if (colorAttachment.isAttached())
137 {
138 if (colorAttachment.getMultiviewLayout() == GL_NONE)
139 {
140 return false;
141 }
142 attachment = &colorAttachment;
143 allTextureArraysAreFullyAttached =
144 allTextureArraysAreFullyAttached && AreAllLayersActive(*attachment);
145 }
146 }
147
148 const FramebufferAttachment *depthAttachment = state.getDepthAttachment();
149 if (depthAttachment)
150 {
151 if (depthAttachment->getMultiviewLayout() == GL_NONE)
152 {
153 return false;
154 }
155 attachment = depthAttachment;
156 allTextureArraysAreFullyAttached =
157 allTextureArraysAreFullyAttached && AreAllLayersActive(*attachment);
158 }
159 const FramebufferAttachment *stencilAttachment = state.getStencilAttachment();
160 if (stencilAttachment)
161 {
162 if (stencilAttachment->getMultiviewLayout() == GL_NONE)
163 {
164 return false;
165 }
166 attachment = stencilAttachment;
167 allTextureArraysAreFullyAttached =
168 allTextureArraysAreFullyAttached && AreAllLayersActive(*attachment);
169 }
170
Martin Radev5e424fa2017-08-09 16:25:36 +0300171 if (attachment == nullptr)
172 {
173 return false;
174 }
175 switch (attachment->getMultiviewLayout())
176 {
177 case GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE:
Martin Radev61e710b2017-09-05 11:59:52 +0300178 // If all layers of each texture array are active, then there is no need to issue a
179 // special multiview clear.
180 return !allTextureArraysAreFullyAttached;
Martin Radev5e424fa2017-08-09 16:25:36 +0300181 case GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE:
182 return (scissorTestEnabled == true);
Martin Radev5e424fa2017-08-09 16:25:36 +0300183 default:
184 UNREACHABLE();
185 }
186 return false;
Martin Radevb0761932017-07-25 17:42:25 +0300187}
188
Martin Radev878c8b12017-07-28 09:51:04 +0300189} // namespace
190
Geoff Lang61107632018-05-09 11:32:46 -0400191FramebufferGL::FramebufferGL(const gl::FramebufferState &data, GLuint id, bool isDefault)
192 : FramebufferImpl(data),
Martin Radev878c8b12017-07-28 09:51:04 +0300193 mFramebufferID(id),
Geoff Lang61107632018-05-09 11:32:46 -0400194 mIsDefault(isDefault),
Martin Radev878c8b12017-07-28 09:51:04 +0300195 mAppliedEnabledDrawBuffers(1)
196{
197}
198
199FramebufferGL::~FramebufferGL()
200{
Geoff Lang61107632018-05-09 11:32:46 -0400201 ASSERT(mFramebufferID == 0);
202}
203
204void FramebufferGL::destroy(const gl::Context *context)
205{
206 StateManagerGL *stateManager = GetStateManagerGL(context);
207 stateManager->deleteFramebuffer(mFramebufferID);
Martin Radev878c8b12017-07-28 09:51:04 +0300208 mFramebufferID = 0;
209}
210
Jamie Madill4928b7c2017-06-20 12:57:39 -0400211Error FramebufferGL::discard(const gl::Context *context, size_t count, const GLenum *attachments)
Austin Kinross08332632015-05-05 13:35:47 -0700212{
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500213 // glInvalidateFramebuffer accepts the same enums as glDiscardFramebufferEXT
Jamie Madill4928b7c2017-06-20 12:57:39 -0400214 return invalidate(context, count, attachments);
Austin Kinross08332632015-05-05 13:35:47 -0700215}
216
Jamie Madill4928b7c2017-06-20 12:57:39 -0400217Error FramebufferGL::invalidate(const gl::Context *context, size_t count, const GLenum *attachments)
Geoff Langf9a6f082015-01-22 13:32:49 -0500218{
Geoff Lang005a7012017-03-27 13:17:34 -0400219 const GLenum *finalAttachmentsPtr = attachments;
220
221 std::vector<GLenum> modifiedAttachments;
222 if (modifyInvalidateAttachmentsForEmulatedDefaultFBO(count, attachments, &modifiedAttachments))
223 {
224 finalAttachmentsPtr = modifiedAttachments.data();
225 }
226
Geoff Lang61107632018-05-09 11:32:46 -0400227 const FunctionsGL *functions = GetFunctionsGL(context);
228 StateManagerGL *stateManager = GetStateManagerGL(context);
229
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500230 // Since this function is just a hint, only call a native function if it exists.
Geoff Lang61107632018-05-09 11:32:46 -0400231 if (functions->invalidateFramebuffer)
Geoff Lang64a72442015-04-01 14:43:11 -0400232 {
Geoff Lang61107632018-05-09 11:32:46 -0400233 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
234 functions->invalidateFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
235 finalAttachmentsPtr);
Geoff Lang64a72442015-04-01 14:43:11 -0400236 }
Geoff Lang61107632018-05-09 11:32:46 -0400237 else if (functions->discardFramebufferEXT)
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500238 {
Geoff Lang61107632018-05-09 11:32:46 -0400239 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
240 functions->discardFramebufferEXT(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
241 finalAttachmentsPtr);
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500242 }
Geoff Lang64a72442015-04-01 14:43:11 -0400243
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500244 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500245}
246
Jamie Madill4928b7c2017-06-20 12:57:39 -0400247Error FramebufferGL::invalidateSub(const gl::Context *context,
248 size_t count,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500249 const GLenum *attachments,
250 const gl::Rectangle &area)
Geoff Langf9a6f082015-01-22 13:32:49 -0500251{
Geoff Lang005a7012017-03-27 13:17:34 -0400252
253 const GLenum *finalAttachmentsPtr = attachments;
254
255 std::vector<GLenum> modifiedAttachments;
256 if (modifyInvalidateAttachmentsForEmulatedDefaultFBO(count, attachments, &modifiedAttachments))
257 {
258 finalAttachmentsPtr = modifiedAttachments.data();
259 }
260
Geoff Lang61107632018-05-09 11:32:46 -0400261 const FunctionsGL *functions = GetFunctionsGL(context);
262 StateManagerGL *stateManager = GetStateManagerGL(context);
263
Jamie Madill231c7f52017-04-26 13:45:37 -0400264 // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is
265 // available.
Geoff Lang61107632018-05-09 11:32:46 -0400266 if (functions->invalidateSubFramebuffer)
Geoff Lang64a72442015-04-01 14:43:11 -0400267 {
Geoff Lang61107632018-05-09 11:32:46 -0400268 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
269 functions->invalidateSubFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
270 finalAttachmentsPtr, area.x, area.y, area.width,
271 area.height);
Geoff Lang64a72442015-04-01 14:43:11 -0400272 }
273
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500274 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500275}
276
Jamie Madillc564c072017-06-01 12:45:42 -0400277Error FramebufferGL::clear(const gl::Context *context, GLbitfield mask)
Geoff Langf9a6f082015-01-22 13:32:49 -0500278{
Geoff Lang61107632018-05-09 11:32:46 -0400279 const FunctionsGL *functions = GetFunctionsGL(context);
280 StateManagerGL *stateManager = GetStateManagerGL(context);
281
Frank Henigman308d7452017-02-15 22:51:21 -0500282 syncClearState(context, mask);
Geoff Lang61107632018-05-09 11:32:46 -0400283 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300284
Martin Radev61e710b2017-09-05 11:59:52 +0300285 if (!RequiresMultiviewClear(mState, context->getGLState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300286 {
Geoff Lang61107632018-05-09 11:32:46 -0400287 functions->clear(mask);
Martin Radevb0761932017-07-25 17:42:25 +0300288 }
289 else
290 {
Geoff Lang61107632018-05-09 11:32:46 -0400291 ClearMultiviewGL *multiviewClearer = GetMultiviewClearer(context);
292 multiviewClearer->clearMultiviewFBO(mState, context->getGLState().getScissor(),
293 ClearMultiviewGL::ClearCommandType::Clear, mask,
294 GL_NONE, 0, nullptr, 0.0f, 0);
Martin Radevb0761932017-07-25 17:42:25 +0300295 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400296
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500297 return gl::NoError();
Geoff Lang4ad17092015-03-10 16:47:44 -0400298}
299
Jamie Madillc564c072017-06-01 12:45:42 -0400300Error FramebufferGL::clearBufferfv(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500301 GLenum buffer,
302 GLint drawbuffer,
303 const GLfloat *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500304{
Geoff Lang61107632018-05-09 11:32:46 -0400305 const FunctionsGL *functions = GetFunctionsGL(context);
306 StateManagerGL *stateManager = GetStateManagerGL(context);
307
Frank Henigman308d7452017-02-15 22:51:21 -0500308 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang61107632018-05-09 11:32:46 -0400309 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300310
Martin Radev61e710b2017-09-05 11:59:52 +0300311 if (!RequiresMultiviewClear(mState, context->getGLState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300312 {
Geoff Lang61107632018-05-09 11:32:46 -0400313 functions->clearBufferfv(buffer, drawbuffer, values);
Martin Radevb0761932017-07-25 17:42:25 +0300314 }
315 else
316 {
Geoff Lang61107632018-05-09 11:32:46 -0400317 ClearMultiviewGL *multiviewClearer = GetMultiviewClearer(context);
318 multiviewClearer->clearMultiviewFBO(mState, context->getGLState().getScissor(),
319 ClearMultiviewGL::ClearCommandType::ClearBufferfv,
320 static_cast<GLbitfield>(0u), buffer, drawbuffer,
321 reinterpret_cast<const uint8_t *>(values), 0.0f, 0);
Martin Radevb0761932017-07-25 17:42:25 +0300322 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400323
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500324 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500325}
326
Jamie Madillc564c072017-06-01 12:45:42 -0400327Error FramebufferGL::clearBufferuiv(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500328 GLenum buffer,
329 GLint drawbuffer,
330 const GLuint *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500331{
Geoff Lang61107632018-05-09 11:32:46 -0400332 const FunctionsGL *functions = GetFunctionsGL(context);
333 StateManagerGL *stateManager = GetStateManagerGL(context);
334
Frank Henigman308d7452017-02-15 22:51:21 -0500335 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang61107632018-05-09 11:32:46 -0400336 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300337
Martin Radev61e710b2017-09-05 11:59:52 +0300338 if (!RequiresMultiviewClear(mState, context->getGLState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300339 {
Geoff Lang61107632018-05-09 11:32:46 -0400340 functions->clearBufferuiv(buffer, drawbuffer, values);
Martin Radevb0761932017-07-25 17:42:25 +0300341 }
342 else
343 {
Geoff Lang61107632018-05-09 11:32:46 -0400344 ClearMultiviewGL *multiviewClearer = GetMultiviewClearer(context);
345 multiviewClearer->clearMultiviewFBO(mState, context->getGLState().getScissor(),
346 ClearMultiviewGL::ClearCommandType::ClearBufferuiv,
347 static_cast<GLbitfield>(0u), buffer, drawbuffer,
348 reinterpret_cast<const uint8_t *>(values), 0.0f, 0);
Martin Radevb0761932017-07-25 17:42:25 +0300349 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400350
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500351 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500352}
353
Jamie Madillc564c072017-06-01 12:45:42 -0400354Error FramebufferGL::clearBufferiv(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500355 GLenum buffer,
356 GLint drawbuffer,
357 const GLint *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500358{
Geoff Lang61107632018-05-09 11:32:46 -0400359 const FunctionsGL *functions = GetFunctionsGL(context);
360 StateManagerGL *stateManager = GetStateManagerGL(context);
361
Frank Henigman308d7452017-02-15 22:51:21 -0500362 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang61107632018-05-09 11:32:46 -0400363 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300364
Martin Radev61e710b2017-09-05 11:59:52 +0300365 if (!RequiresMultiviewClear(mState, context->getGLState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300366 {
Geoff Lang61107632018-05-09 11:32:46 -0400367 functions->clearBufferiv(buffer, drawbuffer, values);
Martin Radevb0761932017-07-25 17:42:25 +0300368 }
369 else
370 {
Geoff Lang61107632018-05-09 11:32:46 -0400371 ClearMultiviewGL *multiviewClearer = GetMultiviewClearer(context);
372 multiviewClearer->clearMultiviewFBO(mState, context->getGLState().getScissor(),
373 ClearMultiviewGL::ClearCommandType::ClearBufferiv,
374 static_cast<GLbitfield>(0u), buffer, drawbuffer,
375 reinterpret_cast<const uint8_t *>(values), 0.0f, 0);
Martin Radevb0761932017-07-25 17:42:25 +0300376 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400377
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500378 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500379}
380
Jamie Madillc564c072017-06-01 12:45:42 -0400381Error FramebufferGL::clearBufferfi(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500382 GLenum buffer,
383 GLint drawbuffer,
384 GLfloat depth,
385 GLint stencil)
Geoff Langf9a6f082015-01-22 13:32:49 -0500386{
Geoff Lang61107632018-05-09 11:32:46 -0400387 const FunctionsGL *functions = GetFunctionsGL(context);
388 StateManagerGL *stateManager = GetStateManagerGL(context);
389
Frank Henigman308d7452017-02-15 22:51:21 -0500390 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang61107632018-05-09 11:32:46 -0400391 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300392
Martin Radev61e710b2017-09-05 11:59:52 +0300393 if (!RequiresMultiviewClear(mState, context->getGLState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300394 {
Geoff Lang61107632018-05-09 11:32:46 -0400395 functions->clearBufferfi(buffer, drawbuffer, depth, stencil);
Martin Radevb0761932017-07-25 17:42:25 +0300396 }
Martin Radev5e424fa2017-08-09 16:25:36 +0300397 else
398 {
Geoff Lang61107632018-05-09 11:32:46 -0400399 ClearMultiviewGL *multiviewClearer = GetMultiviewClearer(context);
400 multiviewClearer->clearMultiviewFBO(mState, context->getGLState().getScissor(),
401 ClearMultiviewGL::ClearCommandType::ClearBufferfi,
402 static_cast<GLbitfield>(0u), buffer, drawbuffer,
403 nullptr, depth, stencil);
Martin Radev5e424fa2017-08-09 16:25:36 +0300404 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400405
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500406 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500407}
408
Jamie Madill4928b7c2017-06-20 12:57:39 -0400409GLenum FramebufferGL::getImplementationColorReadFormat(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->getReadPixelsFormat();
Geoff Langf9a6f082015-01-22 13:32:49 -0500414}
415
Jamie Madill4928b7c2017-06-20 12:57:39 -0400416GLenum FramebufferGL::getImplementationColorReadType(const gl::Context *context) const
Geoff Langf9a6f082015-01-22 13:32:49 -0500417{
Jamie Madilla3944d42016-07-22 22:13:26 -0400418 const auto *readAttachment = mState.getReadAttachment();
419 const Format &format = readAttachment->getFormat();
Geoff Langc71ea662017-09-26 17:06:02 -0400420 return format.info->getReadPixelsType(context->getClientVersion());
Geoff Langf9a6f082015-01-22 13:32:49 -0500421}
422
Jamie Madillc564c072017-06-01 12:45:42 -0400423Error FramebufferGL::readPixels(const gl::Context *context,
Frank Henigmanfa36c332017-06-09 18:44:45 -0400424 const gl::Rectangle &origArea,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500425 GLenum format,
426 GLenum type,
Jamie Madilld4826152017-09-21 11:18:59 -0400427 void *ptrOrOffset)
Geoff Langf9a6f082015-01-22 13:32:49 -0500428{
Geoff Lang61107632018-05-09 11:32:46 -0400429 const FunctionsGL *functions = GetFunctionsGL(context);
430 StateManagerGL *stateManager = GetStateManagerGL(context);
431 const WorkaroundsGL &workarounds = GetWorkaroundsGL(context);
432
Frank Henigmanfa36c332017-06-09 18:44:45 -0400433 // Clip read area to framebuffer.
434 const gl::Extents fbSize = getState().getReadAttachment()->getSize();
435 const gl::Rectangle fbRect(0, 0, fbSize.width, fbSize.height);
436 gl::Rectangle area;
437 if (!ClipRectangle(origArea, fbRect, &area))
438 {
439 // nothing to read
440 return gl::NoError();
441 }
442
Corentin Wallezcda6af12017-10-30 19:20:37 -0400443 PixelPackState packState = context->getGLState().getPackState();
Corentin Wallez336129f2017-10-17 15:55:40 -0400444 const gl::Buffer *packBuffer =
445 context->getGLState().getTargetBuffer(gl::BufferBinding::PixelPack);
Jamie Madill87de3622015-03-16 10:41:44 -0400446
Geoff Langf607c602016-09-21 11:46:48 -0400447 nativegl::ReadPixelsFormat readPixelsFormat =
Geoff Lang61107632018-05-09 11:32:46 -0400448 nativegl::GetReadPixelsFormat(functions, workarounds, format, type);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400449 GLenum readFormat = readPixelsFormat.format;
450 GLenum readType = readPixelsFormat.type;
Geoff Lang4ad17092015-03-10 16:47:44 -0400451
Geoff Lang61107632018-05-09 11:32:46 -0400452 stateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, mFramebufferID);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400453
Geoff Lang61107632018-05-09 11:32:46 -0400454 bool useOverlappingRowsWorkaround = workarounds.packOverlappingRowsSeparatelyPackBuffer &&
Corentin Wallezcda6af12017-10-30 19:20:37 -0400455 packBuffer && packState.rowLength != 0 &&
Frank Henigmanfa36c332017-06-09 18:44:45 -0400456 packState.rowLength < area.width;
457
Rafael Cintron05a449a2018-06-20 18:08:04 -0700458 GLubyte *pixels = static_cast<GLubyte *>(ptrOrOffset);
Frank Henigmanfa36c332017-06-09 18:44:45 -0400459 int leftClip = area.x - origArea.x;
460 int topClip = area.y - origArea.y;
461 if (leftClip || topClip)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400462 {
Frank Henigmanfa36c332017-06-09 18:44:45 -0400463 // Adjust destination to match portion clipped off left and/or top.
464 const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(readFormat, readType);
465
466 GLuint rowBytes = 0;
Jamie Madillca2ff382018-07-11 09:01:17 -0400467 ANGLE_TRY_CHECKED_MATH(glFormat.computeRowPitch(
468 readType, origArea.width, packState.alignment, packState.rowLength, &rowBytes));
Frank Henigmanfa36c332017-06-09 18:44:45 -0400469 pixels += leftClip * glFormat.pixelBytes + topClip * rowBytes;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400470 }
471
Frank Henigmanfa36c332017-06-09 18:44:45 -0400472 if (packState.rowLength == 0 && area.width != origArea.width)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400473 {
Frank Henigmanfa36c332017-06-09 18:44:45 -0400474 // No rowLength was specified so it will derive from read width, but clipping changed the
475 // read width. Use the original width so we fill the user's buffer as they intended.
476 packState.rowLength = origArea.width;
477 }
Corentin Wallez886de362016-09-27 10:49:35 -0400478
Frank Henigmanfa36c332017-06-09 18:44:45 -0400479 // We want to use rowLength, but that might not be supported.
480 bool cannotSetDesiredRowLength =
481 packState.rowLength && !GetImplAs<ContextGL>(context)->getNativeExtensions().packSubimage;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400482
Frank Henigmanfa36c332017-06-09 18:44:45 -0400483 gl::Error retVal = gl::NoError();
484 if (cannotSetDesiredRowLength || useOverlappingRowsWorkaround)
485 {
486 retVal = readPixelsRowByRow(context, area, readFormat, readType, packState, pixels);
487 }
488 else
489 {
490 gl::ErrorOrResult<bool> useLastRowPaddingWorkaround = false;
Geoff Lang61107632018-05-09 11:32:46 -0400491 if (workarounds.packLastRowSeparatelyForPaddingInclusion)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400492 {
Corentin Wallezcda6af12017-10-30 19:20:37 -0400493 useLastRowPaddingWorkaround = ShouldApplyLastRowPaddingWorkaround(
494 gl::Extents(area.width, area.height, 1), packState, packBuffer, readFormat,
495 readType, false, pixels);
Frank Henigmanfa36c332017-06-09 18:44:45 -0400496 }
497
498 if (useLastRowPaddingWorkaround.isError())
499 {
500 retVal = useLastRowPaddingWorkaround.getError();
501 }
502 else
503 {
504 retVal = readPixelsAllAtOnce(context, area, readFormat, readType, packState, pixels,
505 useLastRowPaddingWorkaround.getResult());
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400506 }
507 }
508
Frank Henigmanfa36c332017-06-09 18:44:45 -0400509 return retVal;
Geoff Langf9a6f082015-01-22 13:32:49 -0500510}
511
Jamie Madillc564c072017-06-01 12:45:42 -0400512Error FramebufferGL::blit(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500513 const gl::Rectangle &sourceArea,
514 const gl::Rectangle &destArea,
515 GLbitfield mask,
Jamie Madill8415b5f2016-04-26 13:41:39 -0400516 GLenum filter)
Geoff Langf9a6f082015-01-22 13:32:49 -0500517{
Geoff Lang61107632018-05-09 11:32:46 -0400518 const FunctionsGL *functions = GetFunctionsGL(context);
519 StateManagerGL *stateManager = GetStateManagerGL(context);
520
Jamie Madill231c7f52017-04-26 13:45:37 -0400521 const Framebuffer *sourceFramebuffer = context->getGLState().getReadFramebuffer();
522 const Framebuffer *destFramebuffer = context->getGLState().getDrawFramebuffer();
Geoff Lang4ad17092015-03-10 16:47:44 -0400523
Corentin Wallez6898b352016-11-10 11:41:15 -0500524 const FramebufferAttachment *colorReadAttachment = sourceFramebuffer->getReadColorbuffer();
Corentin Wallez4596a762016-12-20 14:50:18 -0500525
526 GLsizei readAttachmentSamples = 0;
527 if (colorReadAttachment != nullptr)
528 {
529 readAttachmentSamples = colorReadAttachment->getSamples();
530 }
Corentin Wallez6898b352016-11-10 11:41:15 -0500531
Corentin Wallez26a717b2016-09-27 08:45:42 -0700532 bool needManualColorBlit = false;
533
Corentin Wallez6898b352016-11-10 11:41:15 -0500534 // TODO(cwallez) when the filter is LINEAR and both source and destination are SRGB, we
535 // could avoid doing a manual blit.
536
537 // Prior to OpenGL 4.4 BlitFramebuffer (section 18.3.1 of GL 4.3 core profile) reads:
538 // When values are taken from the read buffer, no linearization is performed, even
539 // if the format of the buffer is SRGB.
540 // Starting from OpenGL 4.4 (section 18.3.1) it reads:
541 // When values are taken from the read buffer, if FRAMEBUFFER_SRGB is enabled and the
542 // value of FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING for the framebuffer attachment
543 // corresponding to the read buffer is SRGB, the red, green, and blue components are
544 // converted from the non-linear sRGB color space according [...].
Corentin Wallez26a717b2016-09-27 08:45:42 -0700545 {
Jamie Madill231c7f52017-04-26 13:45:37 -0400546 bool sourceSRGB =
547 colorReadAttachment != nullptr && colorReadAttachment->getColorEncoding() == GL_SRGB;
Corentin Wallez6898b352016-11-10 11:41:15 -0500548 needManualColorBlit =
Geoff Lang61107632018-05-09 11:32:46 -0400549 needManualColorBlit || (sourceSRGB && functions->isAtMostGL(gl::Version(4, 3)));
Corentin Wallez6898b352016-11-10 11:41:15 -0500550 }
Corentin Wallez26a717b2016-09-27 08:45:42 -0700551
Corentin Wallez6898b352016-11-10 11:41:15 -0500552 // Prior to OpenGL 4.2 BlitFramebuffer (section 4.3.2 of GL 4.1 core profile) reads:
553 // Blit operations bypass the fragment pipeline. The only fragment operations which
554 // affect a blit are the pixel ownership test and scissor test.
555 // Starting from OpenGL 4.2 (section 4.3.2) it reads:
556 // When values are written to the draw buffers, blit operations bypass the fragment
557 // pipeline. The only fragment operations which affect a blit are the pixel ownership
558 // test, the scissor test and sRGB conversion.
559 if (!needManualColorBlit)
560 {
561 bool destSRGB = false;
562 for (size_t i = 0; i < destFramebuffer->getDrawbufferStateCount(); ++i)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700563 {
Corentin Wallez6898b352016-11-10 11:41:15 -0500564 const FramebufferAttachment *attachment = destFramebuffer->getDrawBuffer(i);
565 if (attachment && attachment->getColorEncoding() == GL_SRGB)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700566 {
Corentin Wallez6898b352016-11-10 11:41:15 -0500567 destSRGB = true;
568 break;
Corentin Wallez26a717b2016-09-27 08:45:42 -0700569 }
Corentin Wallez26a717b2016-09-27 08:45:42 -0700570 }
Corentin Wallez6898b352016-11-10 11:41:15 -0500571
572 needManualColorBlit =
Geoff Lang61107632018-05-09 11:32:46 -0400573 needManualColorBlit || (destSRGB && functions->isAtMostGL(gl::Version(4, 1)));
Corentin Wallez26a717b2016-09-27 08:45:42 -0700574 }
575
576 // Enable FRAMEBUFFER_SRGB if needed
Geoff Lang61107632018-05-09 11:32:46 -0400577 stateManager->setFramebufferSRGBEnabledForFramebuffer(context, true, this);
Corentin Wallez26a717b2016-09-27 08:45:42 -0700578
579 GLenum blitMask = mask;
Corentin Wallez6898b352016-11-10 11:41:15 -0500580 if (needManualColorBlit && (mask & GL_COLOR_BUFFER_BIT) && readAttachmentSamples <= 1)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700581 {
Geoff Lang61107632018-05-09 11:32:46 -0400582 BlitGL *blitter = GetBlitGL(context);
583 ANGLE_TRY(blitter->blitColorBufferWithShader(sourceFramebuffer, destFramebuffer, sourceArea,
584 destArea, filter));
Corentin Wallez26a717b2016-09-27 08:45:42 -0700585 blitMask &= ~GL_COLOR_BUFFER_BIT;
586 }
587
588 if (blitMask == 0)
589 {
590 return gl::NoError();
591 }
592
593 const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(sourceFramebuffer);
Geoff Lang61107632018-05-09 11:32:46 -0400594 stateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
595 stateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferID);
Geoff Lang4ad17092015-03-10 16:47:44 -0400596
Geoff Lang61107632018-05-09 11:32:46 -0400597 functions->blitFramebuffer(sourceArea.x, sourceArea.y, sourceArea.x1(), sourceArea.y1(),
598 destArea.x, destArea.y, destArea.x1(), destArea.y1(), blitMask,
599 filter);
Geoff Lang4ad17092015-03-10 16:47:44 -0400600
Corentin Wallez26a717b2016-09-27 08:45:42 -0700601 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500602}
603
Geoff Lang13455072018-05-09 11:24:43 -0400604gl::Error FramebufferGL::getSamplePosition(const gl::Context *context,
605 size_t index,
606 GLfloat *xy) const
JiangYizhoubddc46b2016-12-09 09:50:51 +0800607{
Geoff Lang61107632018-05-09 11:32:46 -0400608 const FunctionsGL *functions = GetFunctionsGL(context);
609 StateManagerGL *stateManager = GetStateManagerGL(context);
610
611 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
612 functions->getMultisamplefv(GL_SAMPLE_POSITION, static_cast<GLuint>(index), xy);
JiangYizhoubddc46b2016-12-09 09:50:51 +0800613 return gl::NoError();
614}
615
Kenneth Russellce8602a2017-10-03 18:23:08 -0700616bool FramebufferGL::checkStatus(const gl::Context *context) const
Geoff Langf9a6f082015-01-22 13:32:49 -0500617{
Geoff Lang61107632018-05-09 11:32:46 -0400618 const FunctionsGL *functions = GetFunctionsGL(context);
619 StateManagerGL *stateManager = GetStateManagerGL(context);
620
621 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
622 GLenum status = functions->checkFramebufferStatus(GL_FRAMEBUFFER);
Jamie Madillcc86d642015-11-24 13:00:07 -0500623 if (status != GL_FRAMEBUFFER_COMPLETE)
624 {
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500625 WARN() << "GL framebuffer returned incomplete.";
Jamie Madillcc86d642015-11-24 13:00:07 -0500626 }
627 return (status == GL_FRAMEBUFFER_COMPLETE);
Geoff Lang4ad17092015-03-10 16:47:44 -0400628}
629
Jamie Madill19fa1c62018-03-08 09:47:21 -0500630gl::Error FramebufferGL::syncState(const gl::Context *context,
631 const Framebuffer::DirtyBits &dirtyBits)
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500632{
633 // Don't need to sync state for the default FBO.
634 if (mIsDefault)
635 {
Jamie Madill19fa1c62018-03-08 09:47:21 -0500636 return gl::NoError();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500637 }
638
Geoff Lang61107632018-05-09 11:32:46 -0400639 const FunctionsGL *functions = GetFunctionsGL(context);
640 StateManagerGL *stateManager = GetStateManagerGL(context);
641
642 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500643
Martin Radev7c2e6a92017-08-28 11:13:16 +0300644 // A pointer to one of the attachments for which the texture or the render buffer is not zero.
645 const FramebufferAttachment *attachment = nullptr;
Martin Radev878c8b12017-07-28 09:51:04 +0300646
Jamie Madill6de51852017-04-12 09:53:01 -0400647 for (auto dirtyBit : dirtyBits)
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500648 {
649 switch (dirtyBit)
650 {
651 case Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
Martin Radev7c2e6a92017-08-28 11:13:16 +0300652 {
653 const FramebufferAttachment *newAttachment = mState.getDepthAttachment();
Geoff Lang61107632018-05-09 11:32:46 -0400654 BindFramebufferAttachment(functions, GL_DEPTH_ATTACHMENT, newAttachment);
Martin Radev7c2e6a92017-08-28 11:13:16 +0300655 if (newAttachment)
656 {
657 attachment = newAttachment;
658 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500659 break;
Martin Radev7c2e6a92017-08-28 11:13:16 +0300660 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500661 case Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
Martin Radev7c2e6a92017-08-28 11:13:16 +0300662 {
663 const FramebufferAttachment *newAttachment = mState.getStencilAttachment();
Geoff Lang61107632018-05-09 11:32:46 -0400664 BindFramebufferAttachment(functions, GL_STENCIL_ATTACHMENT, newAttachment);
Martin Radev7c2e6a92017-08-28 11:13:16 +0300665 if (newAttachment)
666 {
667 attachment = newAttachment;
668 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500669 break;
Martin Radev7c2e6a92017-08-28 11:13:16 +0300670 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500671 case Framebuffer::DIRTY_BIT_DRAW_BUFFERS:
672 {
Jamie Madill48ef11b2016-04-27 15:21:52 -0400673 const auto &drawBuffers = mState.getDrawBufferStates();
Geoff Lang61107632018-05-09 11:32:46 -0400674 functions->drawBuffers(static_cast<GLsizei>(drawBuffers.size()),
675 drawBuffers.data());
Corentin Walleze7557742017-06-01 13:09:57 -0400676 mAppliedEnabledDrawBuffers = mState.getEnabledDrawBuffers();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500677 break;
678 }
679 case Framebuffer::DIRTY_BIT_READ_BUFFER:
Geoff Lang61107632018-05-09 11:32:46 -0400680 functions->readBuffer(mState.getReadBufferState());
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500681 break;
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800682 case Framebuffer::DIRTY_BIT_DEFAULT_WIDTH:
Geoff Lang61107632018-05-09 11:32:46 -0400683 functions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH,
684 mState.getDefaultWidth());
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800685 break;
686 case Framebuffer::DIRTY_BIT_DEFAULT_HEIGHT:
Geoff Lang61107632018-05-09 11:32:46 -0400687 functions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT,
688 mState.getDefaultHeight());
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800689 break;
690 case Framebuffer::DIRTY_BIT_DEFAULT_SAMPLES:
Geoff Lang61107632018-05-09 11:32:46 -0400691 functions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_SAMPLES,
692 mState.getDefaultSamples());
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800693 break;
694 case Framebuffer::DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS:
Geoff Lang61107632018-05-09 11:32:46 -0400695 functions->framebufferParameteri(
Geoff Lang92019432017-11-20 13:09:34 -0500696 GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS,
697 gl::ConvertToGLBoolean(mState.getDefaultFixedSampleLocations()));
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800698 break;
Jiawei Shaob1e91382018-05-17 14:33:55 +0800699 case Framebuffer::DIRTY_BIT_DEFAULT_LAYERS:
700 functions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT,
701 mState.getDefaultLayers());
702 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500703 default:
704 {
705 ASSERT(Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0 &&
706 dirtyBit < Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX);
707 size_t index =
708 static_cast<size_t>(dirtyBit - Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
Martin Radev7c2e6a92017-08-28 11:13:16 +0300709 const FramebufferAttachment *newAttachment = mState.getColorAttachment(index);
710 BindFramebufferAttachment(
Geoff Lang61107632018-05-09 11:32:46 -0400711 functions, static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + index), newAttachment);
Martin Radev7c2e6a92017-08-28 11:13:16 +0300712 if (newAttachment)
713 {
714 attachment = newAttachment;
715 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500716 break;
717 }
718 }
719 }
Martin Radev878c8b12017-07-28 09:51:04 +0300720
Martin Radev7c2e6a92017-08-28 11:13:16 +0300721 if (attachment)
Martin Radev878c8b12017-07-28 09:51:04 +0300722 {
Martin Radev7c2e6a92017-08-28 11:13:16 +0300723 const bool isSideBySide =
724 (attachment->getMultiviewLayout() == GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE);
Geoff Lang61107632018-05-09 11:32:46 -0400725 stateManager->setSideBySide(isSideBySide);
726 stateManager->setViewportOffsets(attachment->getMultiviewViewportOffsets());
727 stateManager->updateMultiviewBaseViewLayerIndexUniform(context->getGLState().getProgram(),
728 getState());
Martin Radev878c8b12017-07-28 09:51:04 +0300729 }
Jamie Madill19fa1c62018-03-08 09:47:21 -0500730
731 return gl::NoError();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500732}
733
Geoff Lang4ad17092015-03-10 16:47:44 -0400734GLuint FramebufferGL::getFramebufferID() const
735{
736 return mFramebufferID;
Geoff Langf9a6f082015-01-22 13:32:49 -0500737}
738
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700739bool FramebufferGL::isDefault() const
Geoff Langafd7f0a2015-09-09 15:33:31 -0400740{
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700741 return mIsDefault;
Geoff Langafd7f0a2015-09-09 15:33:31 -0400742}
743
Geoff Lang61107632018-05-09 11:32:46 -0400744void FramebufferGL::maskOutInactiveOutputDrawBuffers(const gl::Context *context,
745 GLenum binding,
746 DrawBufferMask maxSet)
Corentin Walleze7557742017-06-01 13:09:57 -0400747{
Geoff Lang61107632018-05-09 11:32:46 -0400748
Corentin Walleze7557742017-06-01 13:09:57 -0400749 auto targetAppliedDrawBuffers = mState.getEnabledDrawBuffers() & maxSet;
750 if (mAppliedEnabledDrawBuffers != targetAppliedDrawBuffers)
751 {
752 mAppliedEnabledDrawBuffers = targetAppliedDrawBuffers;
753
754 const auto &stateDrawBuffers = mState.getDrawBufferStates();
755 GLsizei drawBufferCount = static_cast<GLsizei>(stateDrawBuffers.size());
756 ASSERT(drawBufferCount <= IMPLEMENTATION_MAX_DRAW_BUFFERS);
757
758 GLenum drawBuffers[IMPLEMENTATION_MAX_DRAW_BUFFERS];
759 for (GLenum i = 0; static_cast<int>(i) < drawBufferCount; ++i)
760 {
761 drawBuffers[i] = targetAppliedDrawBuffers[i] ? stateDrawBuffers[i] : GL_NONE;
762 }
763
Geoff Lang61107632018-05-09 11:32:46 -0400764 const FunctionsGL *functions = GetFunctionsGL(context);
765 StateManagerGL *stateManager = GetStateManagerGL(context);
766
767 stateManager->bindFramebuffer(binding, mFramebufferID);
768 functions->drawBuffers(drawBufferCount, drawBuffers);
Corentin Walleze7557742017-06-01 13:09:57 -0400769 }
770}
771
Jamie Madillc564c072017-06-01 12:45:42 -0400772void FramebufferGL::syncClearState(const gl::Context *context, GLbitfield mask)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400773{
Geoff Lang61107632018-05-09 11:32:46 -0400774 const FunctionsGL *functions = GetFunctionsGL(context);
775
776 if (functions->standard == STANDARD_GL_DESKTOP)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400777 {
Geoff Lang61107632018-05-09 11:32:46 -0400778 StateManagerGL *stateManager = GetStateManagerGL(context);
779 const WorkaroundsGL &workarounds = GetWorkaroundsGL(context);
780
781 if (workarounds.doesSRGBClearsOnLinearFramebufferAttachments &&
Frank Henigmana3d333c2016-03-22 22:09:14 -0400782 (mask & GL_COLOR_BUFFER_BIT) != 0 && !mIsDefault)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400783 {
Corentin Wallez26a717b2016-09-27 08:45:42 -0700784 bool hasSRGBAttachment = false;
Jamie Madill48ef11b2016-04-27 15:21:52 -0400785 for (const auto &attachment : mState.getColorAttachments())
Geoff Langafd7f0a2015-09-09 15:33:31 -0400786 {
Frank Henigmana3d333c2016-03-22 22:09:14 -0400787 if (attachment.isAttached() && attachment.getColorEncoding() == GL_SRGB)
788 {
Corentin Wallez26a717b2016-09-27 08:45:42 -0700789 hasSRGBAttachment = true;
Frank Henigmana3d333c2016-03-22 22:09:14 -0400790 break;
791 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400792 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400793
Geoff Lang61107632018-05-09 11:32:46 -0400794 stateManager->setFramebufferSRGBEnabled(context, hasSRGBAttachment);
Frank Henigmana3d333c2016-03-22 22:09:14 -0400795 }
796 else
797 {
Geoff Lang61107632018-05-09 11:32:46 -0400798 stateManager->setFramebufferSRGBEnabled(context, !mIsDefault);
Frank Henigmana3d333c2016-03-22 22:09:14 -0400799 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400800 }
801}
802
Jamie Madillc564c072017-06-01 12:45:42 -0400803void FramebufferGL::syncClearBufferState(const gl::Context *context,
804 GLenum buffer,
805 GLint drawBuffer)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400806{
Geoff Lang61107632018-05-09 11:32:46 -0400807 const FunctionsGL *functions = GetFunctionsGL(context);
808
809 if (functions->standard == STANDARD_GL_DESKTOP)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400810 {
Geoff Lang61107632018-05-09 11:32:46 -0400811 StateManagerGL *stateManager = GetStateManagerGL(context);
812 const WorkaroundsGL &workarounds = GetWorkaroundsGL(context);
813
814 if (workarounds.doesSRGBClearsOnLinearFramebufferAttachments && buffer == GL_COLOR &&
Geoff Langafd7f0a2015-09-09 15:33:31 -0400815 !mIsDefault)
816 {
817 // If doing a clear on a color buffer, set SRGB blend enabled only if the color buffer
818 // is an SRGB format.
Jamie Madill48ef11b2016-04-27 15:21:52 -0400819 const auto &drawbufferState = mState.getDrawBufferStates();
820 const auto &colorAttachments = mState.getColorAttachments();
Geoff Langafd7f0a2015-09-09 15:33:31 -0400821
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500822 const FramebufferAttachment *attachment = nullptr;
Geoff Langafd7f0a2015-09-09 15:33:31 -0400823 if (drawbufferState[drawBuffer] >= GL_COLOR_ATTACHMENT0 &&
824 drawbufferState[drawBuffer] < GL_COLOR_ATTACHMENT0 + colorAttachments.size())
825 {
826 size_t attachmentIdx =
827 static_cast<size_t>(drawbufferState[drawBuffer] - GL_COLOR_ATTACHMENT0);
828 attachment = &colorAttachments[attachmentIdx];
829 }
830
831 if (attachment != nullptr)
832 {
Geoff Lang61107632018-05-09 11:32:46 -0400833 stateManager->setFramebufferSRGBEnabled(context,
834 attachment->getColorEncoding() == GL_SRGB);
Geoff Langafd7f0a2015-09-09 15:33:31 -0400835 }
836 }
837 else
838 {
Geoff Lang61107632018-05-09 11:32:46 -0400839 stateManager->setFramebufferSRGBEnabled(context, !mIsDefault);
Geoff Langafd7f0a2015-09-09 15:33:31 -0400840 }
841 }
842}
Geoff Lang005a7012017-03-27 13:17:34 -0400843
844bool FramebufferGL::modifyInvalidateAttachmentsForEmulatedDefaultFBO(
845 size_t count,
846 const GLenum *attachments,
847 std::vector<GLenum> *modifiedAttachments) const
848{
849 bool needsModification = mIsDefault && mFramebufferID != 0;
850 if (!needsModification)
851 {
852 return false;
853 }
854
855 modifiedAttachments->resize(count);
856 for (size_t i = 0; i < count; i++)
857 {
858 switch (attachments[i])
859 {
860 case GL_COLOR:
861 (*modifiedAttachments)[i] = GL_COLOR_ATTACHMENT0;
862 break;
863
864 case GL_DEPTH:
865 (*modifiedAttachments)[i] = GL_DEPTH_ATTACHMENT;
866 break;
867
868 case GL_STENCIL:
869 (*modifiedAttachments)[i] = GL_STENCIL_ATTACHMENT;
870 break;
871
872 default:
873 UNREACHABLE();
874 break;
875 }
876 }
877
878 return true;
879}
880
Frank Henigmanfa36c332017-06-09 18:44:45 -0400881gl::Error FramebufferGL::readPixelsRowByRow(const gl::Context *context,
882 const gl::Rectangle &area,
883 GLenum format,
884 GLenum type,
885 const gl::PixelPackState &pack,
886 GLubyte *pixels) const
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400887{
Geoff Lang61107632018-05-09 11:32:46 -0400888 const FunctionsGL *functions = GetFunctionsGL(context);
889 StateManagerGL *stateManager = GetStateManagerGL(context);
890
Geoff Langca271392017-04-05 12:30:00 -0400891 const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(format, type);
Frank Henigmanfa36c332017-06-09 18:44:45 -0400892
893 GLuint rowBytes = 0;
Jamie Madillca2ff382018-07-11 09:01:17 -0400894 ANGLE_TRY_CHECKED_MATH(
895 glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength, &rowBytes));
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400896 GLuint skipBytes = 0;
Jamie Madillca2ff382018-07-11 09:01:17 -0400897 ANGLE_TRY_CHECKED_MATH(glFormat.computeSkipBytes(type, rowBytes, 0, pack, false, &skipBytes));
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400898
899 gl::PixelPackState directPack;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400900 directPack.alignment = 1;
Geoff Lang61107632018-05-09 11:32:46 -0400901 stateManager->setPixelPackState(directPack);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400902
Frank Henigmanfa36c332017-06-09 18:44:45 -0400903 pixels += skipBytes;
904 for (GLint y = area.y; y < area.y + area.height; ++y)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400905 {
Geoff Lang61107632018-05-09 11:32:46 -0400906 functions->readPixels(area.x, y, area.width, 1, format, type, pixels);
Frank Henigmanfa36c332017-06-09 18:44:45 -0400907 pixels += rowBytes;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400908 }
909
910 return gl::NoError();
911}
912
Frank Henigmanfa36c332017-06-09 18:44:45 -0400913gl::Error FramebufferGL::readPixelsAllAtOnce(const gl::Context *context,
914 const gl::Rectangle &area,
915 GLenum format,
916 GLenum type,
917 const gl::PixelPackState &pack,
918 GLubyte *pixels,
919 bool readLastRowSeparately) const
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400920{
Geoff Lang61107632018-05-09 11:32:46 -0400921 const FunctionsGL *functions = GetFunctionsGL(context);
922 StateManagerGL *stateManager = GetStateManagerGL(context);
923
Frank Henigmanfa36c332017-06-09 18:44:45 -0400924 GLint height = area.height - readLastRowSeparately;
925 if (height > 0)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400926 {
Geoff Lang61107632018-05-09 11:32:46 -0400927 stateManager->setPixelPackState(pack);
928 functions->readPixels(area.x, area.y, area.width, height, format, type, pixels);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400929 }
930
Frank Henigmanfa36c332017-06-09 18:44:45 -0400931 if (readLastRowSeparately)
932 {
933 const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(format, type);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400934
Frank Henigmanfa36c332017-06-09 18:44:45 -0400935 GLuint rowBytes = 0;
Jamie Madillca2ff382018-07-11 09:01:17 -0400936 ANGLE_TRY_CHECKED_MATH(
937 glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength, &rowBytes));
Frank Henigmanfa36c332017-06-09 18:44:45 -0400938 GLuint skipBytes = 0;
Jamie Madillca2ff382018-07-11 09:01:17 -0400939 ANGLE_TRY_CHECKED_MATH(
940 glFormat.computeSkipBytes(type, rowBytes, 0, pack, false, &skipBytes));
Frank Henigmanfa36c332017-06-09 18:44:45 -0400941
942 gl::PixelPackState directPack;
Frank Henigmanfa36c332017-06-09 18:44:45 -0400943 directPack.alignment = 1;
Geoff Lang61107632018-05-09 11:32:46 -0400944 stateManager->setPixelPackState(directPack);
Frank Henigmanfa36c332017-06-09 18:44:45 -0400945
946 pixels += skipBytes + (area.height - 1) * rowBytes;
Geoff Lang61107632018-05-09 11:32:46 -0400947 functions->readPixels(area.x, area.y + area.height - 1, area.width, 1, format, type,
948 pixels);
Frank Henigmanfa36c332017-06-09 18:44:45 -0400949 }
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400950
951 return gl::NoError();
952}
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500953} // namespace rx