7 #include "flutter/fml/trace_event.h"
16 RenderPassGLES::RenderPassGLES(std::weak_ptr<const Context> context,
17 const RenderTarget& target,
19 : RenderPass(
std::move(context), target),
20 reactor_(
std::move(reactor)),
21 is_valid_(reactor_ && reactor_->IsValid()) {}
27 bool RenderPassGLES::IsValid()
const {
32 void RenderPassGLES::OnSetLabel(std::string label) {
33 label_ = std::move(label);
46 gl.BlendEquationSeparate(
55 const auto is_set = [](std::underlying_type_t<ColorWriteMask> mask,
57 using RawType = decltype(mask);
58 return (
static_cast<RawType
>(mask) &
static_cast<RawType
>(check))
74 uint32_t stencil_reference) {
81 gl.StencilFuncSeparate(face,
86 gl.StencilMaskSeparate(face, stencil.
write_mask);
91 uint32_t stencil_reference) {
93 gl.Disable(GL_STENCIL_TEST);
97 gl.Enable(GL_STENCIL_TEST);
101 if (front.has_value() && back.has_value() && front == back) {
105 if (front.has_value()) {
108 if (back.has_value()) {
141 const std::shared_ptr<Allocator>& transients_allocator,
143 const std::vector<Command>& commands) {
144 TRACE_EVENT0(
"impeller",
"RenderPassGLES::EncodeCommandsInReactor");
146 if (commands.empty()) {
152 fml::ScopedCleanupClosure pop_pass_debug_marker(
153 [&gl]() { gl.PopDebugGroup(); });
154 if (!pass_data.
label.empty()) {
157 pop_pass_debug_marker.Release();
160 GLuint fbo = GL_NONE;
161 fml::ScopedCleanupClosure delete_fbo([&gl, &fbo]() {
162 if (fbo != GL_NONE) {
163 gl.BindFramebuffer(GL_FRAMEBUFFER, GL_NONE);
164 gl.DeleteFramebuffers(1u, &fbo);
168 const auto is_default_fbo =
171 if (!is_default_fbo) {
173 gl.GenFramebuffers(1u, &fbo);
174 gl.BindFramebuffer(GL_FRAMEBUFFER, fbo);
177 if (!color->SetAsFramebufferAttachment(
183 if (!depth->SetAsFramebufferAttachment(
189 if (!stencil->SetAsFramebufferAttachment(
195 if (gl.CheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
213 GLenum clear_bits = 0u;
215 clear_bits |= GL_COLOR_BUFFER_BIT;
218 clear_bits |= GL_DEPTH_BUFFER_BIT;
221 clear_bits |= GL_STENCIL_BUFFER_BIT;
224 gl.Disable(GL_SCISSOR_TEST);
225 gl.Disable(GL_DEPTH_TEST);
226 gl.Disable(GL_STENCIL_TEST);
227 gl.Disable(GL_CULL_FACE);
228 gl.Disable(GL_BLEND);
229 gl.ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
231 gl.Clear(clear_bits);
233 for (
const auto& command : commands) {
234 if (command.instance_count != 1u) {
235 VALIDATION_LOG <<
"GLES backend does not support instanced rendering.";
239 if (!command.pipeline) {
244 #ifdef IMPELLER_DEBUG
245 fml::ScopedCleanupClosure pop_cmd_debug_marker(
246 [&gl]() { gl.PopDebugGroup(); });
247 if (!command.label.empty()) {
248 gl.PushDebugGroup(command.label);
250 pop_cmd_debug_marker.Release();
252 #endif // IMPELLER_DEBUG
256 const auto* color_attachment =
257 pipeline.GetDescriptor().GetLegacyCompatibleColorAttachment();
258 if (!color_attachment) {
260 <<
"Color attachment is too complicated for a legacy renderer.";
278 pipeline.GetDescriptor().GetDepthStencilAttachmentDescriptor();
280 gl.Enable(GL_DEPTH_TEST);
282 gl.DepthMask(depth->depth_write_enabled ? GL_TRUE : GL_FALSE);
284 gl.Disable(GL_DEPTH_TEST);
295 const auto& viewport = command.viewport.value_or(pass_data.
viewport);
296 gl.Viewport(viewport.rect.origin.x,
297 target_size.height - viewport.rect.origin.y -
298 viewport.rect.size.height,
299 viewport.rect.size.width,
300 viewport.rect.size.height
303 gl.DepthRangef(viewport.depth_range.z_near, viewport.depth_range.z_far);
309 if (command.scissor.has_value()) {
310 const auto& scissor = command.scissor.value();
311 gl.Enable(GL_SCISSOR_TEST);
314 target_size.height - scissor.origin.y - scissor.size.height,
319 gl.Disable(GL_SCISSOR_TEST);
325 switch (pipeline.GetDescriptor().GetCullMode()) {
327 gl.Disable(GL_CULL_FACE);
330 gl.Enable(GL_CULL_FACE);
331 gl.CullFace(GL_FRONT);
334 gl.Enable(GL_CULL_FACE);
335 gl.CullFace(GL_BACK);
341 switch (pipeline.GetDescriptor().GetWindingOrder()) {
346 gl.FrontFace(GL_CCW);
354 const auto& vertex_desc_gles = pipeline.GetBufferBindings();
359 auto vertex_buffer_view = command.GetVertexBuffer();
361 if (!vertex_buffer_view) {
366 vertex_buffer_view.buffer->GetDeviceBuffer(*transients_allocator);
368 if (!vertex_buffer) {
373 if (!vertex_buffer_gles.BindAndUploadDataIfNecessary(
381 if (!pipeline.BindProgram()) {
388 if (!vertex_desc_gles->BindVertexAttributes(
389 gl, vertex_buffer_view.range.offset)) {
396 if (!vertex_desc_gles->BindUniformData(gl,
397 *transients_allocator,
398 command.vertex_bindings,
399 command.fragment_bindings
414 :
ToMode(pipeline.GetDescriptor().GetPrimitiveType());
420 gl.DrawArrays(mode, command.base_vertex, command.vertex_count);
423 auto index_buffer_view = command.index_buffer;
425 index_buffer_view.buffer->GetDeviceBuffer(*transients_allocator);
427 if (!index_buffer_gles.BindAndUploadDataIfNecessary(
431 gl.DrawElements(mode,
432 command.vertex_count,
434 reinterpret_cast<const GLvoid*
>(
static_cast<GLsizei
>(
435 index_buffer_view.range.offset))
442 if (!vertex_desc_gles->UnbindVertexAttributes(gl)) {
449 if (!pipeline.UnbindProgram()) {
454 if (gl.DiscardFramebufferEXT.IsAvailable()) {
455 std::vector<GLenum> attachments;
458 attachments.push_back(is_default_fbo ? GL_COLOR_EXT
459 : GL_COLOR_ATTACHMENT0);
462 attachments.push_back(is_default_fbo ? GL_DEPTH_EXT
463 : GL_DEPTH_ATTACHMENT);
474 attachments.push_back(is_default_fbo ? GL_STENCIL_EXT
475 : GL_STENCIL_ATTACHMENT);
477 gl.DiscardFramebufferEXT(GL_FRAMEBUFFER,
487 bool RenderPassGLES::OnEncodeCommands(
const Context& context)
const {
495 if (!render_target.HasColorAttachment(0u)) {
498 const auto& color0 = render_target.GetColorAttachments().at(0u);
499 const auto& depth0 = render_target.GetDepthAttachment();
500 const auto& stencil0 = render_target.GetStencilAttachment();
502 auto pass_data = std::make_shared<RenderPassData>();
503 pass_data->
label = label_;
518 if (depth0.has_value()) {
529 if (stencil0.has_value()) {
538 std::shared_ptr<const RenderPassGLES> shared_this = shared_from_this();
539 return reactor_->AddOperation([pass_data,
541 render_pass = std::move(shared_this)](
542 const auto& reactor) {
543 auto result = EncodeCommandsInReactor(*pass_data, allocator, reactor,
544 render_pass->commands_);
545 FML_CHECK(result) <<
"Must be able to encode GL commands without error.";