| Index: remoting/client/jni/jni_gl_display_handler.cc
|
| diff --git a/remoting/client/jni/jni_gl_display_handler.cc b/remoting/client/jni/jni_gl_display_handler.cc
|
| index 4e86735f96e647f0103743eb6fc41a1ee3061bb0..039a47ee168599409b748ef963194628fbeee8d3 100644
|
| --- a/remoting/client/jni/jni_gl_display_handler.cc
|
| +++ b/remoting/client/jni/jni_gl_display_handler.cc
|
| @@ -4,17 +4,32 @@
|
|
|
| #include "remoting/client/jni/jni_gl_display_handler.h"
|
|
|
| +#include <android/native_window_jni.h>
|
| +#include <array>
|
| +
|
| +#include "base/android/jni_android.h"
|
| +#include "base/bind.h"
|
| #include "base/logging.h"
|
| +#include "base/memory/ptr_util.h"
|
| #include "jni/GlDisplay_jni.h"
|
| +#include "remoting/client/cursor_shape_stub_proxy.h"
|
| +#include "remoting/client/dual_buffer_frame_consumer.h"
|
| #include "remoting/client/jni/chromoting_jni_runtime.h"
|
| -#include "remoting/protocol/video_renderer.h"
|
| +#include "remoting/client/jni/egl_thread_context.h"
|
| +#include "remoting/client/software_video_renderer.h"
|
| +#include "remoting/protocol/frame_consumer.h"
|
| +#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
|
| +
|
|
|
| namespace remoting {
|
|
|
| JniGlDisplayHandler::JniGlDisplayHandler(ChromotingJniRuntime* runtime) :
|
| - runtime_(runtime) {
|
| + runtime_(runtime),
|
| + weak_factory_(this) {
|
| + weak_ptr_ = weak_factory_.GetWeakPtr();
|
| java_display_.Reset(Java_GlDisplay_createJavaDisplayObject(
|
| base::android::AttachCurrentThread(), reinterpret_cast<intptr_t>(this)));
|
| + renderer_.SetDelegate(weak_ptr_);
|
| }
|
|
|
| JniGlDisplayHandler::~JniGlDisplayHandler() {
|
| @@ -30,16 +45,29 @@ void JniGlDisplayHandler::InitializeClient(
|
| java_client.obj());
|
| }
|
|
|
| +void JniGlDisplayHandler::SetCursorShape(
|
| + const protocol::CursorShapeInfo& cursor_shape) {
|
| + DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
|
| + renderer_.OnCursorShapeChanged(cursor_shape);
|
| +}
|
| +
|
| std::unique_ptr<protocol::CursorShapeStub>
|
| JniGlDisplayHandler::CreateCursorShapeStub() {
|
| - NOTIMPLEMENTED();
|
| - return std::unique_ptr<protocol::CursorShapeStub>();
|
| + return base::WrapUnique(new CursorShapeStubProxy(
|
| + weak_ptr_, runtime_->display_task_runner()));
|
| }
|
|
|
| std::unique_ptr<protocol::VideoRenderer>
|
| JniGlDisplayHandler::CreateVideoRenderer() {
|
| - NOTIMPLEMENTED();
|
| - return std::unique_ptr<protocol::VideoRenderer>();
|
| + DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
|
| + DCHECK(!frame_consumer_);
|
| + std::unique_ptr<DualBufferFrameConsumer> consumer = base::WrapUnique(
|
| + new DualBufferFrameConsumer(
|
| + base::Bind(&GlRenderer::OnFrameReceived, renderer_.GetWeakPtr()),
|
| + runtime_->display_task_runner(),
|
| + protocol::FrameConsumer::PixelFormat::FORMAT_RGBA));
|
| + frame_consumer_ = consumer->GetWeakPtr();
|
| + return base::WrapUnique(new SoftwareVideoRenderer(std::move(consumer)));
|
| }
|
|
|
| // static
|
| @@ -52,7 +80,36 @@ void JniGlDisplayHandler::OnSurfaceCreated(
|
| const base::android::JavaParamRef<jobject>& caller,
|
| const base::android::JavaParamRef<jobject>& surface) {
|
| DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
|
| - NOTIMPLEMENTED();
|
| +
|
| + // Notifies the Java surface of the canvas size if the surface is recreated.
|
| + runtime_->display_task_runner()->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&JniGlDisplayHandler::SurfaceCreatedOnDisplayThread, weak_ptr_,
|
| + base::android::ScopedJavaGlobalRef<jobject>(env, surface)));
|
| +}
|
| +
|
| +bool JniGlDisplayHandler::CanRenderFrame() {
|
| + DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
|
| + return !rendering_blocked_ && egl_context_ && egl_context_->IsWindowBound();
|
| +}
|
| +
|
| +void JniGlDisplayHandler::OnFrameRendered() {
|
| + DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
|
| + egl_context_->SwapBuffers();
|
| + if (render_event_enabled_) {
|
| + runtime_->ui_task_runner()->PostTask(
|
| + FROM_HERE, base::Bind(&JniGlDisplayHandler::NotifyRenderDoneOnUiThread,
|
| + java_display_));
|
| + }
|
| +}
|
| +
|
| +void JniGlDisplayHandler::OnSizeChanged(int width, int height) {
|
| + DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
|
| + runtime_->ui_task_runner()->PostTask(
|
| + FROM_HERE, base::Bind(&JniGlDisplayHandler::ChangeCanvasSizeOnUiThread,
|
| + java_display_,
|
| + width,
|
| + height));
|
| }
|
|
|
| void JniGlDisplayHandler::OnSurfaceChanged(
|
| @@ -61,14 +118,19 @@ void JniGlDisplayHandler::OnSurfaceChanged(
|
| int width,
|
| int height) {
|
| DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
|
| - NOTIMPLEMENTED();
|
| + runtime_->display_task_runner()->PostTask(
|
| + FROM_HERE, base::Bind(&GlRenderer::OnSurfaceChanged,
|
| + renderer_.GetWeakPtr(), width, height));
|
| }
|
|
|
| void JniGlDisplayHandler::OnSurfaceDestroyed(
|
| JNIEnv* env,
|
| const base::android::JavaParamRef<jobject>& caller) {
|
| DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
|
| - NOTIMPLEMENTED();
|
| + runtime_->display_task_runner()->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&JniGlDisplayHandler::SurfaceDestroyedOnDisplayThread,
|
| + weak_ptr_));
|
| }
|
|
|
| void JniGlDisplayHandler::OnPixelTransformationChanged(
|
| @@ -76,16 +138,23 @@ void JniGlDisplayHandler::OnPixelTransformationChanged(
|
| const base::android::JavaParamRef<jobject>& caller,
|
| const base::android::JavaParamRef<jfloatArray>& jmatrix) {
|
| DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
|
| - NOTIMPLEMENTED();
|
| + DCHECK(env->GetArrayLength(jmatrix.obj()) == 9);
|
| + runtime_->display_task_runner()->PostTask(FROM_HERE, base::Bind(
|
| + &JniGlDisplayHandler::ChangePixelTransformationOnDisplayThread,
|
| + weak_ptr_, base::android::ScopedJavaGlobalRef<jfloatArray>(jmatrix)));
|
| }
|
|
|
| void JniGlDisplayHandler::OnCursorPixelPositionChanged(
|
| JNIEnv* env,
|
| const base::android::JavaParamRef<jobject>& caller,
|
| int x,
|
| - int y) {
|
| + int y,
|
| + bool followed_by_viewport_move) {
|
| DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
|
| - NOTIMPLEMENTED();
|
| + runtime_->display_task_runner()->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&JniGlDisplayHandler::ChangeCursorPositionOnDisplayThread,
|
| + weak_ptr_, x, y, followed_by_viewport_move));
|
| }
|
|
|
| void JniGlDisplayHandler::OnCursorVisibilityChanged(
|
| @@ -93,7 +162,10 @@ void JniGlDisplayHandler::OnCursorVisibilityChanged(
|
| const base::android::JavaParamRef<jobject>& caller,
|
| bool visible) {
|
| DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
|
| - NOTIMPLEMENTED();
|
| + runtime_->display_task_runner()->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&GlRenderer::OnCursorVisibilityChanged,
|
| + renderer_.GetWeakPtr(), visible));
|
| }
|
|
|
| void JniGlDisplayHandler::OnCursorInputFeedback(
|
| @@ -103,7 +175,10 @@ void JniGlDisplayHandler::OnCursorInputFeedback(
|
| int y,
|
| float diameter) {
|
| DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
|
| - NOTIMPLEMENTED();
|
| + runtime_->display_task_runner()->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&GlRenderer::OnCursorInputFeedback,
|
| + renderer_.GetWeakPtr(), x, y, diameter));
|
| }
|
|
|
| void JniGlDisplayHandler::SetRenderEventEnabled(
|
| @@ -111,23 +186,74 @@ void JniGlDisplayHandler::SetRenderEventEnabled(
|
| const base::android::JavaParamRef<jobject>& caller,
|
| jboolean enabled) {
|
| DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
|
| - NOTIMPLEMENTED();
|
| + runtime_->display_task_runner()->PostTask(FROM_HERE, base::Bind(
|
| + &JniGlDisplayHandler::SetRenderEventEnabledOnDisplayThread, weak_ptr_,
|
| + enabled));
|
| +}
|
| +
|
| +void JniGlDisplayHandler::SetRenderEventEnabledOnDisplayThread(bool enabled) {
|
| + DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
|
| + render_event_enabled_ = enabled;
|
| }
|
|
|
| // static
|
| -void JniGlDisplayHandler::NotifyRenderEventOnUiThread(
|
| - base::android::ScopedJavaGlobalRef<jobject> java_client) {
|
| +void JniGlDisplayHandler::NotifyRenderDoneOnUiThread(
|
| + base::android::ScopedJavaGlobalRef<jobject> java_display) {
|
| Java_GlDisplay_canvasRendered(base::android::AttachCurrentThread(),
|
| - java_client.obj());
|
| + java_display.obj());
|
| +}
|
| +
|
| +void JniGlDisplayHandler::SurfaceCreatedOnDisplayThread(
|
| + base::android::ScopedJavaGlobalRef<jobject> surface) {
|
| + DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
|
| + renderer_.RequestCanvasSize();
|
| + ANativeWindow* window = ANativeWindow_fromSurface(
|
| + base::android::AttachCurrentThread(), surface.obj());
|
| + egl_context_.reset(new EglThreadContext());
|
| + egl_context_->BindToWindow(window);
|
| + ANativeWindow_release(window);
|
| + renderer_.OnSurfaceCreated(static_cast<int>(egl_context_->client_version()));
|
| + runtime_->network_task_runner()->PostTask(
|
| + FROM_HERE, base::Bind(&DualBufferFrameConsumer::RequestFullDesktopFrame,
|
| + frame_consumer_));
|
| +}
|
| +
|
| +void JniGlDisplayHandler::SurfaceDestroyedOnDisplayThread() {
|
| + DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
|
| + renderer_.OnSurfaceDestroyed();
|
| + egl_context_.reset();
|
| +}
|
| +
|
| +void JniGlDisplayHandler::ChangePixelTransformationOnDisplayThread(
|
| + base::android::ScopedJavaGlobalRef<jfloatArray> jmatrix) {
|
| + DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
|
| + rendering_blocked_ = false;
|
| + JNIEnv* env = base::android::AttachCurrentThread();
|
| +
|
| + std::array<float, 9> matrix;
|
| +
|
| + env->GetFloatArrayRegion(jmatrix.obj(), 0, 9, matrix.data());
|
| + renderer_.OnPixelTransformationChanged(matrix);
|
| +}
|
| +
|
| +void JniGlDisplayHandler::ChangeCursorPositionOnDisplayThread(
|
| + int x,
|
| + int y,
|
| + bool followed_by_viewport_move) {
|
| + DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
|
| + if (followed_by_viewport_move) {
|
| + rendering_blocked_ = true;
|
| + }
|
| + renderer_.OnCursorMoved(x, y);
|
| }
|
|
|
| // static
|
| void JniGlDisplayHandler::ChangeCanvasSizeOnUiThread(
|
| - base::android::ScopedJavaGlobalRef<jobject> java_client,
|
| + base::android::ScopedJavaGlobalRef<jobject> java_display,
|
| int width,
|
| int height) {
|
| JNIEnv* env = base::android::AttachCurrentThread();
|
| - Java_GlDisplay_changeCanvasSize(env, java_client.obj(), width, height);
|
| + Java_GlDisplay_changeCanvasSize(env, java_display.obj(), width, height);
|
| }
|
|
|
| } // namespace remoting
|
|
|