diff options
author | danakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-10 17:32:22 +0000 |
---|---|---|
committer | danakj@chromium.org <danakj@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-04-10 17:32:22 +0000 |
commit | 79635310f5dd0c84a7fad921bf6f93edbadf07ea (patch) | |
tree | 038240395997893649e0550615bdfa82201eb2ad /cc/resources/video_resource_updater.cc | |
parent | 70b0c1649385b92aee1dc0a75825ace70d1cd56a (diff) | |
download | chromium_src-79635310f5dd0c84a7fad921bf6f93edbadf07ea.zip chromium_src-79635310f5dd0c84a7fad921bf6f93edbadf07ea.tar.gz chromium_src-79635310f5dd0c84a7fad921bf6f93edbadf07ea.tar.bz2 |
cc: Recycle resources for software video decode.
When we update a compositor resource from a media::VideoFrame,
try to reuse resources from previous frames that were returned
to us by the ResourceProvider.
R=piman,enne
BUG=179729
Depends on: https://codereview.chromium.org/13445009/
Review URL: https://chromiumcodereview.appspot.com/13959005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@193409 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc/resources/video_resource_updater.cc')
-rw-r--r-- | cc/resources/video_resource_updater.cc | 155 |
1 files changed, 110 insertions, 45 deletions
diff --git a/cc/resources/video_resource_updater.cc b/cc/resources/video_resource_updater.cc index ca2d3bb..bb8e41d 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 |