Chromium Code Reviews| Index: cc/resources/video_resource_updater.cc |
| diff --git a/cc/resources/video_resource_updater.cc b/cc/resources/video_resource_updater.cc |
| index cdeb363e1ecdd4d6a3144fe6dfc105986996f61a..aa1e79ebea604238865e8d2c0540f1aa8486a104 100644 |
| --- a/cc/resources/video_resource_updater.cc |
| +++ b/cc/resources/video_resource_updater.cc |
| @@ -172,6 +172,29 @@ VideoResourceUpdater::~VideoResourceUpdater() { |
| } |
| VideoResourceUpdater::ResourceList::iterator |
| +VideoResourceUpdater::RecycleOrAllocateTexture( |
| + const gfx::Size& resource_size, |
| + ResourceFormat resource_format, |
| + const gfx::ColorSpace& color_space, |
| + bool immutable_hint) { |
| + for (auto it = all_resources_.begin(); it != all_resources_.end(); ++it) { |
| + // Reuse resource if attributes match and the resource is a currently |
| + // unreferenced texture. |
| + if (it->resource_size() == resource_size && |
| + it->resource_format() == resource_format && !it->mailbox().IsZero() && |
| + !it->has_refs() && |
| + resource_provider_->GetTextureHint(it->resource_id()) != |
| + ResourceProvider::TEXTURE_HINT_IMMUTABLE) { |
| + return it; |
| + } |
| + } |
| + |
| + // Otherwise allocate a new resource. |
| + return AllocateResource(resource_size, resource_format, color_space, true, |
| + immutable_hint); |
| +} |
| + |
| +VideoResourceUpdater::ResourceList::iterator |
| VideoResourceUpdater::AllocateResource(const gfx::Size& plane_size, |
| ResourceFormat format, |
| const gfx::ColorSpace& color_space, |
| @@ -246,6 +269,54 @@ static gfx::Size SoftwarePlaneDimension(media::VideoFrame* input_frame, |
| return gfx::Size(plane_width, plane_height); |
| } |
| +// Create an RGB texture by software converting YUV planar data, for the case |
| +// where YUV planar textures are not renderable by the GPU. |
| +VideoFrameExternalResources |
| +VideoResourceUpdater::CreateRGBTextureForSoftwarePlanes( |
| + media::VideoFrame* video_frame) { |
| + DCHECK(media::IsYuvPlanar(video_frame->format())); |
| + gpu::gles2::GLES2Interface* gl = context_provider_->ContextGL(); |
| + const ResourceFormat resource_format = ResourceFormat::RGBA_8888; |
| + const gfx::Size output_plane_resource_size = video_frame->coded_size(); |
| + const bool is_immutable = false; |
| + |
| + VideoResourceUpdater::ResourceList::iterator resource = |
| + RecycleOrAllocateTexture(output_plane_resource_size, resource_format, |
| + is_immutable); |
| + |
| + resource->add_ref(); |
| + |
| + size_t bytes_per_row = ResourceUtil::CheckedWidthInBytes<size_t>( |
| + output_plane_resource_size.width(), ResourceFormat::RGBA_8888); |
| + size_t upload_image_stride = |
| + MathUtil::CheckedRoundUp<size_t>(bytes_per_row, 4u); |
|
danakj
2016/08/25 01:25:39
If the format is RGBA8888 how can the bytes per ro
Tobias Sargeant
2016/08/26 15:52:11
True, removed.
|
| + size_t needed_size = |
| + upload_image_stride * output_plane_resource_size.height(); |
| + if (upload_pixels_.size() < needed_size) |
| + upload_pixels_.resize(needed_size); |
| + |
| + media::SkCanvasVideoRenderer::ConvertVideoFrameToRGBPixels( |
| + video_frame, &upload_pixels_[0], upload_image_stride); |
| + |
| + resource_provider_->CopyToResource( |
| + resource->resource_id(), &upload_pixels_[0], resource->resource_size()); |
| + |
| + gpu::SyncToken sync_token; |
| + const uint64_t fence_sync = gl->InsertFenceSyncCHROMIUM(); |
| + gl->ShallowFlushCHROMIUM(); |
| + gl->GenSyncTokenCHROMIUM(fence_sync, sync_token.GetData()); |
| + |
| + VideoFrameExternalResources external_resources; |
| + |
| + external_resources.mailboxes.push_back( |
| + TextureMailbox(resource->mailbox(), sync_token, GL_TEXTURE_2D, |
| + video_frame->coded_size(), false, false)); |
| + external_resources.release_callbacks.push_back( |
| + base::Bind(&RecycleResource, AsWeakPtr(), resource->resource_id())); |
| + external_resources.type = VideoFrameExternalResources::RGBA_RESOURCE; |
| + return external_resources; |
| +} |
| + |
| VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( |
| scoped_refptr<media::VideoFrame> video_frame) { |
| TRACE_EVENT0("cc", "VideoResourceUpdater::CreateForSoftwarePlanes"); |
| @@ -297,6 +368,15 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( |
| ResourceFormat output_resource_format = |
| resource_provider_->YuvResourceFormat(bits_per_channel); |
| + // If GPU compositing is enabled, but the output resource format |
| + // returned by the resource provider is RGBA_8888, then a GPU driver |
| + // bug workaround requires that YUV frames must be converted to RGB |
| + // before texture upload. |
| + if (!software_compositor && |
| + output_resource_format == ResourceFormat::RGBA_8888) { |
| + return CreateRGBTextureForSoftwarePlanes(video_frame.get()); |
| + } |
| + |
| size_t output_plane_count = media::VideoFrame::NumPlanes(input_frame_format); |
| // TODO(skaslev): If we're in software compositing mode, we do the YUV -> RGB |
| @@ -424,12 +504,12 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes( |
| // uploading (including non-frame data to fill in the stride). |
| int video_stride_bytes = video_frame->stride(i); |
| - size_t bytes_per_row = ResourceUtil::UncheckedWidthInBytes<size_t>( |
| + size_t bytes_per_row = ResourceUtil::CheckedWidthInBytes<size_t>( |
| resource_size_pixels.width(), plane_resource.resource_format()); |
| // Use 4-byte row alignment (OpenGL default) for upload performance. |
| // Assuming that GL_UNPACK_ALIGNMENT has not changed from default. |
| size_t upload_image_stride = |
| - MathUtil::UncheckedRoundUp<size_t>(bytes_per_row, 4u); |
| + MathUtil::CheckedRoundUp<size_t>(bytes_per_row, 4u); |
| bool needs_conversion = false; |
| int shift = 0; |
| @@ -564,28 +644,10 @@ void VideoResourceUpdater::CopyPlaneTexture( |
| // target to avoid loss of precision or dropping any alpha component. |
| const ResourceFormat copy_target_format = ResourceFormat::RGBA_8888; |
| - // Search for an existing resource to reuse. |
| - VideoResourceUpdater::ResourceList::iterator resource = all_resources_.end(); |
| - |
| - for (auto it = all_resources_.begin(); it != all_resources_.end(); ++it) { |
| - // Reuse resource if attributes match and the resource is a currently |
| - // unreferenced texture. |
| - if (it->resource_size() == output_plane_resource_size && |
| - it->resource_format() == copy_target_format && |
| - !it->mailbox().IsZero() && !it->has_refs() && |
| - resource_provider_->GetTextureHint(it->resource_id()) != |
| - ResourceProvider::TEXTURE_HINT_IMMUTABLE) { |
| - resource = it; |
| - break; |
| - } |
| - } |
| - |
| - // Otherwise allocate a new resource. |
| - if (resource == all_resources_.end()) { |
| - const bool is_immutable = false; |
| - resource = AllocateResource(output_plane_resource_size, copy_target_format, |
| - video_frame->ColorSpace(), true, is_immutable); |
| - } |
| + const bool is_immutable = false; |
| + VideoResourceUpdater::ResourceList::iterator resource = |
| + RecycleOrAllocateTexture(output_plane_resource_size, copy_target_format, |
| + video_frame->ColorSpace(), is_immutable); |
| resource->add_ref(); |