| 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 2edb220e1fdb411e261809a5fdd442ce9d5143fc..42b2676db8c4a4453883c0ceb9d9f9d1cb1b74da 100644
|
| --- a/remoting/client/jni/jni_gl_display_handler.cc
|
| +++ b/remoting/client/jni/jni_gl_display_handler.cc
|
| @@ -16,57 +16,196 @@
|
| #include "remoting/client/dual_buffer_frame_consumer.h"
|
| #include "remoting/client/jni/chromoting_jni_runtime.h"
|
| #include "remoting/client/jni/egl_thread_context.h"
|
| -#include "remoting/client/queued_task_poster.h"
|
| #include "remoting/client/software_video_renderer.h"
|
| #include "remoting/protocol/frame_consumer.h"
|
|
|
| namespace remoting {
|
|
|
| -JniGlDisplayHandler::JniGlDisplayHandler(ChromotingJniRuntime* runtime)
|
| - : runtime_(runtime), weak_factory_(this) {
|
| +// The core that lives on the display thread.
|
| +class JniGlDisplayHandler::Core : public protocol::CursorShapeStub,
|
| + public GlRendererDelegate {
|
| + public:
|
| + Core(ChromotingJniRuntime* runtime, base::WeakPtr<JniGlDisplayHandler> shell);
|
| + ~Core() override;
|
| +
|
| + // GlRendererDelegate interface.
|
| + bool CanRenderFrame() override;
|
| + void OnFrameRendered() override;
|
| + void OnSizeChanged(int width, int height) override;
|
| +
|
| + // CursorShapeStub interface.
|
| + void SetCursorShape(const protocol::CursorShapeInfo& cursor_shape) override;
|
| +
|
| + // Returns the frame consumer for updating desktop frame. Can be called on any
|
| + // thread but no more than once.
|
| + std::unique_ptr<protocol::FrameConsumer> GrabFrameConsumer();
|
| +
|
| + void SurfaceCreated(base::android::ScopedJavaGlobalRef<jobject> surface);
|
| + void SurfaceChanged(int width, int height);
|
| + void SurfaceDestroyed();
|
| +
|
| + void SetTransformation(const std::array<float, 9>& matrix);
|
| + void MoveCursor(float x, float y);
|
| + void SetCursorVisibility(bool visible);
|
| + void StartInputFeedback(float x, float y, float diameter);
|
| +
|
| + base::WeakPtr<Core> GetWeakPtr();
|
| +
|
| + private:
|
| + ChromotingJniRuntime* runtime_;
|
| + base::WeakPtr<JniGlDisplayHandler> shell_;
|
| +
|
| + // Will be std::move'd when GrabFrameConsumer() is called.
|
| + std::unique_ptr<DualBufferFrameConsumer> owned_frame_consumer_;
|
| +
|
| + base::WeakPtr<DualBufferFrameConsumer> frame_consumer_;
|
| +
|
| + ANativeWindow* window_ = nullptr;
|
| + std::unique_ptr<EglThreadContext> egl_context_;
|
| + GlRenderer renderer_;
|
| +
|
| + // Used on display thread.
|
| + base::WeakPtr<Core> weak_ptr_;
|
| + base::WeakPtrFactory<Core> weak_factory_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(Core);
|
| +};
|
| +
|
| +JniGlDisplayHandler::Core::Core(ChromotingJniRuntime* runtime,
|
| + base::WeakPtr<JniGlDisplayHandler> shell)
|
| + : runtime_(runtime), shell_(shell), 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_);
|
| - ui_task_poster_.reset(new QueuedTaskPoster(runtime->display_task_runner()));
|
| + owned_frame_consumer_.reset(new DualBufferFrameConsumer(
|
| + base::Bind(&GlRenderer::OnFrameReceived, renderer_.GetWeakPtr()),
|
| + runtime_->display_task_runner(),
|
| + protocol::FrameConsumer::PixelFormat::FORMAT_RGBA));
|
| + frame_consumer_ = owned_frame_consumer_->GetWeakPtr();
|
| }
|
|
|
| -JniGlDisplayHandler::~JniGlDisplayHandler() {
|
| +JniGlDisplayHandler::Core::~Core() {}
|
| +
|
| +bool JniGlDisplayHandler::Core::CanRenderFrame() {
|
| + DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
|
| + return egl_context_ && egl_context_->IsWindowBound();
|
| +}
|
| +
|
| +void JniGlDisplayHandler::Core::OnFrameRendered() {
|
| + DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
|
| + egl_context_->SwapBuffers();
|
| + runtime_->ui_task_runner()->PostTask(
|
| + FROM_HERE, base::Bind(&JniGlDisplayHandler::OnRenderDone, shell_));
|
| +}
|
| +
|
| +void JniGlDisplayHandler::Core::OnSizeChanged(int width, int height) {
|
| + DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
|
| + runtime_->ui_task_runner()->PostTask(
|
| + FROM_HERE, base::Bind(&JniGlDisplayHandler::OnCanvasSizeChanged, shell_,
|
| + width, height));
|
| +}
|
| +
|
| +void JniGlDisplayHandler::Core::SetCursorShape(
|
| + const protocol::CursorShapeInfo& cursor_shape) {
|
| + DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
|
| + renderer_.OnCursorShapeChanged(cursor_shape);
|
| +}
|
| +
|
| +std::unique_ptr<protocol::FrameConsumer>
|
| +JniGlDisplayHandler::Core::GrabFrameConsumer() {
|
| + DCHECK(owned_frame_consumer_) << "The frame consumer is already grabbed.";
|
| + return std::move(owned_frame_consumer_);
|
| +}
|
| +
|
| +void JniGlDisplayHandler::Core::SurfaceCreated(
|
| + base::android::ScopedJavaGlobalRef<jobject> surface) {
|
| + DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
|
| + DCHECK(!egl_context_);
|
| + DCHECK(!window_);
|
| + renderer_.RequestCanvasSize();
|
| + window_ = ANativeWindow_fromSurface(base::android::AttachCurrentThread(),
|
| + surface.obj());
|
| + egl_context_.reset(new EglThreadContext());
|
| + egl_context_->BindToWindow(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::Core::SurfaceChanged(int width, int height) {
|
| + DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
|
| + renderer_.OnSurfaceChanged(width, height);
|
| +}
|
| +
|
| +void JniGlDisplayHandler::Core::SurfaceDestroyed() {
|
| + DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
|
| + DCHECK(egl_context_);
|
| + DCHECK(window_);
|
| + renderer_.OnSurfaceDestroyed();
|
| + egl_context_.reset();
|
| + ANativeWindow_release(window_);
|
| + window_ = nullptr;
|
| +}
|
| +
|
| +void JniGlDisplayHandler::Core::SetTransformation(
|
| + const std::array<float, 9>& matrix) {
|
| + DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
|
| + renderer_.OnPixelTransformationChanged(matrix);
|
| +}
|
| +
|
| +void JniGlDisplayHandler::Core::MoveCursor(float x, float y) {
|
| DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
|
| - DCHECK(!ui_task_poster_) << "Invalidate() must be called on the UI thread "
|
| - "before deleting this object.";
|
| + renderer_.OnCursorMoved(x, y);
|
| }
|
|
|
| -void JniGlDisplayHandler::Initialize(
|
| - const base::android::JavaRef<jobject>& java_client) {
|
| - Java_GlDisplay_initializeClient(base::android::AttachCurrentThread(),
|
| - java_display_, java_client);
|
| +void JniGlDisplayHandler::Core::SetCursorVisibility(bool visible) {
|
| + DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
|
| + renderer_.OnCursorVisibilityChanged(visible);
|
| +}
|
| +
|
| +void JniGlDisplayHandler::Core::StartInputFeedback(float x,
|
| + float y,
|
| + float diameter) {
|
| + DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
|
| + renderer_.OnCursorInputFeedback(x, y, diameter);
|
| }
|
|
|
| -void JniGlDisplayHandler::Invalidate() {
|
| +base::WeakPtr<JniGlDisplayHandler::Core>
|
| +JniGlDisplayHandler::Core::GetWeakPtr() {
|
| + return weak_ptr_;
|
| +}
|
| +
|
| +// Shell implementations.
|
| +
|
| +JniGlDisplayHandler::JniGlDisplayHandler(
|
| + ChromotingJniRuntime* runtime,
|
| + const base::android::JavaRef<jobject>& java_client)
|
| + : runtime_(runtime),
|
| + ui_task_poster_(runtime->display_task_runner()),
|
| + weak_factory_(this) {
|
| + core_.reset(new Core(runtime_, weak_factory_.GetWeakPtr()));
|
| + JNIEnv* env = base::android::AttachCurrentThread();
|
| + java_display_.Reset(Java_GlDisplay_createJavaDisplayObject(
|
| + env, reinterpret_cast<intptr_t>(this)));
|
| + Java_GlDisplay_initializeClient(env, java_display_, java_client);
|
| +}
|
| +
|
| +JniGlDisplayHandler::~JniGlDisplayHandler() {
|
| DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
|
| Java_GlDisplay_invalidate(base::android::AttachCurrentThread(),
|
| java_display_);
|
| - ui_task_poster_.reset();
|
| + runtime_->display_task_runner()->DeleteSoon(FROM_HERE, core_.release());
|
| }
|
|
|
| std::unique_ptr<protocol::CursorShapeStub>
|
| JniGlDisplayHandler::CreateCursorShapeStub() {
|
| return base::MakeUnique<CursorShapeStubProxy>(
|
| - weak_ptr_, runtime_->display_task_runner());
|
| + core_->GetWeakPtr(), runtime_->display_task_runner());
|
| }
|
|
|
| std::unique_ptr<protocol::VideoRenderer>
|
| JniGlDisplayHandler::CreateVideoRenderer() {
|
| - DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
|
| - DCHECK(!frame_consumer_);
|
| - std::unique_ptr<DualBufferFrameConsumer> consumer =
|
| - base::MakeUnique<DualBufferFrameConsumer>(
|
| - base::Bind(&GlRenderer::OnFrameReceived, renderer_.GetWeakPtr()),
|
| - runtime_->display_task_runner(),
|
| - protocol::FrameConsumer::PixelFormat::FORMAT_RGBA);
|
| - frame_consumer_ = consumer->GetWeakPtr();
|
| - return base::MakeUnique<SoftwareVideoRenderer>(std::move(consumer));
|
| + return base::MakeUnique<SoftwareVideoRenderer>(core_->GrabFrameConsumer());
|
| }
|
|
|
| // static
|
| @@ -81,7 +220,7 @@ void JniGlDisplayHandler::OnSurfaceCreated(
|
| DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
|
| runtime_->display_task_runner()->PostTask(
|
| FROM_HERE,
|
| - base::Bind(&JniGlDisplayHandler::SurfaceCreatedOnDisplayThread, weak_ptr_,
|
| + base::Bind(&Core::SurfaceCreated, core_->GetWeakPtr(),
|
| base::android::ScopedJavaGlobalRef<jobject>(env, surface)));
|
| }
|
|
|
| @@ -92,8 +231,8 @@ void JniGlDisplayHandler::OnSurfaceChanged(
|
| int height) {
|
| DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
|
| runtime_->display_task_runner()->PostTask(
|
| - FROM_HERE, base::Bind(&GlRenderer::OnSurfaceChanged,
|
| - renderer_.GetWeakPtr(), width, height));
|
| + FROM_HERE,
|
| + base::Bind(&Core::SurfaceChanged, core_->GetWeakPtr(), width, height));
|
| }
|
|
|
| void JniGlDisplayHandler::OnSurfaceDestroyed(
|
| @@ -101,9 +240,7 @@ void JniGlDisplayHandler::OnSurfaceDestroyed(
|
| const base::android::JavaParamRef<jobject>& caller) {
|
| DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
|
| runtime_->display_task_runner()->PostTask(
|
| - FROM_HERE,
|
| - base::Bind(&JniGlDisplayHandler::SurfaceDestroyedOnDisplayThread,
|
| - weak_ptr_));
|
| + FROM_HERE, base::Bind(&Core::SurfaceDestroyed, core_->GetWeakPtr()));
|
| }
|
|
|
| void JniGlDisplayHandler::OnPixelTransformationChanged(
|
| @@ -114,9 +251,8 @@ void JniGlDisplayHandler::OnPixelTransformationChanged(
|
| DCHECK(env->GetArrayLength(jmatrix.obj()) == 9);
|
| std::array<float, 9> matrix;
|
| env->GetFloatArrayRegion(jmatrix.obj(), 0, 9, matrix.data());
|
| - PostSequentialTaskOnDisplayThread(
|
| - base::Bind(&GlRenderer::OnPixelTransformationChanged,
|
| - renderer_.GetWeakPtr(), matrix));
|
| + ui_task_poster_.AddTask(
|
| + base::Bind(&Core::SetTransformation, core_->GetWeakPtr(), matrix));
|
| }
|
|
|
| void JniGlDisplayHandler::OnCursorPixelPositionChanged(
|
| @@ -125,8 +261,8 @@ void JniGlDisplayHandler::OnCursorPixelPositionChanged(
|
| float x,
|
| float y) {
|
| DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
|
| - PostSequentialTaskOnDisplayThread(
|
| - base::Bind(&GlRenderer::OnCursorMoved, renderer_.GetWeakPtr(), x, y));
|
| + ui_task_poster_.AddTask(
|
| + base::Bind(&Core::MoveCursor, core_->GetWeakPtr(), x, y));
|
| }
|
|
|
| void JniGlDisplayHandler::OnCursorVisibilityChanged(
|
| @@ -134,8 +270,8 @@ void JniGlDisplayHandler::OnCursorVisibilityChanged(
|
| const base::android::JavaParamRef<jobject>& caller,
|
| bool visible) {
|
| DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
|
| - PostSequentialTaskOnDisplayThread(base::Bind(
|
| - &GlRenderer::OnCursorVisibilityChanged, renderer_.GetWeakPtr(), visible));
|
| + ui_task_poster_.AddTask(
|
| + base::Bind(&Core::SetCursorVisibility, core_->GetWeakPtr(), visible));
|
| }
|
|
|
| void JniGlDisplayHandler::OnCursorInputFeedback(
|
| @@ -145,80 +281,20 @@ void JniGlDisplayHandler::OnCursorInputFeedback(
|
| float y,
|
| float diameter) {
|
| DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
|
| - PostSequentialTaskOnDisplayThread(
|
| - base::Bind(&GlRenderer::OnCursorInputFeedback, renderer_.GetWeakPtr(), x,
|
| - y, diameter));
|
| -}
|
| -
|
| -void JniGlDisplayHandler::PostSequentialTaskOnDisplayThread(
|
| - const base::Closure& task) {
|
| - if (!ui_task_poster_) {
|
| - return;
|
| - }
|
| - ui_task_poster_->AddTask(task);
|
| -}
|
| -
|
| -bool JniGlDisplayHandler::CanRenderFrame() {
|
| - DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
|
| - return egl_context_ && egl_context_->IsWindowBound();
|
| + ui_task_poster_.AddTask(base::Bind(&Core::StartInputFeedback,
|
| + core_->GetWeakPtr(), x, y, diameter));
|
| }
|
|
|
| -void JniGlDisplayHandler::OnFrameRendered() {
|
| - DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
|
| - egl_context_->SwapBuffers();
|
| - 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::SetCursorShape(
|
| - const protocol::CursorShapeInfo& cursor_shape) {
|
| - DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
|
| - renderer_.OnCursorShapeChanged(cursor_shape);
|
| -}
|
| -
|
| -// static
|
| -void JniGlDisplayHandler::NotifyRenderDoneOnUiThread(
|
| - base::android::ScopedJavaGlobalRef<jobject> java_display) {
|
| +void JniGlDisplayHandler::OnRenderDone() {
|
| + DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
|
| Java_GlDisplay_canvasRendered(base::android::AttachCurrentThread(),
|
| - java_display);
|
| + java_display_);
|
| }
|
|
|
| -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();
|
| -}
|
| -
|
| -// static
|
| -void JniGlDisplayHandler::ChangeCanvasSizeOnUiThread(
|
| - base::android::ScopedJavaGlobalRef<jobject> java_display,
|
| - int width,
|
| - int height) {
|
| - JNIEnv* env = base::android::AttachCurrentThread();
|
| - Java_GlDisplay_changeCanvasSize(env, java_display, width, height);
|
| +void JniGlDisplayHandler::OnCanvasSizeChanged(int width, int height) {
|
| + DCHECK(runtime_->ui_task_runner()->BelongsToCurrentThread());
|
| + Java_GlDisplay_changeCanvasSize(base::android::AttachCurrentThread(),
|
| + java_display_, width, height);
|
| }
|
|
|
| } // namespace remoting
|
|
|