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); };