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
;
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
,
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
,
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
,
68 SetSurfaceAsync(env
, surface
,
69 static_cast<SurfaceTexturePeer::SurfaceTextureTarget
>(type
),
70 primaryID
, secondaryID
, NULL
);
73 void ReleaseSurface(jobject surface
) {
77 JNIEnv
* env
= AttachCurrentThread();
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
,
90 SurfaceTexturePeer::SurfaceTextureTarget type
,
93 WaitableEvent
* completion
) {
94 base::AutoLock
lock(g_state
.Pointer()->registration_lock
);
96 ANativeWindow
* native_window
= NULL
;
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();
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(
113 base::Bind(&RunNativeWindowCallback
,
115 static_cast<uint32_t>(secondary_id
),
118 // ANativeWindow_release will be called in SetNativeWindow()
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(
126 base::Bind(&RunVideoSurfaceCallback
,
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