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

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: Add override for ~Core() 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
« no previous file with comments | « remoting/client/jni/jni_gl_display_handler.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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() override;
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 // Returns the frame consumer for updating desktop frame. Can be called on any
40 // thread but no more than once.
41 std::unique_ptr<protocol::FrameConsumer> GrabFrameConsumer();
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
58 // Will be std::move'd when GrabFrameConsumer() is called.
59 std::unique_ptr<DualBufferFrameConsumer> owned_frame_consumer_;
60
61 base::WeakPtr<DualBufferFrameConsumer> frame_consumer_;
62
63 ANativeWindow* window_ = nullptr;
64 std::unique_ptr<EglThreadContext> egl_context_;
65 GlRenderer renderer_;
66
67 // Used on display thread.
68 base::WeakPtr<Core> weak_ptr_;
69 base::WeakPtrFactory<Core> weak_factory_;
70
71 DISALLOW_COPY_AND_ASSIGN(Core);
72 };
73
74 JniGlDisplayHandler::Core::Core(ChromotingJniRuntime* runtime,
75 base::WeakPtr<JniGlDisplayHandler> shell)
76 : runtime_(runtime), shell_(shell), weak_factory_(this) {
27 weak_ptr_ = weak_factory_.GetWeakPtr(); 77 weak_ptr_ = weak_factory_.GetWeakPtr();
78 renderer_.SetDelegate(weak_ptr_);
79 owned_frame_consumer_.reset(new DualBufferFrameConsumer(
80 base::Bind(&GlRenderer::OnFrameReceived, renderer_.GetWeakPtr()),
81 runtime_->display_task_runner(),
82 protocol::FrameConsumer::PixelFormat::FORMAT_RGBA));
83 frame_consumer_ = owned_frame_consumer_->GetWeakPtr();
84 }
85
86 JniGlDisplayHandler::Core::~Core() {}
87
88 bool JniGlDisplayHandler::Core::CanRenderFrame() {
89 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
90 return egl_context_ && egl_context_->IsWindowBound();
91 }
92
93 void JniGlDisplayHandler::Core::OnFrameRendered() {
94 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
95 egl_context_->SwapBuffers();
96 runtime_->ui_task_runner()->PostTask(
97 FROM_HERE, base::Bind(&JniGlDisplayHandler::OnRenderDone, shell_));
98 }
99
100 void JniGlDisplayHandler::Core::OnSizeChanged(int width, int height) {
101 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
102 runtime_->ui_task_runner()->PostTask(
103 FROM_HERE, base::Bind(&JniGlDisplayHandler::OnCanvasSizeChanged, shell_,
104 width, height));
105 }
106
107 void JniGlDisplayHandler::Core::SetCursorShape(
108 const protocol::CursorShapeInfo& cursor_shape) {
109 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
110 renderer_.OnCursorShapeChanged(cursor_shape);
111 }
112
113 std::unique_ptr<protocol::FrameConsumer>
114 JniGlDisplayHandler::Core::GrabFrameConsumer() {
115 DCHECK(owned_frame_consumer_) << "The frame consumer is already grabbed.";
116 return std::move(owned_frame_consumer_);
117 }
118
119 void JniGlDisplayHandler::Core::SurfaceCreated(
120 base::android::ScopedJavaGlobalRef<jobject> surface) {
121 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
122 DCHECK(!egl_context_);
123 DCHECK(!window_);
124 renderer_.RequestCanvasSize();
125 window_ = ANativeWindow_fromSurface(base::android::AttachCurrentThread(),
126 surface.obj());
127 egl_context_.reset(new EglThreadContext());
128 egl_context_->BindToWindow(window_);
129 renderer_.OnSurfaceCreated(static_cast<int>(egl_context_->client_version()));
130 runtime_->network_task_runner()->PostTask(
131 FROM_HERE, base::Bind(&DualBufferFrameConsumer::RequestFullDesktopFrame,
132 frame_consumer_));
133 }
134
135 void JniGlDisplayHandler::Core::SurfaceChanged(int width, int height) {
136 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
137 renderer_.OnSurfaceChanged(width, height);
138 }
139
140 void JniGlDisplayHandler::Core::SurfaceDestroyed() {
141 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
142 DCHECK(egl_context_);
143 DCHECK(window_);
144 renderer_.OnSurfaceDestroyed();
145 egl_context_.reset();
146 ANativeWindow_release(window_);
147 window_ = nullptr;
148 }
149
150 void JniGlDisplayHandler::Core::SetTransformation(
151 const std::array<float, 9>& matrix) {
152 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
153 renderer_.OnPixelTransformationChanged(matrix);
154 }
155
156 void JniGlDisplayHandler::Core::MoveCursor(float x, float y) {
157 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
158 renderer_.OnCursorMoved(x, y);
159 }
160
161 void JniGlDisplayHandler::Core::SetCursorVisibility(bool visible) {
162 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
163 renderer_.OnCursorVisibilityChanged(visible);
164 }
165
166 void JniGlDisplayHandler::Core::StartInputFeedback(float x,
167 float y,
168 float diameter) {
169 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
170 renderer_.OnCursorInputFeedback(x, y, diameter);
171 }
172
173 base::WeakPtr<JniGlDisplayHandler::Core>
174 JniGlDisplayHandler::Core::GetWeakPtr() {
175 return weak_ptr_;
176 }
177
178 // Shell implementations.
179
180 JniGlDisplayHandler::JniGlDisplayHandler(
181 ChromotingJniRuntime* runtime,
182 const base::android::JavaRef<jobject>& java_client)
183 : runtime_(runtime),
184 ui_task_poster_(runtime->display_task_runner()),
185 weak_factory_(this) {
186 core_.reset(new Core(runtime_, weak_factory_.GetWeakPtr()));
187 JNIEnv* env = base::android::AttachCurrentThread();
28 java_display_.Reset(Java_GlDisplay_createJavaDisplayObject( 188 java_display_.Reset(Java_GlDisplay_createJavaDisplayObject(
29 base::android::AttachCurrentThread(), reinterpret_cast<intptr_t>(this))); 189 env, reinterpret_cast<intptr_t>(this)));
30 renderer_.SetDelegate(weak_ptr_); 190 Java_GlDisplay_initializeClient(env, java_display_, java_client);
31 ui_task_poster_.reset(new QueuedTaskPoster(runtime->display_task_runner()));
32 } 191 }
33 192
34 JniGlDisplayHandler::~JniGlDisplayHandler() { 193 JniGlDisplayHandler::~JniGlDisplayHandler() {
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 }
39
40 void JniGlDisplayHandler::Initialize(
41 const base::android::JavaRef<jobject>& java_client) {
42 Java_GlDisplay_initializeClient(base::android::AttachCurrentThread(),
43 java_display_, java_client);
44 }
45
46 void JniGlDisplayHandler::Invalidate() {
47 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); 194 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
48 Java_GlDisplay_invalidate(base::android::AttachCurrentThread(), 195 Java_GlDisplay_invalidate(base::android::AttachCurrentThread(),
49 java_display_); 196 java_display_);
50 ui_task_poster_.reset(); 197 runtime_->display_task_runner()->DeleteSoon(FROM_HERE, core_.release());
51 } 198 }
52 199
53 std::unique_ptr<protocol::CursorShapeStub> 200 std::unique_ptr<protocol::CursorShapeStub>
54 JniGlDisplayHandler::CreateCursorShapeStub() { 201 JniGlDisplayHandler::CreateCursorShapeStub() {
55 return base::MakeUnique<CursorShapeStubProxy>( 202 return base::MakeUnique<CursorShapeStubProxy>(
56 weak_ptr_, runtime_->display_task_runner()); 203 core_->GetWeakPtr(), runtime_->display_task_runner());
57 } 204 }
58 205
59 std::unique_ptr<protocol::VideoRenderer> 206 std::unique_ptr<protocol::VideoRenderer>
60 JniGlDisplayHandler::CreateVideoRenderer() { 207 JniGlDisplayHandler::CreateVideoRenderer() {
61 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); 208 return base::MakeUnique<SoftwareVideoRenderer>(core_->GrabFrameConsumer());
62 DCHECK(!frame_consumer_);
63 std::unique_ptr<DualBufferFrameConsumer> consumer =
64 base::MakeUnique<DualBufferFrameConsumer>(
65 base::Bind(&GlRenderer::OnFrameReceived, renderer_.GetWeakPtr()),
66 runtime_->display_task_runner(),
67 protocol::FrameConsumer::PixelFormat::FORMAT_RGBA);
68 frame_consumer_ = consumer->GetWeakPtr();
69 return base::MakeUnique<SoftwareVideoRenderer>(std::move(consumer));
70 } 209 }
71 210
72 // static 211 // static
73 bool JniGlDisplayHandler::RegisterJni(JNIEnv* env) { 212 bool JniGlDisplayHandler::RegisterJni(JNIEnv* env) {
74 return RegisterNativesImpl(env); 213 return RegisterNativesImpl(env);
75 } 214 }
76 215
77 void JniGlDisplayHandler::OnSurfaceCreated( 216 void JniGlDisplayHandler::OnSurfaceCreated(
78 JNIEnv* env, 217 JNIEnv* env,
79 const base::android::JavaParamRef<jobject>& caller, 218 const base::android::JavaParamRef<jobject>& caller,
80 const base::android::JavaParamRef<jobject>& surface) { 219 const base::android::JavaParamRef<jobject>& surface) {
81 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); 220 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
82 runtime_->display_task_runner()->PostTask( 221 runtime_->display_task_runner()->PostTask(
83 FROM_HERE, 222 FROM_HERE,
84 base::Bind(&JniGlDisplayHandler::SurfaceCreatedOnDisplayThread, weak_ptr_, 223 base::Bind(&Core::SurfaceCreated, core_->GetWeakPtr(),
85 base::android::ScopedJavaGlobalRef<jobject>(env, surface))); 224 base::android::ScopedJavaGlobalRef<jobject>(env, surface)));
86 } 225 }
87 226
88 void JniGlDisplayHandler::OnSurfaceChanged( 227 void JniGlDisplayHandler::OnSurfaceChanged(
89 JNIEnv* env, 228 JNIEnv* env,
90 const base::android::JavaParamRef<jobject>& caller, 229 const base::android::JavaParamRef<jobject>& caller,
91 int width, 230 int width,
92 int height) { 231 int height) {
93 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); 232 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
94 runtime_->display_task_runner()->PostTask( 233 runtime_->display_task_runner()->PostTask(
95 FROM_HERE, base::Bind(&GlRenderer::OnSurfaceChanged, 234 FROM_HERE,
96 renderer_.GetWeakPtr(), width, height)); 235 base::Bind(&Core::SurfaceChanged, core_->GetWeakPtr(), width, height));
97 } 236 }
98 237
99 void JniGlDisplayHandler::OnSurfaceDestroyed( 238 void JniGlDisplayHandler::OnSurfaceDestroyed(
100 JNIEnv* env, 239 JNIEnv* env,
101 const base::android::JavaParamRef<jobject>& caller) { 240 const base::android::JavaParamRef<jobject>& caller) {
102 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); 241 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
103 runtime_->display_task_runner()->PostTask( 242 runtime_->display_task_runner()->PostTask(
104 FROM_HERE, 243 FROM_HERE, base::Bind(&Core::SurfaceDestroyed, core_->GetWeakPtr()));
105 base::Bind(&JniGlDisplayHandler::SurfaceDestroyedOnDisplayThread,
106 weak_ptr_));
107 } 244 }
108 245
109 void JniGlDisplayHandler::OnPixelTransformationChanged( 246 void JniGlDisplayHandler::OnPixelTransformationChanged(
110 JNIEnv* env, 247 JNIEnv* env,
111 const base::android::JavaParamRef<jobject>& caller, 248 const base::android::JavaParamRef<jobject>& caller,
112 const base::android::JavaParamRef<jfloatArray>& jmatrix) { 249 const base::android::JavaParamRef<jfloatArray>& jmatrix) {
113 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); 250 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
114 DCHECK(env->GetArrayLength(jmatrix.obj()) == 9); 251 DCHECK(env->GetArrayLength(jmatrix.obj()) == 9);
115 std::array<float, 9> matrix; 252 std::array<float, 9> matrix;
116 env->GetFloatArrayRegion(jmatrix.obj(), 0, 9, matrix.data()); 253 env->GetFloatArrayRegion(jmatrix.obj(), 0, 9, matrix.data());
117 PostSequentialTaskOnDisplayThread( 254 ui_task_poster_.AddTask(
118 base::Bind(&GlRenderer::OnPixelTransformationChanged, 255 base::Bind(&Core::SetTransformation, core_->GetWeakPtr(), matrix));
119 renderer_.GetWeakPtr(), matrix));
120 } 256 }
121 257
122 void JniGlDisplayHandler::OnCursorPixelPositionChanged( 258 void JniGlDisplayHandler::OnCursorPixelPositionChanged(
123 JNIEnv* env, 259 JNIEnv* env,
124 const base::android::JavaParamRef<jobject>& caller, 260 const base::android::JavaParamRef<jobject>& caller,
125 float x, 261 float x,
126 float y) { 262 float y) {
127 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); 263 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
128 PostSequentialTaskOnDisplayThread( 264 ui_task_poster_.AddTask(
129 base::Bind(&GlRenderer::OnCursorMoved, renderer_.GetWeakPtr(), x, y)); 265 base::Bind(&Core::MoveCursor, core_->GetWeakPtr(), x, y));
130 } 266 }
131 267
132 void JniGlDisplayHandler::OnCursorVisibilityChanged( 268 void JniGlDisplayHandler::OnCursorVisibilityChanged(
133 JNIEnv* env, 269 JNIEnv* env,
134 const base::android::JavaParamRef<jobject>& caller, 270 const base::android::JavaParamRef<jobject>& caller,
135 bool visible) { 271 bool visible) {
136 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); 272 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
137 PostSequentialTaskOnDisplayThread(base::Bind( 273 ui_task_poster_.AddTask(
138 &GlRenderer::OnCursorVisibilityChanged, renderer_.GetWeakPtr(), visible)); 274 base::Bind(&Core::SetCursorVisibility, core_->GetWeakPtr(), visible));
139 } 275 }
140 276
141 void JniGlDisplayHandler::OnCursorInputFeedback( 277 void JniGlDisplayHandler::OnCursorInputFeedback(
142 JNIEnv* env, 278 JNIEnv* env,
143 const base::android::JavaParamRef<jobject>& caller, 279 const base::android::JavaParamRef<jobject>& caller,
144 float x, 280 float x,
145 float y, 281 float y,
146 float diameter) { 282 float diameter) {
147 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread()); 283 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
148 PostSequentialTaskOnDisplayThread( 284 ui_task_poster_.AddTask(base::Bind(&Core::StartInputFeedback,
149 base::Bind(&GlRenderer::OnCursorInputFeedback, renderer_.GetWeakPtr(), x, 285 core_->GetWeakPtr(), x, y, diameter));
150 y, diameter));
151 } 286 }
152 287
153 void JniGlDisplayHandler::PostSequentialTaskOnDisplayThread( 288 void JniGlDisplayHandler::OnRenderDone() {
154 const base::Closure& task) { 289 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
155 if (!ui_task_poster_) { 290 Java_GlDisplay_canvasRendered(base::android::AttachCurrentThread(),
156 return; 291 java_display_);
157 }
158 ui_task_poster_->AddTask(task);
159 } 292 }
160 293
161 bool JniGlDisplayHandler::CanRenderFrame() { 294 void JniGlDisplayHandler::OnCanvasSizeChanged(int width, int height) {
162 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread()); 295 DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
163 return egl_context_ && egl_context_->IsWindowBound(); 296 Java_GlDisplay_changeCanvasSize(base::android::AttachCurrentThread(),
164 } 297 java_display_, width, height);
165
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
« no previous file with comments | « 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