| OLD | NEW |
| (Empty) |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #if !defined(__has_feature) || !__has_feature(objc_arc) | |
| 6 #error "This file requires ARC support." | |
| 7 #endif | |
| 8 | |
| 9 #include <array> | |
| 10 | |
| 11 #import "remoting/client/ios/display/gl_display_handler.h" | |
| 12 | |
| 13 #import "base/mac/bind_objc_block.h" | |
| 14 #import "remoting/client/display/sys_opengl.h" | |
| 15 #import "remoting/client/ios/display/gl_demo_screen.h" | |
| 16 | |
| 17 #include "base/bind.h" | |
| 18 #include "base/macros.h" | |
| 19 #include "base/memory/ptr_util.h" | |
| 20 #include "base/memory/weak_ptr.h" | |
| 21 #include "remoting/client/chromoting_client_runtime.h" | |
| 22 #include "remoting/client/cursor_shape_stub_proxy.h" | |
| 23 #include "remoting/client/display/gl_canvas.h" | |
| 24 #include "remoting/client/display/gl_renderer.h" | |
| 25 #include "remoting/client/display/gl_renderer_delegate.h" | |
| 26 #include "remoting/client/dual_buffer_frame_consumer.h" | |
| 27 #include "remoting/client/queued_task_poster.h" | |
| 28 #include "remoting/client/software_video_renderer.h" | |
| 29 | |
| 30 namespace remoting { | |
| 31 namespace GlDisplayHandler { | |
| 32 | |
| 33 // The core that lives on the display thread. | |
| 34 class Core : public protocol::CursorShapeStub, public GlRendererDelegate { | |
| 35 public: | |
| 36 Core(); | |
| 37 ~Core() override; | |
| 38 | |
| 39 void Initialize(); | |
| 40 | |
| 41 void SetHandlerDelegate(id<GlDisplayHandlerDelegate> delegate); | |
| 42 | |
| 43 // CursorShapeStub interface. | |
| 44 void SetCursorShape(const protocol::CursorShapeInfo& cursor_shape) override; | |
| 45 | |
| 46 // GlRendererDelegate interface. | |
| 47 bool CanRenderFrame() override; | |
| 48 void OnFrameRendered() override; | |
| 49 void OnSizeChanged(int width, int height) override; | |
| 50 | |
| 51 void OnFrameReceived(std::unique_ptr<webrtc::DesktopFrame> frame, | |
| 52 const base::Closure& done); | |
| 53 void Stop(); | |
| 54 void SurfaceCreated(GLKView* view); | |
| 55 void SurfaceChanged(int width, int height); | |
| 56 void SetTransformation(const remoting::ViewMatrix& matrix); | |
| 57 std::unique_ptr<protocol::FrameConsumer> GrabFrameConsumer(); | |
| 58 EAGLContext* GetEAGLContext(); | |
| 59 base::WeakPtr<Core> GetWeakPtr(); | |
| 60 | |
| 61 private: | |
| 62 remoting::ChromotingClientRuntime* runtime_; | |
| 63 | |
| 64 // Will be std::move'd when GrabFrameConsumer() is called. | |
| 65 std::unique_ptr<DualBufferFrameConsumer> owned_frame_consumer_; | |
| 66 base::WeakPtr<DualBufferFrameConsumer> frame_consumer_; | |
| 67 | |
| 68 // TODO(yuweih): Release references once the surface is destroyed. | |
| 69 GLKView* gl_view_; | |
| 70 EAGLContext* eagl_context_; | |
| 71 std::unique_ptr<GlRenderer> renderer_; | |
| 72 // GlDemoScreen *demo_screen_; | |
| 73 id<GlDisplayHandlerDelegate> handler_delegate_; | |
| 74 | |
| 75 // Used on display thread. | |
| 76 base::WeakPtr<Core> weak_ptr_; | |
| 77 base::WeakPtrFactory<Core> weak_factory_; | |
| 78 | |
| 79 DISALLOW_COPY_AND_ASSIGN(Core); | |
| 80 }; | |
| 81 | |
| 82 Core::Core() : weak_factory_(this) { | |
| 83 runtime_ = ChromotingClientRuntime::GetInstance(); | |
| 84 DCHECK(!runtime_->display_task_runner()->BelongsToCurrentThread()); | |
| 85 | |
| 86 weak_ptr_ = weak_factory_.GetWeakPtr(); | |
| 87 | |
| 88 runtime_->display_task_runner()->PostTask( | |
| 89 FROM_HERE, base::Bind(&Core::Initialize, base::Unretained(this))); | |
| 90 | |
| 91 // Do not bind GlRenderer::OnFrameReceived. |renderer_| is not ready yet. | |
| 92 owned_frame_consumer_.reset(new remoting::DualBufferFrameConsumer( | |
| 93 base::Bind(&Core::OnFrameReceived, weak_ptr_), | |
| 94 runtime_->display_task_runner(), | |
| 95 protocol::FrameConsumer::PixelFormat::FORMAT_RGBA)); | |
| 96 frame_consumer_ = owned_frame_consumer_->GetWeakPtr(); | |
| 97 } | |
| 98 | |
| 99 Core::~Core() { | |
| 100 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread()); | |
| 101 } | |
| 102 | |
| 103 void Core::Initialize() { | |
| 104 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread()); | |
| 105 | |
| 106 eagl_context_ = [EAGLContext currentContext]; | |
| 107 if (!eagl_context_) { | |
| 108 // TODO(nicholss): For prod code, make sure to check for ES3 support and | |
| 109 // fall back to ES2 if needed. | |
| 110 eagl_context_ = | |
| 111 [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES3]; | |
| 112 [EAGLContext setCurrentContext:eagl_context_]; | |
| 113 } | |
| 114 | |
| 115 renderer_ = remoting::GlRenderer::CreateGlRendererWithDesktop(); | |
| 116 | |
| 117 // renderer_.RequestCanvasSize(); | |
| 118 | |
| 119 // demo_screen_ = new GlDemoScreen(); | |
| 120 // renderer_->AddDrawable(demo_screen_->GetWeakPtr()); | |
| 121 renderer_->SetDelegate(weak_ptr_); | |
| 122 } | |
| 123 | |
| 124 void Core::SetHandlerDelegate(id<GlDisplayHandlerDelegate> delegate) { | |
| 125 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread()); | |
| 126 handler_delegate_ = delegate; | |
| 127 } | |
| 128 | |
| 129 void Core::SetCursorShape(const protocol::CursorShapeInfo& cursor_shape) { | |
| 130 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread()); | |
| 131 renderer_->OnCursorShapeChanged(cursor_shape); | |
| 132 } | |
| 133 | |
| 134 bool Core::CanRenderFrame() { | |
| 135 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread()); | |
| 136 return gl_view_ != NULL && eagl_context_ != NULL; | |
| 137 } | |
| 138 | |
| 139 std::unique_ptr<protocol::FrameConsumer> Core::GrabFrameConsumer() { | |
| 140 DCHECK(owned_frame_consumer_) << "The frame consumer is already grabbed."; | |
| 141 return std::move(owned_frame_consumer_); | |
| 142 } | |
| 143 | |
| 144 void Core::OnFrameReceived(std::unique_ptr<webrtc::DesktopFrame> frame, | |
| 145 const base::Closure& done) { | |
| 146 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread()); | |
| 147 renderer_->OnFrameReceived(std::move(frame), done); | |
| 148 } | |
| 149 | |
| 150 void Core::OnFrameRendered() { | |
| 151 [gl_view_ display]; | |
| 152 } | |
| 153 | |
| 154 void Core::OnSizeChanged(int width, int height) { | |
| 155 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread()); | |
| 156 runtime_->ui_task_runner()->PostTask( | |
| 157 FROM_HERE, base::BindBlockArc(^() { | |
| 158 [handler_delegate_ canvasSizeChanged:CGSizeMake(width, height)]; | |
| 159 })); | |
| 160 } | |
| 161 | |
| 162 void Core::Stop() { | |
| 163 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread()); | |
| 164 | |
| 165 eagl_context_ = nil; | |
| 166 // demo_screen_ = nil; | |
| 167 } | |
| 168 | |
| 169 void Core::SurfaceCreated(GLKView* view) { | |
| 170 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread()); | |
| 171 gl_view_ = view; | |
| 172 | |
| 173 renderer_->OnSurfaceCreated( | |
| 174 base::MakeUnique<GlCanvas>(static_cast<int>([eagl_context_ API]))); | |
| 175 | |
| 176 renderer_->RequestCanvasSize(); | |
| 177 | |
| 178 runtime_->network_task_runner()->PostTask( | |
| 179 FROM_HERE, base::Bind(&DualBufferFrameConsumer::RequestFullDesktopFrame, | |
| 180 frame_consumer_)); | |
| 181 } | |
| 182 | |
| 183 void Core::SurfaceChanged(int width, int height) { | |
| 184 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread()); | |
| 185 renderer_->OnSurfaceChanged(width, height); | |
| 186 } | |
| 187 | |
| 188 void Core::SetTransformation(const remoting::ViewMatrix& matrix) { | |
| 189 DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread()); | |
| 190 renderer_->OnPixelTransformationChanged(matrix.ToMatrixArray()); | |
| 191 } | |
| 192 | |
| 193 EAGLContext* Core::GetEAGLContext() { | |
| 194 return eagl_context_; | |
| 195 } | |
| 196 | |
| 197 base::WeakPtr<remoting::GlDisplayHandler::Core> Core::GetWeakPtr() { | |
| 198 return weak_ptr_; | |
| 199 } | |
| 200 | |
| 201 } // namespace GlDisplayHandler | |
| 202 } // namespace remoting | |
| 203 | |
| 204 @interface GlDisplayHandler () { | |
| 205 remoting::GlDisplayHandler::Core* _core; | |
| 206 remoting::ChromotingClientRuntime* _runtime; | |
| 207 std::unique_ptr<remoting::QueuedTaskPoster> _uiTaskPoster; | |
| 208 } | |
| 209 @end | |
| 210 | |
| 211 @implementation GlDisplayHandler | |
| 212 | |
| 213 - (id)init { | |
| 214 self = [super init]; | |
| 215 if (self) { | |
| 216 _runtime = remoting::ChromotingClientRuntime::GetInstance(); | |
| 217 _core = new remoting::GlDisplayHandler::Core(); | |
| 218 _uiTaskPoster.reset( | |
| 219 new remoting::QueuedTaskPoster(_runtime->display_task_runner())); | |
| 220 } | |
| 221 return self; | |
| 222 } | |
| 223 | |
| 224 #pragma mark - Public | |
| 225 | |
| 226 - (void)stop { | |
| 227 _runtime->display_task_runner()->PostTask( | |
| 228 FROM_HERE, | |
| 229 base::Bind(&remoting::GlDisplayHandler::Core::Stop, _core->GetWeakPtr())); | |
| 230 } | |
| 231 | |
| 232 - (std::unique_ptr<remoting::protocol::VideoRenderer>)CreateVideoRenderer { | |
| 233 return base::MakeUnique<remoting::SoftwareVideoRenderer>( | |
| 234 _core->GrabFrameConsumer()); | |
| 235 } | |
| 236 | |
| 237 - (std::unique_ptr<remoting::protocol::CursorShapeStub>)CreateCursorShapeStub { | |
| 238 return base::MakeUnique<remoting::CursorShapeStubProxy>( | |
| 239 _core->GetWeakPtr(), _runtime->display_task_runner()); | |
| 240 } | |
| 241 | |
| 242 - (EAGLContext*)GetEAGLContext { | |
| 243 return _core->GetEAGLContext(); | |
| 244 } | |
| 245 | |
| 246 - (void)onSurfaceCreated:(GLKView*)view { | |
| 247 _runtime->display_task_runner()->PostTask( | |
| 248 FROM_HERE, base::Bind(&remoting::GlDisplayHandler::Core::SurfaceCreated, | |
| 249 _core->GetWeakPtr(), view)); | |
| 250 } | |
| 251 | |
| 252 - (void)onSurfaceChanged:(const CGRect&)frame { | |
| 253 _runtime->display_task_runner()->PostTask( | |
| 254 FROM_HERE, | |
| 255 base::Bind(&remoting::GlDisplayHandler::Core::SurfaceChanged, | |
| 256 _core->GetWeakPtr(), frame.size.width, frame.size.height)); | |
| 257 } | |
| 258 | |
| 259 - (void)onPixelTransformationChanged:(const remoting::ViewMatrix&)matrix { | |
| 260 _uiTaskPoster->AddTask( | |
| 261 base::Bind(&remoting::GlDisplayHandler::Core::SetTransformation, | |
| 262 _core->GetWeakPtr(), matrix)); | |
| 263 } | |
| 264 | |
| 265 #pragma mark - Properties | |
| 266 | |
| 267 - (void)setDelegate:(id<GlDisplayHandlerDelegate>)delegate { | |
| 268 _runtime->display_task_runner()->PostTask( | |
| 269 FROM_HERE, | |
| 270 base::Bind(&remoting::GlDisplayHandler::Core::SetHandlerDelegate, | |
| 271 _core->GetWeakPtr(), delegate)); | |
| 272 } | |
| 273 | |
| 274 - (id<GlDisplayHandlerDelegate>)delegate { | |
| 275 // Implementation is still required for UNAVAILABLE_ATTRIBUTE. | |
| 276 NOTREACHED(); | |
| 277 return nil; | |
| 278 } | |
| 279 | |
| 280 @end | |
| OLD | NEW |