[TreesInViz] Implement UIResource sync to LayerContextImpl
This change implements synchronization of UIResources to the Viz-side LayerContextImpl. Creation & deletion are tracked for each UIResourceId, and changes are wired during UpdateDisplayTree. Usage of these resources in Viz is tested in an upcoming dependent CL. Bug: 388877791 Change-Id: Ie9c02fd0914b349bce7a1ad627c55f957f3295a9 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6532287 Reviewed-by: Zhenyao Mo <zmo@chromium.org> Reviewed-by: Jonathan Ross <jonross@chromium.org> Reviewed-by: Matthew Denton <mpdenton@chromium.org> Commit-Queue: Victor Miura <vmiura@chromium.org> Cr-Commit-Position: refs/heads/main@{#1459446}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
ad4ae119b8
commit
e9c3aa9b5f
@ -471,6 +471,7 @@ cc_component("cc") {
|
||||
public_deps = [
|
||||
"//cc/base",
|
||||
"//cc/mojom:layer_type",
|
||||
"//cc/mojom:ui_resource_id",
|
||||
"//cc/paint",
|
||||
"//components/viz/common",
|
||||
"//skia",
|
||||
|
@ -396,6 +396,38 @@ viz::mojom::TransformTreeUpdatePtr ComputeTransformTreePropertiesUpdate(
|
||||
return wire;
|
||||
}
|
||||
|
||||
void SerializeUIResourceRequest(
|
||||
cc::LayerTreeHostImpl& host_impl,
|
||||
viz::RasterContextProvider& context_provider,
|
||||
viz::mojom::LayerTreeUpdate& update,
|
||||
cc::UIResourceId uid,
|
||||
viz::mojom::TransferableUIResourceRequest::Type type) {
|
||||
if (type == viz::mojom::TransferableUIResourceRequest::Type::kCreate) {
|
||||
std::vector<viz::ResourceId> ids;
|
||||
std::vector<viz::TransferableResource> resources;
|
||||
|
||||
viz::ResourceId resource_id = host_impl.ResourceIdForUIResource(uid);
|
||||
bool opaque = host_impl.IsUIResourceOpaque(uid);
|
||||
ids.push_back(resource_id);
|
||||
host_impl.resource_provider()->PrepareSendToParent(ids, &resources,
|
||||
&context_provider);
|
||||
CHECK_EQ(resources.size(), ids.size());
|
||||
|
||||
auto& request = update.ui_resource_requests.emplace_back(
|
||||
viz::mojom::TransferableUIResourceRequest::New());
|
||||
request->type = type;
|
||||
request->uid = uid;
|
||||
request->transferable_resource = resources[0];
|
||||
request->opaque = opaque;
|
||||
} else {
|
||||
CHECK_EQ(type, viz::mojom::TransferableUIResourceRequest::Type::kDelete);
|
||||
auto& request = update.ui_resource_requests.emplace_back(
|
||||
viz::mojom::TransferableUIResourceRequest::New());
|
||||
request->type = type;
|
||||
request->uid = uid;
|
||||
}
|
||||
}
|
||||
|
||||
viz::mojom::TileResourcePtr SerializeTileResource(
|
||||
const Tile& tile,
|
||||
viz::ClientResourceProvider& resource_provider,
|
||||
@ -942,6 +974,23 @@ void VizLayerContext::UpdateDisplayTreeFrom(
|
||||
|
||||
update->viewport_damage_rect = viewport_damage_rect;
|
||||
|
||||
// Sync changes to UI resources
|
||||
{
|
||||
auto resource_changes = host_impl_->TakeUIResourceChanges(needs_full_sync_);
|
||||
for (const auto& [uid, change] : resource_changes) {
|
||||
if (change.resource_deleted) {
|
||||
SerializeUIResourceRequest(
|
||||
*host_impl_, context_provider, *update, uid,
|
||||
viz::mojom::TransferableUIResourceRequest::Type::kDelete);
|
||||
}
|
||||
if (change.resource_created) {
|
||||
SerializeUIResourceRequest(
|
||||
*host_impl_, context_provider, *update, uid,
|
||||
viz::mojom::TransferableUIResourceRequest::Type::kCreate);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This flag will be set if and only if a new layer list was pushed to the
|
||||
// active tree during activation, implying that at least one layer addition or
|
||||
// removal happened since our last update. In this case only, we push the full
|
||||
|
@ -119,6 +119,25 @@ mojom("layer_type") {
|
||||
sources = [ "layer_type.mojom" ]
|
||||
}
|
||||
|
||||
mojom("ui_resource_id") {
|
||||
generate_java = true
|
||||
sources = [ "ui_resource_id.mojom" ]
|
||||
|
||||
cpp_typemaps = [
|
||||
{
|
||||
types = [
|
||||
{
|
||||
mojom = "cc.mojom.UIResourceId"
|
||||
cpp = "::cc::UIResourceId"
|
||||
nullable_is_same_type = true
|
||||
copyable_pass_by_value = true
|
||||
},
|
||||
]
|
||||
traits_headers = [ "ui_resource_id_mojom_traits.h" ]
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
mojom("hit_test_opaqueness") {
|
||||
generate_java = true
|
||||
sources = [ "hit_test_opaqueness.mojom" ]
|
||||
|
9
cc/mojom/ui_resource_id.mojom
Normal file
9
cc/mojom/ui_resource_id.mojom
Normal file
@ -0,0 +1,9 @@
|
||||
// Copyright 2025 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
module cc.mojom;
|
||||
|
||||
struct UIResourceId {
|
||||
int32 value;
|
||||
};
|
35
cc/mojom/ui_resource_id_mojom_traits.h
Normal file
35
cc/mojom/ui_resource_id_mojom_traits.h
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright 2025 The Chromium Authors
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef CC_MOJOM_UI_RESOURCE_ID_MOJOM_TRAITS_H_
|
||||
#define CC_MOJOM_UI_RESOURCE_ID_MOJOM_TRAITS_H_
|
||||
|
||||
#include "cc/mojom/ui_resource_id.mojom-shared.h"
|
||||
#include "cc/resources/ui_resource_client.h"
|
||||
|
||||
namespace mojo {
|
||||
|
||||
template <>
|
||||
struct StructTraits<cc::mojom::UIResourceIdDataView, cc::UIResourceId> {
|
||||
static int32_t value(const cc::UIResourceId& id) {
|
||||
// We cannot send resource ids that are uninitialized.
|
||||
DCHECK_NE(id, cc::UIResourceClient::kUninitializedUIResourceId);
|
||||
return static_cast<int32_t>(id);
|
||||
}
|
||||
|
||||
static bool Read(cc::mojom::UIResourceIdDataView data,
|
||||
cc::UIResourceId* out) {
|
||||
cc::UIResourceId result(data.value());
|
||||
// We cannot receive resource ids that are uninitialized.
|
||||
if (result == cc::UIResourceClient::kUninitializedUIResourceId) {
|
||||
return false;
|
||||
}
|
||||
*out = result;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace mojo
|
||||
|
||||
#endif // CC_MOJOM_UI_RESOURCE_ID_MOJOM_TRAITS_H_
|
@ -4342,6 +4342,25 @@ std::unique_ptr<MutatorEvents> LayerTreeHostImpl::TakeMutatorEvents() {
|
||||
return events;
|
||||
}
|
||||
|
||||
UIResourceChangeMap LayerTreeHostImpl::TakeUIResourceChanges(
|
||||
bool require_full_sync) {
|
||||
if (require_full_sync) {
|
||||
ui_resource_changes_.clear();
|
||||
|
||||
if (settings_.TreesInVizInClientProcess()) {
|
||||
// Mark all ui resources as created in this change set.
|
||||
for (auto& pair : ui_resource_map_) {
|
||||
UIResourceId uid = pair.first;
|
||||
auto [change_it, success] =
|
||||
ui_resource_changes_.try_emplace(uid, UIResourceChange());
|
||||
change_it->second.resource_created = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return std::move(ui_resource_changes_);
|
||||
}
|
||||
|
||||
void LayerTreeHostImpl::ClearHistory() {
|
||||
client_->ClearHistory();
|
||||
}
|
||||
@ -5346,6 +5365,9 @@ void LayerTreeHostImpl::CreateUIResource(UIResourceId uid,
|
||||
const UIResourceBitmap& bitmap) {
|
||||
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
|
||||
"LayerTreeHostImpl::CreateUIResource");
|
||||
// We expect only CreateUIResourceFromImportedResource to be used for
|
||||
// trees_in_viz_in_viz_process mode.
|
||||
DCHECK(!settings_.trees_in_viz_in_viz_process);
|
||||
DCHECK_GT(uid, 0);
|
||||
|
||||
// Allow for multiple creation requests with the same UIResourceId. The
|
||||
@ -5546,6 +5568,51 @@ void LayerTreeHostImpl::CreateUIResource(UIResourceId uid,
|
||||
ui_resource_map_[uid] = std::move(data);
|
||||
|
||||
MarkUIResourceNotEvicted(uid);
|
||||
|
||||
if (settings_.TreesInVizInClientProcess()) {
|
||||
auto [change_it, success] =
|
||||
ui_resource_changes_.try_emplace(uid, UIResourceChange());
|
||||
// Mark that a resource was created in this change set.
|
||||
change_it->second.resource_created = true;
|
||||
}
|
||||
}
|
||||
|
||||
void LayerTreeHostImpl::CreateUIResourceFromImportedResource(
|
||||
UIResourceId uid,
|
||||
viz::ResourceId resource_id,
|
||||
bool is_opaque) {
|
||||
TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("cc.debug"),
|
||||
"LayerTreeHostImpl::CreateUIResourceFromResource");
|
||||
// We expect only CreateUIResource to be used for
|
||||
// non-trees_in_viz_in_viz_process mode.
|
||||
DCHECK(settings_.trees_in_viz_in_viz_process);
|
||||
DCHECK_GT(uid, 0);
|
||||
|
||||
// Allow for multiple creation requests with the same UIResourceId. The
|
||||
// previous resource is simply deleted.
|
||||
viz::ResourceId id = ResourceIdForUIResource(uid);
|
||||
if (id) {
|
||||
DeleteUIResource(uid);
|
||||
}
|
||||
|
||||
if (!has_valid_layer_tree_frame_sink_) {
|
||||
evicted_ui_resources_.insert(uid);
|
||||
return;
|
||||
}
|
||||
|
||||
UIResourceData data;
|
||||
data.opaque = is_opaque;
|
||||
data.resource_id_for_export = resource_id;
|
||||
ui_resource_map_[uid] = std::move(data);
|
||||
|
||||
MarkUIResourceNotEvicted(uid);
|
||||
|
||||
if (settings_.TreesInVizInClientProcess()) {
|
||||
auto [change_it, success] =
|
||||
ui_resource_changes_.try_emplace(uid, UIResourceChange());
|
||||
// Mark that a resource was created in this change set.
|
||||
change_it->second.resource_created = true;
|
||||
}
|
||||
}
|
||||
|
||||
void LayerTreeHostImpl::DeleteUIResource(UIResourceId uid) {
|
||||
@ -5562,6 +5629,19 @@ void LayerTreeHostImpl::DeleteUIResource(UIResourceId uid) {
|
||||
ui_resource_map_.erase(it);
|
||||
|
||||
resource_provider_->RemoveImportedResource(id);
|
||||
|
||||
if (settings_.TreesInVizInClientProcess()) {
|
||||
auto [change_it, success] =
|
||||
ui_resource_changes_.try_emplace(uid, UIResourceChange());
|
||||
// If a resource was marked as created in this change set, unmark it.
|
||||
// Otherwise, the resource must have been created in a prior change set,
|
||||
// so we mark it as requiring deletion.
|
||||
if (change_it->second.resource_created) {
|
||||
change_it->second.resource_created = false;
|
||||
} else {
|
||||
change_it->second.resource_deleted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
MarkUIResourceNotEvicted(uid);
|
||||
}
|
||||
|
@ -124,6 +124,13 @@ class TaskGraphRunner;
|
||||
class UIResourceBitmap;
|
||||
class Viewport;
|
||||
|
||||
struct UIResourceChange {
|
||||
bool resource_created : 1 = false;
|
||||
bool resource_deleted : 1 = false;
|
||||
};
|
||||
|
||||
using UIResourceChangeMap = std::unordered_map<UIResourceId, UIResourceChange>;
|
||||
|
||||
// LayerTreeHostImpl owns the LayerImpl trees as well as associated rendering
|
||||
// state.
|
||||
class CC_EXPORT LayerTreeHostImpl : public TileManagerClient,
|
||||
@ -731,6 +738,10 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient,
|
||||
|
||||
virtual void CreateUIResource(UIResourceId uid,
|
||||
const UIResourceBitmap& bitmap);
|
||||
virtual void CreateUIResourceFromImportedResource(UIResourceId uid,
|
||||
viz::ResourceId resource_id,
|
||||
bool is_opaque);
|
||||
|
||||
// Deletes a UI resource. May safely be called more than once.
|
||||
virtual void DeleteUIResource(UIResourceId uid);
|
||||
// Evict all UI resources. This differs from ClearUIResources in that this
|
||||
@ -812,6 +823,7 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient,
|
||||
std::vector<std::pair<int, bool>> TakeCompletedImageDecodeRequests();
|
||||
// Returns mutator events to be handled by BeginMainFrame.
|
||||
std::unique_ptr<MutatorEvents> TakeMutatorEvents();
|
||||
UIResourceChangeMap TakeUIResourceChanges(bool require_full_sync);
|
||||
|
||||
void ClearHistory();
|
||||
size_t CommitDurationSampleCountForTesting() const;
|
||||
@ -1075,6 +1087,10 @@ class CC_EXPORT LayerTreeHostImpl : public TileManagerClient,
|
||||
// associated with them anymore, as that is freed at the time of eviction.
|
||||
std::set<UIResourceId> evicted_ui_resources_;
|
||||
|
||||
// When using a layer context for display, this tracks changes to UIResources
|
||||
// that should be synchronized to the layer context.
|
||||
UIResourceChangeMap ui_resource_changes_;
|
||||
|
||||
// These are valid when has_valid_layer_tree_frame_sink_ is true.
|
||||
//
|
||||
// A pointer used for communicating with and submitting output to the display
|
||||
|
@ -1343,6 +1343,36 @@ base::expected<void, std::string> LayerContextImpl::DoUpdateDisplayTree(
|
||||
|
||||
host_impl_->SetViewportDamage(update->viewport_damage_rect);
|
||||
|
||||
for (auto& ui_resource_request : update->ui_resource_requests) {
|
||||
if (ui_resource_request->type ==
|
||||
mojom::TransferableUIResourceRequest::Type::kCreate) {
|
||||
if (!ui_resource_request->transferable_resource ||
|
||||
ui_resource_request->transferable_resource->is_empty()) {
|
||||
return base::unexpected(
|
||||
"Invalid transferable resource in UI resource creation");
|
||||
}
|
||||
ReleaseCallback release_callback = base::BindOnce(
|
||||
[](cc::LayerTreeHostImpl* host_impl, ResourceId id,
|
||||
const gpu::SyncToken& sync_token, bool is_lost) {
|
||||
host_impl->ReturnResource({id, sync_token,
|
||||
/*release_fence=*/gfx::GpuFenceHandle(),
|
||||
/*count=*/1, is_lost});
|
||||
},
|
||||
host_impl_.get(), ui_resource_request->transferable_resource->id);
|
||||
|
||||
auto resource_id = host_impl_->resource_provider()->ImportResource(
|
||||
ui_resource_request->transferable_resource.value(),
|
||||
/*impl_release_callback=*/std::move(release_callback),
|
||||
/*main_thread_release_callback=*/base::NullCallback(),
|
||||
/*evicted_callback=*/base::NullCallback());
|
||||
|
||||
host_impl_->CreateUIResourceFromImportedResource(
|
||||
ui_resource_request->uid, resource_id, ui_resource_request->opaque);
|
||||
} else {
|
||||
host_impl_->DeleteUIResource(ui_resource_request->uid);
|
||||
}
|
||||
}
|
||||
|
||||
property_trees.UpdateChangeTracking();
|
||||
property_trees.transform_tree_mutable().set_needs_update(
|
||||
transform_size_changed || transform_properties_changed ||
|
||||
|
@ -70,6 +70,7 @@ mojom("mojom") {
|
||||
"//cc/mojom:hit_test_opaqueness",
|
||||
"//cc/mojom:layer_type",
|
||||
"//cc/mojom:paint_flags",
|
||||
"//cc/mojom:ui_resource_id",
|
||||
"//gpu/ipc/common:interfaces",
|
||||
"//media/mojo/mojom",
|
||||
"//mojo/public/mojom/base",
|
||||
|
@ -4,17 +4,42 @@
|
||||
|
||||
module viz.mojom;
|
||||
|
||||
import "cc/mojom/ui_resource_id.mojom";
|
||||
import "services/viz/public/mojom/compositing/animation.mojom";
|
||||
import "services/viz/public/mojom/compositing/begin_frame_args.mojom";
|
||||
import "services/viz/public/mojom/compositing/layer.mojom";
|
||||
import "services/viz/public/mojom/compositing/local_surface_id.mojom";
|
||||
import "services/viz/public/mojom/compositing/tiling.mojom";
|
||||
import "services/viz/public/mojom/compositing/resource_id.mojom";
|
||||
import "services/viz/public/mojom/compositing/surface_range.mojom";
|
||||
import "services/viz/public/mojom/compositing/tiling.mojom";
|
||||
import "services/viz/public/mojom/compositing/transferable_resource.mojom";
|
||||
import "services/viz/public/mojom/compositing/view_transition_request.mojom";
|
||||
import "skia/public/mojom/skcolor4f.mojom";
|
||||
import "ui/gfx/geometry/mojom/geometry.mojom";
|
||||
import "ui/gfx/mojom/display_color_spaces.mojom";
|
||||
|
||||
// Describes a request to create or delete a UIResource in the service-side
|
||||
// display tree.
|
||||
struct TransferableUIResourceRequest {
|
||||
// The type of request.
|
||||
enum Type {
|
||||
kCreate,
|
||||
kDelete
|
||||
};
|
||||
Type type;
|
||||
|
||||
// The UIResourceId used to reference the UIResource for creation or
|
||||
// deletion. cc::Layers reference resources by this Id.
|
||||
cc.mojom.UIResourceId uid;
|
||||
|
||||
// The UI resource to be created should use the following
|
||||
// TransferableResource contents.
|
||||
TransferableResource? transferable_resource;
|
||||
|
||||
// The resource's pixel content should be treated as opaque for rendering.
|
||||
bool opaque;
|
||||
};
|
||||
|
||||
// Metadata and contents of a service-side display tree to be updated each time
|
||||
// the corresponding client layer tree activates.
|
||||
//
|
||||
@ -79,6 +104,9 @@ struct LayerTreeUpdate {
|
||||
// The tree's viewport damage rect.
|
||||
gfx.mojom.Rect viewport_damage_rect;
|
||||
|
||||
// UIResource change requests accumulated since the last LayerTreeUpdate.
|
||||
array<TransferableUIResourceRequest> ui_resource_requests;
|
||||
|
||||
// Properties of layers added or modified since the last update. Note that the
|
||||
// ordering of this array is arbitrary and not relevant to the tree's layer
|
||||
// list order. If any layers were added, removed, or otherwise reordered in
|
||||
|
Reference in New Issue
Block a user