Commit 5a2dde3e authored by Peng Huang's avatar Peng Huang Committed by Commit Bot

Support overlays with SkiaOutputDeviceBufferQueue

This CL supports overlays with SkiaOutputDeviceBufferQueue via
GLSurface. However this CL doesn't change the code in
features::IsUsingSkiaRenderer() at [1], so SkiaRenderer is not used with
Android surface control.

[1] https://cs.chromium.org/chromium/src/components/viz/common/features.cc?type=cs&sq=package:chromium&g=0&l=76

TODO:
 * Refactor overlay related code out of GLSurface to a new class. those
   code is not GL related.
 * Use the new class to replace gl_surface_ in SkiaOutputDeviceBufferQueue.
 * Turn on SkiaRenderer with Android surface control.
 * Long term, we plan to use viz::BufferQueue for overlays. We need refactor
   overlay related code from SkiaOutputDevice* to a service side
   BufferQueue on GPU thread.

Bug: 1012401
Change-Id: Ic66072cad8df72a1e4375a895ac4af5fde42a5f0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1949270
Commit-Queue: Peng Huang <penghuang@chromium.org>
Reviewed-by: default avatarVasiliy Telezhnikov <vasilyt@chromium.org>
Cr-Commit-Position: refs/heads/master@{#721491}
parent 7cd7a457
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/core/SkSurfaceProps.h" #include "third_party/skia/include/core/SkSurfaceProps.h"
#include "ui/display/types/display_snapshot.h" #include "ui/display/types/display_snapshot.h"
#include "ui/gfx/geometry/rect_conversions.h"
#include "ui/gl/color_space_utils.h" #include "ui/gl/color_space_utils.h"
#include "ui/gl/gl_fence.h" #include "ui/gl/gl_fence.h"
#include "ui/gl/gl_surface.h" #include "ui/gl/gl_surface.h"
...@@ -165,6 +166,26 @@ SkiaOutputDeviceBufferQueue::Image::CreateFence() { ...@@ -165,6 +166,26 @@ SkiaOutputDeviceBufferQueue::Image::CreateFence() {
return fence_->GetGpuFence(); return fence_->GetGpuFence();
} }
class SkiaOutputDeviceBufferQueue::OverlayData {
public:
OverlayData(
std::unique_ptr<gpu::SharedImageRepresentationGLTexture> representation)
: representation_(std::move(representation)),
scoped_read_access_(representation_.get(),
GL_SHARED_IMAGE_ACCESS_MODE_READ_CHROMIUM) {}
OverlayData(OverlayData&&) = default;
~OverlayData() = default;
OverlayData& operator=(OverlayData&&) = default;
gpu::SharedImageRepresentationGLTexture* representation() {
return representation_.get();
}
private:
std::unique_ptr<gpu::SharedImageRepresentationGLTexture> representation_;
gpu::SharedImageRepresentationGLTexture::ScopedAccess scoped_read_access_;
};
SkiaOutputDeviceBufferQueue::SkiaOutputDeviceBufferQueue( SkiaOutputDeviceBufferQueue::SkiaOutputDeviceBufferQueue(
scoped_refptr<gl::GLSurface> gl_surface, scoped_refptr<gl::GLSurface> gl_surface,
SkiaOutputSurfaceDependency* deps, SkiaOutputSurfaceDependency* deps,
...@@ -197,6 +218,8 @@ SkiaOutputDeviceBufferQueue::SkiaOutputDeviceBufferQueue( ...@@ -197,6 +218,8 @@ SkiaOutputDeviceBufferQueue::SkiaOutputDeviceBufferQueue(
// TODO(vasilyt): Need to figure out why partial swap isn't working // TODO(vasilyt): Need to figure out why partial swap isn't working
capabilities_.supports_post_sub_buffer = false; capabilities_.supports_post_sub_buffer = false;
capabilities_.max_frames_pending = 2; capabilities_.max_frames_pending = 2;
// Set supports_surfaceless to enable overlays.
capabilities_.supports_surfaceless = true;
} }
SkiaOutputDeviceBufferQueue::SkiaOutputDeviceBufferQueue( SkiaOutputDeviceBufferQueue::SkiaOutputDeviceBufferQueue(
...@@ -313,6 +336,43 @@ SkiaOutputDeviceBufferQueue::SubmitOverlayGpuFence() { ...@@ -313,6 +336,43 @@ SkiaOutputDeviceBufferQueue::SubmitOverlayGpuFence() {
return nullptr; return nullptr;
} }
void SkiaOutputDeviceBufferQueue::ScheduleOverlays(
SkiaOutputSurface::OverlayList overlays) {
#if defined(OS_ANDROID)
DCHECK(pending_overlays_.empty());
for (auto& overlay : overlays) {
// TODO(https://crbug.com/1012401): don't depend on GL.
auto shared_image =
shared_image_representation_factory_->ProduceGLTexture(overlay.mailbox);
// When display is re-opened, the first few frames might not have video
// resource ready. Possible investigation crbug.com/1023971.
if (!shared_image) {
LOG(ERROR) << "Invalid mailbox.";
continue;
}
pending_overlays_.emplace_back(std::move(shared_image));
auto* texture = pending_overlays_.back().representation()->GetTexture();
auto* image = texture->GetLevelImage(GL_TEXTURE_2D, 0);
DLOG_IF(ERROR, !image) << "Cannot get GLImage.";
DCHECK(!overlay.gpu_fence_id);
if (image) {
// We still use GL representation, so the BeginAccess() will import
// semaphore associate with the shared image to GL and wait on it.
// So we can create another GLFence, and use it for ScheduleOverlayPlane
// call.
// TODO(https://crbug.com/1012401): don't depend on GL, and use the
// semaphore associated with shared image directly.
auto gl_fence = gl::GLFence::CreateForGpuFence();
gl_surface_->ScheduleOverlayPlane(
overlay.plane_z_order, overlay.transform, image,
ToNearestRect(overlay.display_rect), overlay.uv_rect,
!overlay.is_opaque, gl_fence->GetGpuFence());
}
}
#endif // defined(OS_ANDROID)
}
void SkiaOutputDeviceBufferQueue::SwapBuffers( void SkiaOutputDeviceBufferQueue::SwapBuffers(
BufferPresentedCallback feedback, BufferPresentedCallback feedback,
std::vector<ui::LatencyInfo> latency_info) { std::vector<ui::LatencyInfo> latency_info) {
...@@ -325,14 +385,18 @@ void SkiaOutputDeviceBufferQueue::SwapBuffers( ...@@ -325,14 +385,18 @@ void SkiaOutputDeviceBufferQueue::SwapBuffers(
StartSwapBuffers({}); StartSwapBuffers({});
if (gl_surface_->SupportsAsyncSwap()) { if (gl_surface_->SupportsAsyncSwap()) {
auto callback = base::BindOnce( auto callback =
&SkiaOutputDeviceBufferQueue::DoFinishSwapBuffers, base::BindOnce(&SkiaOutputDeviceBufferQueue::DoFinishSwapBuffers,
weak_ptr_factory_.GetWeakPtr(), image_size_, std::move(latency_info)); weak_ptr_factory_.GetWeakPtr(), image_size_,
std::move(latency_info), std::move(committed_overlays_));
gl_surface_->SwapBuffersAsync(std::move(callback), std::move(feedback)); gl_surface_->SwapBuffersAsync(std::move(callback), std::move(feedback));
} else { } else {
DoFinishSwapBuffers(image_size_, std::move(latency_info), DoFinishSwapBuffers(image_size_, std::move(latency_info),
std::move(committed_overlays_),
gl_surface_->SwapBuffers(std::move(feedback)), nullptr); gl_surface_->SwapBuffers(std::move(feedback)), nullptr);
} }
committed_overlays_.clear();
std::swap(committed_overlays_, pending_overlays_);
} }
void SkiaOutputDeviceBufferQueue::PostSubBuffer( void SkiaOutputDeviceBufferQueue::PostSubBuffer(
...@@ -343,25 +407,29 @@ void SkiaOutputDeviceBufferQueue::PostSubBuffer( ...@@ -343,25 +407,29 @@ void SkiaOutputDeviceBufferQueue::PostSubBuffer(
StartSwapBuffers({}); StartSwapBuffers({});
if (gl_surface_->SupportsAsyncSwap()) { if (gl_surface_->SupportsAsyncSwap()) {
auto callback = base::BindOnce( auto callback =
&SkiaOutputDeviceBufferQueue::DoFinishSwapBuffers, base::BindOnce(&SkiaOutputDeviceBufferQueue::DoFinishSwapBuffers,
weak_ptr_factory_.GetWeakPtr(), image_size_, std::move(latency_info)); weak_ptr_factory_.GetWeakPtr(), image_size_,
std::move(latency_info), std::move(committed_overlays_));
gl_surface_->PostSubBufferAsync(rect.x(), rect.y(), rect.width(), gl_surface_->PostSubBufferAsync(rect.x(), rect.y(), rect.width(),
rect.height(), std::move(callback), rect.height(), std::move(callback),
std::move(feedback)); std::move(feedback));
} else { } else {
DoFinishSwapBuffers( DoFinishSwapBuffers(
image_size_, std::move(latency_info), image_size_, std::move(latency_info), std::move(committed_overlays_),
gl_surface_->PostSubBuffer(rect.x(), rect.y(), rect.width(), gl_surface_->PostSubBuffer(rect.x(), rect.y(), rect.width(),
rect.height(), std::move(feedback)), rect.height(), std::move(feedback)),
nullptr); nullptr);
} }
committed_overlays_ = std::move(pending_overlays_);
pending_overlays_.clear();
} }
void SkiaOutputDeviceBufferQueue::DoFinishSwapBuffers( void SkiaOutputDeviceBufferQueue::DoFinishSwapBuffers(
const gfx::Size& size, const gfx::Size& size,
std::vector<ui::LatencyInfo> latency_info, std::vector<ui::LatencyInfo> latency_info,
std::vector<OverlayData> overlays,
gfx::SwapResult result, gfx::SwapResult result,
std::unique_ptr<gfx::GpuFence> gpu_fence) { std::unique_ptr<gfx::GpuFence> gpu_fence) {
DCHECK(!gpu_fence); DCHECK(!gpu_fence);
......
...@@ -54,12 +54,14 @@ class VIZ_SERVICE_EXPORT SkiaOutputDeviceBufferQueue final ...@@ -54,12 +54,14 @@ class VIZ_SERVICE_EXPORT SkiaOutputDeviceBufferQueue final
gl::GLImage* GetOverlayImage() override; gl::GLImage* GetOverlayImage() override;
// Creates and submits gpu fence // Creates and submits gpu fence
std::unique_ptr<gfx::GpuFence> SubmitOverlayGpuFence() override; std::unique_ptr<gfx::GpuFence> SubmitOverlayGpuFence() override;
void ScheduleOverlays(SkiaOutputSurface::OverlayList overlays) override;
gl::GLSurface* gl_surface() { return gl_surface_.get(); } gl::GLSurface* gl_surface() { return gl_surface_.get(); }
private: private:
friend class SkiaOutputDeviceBufferQueueTest; friend class SkiaOutputDeviceBufferQueueTest;
class Image; class Image;
class OverlayData;
Image* GetCurrentImage(); Image* GetCurrentImage();
std::unique_ptr<Image> GetNextImage(); std::unique_ptr<Image> GetNextImage();
...@@ -69,8 +71,9 @@ class VIZ_SERVICE_EXPORT SkiaOutputDeviceBufferQueue final ...@@ -69,8 +71,9 @@ class VIZ_SERVICE_EXPORT SkiaOutputDeviceBufferQueue final
// operation // operation
void DoFinishSwapBuffers(const gfx::Size& size, void DoFinishSwapBuffers(const gfx::Size& size,
std::vector<ui::LatencyInfo> latency_info, std::vector<ui::LatencyInfo> latency_info,
std::vector<OverlayData> overlays,
gfx::SwapResult result, gfx::SwapResult result,
std::unique_ptr<gfx::GpuFence>); std::unique_ptr<gfx::GpuFence> gpu_fence);
SkiaOutputSurfaceDependency* const dependency_; SkiaOutputSurfaceDependency* const dependency_;
scoped_refptr<gl::GLSurface> gl_surface_; scoped_refptr<gl::GLSurface> gl_surface_;
...@@ -90,6 +93,10 @@ class VIZ_SERVICE_EXPORT SkiaOutputDeviceBufferQueue final ...@@ -90,6 +93,10 @@ class VIZ_SERVICE_EXPORT SkiaOutputDeviceBufferQueue final
// Entries of this deque may be nullptr, if they represent frames that have // Entries of this deque may be nullptr, if they represent frames that have
// been destroyed. // been destroyed.
base::circular_deque<std::unique_ptr<Image>> in_flight_images_; base::circular_deque<std::unique_ptr<Image>> in_flight_images_;
// Scheduled overlays for the next SwapBuffers call.
std::vector<OverlayData> pending_overlays_;
// Committed overlays for the last SwapBuffers call.
std::vector<OverlayData> committed_overlays_;
// Shared Image factories // Shared Image factories
gpu::SharedImageFactory shared_image_factory_; gpu::SharedImageFactory shared_image_factory_;
......
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