diff --git a/impeller/aiks/aiks_blur_unittests.cc b/impeller/aiks/aiks_blur_unittests.cc index 03151a3ffbe67..370eee168332d 100644 --- a/impeller/aiks/aiks_blur_unittests.cc +++ b/impeller/aiks/aiks_blur_unittests.cc @@ -354,6 +354,7 @@ TEST_P(AiksTest, GaussianBlurWithoutDecalSupport) { FLT_FORWARD(mock_capabilities, old_capabilities, SupportsCompute); FLT_FORWARD(mock_capabilities, old_capabilities, SupportsTextureToTextureBlits); + FLT_FORWARD(mock_capabilities, old_capabilities, GetDefaultGlyphAtlasFormat); ASSERT_TRUE(SetCapabilities(mock_capabilities).ok()); auto texture = std::make_shared(CreateTextureForFixture("boston.jpg")); diff --git a/impeller/entity/contents/content_context.cc b/impeller/entity/contents/content_context.cc index bde5a604b62ce..1d73fcff072b0 100644 --- a/impeller/entity/contents/content_context.cc +++ b/impeller/entity/contents/content_context.cc @@ -404,7 +404,11 @@ ContentContext::ContentContext( options_trianglestrip); srgb_to_linear_filter_pipelines_.CreateDefault(*context_, options_trianglestrip); - glyph_atlas_pipelines_.CreateDefault(*context_, options); + glyph_atlas_pipelines_.CreateDefault( + *context_, options, + {static_cast( + GetContext()->GetCapabilities()->GetDefaultGlyphAtlasFormat() == + PixelFormat::kA8UNormInt)}); glyph_atlas_color_pipelines_.CreateDefault(*context_, options); geometry_color_pipelines_.CreateDefault(*context_, options); yuv_to_rgb_filter_pipelines_.CreateDefault(*context_, options_trianglestrip); diff --git a/impeller/entity/shaders/glyph_atlas.frag b/impeller/entity/shaders/glyph_atlas.frag index 9a9b71780dd33..8db425d0e97ff 100644 --- a/impeller/entity/shaders/glyph_atlas.frag +++ b/impeller/entity/shaders/glyph_atlas.frag @@ -8,6 +8,8 @@ precision mediump float; uniform f16sampler2D glyph_atlas_sampler; +layout(constant_id = 0) const float use_alpha_color_channel = 1.0; + in highp vec2 v_uv; IMPELLER_MAYBE_FLAT in f16vec4 v_text_color; @@ -16,5 +18,9 @@ out f16vec4 frag_color; void main() { f16vec4 value = texture(glyph_atlas_sampler, v_uv); - frag_color = value.aaaa * v_text_color; + if (use_alpha_color_channel == 1.0) { + frag_color = value.aaaa * v_text_color; + } else { + frag_color = value.rrrr * v_text_color; + } } diff --git a/impeller/renderer/backend/gles/capabilities_gles.cc b/impeller/renderer/backend/gles/capabilities_gles.cc index e379497edfd43..a67486bd37047 100644 --- a/impeller/renderer/backend/gles/capabilities_gles.cc +++ b/impeller/renderer/backend/gles/capabilities_gles.cc @@ -4,6 +4,7 @@ #include "impeller/renderer/backend/gles/capabilities_gles.h" +#include "impeller/core/formats.h" #include "impeller/renderer/backend/gles/proc_table_gles.h" namespace impeller { @@ -102,6 +103,12 @@ CapabilitiesGLES::CapabilitiesGLES(const ProcTableGLES& gl) { num_shader_binary_formats = value; } + if (desc->IsES()) { + default_glyph_atlas_format_ = PixelFormat::kA8UNormInt; + } else { + default_glyph_atlas_format_ = PixelFormat::kR8UNormInt; + } + supports_framebuffer_fetch_ = desc->HasExtension(kFramebufferFetchExt); if (desc->HasExtension(kTextureBorderClampExt) || @@ -194,4 +201,8 @@ bool CapabilitiesGLES::IsANGLE() const { return is_angle_; } +PixelFormat CapabilitiesGLES::GetDefaultGlyphAtlasFormat() const { + return default_glyph_atlas_format_; +} + } // namespace impeller diff --git a/impeller/renderer/backend/gles/capabilities_gles.h b/impeller/renderer/backend/gles/capabilities_gles.h index dc58081f05e44..afcc71b418f73 100644 --- a/impeller/renderer/backend/gles/capabilities_gles.h +++ b/impeller/renderer/backend/gles/capabilities_gles.h @@ -8,6 +8,7 @@ #include #include "impeller/base/backend_cast.h" +#include "impeller/core/formats.h" #include "impeller/core/shader_types.h" #include "impeller/geometry/size.h" #include "impeller/renderer/capabilities.h" @@ -118,12 +119,16 @@ class CapabilitiesGLES final // |Capabilities| PixelFormat GetDefaultDepthStencilFormat() const override; + // |Capabilities| + PixelFormat GetDefaultGlyphAtlasFormat() const override; + private: bool supports_framebuffer_fetch_ = false; bool supports_decal_sampler_address_mode_ = false; bool supports_offscreen_msaa_ = false; bool supports_implicit_msaa_ = false; bool is_angle_ = false; + PixelFormat default_glyph_atlas_format_ = PixelFormat::kUnknown; }; } // namespace impeller diff --git a/impeller/renderer/backend/gles/texture_gles.cc b/impeller/renderer/backend/gles/texture_gles.cc index 74b2f6f503fcf..55577bcb6add9 100644 --- a/impeller/renderer/backend/gles/texture_gles.cc +++ b/impeller/renderer/backend/gles/texture_gles.cc @@ -130,6 +130,11 @@ struct TexImage2DData { external_format = GL_ALPHA; type = GL_UNSIGNED_BYTE; break; + case PixelFormat::kR8UNormInt: + internal_format = GL_RED; + external_format = GL_RED; + type = GL_UNSIGNED_BYTE; + break; case PixelFormat::kR8G8B8A8UNormInt: case PixelFormat::kB8G8R8A8UNormInt: case PixelFormat::kR8G8B8A8UNormIntSRGB: @@ -161,7 +166,6 @@ struct TexImage2DData { break; case PixelFormat::kUnknown: case PixelFormat::kD32FloatS8UInt: - case PixelFormat::kR8UNormInt: case PixelFormat::kR8G8UNormInt: case PixelFormat::kB10G10R10XRSRGB: case PixelFormat::kB10G10R10XR: diff --git a/impeller/renderer/backend/metal/context_mtl.mm b/impeller/renderer/backend/metal/context_mtl.mm index 8b23d4bed64a8..623f3c8335f4c 100644 --- a/impeller/renderer/backend/metal/context_mtl.mm +++ b/impeller/renderer/backend/metal/context_mtl.mm @@ -67,6 +67,7 @@ static bool DeviceSupportsComputeSubgroups(id device) { .SetSupportsComputeSubgroups(DeviceSupportsComputeSubgroups(device)) .SetSupportsReadFromResolve(true) .SetSupportsDeviceTransientTextures(true) + .SetDefaultGlyphAtlasFormat(PixelFormat::kA8UNormInt) .Build(); } diff --git a/impeller/renderer/backend/vulkan/capabilities_vk.cc b/impeller/renderer/backend/vulkan/capabilities_vk.cc index 812aae651a501..ab5214747b5b5 100644 --- a/impeller/renderer/backend/vulkan/capabilities_vk.cc +++ b/impeller/renderer/backend/vulkan/capabilities_vk.cc @@ -484,4 +484,8 @@ bool CapabilitiesVK::HasOptionalDeviceExtension( optional_device_extensions_.end(); } +PixelFormat CapabilitiesVK::GetDefaultGlyphAtlasFormat() const { + return PixelFormat::kR8UNormInt; +} + } // namespace impeller diff --git a/impeller/renderer/backend/vulkan/capabilities_vk.h b/impeller/renderer/backend/vulkan/capabilities_vk.h index b2dad43260b99..d3f5d70fbffee 100644 --- a/impeller/renderer/backend/vulkan/capabilities_vk.h +++ b/impeller/renderer/backend/vulkan/capabilities_vk.h @@ -100,6 +100,9 @@ class CapabilitiesVK final : public Capabilities, // |Capabilities| PixelFormat GetDefaultDepthStencilFormat() const override; + // |Capabilities| + PixelFormat GetDefaultGlyphAtlasFormat() const override; + private: bool validations_enabled_ = false; std::map> exts_; diff --git a/impeller/renderer/backend/vulkan/debug_report_vk.cc b/impeller/renderer/backend/vulkan/debug_report_vk.cc index 983c25ee80d47..fce16f8751d4b 100644 --- a/impeller/renderer/backend/vulkan/debug_report_vk.cc +++ b/impeller/renderer/backend/vulkan/debug_report_vk.cc @@ -111,15 +111,6 @@ DebugReportVK::Result DebugReportVK::OnDebugCallback( return Result::kContinue; } - // This is a real error but we can't fix it due to our headers being too - // old. More more details see: - // https://vulkan.lunarg.com/doc/view/1.3.224.1/mac/1.3-extensions/vkspec.html#VUID-VkImageViewCreateInfo-imageViewFormatSwizzle-04465 - // This validation error currently only trips on macOS due to the use of - // texture swizzles. - if (data->messageIdNumber == static_cast(0x82ae5050)) { - return Result::kContinue; - } - std::vector> items; items.emplace_back("Severity", vk::to_string(severity)); diff --git a/impeller/renderer/capabilities.cc b/impeller/renderer/capabilities.cc index 4dcda955ab954..1ef1fe38a8062 100644 --- a/impeller/renderer/capabilities.cc +++ b/impeller/renderer/capabilities.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "impeller/renderer/capabilities.h" +#include "impeller/core/formats.h" namespace impeller { @@ -74,10 +75,16 @@ class StandardCapabilities final : public Capabilities { return default_depth_stencil_format_; } + // |Capabilities| bool SupportsDeviceTransientTextures() const override { return supports_device_transient_textures_; } + // |Capabilities| + PixelFormat GetDefaultGlyphAtlasFormat() const override { + return default_glyph_atlas_format_; + } + private: StandardCapabilities(bool supports_offscreen_msaa, bool supports_ssbo, @@ -91,7 +98,8 @@ class StandardCapabilities final : public Capabilities { bool supports_device_transient_textures, PixelFormat default_color_format, PixelFormat default_stencil_format, - PixelFormat default_depth_stencil_format) + PixelFormat default_depth_stencil_format, + PixelFormat default_glyph_atlas_format) : supports_offscreen_msaa_(supports_offscreen_msaa), supports_ssbo_(supports_ssbo), supports_buffer_to_texture_blits_(supports_buffer_to_texture_blits), @@ -105,7 +113,8 @@ class StandardCapabilities final : public Capabilities { supports_device_transient_textures_(supports_device_transient_textures), default_color_format_(default_color_format), default_stencil_format_(default_stencil_format), - default_depth_stencil_format_(default_depth_stencil_format) {} + default_depth_stencil_format_(default_depth_stencil_format), + default_glyph_atlas_format_(default_glyph_atlas_format) {} friend class CapabilitiesBuilder; @@ -122,6 +131,7 @@ class StandardCapabilities final : public Capabilities { PixelFormat default_color_format_ = PixelFormat::kUnknown; PixelFormat default_stencil_format_ = PixelFormat::kUnknown; PixelFormat default_depth_stencil_format_ = PixelFormat::kUnknown; + PixelFormat default_glyph_atlas_format_ = PixelFormat::kUnknown; StandardCapabilities(const StandardCapabilities&) = delete; @@ -207,6 +217,12 @@ CapabilitiesBuilder& CapabilitiesBuilder::SetSupportsDeviceTransientTextures( return *this; } +CapabilitiesBuilder& CapabilitiesBuilder::SetDefaultGlyphAtlasFormat( + PixelFormat value) { + default_glyph_atlas_format_ = value; + return *this; +} + std::unique_ptr CapabilitiesBuilder::Build() { return std::unique_ptr(new StandardCapabilities( // supports_offscreen_msaa_, // @@ -221,7 +237,8 @@ std::unique_ptr CapabilitiesBuilder::Build() { supports_device_transient_textures_, // default_color_format_.value_or(PixelFormat::kUnknown), // default_stencil_format_.value_or(PixelFormat::kUnknown), // - default_depth_stencil_format_.value_or(PixelFormat::kUnknown) // + default_depth_stencil_format_.value_or(PixelFormat::kUnknown), // + default_glyph_atlas_format_.value_or(PixelFormat::kUnknown) // )); } diff --git a/impeller/renderer/capabilities.h b/impeller/renderer/capabilities.h index 9f3f15cefe897..34c5839bd5959 100644 --- a/impeller/renderer/capabilities.h +++ b/impeller/renderer/capabilities.h @@ -105,6 +105,12 @@ class Capabilities { /// format was found. virtual PixelFormat GetDefaultDepthStencilFormat() const = 0; + /// @brief Returns the default pixel format for the alpha bitmap glyph atlas. + /// + /// Some backends may use Red channel while others use grey. This + /// should not have any impact + virtual PixelFormat GetDefaultGlyphAtlasFormat() const = 0; + protected: Capabilities(); @@ -145,6 +151,8 @@ class CapabilitiesBuilder { CapabilitiesBuilder& SetSupportsDeviceTransientTextures(bool value); + CapabilitiesBuilder& SetDefaultGlyphAtlasFormat(PixelFormat value); + std::unique_ptr Build(); private: @@ -161,6 +169,7 @@ class CapabilitiesBuilder { std::optional default_color_format_ = std::nullopt; std::optional default_stencil_format_ = std::nullopt; std::optional default_depth_stencil_format_ = std::nullopt; + std::optional default_glyph_atlas_format_ = std::nullopt; CapabilitiesBuilder(const CapabilitiesBuilder&) = delete; diff --git a/impeller/renderer/capabilities_unittests.cc b/impeller/renderer/capabilities_unittests.cc index 06c9bc3f82282..2692d067ad0a3 100644 --- a/impeller/renderer/capabilities_unittests.cc +++ b/impeller/renderer/capabilities_unittests.cc @@ -31,31 +31,40 @@ CAPABILITY_TEST(SupportsDeviceTransientTextures, false); TEST(CapabilitiesTest, DefaultColorFormat) { auto defaults = CapabilitiesBuilder().Build(); - ASSERT_EQ(defaults->GetDefaultColorFormat(), PixelFormat::kUnknown); + EXPECT_EQ(defaults->GetDefaultColorFormat(), PixelFormat::kUnknown); auto mutated = CapabilitiesBuilder() .SetDefaultColorFormat(PixelFormat::kB10G10R10A10XR) .Build(); - ASSERT_EQ(mutated->GetDefaultColorFormat(), PixelFormat::kB10G10R10A10XR); + EXPECT_EQ(mutated->GetDefaultColorFormat(), PixelFormat::kB10G10R10A10XR); } TEST(CapabilitiesTest, DefaultStencilFormat) { auto defaults = CapabilitiesBuilder().Build(); - ASSERT_EQ(defaults->GetDefaultStencilFormat(), PixelFormat::kUnknown); + EXPECT_EQ(defaults->GetDefaultStencilFormat(), PixelFormat::kUnknown); auto mutated = CapabilitiesBuilder() .SetDefaultStencilFormat(PixelFormat::kS8UInt) .Build(); - ASSERT_EQ(mutated->GetDefaultStencilFormat(), PixelFormat::kS8UInt); + EXPECT_EQ(mutated->GetDefaultStencilFormat(), PixelFormat::kS8UInt); } TEST(CapabilitiesTest, DefaultDepthStencilFormat) { auto defaults = CapabilitiesBuilder().Build(); - ASSERT_EQ(defaults->GetDefaultDepthStencilFormat(), PixelFormat::kUnknown); + EXPECT_EQ(defaults->GetDefaultDepthStencilFormat(), PixelFormat::kUnknown); auto mutated = CapabilitiesBuilder() .SetDefaultDepthStencilFormat(PixelFormat::kD32FloatS8UInt) .Build(); - ASSERT_EQ(mutated->GetDefaultDepthStencilFormat(), + EXPECT_EQ(mutated->GetDefaultDepthStencilFormat(), PixelFormat::kD32FloatS8UInt); } +TEST(CapabilitiesTest, DefaultGlyphAtlasFormat) { + auto defaults = CapabilitiesBuilder().Build(); + EXPECT_EQ(defaults->GetDefaultGlyphAtlasFormat(), PixelFormat::kUnknown); + auto mutated = CapabilitiesBuilder() + .SetDefaultGlyphAtlasFormat(PixelFormat::kA8UNormInt) + .Build(); + EXPECT_EQ(mutated->GetDefaultGlyphAtlasFormat(), PixelFormat::kA8UNormInt); +} + } // namespace testing } // namespace impeller diff --git a/impeller/renderer/testing/mocks.h b/impeller/renderer/testing/mocks.h index 78b1d388ea67e..45b519cc3c937 100644 --- a/impeller/renderer/testing/mocks.h +++ b/impeller/renderer/testing/mocks.h @@ -204,6 +204,7 @@ class MockCapabilities : public Capabilities { MOCK_METHOD(PixelFormat, GetDefaultColorFormat, (), (const, override)); MOCK_METHOD(PixelFormat, GetDefaultStencilFormat, (), (const, override)); MOCK_METHOD(PixelFormat, GetDefaultDepthStencilFormat, (), (const, override)); + MOCK_METHOD(PixelFormat, GetDefaultGlyphAtlasFormat, (), (const, override)); }; class MockCommandQueue : public CommandQueue { diff --git a/impeller/typographer/backends/skia/typographer_context_skia.cc b/impeller/typographer/backends/skia/typographer_context_skia.cc index 1330d77495d30..b6f266dbed48b 100644 --- a/impeller/typographer/backends/skia/typographer_context_skia.cc +++ b/impeller/typographer/backends/skia/typographer_context_skia.cc @@ -15,6 +15,8 @@ #include "impeller/typographer/backends/skia/typeface_skia.h" #include "impeller/typographer/rectangle_packer.h" #include "impeller/typographer/typographer_context.h" +#include "include/core/SkColor.h" +#include "include/core/SkSize.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkFont.h" @@ -220,7 +222,9 @@ static std::shared_ptr CreateAtlasBitmap(const GlyphAtlas& atlas, switch (atlas.GetType()) { case GlyphAtlas::Type::kAlphaBitmap: - image_info = SkImageInfo::MakeA8(atlas_size.width, atlas_size.height); + image_info = + SkImageInfo::MakeA8(SkISize{static_cast(atlas_size.width), + static_cast(atlas_size.height)}); break; case GlyphAtlas::Type::kColorBitmap: image_info = @@ -466,7 +470,7 @@ std::shared_ptr TypographerContextSkia::CreateGlyphAtlas( PixelFormat format; switch (type) { case GlyphAtlas::Type::kAlphaBitmap: - format = PixelFormat::kA8UNormInt; + format = context.GetCapabilities()->GetDefaultGlyphAtlasFormat(); break; case GlyphAtlas::Type::kColorBitmap: format = PixelFormat::kR8G8B8A8UNormInt; diff --git a/impeller/typographer/backends/stb/typographer_context_stb.cc b/impeller/typographer/backends/stb/typographer_context_stb.cc index be909744edaed..6c5bcad667483 100644 --- a/impeller/typographer/backends/stb/typographer_context_stb.cc +++ b/impeller/typographer/backends/stb/typographer_context_stb.cc @@ -516,11 +516,12 @@ std::shared_ptr TypographerContextSTB::CreateGlyphAtlas( PixelFormat format; switch (type) { case GlyphAtlas::Type::kAlphaBitmap: - format = PixelFormat::kA8UNormInt; + format = context.GetCapabilities()->GetDefaultGlyphAtlasFormat(); break; case GlyphAtlas::Type::kColorBitmap: - format = DISABLE_COLOR_FONT_SUPPORT ? PixelFormat::kA8UNormInt - : PixelFormat::kR8G8B8A8UNormInt; + format = DISABLE_COLOR_FONT_SUPPORT + ? context.GetCapabilities()->GetDefaultGlyphAtlasFormat() + : PixelFormat::kR8G8B8A8UNormInt; break; } auto texture = UploadGlyphTextureAtlas(context.GetResourceAllocator(), bitmap, diff --git a/impeller/typographer/glyph_atlas.h b/impeller/typographer/glyph_atlas.h index ea4ea295e4845..9df7eecd4bd71 100644 --- a/impeller/typographer/glyph_atlas.h +++ b/impeller/typographer/glyph_atlas.h @@ -10,7 +10,6 @@ #include #include -#include "flutter/fml/macros.h" #include "impeller/core/texture.h" #include "impeller/geometry/rect.h" #include "impeller/renderer/pipeline.h" @@ -33,8 +32,10 @@ class GlyphAtlas { enum class Type { //-------------------------------------------------------------------------- /// The glyphs are reprsented at their requested size using only an 8-bit - /// alpha channel. + /// color channel. /// + /// This might be backed by a grey or red single channel texture, depending + /// on the backend capabilities. kAlphaBitmap, //-------------------------------------------------------------------------- diff --git a/impeller/typographer/typographer_unittests.cc b/impeller/typographer/typographer_unittests.cc index 5a239b3b12d46..4fc6fc58a7041 100644 --- a/impeller/typographer/typographer_unittests.cc +++ b/impeller/typographer/typographer_unittests.cc @@ -117,7 +117,7 @@ TEST_P(TypographerTest, LazyAtlasTracksColor) { lazy_atlas.AddTextFrame(*frame, 1.0f); - // Creates different atlases for color and alpha bitmap. + // Creates different atlases for color and red bitmap. auto color_atlas = lazy_atlas.CreateOrGetGlyphAtlas( *GetContext(), GlyphAtlas::Type::kColorBitmap);