提交 2d585bc4 编写于 作者: C Chinmay Garde 提交者: GitHub

Extract a common interface out of GaneshCanvas (into GPUCanvas) that can also...

Extract a common interface out of GaneshCanvas (into GPUCanvas) that can also be used for the Vulkan canvas. (#3058)
上级 f5683b99
......@@ -4,8 +4,6 @@
source_set("gpu") {
sources = [
"ganesh_canvas.cc",
"ganesh_canvas.h",
"gpu_canvas.cc",
"gpu_canvas.h",
"gpu_canvas_gl.cc",
......
// 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 "flutter/shell/gpu/ganesh_canvas.h"
#include "flutter/flow/gl_connection.h"
#include "lib/ftl/arraysize.h"
#include "lib/ftl/logging.h"
#include "third_party/skia/include/gpu/gl/GrGLInterface.h"
namespace shell {
namespace {
// The limit of the number of GPU resources we hold in the GrContext's
// GPU cache.
const int kMaxGaneshResourceCacheCount = 2048;
// The limit of the bytes allocated toward GPU resources in the GrContext's
// GPU cache.
const size_t kMaxGaneshResourceCacheBytes = 96 * 1024 * 1024;
} // namespace
GaneshCanvas::GaneshCanvas() {}
GaneshCanvas::~GaneshCanvas() {}
bool GaneshCanvas::SetupGrGLInterface() {
sk_surface_ = nullptr;
gr_context_ = sk_sp<GrContext>(GrContext::Create(
kOpenGL_GrBackend,
reinterpret_cast<GrBackendContext>(GrGLCreateNativeInterface())));
if (gr_context_ == nullptr) {
flow::GLConnection connection;
FTL_LOG(INFO) << "Failed to setup GL context. Aborting.";
FTL_LOG(INFO) << connection.Description();
}
if (!gr_context_)
return false;
gr_context_->setResourceCacheLimits(kMaxGaneshResourceCacheCount,
kMaxGaneshResourceCacheBytes);
return true;
}
bool GaneshCanvas::SelectPixelConfig(GrPixelConfig* config) {
static const GrPixelConfig kConfigOptions[] = {
kSkia8888_GrPixelConfig, kRGBA_4444_GrPixelConfig,
};
for (size_t i = 0; i < arraysize(kConfigOptions); i++) {
if (gr_context_->caps()->isConfigRenderable(kConfigOptions[i], false)) {
*config = kConfigOptions[i];
return true;
}
}
return false;
}
SkCanvas* GaneshCanvas::GetCanvas(int32_t fbo, const SkISize& size) {
FTL_DCHECK(IsValid());
if (sk_surface_ && sk_surface_->width() == size.width() &&
sk_surface_->height() == size.height())
return sk_surface_->getCanvas();
GrBackendRenderTargetDesc desc;
desc.fWidth = size.width();
desc.fHeight = size.height();
FTL_CHECK(SelectPixelConfig(&desc.fConfig));
desc.fStencilBits = 8;
desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
desc.fRenderTargetHandle = fbo;
sk_surface_ =
SkSurface::MakeFromBackendRenderTarget(gr_context_.get(), desc, nullptr);
FTL_DCHECK(sk_surface_);
return sk_surface_->getCanvas();
}
bool GaneshCanvas::IsValid() {
return gr_context_;
}
} // namespace shell
// 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.
#ifndef SHELL_GPU_DIRECT_GANESH_CANVAS_H_
#define SHELL_GPU_DIRECT_GANESH_CANVAS_H_
#include "lib/ftl/macros.h"
#include "third_party/skia/include/core/SkSize.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/gpu/gl/GrGLInterface.h"
#include "third_party/skia/include/gpu/gl/GrGLInterface.h"
#include "third_party/skia/include/gpu/GrContext.h"
namespace shell {
class GaneshCanvas {
public:
GaneshCanvas();
~GaneshCanvas();
bool SetupGrGLInterface();
SkCanvas* GetCanvas(int32_t fbo, const SkISize& size);
bool IsValid();
GrContext* gr_context() { return gr_context_.get(); }
private:
bool SelectPixelConfig(GrPixelConfig* config);
sk_sp<GrContext> gr_context_;
sk_sp<SkSurface> sk_surface_;
FTL_DISALLOW_COPY_AND_ASSIGN(GaneshCanvas);
};
} // namespace shell
#endif // SHELL_GPU_DIRECT_GANESH_CANVAS_H_
......@@ -3,9 +3,23 @@
// found in the LICENSE file.
#include "gpu_canvas.h"
#include "gpu_canvas_gl.h"
#include "gpu_canvas_vulkan.h"
namespace shell {
//
GPUCanvas::~GPUCanvas() = default;
std::unique_ptr<GPUCanvas> GPUCanvas::CreatePlatformCanvas(
const PlatformView& platform_view) {
std::unique_ptr<GPUCanvas> canvas;
// TODO: Vulkan capability detection will be added here to return a differnt
// canvas instance.
canvas.reset(new GPUCanvasGL(platform_view.DefaultFramebuffer()));
return canvas;
}
} // namespace shell
......@@ -5,11 +5,29 @@
#ifndef SHELL_GPU_GPU_CANVAS_H_
#define SHELL_GPU_GPU_CANVAS_H_
#include "flutter/shell/common/platform_view.h"
#include "lib/ftl/macros.h"
#include "lib/ftl/compiler_specific.h"
#include "third_party/skia/include/core/SkCanvas.h"
namespace shell {
//
class GPUCanvas {
public:
static std::unique_ptr<GPUCanvas> CreatePlatformCanvas(
const PlatformView& platform_view);
virtual ~GPUCanvas();
FTL_WARN_UNUSED_RESULT
virtual bool Setup() = 0;
virtual bool IsValid() = 0;
virtual SkCanvas* AcquireCanvas(const SkISize& size) = 0;
virtual GrContext* GetContext() = 0;
};
} // namespace shell
......
......@@ -4,8 +4,119 @@
#include "gpu_canvas_gl.h"
#include "lib/ftl/arraysize.h"
#include "lib/ftl/logging.h"
#include "flutter/flow/gl_connection.h"
#include "third_party/skia/include/gpu/GrContext.h"
#include "third_party/skia/include/gpu/gl/GrGLInterface.h"
#include "third_party/skia/include/core/SkSurface.h"
namespace shell {
//
// The limit of the number of GPU resources we hold in the GrContext's
// GPU cache.
static const int kMaxGaneshResourceCacheCount = 2048;
// The limit of the bytes allocated toward GPU resources in the GrContext's
// GPU cache.
static const size_t kMaxGaneshResourceCacheBytes = 96 * 1024 * 1024;
GPUCanvasGL::GPUCanvasGL(intptr_t fbo) : fbo_(fbo) {}
GPUCanvasGL::~GPUCanvasGL() = default;
bool GPUCanvasGL::Setup() {
if (context_ != nullptr) {
// Already setup.
return false;
}
auto backend_context =
reinterpret_cast<GrBackendContext>(GrGLCreateNativeInterface());
context_ =
sk_sp<GrContext>(GrContext::Create(kOpenGL_GrBackend, backend_context));
if (context_ == nullptr) {
flow::GLConnection connection;
FTL_LOG(INFO) << "Failed to setup GL context. Aborting.";
FTL_LOG(INFO) << connection.Description();
}
context_->setResourceCacheLimits(kMaxGaneshResourceCacheCount,
kMaxGaneshResourceCacheBytes);
return true;
}
bool GPUCanvasGL::IsValid() {
return context_ != nullptr;
}
SkCanvas* GPUCanvasGL::AcquireCanvas(const SkISize& size) {
auto surface = AcquireSurface(size);
if (surface == nullptr) {
return nullptr;
}
return surface->getCanvas();
}
bool GPUCanvasGL::SelectPixelConfig(GrPixelConfig* config) {
static const GrPixelConfig kConfigOptions[] = {
kSkia8888_GrPixelConfig, kRGBA_4444_GrPixelConfig,
};
for (size_t i = 0; i < arraysize(kConfigOptions); i++) {
if (context_->caps()->isConfigRenderable(kConfigOptions[i], false)) {
*config = kConfigOptions[i];
return true;
}
}
return false;
}
sk_sp<SkSurface> GPUCanvasGL::CreateSurface(const SkISize& size) {
if (context_ == nullptr) {
return nullptr;
}
GrBackendRenderTargetDesc desc;
if (!SelectPixelConfig(&desc.fConfig)) {
return nullptr;
}
desc.fWidth = size.width();
desc.fHeight = size.height();
desc.fStencilBits = 8;
desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
desc.fRenderTargetHandle = fbo_;
return SkSurface::MakeFromBackendRenderTarget(context_.get(), desc, nullptr);
}
sk_sp<SkSurface> GPUCanvasGL::AcquireSurface(const SkISize& size) {
// There is no cached surface.
if (cached_surface_ == nullptr) {
cached_surface_ = CreateSurface(size);
return cached_surface_;
}
// There is a surface previously created of the same size.
if (cached_surface_->width() == size.width() &&
cached_surface_->height() == size.height()) {
return cached_surface_;
}
cached_surface_ = CreateSurface(size);
return cached_surface_;
}
GrContext* GPUCanvasGL::GetContext() {
return context_.get();
}
} // namespace shell
......@@ -6,10 +6,37 @@
#define SHELL_GPU_GPU_CANVAS_GL_H_
#include "lib/ftl/macros.h"
#include "gpu_canvas.h"
namespace shell {
//
class GPUCanvasGL : public GPUCanvas {
public:
GPUCanvasGL(intptr_t fbo);
~GPUCanvasGL() override;
bool Setup() override;
bool IsValid() override;
SkCanvas* AcquireCanvas(const SkISize& size) override;
GrContext* GetContext() override;
private:
intptr_t fbo_;
sk_sp<GrContext> context_;
sk_sp<SkSurface> cached_surface_;
sk_sp<SkSurface> CreateSurface(const SkISize& size);
sk_sp<SkSurface> AcquireSurface(const SkISize& size);
bool SelectPixelConfig(GrPixelConfig* config);
FTL_DISALLOW_COPY_AND_ASSIGN(GPUCanvasGL);
};
} // namespace shell
......
......@@ -37,39 +37,56 @@ ftl::WeakPtr<Rasterizer> GPURasterizer::GetWeakRasterizerPtr() {
return weak_factory_.GetWeakPtr();
}
void GPURasterizer::Setup(PlatformView* platform_view,
ftl::Closure continuation,
ftl::AutoResetWaitableEvent* setup_completion_event) {
FTL_CHECK(platform_view) << "Must be able to acquire the view.";
bool GPURasterizer::Setup(PlatformView* platform_view) {
if (platform_view == nullptr) {
return false;
}
// The context needs to be made current before the GrGL interface can be
// setup.
bool success = platform_view->ContextMakeCurrent();
if (success) {
success = ganesh_canvas_.SetupGrGLInterface();
if (!success)
FTL_LOG(ERROR) << "Could not create the GL interface";
} else {
FTL_LOG(ERROR) << "Could not make the context current for initial GL setup";
if (!platform_view->ContextMakeCurrent()) {
return false;
}
if (success) {
platform_view_ = platform_view;
} else {
FTL_LOG(ERROR)
<< "WARNING: Flutter will be unable to render to the display";
auto gpu_canvas = GPUCanvas::CreatePlatformCanvas(*platform_view);
if (gpu_canvas == nullptr) {
return false;
}
if (!gpu_canvas->Setup()) {
return false;
}
gpu_canvas_ = std::move(gpu_canvas);
platform_view_ = platform_view;
return true;
}
void GPURasterizer::Setup(PlatformView* platform_view,
ftl::Closure continuation,
ftl::AutoResetWaitableEvent* setup_completion_event) {
auto setup_result = Setup(platform_view);
FTL_CHECK(setup_result) << "Must be able to setup the GPU canvas.";
continuation();
setup_completion_event->Signal();
}
void GPURasterizer::Clear(SkColor color) {
SkCanvas* canvas = ganesh_canvas_.GetCanvas(
platform_view_->DefaultFramebuffer(), platform_view_->GetSize());
if (gpu_canvas_ == nullptr) {
return;
}
SkCanvas* canvas = gpu_canvas_->AcquireCanvas(platform_view_->GetSize());
if (canvas == nullptr) {
return;
}
canvas->clear(color);
canvas->flush();
platform_view_->SwapBuffers();
}
......@@ -113,7 +130,7 @@ void GPURasterizer::Draw(
}
void GPURasterizer::DoDraw(std::unique_ptr<flow::LayerTree> layer_tree) {
if (!layer_tree) {
if (!layer_tree || !gpu_canvas_) {
return;
}
......@@ -132,10 +149,9 @@ void GPURasterizer::DoDraw(std::unique_ptr<flow::LayerTree> layer_tree) {
}
{
SkCanvas* canvas = ganesh_canvas_.GetCanvas(
platform_view_->DefaultFramebuffer(), layer_tree->frame_size());
SkCanvas* canvas = gpu_canvas_->AcquireCanvas(layer_tree->frame_size());
flow::CompositorContext::ScopedFrame frame =
compositor_context_.AcquireFrame(ganesh_canvas_.gr_context(), *canvas);
compositor_context_.AcquireFrame(gpu_canvas_->GetContext(), *canvas);
canvas->clear(SK_ColorBLACK);
layer_tree->Raster(frame);
......
......@@ -7,7 +7,7 @@
#include "flutter/flow/compositor_context.h"
#include "flutter/shell/common/rasterizer.h"
#include "flutter/shell/gpu/ganesh_canvas.h"
#include "flutter/shell/gpu/gpu_canvas.h"
#include "lib/ftl/memory/weak_ptr.h"
#include "lib/ftl/synchronization/waitable_event.h"
......@@ -35,12 +35,15 @@ class GPURasterizer : public Rasterizer {
void Draw(ftl::RefPtr<flutter::Pipeline<flow::LayerTree>> pipeline) override;
private:
GaneshCanvas ganesh_canvas_;
std::unique_ptr<GPUCanvas> gpu_canvas_;
flow::CompositorContext compositor_context_;
std::unique_ptr<flow::LayerTree> last_layer_tree_;
PlatformView* platform_view_;
ftl::WeakPtrFactory<GPURasterizer> weak_factory_;
FTL_WARN_UNUSED_RESULT
bool Setup(PlatformView* platform_view);
void DoDraw(std::unique_ptr<flow::LayerTree> tree);
FTL_DISALLOW_COPY_AND_ASSIGN(GPURasterizer);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册