1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/xr/service/xr_frame_sink_client_impl.h"
#include <memory>
#include "base/functional/callback.h"
#include "build/build_config.h"
#include "components/viz/host/host_frame_sink_manager.h"
#include "content/browser/browser_thread_impl.h"
#include "content/browser/compositor/surface_utils.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_view_base.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "services/viz/privileged/mojom/compositing/frame_sink_manager.mojom.h"
#if BUILDFLAG(IS_ANDROID)
#include "content/browser/renderer_host/render_widget_host_view_android.h"
#endif
namespace content {
XrFrameSinkClientImpl::XrFrameSinkClientImpl(int32_t render_process_id,
int32_t render_frame_id)
: ui_thread_task_runner_(GetUIThreadTaskRunner({})),
render_process_id_(render_process_id),
render_frame_id_(render_frame_id) {
DCHECK(IsOnUiThread())
<< "XrFrameSinkClientImpl must be constructed on the UI thread.";
}
XrFrameSinkClientImpl::~XrFrameSinkClientImpl() {
DCHECK(IsOnUiThread())
<< "XrFrameSinkClientImpl must be destructed on the UI thread.";
if (!initialized_)
return;
SurfaceDestroyed();
}
bool XrFrameSinkClientImpl::IsOnUiThread() const {
return ui_thread_task_runner_->BelongsToCurrentThread();
}
void XrFrameSinkClientImpl::SurfaceDestroyed() {
DCHECK(IsOnUiThread());
if (!initialized_)
return;
auto* frame_sink_manager = GetHostFrameSinkManager();
// Since this code can be run during destruction, it's theoretically possible,
// though unlikely, that the FrameSinkManager no longer exists.
if (frame_sink_manager)
frame_sink_manager->InvalidateFrameSinkId(root_frame_sink_id_, this);
// Reset the initialized state and the root FrameSinkId to an invalid value.
initialized_ = false;
root_frame_sink_id_ = viz::FrameSinkId();
}
std::optional<viz::SurfaceId> XrFrameSinkClientImpl::GetDOMSurface() {
base::AutoLock lock(dom_surface_lock_);
return dom_surface_id_;
}
viz::FrameSinkId XrFrameSinkClientImpl::FrameSinkId() {
return root_frame_sink_id_;
}
void XrFrameSinkClientImpl::InitializeRootCompositorFrameSink(
viz::mojom::RootCompositorFrameSinkParamsPtr root_params,
device::DomOverlaySetup dom_setup,
base::OnceClosure on_initialized) {
DCHECK(!initialized_);
DVLOG(1) << __func__;
ui_thread_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&XrFrameSinkClientImpl::InitializeOnUiThread,
weak_ptr_factory_.GetWeakPtr(), std::move(root_params),
dom_setup, std::move(on_initialized)));
}
void XrFrameSinkClientImpl::InitializeOnUiThread(
viz::mojom::RootCompositorFrameSinkParamsPtr root_params,
device::DomOverlaySetup dom_setup,
base::OnceClosure on_initialized) {
// AllocateFrameSinkId needs to be called from the UI thread.
DCHECK(IsOnUiThread());
DVLOG(1) << __func__;
root_frame_sink_id_ = AllocateFrameSinkId();
root_params->frame_sink_id = root_frame_sink_id_;
GetHostFrameSinkManager()->RegisterFrameSinkId(
root_params->frame_sink_id, this, viz::ReportFirstSurfaceActivation::kNo);
GetHostFrameSinkManager()->CreateRootCompositorFrameSink(
std::move(root_params));
if (dom_setup != device::DomOverlaySetup::kNone) {
ConfigureDOMOverlay();
}
initialized_ = true;
std::move(on_initialized).Run();
}
void XrFrameSinkClientImpl::ConfigureDOMOverlay() {
DCHECK(IsOnUiThread());
base::AutoLock lock(dom_surface_lock_);
// This is left outside of the OS_ANDROID ifdef to prevent warnings about the
// render_process_id and render_frame_id from being unused. Since we check
// the render_frame_host for an early return, it is in fact used.
RenderFrameHostImpl* render_frame_host =
RenderFrameHostImpl::FromID(render_process_id_, render_frame_id_);
if (!render_frame_host)
return;
RenderWidgetHostViewBase* root_view = static_cast<RenderWidgetHostViewBase*>(
render_frame_host->GetOutermostMainFrameOrEmbedder()->GetView());
CHECK(!root_view || !root_view->IsRenderWidgetHostViewChildFrame());
// Since we don't have the ability to get updates to the surface id on non-
// Android OS's, we let it stay null, which callers can use to as a signal that
// DOMOverlay will not work.
#if BUILDFLAG(IS_ANDROID)
RenderWidgetHostViewAndroid* view =
static_cast<RenderWidgetHostViewAndroid*>(root_view);
if (!view)
return;
// The returned CallbackListSubscription manages the lifetime of this callback
// and thus makes Unretained safe.
surface_id_changed_subscription_ =
view->SubscribeToSurfaceIdChanges(base::BindRepeating(
&XrFrameSinkClientImpl::OnSurfaceIdUpdated, base::Unretained(this)));
dom_surface_id_ = view->GetCurrentSurfaceId();
#endif
if (dom_surface_id_ && dom_surface_id_->is_valid()) {
GetHostFrameSinkManager()->RegisterFrameSinkHierarchy(
root_frame_sink_id_, dom_surface_id_->frame_sink_id());
}
}
void XrFrameSinkClientImpl::OnSurfaceIdUpdated(
const viz::SurfaceId& dom_surface_id) {
base::AutoLock lock(dom_surface_lock_);
dom_surface_id_ = dom_surface_id;
}
} // namespace content
|