Commit 33ca177f authored by Peng Huang's avatar Peng Huang Committed by Commit Bot

Hook up skia makeYUVAPromiseTexture API

Know issues:
 * Skia only draws Y plane.
 * makeYUVAPromiseTexture() will release context, even if it failed.
 * Skia doesn't accept GL_RGBA8 format for a yuva plane

Bug: 824382
Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel
Change-Id: Ic8da2b3de574ef2a0d527c79f34d383a676a3bc0
Reviewed-on: https://chromium-review.googlesource.com/c/1262421Reviewed-by: default avatarAntoine Labour <piman@chromium.org>
Commit-Queue: Peng Huang <penghuang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#599193}
parent c43eba93
...@@ -43,15 +43,16 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurface : public OutputSurface { ...@@ -43,15 +43,16 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurface : public OutputSurface {
virtual sk_sp<SkImage> MakePromiseSkImage(ResourceMetadata metadata) = 0; virtual sk_sp<SkImage> MakePromiseSkImage(ResourceMetadata metadata) = 0;
// Make a promise SkImage from the given |metadata| and the |yuv_color_space|. // Make a promise SkImage from the given |metadata| and the |yuv_color_space|.
// For YUV format, three resource metadatas should be provided. metadatas[0] // For YUV format, at least three resource metadatas should be provided.
// contains pixels from y panel, metadatas[1] contains pixels from u panel, // metadatas[0] contains pixels from y panel, metadatas[1] contains pixels
// metadatas[2] contains pixels from v panel. // from u panel, metadatas[2] contains pixels from v panel. For NV12 format,
// For NV12 format, two resource metadatas should be provided. metadatas[0] // at least two resource metadatas should be provided. metadatas[0] contains
// contains pixels from y panel, metadatas[1] contains pixels from u and v // pixels from y panel, metadatas[1] contains pixels from u and v panels. If
// panels. // has_alpha is true, the last item in metadatas contains alpha panel.
virtual sk_sp<SkImage> MakePromiseSkImageFromYUV( virtual sk_sp<SkImage> MakePromiseSkImageFromYUV(
std::vector<ResourceMetadata> metadatas, std::vector<ResourceMetadata> metadatas,
SkYUVColorSpace yuv_color_space) = 0; SkYUVColorSpace yuv_color_space,
bool has_alpha) = 0;
// Swaps the current backbuffer to the screen. // Swaps the current backbuffer to the screen.
virtual void SkiaSwapBuffers(OutputSurfaceFrame frame) = 0; virtual void SkiaSwapBuffers(OutputSurfaceFrame frame) = 0;
......
...@@ -107,7 +107,7 @@ SkiaRenderer::ScopedSkImageBuilder::ScopedSkImageBuilder( ...@@ -107,7 +107,7 @@ SkiaRenderer::ScopedSkImageBuilder::ScopedSkImageBuilder(
DCHECK(!metadata.mailbox.IsZero()); DCHECK(!metadata.mailbox.IsZero());
image = skia_renderer->skia_output_surface_->MakePromiseSkImage( image = skia_renderer->skia_output_surface_->MakePromiseSkImage(
std::move(metadata)); std::move(metadata));
DCHECK(image); LOG_IF(ERROR, !image) << "Failed to create the promise sk image.";
} }
sk_image_ = image.get(); sk_image_ = image.get();
} }
...@@ -136,30 +136,35 @@ class SkiaRenderer::ScopedYUVSkImageBuilder { ...@@ -136,30 +136,35 @@ class SkiaRenderer::ScopedYUVSkImageBuilder {
auto yuv_color_space = kRec601_SkYUVColorSpace; auto yuv_color_space = kRec601_SkYUVColorSpace;
quad->video_color_space.ToSkYUVColorSpace(&yuv_color_space); quad->video_color_space.ToSkYUVColorSpace(&yuv_color_space);
const bool is_i420 =
quad->u_plane_resource_id() != quad->v_plane_resource_id();
const bool has_alpha = quad->a_plane_resource_id() != kInvalidResourceId;
const size_t number_of_textures = (is_i420 ? 3 : 2) + (has_alpha ? 1 : 0);
std::vector<ResourceMetadata> metadatas; std::vector<ResourceMetadata> metadatas;
bool is_yuv = quad->u_plane_resource_id() != quad->v_plane_resource_id(); metadatas.reserve(number_of_textures);
metadatas.reserve(is_yuv ? 3 : 2);
auto y_metadata = skia_renderer->lock_set_for_external_use_.LockResource( auto y_metadata = skia_renderer->lock_set_for_external_use_.LockResource(
quad->y_plane_resource_id()); quad->y_plane_resource_id());
metadatas.push_back(std::move(y_metadata)); metadatas.push_back(std::move(y_metadata));
auto u_metadata = skia_renderer->lock_set_for_external_use_.LockResource( auto u_metadata = skia_renderer->lock_set_for_external_use_.LockResource(
quad->u_plane_resource_id()); quad->u_plane_resource_id());
metadatas.push_back(std::move(u_metadata)); metadatas.push_back(std::move(u_metadata));
if (is_yuv) { if (is_i420) {
auto v_metadata = auto v_metadata =
skia_renderer->lock_set_for_external_use_.LockResource( skia_renderer->lock_set_for_external_use_.LockResource(
quad->v_plane_resource_id()); quad->v_plane_resource_id());
metadatas.push_back(std::move(v_metadata)); metadatas.push_back(std::move(v_metadata));
} }
if (quad->a_plane_resource_id() != kInvalidResourceId) { if (has_alpha) {
// TODO(penghuang): Handle alpha channel when Skia supports YUVA format. auto a_metadata =
NOTIMPLEMENTED(); skia_renderer->lock_set_for_external_use_.LockResource(
quad->a_plane_resource_id());
metadatas.push_back(std::move(a_metadata));
} }
image = skia_renderer->skia_output_surface_->MakePromiseSkImageFromYUV( image = skia_renderer->skia_output_surface_->MakePromiseSkImageFromYUV(
std::move(metadatas), yuv_color_space); std::move(metadatas), yuv_color_space, has_alpha);
DCHECK(image); LOG_IF(ERROR, !image) << "Failed to create the promise sk yuva image.";
} }
sk_image_ = image.get(); sk_image_ = image.get();
} }
......
...@@ -26,8 +26,6 @@ class GpuServiceImpl; ...@@ -26,8 +26,6 @@ class GpuServiceImpl;
class SkiaOutputSurfaceImplOnGpu; class SkiaOutputSurfaceImplOnGpu;
class SyntheticBeginFrameSource; class SyntheticBeginFrameSource;
class YUVResourceMetadata;
// The SkiaOutputSurface implementation. It is the output surface for // The SkiaOutputSurface implementation. It is the output surface for
// SkiaRenderer. It lives on the compositor thread, but it will post tasks // SkiaRenderer. It lives on the compositor thread, but it will post tasks
// to the GPU thread for initializing. Currently, SkiaOutputSurfaceImpl // to the GPU thread for initializing. Currently, SkiaOutputSurfaceImpl
...@@ -77,7 +75,8 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurfaceImpl : public SkiaOutputSurface { ...@@ -77,7 +75,8 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurfaceImpl : public SkiaOutputSurface {
sk_sp<SkImage> MakePromiseSkImage(ResourceMetadata metadata) override; sk_sp<SkImage> MakePromiseSkImage(ResourceMetadata metadata) override;
sk_sp<SkImage> MakePromiseSkImageFromYUV( sk_sp<SkImage> MakePromiseSkImageFromYUV(
std::vector<ResourceMetadata> metadatas, std::vector<ResourceMetadata> metadatas,
SkYUVColorSpace yuv_color_space) override; SkYUVColorSpace yuv_color_space,
bool has_alpha) override;
void SkiaSwapBuffers(OutputSurfaceFrame frame) override; void SkiaSwapBuffers(OutputSurfaceFrame frame) override;
SkCanvas* BeginPaintRenderPass(const RenderPassId& id, SkCanvas* BeginPaintRenderPass(const RenderPassId& id,
const gfx::Size& surface_size, const gfx::Size& surface_size,
...@@ -96,6 +95,7 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurfaceImpl : public SkiaOutputSurface { ...@@ -96,6 +95,7 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurfaceImpl : public SkiaOutputSurface {
private: private:
template <class T> template <class T>
class PromiseTextureHelper; class PromiseTextureHelper;
class YUVAPromiseTextureHelper;
void InitializeOnGpuThread(base::WaitableEvent* event); void InitializeOnGpuThread(base::WaitableEvent* event);
void RecreateRecorder(); void RecreateRecorder();
void DidSwapBuffersComplete(gpu::SwapBuffersCompleteParams params, void DidSwapBuffersComplete(gpu::SwapBuffersCompleteParams params,
...@@ -122,12 +122,6 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurfaceImpl : public SkiaOutputSurface { ...@@ -122,12 +122,6 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurfaceImpl : public SkiaOutputSurface {
// Sync tokens for resources which are used for the current frame. // Sync tokens for resources which are used for the current frame.
std::vector<gpu::SyncToken> resource_sync_tokens_; std::vector<gpu::SyncToken> resource_sync_tokens_;
// YUV resource metadatas for the current frame or the current render pass.
// They should be preprocessed for playing recorded frame into a surface.
// TODO(penghuang): Remove it when Skia supports drawing YUV textures
// directly.
std::vector<YUVResourceMetadata*> yuv_resource_metadatas_;
// The task runner for running task on the client (compositor) thread. // The task runner for running task on the client (compositor) thread.
scoped_refptr<base::SingleThreadTaskRunner> client_thread_task_runner_; scoped_refptr<base::SingleThreadTaskRunner> client_thread_task_runner_;
......
...@@ -39,20 +39,6 @@ base::AtomicSequenceNumber g_next_command_buffer_id; ...@@ -39,20 +39,6 @@ base::AtomicSequenceNumber g_next_command_buffer_id;
} // namespace } // namespace
YUVResourceMetadata::YUVResourceMetadata(
std::vector<ResourceMetadata> metadatas,
SkYUVColorSpace yuv_color_space)
: metadatas_(std::move(metadatas)), yuv_color_space_(yuv_color_space) {
DCHECK(metadatas_.size() == 2 || metadatas_.size() == 3);
}
YUVResourceMetadata::YUVResourceMetadata(YUVResourceMetadata&& other) = default;
YUVResourceMetadata::~YUVResourceMetadata() = default;
YUVResourceMetadata& YUVResourceMetadata::operator=(
YUVResourceMetadata&& other) = default;
SkiaOutputSurfaceImplOnGpu::SkiaOutputSurfaceImplOnGpu( SkiaOutputSurfaceImplOnGpu::SkiaOutputSurfaceImplOnGpu(
GpuServiceImpl* gpu_service, GpuServiceImpl* gpu_service,
gpu::SurfaceHandle surface_handle, gpu::SurfaceHandle surface_handle,
...@@ -183,7 +169,6 @@ void SkiaOutputSurfaceImplOnGpu::Reshape( ...@@ -183,7 +169,6 @@ void SkiaOutputSurfaceImplOnGpu::Reshape(
void SkiaOutputSurfaceImplOnGpu::FinishPaintCurrentFrame( void SkiaOutputSurfaceImplOnGpu::FinishPaintCurrentFrame(
std::unique_ptr<SkDeferredDisplayList> ddl, std::unique_ptr<SkDeferredDisplayList> ddl,
std::vector<YUVResourceMetadata*> yuv_resource_metadatas,
uint64_t sync_fence_release) { uint64_t sync_fence_release) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(ddl); DCHECK(ddl);
...@@ -195,7 +180,6 @@ void SkiaOutputSurfaceImplOnGpu::FinishPaintCurrentFrame( ...@@ -195,7 +180,6 @@ void SkiaOutputSurfaceImplOnGpu::FinishPaintCurrentFrame(
// TODO(penghuang): Handle the failure. // TODO(penghuang): Handle the failure.
} }
PreprocessYUVResources(std::move(yuv_resource_metadatas));
sk_surface_->draw(ddl.get()); sk_surface_->draw(ddl.get());
gr_context_->flush(); gr_context_->flush();
sync_point_client_state_->ReleaseFenceSync(sync_fence_release); sync_point_client_state_->ReleaseFenceSync(sync_fence_release);
...@@ -240,7 +224,6 @@ void SkiaOutputSurfaceImplOnGpu::SwapBuffers(OutputSurfaceFrame frame) { ...@@ -240,7 +224,6 @@ void SkiaOutputSurfaceImplOnGpu::SwapBuffers(OutputSurfaceFrame frame) {
void SkiaOutputSurfaceImplOnGpu::FinishPaintRenderPass( void SkiaOutputSurfaceImplOnGpu::FinishPaintRenderPass(
RenderPassId id, RenderPassId id,
std::unique_ptr<SkDeferredDisplayList> ddl, std::unique_ptr<SkDeferredDisplayList> ddl,
std::vector<YUVResourceMetadata*> yuv_resource_metadatas,
uint64_t sync_fence_release) { uint64_t sync_fence_release) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(ddl); DCHECK(ddl);
...@@ -251,8 +234,6 @@ void SkiaOutputSurfaceImplOnGpu::FinishPaintRenderPass( ...@@ -251,8 +234,6 @@ void SkiaOutputSurfaceImplOnGpu::FinishPaintRenderPass(
// TODO(penghuang): Handle the failure. // TODO(penghuang): Handle the failure.
} }
PreprocessYUVResources(std::move(yuv_resource_metadatas));
auto& surface = offscreen_surfaces_[id]; auto& surface = offscreen_surfaces_[id];
SkSurfaceCharacterization characterization; SkSurfaceCharacterization characterization;
// TODO(penghuang): Using characterization != ddl->characterization(), when // TODO(penghuang): Using characterization != ddl->characterization(), when
...@@ -304,7 +285,7 @@ void SkiaOutputSurfaceImplOnGpu::CopyOutput( ...@@ -304,7 +285,7 @@ void SkiaOutputSurfaceImplOnGpu::CopyOutput(
std::make_unique<CopyOutputSkBitmapResult>(copy_rect, bitmap)); std::make_unique<CopyOutputSkBitmapResult>(copy_rect, bitmap));
} }
void SkiaOutputSurfaceImplOnGpu::FullfillPromiseTexture( void SkiaOutputSurfaceImplOnGpu::FulfillPromiseTexture(
const ResourceMetadata& metadata, const ResourceMetadata& metadata,
GrBackendTexture* backend_texture) { GrBackendTexture* backend_texture) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
...@@ -329,18 +310,7 @@ void SkiaOutputSurfaceImplOnGpu::FullfillPromiseTexture( ...@@ -329,18 +310,7 @@ void SkiaOutputSurfaceImplOnGpu::FullfillPromiseTexture(
metadata.mip_mapped, texture_info); metadata.mip_mapped, texture_info);
} }
void SkiaOutputSurfaceImplOnGpu::FullfillPromiseTexture( void SkiaOutputSurfaceImplOnGpu::FulfillPromiseTexture(
const YUVResourceMetadata& yuv_metadata,
GrBackendTexture* backend_texture) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (yuv_metadata.image())
*backend_texture = yuv_metadata.image()->getBackendTexture(true);
DLOG_IF(ERROR, !backend_texture->isValid())
<< "Failed to full fill the promise texture from yuv resources.";
}
void SkiaOutputSurfaceImplOnGpu::FullfillPromiseTexture(
const RenderPassId id, const RenderPassId id,
GrBackendTexture* backend_texture) { GrBackendTexture* backend_texture) {
auto it = offscreen_surfaces_.find(id); auto it = offscreen_surfaces_.find(id);
...@@ -481,55 +451,6 @@ void SkiaOutputSurfaceImplOnGpu::BindOrCopyTextureIfNecessary( ...@@ -481,55 +451,6 @@ void SkiaOutputSurfaceImplOnGpu::BindOrCopyTextureIfNecessary(
} }
} }
void SkiaOutputSurfaceImplOnGpu::PreprocessYUVResources(
std::vector<YUVResourceMetadata*> yuv_resource_metadatas) {
if (gpu_service_->is_using_vulkan()) {
// TODO(https://crbug.com/838899): Use VkImage for video.
// NOTIMPLEMENTED();
return;
}
// Create SkImage for fullfilling YUV promise image, before drawing the ddl.
// TODO(penghuang): Remove the extra step when Skia supports drawing YUV
// textures directly.
auto* mailbox_manager = gpu_service_->mailbox_manager();
for (auto* yuv_metadata : yuv_resource_metadatas) {
const auto& metadatas = yuv_metadata->metadatas();
DCHECK(metadatas.size() == 2 || metadatas.size() == 3);
GrBackendTexture backend_textures[3];
size_t i = 0;
for (const auto& metadata : metadatas) {
auto* texture_base = mailbox_manager->ConsumeTexture(metadata.mailbox);
if (!texture_base)
break;
BindOrCopyTextureIfNecessary(texture_base);
GrGLTextureInfo texture_info;
texture_info.fTarget = texture_base->target();
texture_info.fID = texture_base->service_id();
texture_info.fFormat = *metadata.backend_format.getGLFormat();
backend_textures[i++] =
GrBackendTexture(metadata.size.width(), metadata.size.height(),
GrMipMapped::kNo, texture_info);
}
if (i != metadatas.size())
continue;
sk_sp<SkImage> image;
if (metadatas.size() == 2) {
image = SkImage::MakeFromNV12TexturesCopy(
gr_context_, yuv_metadata->yuv_color_space(), backend_textures,
kTopLeft_GrSurfaceOrigin, nullptr /* image_color_space */);
DCHECK(image);
} else {
image = SkImage::MakeFromYUVTexturesCopy(
gr_context_, yuv_metadata->yuv_color_space(), backend_textures,
kTopLeft_GrSurfaceOrigin, nullptr /* image_color_space */);
DCHECK(image);
}
yuv_metadata->set_image(std::move(image));
}
}
void SkiaOutputSurfaceImplOnGpu::OnSwapBuffers() { void SkiaOutputSurfaceImplOnGpu::OnSwapBuffers() {
uint64_t swap_id = swap_id_++; uint64_t swap_id = swap_id_++;
gfx::Size pixel_size(sk_surface_->width(), sk_surface_->height()); gfx::Size pixel_size(sk_surface_->width(), sk_surface_->height());
......
...@@ -41,36 +41,6 @@ namespace viz { ...@@ -41,36 +41,6 @@ namespace viz {
class GpuServiceImpl; class GpuServiceImpl;
// Metadata for YUV promise SkImage.
class YUVResourceMetadata {
public:
YUVResourceMetadata(std::vector<ResourceMetadata> metadatas,
SkYUVColorSpace yuv_color_space);
YUVResourceMetadata(YUVResourceMetadata&& other);
~YUVResourceMetadata();
YUVResourceMetadata& operator=(YUVResourceMetadata&& other);
const std::vector<ResourceMetadata>& metadatas() const { return metadatas_; }
SkYUVColorSpace yuv_color_space() const { return yuv_color_space_; }
const sk_sp<SkImage> image() const { return image_; }
void set_image(sk_sp<SkImage> image) { image_ = image; }
const gfx::Size size() const { return metadatas_[0].size; }
private:
// Metadatas for YUV planes.
std::vector<ResourceMetadata> metadatas_;
SkYUVColorSpace yuv_color_space_;
// The image copied from YUV textures, it is for fullfilling the promise
// image.
// TODO(penghuang): Remove it when Skia supports drawing YUV textures
// directly.
sk_sp<SkImage> image_;
DISALLOW_COPY_AND_ASSIGN(YUVResourceMetadata);
};
// The SkiaOutputSurface implementation running on the GPU thread. This class // The SkiaOutputSurface implementation running on the GPU thread. This class
// should be created, used and destroyed on the GPU thread. // should be created, used and destroyed on the GPU thread.
class SkiaOutputSurfaceImplOnGpu : public gpu::ImageTransportSurfaceDelegate { class SkiaOutputSurfaceImplOnGpu : public gpu::ImageTransportSurfaceDelegate {
...@@ -104,28 +74,23 @@ class SkiaOutputSurfaceImplOnGpu : public gpu::ImageTransportSurfaceDelegate { ...@@ -104,28 +74,23 @@ class SkiaOutputSurfaceImplOnGpu : public gpu::ImageTransportSurfaceDelegate {
base::WaitableEvent* event); base::WaitableEvent* event);
void FinishPaintCurrentFrame( void FinishPaintCurrentFrame(
std::unique_ptr<SkDeferredDisplayList> ddl, std::unique_ptr<SkDeferredDisplayList> ddl,
std::vector<YUVResourceMetadata*> yuv_resource_metadatas,
uint64_t sync_fence_release); uint64_t sync_fence_release);
void SwapBuffers(OutputSurfaceFrame frame); void SwapBuffers(OutputSurfaceFrame frame);
void FinishPaintRenderPass( void FinishPaintRenderPass(
RenderPassId id, RenderPassId id,
std::unique_ptr<SkDeferredDisplayList> ddl, std::unique_ptr<SkDeferredDisplayList> ddl,
std::vector<YUVResourceMetadata*> yuv_resource_metadatas,
uint64_t sync_fence_release); uint64_t sync_fence_release);
void RemoveRenderPassResource(std::vector<RenderPassId> ids); void RemoveRenderPassResource(std::vector<RenderPassId> ids);
void CopyOutput(RenderPassId id, void CopyOutput(RenderPassId id,
const gfx::Rect& copy_rect, const gfx::Rect& copy_rect,
std::unique_ptr<CopyOutputRequest> request); std::unique_ptr<CopyOutputRequest> request);
// Fullfill callback for promise SkImage created from a resource. // Fulfill callback for promise SkImage created from a resource.
void FullfillPromiseTexture(const ResourceMetadata& metadata, void FulfillPromiseTexture(const ResourceMetadata& metadata,
GrBackendTexture* backend_texture); GrBackendTexture* backend_texture);
// Fullfill callback for promise SkImage created from YUV resources. // Fulfill callback for promise SkImage created from a render pass.
void FullfillPromiseTexture(const YUVResourceMetadata& metadata, void FulfillPromiseTexture(const RenderPassId id,
GrBackendTexture* backend_texture); GrBackendTexture* backend_texture);
// Fullfill callback for promise SkImage created from a render pass.
void FullfillPromiseTexture(const RenderPassId id,
GrBackendTexture* backend_texture);
sk_sp<GrContextThreadSafeProxy> GetGrContextThreadSafeProxy(); sk_sp<GrContextThreadSafeProxy> GetGrContextThreadSafeProxy();
const gl::GLVersionInfo* gl_version_info() const { return gl_version_info_; } const gl::GLVersionInfo* gl_version_info() const { return gl_version_info_; }
...@@ -148,8 +113,6 @@ class SkiaOutputSurfaceImplOnGpu : public gpu::ImageTransportSurfaceDelegate { ...@@ -148,8 +113,6 @@ class SkiaOutputSurfaceImplOnGpu : public gpu::ImageTransportSurfaceDelegate {
void InitializeForVulkan(); void InitializeForVulkan();
void BindOrCopyTextureIfNecessary(gpu::TextureBase* texture_base); void BindOrCopyTextureIfNecessary(gpu::TextureBase* texture_base);
void PreprocessYUVResources(
std::vector<YUVResourceMetadata*> yuv_resource_metadatas);
// Generage the next swap ID and push it to our pending swap ID queues. // Generage the next swap ID and push it to our pending swap ID queues.
void OnSwapBuffers(); void OnSwapBuffers();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment