| Index: cc/resources/video_resource_updater.cc
|
| diff --git a/cc/resources/video_resource_updater.cc b/cc/resources/video_resource_updater.cc
|
| index b54be5579f05d7d58728d89ae6f204a15549c669..ea8c43a4d8265f25bb5d3bb364b31d7a628fe13c 100644
|
| --- a/cc/resources/video_resource_updater.cc
|
| +++ b/cc/resources/video_resource_updater.cc
|
| @@ -18,6 +18,7 @@
|
| #include "cc/resources/resource_util.h"
|
| #include "gpu/GLES2/gl2extchromium.h"
|
| #include "gpu/command_buffer/client/gles2_interface.h"
|
| +#include "media/base/media_switches.h"
|
| #include "media/base/video_frame.h"
|
| #include "media/renderers/skcanvas_video_renderer.h"
|
| #include "third_party/khronos/GLES2/gl2.h"
|
| @@ -157,6 +158,7 @@ void VideoResourceUpdater::PlaneResource::SetUniqueId(int unique_frame_id,
|
|
|
| VideoFrameExternalResources::VideoFrameExternalResources()
|
| : type(NONE),
|
| + format(RGBA_8888),
|
| read_lock_fences_enabled(false),
|
| offset(0.0f),
|
| multiplier(1.0f),
|
| @@ -308,12 +310,34 @@ void VideoResourceUpdater::MakeHalfFloats(const uint16_t* src,
|
| libyuv::HalfFloatPlane(src, stride, dst, stride, 1.0f / max_value, num, rows);
|
| }
|
|
|
| +ResourceFormat VideoResourceUpdater::YuvResourceFormat(int bits) const {
|
| + if (!context_provider_)
|
| + return LUMINANCE_8;
|
| +
|
| + const auto caps = context_provider_->ContextCapabilities();
|
| + if (caps.disable_one_component_textures)
|
| + return RGBA_8888;
|
| +
|
| + ResourceFormat yuv_resource_format = caps.texture_rg ? RED_8 : LUMINANCE_8;
|
| + if (bits <= 8)
|
| + return yuv_resource_format;
|
| +
|
| + if (caps.texture_half_float_linear)
|
| + return LUMINANCE_F16;
|
| +
|
| + if (base::FeatureList::IsEnabled(media::kUseRGTexture) || use_rg_for_testing_)
|
| + return caps.texture_rg ? RG_88 : RGBA_8888;
|
| +
|
| + return yuv_resource_format;
|
| +}
|
| +
|
| VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
|
| scoped_refptr<media::VideoFrame> video_frame) {
|
| TRACE_EVENT0("cc", "VideoResourceUpdater::CreateForSoftwarePlanes");
|
| const media::VideoPixelFormat input_frame_format = video_frame->format();
|
|
|
| // TODO(hubbe): Make this a video frame method.
|
| + // TODO(dshwang): handle YUV4XXPX by GMBs pool code. crbug.com/445071
|
| int bits_per_channel = 0;
|
| switch (input_frame_format) {
|
| case media::PIXEL_FORMAT_UNKNOWN:
|
| @@ -357,27 +381,27 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
|
| break;
|
| }
|
|
|
| - // TODO(dshwang): support PIXEL_FORMAT_Y16. crbug.com/624436
|
| - DCHECK_NE(bits_per_channel, 16);
|
| -
|
| // Only YUV software video frames are supported.
|
| if (!media::IsYuvPlanar(input_frame_format)) {
|
| NOTREACHED() << media::VideoPixelFormatToString(input_frame_format);
|
| return VideoFrameExternalResources();
|
| }
|
|
|
| - const bool software_compositor = context_provider_ == NULL;
|
| + const bool software_compositor = context_provider_ == nullptr;
|
| + bool disable_one_component_textures = true;
|
| + if (!software_compositor) {
|
| + const auto caps = context_provider_->ContextCapabilities();
|
| + disable_one_component_textures = caps.disable_one_component_textures;
|
| + }
|
|
|
| - ResourceFormat output_resource_format =
|
| - resource_provider_->YuvResourceFormat(bits_per_channel);
|
| + ResourceFormat output_resource_format = 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.
|
| bool texture_needs_rgb_conversion =
|
| - !software_compositor &&
|
| - output_resource_format == ResourceFormat::RGBA_8888;
|
| + !software_compositor && disable_one_component_textures;
|
| 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,8 +448,8 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
|
| }
|
|
|
| VideoFrameExternalResources external_resources;
|
| -
|
| external_resources.bits_per_channel = bits_per_channel;
|
| + external_resources.format = output_resource_format;
|
|
|
| if (software_compositor || texture_needs_rgb_conversion) {
|
| DCHECK_EQ(plane_resources.size(), 1u);
|
| @@ -483,13 +507,33 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
|
| return external_resources;
|
| }
|
|
|
| - for (size_t i = 0; i < plane_resources.size(); ++i) {
|
| - PlaneResource& plane_resource = *plane_resources[i];
|
| + const bool highbit_rg_rgba_fallback =
|
| + bits_per_channel > 8 && output_resource_format == RGBA_8888;
|
| + bool needs_conversion = false;
|
| + int shift = 0;
|
| + if (output_resource_format == LUMINANCE_F16) {
|
| + // LUMINANCE_F16 uses half-floats, so we always need a conversion step.
|
| + needs_conversion = true;
|
| + } else if (output_resource_format == RG_88) {
|
| + // RG_88 can represent 16bit int, so we don't need a conversion step.
|
| + needs_conversion = false;
|
| + } else if (highbit_rg_rgba_fallback) {
|
| + // RG channels is used to represent 16bit int.
|
| + needs_conversion = true;
|
| + } else if (bits_per_channel > 8) {
|
| + // If bits_per_channel > 8 and we can't use RG_88, we need to
|
| + // shift the data down and create an 8-bit texture.
|
| + needs_conversion = true;
|
| + shift = bits_per_channel - 8;
|
| + external_resources.bits_per_channel = 8;
|
| + }
|
| +
|
| + for (size_t plane = 0; plane < plane_resources.size(); ++plane) {
|
| + PlaneResource& plane_resource = *plane_resources[plane];
|
| // Update each plane's resource id with its content.
|
| - DCHECK_EQ(plane_resource.resource_format(),
|
| - resource_provider_->YuvResourceFormat(bits_per_channel));
|
| + DCHECK_EQ(plane_resource.resource_format(), output_resource_format);
|
|
|
| - if (!plane_resource.Matches(video_frame->unique_id(), i)) {
|
| + if (!plane_resource.Matches(video_frame->unique_id(), plane)) {
|
| // TODO(hubbe): Move all conversion (and upload?) code to media/.
|
| // We need to transfer data from |video_frame| to the plane resource.
|
| // TODO(reveman): Can use GpuMemoryBuffers here to improve performance.
|
| @@ -499,31 +543,19 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
|
| gfx::Size resource_size_pixels = plane_resource.resource_size();
|
| // The |video_stride_bytes| is the width of the video frame we are
|
| // uploading (including non-frame data to fill in the stride).
|
| - int video_stride_bytes = video_frame->stride(i);
|
| + int video_stride_bytes = video_frame->stride(plane);
|
|
|
| size_t bytes_per_row = ResourceUtil::CheckedWidthInBytes<size_t>(
|
| - resource_size_pixels.width(), plane_resource.resource_format());
|
| + resource_size_pixels.width(), output_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::CheckedRoundUp<size_t>(bytes_per_row, 4u);
|
|
|
| - bool needs_conversion = false;
|
| - int shift = 0;
|
| -
|
| - // LUMINANCE_F16 uses half-floats, so we always need a conversion step.
|
| - if (plane_resource.resource_format() == LUMINANCE_F16) {
|
| - needs_conversion = true;
|
| - } else if (bits_per_channel > 8) {
|
| - // If bits_per_channel > 8 and we can't use LUMINANCE_F16, we need to
|
| - // shift the data down and create an 8-bit texture.
|
| - needs_conversion = true;
|
| - shift = bits_per_channel - 8;
|
| - }
|
| const uint8_t* pixels;
|
| if (static_cast<int>(upload_image_stride) == video_stride_bytes &&
|
| !needs_conversion) {
|
| - pixels = video_frame->data(i);
|
| + pixels = video_frame->data(plane);
|
| } else {
|
| // Avoid malloc for each frame/plane if possible.
|
| size_t needed_size =
|
| @@ -532,11 +564,11 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
|
| upload_pixels_.resize(needed_size);
|
|
|
| for (int row = 0; row < resource_size_pixels.height(); ++row) {
|
| - if (plane_resource.resource_format() == LUMINANCE_F16) {
|
| + if (output_resource_format == LUMINANCE_F16) {
|
| uint16_t* dst = reinterpret_cast<uint16_t*>(
|
| &upload_pixels_[upload_image_stride * row]);
|
| const uint16_t* src = reinterpret_cast<uint16_t*>(
|
| - video_frame->data(i) + (video_stride_bytes * row));
|
| + video_frame->data(plane) + (video_stride_bytes * row));
|
| if (bits_per_channel <= 10) {
|
| // Micro-benchmarking indicates that the compiler does
|
| // a good enough job of optimizing this loop that trying
|
| @@ -548,12 +580,19 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
|
| } else {
|
| MakeHalfFloats(src, bits_per_channel, bytes_per_row / 2, dst);
|
| }
|
| + } else if (highbit_rg_rgba_fallback) {
|
| + uint32_t* dst = reinterpret_cast<uint32_t*>(
|
| + &upload_pixels_[upload_image_stride * row]);
|
| + const uint16_t* src = reinterpret_cast<uint16_t*>(
|
| + video_frame->data(plane) + (video_stride_bytes * row));
|
| + for (int i = 0; i < resource_size_pixels.width(); i++)
|
| + dst[i] = src[i];
|
| } else if (shift != 0) {
|
| // We have more-than-8-bit input which we need to shift
|
| // down to fit it into an 8-bit texture.
|
| uint8_t* dst = &upload_pixels_[upload_image_stride * row];
|
| const uint16_t* src = reinterpret_cast<uint16_t*>(
|
| - video_frame->data(i) + (video_stride_bytes * row));
|
| + video_frame->data(plane) + (video_stride_bytes * row));
|
| for (size_t i = 0; i < bytes_per_row; i++)
|
| dst[i] = src[i] >> shift;
|
| } else {
|
| @@ -561,7 +600,7 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
|
| // differ in stride, copy one row at a time.
|
| uint8_t* dst = &upload_pixels_[upload_image_stride * row];
|
| const uint8_t* src =
|
| - video_frame->data(i) + (video_stride_bytes * row);
|
| + video_frame->data(plane) + (video_stride_bytes * row);
|
| memcpy(dst, src, bytes_per_row);
|
| }
|
| }
|
| @@ -570,7 +609,7 @@ VideoFrameExternalResources VideoResourceUpdater::CreateForSoftwarePlanes(
|
|
|
| resource_provider_->CopyToResource(plane_resource.resource_id(), pixels,
|
| resource_size_pixels);
|
| - plane_resource.SetUniqueId(video_frame->unique_id(), i);
|
| + plane_resource.SetUniqueId(video_frame->unique_id(), plane);
|
| }
|
|
|
| if (plane_resource.resource_format() == LUMINANCE_F16) {
|
|
|