blob: a5a64cd3fdc0da588e762c293d42a8f4d2c91733 [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 ||
Olli Etuahodff32a02018-08-28 14:35:50 +030064 textureType == TextureType::CubeMap ||
65 textureType == TextureType::_2DMultisampleArray);
Jiawei Shaoa8802472018-05-28 11:17:47 +080066 functions->framebufferTexture(GL_FRAMEBUFFER, attachmentPoint,
67 textureGL->getTextureID(), attachment->mipLevel());
68 }
Corentin Wallez99d492c2018-02-27 15:17:10 -050069 else if (texture->getType() == TextureType::CubeMap)
70 {
71 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint,
72 ToGLenum(attachment->cubeMapFace()),
73 textureGL->getTextureID(), attachment->mipLevel());
74 }
75 else if (texture->getType() == TextureType::_2DArray ||
Olli Etuahofd162102018-08-27 16:14:57 +030076 texture->getType() == TextureType::_3D ||
77 texture->getType() == TextureType::_2DMultisampleArray)
Geoff Lang4ad17092015-03-10 16:47:44 -040078 {
Martin Radev5e424fa2017-08-09 16:25:36 +030079 if (attachment->getMultiviewLayout() == GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE)
80 {
81 ASSERT(functions->framebufferTexture);
82 functions->framebufferTexture(GL_FRAMEBUFFER, attachmentPoint,
83 textureGL->getTextureID(),
84 attachment->mipLevel());
85 }
86 else
87 {
88 functions->framebufferTextureLayer(GL_FRAMEBUFFER, attachmentPoint,
89 textureGL->getTextureID(),
90 attachment->mipLevel(), attachment->layer());
91 }
Geoff Lang4ad17092015-03-10 16:47:44 -040092 }
93 else
94 {
95 UNREACHABLE();
96 }
97 }
98 else if (attachment->type() == GL_RENDERBUFFER)
99 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500100 const Renderbuffer *renderbuffer = attachment->getRenderbuffer();
Geoff Langcd69f1c2015-03-18 14:33:23 -0400101 const RenderbufferGL *renderbufferGL = GetImplAs<RenderbufferGL>(renderbuffer);
Geoff Lang4ad17092015-03-10 16:47:44 -0400102
Geoff Langcd69f1c2015-03-18 14:33:23 -0400103 functions->framebufferRenderbuffer(GL_FRAMEBUFFER, attachmentPoint, GL_RENDERBUFFER,
104 renderbufferGL->getRenderbufferID());
Geoff Lang4ad17092015-03-10 16:47:44 -0400105 }
106 else
107 {
108 UNREACHABLE();
109 }
110 }
111 else
112 {
113 // Unbind this attachment
114 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint, GL_TEXTURE_2D, 0, 0);
115 }
116}
Geoff Langf9a6f082015-01-22 13:32:49 -0500117
Martin Radev61e710b2017-09-05 11:59:52 +0300118bool AreAllLayersActive(const FramebufferAttachment &attachment)
Martin Radevb0761932017-07-25 17:42:25 +0300119{
Martin Radev61e710b2017-09-05 11:59:52 +0300120 int baseViewIndex = attachment.getBaseViewIndex();
121 if (baseViewIndex != 0)
122 {
123 return false;
124 }
125 const ImageIndex &imageIndex = attachment.getTextureImageIndex();
Jamie Madillcc129372018-04-12 09:13:18 -0400126 int numLayers = static_cast<int>(
127 attachment.getTexture()->getDepth(imageIndex.getTarget(), imageIndex.getLevelIndex()));
Martin Radev61e710b2017-09-05 11:59:52 +0300128 return (attachment.getNumViews() == numLayers);
129}
130
131bool RequiresMultiviewClear(const FramebufferState &state, bool scissorTestEnabled)
132{
133 // Get one attachment and check whether all layers are attached.
134 const FramebufferAttachment *attachment = nullptr;
135 bool allTextureArraysAreFullyAttached = true;
136 for (const FramebufferAttachment &colorAttachment : state.getColorAttachments())
137 {
138 if (colorAttachment.isAttached())
139 {
140 if (colorAttachment.getMultiviewLayout() == GL_NONE)
141 {
142 return false;
143 }
144 attachment = &colorAttachment;
145 allTextureArraysAreFullyAttached =
146 allTextureArraysAreFullyAttached && AreAllLayersActive(*attachment);
147 }
148 }
149
150 const FramebufferAttachment *depthAttachment = state.getDepthAttachment();
151 if (depthAttachment)
152 {
153 if (depthAttachment->getMultiviewLayout() == GL_NONE)
154 {
155 return false;
156 }
157 attachment = depthAttachment;
158 allTextureArraysAreFullyAttached =
159 allTextureArraysAreFullyAttached && AreAllLayersActive(*attachment);
160 }
161 const FramebufferAttachment *stencilAttachment = state.getStencilAttachment();
162 if (stencilAttachment)
163 {
164 if (stencilAttachment->getMultiviewLayout() == GL_NONE)
165 {
166 return false;
167 }
168 attachment = stencilAttachment;
169 allTextureArraysAreFullyAttached =
170 allTextureArraysAreFullyAttached && AreAllLayersActive(*attachment);
171 }
172
Martin Radev5e424fa2017-08-09 16:25:36 +0300173 if (attachment == nullptr)
174 {
175 return false;
176 }
177 switch (attachment->getMultiviewLayout())
178 {
179 case GL_FRAMEBUFFER_MULTIVIEW_LAYERED_ANGLE:
Martin Radev61e710b2017-09-05 11:59:52 +0300180 // If all layers of each texture array are active, then there is no need to issue a
181 // special multiview clear.
182 return !allTextureArraysAreFullyAttached;
Martin Radev5e424fa2017-08-09 16:25:36 +0300183 case GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE:
184 return (scissorTestEnabled == true);
Martin Radev5e424fa2017-08-09 16:25:36 +0300185 default:
186 UNREACHABLE();
187 }
188 return false;
Martin Radevb0761932017-07-25 17:42:25 +0300189}
190
Martin Radev878c8b12017-07-28 09:51:04 +0300191} // namespace
192
Geoff Lang61107632018-05-09 11:32:46 -0400193FramebufferGL::FramebufferGL(const gl::FramebufferState &data, GLuint id, bool isDefault)
194 : FramebufferImpl(data),
Martin Radev878c8b12017-07-28 09:51:04 +0300195 mFramebufferID(id),
Geoff Lang61107632018-05-09 11:32:46 -0400196 mIsDefault(isDefault),
Martin Radev878c8b12017-07-28 09:51:04 +0300197 mAppliedEnabledDrawBuffers(1)
198{
199}
200
201FramebufferGL::~FramebufferGL()
202{
Geoff Lang61107632018-05-09 11:32:46 -0400203 ASSERT(mFramebufferID == 0);
204}
205
206void FramebufferGL::destroy(const gl::Context *context)
207{
208 StateManagerGL *stateManager = GetStateManagerGL(context);
209 stateManager->deleteFramebuffer(mFramebufferID);
Martin Radev878c8b12017-07-28 09:51:04 +0300210 mFramebufferID = 0;
211}
212
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400213angle::Result FramebufferGL::discard(const gl::Context *context,
214 size_t count,
215 const GLenum *attachments)
Austin Kinross08332632015-05-05 13:35:47 -0700216{
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500217 // glInvalidateFramebuffer accepts the same enums as glDiscardFramebufferEXT
Jamie Madill4928b7c2017-06-20 12:57:39 -0400218 return invalidate(context, count, attachments);
Austin Kinross08332632015-05-05 13:35:47 -0700219}
220
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400221angle::Result FramebufferGL::invalidate(const gl::Context *context,
222 size_t count,
223 const GLenum *attachments)
Geoff Langf9a6f082015-01-22 13:32:49 -0500224{
Geoff Lang005a7012017-03-27 13:17:34 -0400225 const GLenum *finalAttachmentsPtr = attachments;
226
227 std::vector<GLenum> modifiedAttachments;
228 if (modifyInvalidateAttachmentsForEmulatedDefaultFBO(count, attachments, &modifiedAttachments))
229 {
230 finalAttachmentsPtr = modifiedAttachments.data();
231 }
232
Geoff Lang61107632018-05-09 11:32:46 -0400233 const FunctionsGL *functions = GetFunctionsGL(context);
234 StateManagerGL *stateManager = GetStateManagerGL(context);
235
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500236 // Since this function is just a hint, only call a native function if it exists.
Geoff Lang61107632018-05-09 11:32:46 -0400237 if (functions->invalidateFramebuffer)
Geoff Lang64a72442015-04-01 14:43:11 -0400238 {
Geoff Lang61107632018-05-09 11:32:46 -0400239 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
240 functions->invalidateFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
241 finalAttachmentsPtr);
Geoff Lang64a72442015-04-01 14:43:11 -0400242 }
Geoff Lang61107632018-05-09 11:32:46 -0400243 else if (functions->discardFramebufferEXT)
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500244 {
Geoff Lang61107632018-05-09 11:32:46 -0400245 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
246 functions->discardFramebufferEXT(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
247 finalAttachmentsPtr);
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500248 }
Geoff Lang64a72442015-04-01 14:43:11 -0400249
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400250 return angle::Result::Continue();
Geoff Langf9a6f082015-01-22 13:32:49 -0500251}
252
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400253angle::Result FramebufferGL::invalidateSub(const gl::Context *context,
254 size_t count,
255 const GLenum *attachments,
256 const gl::Rectangle &area)
Geoff Langf9a6f082015-01-22 13:32:49 -0500257{
Geoff Lang005a7012017-03-27 13:17:34 -0400258
259 const GLenum *finalAttachmentsPtr = attachments;
260
261 std::vector<GLenum> modifiedAttachments;
262 if (modifyInvalidateAttachmentsForEmulatedDefaultFBO(count, attachments, &modifiedAttachments))
263 {
264 finalAttachmentsPtr = modifiedAttachments.data();
265 }
266
Geoff Lang61107632018-05-09 11:32:46 -0400267 const FunctionsGL *functions = GetFunctionsGL(context);
268 StateManagerGL *stateManager = GetStateManagerGL(context);
269
Jamie Madill231c7f52017-04-26 13:45:37 -0400270 // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is
271 // available.
Geoff Lang61107632018-05-09 11:32:46 -0400272 if (functions->invalidateSubFramebuffer)
Geoff Lang64a72442015-04-01 14:43:11 -0400273 {
Geoff Lang61107632018-05-09 11:32:46 -0400274 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
275 functions->invalidateSubFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
276 finalAttachmentsPtr, area.x, area.y, area.width,
277 area.height);
Geoff Lang64a72442015-04-01 14:43:11 -0400278 }
279
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400280 return angle::Result::Continue();
Geoff Langf9a6f082015-01-22 13:32:49 -0500281}
282
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400283angle::Result FramebufferGL::clear(const gl::Context *context, GLbitfield mask)
Geoff Langf9a6f082015-01-22 13:32:49 -0500284{
Geoff Lang61107632018-05-09 11:32:46 -0400285 const FunctionsGL *functions = GetFunctionsGL(context);
286 StateManagerGL *stateManager = GetStateManagerGL(context);
287
Frank Henigman308d7452017-02-15 22:51:21 -0500288 syncClearState(context, mask);
Geoff Lang61107632018-05-09 11:32:46 -0400289 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300290
Martin Radev61e710b2017-09-05 11:59:52 +0300291 if (!RequiresMultiviewClear(mState, context->getGLState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300292 {
Geoff Lang61107632018-05-09 11:32:46 -0400293 functions->clear(mask);
Martin Radevb0761932017-07-25 17:42:25 +0300294 }
295 else
296 {
Geoff Lang61107632018-05-09 11:32:46 -0400297 ClearMultiviewGL *multiviewClearer = GetMultiviewClearer(context);
298 multiviewClearer->clearMultiviewFBO(mState, context->getGLState().getScissor(),
299 ClearMultiviewGL::ClearCommandType::Clear, mask,
300 GL_NONE, 0, nullptr, 0.0f, 0);
Martin Radevb0761932017-07-25 17:42:25 +0300301 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400302
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400303 return angle::Result::Continue();
Geoff Lang4ad17092015-03-10 16:47:44 -0400304}
305
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400306angle::Result FramebufferGL::clearBufferfv(const gl::Context *context,
307 GLenum buffer,
308 GLint drawbuffer,
309 const GLfloat *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500310{
Geoff Lang61107632018-05-09 11:32:46 -0400311 const FunctionsGL *functions = GetFunctionsGL(context);
312 StateManagerGL *stateManager = GetStateManagerGL(context);
313
Frank Henigman308d7452017-02-15 22:51:21 -0500314 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang61107632018-05-09 11:32:46 -0400315 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300316
Martin Radev61e710b2017-09-05 11:59:52 +0300317 if (!RequiresMultiviewClear(mState, context->getGLState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300318 {
Geoff Lang61107632018-05-09 11:32:46 -0400319 functions->clearBufferfv(buffer, drawbuffer, values);
Martin Radevb0761932017-07-25 17:42:25 +0300320 }
321 else
322 {
Geoff Lang61107632018-05-09 11:32:46 -0400323 ClearMultiviewGL *multiviewClearer = GetMultiviewClearer(context);
324 multiviewClearer->clearMultiviewFBO(mState, context->getGLState().getScissor(),
325 ClearMultiviewGL::ClearCommandType::ClearBufferfv,
326 static_cast<GLbitfield>(0u), buffer, drawbuffer,
327 reinterpret_cast<const uint8_t *>(values), 0.0f, 0);
Martin Radevb0761932017-07-25 17:42:25 +0300328 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400329
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400330 return angle::Result::Continue();
Geoff Langf9a6f082015-01-22 13:32:49 -0500331}
332
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400333angle::Result FramebufferGL::clearBufferuiv(const gl::Context *context,
334 GLenum buffer,
335 GLint drawbuffer,
336 const GLuint *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500337{
Geoff Lang61107632018-05-09 11:32:46 -0400338 const FunctionsGL *functions = GetFunctionsGL(context);
339 StateManagerGL *stateManager = GetStateManagerGL(context);
340
Frank Henigman308d7452017-02-15 22:51:21 -0500341 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang61107632018-05-09 11:32:46 -0400342 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300343
Martin Radev61e710b2017-09-05 11:59:52 +0300344 if (!RequiresMultiviewClear(mState, context->getGLState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300345 {
Geoff Lang61107632018-05-09 11:32:46 -0400346 functions->clearBufferuiv(buffer, drawbuffer, values);
Martin Radevb0761932017-07-25 17:42:25 +0300347 }
348 else
349 {
Geoff Lang61107632018-05-09 11:32:46 -0400350 ClearMultiviewGL *multiviewClearer = GetMultiviewClearer(context);
351 multiviewClearer->clearMultiviewFBO(mState, context->getGLState().getScissor(),
352 ClearMultiviewGL::ClearCommandType::ClearBufferuiv,
353 static_cast<GLbitfield>(0u), buffer, drawbuffer,
354 reinterpret_cast<const uint8_t *>(values), 0.0f, 0);
Martin Radevb0761932017-07-25 17:42:25 +0300355 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400356
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400357 return angle::Result::Continue();
Geoff Langf9a6f082015-01-22 13:32:49 -0500358}
359
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400360angle::Result FramebufferGL::clearBufferiv(const gl::Context *context,
361 GLenum buffer,
362 GLint drawbuffer,
363 const GLint *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500364{
Geoff Lang61107632018-05-09 11:32:46 -0400365 const FunctionsGL *functions = GetFunctionsGL(context);
366 StateManagerGL *stateManager = GetStateManagerGL(context);
367
Frank Henigman308d7452017-02-15 22:51:21 -0500368 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang61107632018-05-09 11:32:46 -0400369 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300370
Martin Radev61e710b2017-09-05 11:59:52 +0300371 if (!RequiresMultiviewClear(mState, context->getGLState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300372 {
Geoff Lang61107632018-05-09 11:32:46 -0400373 functions->clearBufferiv(buffer, drawbuffer, values);
Martin Radevb0761932017-07-25 17:42:25 +0300374 }
375 else
376 {
Geoff Lang61107632018-05-09 11:32:46 -0400377 ClearMultiviewGL *multiviewClearer = GetMultiviewClearer(context);
378 multiviewClearer->clearMultiviewFBO(mState, context->getGLState().getScissor(),
379 ClearMultiviewGL::ClearCommandType::ClearBufferiv,
380 static_cast<GLbitfield>(0u), buffer, drawbuffer,
381 reinterpret_cast<const uint8_t *>(values), 0.0f, 0);
Martin Radevb0761932017-07-25 17:42:25 +0300382 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400383
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400384 return angle::Result::Continue();
Geoff Langf9a6f082015-01-22 13:32:49 -0500385}
386
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400387angle::Result FramebufferGL::clearBufferfi(const gl::Context *context,
388 GLenum buffer,
389 GLint drawbuffer,
390 GLfloat depth,
391 GLint stencil)
Geoff Langf9a6f082015-01-22 13:32:49 -0500392{
Geoff Lang61107632018-05-09 11:32:46 -0400393 const FunctionsGL *functions = GetFunctionsGL(context);
394 StateManagerGL *stateManager = GetStateManagerGL(context);
395
Frank Henigman308d7452017-02-15 22:51:21 -0500396 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang61107632018-05-09 11:32:46 -0400397 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300398
Martin Radev61e710b2017-09-05 11:59:52 +0300399 if (!RequiresMultiviewClear(mState, context->getGLState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300400 {
Geoff Lang61107632018-05-09 11:32:46 -0400401 functions->clearBufferfi(buffer, drawbuffer, depth, stencil);
Martin Radevb0761932017-07-25 17:42:25 +0300402 }
Martin Radev5e424fa2017-08-09 16:25:36 +0300403 else
404 {
Geoff Lang61107632018-05-09 11:32:46 -0400405 ClearMultiviewGL *multiviewClearer = GetMultiviewClearer(context);
406 multiviewClearer->clearMultiviewFBO(mState, context->getGLState().getScissor(),
407 ClearMultiviewGL::ClearCommandType::ClearBufferfi,
408 static_cast<GLbitfield>(0u), buffer, drawbuffer,
409 nullptr, depth, stencil);
Martin Radev5e424fa2017-08-09 16:25:36 +0300410 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400411
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400412 return angle::Result::Continue();
Geoff Langf9a6f082015-01-22 13:32:49 -0500413}
414
Jamie Madill4928b7c2017-06-20 12:57:39 -0400415GLenum FramebufferGL::getImplementationColorReadFormat(const gl::Context *context) const
Geoff Langf9a6f082015-01-22 13:32:49 -0500416{
Jamie Madilla3944d42016-07-22 22:13:26 -0400417 const auto *readAttachment = mState.getReadAttachment();
418 const Format &format = readAttachment->getFormat();
Geoff Langf607c602016-09-21 11:46:48 -0400419 return format.info->getReadPixelsFormat();
Geoff Langf9a6f082015-01-22 13:32:49 -0500420}
421
Jamie Madill4928b7c2017-06-20 12:57:39 -0400422GLenum FramebufferGL::getImplementationColorReadType(const gl::Context *context) const
Geoff Langf9a6f082015-01-22 13:32:49 -0500423{
Jamie Madilla3944d42016-07-22 22:13:26 -0400424 const auto *readAttachment = mState.getReadAttachment();
425 const Format &format = readAttachment->getFormat();
Geoff Langc71ea662017-09-26 17:06:02 -0400426 return format.info->getReadPixelsType(context->getClientVersion());
Geoff Langf9a6f082015-01-22 13:32:49 -0500427}
428
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400429angle::Result FramebufferGL::readPixels(const gl::Context *context,
430 const gl::Rectangle &area,
431 GLenum format,
432 GLenum type,
433 void *pixels)
Geoff Langf9a6f082015-01-22 13:32:49 -0500434{
Jamie Madille39e8f42018-10-05 08:17:38 -0400435 ContextGL *contextGL = GetImplAs<ContextGL>(context);
Geoff Lang61107632018-05-09 11:32:46 -0400436 const FunctionsGL *functions = GetFunctionsGL(context);
437 StateManagerGL *stateManager = GetStateManagerGL(context);
438 const WorkaroundsGL &workarounds = GetWorkaroundsGL(context);
439
Frank Henigmanfa36c332017-06-09 18:44:45 -0400440 // Clip read area to framebuffer.
441 const gl::Extents fbSize = getState().getReadAttachment()->getSize();
442 const gl::Rectangle fbRect(0, 0, fbSize.width, fbSize.height);
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400443 gl::Rectangle clippedArea;
444 if (!ClipRectangle(area, fbRect, &clippedArea))
Frank Henigmanfa36c332017-06-09 18:44:45 -0400445 {
446 // nothing to read
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400447 return angle::Result::Continue();
Frank Henigmanfa36c332017-06-09 18:44:45 -0400448 }
449
Corentin Wallezcda6af12017-10-30 19:20:37 -0400450 PixelPackState packState = context->getGLState().getPackState();
Corentin Wallez336129f2017-10-17 15:55:40 -0400451 const gl::Buffer *packBuffer =
452 context->getGLState().getTargetBuffer(gl::BufferBinding::PixelPack);
Jamie Madill87de3622015-03-16 10:41:44 -0400453
Geoff Langf607c602016-09-21 11:46:48 -0400454 nativegl::ReadPixelsFormat readPixelsFormat =
Geoff Lang61107632018-05-09 11:32:46 -0400455 nativegl::GetReadPixelsFormat(functions, workarounds, format, type);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400456 GLenum readFormat = readPixelsFormat.format;
457 GLenum readType = readPixelsFormat.type;
Geoff Lang4ad17092015-03-10 16:47:44 -0400458
Geoff Lang61107632018-05-09 11:32:46 -0400459 stateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, mFramebufferID);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400460
Geoff Lang61107632018-05-09 11:32:46 -0400461 bool useOverlappingRowsWorkaround = workarounds.packOverlappingRowsSeparatelyPackBuffer &&
Corentin Wallezcda6af12017-10-30 19:20:37 -0400462 packBuffer && packState.rowLength != 0 &&
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400463 packState.rowLength < clippedArea.width;
Frank Henigmanfa36c332017-06-09 18:44:45 -0400464
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400465 GLubyte *outPtr = static_cast<GLubyte *>(pixels);
466 int leftClip = clippedArea.x - area.x;
467 int topClip = clippedArea.y - area.y;
Frank Henigmanfa36c332017-06-09 18:44:45 -0400468 if (leftClip || topClip)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400469 {
Frank Henigmanfa36c332017-06-09 18:44:45 -0400470 // Adjust destination to match portion clipped off left and/or top.
471 const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(readFormat, readType);
472
473 GLuint rowBytes = 0;
Jamie Madille39e8f42018-10-05 08:17:38 -0400474 ANGLE_CHECK_GL_MATH(contextGL,
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400475 glFormat.computeRowPitch(readType, area.width, packState.alignment,
Jamie Madille39e8f42018-10-05 08:17:38 -0400476 packState.rowLength, &rowBytes));
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400477 outPtr += leftClip * glFormat.pixelBytes + topClip * rowBytes;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400478 }
479
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400480 if (packState.rowLength == 0 && clippedArea.width != area.width)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400481 {
Frank Henigmanfa36c332017-06-09 18:44:45 -0400482 // No rowLength was specified so it will derive from read width, but clipping changed the
483 // read width. Use the original width so we fill the user's buffer as they intended.
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400484 packState.rowLength = area.width;
Frank Henigmanfa36c332017-06-09 18:44:45 -0400485 }
Corentin Wallez886de362016-09-27 10:49:35 -0400486
Frank Henigmanfa36c332017-06-09 18:44:45 -0400487 // We want to use rowLength, but that might not be supported.
488 bool cannotSetDesiredRowLength =
489 packState.rowLength && !GetImplAs<ContextGL>(context)->getNativeExtensions().packSubimage;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400490
Frank Henigmanfa36c332017-06-09 18:44:45 -0400491 if (cannotSetDesiredRowLength || useOverlappingRowsWorkaround)
492 {
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400493 return readPixelsRowByRow(context, clippedArea, readFormat, readType, packState, outPtr);
Frank Henigmanfa36c332017-06-09 18:44:45 -0400494 }
Jamie Madill13951342018-09-30 15:24:28 -0400495
496 bool useLastRowPaddingWorkaround = false;
497 if (workarounds.packLastRowSeparatelyForPaddingInclusion)
Frank Henigmanfa36c332017-06-09 18:44:45 -0400498 {
Jamie Madille39e8f42018-10-05 08:17:38 -0400499 ANGLE_TRY(ShouldApplyLastRowPaddingWorkaround(
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400500 contextGL, gl::Extents(clippedArea.width, clippedArea.height, 1), packState, packBuffer,
501 readFormat, readType, false, outPtr, &useLastRowPaddingWorkaround));
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400502 }
503
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400504 return readPixelsAllAtOnce(context, clippedArea, readFormat, readType, packState, outPtr,
Jamie Madill13951342018-09-30 15:24:28 -0400505 useLastRowPaddingWorkaround);
Geoff Langf9a6f082015-01-22 13:32:49 -0500506}
507
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400508angle::Result FramebufferGL::blit(const gl::Context *context,
509 const gl::Rectangle &sourceArea,
510 const gl::Rectangle &destArea,
511 GLbitfield mask,
512 GLenum filter)
Geoff Langf9a6f082015-01-22 13:32:49 -0500513{
Geoff Lang61107632018-05-09 11:32:46 -0400514 const FunctionsGL *functions = GetFunctionsGL(context);
515 StateManagerGL *stateManager = GetStateManagerGL(context);
516
Jamie Madill231c7f52017-04-26 13:45:37 -0400517 const Framebuffer *sourceFramebuffer = context->getGLState().getReadFramebuffer();
518 const Framebuffer *destFramebuffer = context->getGLState().getDrawFramebuffer();
Geoff Lang4ad17092015-03-10 16:47:44 -0400519
Corentin Wallez6898b352016-11-10 11:41:15 -0500520 const FramebufferAttachment *colorReadAttachment = sourceFramebuffer->getReadColorbuffer();
Corentin Wallez4596a762016-12-20 14:50:18 -0500521
522 GLsizei readAttachmentSamples = 0;
523 if (colorReadAttachment != nullptr)
524 {
525 readAttachmentSamples = colorReadAttachment->getSamples();
526 }
Corentin Wallez6898b352016-11-10 11:41:15 -0500527
Corentin Wallez26a717b2016-09-27 08:45:42 -0700528 bool needManualColorBlit = false;
529
Corentin Wallez6898b352016-11-10 11:41:15 -0500530 // TODO(cwallez) when the filter is LINEAR and both source and destination are SRGB, we
531 // could avoid doing a manual blit.
532
533 // Prior to OpenGL 4.4 BlitFramebuffer (section 18.3.1 of GL 4.3 core profile) reads:
534 // When values are taken from the read buffer, no linearization is performed, even
535 // if the format of the buffer is SRGB.
536 // Starting from OpenGL 4.4 (section 18.3.1) it reads:
537 // When values are taken from the read buffer, if FRAMEBUFFER_SRGB is enabled and the
538 // value of FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING for the framebuffer attachment
539 // corresponding to the read buffer is SRGB, the red, green, and blue components are
540 // converted from the non-linear sRGB color space according [...].
Corentin Wallez26a717b2016-09-27 08:45:42 -0700541 {
Jamie Madill231c7f52017-04-26 13:45:37 -0400542 bool sourceSRGB =
543 colorReadAttachment != nullptr && colorReadAttachment->getColorEncoding() == GL_SRGB;
Corentin Wallez6898b352016-11-10 11:41:15 -0500544 needManualColorBlit =
Geoff Lang61107632018-05-09 11:32:46 -0400545 needManualColorBlit || (sourceSRGB && functions->isAtMostGL(gl::Version(4, 3)));
Corentin Wallez6898b352016-11-10 11:41:15 -0500546 }
Corentin Wallez26a717b2016-09-27 08:45:42 -0700547
Corentin Wallez6898b352016-11-10 11:41:15 -0500548 // Prior to OpenGL 4.2 BlitFramebuffer (section 4.3.2 of GL 4.1 core profile) reads:
549 // Blit operations bypass the fragment pipeline. The only fragment operations which
550 // affect a blit are the pixel ownership test and scissor test.
551 // Starting from OpenGL 4.2 (section 4.3.2) it reads:
552 // When values are written to the draw buffers, blit operations bypass the fragment
553 // pipeline. The only fragment operations which affect a blit are the pixel ownership
554 // test, the scissor test and sRGB conversion.
555 if (!needManualColorBlit)
556 {
557 bool destSRGB = false;
558 for (size_t i = 0; i < destFramebuffer->getDrawbufferStateCount(); ++i)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700559 {
Corentin Wallez6898b352016-11-10 11:41:15 -0500560 const FramebufferAttachment *attachment = destFramebuffer->getDrawBuffer(i);
561 if (attachment && attachment->getColorEncoding() == GL_SRGB)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700562 {
Corentin Wallez6898b352016-11-10 11:41:15 -0500563 destSRGB = true;
564 break;
Corentin Wallez26a717b2016-09-27 08:45:42 -0700565 }
Corentin Wallez26a717b2016-09-27 08:45:42 -0700566 }
Corentin Wallez6898b352016-11-10 11:41:15 -0500567
568 needManualColorBlit =
Geoff Lang61107632018-05-09 11:32:46 -0400569 needManualColorBlit || (destSRGB && functions->isAtMostGL(gl::Version(4, 1)));
Corentin Wallez26a717b2016-09-27 08:45:42 -0700570 }
571
572 // Enable FRAMEBUFFER_SRGB if needed
Geoff Lang61107632018-05-09 11:32:46 -0400573 stateManager->setFramebufferSRGBEnabledForFramebuffer(context, true, this);
Corentin Wallez26a717b2016-09-27 08:45:42 -0700574
575 GLenum blitMask = mask;
Corentin Wallez6898b352016-11-10 11:41:15 -0500576 if (needManualColorBlit && (mask & GL_COLOR_BUFFER_BIT) && readAttachmentSamples <= 1)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700577 {
Geoff Lang61107632018-05-09 11:32:46 -0400578 BlitGL *blitter = GetBlitGL(context);
Jamie Madille39e8f42018-10-05 08:17:38 -0400579 ANGLE_TRY(blitter->blitColorBufferWithShader(context, sourceFramebuffer, destFramebuffer,
580 sourceArea, destArea, filter));
Corentin Wallez26a717b2016-09-27 08:45:42 -0700581 blitMask &= ~GL_COLOR_BUFFER_BIT;
582 }
583
584 if (blitMask == 0)
585 {
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400586 return angle::Result::Continue();
Corentin Wallez26a717b2016-09-27 08:45:42 -0700587 }
588
589 const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(sourceFramebuffer);
Geoff Lang61107632018-05-09 11:32:46 -0400590 stateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
591 stateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferID);
Geoff Lang4ad17092015-03-10 16:47:44 -0400592
Geoff Lang61107632018-05-09 11:32:46 -0400593 functions->blitFramebuffer(sourceArea.x, sourceArea.y, sourceArea.x1(), sourceArea.y1(),
594 destArea.x, destArea.y, destArea.x1(), destArea.y1(), blitMask,
595 filter);
Geoff Lang4ad17092015-03-10 16:47:44 -0400596
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400597 return angle::Result::Continue();
Geoff Langf9a6f082015-01-22 13:32:49 -0500598}
599
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400600angle::Result FramebufferGL::getSamplePosition(const gl::Context *context,
601 size_t index,
602 GLfloat *xy) const
JiangYizhoubddc46b2016-12-09 09:50:51 +0800603{
Geoff Lang61107632018-05-09 11:32:46 -0400604 const FunctionsGL *functions = GetFunctionsGL(context);
605 StateManagerGL *stateManager = GetStateManagerGL(context);
606
607 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
608 functions->getMultisamplefv(GL_SAMPLE_POSITION, static_cast<GLuint>(index), xy);
Jamie Madill64b7c4f2018-10-19 11:38:04 -0400609 return angle::Result::Continue();
JiangYizhoubddc46b2016-12-09 09:50:51 +0800610}
611
Kenneth Russellce8602a2017-10-03 18:23:08 -0700612bool FramebufferGL::checkStatus(const gl::Context *context) const
Geoff Langf9a6f082015-01-22 13:32:49 -0500613{
Geoff Lang61107632018-05-09 11:32:46 -0400614 const FunctionsGL *functions = GetFunctionsGL(context);
615 StateManagerGL *stateManager = GetStateManagerGL(context);
616
617 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
618 GLenum status = functions->checkFramebufferStatus(GL_FRAMEBUFFER);
Jamie Madillcc86d642015-11-24 13:00:07 -0500619 if (status != GL_FRAMEBUFFER_COMPLETE)
620 {
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500621 WARN() << "GL framebuffer returned incomplete.";
Jamie Madillcc86d642015-11-24 13:00:07 -0500622 }
623 return (status == GL_FRAMEBUFFER_COMPLETE);
Geoff Lang4ad17092015-03-10 16:47:44 -0400624}
625
Jamie Madill6f755b22018-10-09 12:48:54 -0400626angle::Result FramebufferGL::syncState(const gl::Context *context,
627 const gl::Framebuffer::DirtyBits &dirtyBits)
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500628{
629 // Don't need to sync state for the default FBO.
630 if (mIsDefault)
631 {
Jamie Madill6f755b22018-10-09 12:48:54 -0400632 return angle::Result::Continue();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500633 }
634
Geoff Lang61107632018-05-09 11:32:46 -0400635 const FunctionsGL *functions = GetFunctionsGL(context);
636 StateManagerGL *stateManager = GetStateManagerGL(context);
637
638 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500639
Martin Radev7c2e6a92017-08-28 11:13:16 +0300640 // A pointer to one of the attachments for which the texture or the render buffer is not zero.
641 const FramebufferAttachment *attachment = nullptr;
Martin Radev878c8b12017-07-28 09:51:04 +0300642
Jamie Madill6de51852017-04-12 09:53:01 -0400643 for (auto dirtyBit : dirtyBits)
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500644 {
645 switch (dirtyBit)
646 {
647 case Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
Martin Radev7c2e6a92017-08-28 11:13:16 +0300648 {
649 const FramebufferAttachment *newAttachment = mState.getDepthAttachment();
Geoff Lang61107632018-05-09 11:32:46 -0400650 BindFramebufferAttachment(functions, GL_DEPTH_ATTACHMENT, newAttachment);
Martin Radev7c2e6a92017-08-28 11:13:16 +0300651 if (newAttachment)
652 {
653 attachment = newAttachment;
654 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500655 break;
Martin Radev7c2e6a92017-08-28 11:13:16 +0300656 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500657 case Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
Martin Radev7c2e6a92017-08-28 11:13:16 +0300658 {
659 const FramebufferAttachment *newAttachment = mState.getStencilAttachment();
Geoff Lang61107632018-05-09 11:32:46 -0400660 BindFramebufferAttachment(functions, GL_STENCIL_ATTACHMENT, newAttachment);
Martin Radev7c2e6a92017-08-28 11:13:16 +0300661 if (newAttachment)
662 {
663 attachment = newAttachment;
664 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500665 break;
Martin Radev7c2e6a92017-08-28 11:13:16 +0300666 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500667 case Framebuffer::DIRTY_BIT_DRAW_BUFFERS:
668 {
Jamie Madill48ef11b2016-04-27 15:21:52 -0400669 const auto &drawBuffers = mState.getDrawBufferStates();
Geoff Lang61107632018-05-09 11:32:46 -0400670 functions->drawBuffers(static_cast<GLsizei>(drawBuffers.size()),
671 drawBuffers.data());
Corentin Walleze7557742017-06-01 13:09:57 -0400672 mAppliedEnabledDrawBuffers = mState.getEnabledDrawBuffers();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500673 break;
674 }
675 case Framebuffer::DIRTY_BIT_READ_BUFFER:
Geoff Lang61107632018-05-09 11:32:46 -0400676 functions->readBuffer(mState.getReadBufferState());
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500677 break;
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800678 case Framebuffer::DIRTY_BIT_DEFAULT_WIDTH:
Geoff Lang61107632018-05-09 11:32:46 -0400679 functions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH,
680 mState.getDefaultWidth());
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800681 break;
682 case Framebuffer::DIRTY_BIT_DEFAULT_HEIGHT:
Geoff Lang61107632018-05-09 11:32:46 -0400683 functions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT,
684 mState.getDefaultHeight());
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800685 break;
686 case Framebuffer::DIRTY_BIT_DEFAULT_SAMPLES:
Geoff Lang61107632018-05-09 11:32:46 -0400687 functions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_SAMPLES,
688 mState.getDefaultSamples());
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800689 break;
690 case Framebuffer::DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS:
Geoff Lang61107632018-05-09 11:32:46 -0400691 functions->framebufferParameteri(
Geoff Lang92019432017-11-20 13:09:34 -0500692 GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS,
693 gl::ConvertToGLBoolean(mState.getDefaultFixedSampleLocations()));
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800694 break;
Jiawei Shaob1e91382018-05-17 14:33:55 +0800695 case Framebuffer::DIRTY_BIT_DEFAULT_LAYERS:
696 functions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT,
697 mState.getDefaultLayers());
698 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500699 default:
700 {
701 ASSERT(Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0 &&
702 dirtyBit < Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX);
703 size_t index =
704 static_cast<size_t>(dirtyBit - Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
Martin Radev7c2e6a92017-08-28 11:13:16 +0300705 const FramebufferAttachment *newAttachment = mState.getColorAttachment(index);
706 BindFramebufferAttachment(
Geoff Lang61107632018-05-09 11:32:46 -0400707 functions, static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + index), newAttachment);
Martin Radev7c2e6a92017-08-28 11:13:16 +0300708 if (newAttachment)
709 {
710 attachment = newAttachment;
711 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500712 break;
713 }
714 }
715 }
Martin Radev878c8b12017-07-28 09:51:04 +0300716
Martin Radev7c2e6a92017-08-28 11:13:16 +0300717 if (attachment)
Martin Radev878c8b12017-07-28 09:51:04 +0300718 {
Martin Radev7c2e6a92017-08-28 11:13:16 +0300719 const bool isSideBySide =
720 (attachment->getMultiviewLayout() == GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE);
Geoff Lang61107632018-05-09 11:32:46 -0400721 stateManager->setSideBySide(isSideBySide);
722 stateManager->setViewportOffsets(attachment->getMultiviewViewportOffsets());
723 stateManager->updateMultiviewBaseViewLayerIndexUniform(context->getGLState().getProgram(),
724 getState());
Martin Radev878c8b12017-07-28 09:51:04 +0300725 }
Jamie Madill19fa1c62018-03-08 09:47:21 -0500726
Jamie Madill6f755b22018-10-09 12:48:54 -0400727 return angle::Result::Continue();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500728}
729
Geoff Lang4ad17092015-03-10 16:47:44 -0400730GLuint FramebufferGL::getFramebufferID() const
731{
732 return mFramebufferID;
Geoff Langf9a6f082015-01-22 13:32:49 -0500733}
734
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700735bool FramebufferGL::isDefault() const
Geoff Langafd7f0a2015-09-09 15:33:31 -0400736{
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700737 return mIsDefault;
Geoff Langafd7f0a2015-09-09 15:33:31 -0400738}
739
Geoff Lang61107632018-05-09 11:32:46 -0400740void FramebufferGL::maskOutInactiveOutputDrawBuffers(const gl::Context *context,
741 GLenum binding,
742 DrawBufferMask maxSet)
Corentin Walleze7557742017-06-01 13:09:57 -0400743{
Geoff Lang61107632018-05-09 11:32:46 -0400744
Corentin Walleze7557742017-06-01 13:09:57 -0400745 auto targetAppliedDrawBuffers = mState.getEnabledDrawBuffers() & maxSet;
746 if (mAppliedEnabledDrawBuffers != targetAppliedDrawBuffers)
747 {
748 mAppliedEnabledDrawBuffers = targetAppliedDrawBuffers;
749
750 const auto &stateDrawBuffers = mState.getDrawBufferStates();
751 GLsizei drawBufferCount = static_cast<GLsizei>(stateDrawBuffers.size());
752 ASSERT(drawBufferCount <= IMPLEMENTATION_MAX_DRAW_BUFFERS);
753
754 GLenum drawBuffers[IMPLEMENTATION_MAX_DRAW_BUFFERS];
755 for (GLenum i = 0; static_cast<int>(i) < drawBufferCount; ++i)
756 {
757 drawBuffers[i] = targetAppliedDrawBuffers[i] ? stateDrawBuffers[i] : GL_NONE;
758 }
759
Geoff Lang61107632018-05-09 11:32:46 -0400760 const FunctionsGL *functions = GetFunctionsGL(context);
761 StateManagerGL *stateManager = GetStateManagerGL(context);
762
763 stateManager->bindFramebuffer(binding, mFramebufferID);
764 functions->drawBuffers(drawBufferCount, drawBuffers);
Corentin Walleze7557742017-06-01 13:09:57 -0400765 }
766}
767
Jamie Madillc564c072017-06-01 12:45:42 -0400768void FramebufferGL::syncClearState(const gl::Context *context, GLbitfield mask)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400769{
Geoff Lang61107632018-05-09 11:32:46 -0400770 const FunctionsGL *functions = GetFunctionsGL(context);
771
772 if (functions->standard == STANDARD_GL_DESKTOP)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400773 {
Geoff Lang61107632018-05-09 11:32:46 -0400774 StateManagerGL *stateManager = GetStateManagerGL(context);
775 const WorkaroundsGL &workarounds = GetWorkaroundsGL(context);
776
777 if (workarounds.doesSRGBClearsOnLinearFramebufferAttachments &&
Frank Henigmana3d333c2016-03-22 22:09:14 -0400778 (mask & GL_COLOR_BUFFER_BIT) != 0 && !mIsDefault)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400779 {
Corentin Wallez26a717b2016-09-27 08:45:42 -0700780 bool hasSRGBAttachment = false;
Jamie Madill48ef11b2016-04-27 15:21:52 -0400781 for (const auto &attachment : mState.getColorAttachments())
Geoff Langafd7f0a2015-09-09 15:33:31 -0400782 {
Frank Henigmana3d333c2016-03-22 22:09:14 -0400783 if (attachment.isAttached() && attachment.getColorEncoding() == GL_SRGB)
784 {
Corentin Wallez26a717b2016-09-27 08:45:42 -0700785 hasSRGBAttachment = true;
Frank Henigmana3d333c2016-03-22 22:09:14 -0400786 break;
787 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400788 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400789
Geoff Lang61107632018-05-09 11:32:46 -0400790 stateManager->setFramebufferSRGBEnabled(context, hasSRGBAttachment);
Frank Henigmana3d333c2016-03-22 22:09:14 -0400791 }
792 else
793 {
Geoff Lang61107632018-05-09 11:32:46 -0400794 stateManager->setFramebufferSRGBEnabled(context, !mIsDefault);
Frank Henigmana3d333c2016-03-22 22:09:14 -0400795 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400796 }
797}
798
Jamie Madillc564c072017-06-01 12:45:42 -0400799void FramebufferGL::syncClearBufferState(const gl::Context *context,
800 GLenum buffer,
801 GLint drawBuffer)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400802{
Geoff Lang61107632018-05-09 11:32:46 -0400803 const FunctionsGL *functions = GetFunctionsGL(context);
804
805 if (functions->standard == STANDARD_GL_DESKTOP)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400806 {
Geoff Lang61107632018-05-09 11:32:46 -0400807 StateManagerGL *stateManager = GetStateManagerGL(context);
808 const WorkaroundsGL &workarounds = GetWorkaroundsGL(context);
809
810 if (workarounds.doesSRGBClearsOnLinearFramebufferAttachments && buffer == GL_COLOR &&
Geoff Langafd7f0a2015-09-09 15:33:31 -0400811 !mIsDefault)
812 {
813 // If doing a clear on a color buffer, set SRGB blend enabled only if the color buffer
814 // is an SRGB format.
Jamie Madill48ef11b2016-04-27 15:21:52 -0400815 const auto &drawbufferState = mState.getDrawBufferStates();
816 const auto &colorAttachments = mState.getColorAttachments();
Geoff Langafd7f0a2015-09-09 15:33:31 -0400817
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500818 const FramebufferAttachment *attachment = nullptr;
Geoff Langafd7f0a2015-09-09 15:33:31 -0400819 if (drawbufferState[drawBuffer] >= GL_COLOR_ATTACHMENT0 &&
820 drawbufferState[drawBuffer] < GL_COLOR_ATTACHMENT0 + colorAttachments.size())
821 {
822 size_t attachmentIdx =
823 static_cast<size_t>(drawbufferState[drawBuffer] - GL_COLOR_ATTACHMENT0);
824 attachment = &colorAttachments[attachmentIdx];
825 }
826
827 if (attachment != nullptr)
828 {
Geoff Lang61107632018-05-09 11:32:46 -0400829 stateManager->setFramebufferSRGBEnabled(context,
830 attachment->getColorEncoding() == GL_SRGB);
Geoff Langafd7f0a2015-09-09 15:33:31 -0400831 }
832 }
833 else
834 {
Geoff Lang61107632018-05-09 11:32:46 -0400835 stateManager->setFramebufferSRGBEnabled(context, !mIsDefault);
Geoff Langafd7f0a2015-09-09 15:33:31 -0400836 }
837 }
838}
Geoff Lang005a7012017-03-27 13:17:34 -0400839
840bool FramebufferGL::modifyInvalidateAttachmentsForEmulatedDefaultFBO(
841 size_t count,
842 const GLenum *attachments,
843 std::vector<GLenum> *modifiedAttachments) const
844{
845 bool needsModification = mIsDefault && mFramebufferID != 0;
846 if (!needsModification)
847 {
848 return false;
849 }
850
851 modifiedAttachments->resize(count);
852 for (size_t i = 0; i < count; i++)
853 {
854 switch (attachments[i])
855 {
856 case GL_COLOR:
857 (*modifiedAttachments)[i] = GL_COLOR_ATTACHMENT0;
858 break;
859
860 case GL_DEPTH:
861 (*modifiedAttachments)[i] = GL_DEPTH_ATTACHMENT;
862 break;
863
864 case GL_STENCIL:
865 (*modifiedAttachments)[i] = GL_STENCIL_ATTACHMENT;
866 break;
867
868 default:
869 UNREACHABLE();
870 break;
871 }
872 }
873
874 return true;
875}
876
Jamie Madille39e8f42018-10-05 08:17:38 -0400877angle::Result FramebufferGL::readPixelsRowByRow(const gl::Context *context,
878 const gl::Rectangle &area,
879 GLenum format,
880 GLenum type,
881 const gl::PixelPackState &pack,
882 GLubyte *pixels) const
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400883{
Jamie Madille39e8f42018-10-05 08:17:38 -0400884 ContextGL *contextGL = GetImplAs<ContextGL>(context);
Geoff Lang61107632018-05-09 11:32:46 -0400885 const FunctionsGL *functions = GetFunctionsGL(context);
886 StateManagerGL *stateManager = GetStateManagerGL(context);
887
Geoff Langca271392017-04-05 12:30:00 -0400888 const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(format, type);
Frank Henigmanfa36c332017-06-09 18:44:45 -0400889
890 GLuint rowBytes = 0;
Jamie Madille39e8f42018-10-05 08:17:38 -0400891 ANGLE_CHECK_GL_MATH(contextGL, glFormat.computeRowPitch(type, area.width, pack.alignment,
892 pack.rowLength, &rowBytes));
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400893 GLuint skipBytes = 0;
Jamie Madille39e8f42018-10-05 08:17:38 -0400894 ANGLE_CHECK_GL_MATH(contextGL,
895 glFormat.computeSkipBytes(type, rowBytes, 0, pack, false, &skipBytes));
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400896
897 gl::PixelPackState directPack;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400898 directPack.alignment = 1;
Geoff Lang61107632018-05-09 11:32:46 -0400899 stateManager->setPixelPackState(directPack);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400900
Frank Henigmanfa36c332017-06-09 18:44:45 -0400901 pixels += skipBytes;
902 for (GLint y = area.y; y < area.y + area.height; ++y)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400903 {
Geoff Lang61107632018-05-09 11:32:46 -0400904 functions->readPixels(area.x, y, area.width, 1, format, type, pixels);
Frank Henigmanfa36c332017-06-09 18:44:45 -0400905 pixels += rowBytes;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400906 }
907
Jamie Madille39e8f42018-10-05 08:17:38 -0400908 return angle::Result::Continue();
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400909}
910
Jamie Madille39e8f42018-10-05 08:17:38 -0400911angle::Result FramebufferGL::readPixelsAllAtOnce(const gl::Context *context,
912 const gl::Rectangle &area,
913 GLenum format,
914 GLenum type,
915 const gl::PixelPackState &pack,
916 GLubyte *pixels,
917 bool readLastRowSeparately) const
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400918{
Jamie Madille39e8f42018-10-05 08:17:38 -0400919 ContextGL *contextGL = GetImplAs<ContextGL>(context);
Geoff Lang61107632018-05-09 11:32:46 -0400920 const FunctionsGL *functions = GetFunctionsGL(context);
921 StateManagerGL *stateManager = GetStateManagerGL(context);
922
Frank Henigmanfa36c332017-06-09 18:44:45 -0400923 GLint height = area.height - readLastRowSeparately;
924 if (height > 0)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400925 {
Geoff Lang61107632018-05-09 11:32:46 -0400926 stateManager->setPixelPackState(pack);
927 functions->readPixels(area.x, area.y, area.width, height, format, type, pixels);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400928 }
929
Frank Henigmanfa36c332017-06-09 18:44:45 -0400930 if (readLastRowSeparately)
931 {
932 const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(format, type);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400933
Frank Henigmanfa36c332017-06-09 18:44:45 -0400934 GLuint rowBytes = 0;
Jamie Madille39e8f42018-10-05 08:17:38 -0400935 ANGLE_CHECK_GL_MATH(contextGL, glFormat.computeRowPitch(type, area.width, pack.alignment,
936 pack.rowLength, &rowBytes));
Frank Henigmanfa36c332017-06-09 18:44:45 -0400937 GLuint skipBytes = 0;
Jamie Madille39e8f42018-10-05 08:17:38 -0400938 ANGLE_CHECK_GL_MATH(contextGL,
939 glFormat.computeSkipBytes(type, rowBytes, 0, pack, false, &skipBytes));
Frank Henigmanfa36c332017-06-09 18:44:45 -0400940
941 gl::PixelPackState directPack;
Frank Henigmanfa36c332017-06-09 18:44:45 -0400942 directPack.alignment = 1;
Geoff Lang61107632018-05-09 11:32:46 -0400943 stateManager->setPixelPackState(directPack);
Frank Henigmanfa36c332017-06-09 18:44:45 -0400944
945 pixels += skipBytes + (area.height - 1) * rowBytes;
Geoff Lang61107632018-05-09 11:32:46 -0400946 functions->readPixels(area.x, area.y + area.height - 1, area.width, 1, format, type,
947 pixels);
Frank Henigmanfa36c332017-06-09 18:44:45 -0400948 }
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400949
Jamie Madille39e8f42018-10-05 08:17:38 -0400950 return angle::Result::Continue();
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400951}
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500952} // namespace rx