From 3b32bd6a723798e6bd9a67194d46e702e3200cc7 Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Sun, 1 Feb 2015 00:39:36 -0800 Subject: [PATCH] Teach SkyShell how to draw with Ganesh This CL adds support to SkyShell for drawing with Ganesh. Currently, we don't actually create any SkPictures to draw, but that will come in a later CL. R=eseidel@chromium.org Review URL: https://codereview.chromium.org/891143002 --- shell/BUILD.gn | 10 ++++-- shell/gpu/ganesh_context.cc | 42 ++++++++++++++++++++++ shell/gpu/ganesh_context.h | 37 +++++++++++++++++++ shell/gpu/ganesh_surface.cc | 30 ++++++++++++++++ shell/gpu/ganesh_surface.h | 39 ++++++++++++++++++++ shell/gpu/rasterizer.cc | 71 +++++++++++++++++++++++++++++++++++++ shell/gpu/rasterizer.h | 56 +++++++++++++++++++++++++++++ shell/gpu_driver.cc | 44 ----------------------- shell/gpu_driver.h | 43 ---------------------- shell/shell.cc | 4 +-- shell/shell.h | 4 +-- 11 files changed, 287 insertions(+), 93 deletions(-) create mode 100644 shell/gpu/ganesh_context.cc create mode 100644 shell/gpu/ganesh_context.h create mode 100644 shell/gpu/ganesh_surface.cc create mode 100644 shell/gpu/ganesh_surface.h create mode 100644 shell/gpu/rasterizer.cc create mode 100644 shell/gpu/rasterizer.h delete mode 100644 shell/gpu_driver.cc delete mode 100644 shell/gpu_driver.h diff --git a/shell/BUILD.gn b/shell/BUILD.gn index 80c894f3f3e..3494b85863d 100644 --- a/shell/BUILD.gn +++ b/shell/BUILD.gn @@ -23,8 +23,12 @@ generate_jni("jni_headers") { shared_library("sky_shell") { sources = [ - "gpu_driver.cc", - "gpu_driver.h", + "gpu/ganesh_context.cc", + "gpu/ganesh_context.h", + "gpu/ganesh_surface.cc", + "gpu/ganesh_surface.h", + "gpu/rasterizer.cc", + "gpu/rasterizer.h", "library_loader.cc", "shell.cc", "shell.h", @@ -39,6 +43,8 @@ shared_library("sky_shell") { deps = [ "//base", "//build/config/sanitizers:deps", + "//skia", + "//ui/gfx/geometry", "//ui/gl", ":jni_headers", ] diff --git a/shell/gpu/ganesh_context.cc b/shell/gpu/ganesh_context.cc new file mode 100644 index 00000000000..77833b34c76 --- /dev/null +++ b/shell/gpu/ganesh_context.cc @@ -0,0 +1,42 @@ +// 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 "sky/shell/gpu/ganesh_context.h" + +#include "base/logging.h" +#include "third_party/skia/include/gpu/gl/GrGLInterface.h" +#include "ui/gl/gl_bindings_skia_in_process.h" + +namespace sky { +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 + +GaneshContext::GaneshContext(scoped_refptr gl_context) + : gl_context_(gl_context) { + skia::RefPtr interface = + skia::AdoptRef(gfx::CreateInProcessSkiaGLBinding()); + DCHECK(interface); + + gr_context_ = skia::AdoptRef(GrContext::Create( + kOpenGL_GrBackend, reinterpret_cast(interface.get()))); + DCHECK(gr_context_); + gr_context_->setResourceCacheLimits(kMaxGaneshResourceCacheCount, + kMaxGaneshResourceCacheBytes); +} + +GaneshContext::~GaneshContext() { +} + +} // namespace shell +} // namespace sky diff --git a/shell/gpu/ganesh_context.h b/shell/gpu/ganesh_context.h new file mode 100644 index 00000000000..b35158ed3ec --- /dev/null +++ b/shell/gpu/ganesh_context.h @@ -0,0 +1,37 @@ +// 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 SKY_SHELL_GPU_GANESH_CONTEXT_H_ +#define SKY_SHELL_GPU_GANESH_CONTEXT_H_ + +#include "base/basictypes.h" +#include "base/memory/ref_counted.h" +#include "skia/ext/refptr.h" +#include "third_party/skia/include/gpu/GrContext.h" +#include "ui/gl/gl_context.h" + +namespace sky { +namespace shell { + +// GaneshContext holds the top-level context object for Ganesh (known as +// GrContext). We construct the GrContext using the OpenGL interface provided by +// gfx::GLContext. +class GaneshContext { + public: + explicit GaneshContext(scoped_refptr gl_context); + ~GaneshContext(); + + GrContext* gr() const { return gr_context_.get(); } + + private: + scoped_refptr gl_context_; + skia::RefPtr gr_context_; + + DISALLOW_COPY_AND_ASSIGN(GaneshContext); +}; + +} // namespace shell +} // namespace sky + +#endif // SKY_SHELL_GPU_GANESH_CONTEXT_H_ diff --git a/shell/gpu/ganesh_surface.cc b/shell/gpu/ganesh_surface.cc new file mode 100644 index 00000000000..fb15738d374 --- /dev/null +++ b/shell/gpu/ganesh_surface.cc @@ -0,0 +1,30 @@ +// 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 "sky/shell/gpu/ganesh_surface.h" + +#include "base/logging.h" +#include "third_party/skia/include/gpu/GrContext.h" + +namespace sky { +namespace shell { + +GaneshSurface::GaneshSurface(GaneshContext* context, const gfx::Size& size) { + GrBackendRenderTargetDesc desc; + desc.fWidth = size.width(); + desc.fHeight = size.height(); + desc.fConfig = kSkia8888_GrPixelConfig; + desc.fOrigin = kTopLeft_GrSurfaceOrigin; + + auto target = skia::AdoptRef(context->gr()->wrapBackendRenderTarget(desc)); + DCHECK(target); + surface_ = skia::AdoptRef(SkSurface::NewRenderTargetDirect(target.get())); + DCHECK(surface_); +} + +GaneshSurface::~GaneshSurface() { +} + +} // namespace shell +} // namespace sky diff --git a/shell/gpu/ganesh_surface.h b/shell/gpu/ganesh_surface.h new file mode 100644 index 00000000000..9a6ef1490fd --- /dev/null +++ b/shell/gpu/ganesh_surface.h @@ -0,0 +1,39 @@ +// 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 SKY_SHELL_GPU_GANESH_SURFACE_H_ +#define SKY_SHELL_GPU_GANESH_SURFACE_H_ + +#include "base/memory/scoped_ptr.h" +#include "skia/ext/refptr.h" +#include "sky/shell/gpu/ganesh_context.h" +#include "third_party/skia/include/core/SkSurface.h" +#include "ui/gfx/geometry/size.h" + +namespace sky { +namespace shell { + +// GaneshSurface holds an SkSurface configured to render with Ganesh. Using the +// provided GaneshContext, GaneshSurface wraps an SkSurface around FBO 0 so that +// you can use |canvas()| to draw to FBO 0. +class GaneshSurface { + public: + GaneshSurface(GaneshContext* context, const gfx::Size& size); + ~GaneshSurface(); + + SkCanvas* canvas() const { return surface_->getCanvas(); } + gfx::Size size() const { + return gfx::Size(surface_->width(), surface_->height()); + } + + private: + skia::RefPtr surface_; + + DISALLOW_COPY_AND_ASSIGN(GaneshSurface); +}; + +} // namespace shell +} // namespace sky + +#endif // SKY_SHELL_GPU_GANESH_SURFACE_H_ diff --git a/shell/gpu/rasterizer.cc b/shell/gpu/rasterizer.cc new file mode 100644 index 00000000000..8e4b49282e3 --- /dev/null +++ b/shell/gpu/rasterizer.cc @@ -0,0 +1,71 @@ +// 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 "sky/shell/gpu/rasterizer.h" + +#include "sky/shell/gpu/ganesh_context.h" +#include "sky/shell/gpu/ganesh_surface.h" +#include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkPicture.h" +#include "ui/gl/gl_bindings.h" +#include "ui/gl/gl_context.h" +#include "ui/gl/gl_share_group.h" +#include "ui/gl/gl_surface.h" + +namespace sky { +namespace shell { +namespace { + +gfx::Size GetSize(SkPicture* picture) { + const SkRect& rect = picture->cullRect(); + return gfx::Size(rect.width(), rect.height()); +} + +} // namespace + +Rasterizer::Rasterizer() : weak_factory_(this) { +} + +Rasterizer::~Rasterizer() { +} + +base::WeakPtr Rasterizer::GetWeakPtr() { + return weak_factory_.GetWeakPtr(); +} + +void Rasterizer::Init(gfx::AcceleratedWidget widget) { + share_group_ = make_scoped_refptr(new gfx::GLShareGroup()); + surface_ = gfx::GLSurface::CreateViewGLSurface(widget); + CHECK(surface_) << "GLSurface required."; + CHECK(CreateGLContext()) << "GLContext required."; +} + +void Rasterizer::Draw(skia::RefPtr picture) { + // TODO(abarth): We should handle losing the GL context. + CHECK(context_->MakeCurrent(surface_.get())); + EnsureGaneshSurface(GetSize(picture.get())); + + SkCanvas* canvas = ganesh_surface_->canvas(); + canvas->drawPicture(picture.get()); + canvas->flush(); + + surface_->SwapBuffers(); +} + +bool Rasterizer::CreateGLContext() { + context_ = gfx::GLContext::CreateGLContext(share_group_.get(), surface_.get(), + gfx::PreferIntegratedGpu); + if (!context_) + return false; + ganesh_context_.reset(new GaneshContext(context_.get())); + return true; +} + +void Rasterizer::EnsureGaneshSurface(const gfx::Size& size) { + if (!ganesh_surface_ || ganesh_surface_->size() != size) + ganesh_surface_.reset(new GaneshSurface(ganesh_context_.get(), size)); +} + +} // namespace shell +} // namespace sky diff --git a/shell/gpu/rasterizer.h b/shell/gpu/rasterizer.h new file mode 100644 index 00000000000..302e38d9e3c --- /dev/null +++ b/shell/gpu/rasterizer.h @@ -0,0 +1,56 @@ +// 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 SKY_SHELL_GPU_RASTERIZER_H_ +#define SKY_SHELL_GPU_RASTERIZER_H_ + +#include "base/memory/ref_counted.h" +#include "base/memory/weak_ptr.h" +#include "skia/ext/refptr.h" +#include "ui/gfx/geometry/size.h" +#include "ui/gfx/native_widget_types.h" + +class SkPicture; + +namespace gfx { +class GLContext; +class GLShareGroup; +class GLSurface; +} + +namespace sky { +namespace shell { +class GaneshContext; +class GaneshSurface; + +class Rasterizer { + public: + explicit Rasterizer(); + ~Rasterizer(); + + base::WeakPtr GetWeakPtr(); + + void Init(gfx::AcceleratedWidget widget); + void Draw(skia::RefPtr picture); + + private: + bool CreateGLContext(); + void EnsureGaneshSurface(const gfx::Size& size); + + scoped_refptr share_group_; + scoped_refptr surface_; + scoped_refptr context_; + + scoped_ptr ganesh_context_; + scoped_ptr ganesh_surface_; + + base::WeakPtrFactory weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(Rasterizer); +}; + +} // namespace shell +} // namespace sky + +#endif // SKY_SHELL_GPU_RASTERIZER_H_ diff --git a/shell/gpu_driver.cc b/shell/gpu_driver.cc deleted file mode 100644 index 3101f8e1137..00000000000 --- a/shell/gpu_driver.cc +++ /dev/null @@ -1,44 +0,0 @@ -// 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 "sky/shell/gpu_driver.h" - -#include "ui/gl/gl_bindings.h" -#include "ui/gl/gl_context.h" -#include "ui/gl/gl_share_group.h" -#include "ui/gl/gl_surface.h" - -namespace sky { -namespace shell { - -GPUDriver::GPUDriver() : weak_factory_(this) { -} - -GPUDriver::~GPUDriver() { -} - -base::WeakPtr GPUDriver::GetWeakPtr() { - return weak_factory_.GetWeakPtr(); -} - -void GPUDriver::Init(gfx::AcceleratedWidget widget) { - share_group_ = make_scoped_refptr(new gfx::GLShareGroup()); - - surface_ = gfx::GLSurface::CreateViewGLSurface(widget); - CHECK(surface_) << "GLSurface required."; - - context_ = gfx::GLContext::CreateGLContext(share_group_.get(), surface_.get(), - gfx::PreferIntegratedGpu); - CHECK(context_) << "GLContext required."; - - CHECK(context_->MakeCurrent(surface_.get())); - - glClearColor(0.0, 1.0, 0.0, 0.0); - glClear(GL_COLOR_BUFFER_BIT); - - surface_->SwapBuffers(); -} - -} // namespace shell -} // namespace sky diff --git a/shell/gpu_driver.h b/shell/gpu_driver.h deleted file mode 100644 index 5201dcbaf24..00000000000 --- a/shell/gpu_driver.h +++ /dev/null @@ -1,43 +0,0 @@ -// 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 SKY_SHELL_GPU_DRIVER_H_ -#define SKY_SHELL_GPU_DRIVER_H_ - -#include "base/memory/ref_counted.h" -#include "base/memory/weak_ptr.h" -#include "ui/gfx/native_widget_types.h" - -namespace gfx { -class GLContext; -class GLShareGroup; -class GLSurface; -} - -namespace sky { -namespace shell { - -class GPUDriver { - public: - explicit GPUDriver(); - ~GPUDriver(); - - base::WeakPtr GetWeakPtr(); - - void Init(gfx::AcceleratedWidget widget); - - private: - scoped_refptr share_group_; - scoped_refptr surface_; - scoped_refptr context_; - - base::WeakPtrFactory weak_factory_; - - DISALLOW_COPY_AND_ASSIGN(GPUDriver); -}; - -} // namespace shell -} // namespace sky - -#endif // SKY_SHELL_GPU_DRIVER_H_ diff --git a/shell/shell.cc b/shell/shell.cc index 3a465d008fa..757a9e91c2e 100644 --- a/shell/shell.cc +++ b/shell/shell.cc @@ -22,7 +22,7 @@ Shell::~Shell() { void Shell::Init() { gpu_thread_.reset(new base::Thread("gpu_thread")); gpu_thread_->Start(); - gpu_driver_.reset(new GPUDriver()); + rasterizer_.reset(new Rasterizer()); view_.reset(new SkyView(this)); view_->Init(); @@ -31,7 +31,7 @@ void Shell::Init() { void Shell::OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget) { gpu_thread_->message_loop()->PostTask( FROM_HERE, - base::Bind(&GPUDriver::Init, gpu_driver_->GetWeakPtr(), widget)); + base::Bind(&Rasterizer::Init, rasterizer_->GetWeakPtr(), widget)); } void Shell::OnDestroyed() { diff --git a/shell/shell.h b/shell/shell.h index fdf65f959a2..eb69f669b06 100644 --- a/shell/shell.h +++ b/shell/shell.h @@ -8,7 +8,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" -#include "sky/shell/gpu_driver.h" +#include "sky/shell/gpu/rasterizer.h" #include "sky/shell/sky_view.h" namespace base { @@ -35,7 +35,7 @@ class Shell : public SkyView::Delegate { scoped_ptr gpu_thread_; scoped_ptr view_; - scoped_ptr gpu_driver_; + scoped_ptr rasterizer_; DISALLOW_COPY_AND_ASSIGN(Shell); };