123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314 |
- // Copyright 2010 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 "cc/layers/texture_layer.h"
- #include <memory>
- #include <utility>
- #include "base/bind.h"
- #include "base/callback_helpers.h"
- #include "base/containers/cxx20_erase.h"
- #include "base/location.h"
- #include "base/synchronization/lock.h"
- #include "base/task/sequenced_task_runner.h"
- #include "base/trace_event/trace_event.h"
- #include "cc/base/features.h"
- #include "cc/base/simple_enclosed_region.h"
- #include "cc/layers/texture_layer_client.h"
- #include "cc/layers/texture_layer_impl.h"
- #include "cc/trees/layer_tree_impl.h"
- namespace cc {
- scoped_refptr<TextureLayer> TextureLayer::CreateForMailbox(
- TextureLayerClient* client) {
- return scoped_refptr<TextureLayer>(new TextureLayer(client));
- }
- TextureLayer::TextureLayer(TextureLayerClient* client)
- : client_(client),
- flipped_(true),
- nearest_neighbor_(false),
- uv_bottom_right_(1.f, 1.f),
- premultiplied_alpha_(true),
- blend_background_color_(false),
- force_texture_to_opaque_(false),
- needs_set_resource_(false) {}
- TextureLayer::~TextureLayer() = default;
- void TextureLayer::ClearClient() {
- client_.Write(*this) = nullptr;
- ClearTexture();
- SetDrawsContent(HasDrawableContent());
- }
- void TextureLayer::ClearTexture() {
- SetTransferableResource(viz::TransferableResource(), viz::ReleaseCallback());
- }
- std::unique_ptr<LayerImpl> TextureLayer::CreateLayerImpl(
- LayerTreeImpl* tree_impl) const {
- return TextureLayerImpl::Create(tree_impl, id());
- }
- void TextureLayer::SetFlipped(bool flipped) {
- if (flipped_.Read(*this) == flipped)
- return;
- flipped_.Write(*this) = flipped;
- SetNeedsCommit();
- }
- void TextureLayer::SetNearestNeighbor(bool nearest_neighbor) {
- if (nearest_neighbor_.Read(*this) == nearest_neighbor)
- return;
- nearest_neighbor_.Write(*this) = nearest_neighbor;
- SetNeedsCommit();
- }
- void TextureLayer::SetUV(const gfx::PointF& top_left,
- const gfx::PointF& bottom_right) {
- if (uv_top_left_.Read(*this) == top_left &&
- uv_bottom_right_.Read(*this) == bottom_right)
- return;
- uv_top_left_.Write(*this) = top_left;
- uv_bottom_right_.Write(*this) = bottom_right;
- SetNeedsCommit();
- }
- void TextureLayer::SetPremultipliedAlpha(bool premultiplied_alpha) {
- if (premultiplied_alpha_.Read(*this) == premultiplied_alpha)
- return;
- premultiplied_alpha_.Write(*this) = premultiplied_alpha;
- SetNeedsCommit();
- }
- void TextureLayer::SetBlendBackgroundColor(bool blend) {
- if (blend_background_color_.Read(*this) == blend)
- return;
- blend_background_color_.Write(*this) = blend;
- SetNeedsCommit();
- }
- void TextureLayer::SetForceTextureToOpaque(bool opaque) {
- if (force_texture_to_opaque_.Read(*this) == opaque)
- return;
- force_texture_to_opaque_.Write(*this) = opaque;
- SetNeedsCommit();
- }
- void TextureLayer::SetTransferableResourceInternal(
- const viz::TransferableResource& resource,
- viz::ReleaseCallback release_callback,
- bool requires_commit) {
- DCHECK(resource.mailbox_holder.mailbox.IsZero() ||
- !resource_holder_.Read(*this) ||
- resource != resource_holder_.Read(*this)->resource());
- DCHECK_EQ(resource.mailbox_holder.mailbox.IsZero(), !release_callback);
- // If we never commited the mailbox, we need to release it here.
- if (!resource.mailbox_holder.mailbox.IsZero()) {
- resource_holder_.Write(*this) = TransferableResourceHolder::Create(
- resource, std::move(release_callback));
- } else {
- resource_holder_.Write(*this) = nullptr;
- }
- needs_set_resource_.Write(*this) = true;
- // If we are within a commit, no need to do it again immediately after.
- if (requires_commit)
- SetNeedsCommit();
- else
- SetNeedsPushProperties();
- SetDrawsContent(HasDrawableContent());
- }
- void TextureLayer::SetTransferableResource(
- const viz::TransferableResource& resource,
- viz::ReleaseCallback release_callback) {
- bool requires_commit = true;
- SetTransferableResourceInternal(resource, std::move(release_callback),
- requires_commit);
- }
- void TextureLayer::SetLayerTreeHost(LayerTreeHost* host) {
- if (layer_tree_host() == host) {
- Layer::SetLayerTreeHost(host);
- return;
- }
- // If we're removed from the tree, the TextureLayerImpl will be destroyed, and
- // we will need to set the mailbox again on a new TextureLayerImpl the next
- // time we push.
- if (!host && resource_holder_.Read(*this))
- needs_set_resource_.Write(*this) = true;
- if (host) {
- // When attached to a new LayerTreeHost, all previously registered
- // SharedBitmapIds will need to be re-sent to the new TextureLayerImpl
- // representing this layer on the compositor thread.
- auto& registered_bitmaps = registered_bitmaps_.Write(*this);
- to_register_bitmaps_.Write(*this).insert(
- std::make_move_iterator(registered_bitmaps.begin()),
- std::make_move_iterator(registered_bitmaps.end()));
- registered_bitmaps.clear();
- }
- Layer::SetLayerTreeHost(host);
- }
- bool TextureLayer::HasDrawableContent() const {
- return (client_.Read(*this) || resource_holder_.Read(*this)) &&
- Layer::HasDrawableContent();
- }
- bool TextureLayer::Update() {
- bool updated = Layer::Update();
- if (client_.Read(*this)) {
- viz::TransferableResource resource;
- viz::ReleaseCallback release_callback;
- if (client_.Write(*this)->PrepareTransferableResource(this, &resource,
- &release_callback)) {
- // Already within a commit, no need to do another one immediately.
- bool requires_commit = false;
- SetTransferableResourceInternal(resource, std::move(release_callback),
- requires_commit);
- updated = true;
- }
- }
- // SetTransferableResource could be called externally and the same mailbox
- // used for different textures. Such callers notify this layer that the
- // texture has changed by calling SetNeedsDisplay, so check for that here.
- return updated || !update_rect().IsEmpty();
- }
- bool TextureLayer::IsSnappedToPixelGridInTarget() const {
- // Often layers are positioned with CSS to "50%", which can often leave them
- // with a fractional (N + 0.5) pixel position. This would leave them looking
- // fuzzy, so we request that TextureLayers are snapped to the pixel grid,
- // since their content is generated externally and we can not adjust for it
- // inside the content (unlike for PictureLayers).
- return true;
- }
- void TextureLayer::PushPropertiesTo(
- LayerImpl* layer,
- const CommitState& commit_state,
- const ThreadUnsafeCommitState& unsafe_state) {
- Layer::PushPropertiesTo(layer, commit_state, unsafe_state);
- TRACE_EVENT0("cc", "TextureLayer::PushPropertiesTo");
- TextureLayerImpl* texture_layer = static_cast<TextureLayerImpl*>(layer);
- texture_layer->SetFlipped(flipped_.Read(*this));
- texture_layer->SetNearestNeighbor(nearest_neighbor_.Read(*this));
- texture_layer->SetUVTopLeft(uv_top_left_.Read(*this));
- texture_layer->SetUVBottomRight(uv_bottom_right_.Read(*this));
- texture_layer->SetPremultipliedAlpha(premultiplied_alpha_.Read(*this));
- texture_layer->SetBlendBackgroundColor(blend_background_color_.Read(*this));
- texture_layer->SetForceTextureToOpaque(force_texture_to_opaque_.Read(*this));
- if (needs_set_resource_.Read(*this)) {
- viz::TransferableResource resource;
- viz::ReleaseCallback release_callback;
- if (auto& resource_holder = resource_holder_.Write(*this)) {
- resource = resource_holder->resource();
- release_callback =
- base::BindOnce(&TransferableResourceHolder::Return, resource_holder,
- base::RetainedRef(layer->layer_tree_impl()
- ->task_runner_provider()
- ->MainThreadTaskRunner()));
- }
- texture_layer->SetTransferableResource(resource,
- std::move(release_callback));
- needs_set_resource_.Write(*this) = false;
- }
- auto& to_register_bitmaps = to_register_bitmaps_.Write(*this);
- for (auto& pair : to_register_bitmaps)
- texture_layer->RegisterSharedBitmapId(pair.first, pair.second);
- // Store the registered SharedBitmapIds in case we get a new TextureLayerImpl,
- // in a new tree, to re-send them to.
- registered_bitmaps_.Write(*this).insert(
- std::make_move_iterator(to_register_bitmaps.begin()),
- std::make_move_iterator(to_register_bitmaps.end()));
- to_register_bitmaps.clear();
- auto& to_unregister_bitmap_ids = to_unregister_bitmap_ids_.Write(*this);
- for (const auto& id : to_unregister_bitmap_ids)
- texture_layer->UnregisterSharedBitmapId(id);
- to_unregister_bitmap_ids.clear();
- }
- SharedBitmapIdRegistration TextureLayer::RegisterSharedBitmapId(
- const viz::SharedBitmapId& id,
- scoped_refptr<CrossThreadSharedBitmap> bitmap) {
- DCHECK(to_register_bitmaps_.Read(*this).find(id) ==
- to_register_bitmaps_.Read(*this).end());
- DCHECK(registered_bitmaps_.Read(*this).find(id) ==
- registered_bitmaps_.Read(*this).end());
- to_register_bitmaps_.Write(*this)[id] = std::move(bitmap);
- base::Erase(to_unregister_bitmap_ids_.Write(*this), id);
- // This does not SetNeedsCommit() to be as lazy as possible. Notifying a
- // SharedBitmapId is not needed until it is used, and using it will require
- // a commit, so we can wait for that commit before forwarding the
- // notification instead of forcing it to happen as a side effect of this
- // method.
- SetNeedsPushProperties();
- return SharedBitmapIdRegistration(weak_ptr_factory_.GetWeakPtr(), id);
- }
- void TextureLayer::UnregisterSharedBitmapId(viz::SharedBitmapId id) {
- // If we didn't get to sending the registration to the compositor thread yet,
- // just remove it.
- to_register_bitmaps_.Write(*this).erase(id);
- // Since we also track all previously sent registrations, we must remove that
- // to in order to prevent re-registering on another LayerTreeHost.
- registered_bitmaps_.Write(*this).erase(id);
- to_unregister_bitmap_ids_.Write(*this).push_back(id);
- // Unregistering a SharedBitmapId needs to happen eventually to prevent
- // leaking the SharedMemory in the display compositor. But this attempts to be
- // lazy and not force a commit prematurely, so just requests a
- // PushPropertiesTo() without requesting a commit.
- SetNeedsPushProperties();
- }
- TextureLayer::TransferableResourceHolder::TransferableResourceHolder(
- const viz::TransferableResource& resource,
- viz::ReleaseCallback release_callback)
- : resource_(resource),
- release_callback_(std::move(release_callback)),
- sync_token_(resource.mailbox_holder.sync_token) {}
- TextureLayer::TransferableResourceHolder::~TransferableResourceHolder() {
- if (release_callback_) {
- if (!release_callback_task_runner_ ||
- release_callback_task_runner_->RunsTasksInCurrentSequence()) {
- std::move(release_callback_).Run(sync_token_, is_lost_);
- } else {
- DCHECK(release_callback_task_runner_);
- release_callback_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(std::move(release_callback_), sync_token_, is_lost_));
- }
- }
- }
- scoped_refptr<TextureLayer::TransferableResourceHolder>
- TextureLayer::TransferableResourceHolder::Create(
- const viz::TransferableResource& resource,
- viz::ReleaseCallback release_callback) {
- return new TransferableResourceHolder(resource, std::move(release_callback));
- }
- void TextureLayer::TransferableResourceHolder::Return(
- scoped_refptr<base::SequencedTaskRunner> main_thread_task_runner,
- const gpu::SyncToken& sync_token,
- bool is_lost) {
- sync_token_ = sync_token;
- is_lost_ = is_lost;
- // When this method returns, the refcount of the holder will be decremented,
- // which might cause it to be destructed on the impl thread. We store the
- // main thread task runner here to make sure it's available to the destructor.
- release_callback_task_runner_ = std::move(main_thread_task_runner);
- }
- } // namespace cc
|