[content shell] implement testRunner.overridePreference
[chromium-blink-merge.git] / content / common / android / surface_callback.cc
blob7bfd033f5334713271ff3e02581191cfd3e9797f
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/common/android/surface_callback.h"
7 #include <android/native_window_jni.h>
9 #include "base/android/jni_android.h"
10 #include "base/bind.h"
11 #include "base/lazy_instance.h"
12 #include "base/logging.h"
13 #include "base/message_loop.h"
14 #include "base/message_loop_proxy.h"
15 #include "base/synchronization/lock.h"
16 #include "base/synchronization/waitable_event.h"
17 #include "ui/gl/android_native_window.h"
18 #include "jni/SurfaceCallback_jni.h"
20 using base::android::AttachCurrentThread;
21 using base::android::CheckException;
22 using base::android::GetClass;
23 using base::android::MethodID;
24 using base::WaitableEvent;
25 using content::SurfaceTexturePeer;
27 namespace content {
29 namespace {
31 struct GlobalState {
32 base::Lock registration_lock;
33 // We hold a reference to a message loop proxy which handles message loop
34 // destruction gracefully, which is important since we post tasks from an
35 // arbitrary binder thread while the main thread might be shutting down.
36 // Also, in single-process mode we have two ChildThread objects for render
37 // and gpu thread, so we need to store the msg loops separately.
38 scoped_refptr<base::MessageLoopProxy> native_window_loop;
39 scoped_refptr<base::MessageLoopProxy> video_surface_loop;
40 NativeWindowCallback native_window_callback;
41 VideoSurfaceCallback video_surface_callback;
44 base::LazyInstance<GlobalState>::Leaky g_state = LAZY_INSTANCE_INITIALIZER;
46 void RunNativeWindowCallback(int32 routing_id,
47 int32 renderer_id,
48 ANativeWindow* native_window,
49 WaitableEvent* completion) {
50 g_state.Pointer()->native_window_callback.Run(
51 routing_id, renderer_id, native_window, completion);
54 void RunVideoSurfaceCallback(int32 routing_id,
55 int32 renderer_id,
56 jobject surface) {
57 g_state.Pointer()->video_surface_callback.Run(
58 routing_id, renderer_id, surface);
61 } // namespace <anonymous>
63 static void SetSurface(JNIEnv* env, jclass clazz,
64 jint type,
65 jobject surface,
66 jint primaryID,
67 jint secondaryID) {
68 SetSurfaceAsync(env, surface,
69 static_cast<SurfaceTexturePeer::SurfaceTextureTarget>(type),
70 primaryID, secondaryID, NULL);
73 void ReleaseSurface(jobject surface) {
74 if (surface == NULL)
75 return;
77 JNIEnv* env = AttachCurrentThread();
78 CHECK(env);
80 ScopedJavaLocalRef<jclass> cls(GetClass(env, "android/view/Surface"));
82 jmethodID method = MethodID::Get<MethodID::TYPE_INSTANCE>(
83 env, cls.obj(), "release", "()V");
85 env->CallVoidMethod(surface, method);
88 void SetSurfaceAsync(JNIEnv* env,
89 jobject jsurface,
90 SurfaceTexturePeer::SurfaceTextureTarget type,
91 int primary_id,
92 int secondary_id,
93 WaitableEvent* completion) {
94 base::AutoLock lock(g_state.Pointer()->registration_lock);
96 ANativeWindow* native_window = NULL;
98 if (jsurface &&
99 type != SurfaceTexturePeer::SET_VIDEO_SURFACE_TEXTURE) {
100 native_window = ANativeWindow_fromSurface(env, jsurface);
101 ReleaseSurface(jsurface);
103 GlobalState* const global_state = g_state.Pointer();
105 switch (type) {
106 case SurfaceTexturePeer::SET_GPU_SURFACE_TEXTURE: {
107 // This should only be sent as a reaction to the renderer
108 // activating compositing. If the GPU process crashes, we expect this
109 // to be resent after the new thread is initialized.
110 DCHECK(global_state->native_window_loop);
111 global_state->native_window_loop->PostTask(
112 FROM_HERE,
113 base::Bind(&RunNativeWindowCallback,
114 primary_id,
115 static_cast<uint32_t>(secondary_id),
116 native_window,
117 completion));
118 // ANativeWindow_release will be called in SetNativeWindow()
119 break;
121 case SurfaceTexturePeer::SET_VIDEO_SURFACE_TEXTURE: {
122 jobject surface = env->NewGlobalRef(jsurface);
123 DCHECK(global_state->video_surface_loop);
124 global_state->video_surface_loop->PostTask(
125 FROM_HERE,
126 base::Bind(&RunVideoSurfaceCallback,
127 primary_id,
128 secondary_id,
129 surface));
130 break;
135 void RegisterVideoSurfaceCallback(base::MessageLoopProxy* loop,
136 VideoSurfaceCallback& callback) {
137 GlobalState* const global_state = g_state.Pointer();
138 base::AutoLock lock(global_state->registration_lock);
139 global_state->video_surface_loop = loop;
140 global_state->video_surface_callback = callback;
143 void RegisterNativeWindowCallback(base::MessageLoopProxy* loop,
144 NativeWindowCallback& callback) {
145 GlobalState* const global_state = g_state.Pointer();
146 base::AutoLock lock(global_state->registration_lock);
147 global_state->native_window_loop = loop;
148 global_state->native_window_callback = callback;
151 bool RegisterSurfaceCallback(JNIEnv* env) {
152 return RegisterNativesImpl(env);
155 } // namespace content