| Index: content/common/android/surface_callback.cc
|
| diff --git a/content/common/android/surface_callback.cc b/content/common/android/surface_callback.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..de83bbd44b0da2799b28faa03878f50a91ad6cf5
|
| --- /dev/null
|
| +++ b/content/common/android/surface_callback.cc
|
| @@ -0,0 +1,159 @@
|
| +// Copyright (c) 2012 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 "content/common/android/surface_callback.h"
|
| +
|
| +#include <android/native_window_jni.h>
|
| +
|
| +#include "base/android/jni_android.h"
|
| +#include "base/bind.h"
|
| +#include "base/lazy_instance.h"
|
| +#include "base/logging.h"
|
| +#include "base/message_loop.h"
|
| +#include "base/message_loop_proxy.h"
|
| +#include "base/synchronization/lock.h"
|
| +#include "base/synchronization/waitable_event.h"
|
| +#include "ui/gl/android_native_window.h"
|
| +#include "jni/surface_callback_jni.h"
|
| +
|
| +using base::android::AttachCurrentThread;
|
| +using base::android::CheckException;
|
| +using base::android::GetMethodID;
|
| +using base::WaitableEvent;
|
| +using content::SurfaceTexturePeer;
|
| +
|
| +namespace {
|
| +
|
| +struct GlobalState {
|
| + base::Lock registration_lock;
|
| + // We hold a reference to a message loop proxy which handles message loop
|
| + // destruction gracefully, which is important since we post tasks from an
|
| + // arbitrary binder thread while the main thread might be shutting down.
|
| + // Also, in single-process mode we have two ChildThread objects for render
|
| + // and gpu thread, so we need to store the msg loops separately.
|
| + scoped_refptr<base::MessageLoopProxy> native_window_loop;
|
| + scoped_refptr<base::MessageLoopProxy> video_surface_loop;
|
| + content::NativeWindowCallback native_window_callback;
|
| + content::VideoSurfaceCallback video_surface_callback;
|
| +};
|
| +
|
| +base::LazyInstance<GlobalState>::Leaky g_state = LAZY_INSTANCE_INITIALIZER;
|
| +
|
| +void RunNativeWindowCallback(int32 routing_id,
|
| + int32 renderer_id,
|
| + ANativeWindow* native_window,
|
| + WaitableEvent* completion) {
|
| + g_state.Pointer()->native_window_callback.Run(
|
| + routing_id, renderer_id, native_window, completion);
|
| +}
|
| +
|
| +void RunVideoSurfaceCallback(int32 routing_id,
|
| + int32 renderer_id,
|
| + jobject surface) {
|
| + g_state.Pointer()->video_surface_callback.Run(
|
| + routing_id, renderer_id, surface);
|
| +}
|
| +
|
| +} // namespace <anonymous>
|
| +
|
| +static void SetSurface(JNIEnv* env, jclass clazz,
|
| + jint type,
|
| + jobject surface,
|
| + jint primaryID,
|
| + jint secondaryID) {
|
| + SetSurfaceAsync(env, surface,
|
| + static_cast<SurfaceTexturePeer::SurfaceTextureTarget>(type),
|
| + primaryID, secondaryID, NULL);
|
| +}
|
| +
|
| +
|
| +namespace content {
|
| +
|
| +void ReleaseSurface(jobject surface) {
|
| + if (surface == NULL)
|
| + return;
|
| +
|
| + JNIEnv* env = AttachCurrentThread();
|
| + CHECK(env);
|
| +
|
| + jclass cls = env->FindClass("android/view/Surface");
|
| + DCHECK(cls);
|
| +
|
| + jmethodID method = env->GetMethodID(cls, "release", "()V");
|
| + DCHECK(method);
|
| +
|
| + env->CallVoidMethod(surface, method);
|
| + DCHECK(env);
|
| +
|
| + env->DeleteLocalRef(cls);
|
| +}
|
| +
|
| +void SetSurfaceAsync(JNIEnv* env,
|
| + jobject jsurface,
|
| + SurfaceTexturePeer::SurfaceTextureTarget type,
|
| + int primary_id,
|
| + int secondary_id,
|
| + WaitableEvent* completion) {
|
| + base::AutoLock lock(g_state.Pointer()->registration_lock);
|
| +
|
| + ANativeWindow* native_window = NULL;
|
| +
|
| + if (jsurface &&
|
| + type != SurfaceTexturePeer::SET_VIDEO_SURFACE_TEXTURE) {
|
| + native_window = ANativeWindow_fromSurface(env, jsurface);
|
| + ReleaseSurface(jsurface);
|
| + }
|
| + GlobalState* const global_state = g_state.Pointer();
|
| +
|
| + switch (type) {
|
| + case SurfaceTexturePeer::SET_GPU_SURFACE_TEXTURE: {
|
| + // This should only be sent as a reaction to the renderer
|
| + // activating compositing. If the GPU process crashes, we expect this
|
| + // to be resent after the new thread is initialized.
|
| + DCHECK(global_state->native_window_loop);
|
| + global_state->native_window_loop->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&RunNativeWindowCallback,
|
| + primary_id,
|
| + static_cast<uint32_t>(secondary_id),
|
| + native_window,
|
| + completion));
|
| + // ANativeWindow_release will be called in SetNativeWindow()
|
| + break;
|
| + }
|
| + case SurfaceTexturePeer::SET_VIDEO_SURFACE_TEXTURE: {
|
| + jobject surface = env->NewGlobalRef(jsurface);
|
| + DCHECK(global_state->video_surface_loop);
|
| + global_state->video_surface_loop->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&RunVideoSurfaceCallback,
|
| + primary_id,
|
| + secondary_id,
|
| + surface));
|
| + break;
|
| + }
|
| + }
|
| +}
|
| +
|
| +void RegisterVideoSurfaceCallback(base::MessageLoopProxy* loop,
|
| + VideoSurfaceCallback& callback) {
|
| + GlobalState* const global_state = g_state.Pointer();
|
| + base::AutoLock lock(global_state->registration_lock);
|
| + global_state->video_surface_loop = loop;
|
| + global_state->video_surface_callback = callback;
|
| +}
|
| +
|
| +void RegisterNativeWindowCallback(base::MessageLoopProxy* loop,
|
| + NativeWindowCallback& callback) {
|
| + GlobalState* const global_state = g_state.Pointer();
|
| + base::AutoLock lock(global_state->registration_lock);
|
| + global_state->native_window_loop = loop;
|
| + global_state->native_window_callback = callback;
|
| +}
|
| +
|
| +bool RegisterSurfaceCallback(JNIEnv* env) {
|
| + return RegisterNativesImpl(env);
|
| +}
|
| +
|
| +} // namespace content
|
|
|