mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
[Impeller] Conditionally use A8 or R8 format glyph atlas based on capabilities. (flutter/engine#50534)
R8 texture format is more widely supported than A8, which we emulate on the vulkan backend with a swizzle. Rather than adding more capability or swizzling checks lets just switch to R8 which is fairly trivial. (I think some desktop gl does not support A8 too, but not sure). Add Capabilities getDefaultAtlasFormat. Set this to R8 in Vulkan an non-ES GL. A8 Elsewhere.
This commit is contained in:
parent
5ad8fd8f0d
commit
50ee337979
@ -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<Image>(CreateTextureForFixture("boston.jpg"));
|
||||
|
||||
@ -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<Scalar>(
|
||||
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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
#include <cstddef>
|
||||
|
||||
#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
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -67,6 +67,7 @@ static std::unique_ptr<Capabilities> InferMetalCapabilities(
|
||||
.SetSupportsComputeSubgroups(DeviceSupportsComputeSubgroups(device))
|
||||
.SetSupportsReadFromResolve(true)
|
||||
.SetSupportsDeviceTransientTextures(true)
|
||||
.SetDefaultGlyphAtlasFormat(PixelFormat::kA8UNormInt)
|
||||
.Build();
|
||||
}
|
||||
|
||||
|
||||
@ -484,4 +484,8 @@ bool CapabilitiesVK::HasOptionalDeviceExtension(
|
||||
optional_device_extensions_.end();
|
||||
}
|
||||
|
||||
PixelFormat CapabilitiesVK::GetDefaultGlyphAtlasFormat() const {
|
||||
return PixelFormat::kR8UNormInt;
|
||||
}
|
||||
|
||||
} // namespace impeller
|
||||
|
||||
@ -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<std::string, std::set<std::string>> exts_;
|
||||
|
||||
@ -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<int32_t>(0x82ae5050)) {
|
||||
return Result::kContinue;
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::string, std::string>> items;
|
||||
|
||||
items.emplace_back("Severity", vk::to_string(severity));
|
||||
|
||||
@ -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<Capabilities> CapabilitiesBuilder::Build() {
|
||||
return std::unique_ptr<StandardCapabilities>(new StandardCapabilities( //
|
||||
supports_offscreen_msaa_, //
|
||||
@ -221,7 +237,8 @@ std::unique_ptr<Capabilities> 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) //
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@ -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<Capabilities> Build();
|
||||
|
||||
private:
|
||||
@ -161,6 +169,7 @@ class CapabilitiesBuilder {
|
||||
std::optional<PixelFormat> default_color_format_ = std::nullopt;
|
||||
std::optional<PixelFormat> default_stencil_format_ = std::nullopt;
|
||||
std::optional<PixelFormat> default_depth_stencil_format_ = std::nullopt;
|
||||
std::optional<PixelFormat> default_glyph_atlas_format_ = std::nullopt;
|
||||
|
||||
CapabilitiesBuilder(const CapabilitiesBuilder&) = delete;
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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<SkBitmap> 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<int32_t>(atlas_size.width),
|
||||
static_cast<int32_t>(atlas_size.height)});
|
||||
break;
|
||||
case GlyphAtlas::Type::kColorBitmap:
|
||||
image_info =
|
||||
@ -466,7 +470,7 @@ std::shared_ptr<GlyphAtlas> 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;
|
||||
|
||||
@ -516,11 +516,12 @@ std::shared_ptr<GlyphAtlas> 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,
|
||||
|
||||
@ -10,7 +10,6 @@
|
||||
#include <optional>
|
||||
#include <unordered_map>
|
||||
|
||||
#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,
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user