From d86eedd1aaa50956ddd03486276a6ddf962ad14b Mon Sep 17 00:00:00 2001 From: Adam Barth Date: Wed, 18 Feb 2015 13:15:36 -0800 Subject: [PATCH] Connect Sky and Ganesh in SkyShell This CL contains enough plumbing for Sky to render content to the screen using Ganesh in SkyShell. We're still missing the ability to load data off the network. R=eseidel@chromium.org, ojan@chromium.org Review URL: https://codereview.chromium.org/936883002 --- shell/BUILD.gn | 44 +++++++++++-- .../sky/shell/JavaServiceProvider.java | 47 ++++++++++++++ .../shell/{SkyView.java => PlatformView.java} | 46 ++++++------- .../src/org/domokit/sky/shell/SkyMain.java | 14 ++-- .../domokit/sky/shell/SkyShellActivity.java | 4 +- .../sky/shell/SkyShellApplication.java | 5 ++ shell/gpu/ganesh_context.cc | 2 +- shell/gpu/ganesh_surface.cc | 2 +- shell/gpu/rasterizer.cc | 23 ++++--- shell/gpu/rasterizer.h | 5 +- shell/gpu_delegate.h | 4 ++ shell/java_service_provider.cc | 23 +++++++ shell/java_service_provider.h | 20 ++++++ shell/library_loader.cc | 8 ++- shell/{sky_view.cc => platform_view.cc} | 38 ++++++----- shell/{sky_view.h => platform_view.h} | 10 +-- shell/shell.cc | 64 +++++++++++++++---- shell/shell.h | 19 ++++-- shell/sky_main.cc | 27 ++------ shell/ui/animator.cc | 59 +++++++++++++++++ shell/ui/animator.h | 38 +++++++++++ shell/ui/engine.cc | 54 ++++++++++++++-- shell/ui/engine.h | 29 +++++++-- shell/ui/platform_impl.cc | 12 +++- shell/ui/platform_impl.h | 7 +- 25 files changed, 468 insertions(+), 136 deletions(-) create mode 100644 shell/apk/src/org/domokit/sky/shell/JavaServiceProvider.java rename shell/apk/src/org/domokit/sky/shell/{SkyView.java => PlatformView.java} (57%) create mode 100644 shell/java_service_provider.cc create mode 100644 shell/java_service_provider.h rename shell/{sky_view.cc => platform_view.cc} (63%) rename shell/{sky_view.h => platform_view.h} (88%) create mode 100644 shell/ui/animator.cc create mode 100644 shell/ui/animator.h diff --git a/shell/BUILD.gn b/shell/BUILD.gn index 20ceed137fb..547ed9fc25d 100644 --- a/shell/BUILD.gn +++ b/shell/BUILD.gn @@ -15,8 +15,9 @@ group("shell") { generate_jni("jni_headers") { sources = [ + "apk/src/org/domokit/sky/shell/JavaServiceProvider.java", "apk/src/org/domokit/sky/shell/SkyMain.java", - "apk/src/org/domokit/sky/shell/SkyView.java", + "apk/src/org/domokit/sky/shell/PlatformView.java", ] jni_package = "sky/shell" } @@ -31,13 +32,17 @@ shared_library("sky_shell") { "gpu/rasterizer.h", "gpu_delegate.cc", "gpu_delegate.h", + "java_service_provider.cc", + "java_service_provider.h", "library_loader.cc", + "platform_view.cc", + "platform_view.h", "shell.cc", "shell.h", "sky_main.cc", "sky_main.h", - "sky_view.cc", - "sky_view.h", + "ui/animator.cc", + "ui/animator.h", "ui/engine.cc", "ui/engine.h", "ui/platform_impl.cc", @@ -50,7 +55,12 @@ shared_library("sky_shell") { "//base", "//base:i18n", "//build/config/sanitizers:deps", + "//mojo/android:libsystem_java", + "//mojo/common", "//mojo/edk/system", + "//mojo/public/cpp/application", + "//mojo/public/interfaces/application", + "//mojo/services/network/public/interfaces", "//skia", "//sky/engine", "//ui/gfx/geometry", @@ -61,34 +71,54 @@ shared_library("sky_shell") { android_library("java") { java_files = [ + "apk/src/org/domokit/sky/shell/JavaServiceProvider.java", + "apk/src/org/domokit/sky/shell/PlatformView.java", "apk/src/org/domokit/sky/shell/SkyMain.java", "apk/src/org/domokit/sky/shell/SkyShellActivity.java", "apk/src/org/domokit/sky/shell/SkyShellApplication.java", - "apk/src/org/domokit/sky/shell/SkyView.java", ] deps = [ "//base:base_java", + "//mojo/android:system_java", + "//mojo/public/interfaces/application:application_java", + "//mojo/public/java:bindings", + "//mojo/public/java:system", + "//mojo/services/network/public/interfaces:interfaces_java", ] } +sky_shell_assets_dir = "$root_build_dir/sky_shell/assets" + android_resources("resources") { resource_dirs = [ "apk/res" ] custom_package = "org.domokit.sky.shell" } +copy_ex("assets") { + clear_dir = true + dest = sky_shell_assets_dir + sources = [ + "$root_build_dir/icudtl.dat", + ] + deps = [ + "//third_party/icu", + ] +} + android_apk("sky_shell_apk") { apk_name = "SkyShell" android_manifest = "apk/AndroidManifest.xml" native_libs = [ "libsky_shell.so" ] - asset_location = "apk/res" + asset_location = sky_shell_assets_dir deps = [ - ":sky_shell", + "//base:base_java", + ":assets", ":java", ":resources", - "//base:base_java", + ":sky_shell", ] } diff --git a/shell/apk/src/org/domokit/sky/shell/JavaServiceProvider.java b/shell/apk/src/org/domokit/sky/shell/JavaServiceProvider.java new file mode 100644 index 00000000000..e78f53c0deb --- /dev/null +++ b/shell/apk/src/org/domokit/sky/shell/JavaServiceProvider.java @@ -0,0 +1,47 @@ +// 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. + +package org.domokit.sky.shell; + +import org.chromium.base.CalledByNative; +import org.chromium.base.JNINamespace; +import org.chromium.mojo.system.Core; +import org.chromium.mojo.system.MessagePipeHandle; +import org.chromium.mojo.system.MojoException; +import org.chromium.mojo.system.Pair; +import org.chromium.mojo.system.impl.CoreImpl; +import org.chromium.mojom.mojo.ServiceProvider; + +/** + * A class to intialize the network. + **/ +@JNINamespace("sky::shell") +public class JavaServiceProvider implements ServiceProvider { + private Core mCore; + + @SuppressWarnings("unused") + @CalledByNative + public static int create() { + Core core = CoreImpl.getInstance(); + Pair messagePipe = core.createMessagePipe(null); + ServiceProvider.MANAGER.bind(new JavaServiceProvider(core), messagePipe.first); + return messagePipe.second.releaseNativeHandle(); + } + + public JavaServiceProvider(Core core) { + assert core != null; + mCore = core; + } + + @Override + public void close() {} + + @Override + public void onConnectionError(MojoException e) {} + + @Override + public void connectToService(String interfaceName, MessagePipeHandle pipe) { + pipe.close(); + } +} diff --git a/shell/apk/src/org/domokit/sky/shell/SkyView.java b/shell/apk/src/org/domokit/sky/shell/PlatformView.java similarity index 57% rename from shell/apk/src/org/domokit/sky/shell/SkyView.java rename to shell/apk/src/org/domokit/sky/shell/PlatformView.java index 2f82e638ccb..ac8879d43c0 100644 --- a/shell/apk/src/org/domokit/sky/shell/SkyView.java +++ b/shell/apk/src/org/domokit/sky/shell/PlatformView.java @@ -4,67 +4,60 @@ package org.domokit.sky.shell; -import android.app.Activity; import android.content.Context; import android.view.Surface; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.view.View; -import org.chromium.base.CalledByNative; import org.chromium.base.JNINamespace; /** * A view containing Sky */ @JNINamespace("sky::shell") -public class SkyView extends SurfaceView { - private long mNativeSkyView; +public class PlatformView extends SurfaceView { + private long mNativePlatformView; private final SurfaceHolder.Callback mSurfaceCallback; - @SuppressWarnings("unused") - @CalledByNative - public static void createForActivity(Activity activity, long nativeSkyView) { - activity.setContentView(new SkyView(activity, nativeSkyView)); - } - - public SkyView(Context context, long nativeSkyView) { + public PlatformView(Context context) { super(context); setFocusable(true); setFocusableInTouchMode(true); - mNativeSkyView = nativeSkyView; - assert mNativeSkyView != 0; + mNativePlatformView = nativeAttach(); + assert mNativePlatformView != 0; final float density = context.getResources().getDisplayMetrics().density; mSurfaceCallback = new SurfaceHolder.Callback() { @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { - assert mNativeSkyView != 0; - nativeSurfaceSetSize(mNativeSkyView, width, height, density); + assert mNativePlatformView != 0; + nativeSurfaceSetSize(mNativePlatformView, width, height, density); } @Override public void surfaceCreated(SurfaceHolder holder) { - assert mNativeSkyView != 0; - nativeSurfaceCreated(mNativeSkyView, holder.getSurface()); + assert mNativePlatformView != 0; + nativeSurfaceCreated(mNativePlatformView, holder.getSurface()); } @Override public void surfaceDestroyed(SurfaceHolder holder) { - assert mNativeSkyView != 0; - nativeSurfaceDestroyed(mNativeSkyView); + assert mNativePlatformView != 0; + nativeSurfaceDestroyed(mNativePlatformView); } }; getHolder().addCallback(mSurfaceCallback); } - public void destroy() { + @Override + protected void onDetachedFromWindow() { getHolder().removeCallback(mSurfaceCallback); - nativeDestroy(mNativeSkyView); - mNativeSkyView = 0; + nativeDetach(mNativePlatformView); + mNativePlatformView = 0; } @Override @@ -76,9 +69,10 @@ public class SkyView extends SurfaceView { } } - private static native void nativeDestroy(long nativeSkyView); - private static native void nativeSurfaceCreated(long nativeSkyView, Surface surface); - private static native void nativeSurfaceDestroyed(long nativeSkyView); + private static native long nativeAttach(); + private static native void nativeDetach(long nativePlatformView); + private static native void nativeSurfaceCreated(long nativePlatformView, Surface surface); + private static native void nativeSurfaceDestroyed(long nativePlatformView); private static native void nativeSurfaceSetSize( - long nativeSkyView, int width, int height, float density); + long nativePlatformView, int width, int height, float density); } diff --git a/shell/apk/src/org/domokit/sky/shell/SkyMain.java b/shell/apk/src/org/domokit/sky/shell/SkyMain.java index 0f373e4026c..78cd7347c07 100644 --- a/shell/apk/src/org/domokit/sky/shell/SkyMain.java +++ b/shell/apk/src/org/domokit/sky/shell/SkyMain.java @@ -8,6 +8,7 @@ import android.content.Context; import android.util.Log; import org.chromium.base.JNINamespace; +import org.chromium.base.ResourceExtractor; /** * A class to intialize the native code. @@ -28,6 +29,9 @@ public class SkyMain { if (sInitialized) return; try { + ResourceExtractor resourceExtractor = ResourceExtractor.get(applicationContext); + resourceExtractor.startExtractingResources(); + resourceExtractor.waitForCompletion(); nativeInit(applicationContext); sInitialized = true; } catch (Exception e) { @@ -36,15 +40,5 @@ public class SkyMain { } } - /** - * Starts the specified application in the specified context. - * - * @return true if an application has been launched. - **/ - static boolean start() { - return nativeStart(); - } - private static native void nativeInit(Context context); - private static native boolean nativeStart(); } diff --git a/shell/apk/src/org/domokit/sky/shell/SkyShellActivity.java b/shell/apk/src/org/domokit/sky/shell/SkyShellActivity.java index a38d83e9eba..a4f2412c264 100644 --- a/shell/apk/src/org/domokit/sky/shell/SkyShellActivity.java +++ b/shell/apk/src/org/domokit/sky/shell/SkyShellActivity.java @@ -18,7 +18,7 @@ public class SkyShellActivity extends Activity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - SkyMain.ensureInitialized(this); - SkyMain.start(); + SkyMain.ensureInitialized(getApplicationContext()); + setContentView(new PlatformView(this)); } } diff --git a/shell/apk/src/org/domokit/sky/shell/SkyShellApplication.java b/shell/apk/src/org/domokit/sky/shell/SkyShellApplication.java index 27ac093691a..efb12ddc9cf 100644 --- a/shell/apk/src/org/domokit/sky/shell/SkyShellApplication.java +++ b/shell/apk/src/org/domokit/sky/shell/SkyShellApplication.java @@ -8,6 +8,7 @@ import android.util.Log; import org.chromium.base.BaseChromiumApplication; import org.chromium.base.PathUtils; +import org.chromium.base.ResourceExtractor; import org.chromium.base.library_loader.LibraryLoader; import org.chromium.base.library_loader.ProcessInitException; @@ -18,12 +19,16 @@ import org.chromium.base.library_loader.ProcessInitException; public class SkyShellApplication extends BaseChromiumApplication { private static final String TAG = "SkyShellApplication"; private static final String PRIVATE_DATA_DIRECTORY_SUFFIX = "sky_shell"; + private static final String[] SKY_MANDATORY_PAKS = { + "icudtl.dat", + }; @Override public void onCreate() { super.onCreate(); initializeJavaUtils(); initializeNative(); + ResourceExtractor.setMandatoryPaksToExtract(SKY_MANDATORY_PAKS); } /** diff --git a/shell/gpu/ganesh_context.cc b/shell/gpu/ganesh_context.cc index 77833b34c76..6f5de8b2548 100644 --- a/shell/gpu/ganesh_context.cc +++ b/shell/gpu/ganesh_context.cc @@ -30,7 +30,7 @@ GaneshContext::GaneshContext(scoped_refptr gl_context) gr_context_ = skia::AdoptRef(GrContext::Create( kOpenGL_GrBackend, reinterpret_cast(interface.get()))); - DCHECK(gr_context_); + DCHECK(gr_context_) << "Failed to create GrContext."; gr_context_->setResourceCacheLimits(kMaxGaneshResourceCacheCount, kMaxGaneshResourceCacheBytes); } diff --git a/shell/gpu/ganesh_surface.cc b/shell/gpu/ganesh_surface.cc index fb15738d374..c9771de53b0 100644 --- a/shell/gpu/ganesh_surface.cc +++ b/shell/gpu/ganesh_surface.cc @@ -15,7 +15,7 @@ GaneshSurface::GaneshSurface(GaneshContext* context, const gfx::Size& size) { desc.fWidth = size.width(); desc.fHeight = size.height(); desc.fConfig = kSkia8888_GrPixelConfig; - desc.fOrigin = kTopLeft_GrSurfaceOrigin; + desc.fOrigin = kBottomLeft_GrSurfaceOrigin; auto target = skia::AdoptRef(context->gr()->wrapBackendRenderTarget(desc)); DCHECK(target); diff --git a/shell/gpu/rasterizer.cc b/shell/gpu/rasterizer.cc index 70336e64df8..d841ea8a478 100644 --- a/shell/gpu/rasterizer.cc +++ b/shell/gpu/rasterizer.cc @@ -24,7 +24,8 @@ gfx::Size GetSize(SkPicture* picture) { } // namespace -Rasterizer::Rasterizer() : weak_factory_(this) { +Rasterizer::Rasterizer() + : share_group_(new gfx::GLShareGroup()), weak_factory_(this) { } Rasterizer::~Rasterizer() { @@ -35,14 +36,15 @@ base::WeakPtr Rasterizer::GetWeakPtr() { } void Rasterizer::OnAcceleratedWidgetAvailable(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. + if (!surface_) + return; + + EnsureGLContext(); CHECK(context_->MakeCurrent(surface_.get())); EnsureGaneshSurface(GetSize(picture.get())); @@ -54,15 +56,20 @@ void Rasterizer::Draw(skia::RefPtr picture) { } void Rasterizer::OnOutputSurfaceDestroyed() { + ganesh_surface_.reset(); + ganesh_context_.reset(); + context_ = nullptr; + surface_ = nullptr; } -bool Rasterizer::CreateGLContext() { +void Rasterizer::EnsureGLContext() { + if (context_) + return; context_ = gfx::GLContext::CreateGLContext(share_group_.get(), surface_.get(), gfx::PreferIntegratedGpu); - if (!context_) - return false; + CHECK(context_) << "GLContext required."; + CHECK(context_->MakeCurrent(surface_.get())); ganesh_context_.reset(new GaneshContext(context_.get())); - return true; } void Rasterizer::EnsureGaneshSurface(const gfx::Size& size) { diff --git a/shell/gpu/rasterizer.h b/shell/gpu/rasterizer.h index 8e556418903..3fc8a5aaa4d 100644 --- a/shell/gpu/rasterizer.h +++ b/shell/gpu/rasterizer.h @@ -34,11 +34,10 @@ class Rasterizer : public GPUDelegate { void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget) override; void OnOutputSurfaceDestroyed() override; - - void Draw(skia::RefPtr picture); + void Draw(skia::RefPtr picture) override; private: - bool CreateGLContext(); + void EnsureGLContext(); void EnsureGaneshSurface(const gfx::Size& size); scoped_refptr share_group_; diff --git a/shell/gpu_delegate.h b/shell/gpu_delegate.h index 34ab4cdf284..00040c52232 100644 --- a/shell/gpu_delegate.h +++ b/shell/gpu_delegate.h @@ -5,8 +5,11 @@ #ifndef SKY_SHELL_GPU_DELEGATE_H_ #define SKY_SHELL_GPU_DELEGATE_H_ +#include "skia/ext/refptr.h" #include "ui/gfx/native_widget_types.h" +class SkPicture; + namespace sky { namespace shell { @@ -14,6 +17,7 @@ class GPUDelegate { public: virtual void OnAcceleratedWidgetAvailable(gfx::AcceleratedWidget widget) = 0; virtual void OnOutputSurfaceDestroyed() = 0; + virtual void Draw(skia::RefPtr picture) = 0; protected: virtual ~GPUDelegate(); diff --git a/shell/java_service_provider.cc b/shell/java_service_provider.cc new file mode 100644 index 00000000000..8973f2e2c14 --- /dev/null +++ b/shell/java_service_provider.cc @@ -0,0 +1,23 @@ +// 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/java_service_provider.h" + +#include "jni/JavaServiceProvider_jni.h" + +namespace sky { +namespace shell { + +bool RegisterJavaServiceProvider(JNIEnv* env) { + return RegisterNativesImpl(env); +} + +mojo::ScopedMessagePipeHandle CreateJavaServiceProvider() { + JNIEnv* env = base::android::AttachCurrentThread(); + return mojo::ScopedMessagePipeHandle( + mojo::MessagePipeHandle(Java_JavaServiceProvider_create(env))); +} + +} // namespace shell +} // namespace sky diff --git a/shell/java_service_provider.h b/shell/java_service_provider.h new file mode 100644 index 00000000000..aeafbd922a5 --- /dev/null +++ b/shell/java_service_provider.h @@ -0,0 +1,20 @@ +// 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_SERVICE_PROVIDER_IMPL_H_ +#define SKY_SHELL_SERVICE_PROVIDER_IMPL_H_ + +#include +#include "mojo/public/cpp/system/core.h" + +namespace sky { +namespace shell { + +bool RegisterJavaServiceProvider(JNIEnv* env); +mojo::ScopedMessagePipeHandle CreateJavaServiceProvider(); + +} // namespace shell +} // namespace sky + +#endif // SKY_SHELL_SERVICE_PROVIDER_IMPL_H_ diff --git a/shell/library_loader.cc b/shell/library_loader.cc index 1682167f95e..971c861ca82 100644 --- a/shell/library_loader.cc +++ b/shell/library_loader.cc @@ -7,14 +7,18 @@ #include "base/android/jni_registrar.h" #include "base/android/library_loader/library_loader_hooks.h" #include "base/logging.h" +#include "mojo/android/system/core_impl.h" +#include "sky/shell/java_service_provider.h" +#include "sky/shell/platform_view.h" #include "sky/shell/sky_main.h" -#include "sky/shell/sky_view.h" namespace { base::android::RegistrationMethod kSkyRegisteredMethods[] = { + {"CoreImpl", mojo::android::RegisterCoreImpl}, + {"JavaServiceProvider", sky::shell::RegisterJavaServiceProvider}, {"SkyMain", sky::shell::RegisterSkyMain}, - {"SkyView", sky::shell::SkyView::Register}, + {"PlatformView", sky::shell::PlatformView::Register}, }; bool RegisterSkyJni(JNIEnv* env) { diff --git a/shell/sky_view.cc b/shell/platform_view.cc similarity index 63% rename from shell/sky_view.cc rename to shell/platform_view.cc index d7b22112192..e31498dcb39 100644 --- a/shell/sky_view.cc +++ b/shell/platform_view.cc @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "sky/shell/sky_view.h" +#include "sky/shell/platform_view.h" #include #include @@ -10,31 +10,35 @@ #include "base/android/jni_android.h" #include "base/bind.h" #include "base/location.h" -#include "jni/SkyView_jni.h" +#include "jni/PlatformView_jni.h" +#include "sky/shell/shell.h" namespace sky { namespace shell { +static jlong Attach(JNIEnv* env, jclass clazz) { + return reinterpret_cast(Shell::Shared().view()); +} + // static -bool SkyView::Register(JNIEnv* env) { +bool PlatformView::Register(JNIEnv* env) { return RegisterNativesImpl(env); } -SkyView::SkyView(const Config& config) : config_(config), window_(nullptr) { - JNIEnv* env = base::android::AttachCurrentThread(); - Java_SkyView_createForActivity(env, base::android::GetApplicationContext(), - reinterpret_cast(this)); +PlatformView::PlatformView(const Config& config) + : config_(config), window_(nullptr) { } -SkyView::~SkyView() { +PlatformView::~PlatformView() { if (window_) ReleaseWindow(); } -void SkyView::Destroy(JNIEnv* env, jobject obj) { +void PlatformView::Detach(JNIEnv* env, jobject obj) { + DCHECK(!window_); } -void SkyView::SurfaceCreated(JNIEnv* env, jobject obj, jobject jsurface) { +void PlatformView::SurfaceCreated(JNIEnv* env, jobject obj, jobject jsurface) { base::android::ScopedJavaLocalRef protector(env, jsurface); // Note: This ensures that any local references used by // ANativeWindow_fromSurface are released immediately. This is needed as a @@ -48,7 +52,7 @@ void SkyView::SurfaceCreated(JNIEnv* env, jobject obj, jobject jsurface) { config_.gpu_delegate, window_)); } -void SkyView::SurfaceDestroyed(JNIEnv* env, jobject obj) { +void PlatformView::SurfaceDestroyed(JNIEnv* env, jobject obj) { DCHECK(window_); config_.gpu_task_runner->PostTask( FROM_HERE, @@ -56,18 +60,18 @@ void SkyView::SurfaceDestroyed(JNIEnv* env, jobject obj) { ReleaseWindow(); } -void SkyView::SurfaceSetSize(JNIEnv* env, - jobject obj, - jint width, - jint height, - jfloat density) { +void PlatformView::SurfaceSetSize(JNIEnv* env, + jobject obj, + jint width, + jint height, + jfloat density) { config_.ui_task_runner->PostTask( FROM_HERE, base::Bind(&UIDelegate::OnViewportMetricsChanged, config_.ui_delegate, gfx::Size(width, height), density)); } -void SkyView::ReleaseWindow() { +void PlatformView::ReleaseWindow() { ANativeWindow_release(window_); window_ = nullptr; } diff --git a/shell/sky_view.h b/shell/platform_view.h similarity index 88% rename from shell/sky_view.h rename to shell/platform_view.h index b326ea37be4..7f83cde0839 100644 --- a/shell/sky_view.h +++ b/shell/platform_view.h @@ -18,7 +18,7 @@ struct ANativeWindow; namespace sky { namespace shell { -class SkyView { +class PlatformView { public: struct Config { base::WeakPtr gpu_delegate; @@ -30,11 +30,11 @@ class SkyView { static bool Register(JNIEnv* env); - explicit SkyView(const Config& config); - ~SkyView(); + explicit PlatformView(const Config& config); + ~PlatformView(); // Called from Java - void Destroy(JNIEnv* env, jobject obj); + void Detach(JNIEnv* env, jobject obj); void SurfaceCreated(JNIEnv* env, jobject obj, jobject jsurface); void SurfaceDestroyed(JNIEnv* env, jobject obj); void SurfaceSetSize(JNIEnv* env, @@ -49,7 +49,7 @@ class SkyView { Config config_; ANativeWindow* window_; - DISALLOW_COPY_AND_ASSIGN(SkyView); + DISALLOW_COPY_AND_ASSIGN(PlatformView); }; } // namespace shell diff --git a/shell/shell.cc b/shell/shell.cc index a5ca2f38017..ae2f2e9372f 100644 --- a/shell/shell.cc +++ b/shell/shell.cc @@ -6,40 +6,80 @@ #include "base/bind.h" #include "base/single_thread_task_runner.h" -#include "base/threading/thread.h" +#include "mojo/common/message_pump_mojo.h" +#include "mojo/edk/embedder/embedder.h" +#include "mojo/edk/embedder/simple_platform_support.h" #include "sky/shell/gpu/rasterizer.h" -#include "sky/shell/sky_view.h" +#include "sky/shell/java_service_provider.h" +#include "sky/shell/platform_view.h" #include "sky/shell/ui/engine.h" namespace sky { namespace shell { +namespace { + +static Shell* g_shell = nullptr; + +scoped_ptr CreateMessagePumpMojo() { + return make_scoped_ptr(new mojo::common::MessagePumpMojo); +} + +} // namespace Shell::Shell(scoped_refptr java_task_runner) : java_task_runner_(java_task_runner) { + DCHECK(!g_shell); + mojo::embedder::Init(scoped_ptr( + new mojo::embedder::SimplePlatformSupport())); + + base::Thread::Options options; + options.message_pump_factory = base::Bind(&CreateMessagePumpMojo); + + InitGPU(options); + InitUI(options); + InitView(); } Shell::~Shell() { } -void Shell::Init() { - gpu_thread_.reset(new base::Thread("gpu_thread")); - gpu_thread_->Start(); - rasterizer_.reset(new Rasterizer()); +void Shell::Init(scoped_refptr java_task_runner) { + g_shell = new Shell(java_task_runner); +} +Shell& Shell::Shared() { + DCHECK(g_shell); + return *g_shell; +} + +void Shell::InitGPU(const base::Thread::Options& options) { + gpu_thread_.reset(new base::Thread("gpu_thread")); + gpu_thread_->StartWithOptions(options); + + rasterizer_.reset(new Rasterizer()); +} + +void Shell::InitUI(const base::Thread::Options& options) { ui_thread_.reset(new base::Thread("ui_thread")); - ui_thread_->Start(); - engine_.reset(new Engine()); + ui_thread_->StartWithOptions(options); + + Engine::Config config; + config.gpu_task_runner = gpu_thread_->message_loop()->task_runner(); + config.gpu_delegate = rasterizer_->GetWeakPtr(); + engine_.reset(new Engine(config)); ui_thread_->message_loop()->PostTask( - FROM_HERE, base::Bind(&Engine::Init, engine_->GetWeakPtr())); + FROM_HERE, base::Bind(&Engine::Init, engine_->GetWeakPtr(), + base::Passed(CreateJavaServiceProvider()))); +} - SkyView::Config config; +void Shell::InitView() { + PlatformView::Config config; config.gpu_task_runner = gpu_thread_->message_loop()->task_runner(); config.gpu_delegate = rasterizer_->GetWeakPtr(); config.ui_task_runner = ui_thread_->message_loop()->task_runner(); config.ui_delegate = engine_->GetWeakPtr(); - - view_.reset(new SkyView(config)); + view_.reset(new PlatformView(config)); } } // namespace shell diff --git a/shell/shell.h b/shell/shell.h index 6f77c2aa658..4ac112c1fff 100644 --- a/shell/shell.h +++ b/shell/shell.h @@ -8,9 +8,9 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/memory/scoped_ptr.h" +#include "base/threading/thread.h" namespace base { -class Thread; class SingleThreadTaskRunner; } @@ -18,21 +18,30 @@ namespace sky { namespace shell { class Engine; class Rasterizer; -class SkyView; +class PlatformView; class Shell { public: - explicit Shell(scoped_refptr java_task_runner); ~Shell(); - void Init(); + static void Init( + scoped_refptr java_task_runner); + static Shell& Shared(); + + PlatformView* view() const { return view_.get(); } private: + explicit Shell(scoped_refptr java_task_runner); + + void InitGPU(const base::Thread::Options& options); + void InitUI(const base::Thread::Options& options); + void InitView(); + scoped_refptr java_task_runner_; scoped_ptr gpu_thread_; scoped_ptr ui_thread_; - scoped_ptr view_; + scoped_ptr view_; scoped_ptr rasterizer_; scoped_ptr engine_; diff --git a/shell/sky_main.cc b/shell/sky_main.cc index 4ae0b940be6..4a10ab0df3f 100644 --- a/shell/sky_main.cc +++ b/shell/sky_main.cc @@ -31,11 +31,6 @@ namespace { LazyInstance> g_java_message_loop = LAZY_INSTANCE_INITIALIZER; -LazyInstance> g_main_activiy = - LAZY_INSTANCE_INITIALIZER; - -LazyInstance> g_shell = LAZY_INSTANCE_INITIALIZER; - void InitializeLogging() { logging::LoggingSettings settings; settings.logging_dest = logging::LOG_TO_SYSTEM_DEBUG_LOG; @@ -49,16 +44,11 @@ void InitializeLogging() { } // namespace -static void Init(JNIEnv* env, - jclass clazz, - jobject activity) { - g_main_activiy.Get().Reset(env, activity); - - base::android::ScopedJavaLocalRef scoped_activity(env, activity); - base::android::InitApplicationContext(env, scoped_activity); +static void Init(JNIEnv* env, jclass clazz, jobject context) { + base::android::ScopedJavaLocalRef scoped_context(env, context); + base::android::InitApplicationContext(env, scoped_context); base::CommandLine::Init(0, nullptr); - InitializeLogging(); g_java_message_loop.Get().reset(new base::MessageLoopForUI); @@ -67,16 +57,7 @@ static void Init(JNIEnv* env, base::i18n::InitializeICU(); gfx::GLSurface::InitializeOneOff(); - g_shell.Get().reset(new Shell(g_java_message_loop.Get()->task_runner())); - - g_java_message_loop.Get()->PostTask( - FROM_HERE, - base::Bind(&Shell::Init, base::Unretained(g_shell.Get().get()))); -} - -static jboolean Start(JNIEnv* env, jclass clazz) { - LOG(INFO) << "Native code started!"; - return true; + Shell::Init(g_java_message_loop.Get()->task_runner()); } bool RegisterSkyMain(JNIEnv* env) { diff --git a/shell/ui/animator.cc b/shell/ui/animator.cc new file mode 100644 index 00000000000..e7f299b97c9 --- /dev/null +++ b/shell/ui/animator.cc @@ -0,0 +1,59 @@ +// 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/ui/animator.h" + +#include "base/bind.h" +#include "base/message_loop/message_loop.h" + +namespace sky { +namespace shell { + +Animator::Animator(const Engine::Config& config, Engine* engine) + : config_(config), + engine_(engine), + engine_requested_frame_(false), + frame_in_progress_(false), + weak_factory_(this) { +} + +Animator::~Animator() { +} + +void Animator::RequestFrame() { + if (engine_requested_frame_) + return; + engine_requested_frame_ = true; + + if (!frame_in_progress_) { + frame_in_progress_ = true; + base::MessageLoop::current()->PostTask( + FROM_HERE, + base::Bind(&Animator::BeginFrame, weak_factory_.GetWeakPtr())); + } +} + +void Animator::BeginFrame() { + DCHECK(frame_in_progress_); + DCHECK(engine_requested_frame_); + engine_requested_frame_ = false; + + engine_->BeginFrame(base::TimeTicks::Now()); + config_.gpu_task_runner->PostTaskAndReply( + FROM_HERE, + base::Bind(&GPUDelegate::Draw, config_.gpu_delegate, engine_->Paint()), + base::Bind(&Animator::OnFrameComplete, weak_factory_.GetWeakPtr())); +} + +void Animator::OnFrameComplete() { + DCHECK(frame_in_progress_); + frame_in_progress_ = false; + if (engine_requested_frame_) { + frame_in_progress_ = true; + BeginFrame(); + } +} + +} // namespace shell +} // namespace sky diff --git a/shell/ui/animator.h b/shell/ui/animator.h new file mode 100644 index 00000000000..764302541f8 --- /dev/null +++ b/shell/ui/animator.h @@ -0,0 +1,38 @@ +// 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_UI_ANIMATOR_H_ +#define SKY_SHELL_UI_ANIMATOR_H_ + +#include "base/memory/weak_ptr.h" +#include "sky/shell/ui/engine.h" + +namespace sky { +namespace shell { + +class Animator { + public: + explicit Animator(const Engine::Config& config, Engine* engine); + ~Animator(); + + void RequestFrame(); + + private: + void BeginFrame(); + void OnFrameComplete(); + + Engine::Config config_; + Engine* engine_; + bool engine_requested_frame_; + bool frame_in_progress_; + + base::WeakPtrFactory weak_factory_; + + DISALLOW_COPY_AND_ASSIGN(Animator); +}; + +} // namespace shell +} // namespace sky + +#endif // SKY_SHELL_UI_ANIMATOR_H_ diff --git a/shell/ui/engine.cc b/shell/ui/engine.cc index 07deb847c24..b316c4cfed2 100644 --- a/shell/ui/engine.cc +++ b/shell/ui/engine.cc @@ -4,15 +4,22 @@ #include "sky/shell/ui/engine.h" +#include "base/bind.h" #include "sky/engine/public/web/Sky.h" #include "sky/engine/public/web/WebLocalFrame.h" #include "sky/engine/public/web/WebView.h" +#include "sky/shell/ui/animator.h" #include "sky/shell/ui/platform_impl.h" +#include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkPictureRecorder.h" namespace sky { namespace shell { -Engine::Engine() : web_view_(nullptr), weak_factory_(this) { +Engine::Engine(const Config& config) + : animator_(new Animator(config, this)), + web_view_(nullptr), + weak_factory_(this) { } Engine::~Engine() { @@ -24,20 +31,53 @@ base::WeakPtr Engine::GetWeakPtr() { return weak_factory_.GetWeakPtr(); } -void Engine::Init() { - platform_impl_.reset(new PlatformImpl); +void Engine::Init(mojo::ScopedMessagePipeHandle service_provider) { + platform_impl_.reset(new PlatformImpl( + mojo::MakeProxy(service_provider.Pass()))); blink::initialize(platform_impl_.get()); web_view_ = blink::WebView::create(this); web_view_->setMainFrame(blink::WebLocalFrame::create(this)); + web_view_->mainFrame()->load( + GURL("http://127.0.0.1:8000/sky/examples/spinning-square.sky")); } -void Engine::OnViewportMetricsChanged(const gfx::Size& size, +void Engine::BeginFrame(base::TimeTicks frame_time) { + double frame_time_sec = (frame_time - base::TimeTicks()).InSecondsF(); + double deadline_sec = frame_time_sec; + double interval_sec = 1.0 / 60; + blink::WebBeginFrameArgs args(frame_time_sec, deadline_sec, interval_sec); + + web_view_->beginFrame(args); + web_view_->layout(); +} + +skia::RefPtr Engine::Paint() { + SkRTreeFactory factory; + SkPictureRecorder recorder; + auto canvas = skia::SharePtr(recorder.beginRecording( + physical_size_.width(), physical_size_.height(), &factory, + SkPictureRecorder::kComputeSaveLayerInfo_RecordFlag)); + + web_view_->paint(canvas.get(), blink::WebRect(gfx::Rect(physical_size_))); + return skia::AdoptRef(recorder.endRecordingAsPicture()); +} + +void Engine::OnViewportMetricsChanged(const gfx::Size& physical_size, float device_pixel_ratio) { - blink::WebSize web_size(size.width() / device_pixel_ratio, - size.height() / device_pixel_ratio); + physical_size_ = physical_size; web_view_->setDeviceScaleFactor(device_pixel_ratio); - web_view_->resize(web_size); + gfx::SizeF size = gfx::ScaleSize(physical_size, 1 / device_pixel_ratio); + // FIXME: We should be able to set the size of the WebView in floating point + // because its in logical pixels. + web_view_->resize(blink::WebSize(size.width(), size.height())); +} + +void Engine::initializeLayerTreeView() { +} + +void Engine::scheduleVisualUpdate() { + animator_->RequestFrame(); } } // namespace shell diff --git a/shell/ui/engine.h b/shell/ui/engine.h index 9deccd8c6b8..ec21ab4e883 100644 --- a/shell/ui/engine.h +++ b/shell/ui/engine.h @@ -8,32 +8,53 @@ #include "base/macros.h" #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" +#include "base/single_thread_task_runner.h" +#include "mojo/public/cpp/system/core.h" +#include "skia/ext/refptr.h" #include "sky/engine/public/web/WebFrameClient.h" #include "sky/engine/public/web/WebViewClient.h" +#include "sky/shell/gpu_delegate.h" #include "sky/shell/ui_delegate.h" +#include "third_party/skia/include/core/SkPicture.h" #include "ui/gfx/geometry/size.h" namespace sky { namespace shell { +class Animator; class PlatformImpl; class Engine : public UIDelegate, public blink::WebFrameClient, public blink::WebViewClient { public: - Engine(); + struct Config { + base::WeakPtr gpu_delegate; + scoped_refptr gpu_task_runner; + }; + + explicit Engine(const Config& config); ~Engine() override; base::WeakPtr GetWeakPtr(); - void Init(); + void Init(mojo::ScopedMessagePipeHandle service_provider); - void OnViewportMetricsChanged(const gfx::Size& size, - float device_pixel_ratio) override; + void BeginFrame(base::TimeTicks frame_time); + skia::RefPtr Paint(); private: + // UIDelegate methods: + void OnViewportMetricsChanged(const gfx::Size& physical_size, + float device_pixel_ratio) override; + + // WebViewClient methods: + void initializeLayerTreeView() override; + void scheduleVisualUpdate() override; + scoped_ptr platform_impl_; + scoped_ptr animator_; blink::WebView* web_view_; + gfx::Size physical_size_; base::WeakPtrFactory weak_factory_; diff --git a/shell/ui/platform_impl.cc b/shell/ui/platform_impl.cc index dca0039fd3c..6701555469e 100644 --- a/shell/ui/platform_impl.cc +++ b/shell/ui/platform_impl.cc @@ -4,11 +4,15 @@ #include "sky/shell/ui/platform_impl.h" +#include "mojo/public/cpp/application/connect.h" + namespace sky { namespace shell { -PlatformImpl::PlatformImpl() - : main_thread_task_runner_(base::MessageLoop::current()->task_runner()) { +PlatformImpl::PlatformImpl(mojo::ServiceProviderPtr service_provider) + : main_thread_task_runner_(base::MessageLoop::current()->task_runner()), + service_provider_(service_provider.Pass()) { + mojo::ConnectToService(service_provider_.get(), &network_service_); } PlatformImpl::~PlatformImpl() { @@ -22,5 +26,9 @@ base::SingleThreadTaskRunner* PlatformImpl::mainThreadTaskRunner() { return main_thread_task_runner_.get(); } +mojo::NetworkService* PlatformImpl::networkService() { + return network_service_.get(); +} + } // namespace shell } // namespace sky diff --git a/shell/ui/platform_impl.h b/shell/ui/platform_impl.h index 5a62d0e8f21..e8fa5503b09 100644 --- a/shell/ui/platform_impl.h +++ b/shell/ui/platform_impl.h @@ -6,6 +6,8 @@ #define SKY_SHELL_UI_PLATFORM_IMPL_H_ #include "base/message_loop/message_loop.h" +#include "mojo/public/interfaces/application/service_provider.mojom.h" +#include "mojo/services/network/public/interfaces/network_service.mojom.h" #include "sky/engine/public/platform/Platform.h" namespace sky { @@ -13,15 +15,18 @@ namespace shell { class PlatformImpl : public blink::Platform { public: - PlatformImpl(); + explicit PlatformImpl(mojo::ServiceProviderPtr service_provider); ~PlatformImpl() override; // blink::Platform: blink::WebString defaultLocale() override; base::SingleThreadTaskRunner* mainThreadTaskRunner() override; + mojo::NetworkService* networkService() override; private: scoped_refptr main_thread_task_runner_; + mojo::ServiceProviderPtr service_provider_; + mojo::NetworkServicePtr network_service_; DISALLOW_COPY_AND_ASSIGN(PlatformImpl); };