blob: def57908b467117d542e83a1eb3c894845f1cc19 [file] [log] [blame]
// 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 "flutter/display_list/testing/dl_test_surface_metal.h"
#include "flutter/impeller/display_list/dl_dispatcher.h"
#include "flutter/impeller/display_list/dl_image_impeller.h"
#include "flutter/impeller/typographer/backends/skia/typographer_context_skia.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkSurface.h"
namespace flutter {
namespace testing {
class DlMetalSurfaceInstance : public DlSurfaceInstance {
public:
explicit DlMetalSurfaceInstance(
std::unique_ptr<TestMetalSurface> metal_surface)
: metal_surface_(std::move(metal_surface)) {}
~DlMetalSurfaceInstance() = default;
sk_sp<SkSurface> sk_surface() const override {
return metal_surface_->GetSurface();
}
private:
std::unique_ptr<TestMetalSurface> metal_surface_;
};
bool DlMetalSurfaceProvider::InitializeSurface(size_t width,
size_t height,
PixelFormat format) {
if (format != kN32PremulPixelFormat) {
return false;
}
metal_context_ = std::make_unique<TestMetalContext>();
metal_surface_ = MakeOffscreenSurface(width, height, format);
return true;
}
std::shared_ptr<DlSurfaceInstance> DlMetalSurfaceProvider::GetPrimarySurface()
const {
if (!metal_surface_) {
return nullptr;
}
return metal_surface_;
}
std::shared_ptr<DlSurfaceInstance> DlMetalSurfaceProvider::MakeOffscreenSurface(
size_t width,
size_t height,
PixelFormat format) const {
auto surface =
TestMetalSurface::Create(*metal_context_, SkISize::Make(width, height));
surface->GetSurface()->getCanvas()->clear(SK_ColorTRANSPARENT);
return std::make_shared<DlMetalSurfaceInstance>(std::move(surface));
}
class DlMetalPixelData : public DlPixelData {
public:
explicit DlMetalPixelData(
std::unique_ptr<impeller::testing::Screenshot> screenshot)
: screenshot_(std::move(screenshot)),
addr_(reinterpret_cast<const uint32_t*>(screenshot_->GetBytes())),
ints_per_row_(screenshot_->GetBytesPerRow() / 4) {
FML_DCHECK(screenshot_->GetBytesPerRow() == ints_per_row_ * 4);
}
~DlMetalPixelData() override = default;
const uint32_t* addr32(int x, int y) const override {
return addr_ + (y * ints_per_row_) + x;
}
size_t width() const override { return screenshot_->GetWidth(); }
size_t height() const override { return screenshot_->GetHeight(); }
void write(const std::string& path) const override {
screenshot_->WriteToPNG(path);
}
private:
std::unique_ptr<impeller::testing::Screenshot> screenshot_;
const uint32_t* addr_;
const uint32_t ints_per_row_;
};
sk_sp<DlPixelData> DlMetalSurfaceProvider::ImpellerSnapshot(
const sk_sp<DisplayList>& list,
int width,
int height) const {
InitScreenShotter();
impeller::DlDispatcher dispatcher;
dispatcher.drawColor(flutter::DlColor::kTransparent(),
flutter::DlBlendMode::kSrc);
list->Dispatch(dispatcher);
auto picture = dispatcher.EndRecordingAsPicture();
return sk_make_sp<DlMetalPixelData>(snapshotter_->MakeScreenshot(
*aiks_context_, picture, {width, height}, false));
}
sk_sp<DlImage> DlMetalSurfaceProvider::MakeImpellerImage(
const sk_sp<DisplayList>& list,
int width,
int height) const {
InitScreenShotter();
impeller::DlDispatcher dispatcher;
dispatcher.drawColor(flutter::DlColor::kTransparent(),
flutter::DlBlendMode::kSrc);
list->Dispatch(dispatcher);
auto picture = dispatcher.EndRecordingAsPicture();
std::shared_ptr<impeller::Image> image =
picture.ToImage(*aiks_context_, {width, height});
std::shared_ptr<impeller::Texture> texture = image->GetTexture();
return impeller::DlImageImpeller::Make(texture);
}
void DlMetalSurfaceProvider::InitScreenShotter() const {
if (!snapshotter_) {
snapshotter_.reset(new MetalScreenshotter(/*enable_wide_gamut=*/false));
auto typographer = impeller::TypographerContextSkia::Make();
aiks_context_.reset(new impeller::AiksContext(
snapshotter_->GetPlayground().GetContext(), typographer));
}
}
} // namespace testing
} // namespace flutter