123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225 |
- // Copyright 2011 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/video_layer_impl.h"
- #include <stddef.h>
- #include <memory>
- #include <utility>
- #include "base/bind.h"
- #include "base/check.h"
- #include "base/memory/ptr_util.h"
- #include "cc/base/features.h"
- #include "cc/layers/video_frame_provider_client_impl.h"
- #include "cc/trees/layer_tree_frame_sink.h"
- #include "cc/trees/layer_tree_impl.h"
- #include "cc/trees/occlusion.h"
- #include "cc/trees/task_runner_provider.h"
- #include "components/viz/client/client_resource_provider.h"
- #include "components/viz/common/quads/texture_draw_quad.h"
- #include "components/viz/common/quads/yuv_video_draw_quad.h"
- #include "media/base/video_frame.h"
- #include "media/renderers/video_resource_updater.h"
- #include "ui/gfx/color_space.h"
- namespace cc {
- // static
- std::unique_ptr<VideoLayerImpl> VideoLayerImpl::Create(
- LayerTreeImpl* tree_impl,
- int id,
- VideoFrameProvider* provider,
- const media::VideoTransformation& video_transform) {
- DCHECK(tree_impl->task_runner_provider()->IsMainThreadBlocked() ||
- base::FeatureList::IsEnabled(features::kNonBlockingCommit));
- DCHECK(tree_impl->task_runner_provider()->IsImplThread());
- scoped_refptr<VideoFrameProviderClientImpl> provider_client_impl =
- VideoFrameProviderClientImpl::Create(
- provider, tree_impl->GetVideoFrameControllerClient());
- return base::WrapUnique(new VideoLayerImpl(
- tree_impl, id, std::move(provider_client_impl), video_transform));
- }
- VideoLayerImpl::VideoLayerImpl(
- LayerTreeImpl* tree_impl,
- int id,
- scoped_refptr<VideoFrameProviderClientImpl> provider_client_impl,
- const media::VideoTransformation& video_transform)
- : LayerImpl(tree_impl, id),
- provider_client_impl_(std::move(provider_client_impl)),
- video_transform_(video_transform) {
- set_may_contain_video(true);
- }
- VideoLayerImpl::~VideoLayerImpl() {
- if (!provider_client_impl_->Stopped()) {
- // In impl side painting, we may have a pending and active layer
- // associated with the video provider at the same time. Both have a ref
- // on the VideoFrameProviderClientImpl, but we stop when the first
- // LayerImpl (the one on the pending tree) is destroyed since we know
- // the main thread is blocked for this commit.
- DCHECK(layer_tree_impl()->task_runner_provider()->IsMainThreadBlocked() ||
- base::FeatureList::IsEnabled(features::kNonBlockingCommit));
- DCHECK(layer_tree_impl()->task_runner_provider()->IsImplThread());
- provider_client_impl_->Stop();
- }
- }
- std::unique_ptr<LayerImpl> VideoLayerImpl::CreateLayerImpl(
- LayerTreeImpl* tree_impl) const {
- return base::WrapUnique(new VideoLayerImpl(
- tree_impl, id(), provider_client_impl_, video_transform_));
- }
- void VideoLayerImpl::DidBecomeActive() {
- provider_client_impl_->SetActiveVideoLayer(this);
- }
- bool VideoLayerImpl::WillDraw(DrawMode draw_mode,
- viz::ClientResourceProvider* resource_provider)
- NO_THREAD_SAFETY_ANALYSIS {
- if (draw_mode == DRAW_MODE_RESOURCELESS_SOFTWARE)
- return false;
- if (!LayerImpl::WillDraw(draw_mode, resource_provider))
- return false;
- // Explicitly acquire and release the provider mutex so it can be held from
- // WillDraw to DidDraw. Since the compositor thread is in the middle of
- // drawing, the layer will not be destroyed before DidDraw is called.
- // Therefore, the only thing that will prevent this lock from being released
- // is the GPU process locking it. As the GPU process can't cause the
- // destruction of the provider (calling StopUsingProvider), holding this
- // lock should not cause a deadlock.
- frame_ = provider_client_impl_->AcquireLockAndCurrentFrame();
- if (!frame_.get()) {
- // Drop any resources used by the updater if there is no frame to display.
- updater_ = nullptr;
- // NO_THREAD_SAFETY_ANALYSIS: Releasing the lock in some return paths only.
- provider_client_impl_->ReleaseLock();
- return false;
- }
- if (!updater_) {
- const LayerTreeSettings& settings = layer_tree_impl()->settings();
- // TODO(sergeyu): Pass RasterContextProvider when it's available. Then
- // remove ContextProvider parameter from VideoResourceUpdater.
- updater_ = std::make_unique<media::VideoResourceUpdater>(
- layer_tree_impl()->context_provider(),
- /*raster_context_provider=*/nullptr,
- layer_tree_impl()->layer_tree_frame_sink(),
- layer_tree_impl()->resource_provider(),
- settings.use_stream_video_draw_quad,
- settings.resource_settings.use_gpu_memory_buffer_resources,
- settings.resource_settings.use_r16_texture,
- layer_tree_impl()->max_texture_size());
- }
- updater_->ObtainFrameResources(frame_);
- return true;
- }
- void VideoLayerImpl::AppendQuads(viz::CompositorRenderPass* render_pass,
- AppendQuadsData* append_quads_data) {
- DCHECK(frame_);
- gfx::Transform transform = DrawTransform();
- // bounds() is in post-rotation space so quad rect in content space must be
- // in pre-rotation space
- gfx::Size rotated_size = bounds();
- // Prefer the frame level transform if set.
- auto media_transform =
- frame_->metadata().transformation.value_or(video_transform_);
- switch (media_transform.rotation) {
- case media::VIDEO_ROTATION_90:
- rotated_size = gfx::Size(rotated_size.height(), rotated_size.width());
- transform.RotateAboutZAxis(90.0);
- transform.Translate(0.0, -rotated_size.height());
- break;
- case media::VIDEO_ROTATION_180:
- transform.RotateAboutZAxis(180.0);
- transform.Translate(-rotated_size.width(), -rotated_size.height());
- break;
- case media::VIDEO_ROTATION_270:
- rotated_size = gfx::Size(rotated_size.height(), rotated_size.width());
- transform.RotateAboutZAxis(270.0);
- transform.Translate(-rotated_size.width(), 0);
- break;
- case media::VIDEO_ROTATION_0:
- break;
- }
- if (media_transform.mirrored) {
- transform.RotateAboutYAxis(180.0);
- transform.Translate(-rotated_size.width(), 0);
- }
- gfx::Rect quad_rect(rotated_size);
- Occlusion occlusion_in_video_space =
- draw_properties()
- .occlusion_in_content_space.GetOcclusionWithGivenDrawTransform(
- transform);
- gfx::Rect visible_quad_rect =
- occlusion_in_video_space.GetUnoccludedContentRect(quad_rect);
- if (visible_quad_rect.IsEmpty())
- return;
- absl::optional<gfx::Rect> clip_rect_opt;
- if (is_clipped()) {
- clip_rect_opt = clip_rect();
- }
- updater_->AppendQuads(render_pass, frame_, transform, quad_rect,
- visible_quad_rect, draw_properties().mask_filter_info,
- clip_rect_opt, contents_opaque(), draw_opacity(),
- GetSortingContextId());
- }
- void VideoLayerImpl::DidDraw(viz::ClientResourceProvider* resource_provider) {
- provider_client_impl_->AssertLocked();
- LayerImpl::DidDraw(resource_provider);
- DCHECK(frame_.get());
- updater_->ReleaseFrameResources();
- provider_client_impl_->PutCurrentFrame();
- frame_ = nullptr;
- provider_client_impl_->ReleaseLock();
- }
- SimpleEnclosedRegion VideoLayerImpl::VisibleOpaqueRegion() const {
- // If we don't have a frame yet, then we don't have an opaque region.
- if (!provider_client_impl_->HasCurrentFrame())
- return SimpleEnclosedRegion();
- return LayerImpl::VisibleOpaqueRegion();
- }
- void VideoLayerImpl::ReleaseResources() {
- updater_ = nullptr;
- }
- gfx::ContentColorUsage VideoLayerImpl::GetContentColorUsage() const {
- gfx::ColorSpace frame_color_space;
- if (frame_)
- frame_color_space = frame_->ColorSpace();
- return frame_color_space.GetContentColorUsage();
- }
- void VideoLayerImpl::SetNeedsRedraw() {
- UnionUpdateRect(gfx::Rect(bounds()));
- layer_tree_impl()->SetNeedsRedraw();
- }
- const char* VideoLayerImpl::LayerTypeAsString() const {
- return "cc::VideoLayerImpl";
- }
- } // namespace cc
|