Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

[Impeller] write glyphs to malloc buffer. #52937

Merged
merged 1 commit into from
May 20, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 11 additions & 54 deletions impeller/typographer/backends/skia/typographer_context_skia.cc
Original file line number Diff line number Diff line change
Expand Up @@ -46,56 +46,6 @@ namespace impeller {
// https://github.com/flutter/flutter/issues/114563
constexpr auto kPadding = 2;

namespace {

class HostBufferAllocator : public SkBitmap::Allocator {
public:
explicit HostBufferAllocator(HostBuffer& host_buffer)
: host_buffer_(host_buffer) {}

[[nodiscard]] BufferView TakeBufferView() {
buffer_view_.buffer->Flush();
return std::move(buffer_view_);
}

// |SkBitmap::Allocator|
bool allocPixelRef(SkBitmap* bitmap) override {
if (!bitmap) {
return false;
}
const SkImageInfo& info = bitmap->info();
if (kUnknown_SkColorType == info.colorType() || info.width() < 0 ||
info.height() < 0 || !info.validRowBytes(bitmap->rowBytes())) {
return false;
}

size_t required_bytes = bitmap->rowBytes() * bitmap->height();
BufferView buffer_view = host_buffer_.Emplace(nullptr, required_bytes,
DefaultUniformAlignment());

// The impeller host buffer is not cleared between frames and may contain
// stale data. The Skia software canvas does not write to pixels without
// any contents, which causes this data to leak through.
::memset(buffer_view.buffer->OnGetContents() + buffer_view.range.offset, 0,
required_bytes);

auto pixel_ref = sk_sp<SkPixelRef>(new SkPixelRef(
info.width(), info.height(),
buffer_view.buffer->OnGetContents() + buffer_view.range.offset,
bitmap->rowBytes()));

bitmap->setPixelRef(std::move(pixel_ref), 0, 0);
buffer_view_ = std::move(buffer_view);
return true;
}

private:
BufferView buffer_view_;
HostBuffer& host_buffer_;
};

} // namespace

std::shared_ptr<TypographerContext> TypographerContextSkia::Make() {
return std::make_shared<TypographerContextSkia>();
}
Expand Down Expand Up @@ -282,9 +232,8 @@ static bool UpdateAtlasBitmap(const GlyphAtlas& atlas,
}

SkBitmap bitmap;
HostBufferAllocator allocator(host_buffer);
bitmap.setInfo(GetImageInfo(atlas, size));
if (!bitmap.tryAllocPixels(&allocator)) {
if (!bitmap.tryAllocPixels()) {
return false;
}
auto surface = SkSurfaces::WrapPixels(bitmap.pixmap());
Expand All @@ -298,11 +247,19 @@ static bool UpdateAtlasBitmap(const GlyphAtlas& atlas,

DrawGlyph(canvas, pair.scaled_font, pair.glyph, has_color);

// Writing to a malloc'd buffer and then copying to the staging buffers
// benchmarks as substantially faster on a number of Android devices.
BufferView buffer_view = host_buffer.Emplace(
bitmap.getAddr(0, 0),
size.Area() * BytesPerPixelForPixelFormat(
atlas.GetTexture()->GetTextureDescriptor().format),
DefaultUniformAlignment());

// convert_to_read is set to false so that the texture remains in a transfer
// dst layout until we finish writing to it below. This only has an impact
// on Vulkan where we are responsible for managing image layouts.
if (!blit_pass->AddCopy(allocator.TakeBufferView(), //
texture, //
if (!blit_pass->AddCopy(std::move(buffer_view), //
texture, //
IRect::MakeXYWH(pos->GetLeft(), pos->GetTop(),
size.width, size.height), //
/*label=*/"", //
Expand Down