blob: b4799e788a793486594f3b00cd6819f4aef77a37 [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"
Geoff Lang4ad17092015-03-10 16:47:44 -040013#include "libANGLE/FramebufferAttachment.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040014#include "libANGLE/State.h"
Geoff Lang4ad17092015-03-10 16:47:44 -040015#include "libANGLE/angletypes.h"
16#include "libANGLE/formatutils.h"
Geoff Lang92019432017-11-20 13:09:34 -050017#include "libANGLE/queryconversions.h"
Jamie Madill8415b5f2016-04-26 13:41:39 -040018#include "libANGLE/renderer/ContextImpl.h"
Corentin Wallez26a717b2016-09-27 08:45:42 -070019#include "libANGLE/renderer/gl/BlitGL.h"
Martin Radev5e424fa2017-08-09 16:25:36 +030020#include "libANGLE/renderer/gl/ClearMultiviewGL.h"
Frank Henigmanfa36c332017-06-09 18:44:45 -040021#include "libANGLE/renderer/gl/ContextGL.h"
Geoff Lang4ad17092015-03-10 16:47:44 -040022#include "libANGLE/renderer/gl/FunctionsGL.h"
Jacek Cabanfa60f692015-04-27 18:23:44 +020023#include "libANGLE/renderer/gl/RenderbufferGL.h"
Geoff Lang4ad17092015-03-10 16:47:44 -040024#include "libANGLE/renderer/gl/StateManagerGL.h"
25#include "libANGLE/renderer/gl/TextureGL.h"
Geoff Langafd7f0a2015-09-09 15:33:31 -040026#include "libANGLE/renderer/gl/WorkaroundsGL.h"
Geoff Langf607c602016-09-21 11:46:48 -040027#include "libANGLE/renderer/gl/formatutilsgl.h"
Corentin Wallez886de362016-09-27 10:49:35 -040028#include "libANGLE/renderer/gl/renderergl_utils.h"
Jamie Madillcc86d642015-11-24 13:00:07 -050029#include "platform/Platform.h"
Geoff Langf9a6f082015-01-22 13:32:49 -050030
Jamie Madill60ec6ea2016-01-22 15:27:19 -050031using namespace gl;
Corentin Wallez9a8d3662016-09-22 12:18:29 -040032using angle::CheckedNumeric;
Jamie Madill60ec6ea2016-01-22 15:27:19 -050033
Geoff Langf9a6f082015-01-22 13:32:49 -050034namespace rx
35{
36
Martin Radev878c8b12017-07-28 09:51:04 +030037namespace
Geoff Lang4ad17092015-03-10 16:47:44 -040038{
Geoff Langf9a6f082015-01-22 13:32:49 -050039
Martin Radev878c8b12017-07-28 09:51:04 +030040void BindFramebufferAttachment(const FunctionsGL *functions,
41 GLenum attachmentPoint,
42 const FramebufferAttachment *attachment)
Geoff Lang4ad17092015-03-10 16:47:44 -040043{
44 if (attachment)
45 {
46 if (attachment->type() == GL_TEXTURE)
47 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -050048 const Texture *texture = attachment->getTexture();
Geoff Lang4ad17092015-03-10 16:47:44 -040049 const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
50
Corentin Wallez99d492c2018-02-27 15:17:10 -050051 if (texture->getType() == TextureType::_2D ||
52 texture->getType() == TextureType::_2DMultisample ||
53 texture->getType() == TextureType::Rectangle)
Geoff Lang4ad17092015-03-10 16:47:44 -040054 {
JiangYizhoubddc46b2016-12-09 09:50:51 +080055 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint,
Corentin Wallez99d492c2018-02-27 15:17:10 -050056 ToGLenum(texture->getType()),
Geoff Lang4ad17092015-03-10 16:47:44 -040057 textureGL->getTextureID(), attachment->mipLevel());
58 }
Jiawei Shaoa8802472018-05-28 11:17:47 +080059 else if (attachment->isLayered())
60 {
61 TextureType textureType = texture->getType();
62 ASSERT(textureType == TextureType::_2DArray || textureType == TextureType::_3D ||
Olli Etuahodff32a02018-08-28 14:35:50 +030063 textureType == TextureType::CubeMap ||
64 textureType == TextureType::_2DMultisampleArray);
Jiawei Shaoa8802472018-05-28 11:17:47 +080065 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 ||
Olli Etuahofd162102018-08-27 16:14:57 +030075 texture->getType() == TextureType::_3D ||
76 texture->getType() == TextureType::_2DMultisampleArray)
Geoff Lang4ad17092015-03-10 16:47:44 -040077 {
Martin Radev5e424fa2017-08-09 16:25:36 +030078 if (attachment->getMultiviewLayout() == GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE)
79 {
80 ASSERT(functions->framebufferTexture);
81 functions->framebufferTexture(GL_FRAMEBUFFER, attachmentPoint,
82 textureGL->getTextureID(),
83 attachment->mipLevel());
84 }
85 else
86 {
87 functions->framebufferTextureLayer(GL_FRAMEBUFFER, attachmentPoint,
88 textureGL->getTextureID(),
89 attachment->mipLevel(), attachment->layer());
90 }
Geoff Lang4ad17092015-03-10 16:47:44 -040091 }
92 else
93 {
94 UNREACHABLE();
95 }
96 }
97 else if (attachment->type() == GL_RENDERBUFFER)
98 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -050099 const Renderbuffer *renderbuffer = attachment->getRenderbuffer();
Geoff Langcd69f1c2015-03-18 14:33:23 -0400100 const RenderbufferGL *renderbufferGL = GetImplAs<RenderbufferGL>(renderbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400101
Geoff Langcd69f1c2015-03-18 14:33:23 -0400102 functions->framebufferRenderbuffer(GL_FRAMEBUFFER, attachmentPoint, GL_RENDERBUFFER,
103 renderbufferGL->getRenderbufferID());
Geoff Lang4ad17092015-03-10 16:47:44 -0400104 }
105 else
106 {
107 UNREACHABLE();
108 }
109 }
110 else
111 {
112 // Unbind this attachment
113 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_2D, 0, 0);
114 }
115}
Geoff Langf9a6f082015-01-22 13:32:49 -0500116
Martin Radev61e710b2017-09-05 11:59:52 +0300117bool AreAllLayersActive(const FramebufferAttachment &attachment)
Martin Radevb0761932017-07-25 17:42:25 +0300118{
Martin Radev61e710b2017-09-05 11:59:52 +0300119 int baseViewIndex = attachment.getBaseViewIndex();
120 if (baseViewIndex != 0)
121 {
122 return false;
123 }
124 const ImageIndex &imageIndex = attachment.getTextureImageIndex();
Jamie Madillcc129372018-04-12 09:13:18 -0400125 int numLayers = static_cast<int>(
126 attachment.getTexture()->getDepth(imageIndex.getTarget(), imageIndex.getLevelIndex()));
Martin Radev61e710b2017-09-05 11:59:52 +0300127 return (attachment.getNumViews() == numLayers);
128}
129
130bool RequiresMultiviewClear(const FramebufferState &state, bool scissorTestEnabled)
131{
132 // Get one attachment and check whether all layers are attached.
133 const FramebufferAttachment *attachment = nullptr;
134 bool allTextureArraysAreFullyAttached = true;
135 for (const FramebufferAttachment &colorAttachment : state.getColorAttachments())
136 {
137 if (colorAttachment.isAttached())
138 {
139 if (colorAttachment.getMultiviewLayout() == GL_NONE)
140 {
141 return false;
142 }
143 attachment = &colorAttachment;
144 allTextureArraysAreFullyAttached =
145 allTextureArraysAreFullyAttached && AreAllLayersActive(*attachment);
146 }
147 }
148
149 const FramebufferAttachment *depthAttachment = state.getDepthAttachment();
150 if (depthAttachment)
151 {
152 if (depthAttachment->getMultiviewLayout() == GL_NONE)
153 {
154 return false;
155 }
156 attachment = depthAttachment;
157 allTextureArraysAreFullyAttached =
158 allTextureArraysAreFullyAttached && AreAllLayersActive(*attachment);
159 }
160 const FramebufferAttachment *stencilAttachment = state.getStencilAttachment();
161 if (stencilAttachment)
162 {
163 if (stencilAttachment->getMultiviewLayout() == GL_NONE)
164 {
165 return false;
166 }
167 attachment = stencilAttachment;
168 allTextureArraysAreFullyAttached =
169 allTextureArraysAreFullyAttached && AreAllLayersActive(*attachment);
170 }
171
Martin Radev5e424fa2017-08-09 16:25:36 +0300172 if (attachment == nullptr)
173 {
174 return false;
175 }
176 switch (attachment->getMultiviewLayout())
177 {
178 case GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE:
Martin Radev61e710b2017-09-05 11:59:52 +0300179 // If all layers of each texture array are active, then there is no need to issue a
180 // special multiview clear.
181 return !allTextureArraysAreFullyAttached;
Martin Radev5e424fa2017-08-09 16:25:36 +0300182 case GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE:
183 return (scissorTestEnabled == true);
Martin Radev5e424fa2017-08-09 16:25:36 +0300184 default:
185 UNREACHABLE();
186 }
187 return false;
Martin Radevb0761932017-07-25 17:42:25 +0300188}
189
Martin Radev878c8b12017-07-28 09:51:04 +0300190} // namespace
191
Geoff Lang61107632018-05-09 11:32:46 -0400192FramebufferGL::FramebufferGL(const gl::FramebufferState &data, GLuint id, bool isDefault)
193 : FramebufferImpl(data),
Martin Radev878c8b12017-07-28 09:51:04 +0300194 mFramebufferID(id),
Geoff Lang61107632018-05-09 11:32:46 -0400195 mIsDefault(isDefault),
Martin Radev878c8b12017-07-28 09:51:04 +0300196 mAppliedEnabledDrawBuffers(1)
Jamie Madillb980c562018-11-27 11:34:27 -0500197{}
Martin Radev878c8b12017-07-28 09:51:04 +0300198
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 Madill64b7c4f2018-10-19 11:38:04 -0400211angle::Result FramebufferGL::discard(const gl::Context *context,
212 size_t count,
213 const GLenum *attachments)
Austin Kinross08332632015-05-05 13:35:47 -0700214{
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500215 // glInvalidateFramebuffer accepts the same enums as glDiscardFramebufferEXT
Jamie Madill4928b7c2017-06-20 12:57:39 -0400216 return invalidate(context, count, attachments);
Austin Kinross08332632015-05-05 13:35:47 -0700217}
218
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400219angle::Result FramebufferGL::invalidate(const gl::Context *context,
220 size_t count,
221 const GLenum *attachments)
Geoff Langf9a6f082015-01-22 13:32:49 -0500222{
Geoff Lang005a7012017-03-27 13:17:34 -0400223 const GLenum *finalAttachmentsPtr = attachments;
224
225 std::vector<GLenum> modifiedAttachments;
226 if (modifyInvalidateAttachmentsForEmulatedDefaultFBO(count, attachments, &modifiedAttachments))
227 {
228 finalAttachmentsPtr = modifiedAttachments.data();
229 }
230
Geoff Lang61107632018-05-09 11:32:46 -0400231 const FunctionsGL *functions = GetFunctionsGL(context);
232 StateManagerGL *stateManager = GetStateManagerGL(context);
233
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500234 // Since this function is just a hint, only call a native function if it exists.
Geoff Lang61107632018-05-09 11:32:46 -0400235 if (functions->invalidateFramebuffer)
Geoff Lang64a72442015-04-01 14:43:11 -0400236 {
Geoff Lang61107632018-05-09 11:32:46 -0400237 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
238 functions->invalidateFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
239 finalAttachmentsPtr);
Geoff Lang64a72442015-04-01 14:43:11 -0400240 }
Geoff Lang61107632018-05-09 11:32:46 -0400241 else if (functions->discardFramebufferEXT)
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500242 {
Geoff Lang61107632018-05-09 11:32:46 -0400243 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
244 functions->discardFramebufferEXT(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
245 finalAttachmentsPtr);
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500246 }
Geoff Lang64a72442015-04-01 14:43:11 -0400247
Jamie Madill7c985f52018-11-29 18:16:17 -0500248 return angle::Result::Continue;
Geoff Langf9a6f082015-01-22 13:32:49 -0500249}
250
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400251angle::Result FramebufferGL::invalidateSub(const gl::Context *context,
252 size_t count,
253 const GLenum *attachments,
254 const gl::Rectangle &area)
Geoff Langf9a6f082015-01-22 13:32:49 -0500255{
Geoff Lang005a7012017-03-27 13:17:34 -0400256
257 const GLenum *finalAttachmentsPtr = attachments;
258
259 std::vector<GLenum> modifiedAttachments;
260 if (modifyInvalidateAttachmentsForEmulatedDefaultFBO(count, attachments, &modifiedAttachments))
261 {
262 finalAttachmentsPtr = modifiedAttachments.data();
263 }
264
Geoff Lang61107632018-05-09 11:32:46 -0400265 const FunctionsGL *functions = GetFunctionsGL(context);
266 StateManagerGL *stateManager = GetStateManagerGL(context);
267
Jamie Madill231c7f52017-04-26 13:45:37 -0400268 // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is
269 // available.
Geoff Lang61107632018-05-09 11:32:46 -0400270 if (functions->invalidateSubFramebuffer)
Geoff Lang64a72442015-04-01 14:43:11 -0400271 {
Geoff Lang61107632018-05-09 11:32:46 -0400272 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
273 functions->invalidateSubFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
274 finalAttachmentsPtr, area.x, area.y, area.width,
275 area.height);
Geoff Lang64a72442015-04-01 14:43:11 -0400276 }
277
Jamie Madill7c985f52018-11-29 18:16:17 -0500278 return angle::Result::Continue;
Geoff Langf9a6f082015-01-22 13:32:49 -0500279}
280
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400281angle::Result FramebufferGL::clear(const gl::Context *context, GLbitfield mask)
Geoff Langf9a6f082015-01-22 13:32:49 -0500282{
Geoff Lang61107632018-05-09 11:32:46 -0400283 const FunctionsGL *functions = GetFunctionsGL(context);
284 StateManagerGL *stateManager = GetStateManagerGL(context);
285
Frank Henigman308d7452017-02-15 22:51:21 -0500286 syncClearState(context, mask);
Geoff Lang61107632018-05-09 11:32:46 -0400287 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300288
Jamie Madillc3dc5d42018-12-30 12:12:04 -0500289 if (!RequiresMultiviewClear(mState, context->getState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300290 {
Geoff Lang61107632018-05-09 11:32:46 -0400291 functions->clear(mask);
Martin Radevb0761932017-07-25 17:42:25 +0300292 }
293 else
294 {
Geoff Lang61107632018-05-09 11:32:46 -0400295 ClearMultiviewGL *multiviewClearer = GetMultiviewClearer(context);
Jamie Madillc3dc5d42018-12-30 12:12:04 -0500296 multiviewClearer->clearMultiviewFBO(mState, context->getState().getScissor(),
Geoff Lang61107632018-05-09 11:32:46 -0400297 ClearMultiviewGL::ClearCommandType::Clear, mask,
298 GL_NONE, 0, nullptr, 0.0f, 0);
Martin Radevb0761932017-07-25 17:42:25 +0300299 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400300
Jamie Madill7c985f52018-11-29 18:16:17 -0500301 return angle::Result::Continue;
Geoff Lang4ad17092015-03-10 16:47:44 -0400302}
303
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400304angle::Result FramebufferGL::clearBufferfv(const gl::Context *context,
305 GLenum buffer,
306 GLint drawbuffer,
307 const GLfloat *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500308{
Geoff Lang61107632018-05-09 11:32:46 -0400309 const FunctionsGL *functions = GetFunctionsGL(context);
310 StateManagerGL *stateManager = GetStateManagerGL(context);
311
Frank Henigman308d7452017-02-15 22:51:21 -0500312 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang61107632018-05-09 11:32:46 -0400313 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300314
Jamie Madillc3dc5d42018-12-30 12:12:04 -0500315 if (!RequiresMultiviewClear(mState, context->getState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300316 {
Geoff Lang61107632018-05-09 11:32:46 -0400317 functions->clearBufferfv(buffer, drawbuffer, values);
Martin Radevb0761932017-07-25 17:42:25 +0300318 }
319 else
320 {
Geoff Lang61107632018-05-09 11:32:46 -0400321 ClearMultiviewGL *multiviewClearer = GetMultiviewClearer(context);
Jamie Madillc3dc5d42018-12-30 12:12:04 -0500322 multiviewClearer->clearMultiviewFBO(mState, context->getState().getScissor(),
Geoff Lang61107632018-05-09 11:32:46 -0400323 ClearMultiviewGL::ClearCommandType::ClearBufferfv,
324 static_cast<GLbitfield>(0u), buffer, drawbuffer,
325 reinterpret_cast<const uint8_t *>(values), 0.0f, 0);
Martin Radevb0761932017-07-25 17:42:25 +0300326 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400327
Jamie Madill7c985f52018-11-29 18:16:17 -0500328 return angle::Result::Continue;
Geoff Langf9a6f082015-01-22 13:32:49 -0500329}
330
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400331angle::Result FramebufferGL::clearBufferuiv(const gl::Context *context,
332 GLenum buffer,
333 GLint drawbuffer,
334 const GLuint *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500335{
Geoff Lang61107632018-05-09 11:32:46 -0400336 const FunctionsGL *functions = GetFunctionsGL(context);
337 StateManagerGL *stateManager = GetStateManagerGL(context);
338
Frank Henigman308d7452017-02-15 22:51:21 -0500339 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang61107632018-05-09 11:32:46 -0400340 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300341
Jamie Madillc3dc5d42018-12-30 12:12:04 -0500342 if (!RequiresMultiviewClear(mState, context->getState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300343 {
Geoff Lang61107632018-05-09 11:32:46 -0400344 functions->clearBufferuiv(buffer, drawbuffer, values);
Martin Radevb0761932017-07-25 17:42:25 +0300345 }
346 else
347 {
Geoff Lang61107632018-05-09 11:32:46 -0400348 ClearMultiviewGL *multiviewClearer = GetMultiviewClearer(context);
Jamie Madillc3dc5d42018-12-30 12:12:04 -0500349 multiviewClearer->clearMultiviewFBO(mState, context->getState().getScissor(),
Geoff Lang61107632018-05-09 11:32:46 -0400350 ClearMultiviewGL::ClearCommandType::ClearBufferuiv,
351 static_cast<GLbitfield>(0u), buffer, drawbuffer,
352 reinterpret_cast<const uint8_t *>(values), 0.0f, 0);
Martin Radevb0761932017-07-25 17:42:25 +0300353 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400354
Jamie Madill7c985f52018-11-29 18:16:17 -0500355 return angle::Result::Continue;
Geoff Langf9a6f082015-01-22 13:32:49 -0500356}
357
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400358angle::Result FramebufferGL::clearBufferiv(const gl::Context *context,
359 GLenum buffer,
360 GLint drawbuffer,
361 const GLint *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500362{
Geoff Lang61107632018-05-09 11:32:46 -0400363 const FunctionsGL *functions = GetFunctionsGL(context);
364 StateManagerGL *stateManager = GetStateManagerGL(context);
365
Frank Henigman308d7452017-02-15 22:51:21 -0500366 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang61107632018-05-09 11:32:46 -0400367 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300368
Jamie Madillc3dc5d42018-12-30 12:12:04 -0500369 if (!RequiresMultiviewClear(mState, context->getState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300370 {
Geoff Lang61107632018-05-09 11:32:46 -0400371 functions->clearBufferiv(buffer, drawbuffer, values);
Martin Radevb0761932017-07-25 17:42:25 +0300372 }
373 else
374 {
Geoff Lang61107632018-05-09 11:32:46 -0400375 ClearMultiviewGL *multiviewClearer = GetMultiviewClearer(context);
Jamie Madillc3dc5d42018-12-30 12:12:04 -0500376 multiviewClearer->clearMultiviewFBO(mState, context->getState().getScissor(),
Geoff Lang61107632018-05-09 11:32:46 -0400377 ClearMultiviewGL::ClearCommandType::ClearBufferiv,
378 static_cast<GLbitfield>(0u), buffer, drawbuffer,
379 reinterpret_cast<const uint8_t *>(values), 0.0f, 0);
Martin Radevb0761932017-07-25 17:42:25 +0300380 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400381
Jamie Madill7c985f52018-11-29 18:16:17 -0500382 return angle::Result::Continue;
Geoff Langf9a6f082015-01-22 13:32:49 -0500383}
384
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400385angle::Result FramebufferGL::clearBufferfi(const gl::Context *context,
386 GLenum buffer,
387 GLint drawbuffer,
388 GLfloat depth,
389 GLint stencil)
Geoff Langf9a6f082015-01-22 13:32:49 -0500390{
Geoff Lang61107632018-05-09 11:32:46 -0400391 const FunctionsGL *functions = GetFunctionsGL(context);
392 StateManagerGL *stateManager = GetStateManagerGL(context);
393
Frank Henigman308d7452017-02-15 22:51:21 -0500394 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang61107632018-05-09 11:32:46 -0400395 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300396
Jamie Madillc3dc5d42018-12-30 12:12:04 -0500397 if (!RequiresMultiviewClear(mState, context->getState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300398 {
Geoff Lang61107632018-05-09 11:32:46 -0400399 functions->clearBufferfi(buffer, drawbuffer, depth, stencil);
Martin Radevb0761932017-07-25 17:42:25 +0300400 }
Martin Radev5e424fa2017-08-09 16:25:36 +0300401 else
402 {
Geoff Lang61107632018-05-09 11:32:46 -0400403 ClearMultiviewGL *multiviewClearer = GetMultiviewClearer(context);
Jamie Madillc3dc5d42018-12-30 12:12:04 -0500404 multiviewClearer->clearMultiviewFBO(mState, context->getState().getScissor(),
Geoff Lang61107632018-05-09 11:32:46 -0400405 ClearMultiviewGL::ClearCommandType::ClearBufferfi,
406 static_cast<GLbitfield>(0u), buffer, drawbuffer,
407 nullptr, depth, stencil);
Martin Radev5e424fa2017-08-09 16:25:36 +0300408 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400409
Jamie Madill7c985f52018-11-29 18:16:17 -0500410 return angle::Result::Continue;
Geoff Langf9a6f082015-01-22 13:32:49 -0500411}
412
Jamie Madill4928b7c2017-06-20 12:57:39 -0400413GLenum FramebufferGL::getImplementationColorReadFormat(const gl::Context *context) const
Geoff Langf9a6f082015-01-22 13:32:49 -0500414{
Jamie Madilla3944d42016-07-22 22:13:26 -0400415 const auto *readAttachment = mState.getReadAttachment();
416 const Format &format = readAttachment->getFormat();
Geoff Langf607c602016-09-21 11:46:48 -0400417 return format.info->getReadPixelsFormat();
Geoff Langf9a6f082015-01-22 13:32:49 -0500418}
419
Jamie Madill4928b7c2017-06-20 12:57:39 -0400420GLenum FramebufferGL::getImplementationColorReadType(const gl::Context *context) const
Geoff Langf9a6f082015-01-22 13:32:49 -0500421{
Jamie Madilla3944d42016-07-22 22:13:26 -0400422 const auto *readAttachment = mState.getReadAttachment();
423 const Format &format = readAttachment->getFormat();
Geoff Langc71ea662017-09-26 17:06:02 -0400424 return format.info->getReadPixelsType(context->getClientVersion());
Geoff Langf9a6f082015-01-22 13:32:49 -0500425}
426
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400427angle::Result FramebufferGL::readPixels(const gl::Context *context,
428 const gl::Rectangle &area,
429 GLenum format,
430 GLenum type,
431 void *pixels)
Geoff Langf9a6f082015-01-22 13:32:49 -0500432{
Jamie Madille39e8f42018-10-05 08:17:38 -0400433 ContextGL *contextGL = GetImplAs<ContextGL>(context);
Geoff Lang61107632018-05-09 11:32:46 -0400434 const FunctionsGL *functions = GetFunctionsGL(context);
435 StateManagerGL *stateManager = GetStateManagerGL(context);
436 const WorkaroundsGL &workarounds = GetWorkaroundsGL(context);
437
Frank Henigmanfa36c332017-06-09 18:44:45 -0400438 // Clip read area to framebuffer.
439 const gl::Extents fbSize = getState().getReadAttachment()->getSize();
440 const gl::Rectangle fbRect(0, 0, fbSize.width, fbSize.height);
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400441 gl::Rectangle clippedArea;
442 if (!ClipRectangle(area, fbRect, &clippedArea))
Frank Henigmanfa36c332017-06-09 18:44:45 -0400443 {
444 // nothing to read
Jamie Madill7c985f52018-11-29 18:16:17 -0500445 return angle::Result::Continue;
Frank Henigmanfa36c332017-06-09 18:44:45 -0400446 }
447
Jamie Madillc3dc5d42018-12-30 12:12:04 -0500448 PixelPackState packState = context->getState().getPackState();
Corentin Wallez336129f2017-10-17 15:55:40 -0400449 const gl::Buffer *packBuffer =
Jamie Madillc3dc5d42018-12-30 12:12:04 -0500450 context->getState().getTargetBuffer(gl::BufferBinding::PixelPack);
Jamie Madill87de3622015-03-16 10:41:44 -0400451
Geoff Langf607c602016-09-21 11:46:48 -0400452 nativegl::ReadPixelsFormat readPixelsFormat =
Geoff Lang61107632018-05-09 11:32:46 -0400453 nativegl::GetReadPixelsFormat(functions, workarounds, format, type);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400454 GLenum readFormat = readPixelsFormat.format;
455 GLenum readType = readPixelsFormat.type;
Geoff Lang4ad17092015-03-10 16:47:44 -0400456
Geoff Lang61107632018-05-09 11:32:46 -0400457 stateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, mFramebufferID);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400458
Geoff Lang61107632018-05-09 11:32:46 -0400459 bool useOverlappingRowsWorkaround = workarounds.packOverlappingRowsSeparatelyPackBuffer &&
Corentin Wallezcda6af12017-10-30 19:20:37 -0400460 packBuffer && packState.rowLength != 0 &&
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400461 packState.rowLength < clippedArea.width;
Frank Henigmanfa36c332017-06-09 18:44:45 -0400462
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400463 GLubyte *outPtr = static_cast<GLubyte *>(pixels);
464 int leftClip = clippedArea.x - area.x;
465 int topClip = clippedArea.y - area.y;
Frank Henigmanfa36c332017-06-09 18:44:45 -0400466 if (leftClip || topClip)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400467 {
Frank Henigmanfa36c332017-06-09 18:44:45 -0400468 // Adjust destination to match portion clipped off left and/or top.
469 const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(readFormat, readType);
470
471 GLuint rowBytes = 0;
Jamie Madille39e8f42018-10-05 08:17:38 -0400472 ANGLE_CHECK_GL_MATH(contextGL,
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400473 glFormat.computeRowPitch(readType, area.width, packState.alignment,
Jamie Madille39e8f42018-10-05 08:17:38 -0400474 packState.rowLength, &rowBytes));
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400475 outPtr += leftClip * glFormat.pixelBytes + topClip * rowBytes;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400476 }
477
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400478 if (packState.rowLength == 0 && clippedArea.width != area.width)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400479 {
Frank Henigmanfa36c332017-06-09 18:44:45 -0400480 // No rowLength was specified so it will derive from read width, but clipping changed the
481 // read width. Use the original width so we fill the user's buffer as they intended.
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400482 packState.rowLength = area.width;
Frank Henigmanfa36c332017-06-09 18:44:45 -0400483 }
Corentin Wallez886de362016-09-27 10:49:35 -0400484
Frank Henigmanfa36c332017-06-09 18:44:45 -0400485 // We want to use rowLength, but that might not be supported.
486 bool cannotSetDesiredRowLength =
487 packState.rowLength && !GetImplAs<ContextGL>(context)->getNativeExtensions().packSubimage;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400488
Frank Henigmanfa36c332017-06-09 18:44:45 -0400489 if (cannotSetDesiredRowLength || useOverlappingRowsWorkaround)
490 {
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400491 return readPixelsRowByRow(context, clippedArea, readFormat, readType, packState, outPtr);
Frank Henigmanfa36c332017-06-09 18:44:45 -0400492 }
Jamie Madill13951342018-09-30 15:24:28 -0400493
494 bool useLastRowPaddingWorkaround = false;
495 if (workarounds.packLastRowSeparatelyForPaddingInclusion)
Frank Henigmanfa36c332017-06-09 18:44:45 -0400496 {
Jamie Madille39e8f42018-10-05 08:17:38 -0400497 ANGLE_TRY(ShouldApplyLastRowPaddingWorkaround(
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400498 contextGL, gl::Extents(clippedArea.width, clippedArea.height, 1), packState, packBuffer,
499 readFormat, readType, false, outPtr, &useLastRowPaddingWorkaround));
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400500 }
501
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400502 return readPixelsAllAtOnce(context, clippedArea, readFormat, readType, packState, outPtr,
Jamie Madill13951342018-09-30 15:24:28 -0400503 useLastRowPaddingWorkaround);
Geoff Langf9a6f082015-01-22 13:32:49 -0500504}
505
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400506angle::Result FramebufferGL::blit(const gl::Context *context,
507 const gl::Rectangle &sourceArea,
508 const gl::Rectangle &destArea,
509 GLbitfield mask,
510 GLenum filter)
Geoff Langf9a6f082015-01-22 13:32:49 -0500511{
Geoff Lang61107632018-05-09 11:32:46 -0400512 const FunctionsGL *functions = GetFunctionsGL(context);
513 StateManagerGL *stateManager = GetStateManagerGL(context);
514
Jamie Madillc3dc5d42018-12-30 12:12:04 -0500515 const Framebuffer *sourceFramebuffer = context->getState().getReadFramebuffer();
516 const Framebuffer *destFramebuffer = context->getState().getDrawFramebuffer();
Geoff Lang4ad17092015-03-10 16:47:44 -0400517
Corentin Wallez6898b352016-11-10 11:41:15 -0500518 const FramebufferAttachment *colorReadAttachment = sourceFramebuffer->getReadColorbuffer();
Corentin Wallez4596a762016-12-20 14:50:18 -0500519
520 GLsizei readAttachmentSamples = 0;
521 if (colorReadAttachment != nullptr)
522 {
523 readAttachmentSamples = colorReadAttachment->getSamples();
524 }
Corentin Wallez6898b352016-11-10 11:41:15 -0500525
Corentin Wallez26a717b2016-09-27 08:45:42 -0700526 bool needManualColorBlit = false;
527
Corentin Wallez6898b352016-11-10 11:41:15 -0500528 // TODO(cwallez) when the filter is LINEAR and both source and destination are SRGB, we
529 // could avoid doing a manual blit.
530
531 // Prior to OpenGL 4.4 BlitFramebuffer (section 18.3.1 of GL 4.3 core profile) reads:
532 // When values are taken from the read buffer, no linearization is performed, even
533 // if the format of the buffer is SRGB.
534 // Starting from OpenGL 4.4 (section 18.3.1) it reads:
535 // When values are taken from the read buffer, if FRAMEBUFFER_SRGB is enabled and the
536 // value of FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING for the framebuffer attachment
537 // corresponding to the read buffer is SRGB, the red, green, and blue components are
538 // converted from the non-linear sRGB color space according [...].
Corentin Wallez26a717b2016-09-27 08:45:42 -0700539 {
Jamie Madill231c7f52017-04-26 13:45:37 -0400540 bool sourceSRGB =
541 colorReadAttachment != nullptr && colorReadAttachment->getColorEncoding() == GL_SRGB;
Corentin Wallez6898b352016-11-10 11:41:15 -0500542 needManualColorBlit =
Geoff Lang61107632018-05-09 11:32:46 -0400543 needManualColorBlit || (sourceSRGB && functions->isAtMostGL(gl::Version(4, 3)));
Corentin Wallez6898b352016-11-10 11:41:15 -0500544 }
Corentin Wallez26a717b2016-09-27 08:45:42 -0700545
Corentin Wallez6898b352016-11-10 11:41:15 -0500546 // Prior to OpenGL 4.2 BlitFramebuffer (section 4.3.2 of GL 4.1 core profile) reads:
547 // Blit operations bypass the fragment pipeline. The only fragment operations which
548 // affect a blit are the pixel ownership test and scissor test.
549 // Starting from OpenGL 4.2 (section 4.3.2) it reads:
550 // When values are written to the draw buffers, blit operations bypass the fragment
551 // pipeline. The only fragment operations which affect a blit are the pixel ownership
552 // test, the scissor test and sRGB conversion.
553 if (!needManualColorBlit)
554 {
555 bool destSRGB = false;
556 for (size_t i = 0; i < destFramebuffer->getDrawbufferStateCount(); ++i)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700557 {
Corentin Wallez6898b352016-11-10 11:41:15 -0500558 const FramebufferAttachment *attachment = destFramebuffer->getDrawBuffer(i);
559 if (attachment && attachment->getColorEncoding() == GL_SRGB)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700560 {
Corentin Wallez6898b352016-11-10 11:41:15 -0500561 destSRGB = true;
562 break;
Corentin Wallez26a717b2016-09-27 08:45:42 -0700563 }
Corentin Wallez26a717b2016-09-27 08:45:42 -0700564 }
Corentin Wallez6898b352016-11-10 11:41:15 -0500565
566 needManualColorBlit =
Geoff Lang61107632018-05-09 11:32:46 -0400567 needManualColorBlit || (destSRGB && functions->isAtMostGL(gl::Version(4, 1)));
Corentin Wallez26a717b2016-09-27 08:45:42 -0700568 }
569
570 // Enable FRAMEBUFFER_SRGB if needed
Geoff Lang61107632018-05-09 11:32:46 -0400571 stateManager->setFramebufferSRGBEnabledForFramebuffer(context, true, this);
Corentin Wallez26a717b2016-09-27 08:45:42 -0700572
573 GLenum blitMask = mask;
Corentin Wallez6898b352016-11-10 11:41:15 -0500574 if (needManualColorBlit && (mask & GL_COLOR_BUFFER_BIT) && readAttachmentSamples <= 1)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700575 {
Geoff Lang61107632018-05-09 11:32:46 -0400576 BlitGL *blitter = GetBlitGL(context);
Jamie Madille39e8f42018-10-05 08:17:38 -0400577 ANGLE_TRY(blitter->blitColorBufferWithShader(context, sourceFramebuffer, destFramebuffer,
578 sourceArea, destArea, filter));
Corentin Wallez26a717b2016-09-27 08:45:42 -0700579 blitMask &= ~GL_COLOR_BUFFER_BIT;
580 }
581
582 if (blitMask == 0)
583 {
Jamie Madill7c985f52018-11-29 18:16:17 -0500584 return angle::Result::Continue;
Corentin Wallez26a717b2016-09-27 08:45:42 -0700585 }
586
587 const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(sourceFramebuffer);
Geoff Lang61107632018-05-09 11:32:46 -0400588 stateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
589 stateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferID);
Geoff Lang4ad17092015-03-10 16:47:44 -0400590
Geoff Lang61107632018-05-09 11:32:46 -0400591 functions->blitFramebuffer(sourceArea.x, sourceArea.y, sourceArea.x1(), sourceArea.y1(),
592 destArea.x, destArea.y, destArea.x1(), destArea.y1(), blitMask,
593 filter);
Geoff Lang4ad17092015-03-10 16:47:44 -0400594
Jamie Madill7c985f52018-11-29 18:16:17 -0500595 return angle::Result::Continue;
Geoff Langf9a6f082015-01-22 13:32:49 -0500596}
597
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400598angle::Result FramebufferGL::getSamplePosition(const gl::Context *context,
599 size_t index,
600 GLfloat *xy) const
JiangYizhoubddc46b2016-12-09 09:50:51 +0800601{
Geoff Lang61107632018-05-09 11:32:46 -0400602 const FunctionsGL *functions = GetFunctionsGL(context);
603 StateManagerGL *stateManager = GetStateManagerGL(context);
604
605 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
606 functions->getMultisamplefv(GL_SAMPLE_POSITION, static_cast<GLuint>(index), xy);
Jamie Madill7c985f52018-11-29 18:16:17 -0500607 return angle::Result::Continue;
JiangYizhoubddc46b2016-12-09 09:50:51 +0800608}
609
Kenneth Russellce8602a2017-10-03 18:23:08 -0700610bool FramebufferGL::checkStatus(const gl::Context *context) const
Geoff Langf9a6f082015-01-22 13:32:49 -0500611{
Geoff Lang61107632018-05-09 11:32:46 -0400612 const FunctionsGL *functions = GetFunctionsGL(context);
613 StateManagerGL *stateManager = GetStateManagerGL(context);
614
615 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
616 GLenum status = functions->checkFramebufferStatus(GL_FRAMEBUFFER);
Jamie Madillcc86d642015-11-24 13:00:07 -0500617 if (status != GL_FRAMEBUFFER_COMPLETE)
618 {
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500619 WARN() << "GL framebuffer returned incomplete.";
Jamie Madillcc86d642015-11-24 13:00:07 -0500620 }
621 return (status == GL_FRAMEBUFFER_COMPLETE);
Geoff Lang4ad17092015-03-10 16:47:44 -0400622}
623
Jamie Madill6f755b22018-10-09 12:48:54 -0400624angle::Result FramebufferGL::syncState(const gl::Context *context,
625 const gl::Framebuffer::DirtyBits &dirtyBits)
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500626{
627 // Don't need to sync state for the default FBO.
628 if (mIsDefault)
629 {
Jamie Madill7c985f52018-11-29 18:16:17 -0500630 return angle::Result::Continue;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500631 }
632
Geoff Lang61107632018-05-09 11:32:46 -0400633 const FunctionsGL *functions = GetFunctionsGL(context);
634 StateManagerGL *stateManager = GetStateManagerGL(context);
635
636 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500637
Martin Radev7c2e6a92017-08-28 11:13:16 +0300638 // A pointer to one of the attachments for which the texture or the render buffer is not zero.
639 const FramebufferAttachment *attachment = nullptr;
Martin Radev878c8b12017-07-28 09:51:04 +0300640
Jamie Madill6de51852017-04-12 09:53:01 -0400641 for (auto dirtyBit : dirtyBits)
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500642 {
643 switch (dirtyBit)
644 {
645 case Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
Martin Radev7c2e6a92017-08-28 11:13:16 +0300646 {
647 const FramebufferAttachment *newAttachment = mState.getDepthAttachment();
Geoff Lang61107632018-05-09 11:32:46 -0400648 BindFramebufferAttachment(functions, GL_DEPTH_ATTACHMENT, newAttachment);
Martin Radev7c2e6a92017-08-28 11:13:16 +0300649 if (newAttachment)
650 {
651 attachment = newAttachment;
652 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500653 break;
Martin Radev7c2e6a92017-08-28 11:13:16 +0300654 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500655 case Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
Martin Radev7c2e6a92017-08-28 11:13:16 +0300656 {
657 const FramebufferAttachment *newAttachment = mState.getStencilAttachment();
Geoff Lang61107632018-05-09 11:32:46 -0400658 BindFramebufferAttachment(functions, GL_STENCIL_ATTACHMENT, newAttachment);
Martin Radev7c2e6a92017-08-28 11:13:16 +0300659 if (newAttachment)
660 {
661 attachment = newAttachment;
662 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500663 break;
Martin Radev7c2e6a92017-08-28 11:13:16 +0300664 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500665 case Framebuffer::DIRTY_BIT_DRAW_BUFFERS:
666 {
Jamie Madill48ef11b2016-04-27 15:21:52 -0400667 const auto &drawBuffers = mState.getDrawBufferStates();
Geoff Lang61107632018-05-09 11:32:46 -0400668 functions->drawBuffers(static_cast<GLsizei>(drawBuffers.size()),
669 drawBuffers.data());
Corentin Walleze7557742017-06-01 13:09:57 -0400670 mAppliedEnabledDrawBuffers = mState.getEnabledDrawBuffers();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500671 break;
672 }
673 case Framebuffer::DIRTY_BIT_READ_BUFFER:
Geoff Lang61107632018-05-09 11:32:46 -0400674 functions->readBuffer(mState.getReadBufferState());
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500675 break;
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800676 case Framebuffer::DIRTY_BIT_DEFAULT_WIDTH:
Geoff Lang61107632018-05-09 11:32:46 -0400677 functions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH,
678 mState.getDefaultWidth());
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800679 break;
680 case Framebuffer::DIRTY_BIT_DEFAULT_HEIGHT:
Geoff Lang61107632018-05-09 11:32:46 -0400681 functions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT,
682 mState.getDefaultHeight());
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800683 break;
684 case Framebuffer::DIRTY_BIT_DEFAULT_SAMPLES:
Geoff Lang61107632018-05-09 11:32:46 -0400685 functions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_SAMPLES,
686 mState.getDefaultSamples());
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800687 break;
688 case Framebuffer::DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS:
Geoff Lang61107632018-05-09 11:32:46 -0400689 functions->framebufferParameteri(
Geoff Lang92019432017-11-20 13:09:34 -0500690 GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS,
691 gl::ConvertToGLBoolean(mState.getDefaultFixedSampleLocations()));
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800692 break;
Jiawei Shaob1e91382018-05-17 14:33:55 +0800693 case Framebuffer::DIRTY_BIT_DEFAULT_LAYERS:
694 functions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT,
695 mState.getDefaultLayers());
696 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500697 default:
698 {
699 ASSERT(Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0 &&
700 dirtyBit < Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX);
701 size_t index =
702 static_cast<size_t>(dirtyBit - Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
Martin Radev7c2e6a92017-08-28 11:13:16 +0300703 const FramebufferAttachment *newAttachment = mState.getColorAttachment(index);
704 BindFramebufferAttachment(
Geoff Lang61107632018-05-09 11:32:46 -0400705 functions, static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + index), newAttachment);
Martin Radev7c2e6a92017-08-28 11:13:16 +0300706 if (newAttachment)
707 {
708 attachment = newAttachment;
709 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500710 break;
711 }
712 }
713 }
Martin Radev878c8b12017-07-28 09:51:04 +0300714
Jamie Madillc3dc5d42018-12-30 12:12:04 -0500715 if (attachment && mState.id() == context->getState().getDrawFramebuffer()->id())
Martin Radev878c8b12017-07-28 09:51:04 +0300716 {
Martin Radev7c2e6a92017-08-28 11:13:16 +0300717 const bool isSideBySide =
718 (attachment->getMultiviewLayout() == GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE);
Geoff Lang61107632018-05-09 11:32:46 -0400719 stateManager->setSideBySide(isSideBySide);
Jamie Madillc3dc5d42018-12-30 12:12:04 -0500720 stateManager->updateMultiviewBaseViewLayerIndexUniform(context->getState().getProgram(),
Geoff Lang61107632018-05-09 11:32:46 -0400721 getState());
Martin Radev878c8b12017-07-28 09:51:04 +0300722 }
Jamie Madill19fa1c62018-03-08 09:47:21 -0500723
Jamie Madill7c985f52018-11-29 18:16:17 -0500724 return angle::Result::Continue;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500725}
726
Geoff Lang4ad17092015-03-10 16:47:44 -0400727GLuint FramebufferGL::getFramebufferID() const
728{
729 return mFramebufferID;
Geoff Langf9a6f082015-01-22 13:32:49 -0500730}
731
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700732bool FramebufferGL::isDefault() const
Geoff Langafd7f0a2015-09-09 15:33:31 -0400733{
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700734 return mIsDefault;
Geoff Langafd7f0a2015-09-09 15:33:31 -0400735}
736
Jamie Madillf38cb6d2018-10-22 11:53:40 -0400737void FramebufferGL::maskOutInactiveOutputDrawBuffersImpl(const gl::Context *context,
738 DrawBufferMask targetAppliedDrawBuffers)
Corentin Walleze7557742017-06-01 13:09:57 -0400739{
Geoff Lang61107632018-05-09 11:32:46 -0400740
Jamie Madillf38cb6d2018-10-22 11:53:40 -0400741 ASSERT(mAppliedEnabledDrawBuffers != targetAppliedDrawBuffers);
742 mAppliedEnabledDrawBuffers = targetAppliedDrawBuffers;
743
744 const auto &stateDrawBuffers = mState.getDrawBufferStates();
745 GLsizei drawBufferCount = static_cast<GLsizei>(stateDrawBuffers.size());
746 ASSERT(drawBufferCount <= IMPLEMENTATION_MAX_DRAW_BUFFERS);
747
748 GLenum drawBuffers[IMPLEMENTATION_MAX_DRAW_BUFFERS];
749 for (GLenum i = 0; static_cast<int>(i) < drawBufferCount; ++i)
Corentin Walleze7557742017-06-01 13:09:57 -0400750 {
Jamie Madillf38cb6d2018-10-22 11:53:40 -0400751 drawBuffers[i] = targetAppliedDrawBuffers[i] ? stateDrawBuffers[i] : GL_NONE;
Corentin Walleze7557742017-06-01 13:09:57 -0400752 }
Jamie Madillf38cb6d2018-10-22 11:53:40 -0400753
754 const FunctionsGL *functions = GetFunctionsGL(context);
755 StateManagerGL *stateManager = GetStateManagerGL(context);
756
757 ASSERT(stateManager->getFramebufferID(angle::FramebufferBindingDraw) == mFramebufferID);
758 functions->drawBuffers(drawBufferCount, drawBuffers);
Corentin Walleze7557742017-06-01 13:09:57 -0400759}
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
Jamie Madille39e8f42018-10-05 08:17:38 -0400870angle::Result 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{
Jamie Madille39e8f42018-10-05 08:17:38 -0400877 ContextGL *contextGL = GetImplAs<ContextGL>(context);
Geoff Lang61107632018-05-09 11:32:46 -0400878 const FunctionsGL *functions = GetFunctionsGL(context);
879 StateManagerGL *stateManager = GetStateManagerGL(context);
880
Geoff Langca271392017-04-05 12:30:00 -0400881 const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(format, type);
Frank Henigmanfa36c332017-06-09 18:44:45 -0400882
883 GLuint rowBytes = 0;
Jamie Madille39e8f42018-10-05 08:17:38 -0400884 ANGLE_CHECK_GL_MATH(contextGL, glFormat.computeRowPitch(type, area.width, pack.alignment,
885 pack.rowLength, &rowBytes));
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400886 GLuint skipBytes = 0;
Jamie Madille39e8f42018-10-05 08:17:38 -0400887 ANGLE_CHECK_GL_MATH(contextGL,
888 glFormat.computeSkipBytes(type, rowBytes, 0, pack, false, &skipBytes));
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400889
890 gl::PixelPackState directPack;
Jamie Madillb980c562018-11-27 11:34:27 -0500891 directPack.alignment = 1;
Geoff Lang61107632018-05-09 11:32:46 -0400892 stateManager->setPixelPackState(directPack);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400893
Frank Henigmanfa36c332017-06-09 18:44:45 -0400894 pixels += skipBytes;
895 for (GLint y = area.y; y < area.y + area.height; ++y)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400896 {
Geoff Lang61107632018-05-09 11:32:46 -0400897 functions->readPixels(area.x, y, area.width, 1, format, type, pixels);
Frank Henigmanfa36c332017-06-09 18:44:45 -0400898 pixels += rowBytes;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400899 }
900
Jamie Madill7c985f52018-11-29 18:16:17 -0500901 return angle::Result::Continue;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400902}
903
Jamie Madille39e8f42018-10-05 08:17:38 -0400904angle::Result FramebufferGL::readPixelsAllAtOnce(const gl::Context *context,
905 const gl::Rectangle &area,
906 GLenum format,
907 GLenum type,
908 const gl::PixelPackState &pack,
909 GLubyte *pixels,
910 bool readLastRowSeparately) const
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400911{
Jamie Madille39e8f42018-10-05 08:17:38 -0400912 ContextGL *contextGL = GetImplAs<ContextGL>(context);
Geoff Lang61107632018-05-09 11:32:46 -0400913 const FunctionsGL *functions = GetFunctionsGL(context);
914 StateManagerGL *stateManager = GetStateManagerGL(context);
915
Frank Henigmanfa36c332017-06-09 18:44:45 -0400916 GLint height = area.height - readLastRowSeparately;
917 if (height > 0)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400918 {
Geoff Lang61107632018-05-09 11:32:46 -0400919 stateManager->setPixelPackState(pack);
920 functions->readPixels(area.x, area.y, area.width, height, format, type, pixels);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400921 }
922
Frank Henigmanfa36c332017-06-09 18:44:45 -0400923 if (readLastRowSeparately)
924 {
925 const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(format, type);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400926
Frank Henigmanfa36c332017-06-09 18:44:45 -0400927 GLuint rowBytes = 0;
Jamie Madille39e8f42018-10-05 08:17:38 -0400928 ANGLE_CHECK_GL_MATH(contextGL, glFormat.computeRowPitch(type, area.width, pack.alignment,
929 pack.rowLength, &rowBytes));
Frank Henigmanfa36c332017-06-09 18:44:45 -0400930 GLuint skipBytes = 0;
Jamie Madille39e8f42018-10-05 08:17:38 -0400931 ANGLE_CHECK_GL_MATH(contextGL,
932 glFormat.computeSkipBytes(type, rowBytes, 0, pack, false, &skipBytes));
Frank Henigmanfa36c332017-06-09 18:44:45 -0400933
934 gl::PixelPackState directPack;
Frank Henigmanfa36c332017-06-09 18:44:45 -0400935 directPack.alignment = 1;
Geoff Lang61107632018-05-09 11:32:46 -0400936 stateManager->setPixelPackState(directPack);
Frank Henigmanfa36c332017-06-09 18:44:45 -0400937
938 pixels += skipBytes + (area.height - 1) * rowBytes;
Geoff Lang61107632018-05-09 11:32:46 -0400939 functions->readPixels(area.x, area.y + area.height - 1, area.width, 1, format, type,
940 pixels);
Frank Henigmanfa36c332017-06-09 18:44:45 -0400941 }
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400942
Jamie Madill7c985f52018-11-29 18:16:17 -0500943 return angle::Result::Continue;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400944}
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500945} // namespace rx