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;
136 bool clear_color_attachment =
true;
137 bool clear_depth_attachment =
true;
138 bool clear_stencil_attachment =
true;
140 bool discard_color_attachment =
true;
141 bool discard_depth_attachment =
true;
142 bool discard_stencil_attachment =
true;
150 size_t buffer_index) {
151 if (!vertex_buffer_view) {
157 if (!vertex_buffer) {
161 const auto& vertex_buffer_gles = DeviceBufferGLES::Cast(*vertex_buffer);
162 if (!vertex_buffer_gles.BindAndUploadDataIfNecessary(
163 DeviceBufferGLES::BindingType::kArrayBuffer)) {
179 gl.Disable(GL_SCISSOR_TEST);
180 gl.Disable(GL_DEPTH_TEST);
181 gl.Disable(GL_STENCIL_TEST);
182 gl.Disable(GL_CULL_FACE);
183 gl.Disable(GL_BLEND);
184 gl.Disable(GL_DITHER);
185 gl.ColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
186 gl.DepthMask(GL_TRUE);
187 gl.StencilMaskSeparate(GL_FRONT, 0xFFFFFFFF);
188 gl.StencilMaskSeparate(GL_BACK, 0xFFFFFFFF);
194 const std::vector<Command>& commands,
195 const std::vector<BufferView>& vertex_buffers,
196 const std::vector<TextureAndSampler>& bound_textures,
197 const std::vector<BufferResource>& bound_buffers,
198 const std::shared_ptr<GPUTracerGLES>& tracer) {
199 TRACE_EVENT0(
"impeller",
"RenderPassGLES::EncodeCommandsInReactor");
202 #ifdef IMPELLER_DEBUG
203 tracer->MarkFrameStart(gl);
205 fml::ScopedCleanupClosure pop_pass_debug_marker(
206 [&gl]() { gl.PopDebugGroup(); });
207 if (!pass_data.
label.empty()) {
210 pop_pass_debug_marker.Release();
214 GLuint fbo = GL_NONE;
216 const bool is_default_fbo = color_gles.
IsWrapped();
218 if (is_default_fbo) {
219 if (color_gles.
GetFBO().has_value()) {
221 gl.BindFramebuffer(GL_FRAMEBUFFER, *color_gles.
GetFBO());
226 if (cached_fbo != GL_NONE) {
228 gl.BindFramebuffer(GL_FRAMEBUFFER, fbo);
230 gl.GenFramebuffers(1u, &fbo);
232 gl.BindFramebuffer(GL_FRAMEBUFFER, fbo);
235 GL_FRAMEBUFFER, TextureGLES::AttachmentType::kColor0)) {
240 if (!depth->SetAsFramebufferAttachment(
241 GL_FRAMEBUFFER, TextureGLES::AttachmentType::kDepth)) {
247 if (!stencil->SetAsFramebufferAttachment(
248 GL_FRAMEBUFFER, TextureGLES::AttachmentType::kStencil)) {
253 auto status = gl.CheckFramebufferStatus(GL_FRAMEBUFFER);
254 if (status != GL_FRAMEBUFFER_COMPLETE) {
268 if (gl.DepthRangef.IsAvailable()) {
278 GLenum clear_bits = 0u;
280 clear_bits |= GL_COLOR_BUFFER_BIT;
283 clear_bits |= GL_DEPTH_BUFFER_BIT;
286 clear_bits |= GL_STENCIL_BUFFER_BIT;
289 RenderPassGLES::ResetGLState(gl);
291 gl.Clear(clear_bits);
301 const auto& viewport = pass_data.
viewport;
302 gl.Viewport(viewport.rect.GetX(),
303 target_size.
height - viewport.rect.GetY() -
304 viewport.rect.GetHeight(),
305 viewport.rect.GetWidth(),
306 viewport.rect.GetHeight()
309 if (gl.DepthRangef.IsAvailable()) {
310 gl.DepthRangef(viewport.depth_range.z_near, viewport.depth_range.z_far);
312 gl.DepthRange(viewport.depth_range.z_near, viewport.depth_range.z_far);
316 CullMode current_cull_mode = CullMode::kNone;
317 WindingOrder current_winding_order = WindingOrder::kClockwise;
320 for (
const auto& command : commands) {
321 #ifdef IMPELLER_DEBUG
322 fml::ScopedCleanupClosure pop_cmd_debug_marker(
323 [&gl]() { gl.PopDebugGroup(); });
324 if (!command.label.empty()) {
325 gl.PushDebugGroup(command.label);
327 pop_cmd_debug_marker.Release();
331 const auto& pipeline = PipelineGLES::Cast(*command.pipeline);
333 const auto* color_attachment =
334 pipeline.GetDescriptor().GetLegacyCompatibleColorAttachment();
335 if (!color_attachment) {
337 <<
"Color attachment is too complicated for a legacy renderer.";
355 pipeline.GetDescriptor().GetDepthStencilAttachmentDescriptor();
357 gl.Enable(GL_DEPTH_TEST);
359 gl.DepthMask(depth->depth_write_enabled ? GL_TRUE : GL_FALSE);
361 gl.Disable(GL_DEPTH_TEST);
367 if (command.viewport.has_value()) {
368 gl.Viewport(viewport.rect.GetX(),
369 target_size.
height - viewport.rect.GetY() -
370 viewport.rect.GetHeight(),
371 viewport.rect.GetWidth(),
372 viewport.rect.GetHeight()
375 if (gl.DepthRangef.IsAvailable()) {
376 gl.DepthRangef(viewport.depth_range.z_near,
377 viewport.depth_range.z_far);
379 gl.DepthRange(viewport.depth_range.z_near,
380 viewport.depth_range.z_far);
388 if (command.scissor.has_value()) {
389 const auto& scissor = command.scissor.value();
390 gl.Enable(GL_SCISSOR_TEST);
393 target_size.
height - scissor.GetY() - scissor.GetHeight(),
402 CullMode pipeline_cull_mode = pipeline.GetDescriptor().GetCullMode();
403 if (current_cull_mode != pipeline_cull_mode) {
404 switch (pipeline_cull_mode) {
405 case CullMode::kNone:
406 gl.Disable(GL_CULL_FACE);
408 case CullMode::kFrontFace:
409 gl.Enable(GL_CULL_FACE);
410 gl.CullFace(GL_FRONT);
412 case CullMode::kBackFace:
413 gl.Enable(GL_CULL_FACE);
414 gl.CullFace(GL_BACK);
417 current_cull_mode = pipeline_cull_mode;
424 pipeline.GetDescriptor().GetWindingOrder();
425 if (current_winding_order != pipeline_winding_order) {
426 switch (pipeline.GetDescriptor().GetWindingOrder()) {
427 case WindingOrder::kClockwise:
430 case WindingOrder::kCounterClockwise:
431 gl.FrontFace(GL_CCW);
434 current_winding_order = pipeline_winding_order;
446 for (
size_t i = 0; i < command.vertex_buffers.length; i++) {
448 vertex_buffers[i + command.vertex_buffers.offset],
457 if (!pipeline.BindProgram()) {
468 command.bound_textures,
469 command.bound_buffers
483 pipeline.GetDescriptor().GetPolygonMode() == PolygonMode::kLine
485 :
ToMode(pipeline.GetDescriptor().GetPrimitiveType());
490 if (command.index_type == IndexType::kNone) {
491 gl.DrawArrays(mode, command.base_vertex, command.element_count);
494 auto index_buffer_view = command.index_buffer;
495 const DeviceBuffer* index_buffer = index_buffer_view.GetBuffer();
496 const auto& index_buffer_gles = DeviceBufferGLES::Cast(*index_buffer);
497 if (!index_buffer_gles.BindAndUploadDataIfNecessary(
498 DeviceBufferGLES::BindingType::kElementArrayBuffer)) {
501 gl.DrawElements(mode,
502 command.element_count,
504 reinterpret_cast<const GLvoid*
>(
static_cast<GLsizei
>(
505 index_buffer_view.GetRange().offset))
517 if (gl.DiscardFramebufferEXT.IsAvailable()) {
518 std::array<GLenum, 3> attachments;
519 size_t attachment_count = 0;
524 bool angle_safe = gl.GetCapabilities()->IsANGLE() ? !is_default_fbo :
true;
527 attachments[attachment_count++] =
528 (is_default_fbo ? GL_COLOR_EXT : GL_COLOR_ATTACHMENT0);
531 attachments[attachment_count++] =
532 (is_default_fbo ? GL_DEPTH_EXT : GL_DEPTH_ATTACHMENT);
536 attachments[attachment_count++] =
537 (is_default_fbo ? GL_STENCIL_EXT : GL_STENCIL_ATTACHMENT);
539 gl.DiscardFramebufferEXT(GL_FRAMEBUFFER,
545 #ifdef IMPELLER_DEBUG
546 if (is_default_fbo) {
547 tracer->MarkFrameEnd(gl);
555 bool RenderPassGLES::OnEncodeCommands(
const Context& context)
const {
559 const auto& render_target = GetRenderTarget();
560 if (!render_target.HasColorAttachment(0u)) {
563 const ColorAttachment& color0 = render_target.GetColorAttachment(0);
564 const std::optional<DepthAttachment>& depth0 =
565 render_target.GetDepthAttachment();
566 const std::optional<StencilAttachment>& stencil0 =
567 render_target.GetStencilAttachment();
569 auto pass_data = std::make_shared<RenderPassData>();
570 pass_data->label = label_;
571 pass_data->viewport.rect = Rect::MakeSize(GetRenderTargetSize());
576 pass_data->color_attachment = color0.texture;
577 pass_data->clear_color = color0.clear_color;
579 pass_data->discard_color_attachment =
585 if (color0.resolve_texture) {
586 FML_DCHECK(context.GetCapabilities()->SupportsImplicitResolvingMSAA());
587 pass_data->discard_color_attachment =
false;
593 if (depth0.has_value()) {
594 pass_data->depth_attachment = depth0->texture;
595 pass_data->clear_depth = depth0->clear_depth;
597 pass_data->discard_depth_attachment =
604 if (stencil0.has_value()) {
605 pass_data->stencil_attachment = stencil0->texture;
606 pass_data->clear_stencil = stencil0->clear_stencil;
607 pass_data->clear_stencil_attachment =
609 pass_data->discard_stencil_attachment =
613 return reactor_->AddOperation(
614 [pass_data = std::move(pass_data), render_pass = shared_from_this(),
616 ContextGLES::Cast(context).GetGPUTracer()](
const auto& reactor) {
620 render_pass->commands_,
621 render_pass->vertex_buffers_,
622 render_pass->bound_textures_,
623 render_pass->bound_buffers_,
627 <<
"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)
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.
const ProcTableGLES & GetProcTable() const
Get the OpenGL proc. table the reactor uses to manage handles.
void SetCachedFBO(GLuint fbo)
GLuint GetCachedFBO() const
Retrieve the cached FBO object, or GL_NONE if there is no object.
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
bool clear_depth_attachment
StencilOperation stencil_failure
CompareFunction stencil_compare
StencilOperation depth_failure
StencilOperation depth_stencil_pass