blob: 31cff040aff535d337f0426a30d17afe4608ee99 [file] [log] [blame]
// Copyright 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/android/vr/vr_gl_thread.h"
#include <utility>
#include "base/message_loop/message_loop.h"
#include "base/strings/string16.h"
#include "base/version.h"
#include "chrome/browser/android/vr/vr_input_connection.h"
#include "chrome/browser/android/vr/vr_shell.h"
#include "chrome/browser/android/vr/vr_shell_gl.h"
#include "chrome/browser/vr/assets_loader.h"
#include "chrome/browser/vr/browser_ui_interface.h"
#include "chrome/browser/vr/model/assets.h"
#include "chrome/browser/vr/model/omnibox_suggestions.h"
#include "chrome/browser/vr/model/toolbar_state.h"
#include "chrome/browser/vr/sounds_manager_audio_delegate.h"
#include "chrome/browser/vr/ui.h"
#include "chrome/common/chrome_features.h"
#include "third_party/skia/include/core/SkBitmap.h"
namespace vr {
VrGLThread::VrGLThread(
const base::WeakPtr<VrShell>& weak_vr_shell,
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner,
gvr_context* gvr_api,
const UiInitialState& ui_initial_state,
bool reprojected_rendering,
bool daydream_support,
bool pause_content)
: base::android::JavaHandlerThread("VrShellGL"),
weak_vr_shell_(weak_vr_shell),
main_thread_task_runner_(std::move(main_thread_task_runner)),
gvr_api_(gvr_api),
ui_initial_state_(ui_initial_state),
reprojected_rendering_(reprojected_rendering),
daydream_support_(daydream_support),
pause_content_(pause_content) {}
VrGLThread::~VrGLThread() {
Stop();
}
base::WeakPtr<VrShellGl> VrGLThread::GetVrShellGl() {
return vr_shell_gl_->GetWeakPtr();
}
void VrGLThread::SetInputConnection(VrInputConnection* input_connection) {
DCHECK(OnGlThread());
input_connection_ = input_connection;
}
void VrGLThread::Init() {
bool keyboard_enabled =
base::FeatureList::IsEnabled(features::kVrBrowserKeyboard) &&
!ui_initial_state_.web_vr_autopresentation_expected;
if (keyboard_enabled) {
keyboard_delegate_ = GvrKeyboardDelegate::Create();
text_input_delegate_ = std::make_unique<TextInputDelegate>();
}
auto* keyboard_delegate =
!keyboard_delegate_ ? nullptr : keyboard_delegate_.get();
if (!keyboard_delegate)
ui_initial_state_.needs_keyboard_update = true;
audio_delegate_ = std::make_unique<SoundsManagerAudioDelegate>();
auto ui = std::make_unique<Ui>(this, this, keyboard_delegate,
text_input_delegate_.get(),
audio_delegate_.get(), ui_initial_state_);
if (keyboard_enabled) {
text_input_delegate_->SetRequestFocusCallback(
base::BindRepeating(&Ui::RequestFocus, base::Unretained(ui.get())));
text_input_delegate_->SetRequestUnfocusCallback(
base::BindRepeating(&Ui::RequestUnfocus, base::Unretained(ui.get())));
if (keyboard_delegate) {
keyboard_delegate_->SetUiInterface(ui.get());
text_input_delegate_->SetUpdateInputCallback(
base::BindRepeating(&GvrKeyboardDelegate::UpdateInput,
base::Unretained(keyboard_delegate_.get())));
}
}
vr_shell_gl_ = std::make_unique<VrShellGl>(
this, std::move(ui), gvr_api_, reprojected_rendering_, daydream_support_,
ui_initial_state_.in_web_vr, pause_content_);
weak_browser_ui_ = vr_shell_gl_->GetBrowserUiWeakPtr();
vr_shell_gl_->Initialize();
}
void VrGLThread::CleanUp() {
audio_delegate_.reset();
vr_shell_gl_.reset();
}
void VrGLThread::ContentSurfaceCreated(jobject surface,
gl::SurfaceTexture* texture) {
DCHECK(OnGlThread());
main_thread_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&VrShell::ContentSurfaceCreated, weak_vr_shell_,
surface, base::Unretained(texture)));
}
void VrGLThread::ContentOverlaySurfaceCreated(jobject surface,
gl::SurfaceTexture* texture) {
DCHECK(OnGlThread());
main_thread_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&VrShell::ContentOverlaySurfaceCreated, weak_vr_shell_,
surface, base::Unretained(texture)));
}
void VrGLThread::DialogSurfaceCreated(jobject surface,
gl::SurfaceTexture* texture) {
DCHECK(OnGlThread());
main_thread_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&VrShell::DialogSurfaceCreated, weak_vr_shell_,
surface, base::Unretained(texture)));
}
void VrGLThread::GvrDelegateReady(gvr::ViewerType viewer_type) {
DCHECK(OnGlThread());
main_thread_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&VrShell::GvrDelegateReady, weak_vr_shell_, viewer_type));
}
void VrGLThread::SendRequestPresentReply(
bool success,
device::mojom::VRDisplayFrameTransportOptionsPtr transport_options) {
DCHECK(OnGlThread());
main_thread_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&VrShell::SendRequestPresentReply, weak_vr_shell_, success,
std::move(transport_options)));
}
void VrGLThread::UpdateGamepadData(device::GvrGamepadData pad) {
DCHECK(OnGlThread());
main_thread_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&VrShell::UpdateGamepadData, weak_vr_shell_, pad));
}
void VrGLThread::ForwardEvent(std::unique_ptr<blink::WebInputEvent> event,
int content_id) {
DCHECK(OnGlThread());
main_thread_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&VrShell::ProcessContentGesture, weak_vr_shell_,
base::Passed(std::move(event)), content_id));
}
void VrGLThread::ClearFocusedElement() {
DCHECK(OnGlThread());
main_thread_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&VrShell::ClearFocusedElement, weak_vr_shell_));
}
void VrGLThread::OnWebInputEdited(const TextEdits& edits) {
DCHECK(OnGlThread());
DCHECK(input_connection_);
input_connection_->OnKeyboardEdit(edits);
}
void VrGLThread::SubmitWebInput() {
DCHECK(OnGlThread());
DCHECK(input_connection_);
input_connection_->SubmitInput();
}
void VrGLThread::RequestWebInputText(TextStateUpdateCallback callback) {
DCHECK(OnGlThread());
DCHECK(input_connection_);
input_connection_->RequestTextState(std::move(callback));
}
void VrGLThread::ForwardDialogEvent(
std::unique_ptr<blink::WebInputEvent> event) {
DCHECK(OnGlThread());
main_thread_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&VrShell::ProcessDialogGesture, weak_vr_shell_,
base::Passed(std::move(event))));
}
void VrGLThread::ForceExitVr() {
DCHECK(OnGlThread());
main_thread_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&VrShell::ForceExitVr, weak_vr_shell_));
}
void VrGLThread::ExitPresent() {
DCHECK(OnGlThread());
main_thread_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&VrShell::ExitPresent, weak_vr_shell_));
// TODO(vollick): Ui should hang onto the appropriate pointer rather than
// bouncing through VrGLThread.
vr_shell_gl_->OnExitPresent();
}
void VrGLThread::ExitFullscreen() {
DCHECK(OnGlThread());
main_thread_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&VrShell::ExitFullscreen, weak_vr_shell_));
}
void VrGLThread::OnContentPaused(bool enabled) {
DCHECK(OnGlThread());
main_thread_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&VrShell::OnContentPaused, weak_vr_shell_, enabled));
}
void VrGLThread::Navigate(GURL gurl, NavigationMethod method) {
DCHECK(OnGlThread());
main_thread_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&VrShell::Navigate, weak_vr_shell_, gurl, method));
}
void VrGLThread::NavigateBack() {
DCHECK(OnGlThread());
main_thread_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&VrShell::NavigateBack, weak_vr_shell_));
}
void VrGLThread::NavigateForward() {
DCHECK(OnGlThread());
main_thread_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&VrShell::NavigateForward, weak_vr_shell_));
}
void VrGLThread::ReloadTab() {
DCHECK(OnGlThread());
main_thread_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&VrShell::ReloadTab, weak_vr_shell_));
}
void VrGLThread::OpenNewTab(bool incognito) {
DCHECK(OnGlThread());
main_thread_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&VrShell::OpenNewTab, weak_vr_shell_, incognito));
}
void VrGLThread::CloseAllIncognitoTabs() {
DCHECK(OnGlThread());
main_thread_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&VrShell::CloseAllIncognitoTabs, weak_vr_shell_));
}
void VrGLThread::ExitCct() {
DCHECK(OnGlThread());
main_thread_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&VrShell::ExitCct, weak_vr_shell_));
}
void VrGLThread::CloseHostedDialog() {
DCHECK(OnGlThread());
main_thread_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&VrShell::CloseHostedDialog, weak_vr_shell_));
}
void VrGLThread::ToggleCardboardGamepad(bool enabled) {
DCHECK(OnGlThread());
main_thread_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&VrShell::ToggleCardboardGamepad,
weak_vr_shell_, enabled));
}
void VrGLThread::OnUnsupportedMode(UiUnsupportedMode mode) {
DCHECK(OnGlThread());
main_thread_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&VrShell::OnUnsupportedMode, weak_vr_shell_, mode));
}
void VrGLThread::OnExitVrPromptResult(ExitVrPromptChoice choice,
UiUnsupportedMode reason) {
DCHECK(OnGlThread());
main_thread_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&VrShell::OnExitVrPromptResult, weak_vr_shell_,
reason, choice));
}
void VrGLThread::OnContentScreenBoundsChanged(const gfx::SizeF& bounds) {
DCHECK(OnGlThread());
main_thread_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&VrShell::OnContentScreenBoundsChanged,
weak_vr_shell_, bounds));
}
void VrGLThread::SetVoiceSearchActive(bool active) {
DCHECK(OnGlThread());
main_thread_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&VrShell::SetVoiceSearchActive, weak_vr_shell_, active));
}
void VrGLThread::StartAutocomplete(const AutocompleteRequest& request) {
DCHECK(OnGlThread());
main_thread_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&VrShell::StartAutocomplete, weak_vr_shell_, request));
}
void VrGLThread::StopAutocomplete() {
DCHECK(OnGlThread());
main_thread_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&VrShell::StopAutocomplete, weak_vr_shell_));
}
void VrGLThread::ShowPageInfo() {
DCHECK(OnGlThread());
main_thread_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&VrShell::ShowPageInfo, weak_vr_shell_));
}
void VrGLThread::SetFullscreen(bool enabled) {
DCHECK(OnMainThread());
task_runner()->PostTask(FROM_HERE,
base::BindOnce(&BrowserUiInterface::SetFullscreen,
weak_browser_ui_, enabled));
}
void VrGLThread::SetIncognito(bool incognito) {
DCHECK(OnMainThread());
task_runner()->PostTask(FROM_HERE,
base::BindOnce(&BrowserUiInterface::SetIncognito,
weak_browser_ui_, incognito));
}
void VrGLThread::SetHistoryButtonsEnabled(bool can_go_back,
bool can_go_forward) {
DCHECK(OnMainThread());
task_runner()->PostTask(
FROM_HERE, base::BindOnce(&BrowserUiInterface::SetHistoryButtonsEnabled,
weak_browser_ui_, can_go_back, can_go_forward));
}
void VrGLThread::SetLoadProgress(float progress) {
DCHECK(OnMainThread());
task_runner()->PostTask(FROM_HERE,
base::BindOnce(&BrowserUiInterface::SetLoadProgress,
weak_browser_ui_, progress));
}
void VrGLThread::SetLoading(bool loading) {
DCHECK(OnMainThread());
task_runner()->PostTask(FROM_HERE,
base::BindOnce(&BrowserUiInterface::SetLoading,
weak_browser_ui_, loading));
}
void VrGLThread::SetToolbarState(const ToolbarState& state) {
DCHECK(OnMainThread());
task_runner()->PostTask(FROM_HERE,
base::BindOnce(&BrowserUiInterface::SetToolbarState,
weak_browser_ui_, state));
}
void VrGLThread::SetWebVrMode(bool enabled) {
DCHECK(OnMainThread());
task_runner()->PostTask(FROM_HERE,
base::BindOnce(&BrowserUiInterface::SetWebVrMode,
weak_browser_ui_, enabled));
}
void VrGLThread::SetCapturingState(const CapturingStateModel& state) {
DCHECK(OnMainThread());
task_runner()->PostTask(FROM_HERE,
base::BindOnce(&BrowserUiInterface::SetCapturingState,
weak_browser_ui_, state));
}
void VrGLThread::SetIsExiting() {
DCHECK(OnMainThread());
task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&BrowserUiInterface::SetIsExiting, weak_browser_ui_));
}
void VrGLThread::ShowExitVrPrompt(UiUnsupportedMode reason) {
DCHECK(OnMainThread());
task_runner()->PostTask(FROM_HERE,
base::BindOnce(&BrowserUiInterface::ShowExitVrPrompt,
weak_browser_ui_, reason));
}
void VrGLThread::SetSpeechRecognitionEnabled(bool enabled) {
DCHECK(OnMainThread());
task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&BrowserUiInterface::SetSpeechRecognitionEnabled,
weak_browser_ui_, enabled));
}
void VrGLThread::SetRecognitionResult(const base::string16& result) {
DCHECK(OnMainThread());
task_runner()->PostTask(
FROM_HERE, base::BindOnce(&BrowserUiInterface::SetRecognitionResult,
weak_browser_ui_, result));
}
void VrGLThread::OnSpeechRecognitionStateChanged(int new_state) {
DCHECK(OnMainThread());
task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&BrowserUiInterface::OnSpeechRecognitionStateChanged,
weak_browser_ui_, new_state));
}
void VrGLThread::SetOmniboxSuggestions(
std::unique_ptr<OmniboxSuggestions> suggestions) {
DCHECK(OnMainThread());
task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&BrowserUiInterface::SetOmniboxSuggestions,
weak_browser_ui_, base::Passed(std::move(suggestions))));
}
void VrGLThread::OnAssetsLoaded(AssetsLoadStatus status,
std::unique_ptr<Assets> assets,
const base::Version& component_version) {
DCHECK(OnMainThread());
task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&BrowserUiInterface::OnAssetsLoaded, weak_browser_ui_,
status, std::move(assets), component_version));
}
void VrGLThread::OnAssetsUnavailable() {
DCHECK(OnMainThread());
task_runner()->PostTask(
FROM_HERE, base::BindOnce(&BrowserUiInterface::OnAssetsUnavailable,
weak_browser_ui_));
}
void VrGLThread::SetIncognitoTabsOpen(bool open) {
DCHECK(OnMainThread());
task_runner()->PostTask(
FROM_HERE, base::BindOnce(&BrowserUiInterface::SetIncognitoTabsOpen,
weak_browser_ui_, open));
}
void VrGLThread::SetOverlayTextureEmpty(bool empty) {
DCHECK(OnMainThread());
task_runner()->PostTask(
FROM_HERE, base::BindOnce(&BrowserUiInterface::SetOverlayTextureEmpty,
weak_browser_ui_, empty));
}
void VrGLThread::ShowSoftInput(bool show) {
DCHECK(OnMainThread());
task_runner()->PostTask(FROM_HERE,
base::BindOnce(&BrowserUiInterface::ShowSoftInput,
weak_browser_ui_, show));
}
void VrGLThread::UpdateWebInputIndices(int selection_start,
int selection_end,
int composition_start,
int composition_end) {
task_runner()->PostTask(
FROM_HERE,
base::BindRepeating(&BrowserUiInterface::UpdateWebInputIndices,
weak_browser_ui_, selection_start, selection_end,
composition_start, composition_end));
}
bool VrGLThread::OnMainThread() const {
return main_thread_task_runner_->BelongsToCurrentThread();
}
bool VrGLThread::OnGlThread() const {
return task_runner()->BelongsToCurrentThread();
}
} // namespace vr