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);
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);
173 const auto is_default_fbo =
176 if (!is_default_fbo) {
178 gl.GenFramebuffers(1u, &fbo);
179 gl.BindFramebuffer(GL_FRAMEBUFFER, fbo);
182 if (!color->SetAsFramebufferAttachment(
189 if (!depth->SetAsFramebufferAttachment(
195 if (!stencil->SetAsFramebufferAttachment(
201 auto status = gl.CheckFramebufferStatus(GL_FRAMEBUFFER);
202 if (status != GL_FRAMEBUFFER_COMPLETE) {
215 if (gl.DepthRangef.IsAvailable()) {
225 GLenum clear_bits = 0u;
227 clear_bits |= GL_COLOR_BUFFER_BIT;
230 clear_bits |= GL_DEPTH_BUFFER_BIT;
233 clear_bits |= GL_STENCIL_BUFFER_BIT;
236 gl.Disable(GL_SCISSOR_TEST);
237 gl.Disable(GL_DEPTH_TEST);
238 gl.Disable(GL_STENCIL_TEST);
239 gl.Disable(GL_CULL_FACE);
240 gl.Disable(GL_BLEND);
241 gl.ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
242 gl.DepthMask(GL_TRUE);
243 gl.StencilMaskSeparate(GL_FRONT, 0xFFFFFFFF);
244 gl.StencilMaskSeparate(GL_BACK, 0xFFFFFFFF);
246 gl.Clear(clear_bits);
248 for (
const auto& command : commands) {
249 if (command.instance_count != 1u) {
250 VALIDATION_LOG <<
"GLES backend does not support instanced rendering.";
254 if (!command.pipeline) {
259 #ifdef IMPELLER_DEBUG
260 fml::ScopedCleanupClosure pop_cmd_debug_marker(
261 [&gl]() { gl.PopDebugGroup(); });
262 if (!command.label.empty()) {
263 gl.PushDebugGroup(command.label);
265 pop_cmd_debug_marker.Release();
267 #endif // IMPELLER_DEBUG
271 const auto* color_attachment =
272 pipeline.GetDescriptor().GetLegacyCompatibleColorAttachment();
273 if (!color_attachment) {
275 <<
"Color attachment is too complicated for a legacy renderer.";
293 pipeline.GetDescriptor().GetDepthStencilAttachmentDescriptor();
295 gl.Enable(GL_DEPTH_TEST);
297 gl.DepthMask(depth->depth_write_enabled ? GL_TRUE : GL_FALSE);
299 gl.Disable(GL_DEPTH_TEST);
310 const auto& viewport = command.viewport.value_or(pass_data.
viewport);
311 gl.Viewport(viewport.rect.GetX(),
312 target_size.height - viewport.rect.GetY() -
313 viewport.rect.GetHeight(),
314 viewport.rect.GetWidth(),
315 viewport.rect.GetHeight()
318 if (gl.DepthRangef.IsAvailable()) {
319 gl.DepthRangef(viewport.depth_range.z_near, viewport.depth_range.z_far);
321 gl.DepthRange(viewport.depth_range.z_near, viewport.depth_range.z_far);
328 if (command.scissor.has_value()) {
329 const auto& scissor = command.scissor.value();
330 gl.Enable(GL_SCISSOR_TEST);
333 target_size.height - scissor.GetY() - scissor.GetHeight(),
338 gl.Disable(GL_SCISSOR_TEST);
344 switch (pipeline.GetDescriptor().GetCullMode()) {
346 gl.Disable(GL_CULL_FACE);
349 gl.Enable(GL_CULL_FACE);
350 gl.CullFace(GL_FRONT);
353 gl.Enable(GL_CULL_FACE);
354 gl.CullFace(GL_BACK);
360 switch (pipeline.GetDescriptor().GetWindingOrder()) {
365 gl.FrontFace(GL_CCW);
373 auto vertex_desc_gles = pipeline.GetBufferBindings();
378 auto& vertex_buffer_view = command.vertex_buffer.vertex_buffer;
380 if (!vertex_buffer_view) {
384 auto vertex_buffer = vertex_buffer_view.buffer;
386 if (!vertex_buffer) {
391 if (!vertex_buffer_gles.BindAndUploadDataIfNecessary(
399 if (!pipeline.BindProgram()) {
406 if (!vertex_desc_gles->BindVertexAttributes(
407 gl, vertex_buffer_view.range.offset)) {
414 if (!vertex_desc_gles->BindUniformData(gl,
415 *transients_allocator,
416 command.vertex_bindings,
417 command.fragment_bindings
432 :
ToMode(pipeline.GetDescriptor().GetPrimitiveType());
438 gl.DrawArrays(mode, command.base_vertex,
439 command.vertex_buffer.vertex_count);
442 auto index_buffer_view = command.vertex_buffer.index_buffer;
443 auto index_buffer = index_buffer_view.buffer;
445 if (!index_buffer_gles.BindAndUploadDataIfNecessary(
449 gl.DrawElements(mode,
450 command.vertex_buffer.vertex_count,
452 reinterpret_cast<const GLvoid*
>(
static_cast<GLsizei
>(
453 index_buffer_view.range.offset))
460 if (!vertex_desc_gles->UnbindVertexAttributes(gl)) {
467 if (!pipeline.UnbindProgram()) {
472 if (gl.DiscardFramebufferEXT.IsAvailable()) {
473 std::vector<GLenum> attachments;
478 bool angle_safe = gl.GetCapabilities()->IsANGLE() ? !is_default_fbo :
true;
481 attachments.push_back(is_default_fbo ? GL_COLOR_EXT
482 : GL_COLOR_ATTACHMENT0);
485 attachments.push_back(is_default_fbo ? GL_DEPTH_EXT
486 : GL_DEPTH_ATTACHMENT);
490 attachments.push_back(is_default_fbo ? GL_STENCIL_EXT
491 : GL_STENCIL_ATTACHMENT);
493 gl.DiscardFramebufferEXT(GL_FRAMEBUFFER,
499 #ifdef IMPELLER_DEBUG
500 if (is_default_fbo) {
501 tracer->MarkFrameEnd(gl);
503 #endif // IMPELLER_DEBUG
509 bool RenderPassGLES::OnEncodeCommands(
const Context& context)
const {
514 if (!render_target.HasColorAttachment(0u)) {
517 const auto& color0 = render_target.GetColorAttachments().at(0u);
518 const auto& depth0 = render_target.GetDepthAttachment();
519 const auto& stencil0 = render_target.GetStencilAttachment();
521 auto pass_data = std::make_shared<RenderPassData>();
522 pass_data->label = label_;
528 pass_data->color_attachment = color0.texture;
529 pass_data->clear_color = color0.clear_color;
531 pass_data->discard_color_attachment =
537 if (color0.resolve_texture) {
538 FML_DCHECK(context.GetCapabilities()->SupportsImplicitResolvingMSAA());
539 pass_data->discard_color_attachment =
false;
545 if (depth0.has_value()) {
546 pass_data->depth_attachment = depth0->texture;
547 pass_data->clear_depth = depth0->clear_depth;
549 pass_data->discard_depth_attachment =
556 if (stencil0.has_value()) {
557 pass_data->stencil_attachment = stencil0->texture;
558 pass_data->clear_stencil = stencil0->clear_stencil;
559 pass_data->clear_stencil_attachment =
561 pass_data->discard_stencil_attachment =
565 std::shared_ptr<const RenderPassGLES> shared_this = shared_from_this();
567 return reactor_->AddOperation([pass_data,
568 allocator = context.GetResourceAllocator(),
569 render_pass = std::move(shared_this),
570 tracer](
const auto& reactor) {
571 auto result = EncodeCommandsInReactor(*pass_data, allocator, reactor,
572 render_pass->commands_, tracer);
573 FML_CHECK(result) <<
"Must be able to encode GL commands without error.";