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 |