| Index: cc/resources/video_resource_updater.cc
|
| diff --git a/cc/resources/video_resource_updater.cc b/cc/resources/video_resource_updater.cc
|
| index ca2d3bb9d7c211ef818b9bed2bb25e8613107212..bb8e41d7e860420dbbfdf661e48600d1fadf235b 100644
|
| --- a/cc/resources/video_resource_updater.cc
|
| +++ b/cc/resources/video_resource_updater.cc
|
| @@ -27,7 +27,12 @@ VideoResourceUpdater::VideoResourceUpdater(ResourceProvider* resource_provider)
|
| : resource_provider_(resource_provider) {
|
| }
|
|
|
| -VideoResourceUpdater::~VideoResourceUpdater() {}
|
| +VideoResourceUpdater::~VideoResourceUpdater() {
|
| + while (!recycled_resources_.empty()) {
|
| + resource_provider_->DeleteResource(recycled_resources_.back().resource_id);
|
| + recycled_resources_.pop_back();
|
| + }
|
| +}
|
|
|
| bool VideoResourceUpdater::VerifyFrame(
|
| const scoped_refptr<media::VideoFrame>& video_frame) {
|
| @@ -90,12 +95,6 @@ static gfx::Size SoftwarePlaneDimension(
|
| return coded_size;
|
| }
|
|
|
| -static void ReleaseResource(ResourceProvider* resource_provider,
|
| - ResourceProvider::ResourceId resource_id,
|
| - unsigned sync_point) {
|
| - resource_provider->DeleteResource(resource_id);
|
| -}
|
| -
|
| VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
|
| const scoped_refptr<media::VideoFrame>& video_frame) {
|
| if (!VerifyFrame(video_frame))
|
| @@ -135,54 +134,75 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
|
| int max_resource_size = resource_provider_->max_texture_size();
|
| gfx::Size coded_frame_size = video_frame->coded_size();
|
|
|
| - ResourceProvider::ResourceIdArray plane_resources;
|
| + std::vector<PlaneResource> plane_resources;
|
| bool allocation_success = true;
|
|
|
| for (size_t i = 0; i < output_plane_count; ++i) {
|
| - gfx::Size plane_size =
|
| + gfx::Size output_plane_resource_size =
|
| SoftwarePlaneDimension(input_frame_format,
|
| coded_frame_size,
|
| output_resource_format,
|
| i);
|
| - if (plane_size.IsEmpty() ||
|
| - plane_size.width() > max_resource_size ||
|
| - plane_size.height() > max_resource_size) {
|
| + if (output_plane_resource_size.IsEmpty() ||
|
| + output_plane_resource_size.width() > max_resource_size ||
|
| + output_plane_resource_size.height() > max_resource_size) {
|
| allocation_success = false;
|
| break;
|
| }
|
|
|
| - // TODO(danakj): Could recycle resources that we previously allocated and
|
| - // were returned to us.
|
| - ResourceProvider::ResourceId resource_id =
|
| - resource_provider_->CreateResource(plane_size,
|
| - output_resource_format,
|
| - ResourceProvider::TextureUsageAny);
|
| + ResourceProvider::ResourceId resource_id = 0;
|
| + unsigned sync_point = 0;
|
| +
|
| + // Try recycle a previously-allocated resource.
|
| + for (size_t i = 0; i < recycled_resources_.size(); ++i) {
|
| + if (recycled_resources_[i].resource_format == output_resource_format &&
|
| + recycled_resources_[i].resource_size == output_plane_resource_size) {
|
| + resource_id = recycled_resources_[i].resource_id;
|
| + sync_point = recycled_resources_[i].sync_point;
|
| + recycled_resources_.erase(recycled_resources_.begin() + i);
|
| + break;
|
| + }
|
| + }
|
| +
|
| + if (resource_id == 0) {
|
| + // TODO(danakj): Abstract out hw/sw resource create/delete from
|
| + // ResourceProvider and stop using ResourceProvider in this class.
|
| + resource_id =
|
| + resource_provider_->CreateResource(output_plane_resource_size,
|
| + output_resource_format,
|
| + ResourceProvider::TextureUsageAny);
|
| + }
|
| +
|
| if (resource_id == 0) {
|
| allocation_success = false;
|
| break;
|
| }
|
|
|
| - plane_resources.push_back(resource_id);
|
| + plane_resources.push_back(PlaneResource(resource_id,
|
| + output_plane_resource_size,
|
| + output_resource_format,
|
| + sync_point));
|
| }
|
|
|
| if (!allocation_success) {
|
| for (size_t i = 0; i < plane_resources.size(); ++i)
|
| - resource_provider_->DeleteResource(plane_resources[i]);
|
| + resource_provider_->DeleteResource(plane_resources[i].resource_id);
|
| return VideoFrameExternalResources();
|
| }
|
|
|
| VideoFrameExternalResources external_resources;
|
|
|
| if (software_compositor) {
|
| - DCHECK_EQ(output_resource_format, kRGBResourceFormat);
|
| DCHECK_EQ(plane_resources.size(), 1u);
|
| + DCHECK_EQ(plane_resources[0].resource_format, kRGBResourceFormat);
|
| + DCHECK_EQ(plane_resources[0].sync_point, 0u);
|
|
|
| if (!video_renderer_)
|
| video_renderer_.reset(new media::SkCanvasVideoRenderer);
|
|
|
| {
|
| ResourceProvider::ScopedWriteLockSoftware lock(
|
| - resource_provider_, plane_resources[0]);
|
| + resource_provider_, plane_resources[0].resource_id);
|
| video_renderer_->Paint(video_frame,
|
| lock.sk_canvas(),
|
| video_frame->visible_rect(),
|
| @@ -194,38 +214,38 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
|
| // compositing mode, so this raw unretained resource_provider will always
|
| // be valid when the callback is fired.
|
| TextureMailbox::ReleaseCallback callback_to_free_resource =
|
| - base::Bind(&ReleaseResource,
|
| + base::Bind(&RecycleResource,
|
| + AsWeakPtr(),
|
| base::Unretained(resource_provider_),
|
| - plane_resources[0]);
|
| - external_resources.software_resources.push_back(plane_resources[0]);
|
| + plane_resources[0].resource_id,
|
| + plane_resources[0].resource_size,
|
| + plane_resources[0].resource_format,
|
| + gpu::Mailbox());
|
| + external_resources.software_resources.push_back(
|
| + plane_resources[0].resource_id);
|
| external_resources.software_release_callback = callback_to_free_resource;
|
|
|
| external_resources.type = VideoFrameExternalResources::SOFTWARE_RESOURCE;
|
| return external_resources;
|
| }
|
|
|
| - DCHECK_EQ(output_resource_format,
|
| - static_cast<unsigned>(kYUVResourceFormat));
|
| -
|
| WebKit::WebGraphicsContext3D* context =
|
| resource_provider_->GraphicsContext3D();
|
| DCHECK(context);
|
|
|
| - for (size_t plane = 0; plane < plane_resources.size(); ++plane) {
|
| + for (size_t i = 0; i < plane_resources.size(); ++i) {
|
| // Update each plane's resource id with its content.
|
| - ResourceProvider::ResourceId output_plane_resource_id =
|
| - plane_resources[plane];
|
| - gfx::Size plane_size =
|
| - SoftwarePlaneDimension(input_frame_format,
|
| - coded_frame_size,
|
| - output_resource_format,
|
| - plane);
|
| - const uint8_t* input_plane_pixels = video_frame->data(plane);
|
| + DCHECK_EQ(plane_resources[i].resource_format,
|
| + static_cast<unsigned>(kYUVResourceFormat));
|
| +
|
| + const uint8_t* input_plane_pixels = video_frame->data(i);
|
|
|
| - gfx::Rect image_rect(
|
| - 0, 0, video_frame->stride(plane), plane_size.height());
|
| - gfx::Rect source_rect(plane_size);
|
| - resource_provider_->SetPixels(output_plane_resource_id,
|
| + gfx::Rect image_rect(0,
|
| + 0,
|
| + video_frame->stride(i),
|
| + plane_resources[i].resource_size.height());
|
| + gfx::Rect source_rect(plane_resources[i].resource_size);
|
| + resource_provider_->SetPixels(plane_resources[i].resource_id,
|
| input_plane_pixels,
|
| image_rect,
|
| source_rect,
|
| @@ -234,7 +254,7 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
|
| gpu::Mailbox mailbox;
|
| {
|
| ResourceProvider::ScopedWriteLockGL lock(
|
| - resource_provider_, output_plane_resource_id);
|
| + resource_provider_, plane_resources[i].resource_id);
|
|
|
| GLC(context, context->genMailboxCHROMIUM(mailbox.name));
|
| GLC(context, context->bindTexture(GL_TEXTURE_2D, lock.texture_id()));
|
| @@ -246,11 +266,17 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
|
| // This callback is called by the resource provider itself, so it's okay to
|
| // use an unretained raw pointer here.
|
| TextureMailbox::ReleaseCallback callback_to_free_resource =
|
| - base::Bind(&ReleaseResource,
|
| + base::Bind(&RecycleResource,
|
| + AsWeakPtr(),
|
| base::Unretained(resource_provider_),
|
| - output_plane_resource_id);
|
| + plane_resources[i].resource_id,
|
| + plane_resources[i].resource_size,
|
| + plane_resources[i].resource_format,
|
| + mailbox);
|
| external_resources.mailboxes.push_back(
|
| - TextureMailbox(mailbox, callback_to_free_resource));
|
| + TextureMailbox(mailbox,
|
| + callback_to_free_resource,
|
| + plane_resources[i].sync_point));
|
| }
|
|
|
| external_resources.type = VideoFrameExternalResources::YUV_RESOURCE;
|
| @@ -323,4 +349,43 @@ void VideoResourceUpdater::ReturnTexture(
|
| callback.Run(sync_point);
|
| }
|
|
|
| +// static
|
| +void VideoResourceUpdater::RecycleResource(
|
| + base::WeakPtr<VideoResourceUpdater> updater,
|
| + ResourceProvider* resource_provider,
|
| + unsigned resource_id,
|
| + gfx::Size resource_size,
|
| + unsigned resource_format,
|
| + gpu::Mailbox mailbox,
|
| + unsigned sync_point) {
|
| + WebKit::WebGraphicsContext3D* context =
|
| + resource_provider->GraphicsContext3D();
|
| + if (context) {
|
| + ResourceProvider::ScopedWriteLockGL lock(resource_provider, resource_id);
|
| + GLC(context, context->bindTexture(GL_TEXTURE_2D, lock.texture_id()));
|
| + GLC(context, context->consumeTextureCHROMIUM(GL_TEXTURE_2D, mailbox.name));
|
| + GLC(context, context->bindTexture(GL_TEXTURE_2D, 0));
|
| + }
|
| +
|
| + if (!updater) {
|
| + resource_provider->DeleteResource(resource_id);
|
| + return;
|
| + }
|
| +
|
| + // Drop recycled resources that are the wrong format.
|
| + while (!updater->recycled_resources_.empty() &&
|
| + updater->recycled_resources_.back().resource_format !=
|
| + resource_format) {
|
| + resource_provider->DeleteResource(
|
| + updater->recycled_resources_.back().resource_id);
|
| + updater->recycled_resources_.pop_back();
|
| + }
|
| +
|
| + PlaneResource recycled_resource(resource_id,
|
| + resource_size,
|
| + resource_format,
|
| + sync_point);
|
| + updater->recycled_resources_.push_back(recycled_resource);
|
| +}
|
| +
|
| } // namespace cc
|
|
|