OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "remoting/client/jni/jni_gl_display_handler.h" | 5 #include "remoting/client/jni/jni_gl_display_handler.h" |
6 | 6 |
| 7 #include <android/native_window_jni.h> |
| 8 #include <array> |
| 9 |
| 10 #include "base/android/jni_android.h" |
| 11 #include "base/bind.h" |
7 #include "base/logging.h" | 12 #include "base/logging.h" |
| 13 #include "base/memory/ptr_util.h" |
8 #include "jni/GlDisplay_jni.h" | 14 #include "jni/GlDisplay_jni.h" |
| 15 #include "remoting/client/cursor_shape_stub_proxy.h" |
| 16 #include "remoting/client/dual_buffer_frame_consumer.h" |
9 #include "remoting/client/jni/chromoting_jni_runtime.h" | 17 #include "remoting/client/jni/chromoting_jni_runtime.h" |
10 #include "remoting/protocol/video_renderer.h" | 18 #include "remoting/client/jni/egl_thread_context.h" |
| 19 #include "remoting/client/software_video_renderer.h" |
| 20 #include "remoting/protocol/frame_consumer.h" |
| 21 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h" |
| 22 |
11 | 23 |
12 namespace remoting { | 24 namespace remoting { |
13 | 25 |
14 JniGlDisplayHandler::JniGlDisplayHandler(ChromotingJniRuntime* runtime) : | 26 JniGlDisplayHandler::JniGlDisplayHandler(ChromotingJniRuntime* runtime) : |
15 runtime_(runtime) { | 27 runtime_(runtime), |
| 28 weak_factory_(this) { |
| 29 weak_ptr_ = weak_factory_.GetWeakPtr(); |
16 java_display_.Reset(Java_GlDisplay_createJavaDisplayObject( | 30 java_display_.Reset(Java_GlDisplay_createJavaDisplayObject( |
17 base::android::AttachCurrentThread(), reinterpret_cast<intptr_t>(this))); | 31 base::android::AttachCurrentThread(), reinterpret_cast<intptr_t>(this))); |
| 32 renderer_.SetDelegate(weak_ptr_); |
18 } | 33 } |
19 | 34 |
20 JniGlDisplayHandler::~JniGlDisplayHandler() { | 35 JniGlDisplayHandler::~JniGlDisplayHandler() { |
21 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread()); | 36 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread()); |
22 Java_GlDisplay_invalidate(base::android::AttachCurrentThread(), | 37 Java_GlDisplay_invalidate(base::android::AttachCurrentThread(), |
23 java_display_.obj()); | 38 java_display_.obj()); |
24 } | 39 } |
25 | 40 |
26 void JniGlDisplayHandler::InitializeClient( | 41 void JniGlDisplayHandler::InitializeClient( |
27 const base::android::JavaRef<jobject>& java_client) { | 42 const base::android::JavaRef<jobject>& java_client) { |
28 return Java_GlDisplay_initializeClient(base::android::AttachCurrentThread(), | 43 return Java_GlDisplay_initializeClient(base::android::AttachCurrentThread(), |
29 java_display_.obj(), | 44 java_display_.obj(), |
30 java_client.obj()); | 45 java_client.obj()); |
31 } | 46 } |
32 | 47 |
| 48 void JniGlDisplayHandler::SetCursorShape( |
| 49 const protocol::CursorShapeInfo& cursor_shape) { |
| 50 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread()); |
| 51 renderer_.OnCursorShapeChanged(cursor_shape); |
| 52 } |
| 53 |
33 std::unique_ptr<protocol::CursorShapeStub> | 54 std::unique_ptr<protocol::CursorShapeStub> |
34 JniGlDisplayHandler::CreateCursorShapeStub() { | 55 JniGlDisplayHandler::CreateCursorShapeStub() { |
35 NOTIMPLEMENTED(); | 56 return base::WrapUnique(new CursorShapeStubProxy( |
36 return std::unique_ptr<protocol::CursorShapeStub>(); | 57 weak_ptr_, runtime_->display_task_runner())); |
37 } | 58 } |
38 | 59 |
39 std::unique_ptr<protocol::VideoRenderer> | 60 std::unique_ptr<protocol::VideoRenderer> |
40 JniGlDisplayHandler::CreateVideoRenderer() { | 61 JniGlDisplayHandler::CreateVideoRenderer() { |
41 NOTIMPLEMENTED(); | 62 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); |
42 return std::unique_ptr<protocol::VideoRenderer>(); | 63 DCHECK(!frame_consumer_); |
| 64 std::unique_ptr<DualBufferFrameConsumer> consumer = base::WrapUnique( |
| 65 new DualBufferFrameConsumer( |
| 66 base::Bind(&GlRenderer::OnFrameReceived, renderer_.GetWeakPtr()), |
| 67 runtime_->display_task_runner(), |
| 68 protocol::FrameConsumer::PixelFormat::FORMAT_RGBA)); |
| 69 frame_consumer_ = consumer->GetWeakPtr(); |
| 70 return base::WrapUnique(new SoftwareVideoRenderer(std::move(consumer))); |
43 } | 71 } |
44 | 72 |
45 // static | 73 // static |
46 bool JniGlDisplayHandler::RegisterJni(JNIEnv* env) { | 74 bool JniGlDisplayHandler::RegisterJni(JNIEnv* env) { |
47 return RegisterNativesImpl(env); | 75 return RegisterNativesImpl(env); |
48 } | 76 } |
49 | 77 |
50 void JniGlDisplayHandler::OnSurfaceCreated( | 78 void JniGlDisplayHandler::OnSurfaceCreated( |
51 JNIEnv* env, | 79 JNIEnv* env, |
52 const base::android::JavaParamRef<jobject>& caller, | 80 const base::android::JavaParamRef<jobject>& caller, |
53 const base::android::JavaParamRef<jobject>& surface) { | 81 const base::android::JavaParamRef<jobject>& surface) { |
54 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); | 82 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); |
55 NOTIMPLEMENTED(); | 83 |
| 84 // Notifies the Java surface of the canvas size if the surface is recreated. |
| 85 runtime_->display_task_runner()->PostTask( |
| 86 FROM_HERE, |
| 87 base::Bind(&JniGlDisplayHandler::SurfaceCreatedOnDisplayThread, weak_ptr_, |
| 88 base::android::ScopedJavaGlobalRef<jobject>(env, surface))); |
| 89 } |
| 90 |
| 91 bool JniGlDisplayHandler::CanRenderFrame() { |
| 92 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread()); |
| 93 return !rendering_blocked_ && egl_context_ && egl_context_->IsWindowBound(); |
| 94 } |
| 95 |
| 96 void JniGlDisplayHandler::OnFrameRendered() { |
| 97 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread()); |
| 98 egl_context_->SwapBuffers(); |
| 99 if (render_event_enabled_) { |
| 100 runtime_->ui_task_runner()->PostTask( |
| 101 FROM_HERE, base::Bind(&JniGlDisplayHandler::NotifyRenderDoneOnUiThread, |
| 102 java_display_)); |
| 103 } |
| 104 } |
| 105 |
| 106 void JniGlDisplayHandler::OnSizeChanged(int width, int height) { |
| 107 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread()); |
| 108 runtime_->ui_task_runner()->PostTask( |
| 109 FROM_HERE, base::Bind(&JniGlDisplayHandler::ChangeCanvasSizeOnUiThread, |
| 110 java_display_, |
| 111 width, |
| 112 height)); |
56 } | 113 } |
57 | 114 |
58 void JniGlDisplayHandler::OnSurfaceChanged( | 115 void JniGlDisplayHandler::OnSurfaceChanged( |
59 JNIEnv* env, | 116 JNIEnv* env, |
60 const base::android::JavaParamRef<jobject>& caller, | 117 const base::android::JavaParamRef<jobject>& caller, |
61 int width, | 118 int width, |
62 int height) { | 119 int height) { |
63 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); | 120 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); |
64 NOTIMPLEMENTED(); | 121 runtime_->display_task_runner()->PostTask( |
| 122 FROM_HERE, base::Bind(&GlRenderer::OnSurfaceChanged, |
| 123 renderer_.GetWeakPtr(), width, height)); |
65 } | 124 } |
66 | 125 |
67 void JniGlDisplayHandler::OnSurfaceDestroyed( | 126 void JniGlDisplayHandler::OnSurfaceDestroyed( |
68 JNIEnv* env, | 127 JNIEnv* env, |
69 const base::android::JavaParamRef<jobject>& caller) { | 128 const base::android::JavaParamRef<jobject>& caller) { |
70 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); | 129 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); |
71 NOTIMPLEMENTED(); | 130 runtime_->display_task_runner()->PostTask( |
| 131 FROM_HERE, |
| 132 base::Bind(&JniGlDisplayHandler::SurfaceDestroyedOnDisplayThread, |
| 133 weak_ptr_)); |
72 } | 134 } |
73 | 135 |
74 void JniGlDisplayHandler::OnPixelTransformationChanged( | 136 void JniGlDisplayHandler::OnPixelTransformationChanged( |
75 JNIEnv* env, | 137 JNIEnv* env, |
76 const base::android::JavaParamRef<jobject>& caller, | 138 const base::android::JavaParamRef<jobject>& caller, |
77 const base::android::JavaParamRef<jfloatArray>& jmatrix) { | 139 const base::android::JavaParamRef<jfloatArray>& jmatrix) { |
78 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); | 140 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); |
79 NOTIMPLEMENTED(); | 141 DCHECK(env->GetArrayLength(jmatrix.obj()) == 9); |
| 142 runtime_->display_task_runner()->PostTask(FROM_HERE, base::Bind( |
| 143 &JniGlDisplayHandler::ChangePixelTransformationOnDisplayThread, |
| 144 weak_ptr_, base::android::ScopedJavaGlobalRef<jfloatArray>(jmatrix))); |
80 } | 145 } |
81 | 146 |
82 void JniGlDisplayHandler::OnCursorPixelPositionChanged( | 147 void JniGlDisplayHandler::OnCursorPixelPositionChanged( |
83 JNIEnv* env, | 148 JNIEnv* env, |
84 const base::android::JavaParamRef<jobject>& caller, | 149 const base::android::JavaParamRef<jobject>& caller, |
85 int x, | 150 int x, |
86 int y) { | 151 int y, |
| 152 bool followed_by_viewport_move) { |
87 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); | 153 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); |
88 NOTIMPLEMENTED(); | 154 runtime_->display_task_runner()->PostTask( |
| 155 FROM_HERE, |
| 156 base::Bind(&JniGlDisplayHandler::ChangeCursorPositionOnDisplayThread, |
| 157 weak_ptr_, x, y, followed_by_viewport_move)); |
89 } | 158 } |
90 | 159 |
91 void JniGlDisplayHandler::OnCursorVisibilityChanged( | 160 void JniGlDisplayHandler::OnCursorVisibilityChanged( |
92 JNIEnv* env, | 161 JNIEnv* env, |
93 const base::android::JavaParamRef<jobject>& caller, | 162 const base::android::JavaParamRef<jobject>& caller, |
94 bool visible) { | 163 bool visible) { |
95 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); | 164 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); |
96 NOTIMPLEMENTED(); | 165 runtime_->display_task_runner()->PostTask( |
| 166 FROM_HERE, |
| 167 base::Bind(&GlRenderer::OnCursorVisibilityChanged, |
| 168 renderer_.GetWeakPtr(), visible)); |
97 } | 169 } |
98 | 170 |
99 void JniGlDisplayHandler::OnCursorInputFeedback( | 171 void JniGlDisplayHandler::OnCursorInputFeedback( |
100 JNIEnv* env, | 172 JNIEnv* env, |
101 const base::android::JavaParamRef<jobject>& caller, | 173 const base::android::JavaParamRef<jobject>& caller, |
102 int x, | 174 int x, |
103 int y, | 175 int y, |
104 float diameter) { | 176 float diameter) { |
105 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); | 177 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); |
106 NOTIMPLEMENTED(); | 178 runtime_->display_task_runner()->PostTask( |
| 179 FROM_HERE, |
| 180 base::Bind(&GlRenderer::OnCursorInputFeedback, |
| 181 renderer_.GetWeakPtr(), x, y, diameter)); |
107 } | 182 } |
108 | 183 |
109 void JniGlDisplayHandler::SetRenderEventEnabled( | 184 void JniGlDisplayHandler::SetRenderEventEnabled( |
110 JNIEnv* env, | 185 JNIEnv* env, |
111 const base::android::JavaParamRef<jobject>& caller, | 186 const base::android::JavaParamRef<jobject>& caller, |
112 jboolean enabled) { | 187 jboolean enabled) { |
113 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); | 188 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); |
114 NOTIMPLEMENTED(); | 189 runtime_->display_task_runner()->PostTask(FROM_HERE, base::Bind( |
| 190 &JniGlDisplayHandler::SetRenderEventEnabledOnDisplayThread, weak_ptr_, |
| 191 enabled)); |
| 192 } |
| 193 |
| 194 void JniGlDisplayHandler::SetRenderEventEnabledOnDisplayThread(bool enabled) { |
| 195 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread()); |
| 196 render_event_enabled_ = enabled; |
115 } | 197 } |
116 | 198 |
117 // static | 199 // static |
118 void JniGlDisplayHandler::NotifyRenderEventOnUiThread( | 200 void JniGlDisplayHandler::NotifyRenderDoneOnUiThread( |
119 base::android::ScopedJavaGlobalRef<jobject> java_client) { | 201 base::android::ScopedJavaGlobalRef<jobject> java_display) { |
120 Java_GlDisplay_canvasRendered(base::android::AttachCurrentThread(), | 202 Java_GlDisplay_canvasRendered(base::android::AttachCurrentThread(), |
121 java_client.obj()); | 203 java_display.obj()); |
| 204 } |
| 205 |
| 206 void JniGlDisplayHandler::SurfaceCreatedOnDisplayThread( |
| 207 base::android::ScopedJavaGlobalRef<jobject> surface) { |
| 208 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread()); |
| 209 renderer_.RequestCanvasSize(); |
| 210 ANativeWindow* window = ANativeWindow_fromSurface( |
| 211 base::android::AttachCurrentThread(), surface.obj()); |
| 212 egl_context_.reset(new EglThreadContext()); |
| 213 egl_context_->BindToWindow(window); |
| 214 ANativeWindow_release(window); |
| 215 renderer_.OnSurfaceCreated(static_cast<int>(egl_context_->client_version())); |
| 216 runtime_->network_task_runner()->PostTask( |
| 217 FROM_HERE, base::Bind(&DualBufferFrameConsumer::RequestFullDesktopFrame, |
| 218 frame_consumer_)); |
| 219 } |
| 220 |
| 221 void JniGlDisplayHandler::SurfaceDestroyedOnDisplayThread() { |
| 222 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread()); |
| 223 renderer_.OnSurfaceDestroyed(); |
| 224 egl_context_.reset(); |
| 225 } |
| 226 |
| 227 void JniGlDisplayHandler::ChangePixelTransformationOnDisplayThread( |
| 228 base::android::ScopedJavaGlobalRef<jfloatArray> jmatrix) { |
| 229 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread()); |
| 230 rendering_blocked_ = false; |
| 231 JNIEnv* env = base::android::AttachCurrentThread(); |
| 232 |
| 233 std::array<float, 9> matrix; |
| 234 |
| 235 env->GetFloatArrayRegion(jmatrix.obj(), 0, 9, matrix.data()); |
| 236 renderer_.OnPixelTransformationChanged(matrix); |
| 237 } |
| 238 |
| 239 void JniGlDisplayHandler::ChangeCursorPositionOnDisplayThread( |
| 240 int x, |
| 241 int y, |
| 242 bool followed_by_viewport_move) { |
| 243 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread()); |
| 244 if (followed_by_viewport_move) { |
| 245 rendering_blocked_ = true; |
| 246 } |
| 247 renderer_.OnCursorMoved(x, y); |
122 } | 248 } |
123 | 249 |
124 // static | 250 // static |
125 void JniGlDisplayHandler::ChangeCanvasSizeOnUiThread( | 251 void JniGlDisplayHandler::ChangeCanvasSizeOnUiThread( |
126 base::android::ScopedJavaGlobalRef<jobject> java_client, | 252 base::android::ScopedJavaGlobalRef<jobject> java_display, |
127 int width, | 253 int width, |
128 int height) { | 254 int height) { |
129 JNIEnv* env = base::android::AttachCurrentThread(); | 255 JNIEnv* env = base::android::AttachCurrentThread(); |
130 Java_GlDisplay_changeCanvasSize(env, java_client.obj(), width, height); | 256 Java_GlDisplay_changeCanvasSize(env, java_display.obj(), width, height); |
131 } | 257 } |
132 | 258 |
133 } // namespace remoting | 259 } // namespace remoting |
OLD | NEW |