Commit 807d153f authored by yuweih's avatar yuweih Committed by Commit bot

[Remoting iOS] Fix screen tearing and screen dimensions

This CL:
1. Fixes the screen tearing issue by getting rid of the GLKViewController,
   which runs its rendering loops and swaps buffers in unexpected moment. The
   GL view will now do on-demand buffer swapping, similar to how the Android
   client works.
2. Passes GL view dimensions to the renderer to fix the screen aspect issues.

BUG=716699

Review-Url: https://codereview.chromium.org/2848143002
Cr-Commit-Position: refs/heads/master@{#468418}
parent 879b2fcd
...@@ -5,11 +5,14 @@ ...@@ -5,11 +5,14 @@
#ifndef REMOTING_CLIENT_IOS_APP_HOST_VIEW_CONTROLLER_H_ #ifndef REMOTING_CLIENT_IOS_APP_HOST_VIEW_CONTROLLER_H_
#define REMOTING_CLIENT_IOS_APP_HOST_VIEW_CONTROLLER_H_ #define REMOTING_CLIENT_IOS_APP_HOST_VIEW_CONTROLLER_H_
#import <GLKit/GLKit.h> #import <UIKit/UIKit.h>
@class RemotingClient; @class RemotingClient;
@interface HostViewController : GLKViewController // We don't inherit it from GLKViewController since it uses its rendering loop,
// which will swap buffers when the GLRenderer is writing and causes screen
// tearing issues. Instead we use GlDisplayHandler to handle the rendering loop.
@interface HostViewController : UIViewController
- (id)initWithClient:(RemotingClient*)client; - (id)initWithClient:(RemotingClient*)client;
......
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
#import "remoting/client/ios/app/host_view_controller.h" #import "remoting/client/ios/app/host_view_controller.h"
#import <GLKit/GLKit.h>
#import "ios/third_party/material_components_ios/src/components/Buttons/src/MaterialButtons.h" #import "ios/third_party/material_components_ios/src/components/Buttons/src/MaterialButtons.h"
#import "remoting/client/ios/session/remoting_client.h" #import "remoting/client/ios/session/remoting_client.h"
...@@ -15,6 +17,7 @@ static const CGFloat kFabInset = 15.f; ...@@ -15,6 +17,7 @@ static const CGFloat kFabInset = 15.f;
@interface HostViewController () { @interface HostViewController () {
RemotingClient* _client; RemotingClient* _client;
MDCFloatingButton* _floatingButton;
} }
@end @end
...@@ -30,25 +33,23 @@ static const CGFloat kFabInset = 15.f; ...@@ -30,25 +33,23 @@ static const CGFloat kFabInset = 15.f;
#pragma mark - UIViewController #pragma mark - UIViewController
- (void)loadView {
self.view = [[GLKView alloc] initWithFrame:CGRectZero];
}
- (void)viewDidLoad { - (void)viewDidLoad {
[super viewDidLoad]; [super viewDidLoad];
MDCFloatingButton* floatingButton = _floatingButton =
[MDCFloatingButton floatingButtonWithShape:MDCFloatingButtonShapeMini]; [MDCFloatingButton floatingButtonWithShape:MDCFloatingButtonShapeMini];
[floatingButton setTitle:@"+" forState:UIControlStateNormal]; [_floatingButton setTitle:@"+" forState:UIControlStateNormal];
[floatingButton addTarget:self [_floatingButton addTarget:self
action:@selector(didTap:) action:@selector(didTap:)
forControlEvents:UIControlEventTouchUpInside]; forControlEvents:UIControlEventTouchUpInside];
UIImage* settingsImage = [UIImage imageNamed:@"Settings"]; UIImage* settingsImage = [UIImage imageNamed:@"Settings"];
[floatingButton setImage:settingsImage forState:UIControlStateNormal]; [_floatingButton setImage:settingsImage forState:UIControlStateNormal];
[floatingButton sizeToFit]; [_floatingButton sizeToFit];
CGSize btnSize = floatingButton.frame.size; [self.view addSubview:_floatingButton];
floatingButton.frame =
CGRectMake(self.view.frame.size.width - btnSize.width - kFabInset,
self.view.frame.size.height - btnSize.height - kFabInset,
btnSize.width, btnSize.height);
[self.view addSubview:floatingButton];
} }
- (void)viewDidUnload { - (void)viewDidUnload {
...@@ -62,18 +63,35 @@ static const CGFloat kFabInset = 15.f; ...@@ -62,18 +63,35 @@ static const CGFloat kFabInset = 15.f;
- (void)viewDidAppear:(BOOL)animated { - (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated]; [super viewDidAppear:animated];
GLKView* view = (GLKView*)self.view; GLKView* glView = (GLKView*)self.view;
view.context = [_client.displayHandler GetEAGLContext]; glView.context = [_client.displayHandler GetEAGLContext];
[_client.displayHandler onSurfaceCreated:glView];
// viewDidLayoutSubviews may be called before viewDidAppear, in which case
// the surface is not ready and onSurfaceChanged will be no-op.
// Call onSurfaceChanged here to cover that case.
[_client.displayHandler onSurfaceChanged:glView.frame];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
((GLKView*)self.view).enableSetNeedsDisplay = true;
} }
- (void)viewWillDisappear:(BOOL)animated { - (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated]; [super viewWillDisappear:animated];
} }
#pragma mark - GLKViewDelegate - (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
[_client.displayHandler onSurfaceChanged:((GLKView*)self.view).frame];
- (void)glkView:(GLKView*)view drawInRect:(CGRect)rect { const CGSize& btnSize = _floatingButton.frame.size;
// Nothing to do that is synchronous yet. _floatingButton.frame =
CGRectMake(self.view.frame.size.width - btnSize.width - kFabInset,
self.view.frame.size.height - btnSize.height - kFabInset,
btnSize.width, btnSize.height);
} }
#pragma mark - Private #pragma mark - Private
......
...@@ -28,7 +28,13 @@ class CursorShapeStub; ...@@ -28,7 +28,13 @@ class CursorShapeStub;
} }
- (void)stop; - (void)stop;
- (void)glkView:(GLKView*)view drawInRect:(CGRect)rect;
// Called once the GLKView created.
- (void)onSurfaceCreated:(GLKView*)view;
// Called every time the GLKView dimension is initialized or changed.
- (void)onSurfaceChanged:(const CGRect&)frame;
- (std::unique_ptr<remoting::protocol::VideoRenderer>)CreateVideoRenderer; - (std::unique_ptr<remoting::protocol::VideoRenderer>)CreateVideoRenderer;
- (std::unique_ptr<remoting::protocol::CursorShapeStub>)CreateCursorShapeStub; - (std::unique_ptr<remoting::protocol::CursorShapeStub>)CreateCursorShapeStub;
......
...@@ -48,6 +48,7 @@ class Core : public protocol::CursorShapeStub, public GlRendererDelegate { ...@@ -48,6 +48,7 @@ class Core : public protocol::CursorShapeStub, public GlRendererDelegate {
void OnFrameReceived(std::unique_ptr<webrtc::DesktopFrame> frame, void OnFrameReceived(std::unique_ptr<webrtc::DesktopFrame> frame,
const base::Closure& done); const base::Closure& done);
void Stop(); void Stop();
void SurfaceCreated(GLKView* view);
void SurfaceChanged(int width, int height); void SurfaceChanged(int width, int height);
std::unique_ptr<protocol::FrameConsumer> GrabFrameConsumer(); std::unique_ptr<protocol::FrameConsumer> GrabFrameConsumer();
EAGLContext* GetEAGLContext(); EAGLContext* GetEAGLContext();
...@@ -60,6 +61,7 @@ class Core : public protocol::CursorShapeStub, public GlRendererDelegate { ...@@ -60,6 +61,7 @@ class Core : public protocol::CursorShapeStub, public GlRendererDelegate {
std::unique_ptr<DualBufferFrameConsumer> owned_frame_consumer_; std::unique_ptr<DualBufferFrameConsumer> owned_frame_consumer_;
base::WeakPtr<DualBufferFrameConsumer> frame_consumer_; base::WeakPtr<DualBufferFrameConsumer> frame_consumer_;
GLKView* gl_view_;
EAGLContext* eagl_context_; EAGLContext* eagl_context_;
std::unique_ptr<GlRenderer> renderer_; std::unique_ptr<GlRenderer> renderer_;
// GlDemoScreen *demo_screen_; // GlDemoScreen *demo_screen_;
...@@ -108,19 +110,6 @@ void Core::Initialize() { ...@@ -108,19 +110,6 @@ void Core::Initialize() {
// renderer_.RequestCanvasSize(); // renderer_.RequestCanvasSize();
renderer_->OnSurfaceCreated(
base::MakeUnique<GlCanvas>(static_cast<int>([eagl_context_ API])));
SurfaceChanged(1024, 640); // TODO(nicholss): Where does this data comefrom?
// TODO(nicholss): This are wrong values but it lets us get something on the
// screen.
std::array<float, 9> matrix = {{1, 0, 0,
0, 1, 0,
0, 0, 1}};
renderer_->OnPixelTransformationChanged(matrix);
// demo_screen_ = new GlDemoScreen(); // demo_screen_ = new GlDemoScreen();
// renderer_->AddDrawable(demo_screen_->GetWeakPtr()); // renderer_->AddDrawable(demo_screen_->GetWeakPtr());
renderer_->SetDelegate(weak_ptr_); renderer_->SetDelegate(weak_ptr_);
...@@ -133,7 +122,7 @@ void Core::SetCursorShape(const protocol::CursorShapeInfo& cursor_shape) { ...@@ -133,7 +122,7 @@ void Core::SetCursorShape(const protocol::CursorShapeInfo& cursor_shape) {
bool Core::CanRenderFrame() { bool Core::CanRenderFrame() {
DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread()); DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
return eagl_context_ != NULL; return gl_view_ != NULL && eagl_context_ != NULL;
} }
std::unique_ptr<protocol::FrameConsumer> Core::GrabFrameConsumer() { std::unique_ptr<protocol::FrameConsumer> Core::GrabFrameConsumer() {
...@@ -148,7 +137,7 @@ void Core::OnFrameReceived(std::unique_ptr<webrtc::DesktopFrame> frame, ...@@ -148,7 +137,7 @@ void Core::OnFrameReceived(std::unique_ptr<webrtc::DesktopFrame> frame,
} }
void Core::OnFrameRendered() { void Core::OnFrameRendered() {
// Nothing to do. [gl_view_ setNeedsDisplay];
} }
void Core::OnSizeChanged(int width, int height) { void Core::OnSizeChanged(int width, int height) {
...@@ -162,9 +151,29 @@ void Core::Stop() { ...@@ -162,9 +151,29 @@ void Core::Stop() {
// demo_screen_ = nil; // demo_screen_ = nil;
} }
void Core::SurfaceCreated(GLKView* view) {
DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
gl_view_ = view;
renderer_->OnSurfaceCreated(
base::MakeUnique<GlCanvas>(static_cast<int>([eagl_context_ API])));
runtime_->network_task_runner()->PostTask(
FROM_HERE, base::Bind(&DualBufferFrameConsumer::RequestFullDesktopFrame,
frame_consumer_));
}
void Core::SurfaceChanged(int width, int height) { void Core::SurfaceChanged(int width, int height) {
DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread()); DCHECK(runtime_->display_task_runner()->BelongsToCurrentThread());
renderer_->OnSurfaceChanged(width, height); renderer_->OnSurfaceChanged(width, height);
// TODO(nicholss): This are wrong values but it lets us get something on the
// screen.
std::array<float, 9> matrix = {{1, 0, 0, // Row 1
0, 1, 0, // Row 2
0, 0, 1}};
renderer_->OnPixelTransformationChanged(matrix);
} }
EAGLContext* Core::GetEAGLContext() { EAGLContext* Core::GetEAGLContext() {
...@@ -217,6 +226,19 @@ base::WeakPtr<remoting::GlDisplayHandler::Core> Core::GetWeakPtr() { ...@@ -217,6 +226,19 @@ base::WeakPtr<remoting::GlDisplayHandler::Core> Core::GetWeakPtr() {
return _core->GetEAGLContext(); return _core->GetEAGLContext();
} }
- (void)onSurfaceCreated:(GLKView*)view {
_runtime->display_task_runner()->PostTask(
FROM_HERE, base::Bind(&remoting::GlDisplayHandler::Core::SurfaceCreated,
_core->GetWeakPtr(), view));
}
- (void)onSurfaceChanged:(const CGRect&)frame {
_runtime->display_task_runner()->PostTask(
FROM_HERE,
base::Bind(&remoting::GlDisplayHandler::Core::SurfaceChanged,
_core->GetWeakPtr(), frame.size.width, frame.size.height));
}
// TODO(nicholss): Remove this function, it is not used in the final impl, // TODO(nicholss): Remove this function, it is not used in the final impl,
// or it should call RequestRender. // or it should call RequestRender.
- (void)glkView:(GLKView*)view drawInRect:(CGRect)rect { - (void)glkView:(GLKView*)view drawInRect:(CGRect)rect {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment