Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(420)

Side by Side Diff: remoting/client/jni/jni_gl_display_handler.cc

Issue 2389463002: [Remoting Android] Separate the display core from JniGlDisplayHandler (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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> 7 #include <android/native_window_jni.h>
8 #include <array> 8 #include <array>
9 9
10 #include "base/android/jni_android.h" 10 #include "base/android/jni_android.h"
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/memory/ptr_util.h" 13 #include "base/memory/ptr_util.h"
14 #include "jni/GlDisplay_jni.h" 14 #include "jni/GlDisplay_jni.h"
15 #include "remoting/client/cursor_shape_stub_proxy.h" 15 #include "remoting/client/cursor_shape_stub_proxy.h"
16 #include "remoting/client/dual_buffer_frame_consumer.h" 16 #include "remoting/client/dual_buffer_frame_consumer.h"
17 #include "remoting/client/jni/chromoting_jni_runtime.h" 17 #include "remoting/client/jni/chromoting_jni_runtime.h"
18 #include "remoting/client/jni/egl_thread_context.h" 18 #include "remoting/client/jni/egl_thread_context.h"
19 #include "remoting/client/queued_task_poster.h"
20 #include "remoting/client/software_video_renderer.h" 19 #include "remoting/client/software_video_renderer.h"
21 #include "remoting/protocol/frame_consumer.h" 20 #include "remoting/protocol/frame_consumer.h"
22 21
23 namespace remoting { 22 namespace remoting {
24 23
25 JniGlDisplayHandler::JniGlDisplayHandler(ChromotingJniRuntime* runtime) 24 // The core that lives on the display thread.
26 : runtime_(runtime), weak_factory_(this) { 25 class JniGlDisplayHandler::Core : public protocol::CursorShapeStub,
26 public GlRendererDelegate {
27 public:
28 Core(ChromotingJniRuntime* runtime, base::WeakPtr<JniGlDisplayHandler> shell);
29 ~Core();
30
31 // GlRendererDelegate interface.
32 bool CanRenderFrame() override;
33 void OnFrameRendered() override;
34 void OnSizeChanged(int width, int height) override;
35
36 // CursorShapeStub interface.
37 void SetCursorShape(const protocol::CursorShapeInfo& cursor_shape) override;
38
39 // Creates the frame consumer for updating desktop frame. Should be called
40 // exactly once.
41 std::unique_ptr<protocol::FrameConsumer> CreateFrameConsumer();
42
43 void SurfaceCreated(base::android::ScopedJavaGlobalRef<jobject> surface);
44 void SurfaceChanged(int width, int height);
45 void SurfaceDestroyed();
46
47 void SetTransformation(const std::array<float, 9>& matrix);
48 void MoveCursor(float x, float y);
49 void SetCursorVisibility(bool visible);
50 void StartInputFeedback(float x, float y, float diameter);
51
52 base::WeakPtr<Core> GetWeakPtr();
53
54 private:
55 ChromotingJniRuntime* runtime_;
56 base::WeakPtr<JniGlDisplayHandler> shell_;
57 base::WeakPtr<DualBufferFrameConsumer> frame_consumer_;
58
59 std::unique_ptr<EglThreadContext> egl_context_;
60 GlRenderer renderer_;
61
62 // Used on display thread.
63 base::WeakPtr<Core> weak_ptr_;
64 base::WeakPtrFactory<Core> weak_factory_;
65
66 DISALLOW_COPY_AND_ASSIGN(Core);
67 };
68
69 JniGlDisplayHandler::Core::Core(ChromotingJniRuntime* runtime,
70 base::WeakPtr<JniGlDisplayHandler> shell) :
71 runtime_(runtime),
72 shell_(shell),
73 weak_factory_(this) {
27 weak_ptr_ = weak_factory_.GetWeakPtr(); 74 weak_ptr_ = weak_factory_.GetWeakPtr();
28 java_display_.Reset(Java_GlDisplay_createJavaDisplayObject(
29 base::android::AttachCurrentThread(), reinterpret_cast<intptr_t>(this)));
30 renderer_.SetDelegate(weak_ptr_); 75 renderer_.SetDelegate(weak_ptr_);
31 ui_task_poster_.reset(new QueuedTaskPoster(runtime->display_task_runner()));
32 } 76 }
33 77
34 JniGlDisplayHandler::~JniGlDisplayHandler() { 78 JniGlDisplayHandler::Core::~Core() {
35 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
36 DCHECK(!ui_task_poster_) << "Invalidate() must be called on the UI thread "
37 "before deleting this object.";
38 } 79 }
39 80
40 void JniGlDisplayHandler::Initialize( 81
41 const base::android::JavaRef<jobject>& java_client) { 82 bool JniGlDisplayHandler::Core::CanRenderFrame() {
42 Java_GlDisplay_initializeClient(base::android::AttachCurrentThread(), 83 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
43 java_display_, java_client); 84 return egl_context_ && egl_context_->IsWindowBound();
44 } 85 }
45 86
46 void JniGlDisplayHandler::Invalidate() { 87 void JniGlDisplayHandler::Core::OnFrameRendered() {
47 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); 88 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
48 Java_GlDisplay_invalidate(base::android::AttachCurrentThread(), 89 egl_context_->SwapBuffers();
49 java_display_); 90 runtime_->ui_task_runner()->PostTask(
50 ui_task_poster_.reset(); 91 FROM_HERE, base::Bind(&JniGlDisplayHandler::OnRenderDone, shell_));
51 } 92 }
52 93
53 std::unique_ptr<protocol::CursorShapeStub> 94 void JniGlDisplayHandler::Core::OnSizeChanged(int width, int height) {
54 JniGlDisplayHandler::CreateCursorShapeStub() { 95 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
55 return base::MakeUnique<CursorShapeStubProxy>( 96 runtime_->ui_task_runner()->PostTask(
56 weak_ptr_, runtime_->display_task_runner()); 97 FROM_HERE, base::Bind(&JniGlDisplayHandler::OnCanvasSizeChanged, shell_,
98 width, height));
57 } 99 }
58 100
59 std::unique_ptr<protocol::VideoRenderer> 101 void JniGlDisplayHandler::Core::SetCursorShape(
60 JniGlDisplayHandler::CreateVideoRenderer() { 102 const protocol::CursorShapeInfo& cursor_shape) {
61 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); 103 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
104 renderer_.OnCursorShapeChanged(cursor_shape);
105 }
106
107 std::unique_ptr<protocol::FrameConsumer>
108 JniGlDisplayHandler::Core::CreateFrameConsumer() {
62 DCHECK(!frame_consumer_); 109 DCHECK(!frame_consumer_);
63 std::unique_ptr<DualBufferFrameConsumer> consumer = 110 std::unique_ptr<DualBufferFrameConsumer> consumer =
64 base::MakeUnique<DualBufferFrameConsumer>( 111 base::MakeUnique<DualBufferFrameConsumer>(
65 base::Bind(&GlRenderer::OnFrameReceived, renderer_.GetWeakPtr()), 112 base::Bind(&GlRenderer::OnFrameReceived, renderer_.GetWeakPtr()),
66 runtime_->display_task_runner(), 113 runtime_->display_task_runner(),
67 protocol::FrameConsumer::PixelFormat::FORMAT_RGBA); 114 protocol::FrameConsumer::PixelFormat::FORMAT_RGBA);
68 frame_consumer_ = consumer->GetWeakPtr(); 115 frame_consumer_ = consumer->GetWeakPtr();
69 return base::MakeUnique<SoftwareVideoRenderer>(std::move(consumer)); 116 return std::move(consumer);
117 }
118
119 void JniGlDisplayHandler::Core::SurfaceCreated(
120 base::android::ScopedJavaGlobalRef<jobject> surface) {
121 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
122 renderer_.RequestCanvasSize();
123 ANativeWindow* window = ANativeWindow_fromSurface(
Yuwei 2016/10/01 00:23:55 It's unsure whether eglCreateWindowSurface acquire
124 base::android::AttachCurrentThread(), surface.obj());
125 egl_context_.reset(new EglThreadContext());
126 egl_context_->BindToWindow(window);
127 ANativeWindow_release(window);
128 renderer_.OnSurfaceCreated(static_cast<int>(egl_context_->client_version()));
129 runtime_->network_task_runner()->PostTask(
130 FROM_HERE, base::Bind(&DualBufferFrameConsumer::RequestFullDesktopFrame,
131 frame_consumer_));
132 }
133
134 void JniGlDisplayHandler::Core::SurfaceChanged(int width, int height) {
135 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
136 renderer_.OnSurfaceChanged(width, height);
137 }
138
139 void JniGlDisplayHandler::Core::SurfaceDestroyed() {
140 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
141 renderer_.OnSurfaceDestroyed();
142 egl_context_.reset();
143 }
144
145 void JniGlDisplayHandler::Core::SetTransformation(
146 const std::array<float, 9>& matrix) {
147 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
148 renderer_.OnPixelTransformationChanged(matrix);
149 }
150
151 void JniGlDisplayHandler::Core::MoveCursor(float x, float y) {
152 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
153 renderer_.OnCursorMoved(x, y);
154 }
155
156
157 void JniGlDisplayHandler::Core::SetCursorVisibility(bool visible) {
158 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
159 renderer_.OnCursorVisibilityChanged(visible);
160 }
161
162
163 void JniGlDisplayHandler::Core::StartInputFeedback(float x,
164 float y,
165 float diameter) {
166 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
167 renderer_.OnCursorInputFeedback(x, y, diameter);
168 }
169
170 base::WeakPtr<JniGlDisplayHandler::Core>
171 JniGlDisplayHandler::Core::GetWeakPtr() {
172 return weak_ptr_;
173 }
174
175 // Shell implementations.
176
177 JniGlDisplayHandler::JniGlDisplayHandler(
178 ChromotingJniRuntime* runtime,
179 const base::android::JavaRef<jobject>& java_client)
180 : runtime_(runtime),
181 ui_task_poster_(runtime->display_task_runner()),
182 weak_factory_(this) {
183 core_.reset(new Core(runtime_, weak_factory_.GetWeakPtr()));
184 JNIEnv* env = base::android::AttachCurrentThread();
185 java_display_.Reset(Java_GlDisplay_createJavaDisplayObject(
186 env, reinterpret_cast<intptr_t>(this)));
187 Java_GlDisplay_initializeClient(env, java_display_, java_client);
188 }
189
190 JniGlDisplayHandler::~JniGlDisplayHandler() {
191 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
192 Java_GlDisplay_invalidate(base::android::AttachCurrentThread(),
193 java_display_);
194 runtime_->display_task_runner()->DeleteSoon(FROM_HERE, core_.release());
195 }
196
197 std::unique_ptr<protocol::CursorShapeStub>
198 JniGlDisplayHandler::CreateCursorShapeStub() {
199 return base::MakeUnique<CursorShapeStubProxy>(
200 core_->GetWeakPtr(), runtime_->display_task_runner());
201 }
202
203 std::unique_ptr<protocol::VideoRenderer>
204 JniGlDisplayHandler::CreateVideoRenderer() {
205 return base::MakeUnique<SoftwareVideoRenderer>(core_->CreateFrameConsumer());
70 } 206 }
71 207
72 // static 208 // static
73 bool JniGlDisplayHandler::RegisterJni(JNIEnv* env) { 209 bool JniGlDisplayHandler::RegisterJni(JNIEnv* env) {
74 return RegisterNativesImpl(env); 210 return RegisterNativesImpl(env);
75 } 211 }
76 212
77 void JniGlDisplayHandler::OnSurfaceCreated( 213 void JniGlDisplayHandler::OnSurfaceCreated(
78 JNIEnv* env, 214 JNIEnv* env,
79 const base::android::JavaParamRef<jobject>& caller, 215 const base::android::JavaParamRef<jobject>& caller,
80 const base::android::JavaParamRef<jobject>& surface) { 216 const base::android::JavaParamRef<jobject>& surface) {
81 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); 217 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
82 runtime_->display_task_runner()->PostTask( 218 runtime_->display_task_runner()->PostTask(
83 FROM_HERE, 219 FROM_HERE,
84 base::Bind(&JniGlDisplayHandler::SurfaceCreatedOnDisplayThread, weak_ptr_, 220 base::Bind(&Core::SurfaceCreated, core_->GetWeakPtr(),
85 base::android::ScopedJavaGlobalRef<jobject>(env, surface))); 221 base::android::ScopedJavaGlobalRef<jobject>(env, surface)));
86 } 222 }
87 223
88 void JniGlDisplayHandler::OnSurfaceChanged( 224 void JniGlDisplayHandler::OnSurfaceChanged(
89 JNIEnv* env, 225 JNIEnv* env,
90 const base::android::JavaParamRef<jobject>& caller, 226 const base::android::JavaParamRef<jobject>& caller,
91 int width, 227 int width,
92 int height) { 228 int height) {
93 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); 229 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
94 runtime_->display_task_runner()->PostTask( 230 runtime_->display_task_runner()->PostTask(
95 FROM_HERE, base::Bind(&GlRenderer::OnSurfaceChanged, 231 FROM_HERE, base::Bind(&Core::SurfaceChanged, core_->GetWeakPtr(),
96 renderer_.GetWeakPtr(), width, height)); 232 width, height));
97 } 233 }
98 234
99 void JniGlDisplayHandler::OnSurfaceDestroyed( 235 void JniGlDisplayHandler::OnSurfaceDestroyed(
100 JNIEnv* env, 236 JNIEnv* env,
101 const base::android::JavaParamRef<jobject>& caller) { 237 const base::android::JavaParamRef<jobject>& caller) {
102 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); 238 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
103 runtime_->display_task_runner()->PostTask( 239 runtime_->display_task_runner()->PostTask(
104 FROM_HERE, 240 FROM_HERE,
105 base::Bind(&JniGlDisplayHandler::SurfaceDestroyedOnDisplayThread, 241 base::Bind(&Core::SurfaceDestroyed,
106 weak_ptr_)); 242 core_->GetWeakPtr()));
107 } 243 }
108 244
109 void JniGlDisplayHandler::OnPixelTransformationChanged( 245 void JniGlDisplayHandler::OnPixelTransformationChanged(
110 JNIEnv* env, 246 JNIEnv* env,
111 const base::android::JavaParamRef<jobject>& caller, 247 const base::android::JavaParamRef<jobject>& caller,
112 const base::android::JavaParamRef<jfloatArray>& jmatrix) { 248 const base::android::JavaParamRef<jfloatArray>& jmatrix) {
113 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); 249 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
114 DCHECK(env->GetArrayLength(jmatrix.obj()) == 9); 250 DCHECK(env->GetArrayLength(jmatrix.obj()) == 9);
115 std::array<float, 9> matrix; 251 std::array<float, 9> matrix;
116 env->GetFloatArrayRegion(jmatrix.obj(), 0, 9, matrix.data()); 252 env->GetFloatArrayRegion(jmatrix.obj(), 0, 9, matrix.data());
117 PostSequentialTaskOnDisplayThread( 253 ui_task_poster_.AddTask(
118 base::Bind(&GlRenderer::OnPixelTransformationChanged, 254 base::Bind(&Core::SetTransformation, core_->GetWeakPtr(), matrix));
119 renderer_.GetWeakPtr(), matrix));
120 } 255 }
121 256
122 void JniGlDisplayHandler::OnCursorPixelPositionChanged( 257 void JniGlDisplayHandler::OnCursorPixelPositionChanged(
123 JNIEnv* env, 258 JNIEnv* env,
124 const base::android::JavaParamRef<jobject>& caller, 259 const base::android::JavaParamRef<jobject>& caller,
125 float x, 260 float x,
126 float y) { 261 float y) {
127 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); 262 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
128 PostSequentialTaskOnDisplayThread( 263 ui_task_poster_.AddTask(base::Bind(&Core::MoveCursor, core_->GetWeakPtr(),
129 base::Bind(&GlRenderer::OnCursorMoved, renderer_.GetWeakPtr(), x, y)); 264 x, y));
130 } 265 }
131 266
132 void JniGlDisplayHandler::OnCursorVisibilityChanged( 267 void JniGlDisplayHandler::OnCursorVisibilityChanged(
133 JNIEnv* env, 268 JNIEnv* env,
134 const base::android::JavaParamRef<jobject>& caller, 269 const base::android::JavaParamRef<jobject>& caller,
135 bool visible) { 270 bool visible) {
136 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); 271 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
137 PostSequentialTaskOnDisplayThread(base::Bind( 272 ui_task_poster_.AddTask(base::Bind(&Core::SetCursorVisibility,
138 &GlRenderer::OnCursorVisibilityChanged, renderer_.GetWeakPtr(), visible)); 273 core_->GetWeakPtr(), visible));
139 } 274 }
140 275
141 void JniGlDisplayHandler::OnCursorInputFeedback( 276 void JniGlDisplayHandler::OnCursorInputFeedback(
142 JNIEnv* env, 277 JNIEnv* env,
143 const base::android::JavaParamRef<jobject>& caller, 278 const base::android::JavaParamRef<jobject>& caller,
144 float x, 279 float x,
145 float y, 280 float y,
146 float diameter) { 281 float diameter) {
147 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); 282 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
148 PostSequentialTaskOnDisplayThread( 283 ui_task_poster_.AddTask(base::Bind(&Core::StartInputFeedback,
149 base::Bind(&GlRenderer::OnCursorInputFeedback, renderer_.GetWeakPtr(), x, 284 core_->GetWeakPtr(), x, y, diameter));
150 y, diameter));
151 } 285 }
152 286
153 void JniGlDisplayHandler::PostSequentialTaskOnDisplayThread( 287 void JniGlDisplayHandler::OnRenderDone() {
154 const base::Closure& task) { 288 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
155 if (!ui_task_poster_) { 289 Java_GlDisplay_canvasRendered(base::android::AttachCurrentThread(),
156 return; 290 java_display_);
157 }
158 ui_task_poster_->AddTask(task);
159 } 291 }
160 292
161 bool JniGlDisplayHandler::CanRenderFrame() { 293 void JniGlDisplayHandler::OnCanvasSizeChanged(int width,
162 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread()); 294 int height) {
163 return egl_context_ && egl_context_->IsWindowBound(); 295 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
164 } 296 Java_GlDisplay_changeCanvasSize(base::android::AttachCurrentThread(),
165 297 java_display_, width, height);
166 void JniGlDisplayHandler::OnFrameRendered() {
167 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
168 egl_context_->SwapBuffers();
169 runtime_->ui_task_runner()->PostTask(
170 FROM_HERE, base::Bind(&JniGlDisplayHandler::NotifyRenderDoneOnUiThread,
171 java_display_));
172 }
173
174 void JniGlDisplayHandler::OnSizeChanged(int width, int height) {
175 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
176 runtime_->ui_task_runner()->PostTask(
177 FROM_HERE, base::Bind(&JniGlDisplayHandler::ChangeCanvasSizeOnUiThread,
178 java_display_, width, height));
179 }
180
181 void JniGlDisplayHandler::SetCursorShape(
182 const protocol::CursorShapeInfo& cursor_shape) {
183 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
184 renderer_.OnCursorShapeChanged(cursor_shape);
185 }
186
187 // static
188 void JniGlDisplayHandler::NotifyRenderDoneOnUiThread(
189 base::android::ScopedJavaGlobalRef<jobject> java_display) {
190 Java_GlDisplay_canvasRendered(base::android::AttachCurrentThread(),
191 java_display);
192 }
193
194 void JniGlDisplayHandler::SurfaceCreatedOnDisplayThread(
195 base::android::ScopedJavaGlobalRef<jobject> surface) {
196 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
197 renderer_.RequestCanvasSize();
198 ANativeWindow* window = ANativeWindow_fromSurface(
199 base::android::AttachCurrentThread(), surface.obj());
200 egl_context_.reset(new EglThreadContext());
201 egl_context_->BindToWindow(window);
202 ANativeWindow_release(window);
203 renderer_.OnSurfaceCreated(static_cast<int>(egl_context_->client_version()));
204 runtime_->network_task_runner()->PostTask(
205 FROM_HERE, base::Bind(&DualBufferFrameConsumer::RequestFullDesktopFrame,
206 frame_consumer_));
207 }
208
209 void JniGlDisplayHandler::SurfaceDestroyedOnDisplayThread() {
210 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
211 renderer_.OnSurfaceDestroyed();
212 egl_context_.reset();
213 }
214
215 // static
216 void JniGlDisplayHandler::ChangeCanvasSizeOnUiThread(
217 base::android::ScopedJavaGlobalRef<jobject> java_display,
218 int width,
219 int height) {
220 JNIEnv* env = base::android::AttachCurrentThread();
221 Java_GlDisplay_changeCanvasSize(env, java_display, width, height);
222 } 298 }
223 299
224 } // namespace remoting 300 } // namespace remoting
OLDNEW
« remoting/client/jni/jni_gl_display_handler.h ('K') | « remoting/client/jni/jni_gl_display_handler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698