From 5281fab824ff7a4555fa0472f43f5916fa42207a Mon Sep 17 00:00:00 2001 From: ColdPaleLight Date: Tue, 9 Aug 2022 21:01:51 +0800 Subject: [PATCH 1/4] [Impeller] Implement tiled texture contents for image shader --- ci/licenses_golden/licenses_flutter | 4 + impeller/aiks/aiks_unittests.cc | 32 +++++ .../compiler/shader_lib/impeller/texture.glsl | 26 +++- .../display_list/display_list_dispatcher.cc | 98 ++++++++------ impeller/entity/BUILD.gn | 4 + impeller/entity/contents/content_context.cc | 2 + impeller/entity/contents/content_context.h | 10 ++ .../entity/contents/tiled_texture_contents.cc | 120 ++++++++++++++++++ .../entity/contents/tiled_texture_contents.h | 55 ++++++++ .../entity/shaders/tiled_texture_fill.frag | 29 +++++ .../entity/shaders/tiled_texture_fill.vert | 18 +++ 11 files changed, 349 insertions(+), 49 deletions(-) create mode 100644 impeller/entity/contents/tiled_texture_contents.cc create mode 100644 impeller/entity/contents/tiled_texture_contents.h create mode 100644 impeller/entity/shaders/tiled_texture_fill.frag create mode 100644 impeller/entity/shaders/tiled_texture_fill.vert diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 9c2ebc77f49ca..f3f243a59e8c6 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -587,6 +587,8 @@ FILE: ../../../flutter/impeller/entity/contents/text_contents.cc FILE: ../../../flutter/impeller/entity/contents/text_contents.h FILE: ../../../flutter/impeller/entity/contents/texture_contents.cc FILE: ../../../flutter/impeller/entity/contents/texture_contents.h +FILE: ../../../flutter/impeller/entity/contents/tiled_texture_contents.cc +FILE: ../../../flutter/impeller/entity/contents/tiled_texture_contents.h FILE: ../../../flutter/impeller/entity/contents/vertices_contents.cc FILE: ../../../flutter/impeller/entity/contents/vertices_contents.h FILE: ../../../flutter/impeller/entity/entity.cc @@ -641,6 +643,8 @@ FILE: ../../../flutter/impeller/entity/shaders/sweep_gradient_fill.frag FILE: ../../../flutter/impeller/entity/shaders/sweep_gradient_fill.vert FILE: ../../../flutter/impeller/entity/shaders/texture_fill.frag FILE: ../../../flutter/impeller/entity/shaders/texture_fill.vert +FILE: ../../../flutter/impeller/entity/shaders/tiled_texture_fill.frag +FILE: ../../../flutter/impeller/entity/shaders/tiled_texture_fill.vert FILE: ../../../flutter/impeller/entity/shaders/vertices.frag FILE: ../../../flutter/impeller/entity/shaders/vertices.vert FILE: ../../../flutter/impeller/geometry/color.cc diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc index d4fbf8c6361aa..93e3ed5252da6 100644 --- a/impeller/aiks/aiks_unittests.cc +++ b/impeller/aiks/aiks_unittests.cc @@ -10,10 +10,14 @@ #include "impeller/aiks/aiks_playground.h" #include "impeller/aiks/canvas.h" #include "impeller/aiks/image.h" +#include "impeller/entity/contents/tiled_texture_contents.h" #include "impeller/geometry/color.h" #include "impeller/geometry/geometry_unittests.h" #include "impeller/geometry/path_builder.h" +#include "impeller/geometry/scalar.h" #include "impeller/playground/widgets.h" +#include "impeller/renderer/formats.h" +#include "impeller/renderer/sampler_descriptor.h" #include "impeller/renderer/snapshot.h" #include "impeller/typographer/backends/skia/text_frame_skia.h" #include "impeller/typographer/backends/skia/text_render_context_skia.h" @@ -70,6 +74,34 @@ TEST_P(AiksTest, CanRenderImage) { ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); } +TEST_P(AiksTest, CanRenderTiledImage) { + Canvas canvas; + Paint paint; + std::vector tile_modes = { + Entity::TileMode::kClamp, Entity::TileMode::kRepeat, + Entity::TileMode::kMirror, Entity::TileMode::kDecal}; + auto texture = CreateTextureForFixture("table_mountain_nx.png"); + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + Scalar offset_x = i * 400.0; + Scalar offset_y = j * 400.0; + canvas.Save(); + canvas.Translate({offset_x, offset_y, 0}); + auto contents = std::make_shared(); + contents->SetTexture(texture); + contents->SetTileModes(tile_modes[i], tile_modes[j]); + SamplerDescriptor desc; + desc.width_address_mode = SamplerAddressMode::kMirror; + desc.height_address_mode = SamplerAddressMode::kRepeat; + contents->SetSamplerDescriptor(desc); + paint.contents = contents; + canvas.DrawRect({0, 0, 300, 300}, paint); + canvas.Restore(); + } + } + ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); +} + TEST_P(AiksTest, CanRenderImageRect) { Canvas canvas; Paint paint; diff --git a/impeller/compiler/shader_lib/impeller/texture.glsl b/impeller/compiler/shader_lib/impeller/texture.glsl index 714e92ca81445..633af1cd2819a 100644 --- a/impeller/compiler/shader_lib/impeller/texture.glsl +++ b/impeller/compiler/shader_lib/impeller/texture.glsl @@ -48,9 +48,9 @@ float IPFloatTile(float t, float tile_mode) { /// Remap a vec2 using a tiling mode. /// /// Runs each component of the vec2 through `IPFloatTile`. -vec2 IPVec2Tile(vec2 coords, float tile_mode) { - return vec2(IPFloatTile(coords.x, tile_mode), - IPFloatTile(coords.y, tile_mode)); +vec2 IPVec2Tile(vec2 coords, float x_tile_mode, float y_tile_mode) { + return vec2(IPFloatTile(coords.x, x_tile_mode), + IPFloatTile(coords.y, y_tile_mode)); } /// Sample a texture, emulating a specific tile mode. @@ -60,13 +60,25 @@ vec2 IPVec2Tile(vec2 coords, float tile_mode) { vec4 IPSampleWithTileMode(sampler2D tex, vec2 coords, float y_coord_scale, - float tile_mode) { - if (tile_mode == kTileModeDecal && - (coords.x < 0 || coords.y < 0 || coords.x >= 1 || coords.y >= 1)) { + float x_tile_mode, + float y_tile_mode) { + if (x_tile_mode == kTileModeDecal && (coords.x < 0 || coords.x >= 1) || + y_tile_mode == kTileModeDecal && (coords.y < 0 || coords.y >= 1)) { return vec4(0); } - return IPSample(tex, IPVec2Tile(coords, tile_mode), y_coord_scale); + return IPSample(tex, IPVec2Tile(coords, x_tile_mode, y_tile_mode), y_coord_scale); +} + +/// Sample a texture, emulating a specific tile mode. +/// +/// This is useful for Impeller graphics backend that don't have native support +/// for Decal. +vec4 IPSampleWithTileMode(sampler2D tex, + vec2 coords, + float y_coord_scale, + float tile_mode) { + return IPSampleWithTileMode(tex, coords, y_coord_scale, tile_mode, tile_mode); } #endif diff --git a/impeller/display_list/display_list_dispatcher.cc b/impeller/display_list/display_list_dispatcher.cc index a0678a2e8aa42..8fb7f0643c249 100644 --- a/impeller/display_list/display_list_dispatcher.cc +++ b/impeller/display_list/display_list_dispatcher.cc @@ -19,6 +19,7 @@ #include "impeller/entity/contents/radial_gradient_contents.h" #include "impeller/entity/contents/solid_stroke_contents.h" #include "impeller/entity/contents/sweep_gradient_contents.h" +#include "impeller/entity/contents/tiled_texture_contents.h" #include "impeller/entity/entity.h" #include "impeller/geometry/path.h" #include "impeller/geometry/path_builder.h" @@ -116,6 +117,47 @@ static Entity::TileMode ToTileMode(flutter::DlTileMode tile_mode) { } } +static impeller::SamplerDescriptor ToSamplerDescriptor( + const flutter::DlImageSampling options) { + impeller::SamplerDescriptor desc; + switch (options) { + case flutter::DlImageSampling::kNearestNeighbor: + desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kNearest; + desc.label = "Nearest Sampler"; + break; + case flutter::DlImageSampling::kLinear: + desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kLinear; + desc.label = "Linear Sampler"; + break; + case flutter::DlImageSampling::kMipmapLinear: + desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kLinear; + desc.mip_filter = impeller::MipFilter::kLinear; + desc.label = "Mipmap Linear Sampler"; + break; + default: + break; + } + return desc; +} + +static impeller::SamplerDescriptor ToSamplerDescriptor( + const flutter::DlFilterMode options) { + impeller::SamplerDescriptor desc; + switch (options) { + case flutter::DlFilterMode::kNearest: + desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kNearest; + desc.label = "Nearest Sampler"; + break; + case flutter::DlFilterMode::kLinear: + desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kLinear; + desc.label = "Linear Sampler"; + break; + default: + break; + } + return desc; +} + // |flutter::Dispatcher| void DisplayListDispatcher::setAntiAlias(bool aa) { // Nothing to do because AA is implicit. @@ -298,7 +340,20 @@ void DisplayListDispatcher::setColorSource( paint_.contents = std::move(contents); return; } - case flutter::DlColorSourceType::kImage: + case flutter::DlColorSourceType::kImage: { + const flutter::DlImageColorSource* image_color_source = source->asImage(); + FML_DCHECK(image_color_source && + image_color_source->image()->impeller_texture()); + auto contents = std::make_shared(); + contents->SetTexture(image_color_source->image()->impeller_texture()); + contents->SetTileModes( + ToTileMode(image_color_source->horizontal_tile_mode()), + ToTileMode(image_color_source->vertical_tile_mode())); + contents->SetSamplerDescriptor( + ToSamplerDescriptor(image_color_source->sampling())); + paint_.contents = std::move(contents); + return; + } case flutter::DlColorSourceType::kConicalGradient: case flutter::DlColorSourceType::kUnknown: UNIMPLEMENTED; @@ -874,47 +929,6 @@ void DisplayListDispatcher::drawImage(const sk_sp image, ); } -static impeller::SamplerDescriptor ToSamplerDescriptor( - const flutter::DlImageSampling options) { - impeller::SamplerDescriptor desc; - switch (options) { - case flutter::DlImageSampling::kNearestNeighbor: - desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kNearest; - desc.label = "Nearest Sampler"; - break; - case flutter::DlImageSampling::kLinear: - desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kLinear; - desc.label = "Linear Sampler"; - break; - case flutter::DlImageSampling::kMipmapLinear: - desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kLinear; - desc.mip_filter = impeller::MipFilter::kLinear; - desc.label = "Mipmap Linear Sampler"; - break; - default: - break; - } - return desc; -} - -static impeller::SamplerDescriptor ToSamplerDescriptor( - const flutter::DlFilterMode options) { - impeller::SamplerDescriptor desc; - switch (options) { - case flutter::DlFilterMode::kNearest: - desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kNearest; - desc.label = "Nearest Sampler"; - break; - case flutter::DlFilterMode::kLinear: - desc.min_filter = desc.mag_filter = impeller::MinMagFilter::kLinear; - desc.label = "Linear Sampler"; - break; - default: - break; - } - return desc; -} - // |flutter::Dispatcher| void DisplayListDispatcher::drawImageRect( const sk_sp image, diff --git a/impeller/entity/BUILD.gn b/impeller/entity/BUILD.gn index 014d11484b232..522fefa427bc1 100644 --- a/impeller/entity/BUILD.gn +++ b/impeller/entity/BUILD.gn @@ -48,6 +48,8 @@ impeller_shaders("entity_shaders") { "shaders/sweep_gradient_fill.vert", "shaders/texture_fill.frag", "shaders/texture_fill.vert", + "shaders/tiled_texture_fill.frag", + "shaders/tiled_texture_fill.vert", "shaders/vertices.frag", "shaders/vertices.vert", ] @@ -97,6 +99,8 @@ impeller_component("entity") { "contents/text_contents.h", "contents/texture_contents.cc", "contents/texture_contents.h", + "contents/tiled_texture_contents.cc", + "contents/tiled_texture_contents.h", "contents/vertices_contents.cc", "contents/vertices_contents.h", "entity.cc", diff --git a/impeller/entity/contents/content_context.cc b/impeller/entity/contents/content_context.cc index 2cc6218e08277..c97791d434b89 100644 --- a/impeller/entity/contents/content_context.cc +++ b/impeller/entity/contents/content_context.cc @@ -191,6 +191,8 @@ ContentContext::ContentContext(std::shared_ptr context) blend_softlight_pipelines_[{}] = CreateDefaultPipeline(*context_); texture_pipelines_[{}] = CreateDefaultPipeline(*context_); + tiled_texture_pipelines_[{}] = + CreateDefaultPipeline(*context_); gaussian_blur_pipelines_[{}] = CreateDefaultPipeline(*context_); border_mask_blur_pipelines_[{}] = diff --git a/impeller/entity/contents/content_context.h b/impeller/entity/contents/content_context.h index d31eb9435d8ea..cce72cf50b5c5 100644 --- a/impeller/entity/contents/content_context.h +++ b/impeller/entity/contents/content_context.h @@ -52,6 +52,8 @@ #include "impeller/entity/sweep_gradient_fill.vert.h" #include "impeller/entity/texture_fill.frag.h" #include "impeller/entity/texture_fill.vert.h" +#include "impeller/entity/tiled_texture_fill.frag.h" +#include "impeller/entity/tiled_texture_fill.vert.h" #include "impeller/entity/vertices.frag.h" #include "impeller/entity/vertices.vert.h" #include "impeller/renderer/formats.h" @@ -102,6 +104,8 @@ using BlendSoftLightPipeline = PipelineT; using TexturePipeline = PipelineT; +using TiledTexturePipeline = + PipelineT; using GaussianBlurPipeline = PipelineT; using BorderMaskBlurPipeline = @@ -184,6 +188,11 @@ class ContentContext { return GetPipeline(texture_pipelines_, opts); } + std::shared_ptr GetTiledTexturePipeline( + ContentContextOptions opts) const { + return GetPipeline(tiled_texture_pipelines_, opts); + } + std::shared_ptr GetGaussianBlurPipeline( ContentContextOptions opts) const { return GetPipeline(gaussian_blur_pipelines_, opts); @@ -323,6 +332,7 @@ class ContentContext { mutable Variants rrect_blur_pipelines_; mutable Variants texture_blend_pipelines_; mutable Variants texture_pipelines_; + mutable Variants tiled_texture_pipelines_; mutable Variants gaussian_blur_pipelines_; mutable Variants border_mask_blur_pipelines_; mutable Variants solid_stroke_pipelines_; diff --git a/impeller/entity/contents/tiled_texture_contents.cc b/impeller/entity/contents/tiled_texture_contents.cc new file mode 100644 index 0000000000000..d9924a3a4e768 --- /dev/null +++ b/impeller/entity/contents/tiled_texture_contents.cc @@ -0,0 +1,120 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "impeller/entity/contents/tiled_texture_contents.h" + +#include "impeller/entity/contents/content_context.h" +#include "impeller/entity/entity.h" +#include "impeller/entity/tiled_texture_fill.frag.h" +#include "impeller/entity/tiled_texture_fill.vert.h" +#include "impeller/geometry/matrix.h" +#include "impeller/renderer/render_pass.h" +#include "impeller/renderer/sampler_library.h" +#include "impeller/tessellator/tessellator.h" + +namespace impeller { + +TiledTextureContents::TiledTextureContents() = default; + +TiledTextureContents::~TiledTextureContents() = default; + +void TiledTextureContents::SetPath(Path path) { + path_ = std::move(path); +} + +void TiledTextureContents::SetTexture(std::shared_ptr texture) { + texture_ = std::move(texture); +} + +void TiledTextureContents::SetTileModes(Entity::TileMode x_tile_mode, + Entity::TileMode y_tile_mode) { + x_tile_mode_ = x_tile_mode; + y_tile_mode_ = y_tile_mode; +} + +void TiledTextureContents::SetSamplerDescriptor(SamplerDescriptor desc) { + sampler_descriptor_ = std::move(desc); +} + +std::optional TiledTextureContents::GetCoverage( + const Entity& entity) const { + return path_.GetTransformedBoundingBox(entity.GetTransformation()); +}; + +bool TiledTextureContents::Render(const ContentContext& renderer, + const Entity& entity, + RenderPass& pass) const { + if (texture_ == nullptr) { + return true; + } + + using VS = TiledTextureFillVertexShader; + using FS = TiledTextureFillFragmentShader; + + const auto coverage_rect = path_.GetBoundingBox(); + + if (!coverage_rect.has_value()) { + return true; + } + + if (coverage_rect->size.IsEmpty()) { + return true; + } + + const auto texture_size = texture_->GetSize(); + if (texture_size.IsEmpty()) { + return true; + } + + VertexBufferBuilder vertex_builder; + { + const auto tess_result = + Tessellator{}.Tessellate(path_.GetFillType(), path_.CreatePolyline(), + [&vertex_builder, &texture_size](Point vtx) { + VS::PerVertexData data; + data.position = vtx; + data.texture_coords = vtx / texture_size; + vertex_builder.AppendVertex(data); + }); + + if (tess_result == Tessellator::Result::kInputError) { + return true; + } + if (tess_result == Tessellator::Result::kTessellationError) { + return false; + } + } + + if (!vertex_builder.HasVertices()) { + return true; + } + + auto& host_buffer = pass.GetTransientsBuffer(); + + VS::VertInfo vert_info; + vert_info.mvp = Matrix::MakeOrthographic(pass.GetRenderTargetSize()) * + entity.GetTransformation(); + + FS::FragInfo frag_info; + frag_info.texture_sampler_y_coord_scale = texture_->GetYCoordScale(); + frag_info.x_tile_mode = static_cast(x_tile_mode_); + frag_info.y_tile_mode = static_cast(y_tile_mode_); + + Command cmd; + cmd.label = "TiledTextureFill"; + cmd.pipeline = + renderer.GetTiledTexturePipeline(OptionsFromPassAndEntity(pass, entity)); + cmd.stencil_reference = entity.GetStencilDepth(); + cmd.BindVertices(vertex_builder.CreateVertexBuffer(host_buffer)); + VS::BindVertInfo(cmd, host_buffer.EmplaceUniform(vert_info)); + FS::BindFragInfo(cmd, host_buffer.EmplaceUniform(frag_info)); + FS::BindTextureSampler(cmd, texture_, + renderer.GetContext()->GetSamplerLibrary()->GetSampler( + sampler_descriptor_)); + pass.AddCommand(std::move(cmd)); + + return true; +} + +} // namespace impeller diff --git a/impeller/entity/contents/tiled_texture_contents.h b/impeller/entity/contents/tiled_texture_contents.h new file mode 100644 index 0000000000000..dcd57600cd6f0 --- /dev/null +++ b/impeller/entity/contents/tiled_texture_contents.h @@ -0,0 +1,55 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#pragma once + +#include +#include +#include + +#include "flutter/fml/macros.h" +#include "impeller/entity/contents/path_contents.h" +#include "impeller/entity/entity.h" +#include "impeller/geometry/color.h" +#include "impeller/geometry/path.h" +#include "impeller/geometry/point.h" +#include "impeller/geometry/scalar.h" +#include "impeller/renderer/sampler_descriptor.h" + +namespace impeller { + +class TiledTextureContents final : public PathContents { + public: + TiledTextureContents(); + + ~TiledTextureContents() override; + + void SetPath(Path path) override; + + // |Contents| + std::optional GetCoverage(const Entity& entity) const override; + + // |Contents| + bool Render(const ContentContext& renderer, + const Entity& entity, + RenderPass& pass) const override; + + void SetTexture(std::shared_ptr texture); + + void SetTileModes(Entity::TileMode horizontal_tile_mode, + Entity::TileMode vertical_tile_mode); + + void SetSamplerDescriptor(SamplerDescriptor desc); + + private: + Path path_; + std::shared_ptr texture_; + SamplerDescriptor sampler_descriptor_ = {}; + Entity::TileMode x_tile_mode_; + Entity::TileMode y_tile_mode_; + + FML_DISALLOW_COPY_AND_ASSIGN(TiledTextureContents); +}; + +} // namespace impeller diff --git a/impeller/entity/shaders/tiled_texture_fill.frag b/impeller/entity/shaders/tiled_texture_fill.frag new file mode 100644 index 0000000000000..3a271400f91f7 --- /dev/null +++ b/impeller/entity/shaders/tiled_texture_fill.frag @@ -0,0 +1,29 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include + +uniform sampler2D texture_sampler; + +uniform FragInfo { + float texture_sampler_y_coord_scale; + float x_tile_mode; + float y_tile_mode; +} +frag_info; + +in vec2 v_texture_coords; + +out vec4 frag_color; + +void main() { + frag_color = + IPSampleWithTileMode( + texture_sampler, // sampler + v_texture_coords, // texture coordinates + frag_info.texture_sampler_y_coord_scale, // y coordinate scale + frag_info.x_tile_mode, // x tile mode + frag_info.y_tile_mode // y tile mode + ); +} diff --git a/impeller/entity/shaders/tiled_texture_fill.vert b/impeller/entity/shaders/tiled_texture_fill.vert new file mode 100644 index 0000000000000..c8abc9aaabbce --- /dev/null +++ b/impeller/entity/shaders/tiled_texture_fill.vert @@ -0,0 +1,18 @@ +// Copyright 2013 The Flutter Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +uniform VertInfo { + mat4 mvp; +} +vert_info; + +in vec2 position; +in vec2 texture_coords; + +out vec2 v_texture_coords; + +void main() { + gl_Position = vert_info.mvp * vec4(position, 0.0, 1.0); + v_texture_coords = texture_coords; +} From dff0d8d58295ae9e21f514cf6c8392584de97387 Mon Sep 17 00:00:00 2001 From: ColdPaleLight Date: Wed, 10 Aug 2022 22:07:39 +0800 Subject: [PATCH 2/4] Tweak test --- impeller/aiks/aiks_unittests.cc | 94 ++++++++++++++++++++++++--------- 1 file changed, 70 insertions(+), 24 deletions(-) diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc index 93e3ed5252da6..ff9e5312f21ba 100644 --- a/impeller/aiks/aiks_unittests.cc +++ b/impeller/aiks/aiks_unittests.cc @@ -16,6 +16,7 @@ #include "impeller/geometry/path_builder.h" #include "impeller/geometry/scalar.h" #include "impeller/playground/widgets.h" +#include "impeller/renderer/command_buffer.h" #include "impeller/renderer/formats.h" #include "impeller/renderer/sampler_descriptor.h" #include "impeller/renderer/snapshot.h" @@ -74,32 +75,77 @@ TEST_P(AiksTest, CanRenderImage) { ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); } -TEST_P(AiksTest, CanRenderTiledImage) { - Canvas canvas; - Paint paint; - std::vector tile_modes = { - Entity::TileMode::kClamp, Entity::TileMode::kRepeat, - Entity::TileMode::kMirror, Entity::TileMode::kDecal}; +bool GenerateMipmap(std::shared_ptr context, + std::shared_ptr texture, + std::string label) { + auto buffer = context->CreateCommandBuffer(); + if (!buffer) { + return false; + } + auto pass = buffer->CreateBlitPass(); + if (!pass) { + return false; + } + pass->GenerateMipmap(texture, label); + pass->EncodeCommands(context->GetResourceAllocator()); + return true; +} + +TEST_P(AiksTest, CanRenderTiledTexture) { + auto context = GetContext(); + ASSERT_TRUE(context); + bool first_frame = true; auto texture = CreateTextureForFixture("table_mountain_nx.png"); - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - Scalar offset_x = i * 400.0; - Scalar offset_y = j * 400.0; - canvas.Save(); - canvas.Translate({offset_x, offset_y, 0}); - auto contents = std::make_shared(); - contents->SetTexture(texture); - contents->SetTileModes(tile_modes[i], tile_modes[j]); - SamplerDescriptor desc; - desc.width_address_mode = SamplerAddressMode::kMirror; - desc.height_address_mode = SamplerAddressMode::kRepeat; - contents->SetSamplerDescriptor(desc); - paint.contents = contents; - canvas.DrawRect({0, 0, 300, 300}, paint); - canvas.Restore(); + auto callback = [&](AiksContext& renderer, RenderTarget& render_target) { + if (first_frame) { + first_frame = false; + GenerateMipmap(context, texture, "table_mountain_nx"); + ImGui::SetNextWindowSize({480, 100}); + ImGui::SetNextWindowPos({100, 550}); } - } - ASSERT_TRUE(OpenPlaygroundHere(canvas.EndRecordingAsPicture())); + + const char* tile_mode_names[] = {"Clamp", "Repeat", "Mirror", "Decal"}; + const Entity::TileMode tile_modes[] = { + Entity::TileMode::kClamp, Entity::TileMode::kRepeat, + Entity::TileMode::kMirror, Entity::TileMode::kDecal}; + const char* mip_filter_names[] = {"None", "Nearest", "Linear"}; + const MipFilter mip_filters[] = {MipFilter::kNone, MipFilter::kNearest, + MipFilter::kLinear}; + const char* min_mag_filter_names[] = {"Nearest", "Linear"}; + const MinMagFilter min_mag_filters[] = {MinMagFilter::kNearest, + MinMagFilter::kLinear}; + static int selected_x_tile_mode = 0; + static int selected_y_tile_mode = 0; + static int selected_mip_filter = 0; + static int selected_min_mag_filter = 0; + ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_AlwaysAutoResize); + ImGui::Combo("X tile mode", &selected_x_tile_mode, tile_mode_names, + sizeof(tile_mode_names) / sizeof(char*)); + ImGui::Combo("Y tile mode", &selected_y_tile_mode, tile_mode_names, + sizeof(tile_mode_names) / sizeof(char*)); + ImGui::Combo("Mip filter", &selected_mip_filter, mip_filter_names, + sizeof(mip_filter_names) / sizeof(char*)); + ImGui::Combo("Min Mag filter", &selected_min_mag_filter, + min_mag_filter_names, + sizeof(min_mag_filter_names) / sizeof(char*)); + ImGui::End(); + Canvas canvas; + Paint paint; + canvas.Translate({100.0, 100.0, 0}); + auto contents = std::make_shared(); + contents->SetTexture(texture); + contents->SetTileModes(tile_modes[selected_x_tile_mode], + tile_modes[selected_y_tile_mode]); + SamplerDescriptor descriptor; + descriptor.mip_filter = mip_filters[selected_mip_filter]; + descriptor.min_filter = min_mag_filters[selected_min_mag_filter]; + descriptor.mag_filter = min_mag_filters[selected_min_mag_filter]; + contents->SetSamplerDescriptor(descriptor); + paint.contents = contents; + canvas.DrawRect({0, 0, 600, 600}, paint); + return renderer.Render(canvas.EndRecordingAsPicture(), render_target); + }; + ASSERT_TRUE(OpenPlaygroundHere(callback)); } TEST_P(AiksTest, CanRenderImageRect) { From cfc26952d157df3b43be803a663ffcbe7da304e6 Mon Sep 17 00:00:00 2001 From: ColdPaleLight Date: Wed, 10 Aug 2022 22:21:08 +0800 Subject: [PATCH 3/4] Clean code --- impeller/aiks/aiks_unittests.cc | 3 --- impeller/entity/contents/tiled_texture_contents.cc | 2 -- impeller/entity/contents/tiled_texture_contents.h | 3 --- impeller/entity/shaders/tiled_texture_fill.frag | 2 +- 4 files changed, 1 insertion(+), 9 deletions(-) diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc index ff9e5312f21ba..ea4470a361a3a 100644 --- a/impeller/aiks/aiks_unittests.cc +++ b/impeller/aiks/aiks_unittests.cc @@ -14,11 +14,8 @@ #include "impeller/geometry/color.h" #include "impeller/geometry/geometry_unittests.h" #include "impeller/geometry/path_builder.h" -#include "impeller/geometry/scalar.h" #include "impeller/playground/widgets.h" #include "impeller/renderer/command_buffer.h" -#include "impeller/renderer/formats.h" -#include "impeller/renderer/sampler_descriptor.h" #include "impeller/renderer/snapshot.h" #include "impeller/typographer/backends/skia/text_frame_skia.h" #include "impeller/typographer/backends/skia/text_render_context_skia.h" diff --git a/impeller/entity/contents/tiled_texture_contents.cc b/impeller/entity/contents/tiled_texture_contents.cc index d9924a3a4e768..c3b6521ca97fe 100644 --- a/impeller/entity/contents/tiled_texture_contents.cc +++ b/impeller/entity/contents/tiled_texture_contents.cc @@ -5,10 +5,8 @@ #include "impeller/entity/contents/tiled_texture_contents.h" #include "impeller/entity/contents/content_context.h" -#include "impeller/entity/entity.h" #include "impeller/entity/tiled_texture_fill.frag.h" #include "impeller/entity/tiled_texture_fill.vert.h" -#include "impeller/geometry/matrix.h" #include "impeller/renderer/render_pass.h" #include "impeller/renderer/sampler_library.h" #include "impeller/tessellator/tessellator.h" diff --git a/impeller/entity/contents/tiled_texture_contents.h b/impeller/entity/contents/tiled_texture_contents.h index dcd57600cd6f0..c0e68a4fdb930 100644 --- a/impeller/entity/contents/tiled_texture_contents.h +++ b/impeller/entity/contents/tiled_texture_contents.h @@ -11,10 +11,7 @@ #include "flutter/fml/macros.h" #include "impeller/entity/contents/path_contents.h" #include "impeller/entity/entity.h" -#include "impeller/geometry/color.h" #include "impeller/geometry/path.h" -#include "impeller/geometry/point.h" -#include "impeller/geometry/scalar.h" #include "impeller/renderer/sampler_descriptor.h" namespace impeller { diff --git a/impeller/entity/shaders/tiled_texture_fill.frag b/impeller/entity/shaders/tiled_texture_fill.frag index 3a271400f91f7..1c0c0411414b0 100644 --- a/impeller/entity/shaders/tiled_texture_fill.frag +++ b/impeller/entity/shaders/tiled_texture_fill.frag @@ -25,5 +25,5 @@ void main() { frag_info.texture_sampler_y_coord_scale, // y coordinate scale frag_info.x_tile_mode, // x tile mode frag_info.y_tile_mode // y tile mode - ); + ); } From af8203b96be18de6c0b4e12c3b896b88d20560ef Mon Sep 17 00:00:00 2001 From: ColdPaleLight Date: Thu, 11 Aug 2022 20:31:39 +0800 Subject: [PATCH 4/4] Clean code and add issue link --- impeller/aiks/aiks_unittests.cc | 15 ++++++++------ .../display_list/display_list_dispatcher.cc | 20 +++++++++++-------- .../entity/contents/tiled_texture_contents.h | 3 +-- 3 files changed, 22 insertions(+), 16 deletions(-) diff --git a/impeller/aiks/aiks_unittests.cc b/impeller/aiks/aiks_unittests.cc index 83e6a0b727264..55a8c32993fd7 100644 --- a/impeller/aiks/aiks_unittests.cc +++ b/impeller/aiks/aiks_unittests.cc @@ -129,16 +129,19 @@ TEST_P(AiksTest, CanRenderTiledTexture) { Canvas canvas; Paint paint; canvas.Translate({100.0, 100.0, 0}); - auto contents = std::make_shared(); - contents->SetTexture(texture); - contents->SetTileModes(tile_modes[selected_x_tile_mode], - tile_modes[selected_y_tile_mode]); + auto x_tile_mode = tile_modes[selected_x_tile_mode]; + auto y_tile_mode = tile_modes[selected_y_tile_mode]; SamplerDescriptor descriptor; descriptor.mip_filter = mip_filters[selected_mip_filter]; descriptor.min_filter = min_mag_filters[selected_min_mag_filter]; descriptor.mag_filter = min_mag_filters[selected_min_mag_filter]; - contents->SetSamplerDescriptor(descriptor); - paint.contents = contents; + paint.color_source = [texture, x_tile_mode, y_tile_mode, descriptor]() { + auto contents = std::make_shared(); + contents->SetTexture(texture); + contents->SetTileModes(x_tile_mode, y_tile_mode); + contents->SetSamplerDescriptor(descriptor); + return contents; + }; canvas.DrawRect({0, 0, 600, 600}, paint); return renderer.Render(canvas.EndRecordingAsPicture(), render_target); }; diff --git a/impeller/display_list/display_list_dispatcher.cc b/impeller/display_list/display_list_dispatcher.cc index 9523ff2241e27..4ec8572f770b4 100644 --- a/impeller/display_list/display_list_dispatcher.cc +++ b/impeller/display_list/display_list_dispatcher.cc @@ -362,14 +362,18 @@ void DisplayListDispatcher::setColorSource( const flutter::DlImageColorSource* image_color_source = source->asImage(); FML_DCHECK(image_color_source && image_color_source->image()->impeller_texture()); - auto contents = std::make_shared(); - contents->SetTexture(image_color_source->image()->impeller_texture()); - contents->SetTileModes( - ToTileMode(image_color_source->horizontal_tile_mode()), - ToTileMode(image_color_source->vertical_tile_mode())); - contents->SetSamplerDescriptor( - ToSamplerDescriptor(image_color_source->sampling())); - paint_.contents = std::move(contents); + auto texture = image_color_source->image()->impeller_texture(); + auto x_tile_mode = ToTileMode(image_color_source->horizontal_tile_mode()); + auto y_tile_mode = ToTileMode(image_color_source->vertical_tile_mode()); + auto desc = ToSamplerDescriptor(image_color_source->sampling()); + paint_.color_source = [texture, x_tile_mode, y_tile_mode, desc]() { + auto contents = std::make_shared(); + contents->SetTexture(texture); + contents->SetTileModes(x_tile_mode, y_tile_mode); + contents->SetSamplerDescriptor(desc); + // TODO(109384) Support 'matrix' parameter for all color sources. + return contents; + }; return; } case flutter::DlColorSourceType::kConicalGradient: diff --git a/impeller/entity/contents/tiled_texture_contents.h b/impeller/entity/contents/tiled_texture_contents.h index c0e68a4fdb930..378ff9051eb34 100644 --- a/impeller/entity/contents/tiled_texture_contents.h +++ b/impeller/entity/contents/tiled_texture_contents.h @@ -34,8 +34,7 @@ class TiledTextureContents final : public PathContents { void SetTexture(std::shared_ptr texture); - void SetTileModes(Entity::TileMode horizontal_tile_mode, - Entity::TileMode vertical_tile_mode); + void SetTileModes(Entity::TileMode x_tile_mode, Entity::TileMode y_tile_mode); void SetSamplerDescriptor(SamplerDescriptor desc);