texture_layer.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. // Copyright 2010 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "cc/layers/texture_layer.h"
  5. #include <memory>
  6. #include <utility>
  7. #include "base/bind.h"
  8. #include "base/callback_helpers.h"
  9. #include "base/containers/cxx20_erase.h"
  10. #include "base/location.h"
  11. #include "base/synchronization/lock.h"
  12. #include "base/task/sequenced_task_runner.h"
  13. #include "base/trace_event/trace_event.h"
  14. #include "cc/base/features.h"
  15. #include "cc/base/simple_enclosed_region.h"
  16. #include "cc/layers/texture_layer_client.h"
  17. #include "cc/layers/texture_layer_impl.h"
  18. #include "cc/trees/layer_tree_impl.h"
  19. namespace cc {
  20. scoped_refptr<TextureLayer> TextureLayer::CreateForMailbox(
  21. TextureLayerClient* client) {
  22. return scoped_refptr<TextureLayer>(new TextureLayer(client));
  23. }
  24. TextureLayer::TextureLayer(TextureLayerClient* client)
  25. : client_(client),
  26. flipped_(true),
  27. nearest_neighbor_(false),
  28. uv_bottom_right_(1.f, 1.f),
  29. premultiplied_alpha_(true),
  30. blend_background_color_(false),
  31. force_texture_to_opaque_(false),
  32. needs_set_resource_(false) {}
  33. TextureLayer::~TextureLayer() = default;
  34. void TextureLayer::ClearClient() {
  35. client_.Write(*this) = nullptr;
  36. ClearTexture();
  37. SetDrawsContent(HasDrawableContent());
  38. }
  39. void TextureLayer::ClearTexture() {
  40. SetTransferableResource(viz::TransferableResource(), viz::ReleaseCallback());
  41. }
  42. std::unique_ptr<LayerImpl> TextureLayer::CreateLayerImpl(
  43. LayerTreeImpl* tree_impl) const {
  44. return TextureLayerImpl::Create(tree_impl, id());
  45. }
  46. void TextureLayer::SetFlipped(bool flipped) {
  47. if (flipped_.Read(*this) == flipped)
  48. return;
  49. flipped_.Write(*this) = flipped;
  50. SetNeedsCommit();
  51. }
  52. void TextureLayer::SetNearestNeighbor(bool nearest_neighbor) {
  53. if (nearest_neighbor_.Read(*this) == nearest_neighbor)
  54. return;
  55. nearest_neighbor_.Write(*this) = nearest_neighbor;
  56. SetNeedsCommit();
  57. }
  58. void TextureLayer::SetUV(const gfx::PointF& top_left,
  59. const gfx::PointF& bottom_right) {
  60. if (uv_top_left_.Read(*this) == top_left &&
  61. uv_bottom_right_.Read(*this) == bottom_right)
  62. return;
  63. uv_top_left_.Write(*this) = top_left;
  64. uv_bottom_right_.Write(*this) = bottom_right;
  65. SetNeedsCommit();
  66. }
  67. void TextureLayer::SetPremultipliedAlpha(bool premultiplied_alpha) {
  68. if (premultiplied_alpha_.Read(*this) == premultiplied_alpha)
  69. return;
  70. premultiplied_alpha_.Write(*this) = premultiplied_alpha;
  71. SetNeedsCommit();
  72. }
  73. void TextureLayer::SetBlendBackgroundColor(bool blend) {
  74. if (blend_background_color_.Read(*this) == blend)
  75. return;
  76. blend_background_color_.Write(*this) = blend;
  77. SetNeedsCommit();
  78. }
  79. void TextureLayer::SetForceTextureToOpaque(bool opaque) {
  80. if (force_texture_to_opaque_.Read(*this) == opaque)
  81. return;
  82. force_texture_to_opaque_.Write(*this) = opaque;
  83. SetNeedsCommit();
  84. }
  85. void TextureLayer::SetTransferableResourceInternal(
  86. const viz::TransferableResource& resource,
  87. viz::ReleaseCallback release_callback,
  88. bool requires_commit) {
  89. DCHECK(resource.mailbox_holder.mailbox.IsZero() ||
  90. !resource_holder_.Read(*this) ||
  91. resource != resource_holder_.Read(*this)->resource());
  92. DCHECK_EQ(resource.mailbox_holder.mailbox.IsZero(), !release_callback);
  93. // If we never commited the mailbox, we need to release it here.
  94. if (!resource.mailbox_holder.mailbox.IsZero()) {
  95. resource_holder_.Write(*this) = TransferableResourceHolder::Create(
  96. resource, std::move(release_callback));
  97. } else {
  98. resource_holder_.Write(*this) = nullptr;
  99. }
  100. needs_set_resource_.Write(*this) = true;
  101. // If we are within a commit, no need to do it again immediately after.
  102. if (requires_commit)
  103. SetNeedsCommit();
  104. else
  105. SetNeedsPushProperties();
  106. SetDrawsContent(HasDrawableContent());
  107. }
  108. void TextureLayer::SetTransferableResource(
  109. const viz::TransferableResource& resource,
  110. viz::ReleaseCallback release_callback) {
  111. bool requires_commit = true;
  112. SetTransferableResourceInternal(resource, std::move(release_callback),
  113. requires_commit);
  114. }
  115. void TextureLayer::SetLayerTreeHost(LayerTreeHost* host) {
  116. if (layer_tree_host() == host) {
  117. Layer::SetLayerTreeHost(host);
  118. return;
  119. }
  120. // If we're removed from the tree, the TextureLayerImpl will be destroyed, and
  121. // we will need to set the mailbox again on a new TextureLayerImpl the next
  122. // time we push.
  123. if (!host && resource_holder_.Read(*this))
  124. needs_set_resource_.Write(*this) = true;
  125. if (host) {
  126. // When attached to a new LayerTreeHost, all previously registered
  127. // SharedBitmapIds will need to be re-sent to the new TextureLayerImpl
  128. // representing this layer on the compositor thread.
  129. auto& registered_bitmaps = registered_bitmaps_.Write(*this);
  130. to_register_bitmaps_.Write(*this).insert(
  131. std::make_move_iterator(registered_bitmaps.begin()),
  132. std::make_move_iterator(registered_bitmaps.end()));
  133. registered_bitmaps.clear();
  134. }
  135. Layer::SetLayerTreeHost(host);
  136. }
  137. bool TextureLayer::HasDrawableContent() const {
  138. return (client_.Read(*this) || resource_holder_.Read(*this)) &&
  139. Layer::HasDrawableContent();
  140. }
  141. bool TextureLayer::Update() {
  142. bool updated = Layer::Update();
  143. if (client_.Read(*this)) {
  144. viz::TransferableResource resource;
  145. viz::ReleaseCallback release_callback;
  146. if (client_.Write(*this)->PrepareTransferableResource(this, &resource,
  147. &release_callback)) {
  148. // Already within a commit, no need to do another one immediately.
  149. bool requires_commit = false;
  150. SetTransferableResourceInternal(resource, std::move(release_callback),
  151. requires_commit);
  152. updated = true;
  153. }
  154. }
  155. // SetTransferableResource could be called externally and the same mailbox
  156. // used for different textures. Such callers notify this layer that the
  157. // texture has changed by calling SetNeedsDisplay, so check for that here.
  158. return updated || !update_rect().IsEmpty();
  159. }
  160. bool TextureLayer::IsSnappedToPixelGridInTarget() const {
  161. // Often layers are positioned with CSS to "50%", which can often leave them
  162. // with a fractional (N + 0.5) pixel position. This would leave them looking
  163. // fuzzy, so we request that TextureLayers are snapped to the pixel grid,
  164. // since their content is generated externally and we can not adjust for it
  165. // inside the content (unlike for PictureLayers).
  166. return true;
  167. }
  168. void TextureLayer::PushPropertiesTo(
  169. LayerImpl* layer,
  170. const CommitState& commit_state,
  171. const ThreadUnsafeCommitState& unsafe_state) {
  172. Layer::PushPropertiesTo(layer, commit_state, unsafe_state);
  173. TRACE_EVENT0("cc", "TextureLayer::PushPropertiesTo");
  174. TextureLayerImpl* texture_layer = static_cast<TextureLayerImpl*>(layer);
  175. texture_layer->SetFlipped(flipped_.Read(*this));
  176. texture_layer->SetNearestNeighbor(nearest_neighbor_.Read(*this));
  177. texture_layer->SetUVTopLeft(uv_top_left_.Read(*this));
  178. texture_layer->SetUVBottomRight(uv_bottom_right_.Read(*this));
  179. texture_layer->SetPremultipliedAlpha(premultiplied_alpha_.Read(*this));
  180. texture_layer->SetBlendBackgroundColor(blend_background_color_.Read(*this));
  181. texture_layer->SetForceTextureToOpaque(force_texture_to_opaque_.Read(*this));
  182. if (needs_set_resource_.Read(*this)) {
  183. viz::TransferableResource resource;
  184. viz::ReleaseCallback release_callback;
  185. if (auto& resource_holder = resource_holder_.Write(*this)) {
  186. resource = resource_holder->resource();
  187. release_callback =
  188. base::BindOnce(&TransferableResourceHolder::Return, resource_holder,
  189. base::RetainedRef(layer->layer_tree_impl()
  190. ->task_runner_provider()
  191. ->MainThreadTaskRunner()));
  192. }
  193. texture_layer->SetTransferableResource(resource,
  194. std::move(release_callback));
  195. needs_set_resource_.Write(*this) = false;
  196. }
  197. auto& to_register_bitmaps = to_register_bitmaps_.Write(*this);
  198. for (auto& pair : to_register_bitmaps)
  199. texture_layer->RegisterSharedBitmapId(pair.first, pair.second);
  200. // Store the registered SharedBitmapIds in case we get a new TextureLayerImpl,
  201. // in a new tree, to re-send them to.
  202. registered_bitmaps_.Write(*this).insert(
  203. std::make_move_iterator(to_register_bitmaps.begin()),
  204. std::make_move_iterator(to_register_bitmaps.end()));
  205. to_register_bitmaps.clear();
  206. auto& to_unregister_bitmap_ids = to_unregister_bitmap_ids_.Write(*this);
  207. for (const auto& id : to_unregister_bitmap_ids)
  208. texture_layer->UnregisterSharedBitmapId(id);
  209. to_unregister_bitmap_ids.clear();
  210. }
  211. SharedBitmapIdRegistration TextureLayer::RegisterSharedBitmapId(
  212. const viz::SharedBitmapId& id,
  213. scoped_refptr<CrossThreadSharedBitmap> bitmap) {
  214. DCHECK(to_register_bitmaps_.Read(*this).find(id) ==
  215. to_register_bitmaps_.Read(*this).end());
  216. DCHECK(registered_bitmaps_.Read(*this).find(id) ==
  217. registered_bitmaps_.Read(*this).end());
  218. to_register_bitmaps_.Write(*this)[id] = std::move(bitmap);
  219. base::Erase(to_unregister_bitmap_ids_.Write(*this), id);
  220. // This does not SetNeedsCommit() to be as lazy as possible. Notifying a
  221. // SharedBitmapId is not needed until it is used, and using it will require
  222. // a commit, so we can wait for that commit before forwarding the
  223. // notification instead of forcing it to happen as a side effect of this
  224. // method.
  225. SetNeedsPushProperties();
  226. return SharedBitmapIdRegistration(weak_ptr_factory_.GetWeakPtr(), id);
  227. }
  228. void TextureLayer::UnregisterSharedBitmapId(viz::SharedBitmapId id) {
  229. // If we didn't get to sending the registration to the compositor thread yet,
  230. // just remove it.
  231. to_register_bitmaps_.Write(*this).erase(id);
  232. // Since we also track all previously sent registrations, we must remove that
  233. // to in order to prevent re-registering on another LayerTreeHost.
  234. registered_bitmaps_.Write(*this).erase(id);
  235. to_unregister_bitmap_ids_.Write(*this).push_back(id);
  236. // Unregistering a SharedBitmapId needs to happen eventually to prevent
  237. // leaking the SharedMemory in the display compositor. But this attempts to be
  238. // lazy and not force a commit prematurely, so just requests a
  239. // PushPropertiesTo() without requesting a commit.
  240. SetNeedsPushProperties();
  241. }
  242. TextureLayer::TransferableResourceHolder::TransferableResourceHolder(
  243. const viz::TransferableResource& resource,
  244. viz::ReleaseCallback release_callback)
  245. : resource_(resource),
  246. release_callback_(std::move(release_callback)),
  247. sync_token_(resource.mailbox_holder.sync_token) {}
  248. TextureLayer::TransferableResourceHolder::~TransferableResourceHolder() {
  249. if (release_callback_) {
  250. if (!release_callback_task_runner_ ||
  251. release_callback_task_runner_->RunsTasksInCurrentSequence()) {
  252. std::move(release_callback_).Run(sync_token_, is_lost_);
  253. } else {
  254. DCHECK(release_callback_task_runner_);
  255. release_callback_task_runner_->PostTask(
  256. FROM_HERE,
  257. base::BindOnce(std::move(release_callback_), sync_token_, is_lost_));
  258. }
  259. }
  260. }
  261. scoped_refptr<TextureLayer::TransferableResourceHolder>
  262. TextureLayer::TransferableResourceHolder::Create(
  263. const viz::TransferableResource& resource,
  264. viz::ReleaseCallback release_callback) {
  265. return new TransferableResourceHolder(resource, std::move(release_callback));
  266. }
  267. void TextureLayer::TransferableResourceHolder::Return(
  268. scoped_refptr<base::SequencedTaskRunner> main_thread_task_runner,
  269. const gpu::SyncToken& sync_token,
  270. bool is_lost) {
  271. sync_token_ = sync_token;
  272. is_lost_ = is_lost;
  273. // When this method returns, the refcount of the holder will be decremented,
  274. // which might cause it to be destructed on the impl thread. We store the
  275. // main thread task runner here to make sure it's available to the destructor.
  276. release_callback_task_runner_ = std::move(main_thread_task_runner);
  277. }
  278. } // namespace cc