blob: c422902acfe8071a1a66aef74cb861238c5b5995 [file] [log] [blame]
// Copyright 2013 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.
#ifndef CC_RESOURCES_VIDEO_RESOURCE_UPDATER_H_
#define CC_RESOURCES_VIDEO_RESOURCE_UPDATER_H_
#include <stddef.h>
#include <stdint.h>
#include <list>
#include <memory>
#include <vector>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "cc/cc_export.h"
#include "components/viz/common/resources/release_callback.h"
#include "components/viz/common/resources/resource_format.h"
#include "components/viz/common/resources/resource_id.h"
#include "components/viz/common/resources/transferable_resource.h"
#include "ui/gfx/buffer_types.h"
#include "ui/gfx/geometry/size.h"
namespace media {
class PaintCanvasVideoRenderer;
class VideoFrame;
}
namespace gfx {
class Rect;
class Transform;
} // namespace gfx
namespace viz {
class ContextProvider;
class RenderPass;
}
namespace cc {
class LayerTreeResourceProvider;
class CC_EXPORT VideoFrameExternalResources {
public:
// Specifies what type of data is contained in the mailboxes, as well as how
// many mailboxes will be present.
enum ResourceType {
NONE,
YUV_RESOURCE,
RGB_RESOURCE,
RGBA_PREMULTIPLIED_RESOURCE,
RGBA_RESOURCE,
STREAM_TEXTURE_RESOURCE,
SOFTWARE_RESOURCE
};
ResourceType type = NONE;
std::vector<viz::TransferableResource> resources;
std::vector<viz::ReleaseCallback> release_callbacks;
// TODO(danakj): Remove these and use TransferableResources to send
// software things too.
unsigned software_resource = viz::kInvalidResourceId;
viz::ReleaseCallback software_release_callback;
// Used by hardware textures which do not return values in the 0-1 range.
// After a lookup, subtract offset and multiply by multiplier.
float offset = 0.f;
float multiplier = 1.f;
uint32_t bits_per_channel = 8;
VideoFrameExternalResources();
VideoFrameExternalResources(VideoFrameExternalResources&& other);
VideoFrameExternalResources& operator=(VideoFrameExternalResources&& other);
~VideoFrameExternalResources();
};
// VideoResourceUpdater is used by the video system to produce frame content as
// resources consumable by the compositor.
class CC_EXPORT VideoResourceUpdater {
public:
VideoResourceUpdater(viz::ContextProvider* context_provider,
LayerTreeResourceProvider* resource_provider,
bool use_stream_video_draw_quad);
~VideoResourceUpdater();
VideoFrameExternalResources CreateExternalResourcesFromVideoFrame(
scoped_refptr<media::VideoFrame> video_frame);
void SetUseR16ForTesting(bool use_r16_for_testing) {
use_r16_for_testing_ = use_r16_for_testing;
}
void ObtainFrameResources(scoped_refptr<media::VideoFrame> video_frame);
void ReleaseFrameResources();
void AppendQuads(viz::RenderPass* render_pass,
scoped_refptr<media::VideoFrame> frame,
gfx::Transform transform,
gfx::Size rotated_size,
gfx::Rect visible_layer_rect,
gfx::Rect clip_rect,
bool is_clipped,
bool context_opaque,
float draw_opacity,
int sorting_context_id,
gfx::Rect visible_quad_rect);
private:
class PlaneResource {
public:
PlaneResource(unsigned resource_id,
const gfx::Size& resource_size,
viz::ResourceFormat resource_format,
gpu::Mailbox mailbox);
PlaneResource(const PlaneResource& other);
// Returns true if this resource matches the unique identifiers of another
// VideoFrame resource.
bool Matches(int unique_frame_id, size_t plane_index);
// Sets the unique identifiers for this resource, may only be called when
// there is a single reference to the resource (i.e. |ref_count_| == 1).
void SetUniqueId(int unique_frame_id, size_t plane_index);
// Accessors for resource identifiers provided at construction time.
unsigned resource_id() const { return resource_id_; }
const gfx::Size& resource_size() const { return resource_size_; }
viz::ResourceFormat resource_format() const { return resource_format_; }
const gpu::Mailbox& mailbox() const { return mailbox_; }
// Various methods for managing references. See |ref_count_| for details.
void add_ref() { ++ref_count_; }
void remove_ref() { --ref_count_; }
void clear_refs() { ref_count_ = 0; }
bool has_refs() const { return ref_count_ != 0; }
private:
// The balance between the number of times this resource has been returned
// from CreateForSoftwarePlanes vs released in RecycleResource.
int ref_count_ = 0;
// These two members are used for identifying the data stored in this
// resource; they uniquely identify a media::VideoFrame plane.
int unique_frame_id_ = 0;
size_t plane_index_ = 0u;
// Indicates if the above two members have been set or not.
bool has_unique_frame_id_and_plane_index_ = false;
const unsigned resource_id_;
const gfx::Size resource_size_;
const viz::ResourceFormat resource_format_;
const gpu::Mailbox mailbox_;
};
// This needs to be a container where iterators can be erased without
// invalidating other iterators.
typedef std::list<PlaneResource> ResourceList;
// Obtain a resource of the right format by either recycling an
// unreferenced but appropriately formatted resource, or by
// allocating a new resource.
// Additionally, if the |unique_id| and |plane_index| match, then
// it is assumed that the resource has the right data already and will only be
// used for reading, and so is returned even if it is still referenced.
// Passing -1 for |plane_index| avoids returning referenced
// resources.
ResourceList::iterator RecycleOrAllocateResource(
const gfx::Size& resource_size,
viz::ResourceFormat resource_format,
const gfx::ColorSpace& color_space,
bool software_resource,
int unique_id,
int plane_index);
ResourceList::iterator AllocateResource(const gfx::Size& plane_size,
viz::ResourceFormat format,
const gfx::ColorSpace& color_space,
bool software_resource);
void DeleteResource(ResourceList::iterator resource_it);
void CopyHardwarePlane(media::VideoFrame* video_frame,
const gfx::ColorSpace& resource_color_space,
const gpu::MailboxHolder& mailbox_holder,
VideoFrameExternalResources* external_resources);
VideoFrameExternalResources CreateForHardwarePlanes(
scoped_refptr<media::VideoFrame> video_frame);
VideoFrameExternalResources CreateForSoftwarePlanes(
scoped_refptr<media::VideoFrame> video_frame);
static void RecycleResource(base::WeakPtr<VideoResourceUpdater> updater,
unsigned resource_id,
const gpu::SyncToken& sync_token,
bool lost_resource);
static void ReturnTexture(base::WeakPtr<VideoResourceUpdater> updater,
const scoped_refptr<media::VideoFrame>& video_frame,
const gpu::SyncToken& sync_token,
bool lost_resource);
viz::ContextProvider* context_provider_;
LayerTreeResourceProvider* resource_provider_;
const bool use_stream_video_draw_quad_;
std::unique_ptr<media::PaintCanvasVideoRenderer> video_renderer_;
std::vector<uint8_t> upload_pixels_;
bool use_r16_for_testing_ = false;
VideoFrameExternalResources::ResourceType frame_resource_type_;
// TODO(danakj): Remove these, use TransferableResource for software path too.
unsigned software_resource_ = viz::kInvalidResourceId;
// Called once for |software_resource_|.
viz::ReleaseCallback software_release_callback_;
float frame_resource_offset_;
float frame_resource_multiplier_;
uint32_t frame_bits_per_channel_;
struct FrameResource {
FrameResource(viz::ResourceId id, gfx::Size size_in_pixels)
: id(id), size_in_pixels(size_in_pixels) {}
viz::ResourceId id;
gfx::Size size_in_pixels;
};
std::vector<FrameResource> frame_resources_;
// Recycle resources so that we can reduce the number of allocations and
// data transfers.
ResourceList all_resources_;
base::WeakPtrFactory<VideoResourceUpdater> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN(VideoResourceUpdater);
};
} // namespace cc
#endif // CC_RESOURCES_VIDEO_RESOURCE_UPDATER_H_