blob: 2ea861e372c15016dedad318a0e25d40072352bf [file] [log] [blame]
Geoff Langf9a6f082015-01-22 13:32:49 -05001//
2// Copyright 2015 The ANGLE Project Authors. All rights reserved.
3// Use of this source code is governed by a BSD-style license that can be
4// found in the LICENSE file.
5//
6
7// FramebufferGL.cpp: Implements the class methods for FramebufferGL.
8
9#include "libANGLE/renderer/gl/FramebufferGL.h"
10
Jamie Madill20e005b2017-04-07 14:19:22 -040011#include "common/bitset_utils.h"
Geoff Langf9a6f082015-01-22 13:32:49 -050012#include "common/debug.h"
Jamie Madillc564c072017-06-01 12:45:42 -040013#include "libANGLE/Context.h"
Geoff Lang4ad17092015-03-10 16:47:44 -040014#include "libANGLE/FramebufferAttachment.h"
Jamie Madill231c7f52017-04-26 13:45:37 -040015#include "libANGLE/State.h"
Geoff Lang4ad17092015-03-10 16:47:44 -040016#include "libANGLE/angletypes.h"
17#include "libANGLE/formatutils.h"
Geoff Lang92019432017-11-20 13:09:34 -050018#include "libANGLE/queryconversions.h"
Jamie Madill8415b5f2016-04-26 13:41:39 -040019#include "libANGLE/renderer/ContextImpl.h"
Corentin Wallez26a717b2016-09-27 08:45:42 -070020#include "libANGLE/renderer/gl/BlitGL.h"
Martin Radev5e424fa2017-08-09 16:25:36 +030021#include "libANGLE/renderer/gl/ClearMultiviewGL.h"
Frank Henigmanfa36c332017-06-09 18:44:45 -040022#include "libANGLE/renderer/gl/ContextGL.h"
Geoff Lang4ad17092015-03-10 16:47:44 -040023#include "libANGLE/renderer/gl/FunctionsGL.h"
Jacek Cabanfa60f692015-04-27 18:23:44 +020024#include "libANGLE/renderer/gl/RenderbufferGL.h"
Geoff Lang4ad17092015-03-10 16:47:44 -040025#include "libANGLE/renderer/gl/StateManagerGL.h"
26#include "libANGLE/renderer/gl/TextureGL.h"
Geoff Langafd7f0a2015-09-09 15:33:31 -040027#include "libANGLE/renderer/gl/WorkaroundsGL.h"
Geoff Langf607c602016-09-21 11:46:48 -040028#include "libANGLE/renderer/gl/formatutilsgl.h"
Corentin Wallez886de362016-09-27 10:49:35 -040029#include "libANGLE/renderer/gl/renderergl_utils.h"
Jamie Madillcc86d642015-11-24 13:00:07 -050030#include "platform/Platform.h"
Geoff Langf9a6f082015-01-22 13:32:49 -050031
Jamie Madill60ec6ea2016-01-22 15:27:19 -050032using namespace gl;
Corentin Wallez9a8d3662016-09-22 12:18:29 -040033using angle::CheckedNumeric;
Jamie Madill60ec6ea2016-01-22 15:27:19 -050034
Geoff Langf9a6f082015-01-22 13:32:49 -050035namespace rx
36{
37
Martin Radev878c8b12017-07-28 09:51:04 +030038namespace
Geoff Lang4ad17092015-03-10 16:47:44 -040039{
Geoff Langf9a6f082015-01-22 13:32:49 -050040
Martin Radev878c8b12017-07-28 09:51:04 +030041void BindFramebufferAttachment(const FunctionsGL *functions,
42 GLenum attachmentPoint,
43 const FramebufferAttachment *attachment)
Geoff Lang4ad17092015-03-10 16:47:44 -040044{
45 if (attachment)
46 {
47 if (attachment->type() == GL_TEXTURE)
48 {
Jamie Madill60ec6ea2016-01-22 15:27:19 -050049 const Texture *texture = attachment->getTexture();
Geoff Lang4ad17092015-03-10 16:47:44 -040050 const TextureGL *textureGL = GetImplAs<TextureGL>(texture);
51
Corentin Wallez99d492c2018-02-27 15:17:10 -050052 if (texture->getType() == TextureType::_2D ||
53 texture->getType() == TextureType::_2DMultisample ||
54 texture->getType() == TextureType::Rectangle)
Geoff Lang4ad17092015-03-10 16:47:44 -040055 {
JiangYizhoubddc46b2016-12-09 09:50:51 +080056 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint,
Corentin Wallez99d492c2018-02-27 15:17:10 -050057 ToGLenum(texture->getType()),
Geoff Lang4ad17092015-03-10 16:47:44 -040058 textureGL->getTextureID(), attachment->mipLevel());
59 }
Jiawei Shaoa8802472018-05-28 11:17:47 +080060 else if (attachment->isLayered())
61 {
62 TextureType textureType = texture->getType();
63 ASSERT(textureType == TextureType::_2DArray || textureType == TextureType::_3D ||
64 textureType == TextureType::CubeMap);
65 functions->framebufferTexture(GL_FRAMEBUFFER, attachmentPoint,
66 textureGL->getTextureID(), attachment->mipLevel());
67 }
Corentin Wallez99d492c2018-02-27 15:17:10 -050068 else if (texture->getType() == TextureType::CubeMap)
69 {
70 functions->framebufferTexture2D(GL_FRAMEBUFFER, attachmentPoint,
71 ToGLenum(attachment->cubeMapFace()),
72 textureGL->getTextureID(), attachment->mipLevel());
73 }
74 else if (texture->getType() == TextureType::_2DArray ||
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)
197{
198}
199
200FramebufferGL::~FramebufferGL()
201{
Geoff Lang61107632018-05-09 11:32:46 -0400202 ASSERT(mFramebufferID == 0);
203}
204
205void FramebufferGL::destroy(const gl::Context *context)
206{
207 StateManagerGL *stateManager = GetStateManagerGL(context);
208 stateManager->deleteFramebuffer(mFramebufferID);
Martin Radev878c8b12017-07-28 09:51:04 +0300209 mFramebufferID = 0;
210}
211
Jamie Madill4928b7c2017-06-20 12:57:39 -0400212Error FramebufferGL::discard(const gl::Context *context, size_t count, const GLenum *attachments)
Austin Kinross08332632015-05-05 13:35:47 -0700213{
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500214 // glInvalidateFramebuffer accepts the same enums as glDiscardFramebufferEXT
Jamie Madill4928b7c2017-06-20 12:57:39 -0400215 return invalidate(context, count, attachments);
Austin Kinross08332632015-05-05 13:35:47 -0700216}
217
Jamie Madill4928b7c2017-06-20 12:57:39 -0400218Error FramebufferGL::invalidate(const gl::Context *context, size_t count, const GLenum *attachments)
Geoff Langf9a6f082015-01-22 13:32:49 -0500219{
Geoff Lang005a7012017-03-27 13:17:34 -0400220 const GLenum *finalAttachmentsPtr = attachments;
221
222 std::vector<GLenum> modifiedAttachments;
223 if (modifyInvalidateAttachmentsForEmulatedDefaultFBO(count, attachments, &modifiedAttachments))
224 {
225 finalAttachmentsPtr = modifiedAttachments.data();
226 }
227
Geoff Lang61107632018-05-09 11:32:46 -0400228 const FunctionsGL *functions = GetFunctionsGL(context);
229 StateManagerGL *stateManager = GetStateManagerGL(context);
230
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500231 // Since this function is just a hint, only call a native function if it exists.
Geoff Lang61107632018-05-09 11:32:46 -0400232 if (functions->invalidateFramebuffer)
Geoff Lang64a72442015-04-01 14:43:11 -0400233 {
Geoff Lang61107632018-05-09 11:32:46 -0400234 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
235 functions->invalidateFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
236 finalAttachmentsPtr);
Geoff Lang64a72442015-04-01 14:43:11 -0400237 }
Geoff Lang61107632018-05-09 11:32:46 -0400238 else if (functions->discardFramebufferEXT)
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500239 {
Geoff Lang61107632018-05-09 11:32:46 -0400240 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
241 functions->discardFramebufferEXT(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
242 finalAttachmentsPtr);
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500243 }
Geoff Lang64a72442015-04-01 14:43:11 -0400244
Geoff Lang57ce9ea2016-11-24 12:03:14 -0500245 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500246}
247
Jamie Madill4928b7c2017-06-20 12:57:39 -0400248Error FramebufferGL::invalidateSub(const gl::Context *context,
249 size_t count,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500250 const GLenum *attachments,
251 const gl::Rectangle &area)
Geoff Langf9a6f082015-01-22 13:32:49 -0500252{
Geoff Lang005a7012017-03-27 13:17:34 -0400253
254 const GLenum *finalAttachmentsPtr = attachments;
255
256 std::vector<GLenum> modifiedAttachments;
257 if (modifyInvalidateAttachmentsForEmulatedDefaultFBO(count, attachments, &modifiedAttachments))
258 {
259 finalAttachmentsPtr = modifiedAttachments.data();
260 }
261
Geoff Lang61107632018-05-09 11:32:46 -0400262 const FunctionsGL *functions = GetFunctionsGL(context);
263 StateManagerGL *stateManager = GetStateManagerGL(context);
264
Jamie Madill231c7f52017-04-26 13:45:37 -0400265 // Since this function is just a hint and not available until OpenGL 4.3, only call it if it is
266 // available.
Geoff Lang61107632018-05-09 11:32:46 -0400267 if (functions->invalidateSubFramebuffer)
Geoff Lang64a72442015-04-01 14:43:11 -0400268 {
Geoff Lang61107632018-05-09 11:32:46 -0400269 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
270 functions->invalidateSubFramebuffer(GL_FRAMEBUFFER, static_cast<GLsizei>(count),
271 finalAttachmentsPtr, area.x, area.y, area.width,
272 area.height);
Geoff Lang64a72442015-04-01 14:43:11 -0400273 }
274
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500275 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500276}
277
Jamie Madillc564c072017-06-01 12:45:42 -0400278Error FramebufferGL::clear(const gl::Context *context, GLbitfield mask)
Geoff Langf9a6f082015-01-22 13:32:49 -0500279{
Geoff Lang61107632018-05-09 11:32:46 -0400280 const FunctionsGL *functions = GetFunctionsGL(context);
281 StateManagerGL *stateManager = GetStateManagerGL(context);
282
Frank Henigman308d7452017-02-15 22:51:21 -0500283 syncClearState(context, mask);
Geoff Lang61107632018-05-09 11:32:46 -0400284 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300285
Martin Radev61e710b2017-09-05 11:59:52 +0300286 if (!RequiresMultiviewClear(mState, context->getGLState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300287 {
Geoff Lang61107632018-05-09 11:32:46 -0400288 functions->clear(mask);
Martin Radevb0761932017-07-25 17:42:25 +0300289 }
290 else
291 {
Geoff Lang61107632018-05-09 11:32:46 -0400292 ClearMultiviewGL *multiviewClearer = GetMultiviewClearer(context);
293 multiviewClearer->clearMultiviewFBO(mState, context->getGLState().getScissor(),
294 ClearMultiviewGL::ClearCommandType::Clear, mask,
295 GL_NONE, 0, nullptr, 0.0f, 0);
Martin Radevb0761932017-07-25 17:42:25 +0300296 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400297
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500298 return gl::NoError();
Geoff Lang4ad17092015-03-10 16:47:44 -0400299}
300
Jamie Madillc564c072017-06-01 12:45:42 -0400301Error FramebufferGL::clearBufferfv(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500302 GLenum buffer,
303 GLint drawbuffer,
304 const GLfloat *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500305{
Geoff Lang61107632018-05-09 11:32:46 -0400306 const FunctionsGL *functions = GetFunctionsGL(context);
307 StateManagerGL *stateManager = GetStateManagerGL(context);
308
Frank Henigman308d7452017-02-15 22:51:21 -0500309 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang61107632018-05-09 11:32:46 -0400310 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300311
Martin Radev61e710b2017-09-05 11:59:52 +0300312 if (!RequiresMultiviewClear(mState, context->getGLState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300313 {
Geoff Lang61107632018-05-09 11:32:46 -0400314 functions->clearBufferfv(buffer, drawbuffer, values);
Martin Radevb0761932017-07-25 17:42:25 +0300315 }
316 else
317 {
Geoff Lang61107632018-05-09 11:32:46 -0400318 ClearMultiviewGL *multiviewClearer = GetMultiviewClearer(context);
319 multiviewClearer->clearMultiviewFBO(mState, context->getGLState().getScissor(),
320 ClearMultiviewGL::ClearCommandType::ClearBufferfv,
321 static_cast<GLbitfield>(0u), buffer, drawbuffer,
322 reinterpret_cast<const uint8_t *>(values), 0.0f, 0);
Martin Radevb0761932017-07-25 17:42:25 +0300323 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400324
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500325 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500326}
327
Jamie Madillc564c072017-06-01 12:45:42 -0400328Error FramebufferGL::clearBufferuiv(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500329 GLenum buffer,
330 GLint drawbuffer,
331 const GLuint *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500332{
Geoff Lang61107632018-05-09 11:32:46 -0400333 const FunctionsGL *functions = GetFunctionsGL(context);
334 StateManagerGL *stateManager = GetStateManagerGL(context);
335
Frank Henigman308d7452017-02-15 22:51:21 -0500336 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang61107632018-05-09 11:32:46 -0400337 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300338
Martin Radev61e710b2017-09-05 11:59:52 +0300339 if (!RequiresMultiviewClear(mState, context->getGLState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300340 {
Geoff Lang61107632018-05-09 11:32:46 -0400341 functions->clearBufferuiv(buffer, drawbuffer, values);
Martin Radevb0761932017-07-25 17:42:25 +0300342 }
343 else
344 {
Geoff Lang61107632018-05-09 11:32:46 -0400345 ClearMultiviewGL *multiviewClearer = GetMultiviewClearer(context);
346 multiviewClearer->clearMultiviewFBO(mState, context->getGLState().getScissor(),
347 ClearMultiviewGL::ClearCommandType::ClearBufferuiv,
348 static_cast<GLbitfield>(0u), buffer, drawbuffer,
349 reinterpret_cast<const uint8_t *>(values), 0.0f, 0);
Martin Radevb0761932017-07-25 17:42:25 +0300350 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400351
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500352 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500353}
354
Jamie Madillc564c072017-06-01 12:45:42 -0400355Error FramebufferGL::clearBufferiv(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500356 GLenum buffer,
357 GLint drawbuffer,
358 const GLint *values)
Geoff Langf9a6f082015-01-22 13:32:49 -0500359{
Geoff Lang61107632018-05-09 11:32:46 -0400360 const FunctionsGL *functions = GetFunctionsGL(context);
361 StateManagerGL *stateManager = GetStateManagerGL(context);
362
Frank Henigman308d7452017-02-15 22:51:21 -0500363 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang61107632018-05-09 11:32:46 -0400364 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300365
Martin Radev61e710b2017-09-05 11:59:52 +0300366 if (!RequiresMultiviewClear(mState, context->getGLState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300367 {
Geoff Lang61107632018-05-09 11:32:46 -0400368 functions->clearBufferiv(buffer, drawbuffer, values);
Martin Radevb0761932017-07-25 17:42:25 +0300369 }
370 else
371 {
Geoff Lang61107632018-05-09 11:32:46 -0400372 ClearMultiviewGL *multiviewClearer = GetMultiviewClearer(context);
373 multiviewClearer->clearMultiviewFBO(mState, context->getGLState().getScissor(),
374 ClearMultiviewGL::ClearCommandType::ClearBufferiv,
375 static_cast<GLbitfield>(0u), buffer, drawbuffer,
376 reinterpret_cast<const uint8_t *>(values), 0.0f, 0);
Martin Radevb0761932017-07-25 17:42:25 +0300377 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400378
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500379 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500380}
381
Jamie Madillc564c072017-06-01 12:45:42 -0400382Error FramebufferGL::clearBufferfi(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500383 GLenum buffer,
384 GLint drawbuffer,
385 GLfloat depth,
386 GLint stencil)
Geoff Langf9a6f082015-01-22 13:32:49 -0500387{
Geoff Lang61107632018-05-09 11:32:46 -0400388 const FunctionsGL *functions = GetFunctionsGL(context);
389 StateManagerGL *stateManager = GetStateManagerGL(context);
390
Frank Henigman308d7452017-02-15 22:51:21 -0500391 syncClearBufferState(context, buffer, drawbuffer);
Geoff Lang61107632018-05-09 11:32:46 -0400392 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Martin Radevb0761932017-07-25 17:42:25 +0300393
Martin Radev61e710b2017-09-05 11:59:52 +0300394 if (!RequiresMultiviewClear(mState, context->getGLState().isScissorTestEnabled()))
Martin Radevb0761932017-07-25 17:42:25 +0300395 {
Geoff Lang61107632018-05-09 11:32:46 -0400396 functions->clearBufferfi(buffer, drawbuffer, depth, stencil);
Martin Radevb0761932017-07-25 17:42:25 +0300397 }
Martin Radev5e424fa2017-08-09 16:25:36 +0300398 else
399 {
Geoff Lang61107632018-05-09 11:32:46 -0400400 ClearMultiviewGL *multiviewClearer = GetMultiviewClearer(context);
401 multiviewClearer->clearMultiviewFBO(mState, context->getGLState().getScissor(),
402 ClearMultiviewGL::ClearCommandType::ClearBufferfi,
403 static_cast<GLbitfield>(0u), buffer, drawbuffer,
404 nullptr, depth, stencil);
Martin Radev5e424fa2017-08-09 16:25:36 +0300405 }
Geoff Lang4ad17092015-03-10 16:47:44 -0400406
Yuly Novikovc4d18aa2017-03-09 18:45:02 -0500407 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500408}
409
Jamie Madill4928b7c2017-06-20 12:57:39 -0400410GLenum FramebufferGL::getImplementationColorReadFormat(const gl::Context *context) const
Geoff Langf9a6f082015-01-22 13:32:49 -0500411{
Jamie Madilla3944d42016-07-22 22:13:26 -0400412 const auto *readAttachment = mState.getReadAttachment();
413 const Format &format = readAttachment->getFormat();
Geoff Langf607c602016-09-21 11:46:48 -0400414 return format.info->getReadPixelsFormat();
Geoff Langf9a6f082015-01-22 13:32:49 -0500415}
416
Jamie Madill4928b7c2017-06-20 12:57:39 -0400417GLenum FramebufferGL::getImplementationColorReadType(const gl::Context *context) const
Geoff Langf9a6f082015-01-22 13:32:49 -0500418{
Jamie Madilla3944d42016-07-22 22:13:26 -0400419 const auto *readAttachment = mState.getReadAttachment();
420 const Format &format = readAttachment->getFormat();
Geoff Langc71ea662017-09-26 17:06:02 -0400421 return format.info->getReadPixelsType(context->getClientVersion());
Geoff Langf9a6f082015-01-22 13:32:49 -0500422}
423
Jamie Madillc564c072017-06-01 12:45:42 -0400424Error FramebufferGL::readPixels(const gl::Context *context,
Frank Henigmanfa36c332017-06-09 18:44:45 -0400425 const gl::Rectangle &origArea,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500426 GLenum format,
427 GLenum type,
Jamie Madilld4826152017-09-21 11:18:59 -0400428 void *ptrOrOffset)
Geoff Langf9a6f082015-01-22 13:32:49 -0500429{
Geoff Lang61107632018-05-09 11:32:46 -0400430 const FunctionsGL *functions = GetFunctionsGL(context);
431 StateManagerGL *stateManager = GetStateManagerGL(context);
432 const WorkaroundsGL &workarounds = GetWorkaroundsGL(context);
433
Frank Henigmanfa36c332017-06-09 18:44:45 -0400434 // Clip read area to framebuffer.
435 const gl::Extents fbSize = getState().getReadAttachment()->getSize();
436 const gl::Rectangle fbRect(0, 0, fbSize.width, fbSize.height);
437 gl::Rectangle area;
438 if (!ClipRectangle(origArea, fbRect, &area))
439 {
440 // nothing to read
441 return gl::NoError();
442 }
443
Corentin Wallezcda6af12017-10-30 19:20:37 -0400444 PixelPackState packState = context->getGLState().getPackState();
Corentin Wallez336129f2017-10-17 15:55:40 -0400445 const gl::Buffer *packBuffer =
446 context->getGLState().getTargetBuffer(gl::BufferBinding::PixelPack);
Jamie Madill87de3622015-03-16 10:41:44 -0400447
Geoff Langf607c602016-09-21 11:46:48 -0400448 nativegl::ReadPixelsFormat readPixelsFormat =
Geoff Lang61107632018-05-09 11:32:46 -0400449 nativegl::GetReadPixelsFormat(functions, workarounds, format, type);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400450 GLenum readFormat = readPixelsFormat.format;
451 GLenum readType = readPixelsFormat.type;
Geoff Lang4ad17092015-03-10 16:47:44 -0400452
Geoff Lang61107632018-05-09 11:32:46 -0400453 stateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, mFramebufferID);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400454
Geoff Lang61107632018-05-09 11:32:46 -0400455 bool useOverlappingRowsWorkaround = workarounds.packOverlappingRowsSeparatelyPackBuffer &&
Corentin Wallezcda6af12017-10-30 19:20:37 -0400456 packBuffer && packState.rowLength != 0 &&
Frank Henigmanfa36c332017-06-09 18:44:45 -0400457 packState.rowLength < area.width;
458
Rafael Cintron05a449a2018-06-20 18:08:04 -0700459 GLubyte *pixels = static_cast<GLubyte *>(ptrOrOffset);
Frank Henigmanfa36c332017-06-09 18:44:45 -0400460 int leftClip = area.x - origArea.x;
461 int topClip = area.y - origArea.y;
462 if (leftClip || topClip)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400463 {
Frank Henigmanfa36c332017-06-09 18:44:45 -0400464 // Adjust destination to match portion clipped off left and/or top.
465 const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(readFormat, readType);
466
467 GLuint rowBytes = 0;
Jamie Madillca2ff382018-07-11 09:01:17 -0400468 ANGLE_TRY_CHECKED_MATH(glFormat.computeRowPitch(
469 readType, origArea.width, packState.alignment, packState.rowLength, &rowBytes));
Frank Henigmanfa36c332017-06-09 18:44:45 -0400470 pixels += leftClip * glFormat.pixelBytes + topClip * rowBytes;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400471 }
472
Frank Henigmanfa36c332017-06-09 18:44:45 -0400473 if (packState.rowLength == 0 && area.width != origArea.width)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400474 {
Frank Henigmanfa36c332017-06-09 18:44:45 -0400475 // No rowLength was specified so it will derive from read width, but clipping changed the
476 // read width. Use the original width so we fill the user's buffer as they intended.
477 packState.rowLength = origArea.width;
478 }
Corentin Wallez886de362016-09-27 10:49:35 -0400479
Frank Henigmanfa36c332017-06-09 18:44:45 -0400480 // We want to use rowLength, but that might not be supported.
481 bool cannotSetDesiredRowLength =
482 packState.rowLength && !GetImplAs<ContextGL>(context)->getNativeExtensions().packSubimage;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400483
Frank Henigmanfa36c332017-06-09 18:44:45 -0400484 gl::Error retVal = gl::NoError();
485 if (cannotSetDesiredRowLength || useOverlappingRowsWorkaround)
486 {
487 retVal = readPixelsRowByRow(context, area, readFormat, readType, packState, pixels);
488 }
489 else
490 {
491 gl::ErrorOrResult<bool> useLastRowPaddingWorkaround = false;
Geoff Lang61107632018-05-09 11:32:46 -0400492 if (workarounds.packLastRowSeparatelyForPaddingInclusion)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400493 {
Corentin Wallezcda6af12017-10-30 19:20:37 -0400494 useLastRowPaddingWorkaround = ShouldApplyLastRowPaddingWorkaround(
495 gl::Extents(area.width, area.height, 1), packState, packBuffer, readFormat,
496 readType, false, pixels);
Frank Henigmanfa36c332017-06-09 18:44:45 -0400497 }
498
499 if (useLastRowPaddingWorkaround.isError())
500 {
501 retVal = useLastRowPaddingWorkaround.getError();
502 }
503 else
504 {
505 retVal = readPixelsAllAtOnce(context, area, readFormat, readType, packState, pixels,
506 useLastRowPaddingWorkaround.getResult());
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400507 }
508 }
509
Frank Henigmanfa36c332017-06-09 18:44:45 -0400510 return retVal;
Geoff Langf9a6f082015-01-22 13:32:49 -0500511}
512
Jamie Madillc564c072017-06-01 12:45:42 -0400513Error FramebufferGL::blit(const gl::Context *context,
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500514 const gl::Rectangle &sourceArea,
515 const gl::Rectangle &destArea,
516 GLbitfield mask,
Jamie Madill8415b5f2016-04-26 13:41:39 -0400517 GLenum filter)
Geoff Langf9a6f082015-01-22 13:32:49 -0500518{
Geoff Lang61107632018-05-09 11:32:46 -0400519 const FunctionsGL *functions = GetFunctionsGL(context);
520 StateManagerGL *stateManager = GetStateManagerGL(context);
521
Jamie Madill231c7f52017-04-26 13:45:37 -0400522 const Framebuffer *sourceFramebuffer = context->getGLState().getReadFramebuffer();
523 const Framebuffer *destFramebuffer = context->getGLState().getDrawFramebuffer();
Geoff Lang4ad17092015-03-10 16:47:44 -0400524
Corentin Wallez6898b352016-11-10 11:41:15 -0500525 const FramebufferAttachment *colorReadAttachment = sourceFramebuffer->getReadColorbuffer();
Corentin Wallez4596a762016-12-20 14:50:18 -0500526
527 GLsizei readAttachmentSamples = 0;
528 if (colorReadAttachment != nullptr)
529 {
530 readAttachmentSamples = colorReadAttachment->getSamples();
531 }
Corentin Wallez6898b352016-11-10 11:41:15 -0500532
Corentin Wallez26a717b2016-09-27 08:45:42 -0700533 bool needManualColorBlit = false;
534
Corentin Wallez6898b352016-11-10 11:41:15 -0500535 // TODO(cwallez) when the filter is LINEAR and both source and destination are SRGB, we
536 // could avoid doing a manual blit.
537
538 // Prior to OpenGL 4.4 BlitFramebuffer (section 18.3.1 of GL 4.3 core profile) reads:
539 // When values are taken from the read buffer, no linearization is performed, even
540 // if the format of the buffer is SRGB.
541 // Starting from OpenGL 4.4 (section 18.3.1) it reads:
542 // When values are taken from the read buffer, if FRAMEBUFFER_SRGB is enabled and the
543 // value of FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING for the framebuffer attachment
544 // corresponding to the read buffer is SRGB, the red, green, and blue components are
545 // converted from the non-linear sRGB color space according [...].
Corentin Wallez26a717b2016-09-27 08:45:42 -0700546 {
Jamie Madill231c7f52017-04-26 13:45:37 -0400547 bool sourceSRGB =
548 colorReadAttachment != nullptr && colorReadAttachment->getColorEncoding() == GL_SRGB;
Corentin Wallez6898b352016-11-10 11:41:15 -0500549 needManualColorBlit =
Geoff Lang61107632018-05-09 11:32:46 -0400550 needManualColorBlit || (sourceSRGB && functions->isAtMostGL(gl::Version(4, 3)));
Corentin Wallez6898b352016-11-10 11:41:15 -0500551 }
Corentin Wallez26a717b2016-09-27 08:45:42 -0700552
Corentin Wallez6898b352016-11-10 11:41:15 -0500553 // Prior to OpenGL 4.2 BlitFramebuffer (section 4.3.2 of GL 4.1 core profile) reads:
554 // Blit operations bypass the fragment pipeline. The only fragment operations which
555 // affect a blit are the pixel ownership test and scissor test.
556 // Starting from OpenGL 4.2 (section 4.3.2) it reads:
557 // When values are written to the draw buffers, blit operations bypass the fragment
558 // pipeline. The only fragment operations which affect a blit are the pixel ownership
559 // test, the scissor test and sRGB conversion.
560 if (!needManualColorBlit)
561 {
562 bool destSRGB = false;
563 for (size_t i = 0; i < destFramebuffer->getDrawbufferStateCount(); ++i)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700564 {
Corentin Wallez6898b352016-11-10 11:41:15 -0500565 const FramebufferAttachment *attachment = destFramebuffer->getDrawBuffer(i);
566 if (attachment && attachment->getColorEncoding() == GL_SRGB)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700567 {
Corentin Wallez6898b352016-11-10 11:41:15 -0500568 destSRGB = true;
569 break;
Corentin Wallez26a717b2016-09-27 08:45:42 -0700570 }
Corentin Wallez26a717b2016-09-27 08:45:42 -0700571 }
Corentin Wallez6898b352016-11-10 11:41:15 -0500572
573 needManualColorBlit =
Geoff Lang61107632018-05-09 11:32:46 -0400574 needManualColorBlit || (destSRGB && functions->isAtMostGL(gl::Version(4, 1)));
Corentin Wallez26a717b2016-09-27 08:45:42 -0700575 }
576
577 // Enable FRAMEBUFFER_SRGB if needed
Geoff Lang61107632018-05-09 11:32:46 -0400578 stateManager->setFramebufferSRGBEnabledForFramebuffer(context, true, this);
Corentin Wallez26a717b2016-09-27 08:45:42 -0700579
580 GLenum blitMask = mask;
Corentin Wallez6898b352016-11-10 11:41:15 -0500581 if (needManualColorBlit && (mask & GL_COLOR_BUFFER_BIT) && readAttachmentSamples <= 1)
Corentin Wallez26a717b2016-09-27 08:45:42 -0700582 {
Geoff Lang61107632018-05-09 11:32:46 -0400583 BlitGL *blitter = GetBlitGL(context);
584 ANGLE_TRY(blitter->blitColorBufferWithShader(sourceFramebuffer, destFramebuffer, sourceArea,
585 destArea, filter));
Corentin Wallez26a717b2016-09-27 08:45:42 -0700586 blitMask &= ~GL_COLOR_BUFFER_BIT;
587 }
588
589 if (blitMask == 0)
590 {
591 return gl::NoError();
592 }
593
594 const FramebufferGL *sourceFramebufferGL = GetImplAs<FramebufferGL>(sourceFramebuffer);
Geoff Lang61107632018-05-09 11:32:46 -0400595 stateManager->bindFramebuffer(GL_READ_FRAMEBUFFER, sourceFramebufferGL->getFramebufferID());
596 stateManager->bindFramebuffer(GL_DRAW_FRAMEBUFFER, mFramebufferID);
Geoff Lang4ad17092015-03-10 16:47:44 -0400597
Geoff Lang61107632018-05-09 11:32:46 -0400598 functions->blitFramebuffer(sourceArea.x, sourceArea.y, sourceArea.x1(), sourceArea.y1(),
599 destArea.x, destArea.y, destArea.x1(), destArea.y1(), blitMask,
600 filter);
Geoff Lang4ad17092015-03-10 16:47:44 -0400601
Corentin Wallez26a717b2016-09-27 08:45:42 -0700602 return gl::NoError();
Geoff Langf9a6f082015-01-22 13:32:49 -0500603}
604
Geoff Lang13455072018-05-09 11:24:43 -0400605gl::Error FramebufferGL::getSamplePosition(const gl::Context *context,
606 size_t index,
607 GLfloat *xy) const
JiangYizhoubddc46b2016-12-09 09:50:51 +0800608{
Geoff Lang61107632018-05-09 11:32:46 -0400609 const FunctionsGL *functions = GetFunctionsGL(context);
610 StateManagerGL *stateManager = GetStateManagerGL(context);
611
612 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
613 functions->getMultisamplefv(GL_SAMPLE_POSITION, static_cast<GLuint>(index), xy);
JiangYizhoubddc46b2016-12-09 09:50:51 +0800614 return gl::NoError();
615}
616
Kenneth Russellce8602a2017-10-03 18:23:08 -0700617bool FramebufferGL::checkStatus(const gl::Context *context) const
Geoff Langf9a6f082015-01-22 13:32:49 -0500618{
Geoff Lang61107632018-05-09 11:32:46 -0400619 const FunctionsGL *functions = GetFunctionsGL(context);
620 StateManagerGL *stateManager = GetStateManagerGL(context);
621
622 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
623 GLenum status = functions->checkFramebufferStatus(GL_FRAMEBUFFER);
Jamie Madillcc86d642015-11-24 13:00:07 -0500624 if (status != GL_FRAMEBUFFER_COMPLETE)
625 {
Yuly Novikovbcb3f9b2017-01-27 22:45:18 -0500626 WARN() << "GL framebuffer returned incomplete.";
Jamie Madillcc86d642015-11-24 13:00:07 -0500627 }
628 return (status == GL_FRAMEBUFFER_COMPLETE);
Geoff Lang4ad17092015-03-10 16:47:44 -0400629}
630
Jamie Madill19fa1c62018-03-08 09:47:21 -0500631gl::Error FramebufferGL::syncState(const gl::Context *context,
632 const Framebuffer::DirtyBits &dirtyBits)
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500633{
634 // Don't need to sync state for the default FBO.
635 if (mIsDefault)
636 {
Jamie Madill19fa1c62018-03-08 09:47:21 -0500637 return gl::NoError();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500638 }
639
Geoff Lang61107632018-05-09 11:32:46 -0400640 const FunctionsGL *functions = GetFunctionsGL(context);
641 StateManagerGL *stateManager = GetStateManagerGL(context);
642
643 stateManager->bindFramebuffer(GL_FRAMEBUFFER, mFramebufferID);
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500644
Martin Radev7c2e6a92017-08-28 11:13:16 +0300645 // A pointer to one of the attachments for which the texture or the render buffer is not zero.
646 const FramebufferAttachment *attachment = nullptr;
Martin Radev878c8b12017-07-28 09:51:04 +0300647
Jamie Madill6de51852017-04-12 09:53:01 -0400648 for (auto dirtyBit : dirtyBits)
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500649 {
650 switch (dirtyBit)
651 {
652 case Framebuffer::DIRTY_BIT_DEPTH_ATTACHMENT:
Martin Radev7c2e6a92017-08-28 11:13:16 +0300653 {
654 const FramebufferAttachment *newAttachment = mState.getDepthAttachment();
Geoff Lang61107632018-05-09 11:32:46 -0400655 BindFramebufferAttachment(functions, GL_DEPTH_ATTACHMENT, newAttachment);
Martin Radev7c2e6a92017-08-28 11:13:16 +0300656 if (newAttachment)
657 {
658 attachment = newAttachment;
659 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500660 break;
Martin Radev7c2e6a92017-08-28 11:13:16 +0300661 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500662 case Framebuffer::DIRTY_BIT_STENCIL_ATTACHMENT:
Martin Radev7c2e6a92017-08-28 11:13:16 +0300663 {
664 const FramebufferAttachment *newAttachment = mState.getStencilAttachment();
Geoff Lang61107632018-05-09 11:32:46 -0400665 BindFramebufferAttachment(functions, GL_STENCIL_ATTACHMENT, newAttachment);
Martin Radev7c2e6a92017-08-28 11:13:16 +0300666 if (newAttachment)
667 {
668 attachment = newAttachment;
669 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500670 break;
Martin Radev7c2e6a92017-08-28 11:13:16 +0300671 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500672 case Framebuffer::DIRTY_BIT_DRAW_BUFFERS:
673 {
Jamie Madill48ef11b2016-04-27 15:21:52 -0400674 const auto &drawBuffers = mState.getDrawBufferStates();
Geoff Lang61107632018-05-09 11:32:46 -0400675 functions->drawBuffers(static_cast<GLsizei>(drawBuffers.size()),
676 drawBuffers.data());
Corentin Walleze7557742017-06-01 13:09:57 -0400677 mAppliedEnabledDrawBuffers = mState.getEnabledDrawBuffers();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500678 break;
679 }
680 case Framebuffer::DIRTY_BIT_READ_BUFFER:
Geoff Lang61107632018-05-09 11:32:46 -0400681 functions->readBuffer(mState.getReadBufferState());
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500682 break;
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800683 case Framebuffer::DIRTY_BIT_DEFAULT_WIDTH:
Geoff Lang61107632018-05-09 11:32:46 -0400684 functions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_WIDTH,
685 mState.getDefaultWidth());
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800686 break;
687 case Framebuffer::DIRTY_BIT_DEFAULT_HEIGHT:
Geoff Lang61107632018-05-09 11:32:46 -0400688 functions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_HEIGHT,
689 mState.getDefaultHeight());
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800690 break;
691 case Framebuffer::DIRTY_BIT_DEFAULT_SAMPLES:
Geoff Lang61107632018-05-09 11:32:46 -0400692 functions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_SAMPLES,
693 mState.getDefaultSamples());
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800694 break;
695 case Framebuffer::DIRTY_BIT_DEFAULT_FIXED_SAMPLE_LOCATIONS:
Geoff Lang61107632018-05-09 11:32:46 -0400696 functions->framebufferParameteri(
Geoff Lang92019432017-11-20 13:09:34 -0500697 GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS,
698 gl::ConvertToGLBoolean(mState.getDefaultFixedSampleLocations()));
JiangYizhouf7bbc8a2016-11-16 09:57:22 +0800699 break;
Jiawei Shaob1e91382018-05-17 14:33:55 +0800700 case Framebuffer::DIRTY_BIT_DEFAULT_LAYERS:
701 functions->framebufferParameteri(GL_FRAMEBUFFER, GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT,
702 mState.getDefaultLayers());
703 break;
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500704 default:
705 {
706 ASSERT(Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0 == 0 &&
707 dirtyBit < Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_MAX);
708 size_t index =
709 static_cast<size_t>(dirtyBit - Framebuffer::DIRTY_BIT_COLOR_ATTACHMENT_0);
Martin Radev7c2e6a92017-08-28 11:13:16 +0300710 const FramebufferAttachment *newAttachment = mState.getColorAttachment(index);
711 BindFramebufferAttachment(
Geoff Lang61107632018-05-09 11:32:46 -0400712 functions, static_cast<GLenum>(GL_COLOR_ATTACHMENT0 + index), newAttachment);
Martin Radev7c2e6a92017-08-28 11:13:16 +0300713 if (newAttachment)
714 {
715 attachment = newAttachment;
716 }
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500717 break;
718 }
719 }
720 }
Martin Radev878c8b12017-07-28 09:51:04 +0300721
Martin Radev7c2e6a92017-08-28 11:13:16 +0300722 if (attachment)
Martin Radev878c8b12017-07-28 09:51:04 +0300723 {
Martin Radev7c2e6a92017-08-28 11:13:16 +0300724 const bool isSideBySide =
725 (attachment->getMultiviewLayout() == GL_FRAMEBUFFER_MULTIVIEW_SIDE_BY_SIDE_ANGLE);
Geoff Lang61107632018-05-09 11:32:46 -0400726 stateManager->setSideBySide(isSideBySide);
727 stateManager->setViewportOffsets(attachment->getMultiviewViewportOffsets());
728 stateManager->updateMultiviewBaseViewLayerIndexUniform(context->getGLState().getProgram(),
729 getState());
Martin Radev878c8b12017-07-28 09:51:04 +0300730 }
Jamie Madill19fa1c62018-03-08 09:47:21 -0500731
732 return gl::NoError();
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500733}
734
Geoff Lang4ad17092015-03-10 16:47:44 -0400735GLuint FramebufferGL::getFramebufferID() const
736{
737 return mFramebufferID;
Geoff Langf9a6f082015-01-22 13:32:49 -0500738}
739
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700740bool FramebufferGL::isDefault() const
Geoff Langafd7f0a2015-09-09 15:33:31 -0400741{
Geoff Lang1d2c41d2016-10-19 16:14:46 -0700742 return mIsDefault;
Geoff Langafd7f0a2015-09-09 15:33:31 -0400743}
744
Geoff Lang61107632018-05-09 11:32:46 -0400745void FramebufferGL::maskOutInactiveOutputDrawBuffers(const gl::Context *context,
746 GLenum binding,
747 DrawBufferMask maxSet)
Corentin Walleze7557742017-06-01 13:09:57 -0400748{
Geoff Lang61107632018-05-09 11:32:46 -0400749
Corentin Walleze7557742017-06-01 13:09:57 -0400750 auto targetAppliedDrawBuffers = mState.getEnabledDrawBuffers() & maxSet;
751 if (mAppliedEnabledDrawBuffers != targetAppliedDrawBuffers)
752 {
753 mAppliedEnabledDrawBuffers = targetAppliedDrawBuffers;
754
755 const auto &stateDrawBuffers = mState.getDrawBufferStates();
756 GLsizei drawBufferCount = static_cast<GLsizei>(stateDrawBuffers.size());
757 ASSERT(drawBufferCount <= IMPLEMENTATION_MAX_DRAW_BUFFERS);
758
759 GLenum drawBuffers[IMPLEMENTATION_MAX_DRAW_BUFFERS];
760 for (GLenum i = 0; static_cast<int>(i) < drawBufferCount; ++i)
761 {
762 drawBuffers[i] = targetAppliedDrawBuffers[i] ? stateDrawBuffers[i] : GL_NONE;
763 }
764
Geoff Lang61107632018-05-09 11:32:46 -0400765 const FunctionsGL *functions = GetFunctionsGL(context);
766 StateManagerGL *stateManager = GetStateManagerGL(context);
767
768 stateManager->bindFramebuffer(binding, mFramebufferID);
769 functions->drawBuffers(drawBufferCount, drawBuffers);
Corentin Walleze7557742017-06-01 13:09:57 -0400770 }
771}
772
Jamie Madillc564c072017-06-01 12:45:42 -0400773void FramebufferGL::syncClearState(const gl::Context *context, GLbitfield mask)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400774{
Geoff Lang61107632018-05-09 11:32:46 -0400775 const FunctionsGL *functions = GetFunctionsGL(context);
776
777 if (functions->standard == STANDARD_GL_DESKTOP)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400778 {
Geoff Lang61107632018-05-09 11:32:46 -0400779 StateManagerGL *stateManager = GetStateManagerGL(context);
780 const WorkaroundsGL &workarounds = GetWorkaroundsGL(context);
781
782 if (workarounds.doesSRGBClearsOnLinearFramebufferAttachments &&
Frank Henigmana3d333c2016-03-22 22:09:14 -0400783 (mask & GL_COLOR_BUFFER_BIT) != 0 && !mIsDefault)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400784 {
Corentin Wallez26a717b2016-09-27 08:45:42 -0700785 bool hasSRGBAttachment = false;
Jamie Madill48ef11b2016-04-27 15:21:52 -0400786 for (const auto &attachment : mState.getColorAttachments())
Geoff Langafd7f0a2015-09-09 15:33:31 -0400787 {
Frank Henigmana3d333c2016-03-22 22:09:14 -0400788 if (attachment.isAttached() && attachment.getColorEncoding() == GL_SRGB)
789 {
Corentin Wallez26a717b2016-09-27 08:45:42 -0700790 hasSRGBAttachment = true;
Frank Henigmana3d333c2016-03-22 22:09:14 -0400791 break;
792 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400793 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400794
Geoff Lang61107632018-05-09 11:32:46 -0400795 stateManager->setFramebufferSRGBEnabled(context, hasSRGBAttachment);
Frank Henigmana3d333c2016-03-22 22:09:14 -0400796 }
797 else
798 {
Geoff Lang61107632018-05-09 11:32:46 -0400799 stateManager->setFramebufferSRGBEnabled(context, !mIsDefault);
Frank Henigmana3d333c2016-03-22 22:09:14 -0400800 }
Geoff Langafd7f0a2015-09-09 15:33:31 -0400801 }
802}
803
Jamie Madillc564c072017-06-01 12:45:42 -0400804void FramebufferGL::syncClearBufferState(const gl::Context *context,
805 GLenum buffer,
806 GLint drawBuffer)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400807{
Geoff Lang61107632018-05-09 11:32:46 -0400808 const FunctionsGL *functions = GetFunctionsGL(context);
809
810 if (functions->standard == STANDARD_GL_DESKTOP)
Geoff Langafd7f0a2015-09-09 15:33:31 -0400811 {
Geoff Lang61107632018-05-09 11:32:46 -0400812 StateManagerGL *stateManager = GetStateManagerGL(context);
813 const WorkaroundsGL &workarounds = GetWorkaroundsGL(context);
814
815 if (workarounds.doesSRGBClearsOnLinearFramebufferAttachments && buffer == GL_COLOR &&
Geoff Langafd7f0a2015-09-09 15:33:31 -0400816 !mIsDefault)
817 {
818 // If doing a clear on a color buffer, set SRGB blend enabled only if the color buffer
819 // is an SRGB format.
Jamie Madill48ef11b2016-04-27 15:21:52 -0400820 const auto &drawbufferState = mState.getDrawBufferStates();
821 const auto &colorAttachments = mState.getColorAttachments();
Geoff Langafd7f0a2015-09-09 15:33:31 -0400822
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500823 const FramebufferAttachment *attachment = nullptr;
Geoff Langafd7f0a2015-09-09 15:33:31 -0400824 if (drawbufferState[drawBuffer] >= GL_COLOR_ATTACHMENT0 &&
825 drawbufferState[drawBuffer] < GL_COLOR_ATTACHMENT0 + colorAttachments.size())
826 {
827 size_t attachmentIdx =
828 static_cast<size_t>(drawbufferState[drawBuffer] - GL_COLOR_ATTACHMENT0);
829 attachment = &colorAttachments[attachmentIdx];
830 }
831
832 if (attachment != nullptr)
833 {
Geoff Lang61107632018-05-09 11:32:46 -0400834 stateManager->setFramebufferSRGBEnabled(context,
835 attachment->getColorEncoding() == GL_SRGB);
Geoff Langafd7f0a2015-09-09 15:33:31 -0400836 }
837 }
838 else
839 {
Geoff Lang61107632018-05-09 11:32:46 -0400840 stateManager->setFramebufferSRGBEnabled(context, !mIsDefault);
Geoff Langafd7f0a2015-09-09 15:33:31 -0400841 }
842 }
843}
Geoff Lang005a7012017-03-27 13:17:34 -0400844
845bool FramebufferGL::modifyInvalidateAttachmentsForEmulatedDefaultFBO(
846 size_t count,
847 const GLenum *attachments,
848 std::vector<GLenum> *modifiedAttachments) const
849{
850 bool needsModification = mIsDefault && mFramebufferID != 0;
851 if (!needsModification)
852 {
853 return false;
854 }
855
856 modifiedAttachments->resize(count);
857 for (size_t i = 0; i < count; i++)
858 {
859 switch (attachments[i])
860 {
861 case GL_COLOR:
862 (*modifiedAttachments)[i] = GL_COLOR_ATTACHMENT0;
863 break;
864
865 case GL_DEPTH:
866 (*modifiedAttachments)[i] = GL_DEPTH_ATTACHMENT;
867 break;
868
869 case GL_STENCIL:
870 (*modifiedAttachments)[i] = GL_STENCIL_ATTACHMENT;
871 break;
872
873 default:
874 UNREACHABLE();
875 break;
876 }
877 }
878
879 return true;
880}
881
Frank Henigmanfa36c332017-06-09 18:44:45 -0400882gl::Error FramebufferGL::readPixelsRowByRow(const gl::Context *context,
883 const gl::Rectangle &area,
884 GLenum format,
885 GLenum type,
886 const gl::PixelPackState &pack,
887 GLubyte *pixels) const
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400888{
Geoff Lang61107632018-05-09 11:32:46 -0400889 const FunctionsGL *functions = GetFunctionsGL(context);
890 StateManagerGL *stateManager = GetStateManagerGL(context);
891
Geoff Langca271392017-04-05 12:30:00 -0400892 const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(format, type);
Frank Henigmanfa36c332017-06-09 18:44:45 -0400893
894 GLuint rowBytes = 0;
Jamie Madillca2ff382018-07-11 09:01:17 -0400895 ANGLE_TRY_CHECKED_MATH(
896 glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength, &rowBytes));
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400897 GLuint skipBytes = 0;
Jamie Madillca2ff382018-07-11 09:01:17 -0400898 ANGLE_TRY_CHECKED_MATH(glFormat.computeSkipBytes(type, rowBytes, 0, pack, false, &skipBytes));
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400899
900 gl::PixelPackState directPack;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400901 directPack.alignment = 1;
Geoff Lang61107632018-05-09 11:32:46 -0400902 stateManager->setPixelPackState(directPack);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400903
Frank Henigmanfa36c332017-06-09 18:44:45 -0400904 pixels += skipBytes;
905 for (GLint y = area.y; y < area.y + area.height; ++y)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400906 {
Geoff Lang61107632018-05-09 11:32:46 -0400907 functions->readPixels(area.x, y, area.width, 1, format, type, pixels);
Frank Henigmanfa36c332017-06-09 18:44:45 -0400908 pixels += rowBytes;
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400909 }
910
911 return gl::NoError();
912}
913
Frank Henigmanfa36c332017-06-09 18:44:45 -0400914gl::Error FramebufferGL::readPixelsAllAtOnce(const gl::Context *context,
915 const gl::Rectangle &area,
916 GLenum format,
917 GLenum type,
918 const gl::PixelPackState &pack,
919 GLubyte *pixels,
920 bool readLastRowSeparately) const
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400921{
Geoff Lang61107632018-05-09 11:32:46 -0400922 const FunctionsGL *functions = GetFunctionsGL(context);
923 StateManagerGL *stateManager = GetStateManagerGL(context);
924
Frank Henigmanfa36c332017-06-09 18:44:45 -0400925 GLint height = area.height - readLastRowSeparately;
926 if (height > 0)
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400927 {
Geoff Lang61107632018-05-09 11:32:46 -0400928 stateManager->setPixelPackState(pack);
929 functions->readPixels(area.x, area.y, area.width, height, format, type, pixels);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400930 }
931
Frank Henigmanfa36c332017-06-09 18:44:45 -0400932 if (readLastRowSeparately)
933 {
934 const gl::InternalFormat &glFormat = gl::GetInternalFormatInfo(format, type);
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400935
Frank Henigmanfa36c332017-06-09 18:44:45 -0400936 GLuint rowBytes = 0;
Jamie Madillca2ff382018-07-11 09:01:17 -0400937 ANGLE_TRY_CHECKED_MATH(
938 glFormat.computeRowPitch(type, area.width, pack.alignment, pack.rowLength, &rowBytes));
Frank Henigmanfa36c332017-06-09 18:44:45 -0400939 GLuint skipBytes = 0;
Jamie Madillca2ff382018-07-11 09:01:17 -0400940 ANGLE_TRY_CHECKED_MATH(
941 glFormat.computeSkipBytes(type, rowBytes, 0, pack, false, &skipBytes));
Frank Henigmanfa36c332017-06-09 18:44:45 -0400942
943 gl::PixelPackState directPack;
Frank Henigmanfa36c332017-06-09 18:44:45 -0400944 directPack.alignment = 1;
Geoff Lang61107632018-05-09 11:32:46 -0400945 stateManager->setPixelPackState(directPack);
Frank Henigmanfa36c332017-06-09 18:44:45 -0400946
947 pixels += skipBytes + (area.height - 1) * rowBytes;
Geoff Lang61107632018-05-09 11:32:46 -0400948 functions->readPixels(area.x, area.y + area.height - 1, area.width, 1, format, type,
949 pixels);
Frank Henigmanfa36c332017-06-09 18:44:45 -0400950 }
Corentin Wallez9a8d3662016-09-22 12:18:29 -0400951
952 return gl::NoError();
953}
Jamie Madill60ec6ea2016-01-22 15:27:19 -0500954} // namespace rx