From 2d811593db68c7c9136577976012c7363b99828d Mon Sep 17 00:00:00 2001 From: Jonah Williams Date: Fri, 20 Dec 2024 11:44:19 -0800 Subject: [PATCH] [Impeller] Fix GLES SurfaceTexture rendering. (#160634) Fixes https://github.com/flutter/flutter/issues/160480 Both The Impeller and Skia variant of the OES texture rendering use the same shared code path, so the Impeller code must match the weird 1x1 texture behavior of Skia. In addition, we have to add back the TiledTextureContents support, since we need to render a texture with a transform. I had previously tested this but neglected to force the SurfaceTexture path, so I only tested the ImageReader path which does not use a transform. --- .../entity/contents/color_source_contents.h | 2 - .../entity/contents/content_context.cc | 1 + .../entity/contents/content_context.h | 12 ++++++ .../entity/contents/tiled_texture_contents.cc | 40 +++++++++++++++++++ .../impeller/entity/shaders/texture_fill.vert | 2 +- .../entity/shaders/texture_uv_fill.vert | 2 +- .../entity/shaders/tiled_texture_fill.frag | 2 +- engine/src/flutter/impeller/tools/malioc.json | 16 ++++---- .../surface_texture_external_texture.cc | 5 --- ...ce_texture_external_texture_gl_impeller.cc | 3 +- 10 files changed, 65 insertions(+), 20 deletions(-) diff --git a/engine/src/flutter/impeller/entity/contents/color_source_contents.h b/engine/src/flutter/impeller/entity/contents/color_source_contents.h index 17eba81f89..b988ff4ee0 100644 --- a/engine/src/flutter/impeller/entity/contents/color_source_contents.h +++ b/engine/src/flutter/impeller/entity/contents/color_source_contents.h @@ -101,8 +101,6 @@ class ColorSourceContents : public Contents { protected: using BindFragmentCallback = std::function; - using PipelineBuilderMethod = std::shared_ptr> ( - impeller::ContentContext::*)(ContentContextOptions) const; using PipelineBuilderCallback = std::function; using CreateGeometryCallback = diff --git a/engine/src/flutter/impeller/entity/contents/content_context.cc b/engine/src/flutter/impeller/entity/contents/content_context.cc index 0389344a7e..149c544a89 100644 --- a/engine/src/flutter/impeller/entity/contents/content_context.cc +++ b/engine/src/flutter/impeller/entity/contents/content_context.cc @@ -464,6 +464,7 @@ ContentContext::ContentContext( #if !defined(FML_OS_MACOSX) // GLES only shader that is unsupported on macOS. tiled_texture_external_pipelines_.CreateDefault(*context_, options); + tiled_texture_uv_external_pipelines_.CreateDefault(*context_, options); #endif // !defined(FML_OS_MACOSX) texture_downsample_gles_pipelines_.CreateDefault(*context_, options_trianglestrip); diff --git a/engine/src/flutter/impeller/entity/contents/content_context.h b/engine/src/flutter/impeller/entity/contents/content_context.h index 0a0aee3626..8a0ed4ec8a 100644 --- a/engine/src/flutter/impeller/entity/contents/content_context.h +++ b/engine/src/flutter/impeller/entity/contents/content_context.h @@ -257,6 +257,9 @@ using VerticesUberShader = RenderPipelineHandle; +using TiledTextureUvExternalPipeline = + RenderPipelineHandle; using TextureDownsampleGlesPipeline = RenderPipelineHandle; @@ -469,6 +472,13 @@ class ContentContext { Context::BackendType::kOpenGLES); return GetPipeline(tiled_texture_external_pipelines_, opts); } + + PipelineRef GetTiledTextureUvExternalPipeline( + ContentContextOptions opts) const { + FML_DCHECK(GetContext()->GetBackendType() == + Context::BackendType::kOpenGLES); + return GetPipeline(tiled_texture_uv_external_pipelines_, opts); + } #endif // IMPELLER_ENABLE_OPENGLES PipelineRef GetTiledTexturePipeline(ContentContextOptions opts) const { @@ -892,6 +902,8 @@ class ContentContext { tiled_texture_external_pipelines_; mutable Variants texture_downsample_gles_pipelines_; + mutable Variants + tiled_texture_uv_external_pipelines_; #endif // IMPELLER_ENABLE_OPENGLES mutable Variants tiled_texture_pipelines_; mutable Variants gaussian_blur_pipelines_; diff --git a/engine/src/flutter/impeller/entity/contents/tiled_texture_contents.cc b/engine/src/flutter/impeller/entity/contents/tiled_texture_contents.cc index e7b9e946de..a75fd57cf2 100644 --- a/engine/src/flutter/impeller/entity/contents/tiled_texture_contents.cc +++ b/engine/src/flutter/impeller/entity/contents/tiled_texture_contents.cc @@ -128,6 +128,46 @@ bool TiledTextureContents::Render(const ContentContext& renderer, Rect::MakeSize(texture_size).GetNormalizingTransform() * GetInverseEffectTransform(); +#ifdef IMPELLER_ENABLE_OPENGLES + using FSExternal = TiledTextureFillExternalFragmentShader; + if (texture_->GetTextureDescriptor().type == + TextureType::kTextureExternalOES) { + return ColorSourceContents::DrawGeometry( + renderer, entity, pass, + [&renderer](ContentContextOptions options) { + return renderer.GetTiledTextureUvExternalPipeline(options); + }, + frame_info, + [this, &renderer](RenderPass& pass) { + auto& host_buffer = renderer.GetTransientsBuffer(); +#ifdef IMPELLER_DEBUG + pass.SetCommandLabel("TextureFill External"); +#endif // IMPELLER_DEBUG + + FML_DCHECK(!color_filter_); + FSExternal::FragInfo frag_info; + frag_info.x_tile_mode = + static_cast(sampler_descriptor_.width_address_mode); + frag_info.y_tile_mode = + static_cast(sampler_descriptor_.height_address_mode); + frag_info.alpha = GetOpacityFactor(); + FSExternal::BindFragInfo(pass, host_buffer.EmplaceUniform(frag_info)); + + SamplerDescriptor sampler_desc; + // OES_EGL_image_external states that only CLAMP_TO_EDGE is valid, + // so we emulate all other tile modes here by remapping the texture + // coordinates. + sampler_desc.width_address_mode = SamplerAddressMode::kClampToEdge; + sampler_desc.height_address_mode = SamplerAddressMode::kClampToEdge; + FSExternal::BindSAMPLEREXTERNALOESTextureSampler( + pass, texture_, + renderer.GetContext()->GetSamplerLibrary()->GetSampler( + sampler_desc)); + return true; + }); + } +#endif // IMPELLER_ENABLE_OPENGLES + PipelineBuilderCallback pipeline_callback = [&renderer](ContentContextOptions options) { return renderer.GetTiledTexturePipeline(options); diff --git a/engine/src/flutter/impeller/entity/shaders/texture_fill.vert b/engine/src/flutter/impeller/entity/shaders/texture_fill.vert index 0dbc6fd4bf..49338765bd 100644 --- a/engine/src/flutter/impeller/entity/shaders/texture_fill.vert +++ b/engine/src/flutter/impeller/entity/shaders/texture_fill.vert @@ -14,7 +14,7 @@ frame_info; in vec2 position; in vec2 texture_coords; -out vec2 v_texture_coords; +out highp vec2 v_texture_coords; void main() { gl_Position = frame_info.mvp * vec4(position, 0.0, 1.0); diff --git a/engine/src/flutter/impeller/entity/shaders/texture_uv_fill.vert b/engine/src/flutter/impeller/entity/shaders/texture_uv_fill.vert index 786aedd042..cd07abfdae 100644 --- a/engine/src/flutter/impeller/entity/shaders/texture_uv_fill.vert +++ b/engine/src/flutter/impeller/entity/shaders/texture_uv_fill.vert @@ -16,7 +16,7 @@ frame_info; in vec2 position; -out mediump vec2 v_texture_coords; +out highp vec2 v_texture_coords; void main() { gl_Position = frame_info.mvp * vec4(position, 0.0, 1.0); diff --git a/engine/src/flutter/impeller/entity/shaders/tiled_texture_fill.frag b/engine/src/flutter/impeller/entity/shaders/tiled_texture_fill.frag index 8061712591..25b2af3526 100644 --- a/engine/src/flutter/impeller/entity/shaders/tiled_texture_fill.frag +++ b/engine/src/flutter/impeller/entity/shaders/tiled_texture_fill.frag @@ -18,7 +18,7 @@ uniform FragInfo { } frag_info; -in mediump vec2 v_texture_coords; +in highp vec2 v_texture_coords; out f16vec4 frag_color; diff --git a/engine/src/flutter/impeller/tools/malioc.json b/engine/src/flutter/impeller/tools/malioc.json index 33951a5029..3e75278656 100644 --- a/engine/src/flutter/impeller/tools/malioc.json +++ b/engine/src/flutter/impeller/tools/malioc.json @@ -5969,7 +5969,7 @@ "longest_path_cycles": [ 0.078125, 0.078125, - 0.078125, + 0.015625, 0.0, 3.0, 0.0 @@ -5988,7 +5988,7 @@ "shortest_path_cycles": [ 0.078125, 0.078125, - 0.078125, + 0.015625, 0.0, 3.0, 0.0 @@ -5999,7 +5999,7 @@ "total_cycles": [ 0.078125, 0.078125, - 0.078125, + 0.015625, 0.0, 3.0, 0.0 @@ -6008,7 +6008,7 @@ "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 16, - "work_registers_used": 8 + "work_registers_used": 9 } } }, @@ -8771,7 +8771,7 @@ "longest_path_cycles": [ 0.078125, 0.078125, - 0.078125, + 0.015625, 0.0, 3.0, 0.0 @@ -8790,7 +8790,7 @@ "shortest_path_cycles": [ 0.078125, 0.078125, - 0.078125, + 0.015625, 0.0, 3.0, 0.0 @@ -8801,7 +8801,7 @@ "total_cycles": [ 0.078125, 0.078125, - 0.078125, + 0.015625, 0.0, 3.0, 0.0 @@ -8810,7 +8810,7 @@ "stack_spill_bytes": 0, "thread_occupancy": 100, "uniform_registers_used": 32, - "work_registers_used": 8 + "work_registers_used": 9 } } } diff --git a/engine/src/flutter/shell/platform/android/surface_texture_external_texture.cc b/engine/src/flutter/shell/platform/android/surface_texture_external_texture.cc index ed019b9101..9843937a03 100644 --- a/engine/src/flutter/shell/platform/android/surface_texture_external_texture.cc +++ b/engine/src/flutter/shell/platform/android/surface_texture_external_texture.cc @@ -13,11 +13,6 @@ #include "third_party/skia/include/core/SkColorSpace.h" #include "third_party/skia/include/core/SkColorType.h" #include "third_party/skia/include/core/SkImage.h" -#include "third_party/skia/include/gpu/ganesh/GrBackendSurface.h" -#include "third_party/skia/include/gpu/ganesh/GrDirectContext.h" -#include "third_party/skia/include/gpu/ganesh/SkImageGanesh.h" -#include "third_party/skia/include/gpu/ganesh/gl/GrGLBackendSurface.h" -#include "third_party/skia/include/gpu/ganesh/gl/GrGLTypes.h" namespace flutter { diff --git a/engine/src/flutter/shell/platform/android/surface_texture_external_texture_gl_impeller.cc b/engine/src/flutter/shell/platform/android/surface_texture_external_texture_gl_impeller.cc index 69f4b5e2c6..94eda0f6a2 100644 --- a/engine/src/flutter/shell/platform/android/surface_texture_external_texture_gl_impeller.cc +++ b/engine/src/flutter/shell/platform/android/surface_texture_external_texture_gl_impeller.cc @@ -29,8 +29,7 @@ void SurfaceTextureExternalTextureGLImpeller::ProcessFrame( desc.type = impeller::TextureType::kTextureExternalOES; desc.storage_mode = impeller::StorageMode::kDevicePrivate; desc.format = impeller::PixelFormat::kR8G8B8A8UNormInt; - desc.size = {static_cast(bounds.width()), - static_cast(bounds.height())}; + desc.size = {1, 1}; desc.mip_count = 1; texture_ = std::make_shared( impeller_context_->GetReactor(), desc);