9 #include "flutter/fml/trace_event.h" 
   10 #include "fml/closure.h" 
   11 #include "fml/logging.h" 
   26 RenderPassGLES::RenderPassGLES(std::shared_ptr<const Context> context,
 
   27                                const RenderTarget& target,
 
   28                                std::shared_ptr<ReactorGLES> reactor)
 
   29     : RenderPass(
std::move(context), target),
 
   30       reactor_(
std::move(reactor)),
 
   31       is_valid_(reactor_ && reactor_->IsValid()) {}
 
   34 RenderPassGLES::~RenderPassGLES() = 
default;
 
   37 bool RenderPassGLES::IsValid()
 const {
 
   42 void RenderPassGLES::OnSetLabel(std::string_view label) {
 
   56     gl.BlendEquationSeparate(
 
   67       return (mask & check) ? GL_TRUE : GL_FALSE;
 
   71         is_set(color->
write_mask, ColorWriteMaskBits::kRed),    
 
   72         is_set(color->
write_mask, ColorWriteMaskBits::kGreen),  
 
   73         is_set(color->
write_mask, ColorWriteMaskBits::kBlue),   
 
   74         is_set(color->
write_mask, ColorWriteMaskBits::kAlpha)   
 
   82                       uint32_t stencil_reference) {
 
   89   gl.StencilFuncSeparate(face,                                        
 
   94   gl.StencilMaskSeparate(face, stencil.
write_mask);
 
   99                       uint32_t stencil_reference) {
 
  101     gl.Disable(GL_STENCIL_TEST);
 
  105   gl.Enable(GL_STENCIL_TEST);
 
  109   if (front.has_value() && back.has_value() && front == back) {
 
  113   if (front.has_value()) {
 
  116   if (back.has_value()) {
 
  129   uint32_t clear_stencil = 0u;
 
  137   bool clear_color_attachment = 
true;
 
  138   bool clear_depth_attachment = 
true;
 
  139   bool clear_stencil_attachment = 
true;
 
  141   bool discard_color_attachment = 
true;
 
  142   bool discard_depth_attachment = 
true;
 
  143   bool discard_stencil_attachment = 
true;
 
  151                              size_t buffer_index) {
 
  152   if (!vertex_buffer_view) {
 
  158   if (!vertex_buffer) {
 
  162   const auto& vertex_buffer_gles = DeviceBufferGLES::Cast(*vertex_buffer);
 
  163   if (!vertex_buffer_gles.BindAndUploadDataIfNecessary(
 
  164           DeviceBufferGLES::BindingType::kArrayBuffer)) {
 
  180   gl.Disable(GL_SCISSOR_TEST);
 
  181   gl.Disable(GL_DEPTH_TEST);
 
  182   gl.Disable(GL_STENCIL_TEST);
 
  183   gl.Disable(GL_CULL_FACE);
 
  184   gl.Disable(GL_BLEND);
 
  185   gl.Disable(GL_DITHER);
 
  186   gl.ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
 
  187   gl.DepthMask(GL_TRUE);
 
  188   gl.StencilMaskSeparate(GL_FRONT, 0xFFFFFFFF);
 
  189   gl.StencilMaskSeparate(GL_BACK, 0xFFFFFFFF);
 
  195     const std::vector<Command>& commands,
 
  196     const std::vector<BufferView>& vertex_buffers,
 
  197     const std::vector<TextureAndSampler>& bound_textures,
 
  198     const std::vector<BufferResource>& bound_buffers,
 
  199     const std::shared_ptr<GPUTracerGLES>& tracer) {
 
  200   TRACE_EVENT0(
"impeller", 
"RenderPassGLES::EncodeCommandsInReactor");
 
  203 #ifdef IMPELLER_DEBUG 
  204   tracer->MarkFrameStart(gl);
 
  206   fml::ScopedCleanupClosure pop_pass_debug_marker(
 
  207       [&gl]() { gl.PopDebugGroup(); });
 
  208   if (!pass_data.
label.empty()) {
 
  211     pop_pass_debug_marker.Release();
 
  216   const bool is_default_fbo = color_gles.
IsWrapped();
 
  218   std::optional<GLuint> fbo = 0;
 
  219   if (is_default_fbo) {
 
  220     if (color_gles.
GetFBO().has_value()) {
 
  222       gl.BindFramebuffer(GL_FRAMEBUFFER, *color_gles.
GetFBO());
 
  228       if (!fbo.has_value()) {
 
  231       gl.BindFramebuffer(GL_FRAMEBUFFER, fbo.value());
 
  237       if (!fbo.has_value()) {
 
  240       gl.BindFramebuffer(GL_FRAMEBUFFER, fbo.value());
 
  243               GL_FRAMEBUFFER, TextureGLES::AttachmentType::kColor0)) {
 
  248         if (!depth->SetAsFramebufferAttachment(
 
  249                 GL_FRAMEBUFFER, TextureGLES::AttachmentType::kDepth)) {
 
  255         if (!stencil->SetAsFramebufferAttachment(
 
  256                 GL_FRAMEBUFFER, TextureGLES::AttachmentType::kStencil)) {
 
  261       auto status = gl.CheckFramebufferStatus(GL_FRAMEBUFFER);
 
  262       if (status != GL_FRAMEBUFFER_COMPLETE) {
 
  276     if (gl.DepthRangef.IsAvailable()) {
 
  286   GLenum clear_bits = 0u;
 
  288     clear_bits |= GL_COLOR_BUFFER_BIT;
 
  291     clear_bits |= GL_DEPTH_BUFFER_BIT;
 
  294     clear_bits |= GL_STENCIL_BUFFER_BIT;
 
  297   RenderPassGLES::ResetGLState(gl);
 
  299   gl.Clear(clear_bits);
 
  309   const auto& viewport = pass_data.
viewport;
 
  310   gl.Viewport(viewport.rect.GetX(),  
 
  311               target_size.
height - viewport.rect.GetY() -
 
  312                   viewport.rect.GetHeight(),  
 
  313               viewport.rect.GetWidth(),       
 
  314               viewport.rect.GetHeight()       
 
  317     if (gl.DepthRangef.IsAvailable()) {
 
  318       gl.DepthRangef(viewport.depth_range.z_near, viewport.depth_range.z_far);
 
  320       gl.DepthRange(viewport.depth_range.z_near, viewport.depth_range.z_far);
 
  324   CullMode current_cull_mode = CullMode::kNone;
 
  325   WindingOrder current_winding_order = WindingOrder::kClockwise;
 
  328   for (
const auto& command : commands) {
 
  329 #ifdef IMPELLER_DEBUG 
  330     fml::ScopedCleanupClosure pop_cmd_debug_marker(
 
  331         [&gl]() { gl.PopDebugGroup(); });
 
  332     if (!command.label.empty()) {
 
  333       gl.PushDebugGroup(command.label);
 
  335       pop_cmd_debug_marker.Release();
 
  339     const auto& pipeline = PipelineGLES::Cast(*command.pipeline);
 
  341     const auto* color_attachment =
 
  342         pipeline.GetDescriptor().GetLegacyCompatibleColorAttachment();
 
  343     if (!color_attachment) {
 
  345           << 
"Color attachment is too complicated for a legacy renderer.";
 
  363             pipeline.GetDescriptor().GetDepthStencilAttachmentDescriptor();
 
  365       gl.Enable(GL_DEPTH_TEST);
 
  367       gl.DepthMask(depth->depth_write_enabled ? GL_TRUE : GL_FALSE);
 
  369       gl.Disable(GL_DEPTH_TEST);
 
  375     if (command.viewport.has_value()) {
 
  376       gl.Viewport(viewport.rect.GetX(),  
 
  377                   target_size.
height - viewport.rect.GetY() -
 
  378                       viewport.rect.GetHeight(),  
 
  379                   viewport.rect.GetWidth(),       
 
  380                   viewport.rect.GetHeight()       
 
  383         if (gl.DepthRangef.IsAvailable()) {
 
  384           gl.DepthRangef(viewport.depth_range.z_near,
 
  385                          viewport.depth_range.z_far);
 
  387           gl.DepthRange(viewport.depth_range.z_near,
 
  388                         viewport.depth_range.z_far);
 
  396     if (command.scissor.has_value()) {
 
  397       const auto& scissor = command.scissor.value();
 
  398       gl.Enable(GL_SCISSOR_TEST);
 
  401           target_size.
height - scissor.GetY() - scissor.GetHeight(),  
 
  410     CullMode pipeline_cull_mode = pipeline.GetDescriptor().GetCullMode();
 
  411     if (current_cull_mode != pipeline_cull_mode) {
 
  412       switch (pipeline_cull_mode) {
 
  413         case CullMode::kNone:
 
  414           gl.Disable(GL_CULL_FACE);
 
  416         case CullMode::kFrontFace:
 
  417           gl.Enable(GL_CULL_FACE);
 
  418           gl.CullFace(GL_FRONT);
 
  420         case CullMode::kBackFace:
 
  421           gl.Enable(GL_CULL_FACE);
 
  422           gl.CullFace(GL_BACK);
 
  425       current_cull_mode = pipeline_cull_mode;
 
  432         pipeline.GetDescriptor().GetWindingOrder();
 
  433     if (current_winding_order != pipeline_winding_order) {
 
  434       switch (pipeline.GetDescriptor().GetWindingOrder()) {
 
  435         case WindingOrder::kClockwise:
 
  438         case WindingOrder::kCounterClockwise:
 
  439           gl.FrontFace(GL_CCW);
 
  442       current_winding_order = pipeline_winding_order;
 
  454     for (
size_t i = 0; i < command.vertex_buffers.length; i++) {
 
  456                             vertex_buffers[i + command.vertex_buffers.offset],
 
  465     if (!pipeline.BindProgram()) {
 
  476             command.bound_textures,  
 
  477             command.bound_buffers     
 
  491         pipeline.GetDescriptor().GetPolygonMode() == PolygonMode::kLine
 
  493             : 
ToMode(pipeline.GetDescriptor().GetPrimitiveType());
 
  498     if (command.index_type == IndexType::kNone) {
 
  499       gl.DrawArrays(mode, command.base_vertex, command.element_count);
 
  502       auto index_buffer_view = command.index_buffer;
 
  503       const DeviceBuffer* index_buffer = index_buffer_view.GetBuffer();
 
  504       const auto& index_buffer_gles = DeviceBufferGLES::Cast(*index_buffer);
 
  505       if (!index_buffer_gles.BindAndUploadDataIfNecessary(
 
  506               DeviceBufferGLES::BindingType::kElementArrayBuffer)) {
 
  509       gl.DrawElements(mode,                             
 
  510                       command.element_count,            
 
  512                       reinterpret_cast<const GLvoid*
>(
static_cast<GLsizei
>(
 
  513                           index_buffer_view.GetRange().offset))  
 
  526       !gl.GetCapabilities()->SupportsImplicitResolvingMSAA() &&
 
  532     gl.GenFramebuffers(1u, &resolve_fbo);
 
  533     gl.BindFramebuffer(GL_FRAMEBUFFER, resolve_fbo);
 
  536              .SetAsFramebufferAttachment(
 
  537                  GL_FRAMEBUFFER, TextureGLES::AttachmentType::kColor0)) {
 
  541     auto status = gl.CheckFramebufferStatus(GL_FRAMEBUFFER);
 
  542     if (gl.CheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) {
 
  549     gl.BindFramebuffer(GL_READ_FRAMEBUFFER, fbo.value());
 
  550     gl.BindFramebuffer(GL_DRAW_FRAMEBUFFER, resolve_fbo);
 
  552     RenderPassGLES::ResetGLState(gl);
 
  555     gl.BlitFramebuffer(0,
 
  566     gl.BindFramebuffer(GL_DRAW_FRAMEBUFFER, GL_NONE);
 
  567     gl.BindFramebuffer(GL_READ_FRAMEBUFFER, GL_NONE);
 
  568     gl.DeleteFramebuffers(1u, &resolve_fbo);
 
  570     gl.BindFramebuffer(GL_FRAMEBUFFER, fbo.value());
 
  573   if (gl.DiscardFramebufferEXT.IsAvailable()) {
 
  574     std::array<GLenum, 3> attachments;
 
  575     size_t attachment_count = 0;
 
  580     bool angle_safe = gl.GetCapabilities()->IsANGLE() ? !is_default_fbo : 
true;
 
  583       attachments[attachment_count++] =
 
  584           (is_default_fbo ? GL_COLOR_EXT : GL_COLOR_ATTACHMENT0);
 
  587       attachments[attachment_count++] =
 
  588           (is_default_fbo ? GL_DEPTH_EXT : GL_DEPTH_ATTACHMENT);
 
  592       attachments[attachment_count++] =
 
  593           (is_default_fbo ? GL_STENCIL_EXT : GL_STENCIL_ATTACHMENT);
 
  595     gl.DiscardFramebufferEXT(GL_FRAMEBUFFER,     
 
  601 #ifdef IMPELLER_DEBUG 
  602   if (is_default_fbo) {
 
  603     tracer->MarkFrameEnd(gl);
 
  611 bool RenderPassGLES::OnEncodeCommands(
const Context& context)
 const {
 
  615   const auto& render_target = GetRenderTarget();
 
  616   if (!render_target.HasColorAttachment(0u)) {
 
  619   const ColorAttachment& color0 = render_target.GetColorAttachment(0);
 
  620   const std::optional<DepthAttachment>& depth0 =
 
  621       render_target.GetDepthAttachment();
 
  622   const std::optional<StencilAttachment>& stencil0 =
 
  623       render_target.GetStencilAttachment();
 
  625   auto pass_data = std::make_shared<RenderPassData>();
 
  626   pass_data->label = label_;
 
  627   pass_data->viewport.rect = Rect::MakeSize(GetRenderTargetSize());
 
  632   pass_data->color_attachment = color0.texture;
 
  633   pass_data->resolve_attachment = color0.resolve_texture;
 
  634   pass_data->clear_color = color0.clear_color;
 
  636   pass_data->discard_color_attachment =
 
  644   if (color0.resolve_texture) {
 
  645     pass_data->discard_color_attachment =
 
  646         pass_data->discard_color_attachment &&
 
  647         !context.GetCapabilities()->SupportsImplicitResolvingMSAA();
 
  653   if (depth0.has_value()) {
 
  654     pass_data->depth_attachment = depth0->texture;
 
  655     pass_data->clear_depth = depth0->clear_depth;
 
  657     pass_data->discard_depth_attachment =
 
  664   if (stencil0.has_value()) {
 
  665     pass_data->stencil_attachment = stencil0->texture;
 
  666     pass_data->clear_stencil = stencil0->clear_stencil;
 
  667     pass_data->clear_stencil_attachment =
 
  669     pass_data->discard_stencil_attachment =
 
  673   return reactor_->AddOperation(
 
  674       [pass_data = std::move(pass_data), render_pass = shared_from_this(),
 
  676            ContextGLES::Cast(context).GetGPUTracer()](
const auto& reactor) {
 
  680             render_pass->commands_,              
 
  681             render_pass->vertex_buffers_,  
 
  682             render_pass->bound_textures_,  
 
  683             render_pass->bound_buffers_,    
 
  687             << 
"Must be able to encode GL commands without error.";
 
Sets up stage bindings for single draw call in the OpenGLES backend.
bool BindVertexAttributes(const ProcTableGLES &gl, size_t binding, size_t vertex_offset)
bool UnbindVertexAttributes(const ProcTableGLES &gl)
bool BindUniformData(const ProcTableGLES &gl, const std::vector< TextureAndSampler > &bound_textures, const std::vector< BufferResource > &bound_buffers, Range texture_range, Range buffer_range)
Represents a handle to an underlying OpenGL object. Unlike OpenGL object handles, these handles can b...
constexpr bool IsDead() const
Determines if the handle is dead.
std::optional< StencilAttachmentDescriptor > GetBackStencilAttachmentDescriptor() const
std::optional< StencilAttachmentDescriptor > GetFrontStencilAttachmentDescriptor() const
bool HasStencilAttachmentDescriptors() const
void PushDebugGroup(const std::string &string) const
The reactor attempts to make thread-safe usage of OpenGL ES easier to reason about.
std::optional< GLuint > GetGLHandle(const HandleGLES &handle) const
Returns the OpenGL handle for a reactor handle if one is available. This is typically only safe to ca...
HandleGLES CreateUntrackedHandle(HandleType type) const
Create a handle that is not managed by ReactorGLES.
const ProcTableGLES & GetProcTable() const
Get the OpenGL proc. table the reactor uses to manage handles.
const HandleGLES & GetCachedFBO() const
Retrieve the cached FBO object, or a dead handle if there is no object.
void SetCachedFBO(HandleGLES fbo)
bool SetAsFramebufferAttachment(GLenum target, AttachmentType attachment_type) const
std::optional< GLuint > GetFBO() const
constexpr bool CanClearAttachment(LoadAction action)
constexpr GLenum ToIndexType(IndexType type)
constexpr GLenum ToCompareFunction(CompareFunction func)
std::string DebugToFramebufferError(int status)
bool EncodeCommandsInReactor(const RenderPassData &pass_data, const ReactorGLES &reactor, const std::vector< Command > &commands, const std::vector< BufferView > &vertex_buffers, const std::vector< TextureAndSampler > &bound_textures, const std::vector< BufferResource > &bound_buffers, const std::shared_ptr< GPUTracerGLES > &tracer)
constexpr GLenum ToStencilOp(StencilOperation op)
constexpr GLenum ToMode(PrimitiveType primitive_type)
void ConfigureBlending(const ProcTableGLES &gl, const ColorAttachmentDescriptor *color)
void ConfigureStencil(const ProcTableGLES &gl, const PipelineDescriptor &pipeline, uint32_t stencil_reference)
static bool BindVertexBuffer(const ProcTableGLES &gl, BufferBindingsGLES *vertex_desc_gles, const BufferView &vertex_buffer_view, size_t buffer_index)
constexpr GLenum ToBlendFactor(BlendFactor factor)
constexpr GLenum ToBlendOperation(BlendOperation op)
constexpr bool CanDiscardAttachmentWhenDone(StoreAction action)
const DeviceBuffer * GetBuffer() const
Describe the color attachment that will be used with this pipeline.
BlendOperation color_blend_op
BlendFactor dst_color_blend_factor
ColorWriteMask write_mask
BlendFactor src_alpha_blend_factor
BlendOperation alpha_blend_op
BlendFactor src_color_blend_factor
BlendFactor dst_alpha_blend_factor
Encapsulates data that will be needed in the reactor for the encoding of commands for this render pas...
bool clear_color_attachment
std::shared_ptr< Texture > depth_attachment
bool discard_color_attachment
bool clear_stencil_attachment
std::shared_ptr< Texture > color_attachment
bool discard_depth_attachment
std::shared_ptr< Texture > stencil_attachment
bool discard_stencil_attachment
std::shared_ptr< Texture > resolve_attachment
bool clear_depth_attachment
StencilOperation stencil_failure
CompareFunction stencil_compare
StencilOperation depth_failure
StencilOperation depth_stencil_pass