blob: 6c64e25942e5e7056115ced734d1812a2b034068 [file] [log] [blame]
// Copyright 2015 The Chromium 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 "gpu_rasterizer.h"
#include <string>
#include <utility>
#include "flutter/common/threads.h"
#include "flutter/glue/trace_event.h"
#include "flutter/shell/common/picture_serializer.h"
#include "flutter/shell/common/platform_view.h"
#include "flutter/shell/common/shell.h"
#include "third_party/skia/include/core/SkPicture.h"
namespace shell {
GPURasterizer::GPURasterizer(std::unique_ptr<flow::ProcessInfo> info)
: compositor_context_(std::move(info)), weak_factory_(this) {
auto weak_ptr = weak_factory_.GetWeakPtr();
blink::Threads::Gpu()->PostTask(
[weak_ptr]() { Shell::Shared().AddRasterizer(weak_ptr); });
}
GPURasterizer::~GPURasterizer() {
weak_factory_.InvalidateWeakPtrs();
Shell::Shared().PurgeRasterizers();
}
ftl::WeakPtr<Rasterizer> GPURasterizer::GetWeakRasterizerPtr() {
return weak_factory_.GetWeakPtr();
}
void GPURasterizer::Setup(std::unique_ptr<Surface> surface,
ftl::Closure continuation,
ftl::AutoResetWaitableEvent* setup_completion_event) {
surface_ = std::move(surface);
continuation();
setup_completion_event->Signal();
}
void GPURasterizer::Clear(SkColor color, const SkISize& size) {
if (surface_ == nullptr) {
return;
}
auto frame = surface_->AcquireFrame(size);
if (frame == nullptr) {
return;
}
SkCanvas* canvas = frame->SkiaCanvas();
if (canvas == nullptr) {
return;
}
canvas->clear(color);
frame->Submit();
}
void GPURasterizer::Teardown(
ftl::AutoResetWaitableEvent* teardown_completion_event) {
if (surface_) {
surface_.reset();
}
last_layer_tree_.reset();
compositor_context_.OnGrContextDestroyed();
teardown_completion_event->Signal();
}
flow::LayerTree* GPURasterizer::GetLastLayerTree() {
return last_layer_tree_.get();
}
void GPURasterizer::Draw(
ftl::RefPtr<flutter::Pipeline<flow::LayerTree>> pipeline) {
TRACE_EVENT0("flutter", "GPURasterizer::Draw");
flutter::Pipeline<flow::LayerTree>::Consumer consumer =
std::bind(&GPURasterizer::DoDraw, this, std::placeholders::_1);
// Consume as many pipeline items as possible. But yield the event loop
// between successive tries.
switch (pipeline->Consume(consumer)) {
case flutter::PipelineConsumeResult::MoreAvailable: {
auto weak_this = weak_factory_.GetWeakPtr();
blink::Threads::Gpu()->PostTask([weak_this, pipeline]() {
if (weak_this) {
weak_this->Draw(pipeline);
}
});
break;
}
default:
break;
}
}
void GPURasterizer::DoDraw(std::unique_ptr<flow::LayerTree> layer_tree) {
if (!layer_tree || !surface_) {
return;
}
// There is no way for the compositor to know how long the layer tree
// construction took. Fortunately, the layer tree does. Grab that time
// for instrumentation.
compositor_context_.engine_time().SetLapTime(layer_tree->construction_time());
DrawToSurface(*layer_tree);
last_layer_tree_ = std::move(layer_tree);
}
void GPURasterizer::DrawToSurface(flow::LayerTree& layer_tree) {
auto frame = surface_->AcquireFrame(layer_tree.frame_size());
if (frame == nullptr) {
return;
}
auto canvas = frame->SkiaCanvas();
if (canvas == nullptr) {
return;
}
auto compositor_frame =
compositor_context_.AcquireFrame(surface_->GetContext(), canvas);
canvas->clear(SK_ColorBLACK);
layer_tree.Raster(compositor_frame);
frame->Submit();
}
} // namespace shell