Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
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
[Impeller] write glyphs to malloc buffer.
  • Loading branch information
jonahwilliams committed May 20, 2024
commit 23c851f51c6793ca8f0ffaf2610f0c7cf4ccfd7d
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