blob: 4d090c9664ff5e1142db49fb3452dec91ca47f5e [file] [log] [blame]
// Copyright 2017 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 "third_party/blink/renderer/platform/graphics/video_frame_resource_provider.h"
#include <memory>
#include "base/bind.h"
#include "base/threading/thread_restrictions.h"
#include "base/trace_event/trace_event.h"
#include "components/viz/client/client_resource_provider.h"
#include "components/viz/common/gpu/raster_context_provider.h"
#include "components/viz/common/quads/compositor_render_pass.h"
#include "components/viz/common/quads/solid_color_draw_quad.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 "third_party/blink/public/platform/web_vector.h"
namespace blink {
VideoFrameResourceProvider::VideoFrameResourceProvider(
const cc::LayerTreeSettings& settings,
bool use_sync_primitives)
: settings_(settings), use_sync_primitives_(use_sync_primitives) {}
VideoFrameResourceProvider::~VideoFrameResourceProvider() {
// Drop all resources before closing the ClientResourceProvider.
resource_updater_ = nullptr;
if (resource_provider_)
resource_provider_->ShutdownAndReleaseAllResources();
}
void VideoFrameResourceProvider::Initialize(
viz::RasterContextProvider* media_context_provider,
viz::SharedBitmapReporter* shared_bitmap_reporter) {
context_provider_ = media_context_provider;
resource_provider_ = std::make_unique<viz::ClientResourceProvider>();
int max_texture_size;
if (context_provider_) {
max_texture_size =
context_provider_->ContextCapabilities().max_texture_size;
} else {
// Pick an arbitrary limit here similar to what hardware might.
max_texture_size = 16 * 1024;
}
resource_updater_ = std::make_unique<media::VideoResourceUpdater>(
nullptr, media_context_provider, shared_bitmap_reporter,
resource_provider_.get(), settings_.use_stream_video_draw_quad,
settings_.resource_settings.use_gpu_memory_buffer_resources,
settings_.resource_settings.use_r16_texture, max_texture_size);
}
void VideoFrameResourceProvider::OnContextLost() {
// Drop all resources before closing the ClientResourceProvider.
resource_updater_ = nullptr;
if (resource_provider_)
resource_provider_->ShutdownAndReleaseAllResources();
resource_provider_ = nullptr;
context_provider_ = nullptr;
}
void VideoFrameResourceProvider::AppendQuads(
viz::CompositorRenderPass* render_pass,
scoped_refptr<media::VideoFrame> frame,
media::VideoRotation rotation,
bool is_opaque) {
TRACE_EVENT0("media", "VideoFrameResourceProvider::AppendQuads");
DCHECK(resource_updater_);
DCHECK(resource_provider_);
// When obtaining frame resources, we end up having to wait. See
// https://crbug/878070.
// Unfortunately, we have no idea if blocking is allowed on the current thread
// or not. If we're on the cc impl thread, the answer is yes, and further
// the thread is marked as not allowing blocking primitives. On the various
// media threads, however, blocking is not allowed but the blocking scopes
// are. So, we use ScopedAllow only if we're told that we should do so.
if (use_sync_primitives_) {
base::ScopedAllowBaseSyncPrimitives allow_base_sync_primitives;
resource_updater_->ObtainFrameResources(frame);
} else {
resource_updater_->ObtainFrameResources(frame);
}
gfx::Transform transform = gfx::Transform();
// The quad's rect is in pre-transform space so that applying the transform on
// it will produce the bounds in target space.
gfx::Rect quad_rect = gfx::Rect(frame->natural_size());
switch (rotation) {
case media::VIDEO_ROTATION_90:
transform.Rotate(90.0);
transform.Translate(0.0, -quad_rect.height());
break;
case media::VIDEO_ROTATION_180:
transform.Rotate(180.0);
transform.Translate(-quad_rect.width(), -quad_rect.height());
break;
case media::VIDEO_ROTATION_270:
transform.Rotate(270.0);
transform.Translate(-quad_rect.width(), 0);
break;
case media::VIDEO_ROTATION_0:
break;
}
gfx::Rect visible_quad_rect = quad_rect;
gfx::Rect clip_rect;
gfx::MaskFilterInfo mask_filter_info;
bool is_clipped = false;
float draw_opacity = 1.0f;
int sorting_context_id = 0;
resource_updater_->AppendQuads(render_pass, std::move(frame), transform,
quad_rect, visible_quad_rect, mask_filter_info,
clip_rect, is_clipped, is_opaque, draw_opacity,
sorting_context_id);
}
void VideoFrameResourceProvider::ReleaseFrameResources() {
resource_updater_->ReleaseFrameResources();
}
void VideoFrameResourceProvider::PrepareSendToParent(
const WebVector<viz::ResourceId>& resource_ids,
WebVector<viz::TransferableResource>* transferable_resources) {
std::vector<viz::TransferableResource> resources_list;
resource_provider_->PrepareSendToParent(
const_cast<WebVector<viz::ResourceId>&>(resource_ids).ReleaseVector(),
&resources_list, context_provider_);
*transferable_resources = std::move(resources_list);
}
void VideoFrameResourceProvider::ReceiveReturnsFromParent(
const Vector<viz::ReturnedResource>& transferable_resources) {
resource_provider_->ReceiveReturnsFromParent(
WebVector<viz::ReturnedResource>(transferable_resources).ReleaseVector());
}
} // namespace blink