10 #include "flutter/fml/trace_event.h"
11 #include "fml/closure.h"
12 #include "fml/logging.h"
23 RenderPassGLES::RenderPassGLES(std::shared_ptr<const Context> context,
24 const RenderTarget& target,
26 : RenderPass(
std::move(context), target),
27 reactor_(
std::move(reactor)),
28 is_valid_(reactor_ && reactor_->IsValid()) {}
34 bool RenderPassGLES::IsValid()
const {
39 void RenderPassGLES::OnSetLabel(std::string label) {
40 label_ = std::move(label);
45 if (
color->blending_enabled) {
53 gl.BlendEquationSeparate(
64 return (mask & check) ? GL_TRUE : GL_FALSE;
79 uint32_t stencil_reference) {
86 gl.StencilFuncSeparate(face,
91 gl.StencilMaskSeparate(face, stencil.
write_mask);
96 uint32_t stencil_reference) {
98 gl.Disable(GL_STENCIL_TEST);
102 gl.Enable(GL_STENCIL_TEST);
106 if (front.has_value() && back.has_value() && front == back) {
110 if (front.has_value()) {
113 if (back.has_value()) {
146 const std::shared_ptr<Allocator>& transients_allocator,
148 const std::vector<Command>& commands,
149 const std::shared_ptr<GPUTracerGLES>& tracer) {
150 TRACE_EVENT0(
"impeller",
"RenderPassGLES::EncodeCommandsInReactor");
153 #ifdef IMPELLER_DEBUG
154 tracer->MarkFrameStart(gl);
155 #endif // IMPELLER_DEBUG
157 fml::ScopedCleanupClosure pop_pass_debug_marker(
158 [&gl]() { gl.PopDebugGroup(); });
159 if (!pass_data.
label.empty()) {
162 pop_pass_debug_marker.Release();
165 GLuint fbo = GL_NONE;
166 fml::ScopedCleanupClosure delete_fbo([&gl, &fbo]() {
167 if (fbo != GL_NONE) {
168 gl.BindFramebuffer(GL_FRAMEBUFFER, GL_NONE);
169 gl.DeleteFramebuffers(1u, &fbo);
174 const bool is_default_fbo = color_gles.IsWrapped();
176 if (is_default_fbo) {
177 if (color_gles.GetFBO().has_value()) {
179 gl.BindFramebuffer(GL_FRAMEBUFFER, *color_gles.GetFBO());
183 gl.GenFramebuffers(1u, &fbo);
184 gl.BindFramebuffer(GL_FRAMEBUFFER, fbo);
186 if (!color_gles.SetAsFramebufferAttachment(
192 if (!depth->SetAsFramebufferAttachment(
198 if (!stencil->SetAsFramebufferAttachment(
204 auto status = gl.CheckFramebufferStatus(GL_FRAMEBUFFER);
205 if (status != GL_FRAMEBUFFER_COMPLETE) {
218 if (gl.DepthRangef.IsAvailable()) {
228 GLenum clear_bits = 0u;
230 clear_bits |= GL_COLOR_BUFFER_BIT;
233 clear_bits |= GL_DEPTH_BUFFER_BIT;
236 clear_bits |= GL_STENCIL_BUFFER_BIT;
239 gl.Disable(GL_SCISSOR_TEST);
240 gl.Disable(GL_DEPTH_TEST);
241 gl.Disable(GL_STENCIL_TEST);
242 gl.Disable(GL_CULL_FACE);
243 gl.Disable(GL_BLEND);
244 gl.Disable(GL_DITHER);
245 gl.ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
246 gl.DepthMask(GL_TRUE);
247 gl.StencilMaskSeparate(GL_FRONT, 0xFFFFFFFF);
248 gl.StencilMaskSeparate(GL_BACK, 0xFFFFFFFF);
250 gl.Clear(clear_bits);
252 for (
const auto& command : commands) {
253 if (command.instance_count != 1u) {
254 VALIDATION_LOG <<
"GLES backend does not support instanced rendering.";
258 if (!command.pipeline) {
263 #ifdef IMPELLER_DEBUG
264 fml::ScopedCleanupClosure pop_cmd_debug_marker(
265 [&gl]() { gl.PopDebugGroup(); });
266 if (!command.label.empty()) {
267 gl.PushDebugGroup(command.label);
269 pop_cmd_debug_marker.Release();
271 #endif // IMPELLER_DEBUG
275 const auto* color_attachment =
276 pipeline.GetDescriptor().GetLegacyCompatibleColorAttachment();
277 if (!color_attachment) {
279 <<
"Color attachment is too complicated for a legacy renderer.";
297 pipeline.GetDescriptor().GetDepthStencilAttachmentDescriptor();
299 gl.Enable(GL_DEPTH_TEST);
301 gl.DepthMask(depth->depth_write_enabled ? GL_TRUE : GL_FALSE);
303 gl.Disable(GL_DEPTH_TEST);
314 const auto& viewport = command.viewport.value_or(pass_data.
viewport);
315 gl.Viewport(viewport.rect.GetX(),
316 target_size.height - viewport.rect.GetY() -
317 viewport.rect.GetHeight(),
318 viewport.rect.GetWidth(),
319 viewport.rect.GetHeight()
322 if (gl.DepthRangef.IsAvailable()) {
323 gl.DepthRangef(viewport.depth_range.z_near, viewport.depth_range.z_far);
325 gl.DepthRange(viewport.depth_range.z_near, viewport.depth_range.z_far);
332 if (command.scissor.has_value()) {
333 const auto& scissor = command.scissor.value();
334 gl.Enable(GL_SCISSOR_TEST);
337 target_size.height - scissor.GetY() - scissor.GetHeight(),
346 switch (pipeline.GetDescriptor().GetCullMode()) {
348 gl.Disable(GL_CULL_FACE);
351 gl.Enable(GL_CULL_FACE);
352 gl.CullFace(GL_FRONT);
355 gl.Enable(GL_CULL_FACE);
356 gl.CullFace(GL_BACK);
362 switch (pipeline.GetDescriptor().GetWindingOrder()) {
367 gl.FrontFace(GL_CCW);
375 auto vertex_desc_gles = pipeline.GetBufferBindings();
380 auto& vertex_buffer_view = command.vertex_buffer.vertex_buffer;
382 if (!vertex_buffer_view) {
386 auto vertex_buffer = vertex_buffer_view.buffer;
388 if (!vertex_buffer) {
393 if (!vertex_buffer_gles.BindAndUploadDataIfNecessary(
401 if (!pipeline.BindProgram()) {
408 if (!vertex_desc_gles->BindVertexAttributes(
409 gl, vertex_buffer_view.range.offset)) {
416 if (!vertex_desc_gles->BindUniformData(gl,
417 *transients_allocator,
418 command.vertex_bindings,
419 command.fragment_bindings
434 :
ToMode(pipeline.GetDescriptor().GetPrimitiveType());
440 gl.DrawArrays(mode, command.base_vertex,
441 command.vertex_buffer.vertex_count);
444 auto index_buffer_view = command.vertex_buffer.index_buffer;
445 auto index_buffer = index_buffer_view.buffer;
447 if (!index_buffer_gles.BindAndUploadDataIfNecessary(
451 gl.DrawElements(mode,
452 command.vertex_buffer.vertex_count,
454 reinterpret_cast<const GLvoid*
>(
static_cast<GLsizei
>(
455 index_buffer_view.range.offset))
462 if (!vertex_desc_gles->UnbindVertexAttributes(gl)) {
469 if (!pipeline.UnbindProgram()) {
474 if (gl.DiscardFramebufferEXT.IsAvailable()) {
475 std::vector<GLenum> attachments;
480 bool angle_safe = gl.GetCapabilities()->IsANGLE() ? !is_default_fbo :
true;
483 attachments.push_back(is_default_fbo ? GL_COLOR_EXT
484 : GL_COLOR_ATTACHMENT0);
487 attachments.push_back(is_default_fbo ? GL_DEPTH_EXT
488 : GL_DEPTH_ATTACHMENT);
492 attachments.push_back(is_default_fbo ? GL_STENCIL_EXT
493 : GL_STENCIL_ATTACHMENT);
495 gl.DiscardFramebufferEXT(GL_FRAMEBUFFER,
501 #ifdef IMPELLER_DEBUG
502 if (is_default_fbo) {
503 tracer->MarkFrameEnd(gl);
505 #endif // IMPELLER_DEBUG
511 bool RenderPassGLES::OnEncodeCommands(
const Context& context)
const {
516 if (!render_target.HasColorAttachment(0u)) {
519 const auto& color0 = render_target.GetColorAttachments().at(0u);
520 const auto& depth0 = render_target.GetDepthAttachment();
521 const auto& stencil0 = render_target.GetStencilAttachment();
523 auto pass_data = std::make_shared<RenderPassData>();
524 pass_data->label = label_;
530 pass_data->color_attachment = color0.texture;
531 pass_data->clear_color = color0.clear_color;
533 pass_data->discard_color_attachment =
539 if (color0.resolve_texture) {
540 FML_DCHECK(context.GetCapabilities()->SupportsImplicitResolvingMSAA());
541 pass_data->discard_color_attachment =
false;
547 if (depth0.has_value()) {
548 pass_data->depth_attachment = depth0->texture;
549 pass_data->clear_depth = depth0->clear_depth;
551 pass_data->discard_depth_attachment =
558 if (stencil0.has_value()) {
559 pass_data->stencil_attachment = stencil0->texture;
560 pass_data->clear_stencil = stencil0->clear_stencil;
561 pass_data->clear_stencil_attachment =
563 pass_data->discard_stencil_attachment =
567 std::shared_ptr<const RenderPassGLES> shared_this = shared_from_this();
569 return reactor_->AddOperation([pass_data,
570 allocator = context.GetResourceAllocator(),
571 render_pass = std::move(shared_this),
572 tracer](
const auto& reactor) {
573 auto result = EncodeCommandsInReactor(*pass_data, allocator, reactor,
574 render_pass->commands_, tracer);
575 FML_CHECK(result) <<
"Must be able to encode GL commands without error.";