Commit bfa9f4dd authored by kylechar's avatar kylechar Committed by Commit Bot

Add support for DC overlays in SkiaRenderer.

This CL enables SkiaRenderer to use Windows DC layer overlays. The
operation is essentially the same as GLRenderer with some minor
differences.

The list of DCLayerOverlay candidates is plumbed to the GPU thread via
ScheduleGpuTask() instead of over command buffer. Also instead of
providing a GL texture ID a gpu::Mailbox is provided.

DCLayerOverlayProcessor::ProcessForUnderlay() is modified to set to
SharedQuadState::are_contents_opaque true for the replacement
SolidColorDrawQuad. SkiaRenderer needs to draw the replacement quad with
SkBlendMode::kSrc but setting the blend mode to kSrc isn't supported by
GLRenderer. SkiaRenderer uses the |are_contents_opaque| to change the
blend mode at draw time while GLRenderer ignores it.

SkiaOutputSurface::SkiaSwapBuffers() is also modified to optionally
return a SyncToken. This SyncToken can be used to return overlay
resources after swap buffers completes on the GPU thread. This should
work for all overlay paths except macOS.

Bug: 1003040
Change-Id: I9ff3ff55cde1aabfae8200fc2dfcc416c15d0005
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1796626Reviewed-by: default avatarweiliangc <weiliangc@chromium.org>
Reviewed-by: default avatarVasiliy Telezhnikov <vasilyt@chromium.org>
Reviewed-by: default avatarSunny Sachanandani <sunnyps@chromium.org>
Commit-Queue: kylechar <kylechar@chromium.org>
Cr-Commit-Position: refs/heads/master@{#697751}
parent a1ac2f02
......@@ -645,11 +645,12 @@ void DCLayerOverlayProcessor::ProcessForUnderlay(
// SrcOver_quad uses opacity of source quad (V_alpha)
// SrcOver_premul uses alpha channel and assumes premultipled alpha
bool is_opaque = false;
if (it->ShouldDrawWithBlending() &&
shared_quad_state->blend_mode == SkBlendMode::kSrcOver) {
SharedQuadState* new_shared_quad_state =
render_pass->shared_quad_state_list.AllocateAndCopyFrom(
shared_quad_state);
if (it->ShouldDrawWithBlending() &&
shared_quad_state->blend_mode == SkBlendMode::kSrcOver) {
new_shared_quad_state->blend_mode = SkBlendMode::kDstOut;
auto* replacement =
......@@ -659,6 +660,11 @@ void DCLayerOverlayProcessor::ProcessForUnderlay(
replacement->SetAll(new_shared_quad_state, rect, rect, needs_blending,
SK_ColorBLACK, true /* force_anti_aliasing_off */);
} else {
// Set |are_contents_opaque| true so SkiaRenderer draws the replacement quad
// with SkBlendMode::kSrc.
new_shared_quad_state->are_contents_opaque = false;
it->shared_quad_state = new_shared_quad_state;
// When the opacity == 1.0, drawing with transparent will be done without
// blending and will have the proper effect of completely clearing the
// layer.
......
......@@ -5,11 +5,14 @@
#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_DC_LAYER_OVERLAY_H_
#define COMPONENTS_VIZ_SERVICE_DISPLAY_DC_LAYER_OVERLAY_H_
#include <vector>
#include "base/containers/flat_map.h"
#include "base/memory/ref_counted.h"
#include "components/viz/common/quads/render_pass.h"
#include "components/viz/service/display/output_surface.h"
#include "components/viz/service/viz_service_export.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "third_party/skia/include/core/SkColor.h"
#include "third_party/skia/include/core/SkMatrix44.h"
#include "ui/gfx/geometry/rect_f.h"
......@@ -42,6 +45,10 @@ class VIZ_SERVICE_EXPORT DCLayerOverlay {
enum : size_t { kNumResources = 2 };
ResourceId resources[kNumResources] = {kInvalidResourceId};
// Mailboxes corresponding to |resources|. This is populated in SkiaRenderer
// for accessing the textures on the GPU thread.
gpu::Mailbox mailbox[kNumResources];
// Stacking order relative to backbuffer which has z-order 0.
int z_order = 1;
......
......@@ -26,6 +26,7 @@ namespace viz {
class ContextLostObserver;
class CopyOutputRequest;
class DCLayerOverlay;
namespace copy_output {
struct RenderPassGeometry;
......@@ -73,8 +74,11 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurface : public OutputSurface,
sk_sp<SkColorSpace> dst_color_space,
bool has_alpha) = 0;
// Swaps the current backbuffer to the screen.
virtual void SkiaSwapBuffers(OutputSurfaceFrame frame) = 0;
// Swaps the current backbuffer to the screen. This method returns a non-empty
// sync token which can be waited on to ensure swap is complete if
// |wants_sync_token| is true.
virtual gpu::SyncToken SkiaSwapBuffers(OutputSurfaceFrame frame,
bool wants_sync_token) = 0;
// TODO(weiliangc): This API should move to OverlayProcessor.
// Schedule |output_surface_plane| as an overlay plane to be displayed.
......@@ -125,6 +129,13 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurface : public OutputSurface,
const gfx::ColorSpace& color_space,
std::unique_ptr<CopyOutputRequest> request) = 0;
// Enables/disables drawing with DC layers. Should be enabled before
// ScheduleDCLayers() will be called.
virtual void SetEnableDCLayers(bool enable) = 0;
// Schedule drawing DC layer overlays at next SkiaSwapBuffers() call.
virtual void ScheduleDCLayers(std::vector<DCLayerOverlay> dc_layers) = 0;
// Add context lost observer.
virtual void AddContextLostObserver(ContextLostObserver* observer) = 0;
......
......@@ -30,12 +30,14 @@
#include "components/viz/common/resources/platform_color.h"
#include "components/viz/common/resources/resource_format_utils.h"
#include "components/viz/common/skia_helper.h"
#include "components/viz/service/display/display_resource_provider.h"
#include "components/viz/service/display/output_surface.h"
#include "components/viz/service/display/output_surface_frame.h"
#include "components/viz/service/display/renderer_utils.h"
#include "components/viz/service/display/resource_fence.h"
#include "components/viz/service/display/skia_output_surface.h"
#include "gpu/command_buffer/client/gles2_interface.h"
#include "gpu/command_buffer/common/sync_token.h"
#include "skia/ext/opacity_filter_canvas.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkColor.h"
......@@ -704,9 +706,13 @@ void SkiaRenderer::FinishDrawingFrame() {
swap_content_bounds_ = current_frame()->root_content_bounds;
// TODO(weiliangc): Remove this once OverlayProcessor schedules overlays.
if (current_frame()->output_surface_plane)
if (current_frame()->output_surface_plane) {
skia_output_surface_->ScheduleOutputSurfaceAsOverlay(
current_frame()->output_surface_plane.value());
}
// Schedule overlay planes to be presented before SwapBuffers().
ScheduleDCLayers();
}
void SkiaRenderer::SwapBuffers(std::vector<ui::LatencyInfo> latency_info) {
......@@ -726,7 +732,10 @@ void SkiaRenderer::SwapBuffers(std::vector<ui::LatencyInfo> latency_info) {
switch (draw_mode_) {
case DrawMode::DDL: {
skia_output_surface_->SkiaSwapBuffers(std::move(output_frame));
gpu::SyncToken sync_token = skia_output_surface_->SkiaSwapBuffers(
std::move(output_frame), has_locked_overlay_resources_);
if (has_locked_overlay_resources_)
lock_set_for_external_use_->UnlockResources(sync_token);
break;
}
case DrawMode::SKPRECORD: {
......@@ -1522,6 +1531,29 @@ void SkiaRenderer::DrawUnsupportedQuad(const DrawQuad* quad,
#endif
}
void SkiaRenderer::ScheduleDCLayers() {
if (current_frame()->dc_layer_overlay_list.empty())
return;
for (auto& dc_layer_overlay : current_frame()->dc_layer_overlay_list) {
for (size_t i = 0; i < DCLayerOverlay::kNumResources; ++i) {
ResourceId resource_id = dc_layer_overlay.resources[i];
if (resource_id == kInvalidResourceId)
break;
// Resources will be unlocked after the next call to SwapBuffers().
auto* image_context =
lock_set_for_external_use_->LockResource(resource_id, true);
dc_layer_overlay.mailbox[i] = image_context->mailbox_holder().mailbox;
}
DCHECK(!dc_layer_overlay.mailbox[0].IsZero());
}
has_locked_overlay_resources_ = true;
skia_output_surface_->ScheduleDCLayers(
std::move(current_frame()->dc_layer_overlay_list));
}
sk_sp<SkColorFilter> SkiaRenderer::GetColorFilter(const gfx::ColorSpace& src,
const gfx::ColorSpace& dst,
float resource_offset,
......@@ -1913,8 +1945,7 @@ void SkiaRenderer::CopyDrawnRenderPass(
}
void SkiaRenderer::SetEnableDCLayers(bool enable) {
// TODO(crbug.com/678800): Part of surport overlay on Windows.
NOTIMPLEMENTED();
skia_output_surface_->SetEnableDCLayers(enable);
}
void SkiaRenderer::DidChangeVisibility() {
......
......@@ -160,6 +160,9 @@ class VIZ_SERVICE_EXPORT SkiaRenderer : public DirectRenderer {
void DrawYUVVideoQuad(const YUVVideoDrawQuad* quad, DrawQuadParams* params);
void DrawUnsupportedQuad(const DrawQuad* quad, DrawQuadParams* params);
// Schedule overlay candidates for presentation at next SwapBuffers().
void ScheduleDCLayers();
const TileDrawQuad* CanPassBeDrawnDirectly(const RenderPass* pass) override;
// Get corresponding GrContext. Returns nullptr when there is no GrContext.
......@@ -253,6 +256,8 @@ class VIZ_SERVICE_EXPORT SkiaRenderer : public DirectRenderer {
base::Optional<DisplayResourceProvider::LockSetForExternalUse>
lock_set_for_external_use_;
bool has_locked_overlay_resources_ = false;
// Specific for SkPRecord.
std::unique_ptr<SkPictureRecorder> root_recorder_;
sk_sp<SkPicture> root_picture_;
......
......@@ -5,6 +5,8 @@ include_rules = [
"+cc/output",
"+cc/resources",
"+cc/scheduler",
"+components/viz/common",
"+components/viz/service/display/dc_layer_overlay.h",
"+components/viz/service/display/external_use_client.h",
"+components/viz/service/display/output_surface_client.h",
"+components/viz/service/display/output_surface_frame.h",
......@@ -15,14 +17,13 @@ include_rules = [
"+components/viz/service/display/shared_bitmap_manager.h",
"+components/viz/service/display/skia_output_surface.h",
"+components/viz/service/display/software_output_device.h",
"+components/viz/common",
"+gpu/config/gpu_feature_info.h",
"+components/viz/service/gl/gpu_service_impl.h",
"+gpu/GLES2",
"+gpu/command_buffer/client",
"+gpu/command_buffer/common",
"+gpu/command_buffer/service",
"+gpu/config",
"+gpu/config/gpu_feature_info.h",
"+gpu/GLES2",
"+gpu/ipc",
"+gpu/skia_bindings",
"+gpu/vulkan",
......
......@@ -6,6 +6,8 @@
#include <utility>
#include "base/logging.h"
#include "components/viz/service/display/dc_layer_overlay.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "ui/gfx/gpu_fence.h"
#include "ui/gfx/presentation_feedback.h"
......@@ -32,6 +34,14 @@ void SkiaOutputDevice::PostSubBuffer(
void SkiaOutputDevice::SetDrawRectangle(const gfx::Rect& draw_rectangle) {}
void SkiaOutputDevice::SetEnableDCLayers(bool enable) {
NOTIMPLEMENTED();
}
void SkiaOutputDevice::ScheduleDCLayers(std::vector<DCLayerOverlay> dc_layers) {
NOTIMPLEMENTED();
}
void SkiaOutputDevice::StartSwapBuffers(
base::Optional<BufferPresentedCallback> feedback) {
DCHECK_LT(static_cast<int>(pending_swaps_.size()),
......
......@@ -5,6 +5,9 @@
#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_DEVICE_H_
#define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_DEVICE_H_
#include <memory>
#include <vector>
#include "base/callback.h"
#include "base/containers/queue.h"
#include "base/macros.h"
......@@ -31,6 +34,7 @@ class GLImage;
}
namespace viz {
class DCLayerOverlay;
class SkiaOutputDevice {
public:
......@@ -87,6 +91,9 @@ class SkiaOutputDevice {
// Set the rectangle that will be drawn into on the surface.
virtual void SetDrawRectangle(const gfx::Rect& draw_rectangle);
virtual void SetEnableDCLayers(bool enable);
virtual void ScheduleDCLayers(std::vector<DCLayerOverlay> dc_layers);
const OutputSurface::Capabilities& capabilities() const {
return capabilities_;
}
......
......@@ -7,35 +7,43 @@
#include <utility>
#include "base/bind_helpers.h"
#include "components/viz/service/display/dc_layer_overlay.h"
#include "gpu/command_buffer/common/swap_buffers_complete_params.h"
#include "gpu/command_buffer/service/feature_info.h"
#include "gpu/command_buffer/service/gl_utils.h"
#include "gpu/command_buffer/service/mailbox_manager.h"
#include "gpu/command_buffer/service/texture_base.h"
#include "gpu/command_buffer/service/texture_manager.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/core/SkSurfaceProps.h"
#include "third_party/skia/include/gpu/GrBackendSurface.h"
#include "third_party/skia/include/gpu/GrContext.h"
#include "third_party/skia/include/gpu/gl/GrGLTypes.h"
#include "ui/gl/color_space_utils.h"
#include "ui/gl/dc_renderer_layer_params.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_surface.h"
#include "ui/gl/gl_version_info.h"
namespace viz {
SkiaOutputDeviceGL::SkiaOutputDeviceGL(
gpu::MailboxManager* mailbox_manager,
scoped_refptr<gl::GLSurface> gl_surface,
scoped_refptr<gpu::gles2::FeatureInfo> feature_info,
const DidSwapBufferCompleteCallback& did_swap_buffer_complete_callback)
: SkiaOutputDevice(false /*need_swap_semaphore */,
did_swap_buffer_complete_callback),
gl_surface_(gl_surface) {
mailbox_manager_(mailbox_manager),
gl_surface_(std::move(gl_surface)) {
capabilities_.flipped_output_surface = gl_surface_->FlipsVertically();
capabilities_.supports_post_sub_buffer = gl_surface_->SupportsPostSubBuffer();
if (feature_info->workarounds()
.disable_post_sub_buffers_for_onscreen_surfaces)
capabilities_.supports_post_sub_buffer = false;
capabilities_.max_frames_pending = gl_surface->GetBufferCount() - 1;
capabilities_.supports_dc_layers = gl_surface->SupportsDCLayers();
capabilities_.max_frames_pending = gl_surface_->GetBufferCount() - 1;
capabilities_.supports_dc_layers = gl_surface_->SupportsDCLayers();
}
void SkiaOutputDeviceGL::Initialize(GrContext* gr_context,
......@@ -154,6 +162,51 @@ void SkiaOutputDeviceGL::SetDrawRectangle(const gfx::Rect& draw_rectangle) {
gl_surface_->SetDrawRectangle(draw_rectangle);
}
void SkiaOutputDeviceGL::SetEnableDCLayers(bool enable) {
gl_surface_->SetEnableDCLayers(enable);
}
void SkiaOutputDeviceGL::ScheduleDCLayers(
std::vector<DCLayerOverlay> dc_layers) {
for (auto& dc_layer : dc_layers) {
ui::DCRendererLayerParams params;
// Get GLImages for DC layer textures.
bool success = true;
for (size_t i = 0; i < DCLayerOverlay::kNumResources; ++i) {
if (i > 0 && dc_layer.mailbox[i].IsZero())
break;
auto image = GetGLImageForMailbox(dc_layer.mailbox[i]);
if (!image) {
success = false;
break;
}
image->SetColorSpace(dc_layer.color_space);
params.images[i] = std::move(image);
}
if (!success) {
DLOG(ERROR) << "Failed to get GLImage for DC layer.";
continue;
}
params.z_order = dc_layer.z_order;
params.content_rect = dc_layer.content_rect;
params.quad_rect = dc_layer.quad_rect;
DCHECK(dc_layer.transform.IsFlat());
params.transform = dc_layer.transform;
params.is_clipped = dc_layer.is_clipped;
params.clip_rect = dc_layer.clip_rect;
params.protected_video_type = dc_layer.protected_video_type;
// Schedule DC layer overlay to be presented at next SwapBuffers().
if (!gl_surface_->ScheduleDCLayer(params))
DLOG(ERROR) << "ScheduleDCLayer failed";
}
}
void SkiaOutputDeviceGL::EnsureBackbuffer() {
gl_surface_->SetBackbufferAllocation(true);
}
......@@ -169,4 +222,24 @@ SkSurface* SkiaOutputDeviceGL::BeginPaint() {
void SkiaOutputDeviceGL::EndPaint(const GrBackendSemaphore& semaphore) {}
scoped_refptr<gl::GLImage> SkiaOutputDeviceGL::GetGLImageForMailbox(
const gpu::Mailbox& mailbox) {
// TODO(crbug.com/1005306): Use SharedImageManager to get textures here once
// all clients are using SharedImageInterface to create textures.
auto* texture_base = mailbox_manager_->ConsumeTexture(mailbox);
if (!texture_base)
return nullptr;
if (texture_base->GetType() == gpu::TextureBase::Type::kPassthrough) {
gpu::gles2::TexturePassthrough* texture =
static_cast<gpu::gles2::TexturePassthrough*>(texture_base);
return texture->GetLevelImage(texture->target(), 0);
} else {
DCHECK_EQ(texture_base->GetType(), gpu::TextureBase::Type::kValidated);
gpu::gles2::Texture* texture =
static_cast<gpu::gles2::Texture*>(texture_base);
return texture->GetLevelImage(texture->target(), 0);
}
}
} // namespace viz
......@@ -6,17 +6,20 @@
#define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_DEVICE_GL_H_
#include <memory>
#include <vector>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "build/build_config.h"
#include "components/viz/service/display_embedder/skia_output_device.h"
#include "gpu/command_buffer/common/mailbox.h"
class GrContext;
namespace gl {
class GLContext;
class GLImage;
class GLSurface;
} // namespace gl
......@@ -25,6 +28,8 @@ class GpuFence;
} // namespace gfx
namespace gpu {
class MailboxManager;
namespace gles2 {
class FeatureInfo;
} // namespace gles2
......@@ -35,6 +40,7 @@ namespace viz {
class SkiaOutputDeviceGL final : public SkiaOutputDevice {
public:
SkiaOutputDeviceGL(
gpu::MailboxManager* mailbox_manager,
scoped_refptr<gl::GLSurface> gl_surface,
scoped_refptr<gpu::gles2::FeatureInfo> feature_info,
const DidSwapBufferCompleteCallback& did_swap_buffer_complete_callback);
......@@ -58,12 +64,18 @@ class SkiaOutputDeviceGL final : public SkiaOutputDevice {
BufferPresentedCallback feedback,
std::vector<ui::LatencyInfo> latency_info) override;
void SetDrawRectangle(const gfx::Rect& draw_rectangle) override;
void SetEnableDCLayers(bool enable) override;
void ScheduleDCLayers(std::vector<DCLayerOverlay> dc_layers) override;
void EnsureBackbuffer() override;
void DiscardBackbuffer() override;
SkSurface* BeginPaint() override;
void EndPaint(const GrBackendSemaphore& semaphore) override;
private:
scoped_refptr<gl::GLImage> GetGLImageForMailbox(const gpu::Mailbox& mailbox);
gpu::MailboxManager* const mailbox_manager_;
scoped_refptr<gl::GLSurface> gl_surface_;
GrContext* gr_context_ = nullptr;
......
......@@ -18,6 +18,7 @@
#include "components/viz/common/frame_sinks/copy_output_request.h"
#include "components/viz/common/frame_sinks/copy_output_util.h"
#include "components/viz/common/resources/resource_format_utils.h"
#include "components/viz/service/display/dc_layer_overlay.h"
#include "components/viz/service/display/output_surface_client.h"
#include "components/viz/service/display/output_surface_frame.h"
#include "components/viz/service/display_embedder/image_context_impl.h"
......@@ -129,6 +130,10 @@ SkiaOutputSurfaceImpl::~SkiaOutputSurfaceImpl() {
task_sequence_ = nullptr;
}
gpu::SurfaceHandle SkiaOutputSurfaceImpl::GetSurfaceHandle() const {
return dependency_->GetSurfaceHandle();
}
void SkiaOutputSurfaceImpl::BindToClient(OutputSurfaceClient* client) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(client);
......@@ -357,21 +362,34 @@ SkiaOutputSurfaceImpl::CreateImageContext(const gpu::MailboxHolder& holder,
std::move(color_space));
}
void SkiaOutputSurfaceImpl::SkiaSwapBuffers(OutputSurfaceFrame frame) {
gpu::SyncToken SkiaOutputSurfaceImpl::SkiaSwapBuffers(OutputSurfaceFrame frame,
bool wants_sync_token) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(!current_paint_);
gpu::SyncToken sync_token;
if (wants_sync_token) {
sync_token = gpu::SyncToken(
gpu::CommandBufferNamespace::VIZ_SKIA_OUTPUT_SURFACE,
impl_on_gpu_->command_buffer_id(), ++sync_fence_release_);
sync_token.SetVerifyFlush();
}
// impl_on_gpu_ is released on the GPU thread by a posted task from
// SkiaOutputSurfaceImpl::dtor. So it is safe to use base::Unretained.
auto callback =
base::BindOnce(&SkiaOutputSurfaceImplOnGpu::SwapBuffers,
base::Unretained(impl_on_gpu_.get()), std::move(frame),
std::move(deferred_framebuffer_draw_closure_));
std::move(deferred_framebuffer_draw_closure_),
sync_token.release_count());
ScheduleGpuTask(std::move(callback), std::move(resource_sync_tokens_));
// Recreate |root_recorder_| after SwapBuffers has been scheduled on GPU
// thread to save some time in BeginPaintCurrentFrame
// TODO(vasilyt): reuse root recorder
RecreateRootRecorder();
return sync_token;
}
void SkiaOutputSurfaceImpl::ScheduleOutputSurfaceAsOverlay(
......@@ -536,6 +554,20 @@ void SkiaOutputSurfaceImpl::CopyOutput(
ScheduleGpuTask(std::move(callback), std::move(resource_sync_tokens_));
}
void SkiaOutputSurfaceImpl::SetEnableDCLayers(bool enable) {
auto task = base::BindOnce(&SkiaOutputSurfaceImplOnGpu::SetEnableDCLayers,
base::Unretained(impl_on_gpu_.get()), enable);
ScheduleGpuTask(std::move(task), {});
}
void SkiaOutputSurfaceImpl::ScheduleDCLayers(
std::vector<DCLayerOverlay> overlays) {
auto task =
base::BindOnce(&SkiaOutputSurfaceImplOnGpu::ScheduleDCLayers,
base::Unretained(impl_on_gpu_.get()), std::move(overlays));
ScheduleGpuTask(std::move(task), {});
}
void SkiaOutputSurfaceImpl::SetCapabilitiesForTesting(
bool flipped_output_surface) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
......
......@@ -57,6 +57,7 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurfaceImpl : public SkiaOutputSurface {
~SkiaOutputSurfaceImpl() override;
// OutputSurface implementation:
gpu::SurfaceHandle GetSurfaceHandle() const override;
void BindToClient(OutputSurfaceClient* client) override;
void BindFramebuffer() override;
void SetDrawRectangle(const gfx::Rect& draw_rectangle) override;
......@@ -89,7 +90,8 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurfaceImpl : public SkiaOutputSurface {
SkYUVColorSpace yuv_color_space,
sk_sp<SkColorSpace> dst_color_space,
bool has_alpha) override;
void SkiaSwapBuffers(OutputSurfaceFrame frame) override;
gpu::SyncToken SkiaSwapBuffers(OutputSurfaceFrame frame,
bool wants_sync_token) override;
void ScheduleOutputSurfaceAsOverlay(
OverlayProcessor::OutputSurfaceOverlayPlane output_surface_plane)
override;
......@@ -109,6 +111,8 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurfaceImpl : public SkiaOutputSurface {
sk_sp<SkColorSpace> color_space) override;
void RemoveRenderPassResource(std::vector<RenderPassId> ids) override;
void SetEnableDCLayers(bool enable) override;
void ScheduleDCLayers(std::vector<DCLayerOverlay> overlays) override;
void CopyOutput(RenderPassId id,
const copy_output::RenderPassGeometry& geometry,
const gfx::ColorSpace& color_space,
......
......@@ -18,6 +18,7 @@
#include "components/viz/common/frame_sinks/copy_output_util.h"
#include "components/viz/common/resources/resource_format_utils.h"
#include "components/viz/common/skia_helper.h"
#include "components/viz/service/display/dc_layer_overlay.h"
#include "components/viz/service/display/gl_renderer_copier.h"
#include "components/viz/service/display/output_surface_frame.h"
#include "components/viz/service/display/texture_deleter.h"
......@@ -802,7 +803,8 @@ void SkiaOutputSurfaceImplOnGpu::ScheduleOutputSurfaceAsOverlay(
void SkiaOutputSurfaceImplOnGpu::SwapBuffers(
OutputSurfaceFrame frame,
base::OnceClosure deferred_framebuffer_draw_closure) {
base::OnceClosure deferred_framebuffer_draw_closure,
uint64_t sync_fence_release) {
TRACE_EVENT0("viz", "SkiaOutputSurfaceImplOnGpu::SwapBuffers");
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
......@@ -813,15 +815,14 @@ void SkiaOutputSurfaceImplOnGpu::SwapBuffers(
if (!MakeCurrent(!dependency_->IsOffscreen() /* need_fbo0 */))
return;
}
DCHECK(scoped_output_device_paint_);
DCHECK(output_device_);
scoped_output_device_paint_.reset();
if (frame.sub_buffer_rect && frame.sub_buffer_rect->IsEmpty()) {
// TODO(https://crbug.com/898680): Maybe do something for overlays here.
// This codepath was added in https://codereview.chromium.org/1489153002
// to support updating overlays without changing the framebuffer contents.
// Call SwapBuffers() to present overlays.
output_device_->SwapBuffers(buffer_presented_callback_,
std::move(frame.latency_info));
} else if (capabilities().supports_post_sub_buffer && frame.sub_buffer_rect) {
if (!capabilities().flipped_output_surface)
frame.sub_buffer_rect->set_y(size_.height() - frame.sub_buffer_rect->y() -
......@@ -834,6 +835,9 @@ void SkiaOutputSurfaceImplOnGpu::SwapBuffers(
std::move(frame.latency_info));
}
if (sync_fence_release)
ReleaseFenceSyncAndPushTextureUpdates(sync_fence_release);
destroy_after_swap_.clear();
}
......@@ -1186,6 +1190,15 @@ void SkiaOutputSurfaceImplOnGpu::ReleaseImageContexts(
// |image_contexts| goes out of scope here.
}
void SkiaOutputSurfaceImplOnGpu::SetEnableDCLayers(bool enable) {
output_device_->SetEnableDCLayers(enable);
}
void SkiaOutputSurfaceImplOnGpu::ScheduleDCLayers(
std::vector<DCLayerOverlay> dc_layers) {
output_device_->ScheduleDCLayers(std::move(dc_layers));
}
void SkiaOutputSurfaceImplOnGpu::SetCapabilitiesForTesting(
const OutputSurface::Capabilities& capabilities) {
MakeCurrent(false /* need_fbo0 */);
......@@ -1254,7 +1267,8 @@ bool SkiaOutputSurfaceImplOnGpu::InitializeForGL() {
} else {
std::unique_ptr<SkiaOutputDeviceGL> onscreen_device =
std::make_unique<SkiaOutputDeviceGL>(
gl_surface_, feature_info_, did_swap_buffer_complete_callback_);
dependency_->GetMailboxManager(), gl_surface_, feature_info_,
did_swap_buffer_complete_callback_);
onscreen_device->Initialize(gr_context(), context);
supports_alpha_ = onscreen_device->supports_alpha();
......
......@@ -21,6 +21,7 @@
#include "components/viz/service/display/output_surface_frame.h"
#include "components/viz/service/display/overlay_processor.h"
#include "components/viz/service/display_embedder/skia_output_device.h"
#include "gpu/command_buffer/common/mailbox.h"
#include "gpu/command_buffer/common/sync_token.h"
#include "gpu/command_buffer/service/shared_context_state.h"
#include "gpu/command_buffer/service/sync_point_manager.h"
......@@ -126,7 +127,8 @@ class SkiaOutputSurfaceImplOnGpu : public gpu::ImageTransportSurfaceDelegate {
void ScheduleOutputSurfaceAsOverlay(
const OverlayProcessor::OutputSurfaceOverlayPlane& output_surface_plane);
void SwapBuffers(OutputSurfaceFrame frame,
base::OnceClosure deferred_framebuffer_draw_closure);
base::OnceClosure deferred_framebuffer_draw_closure,
uint64_t sync_fence_release);
void EnsureBackbuffer() { output_device_->EnsureBackbuffer(); }
void DiscardBackbuffer() { output_device_->DiscardBackbuffer(); }
void FinishPaintRenderPass(RenderPassId id,
......@@ -153,6 +155,8 @@ class SkiaOutputSurfaceImplOnGpu : public gpu::ImageTransportSurfaceDelegate {
void ReleaseImageContexts(
std::vector<std::unique_ptr<ExternalUseClient::ImageContext>>
image_contexts);
void SetEnableDCLayers(bool enable);
void ScheduleDCLayers(std::vector<DCLayerOverlay> dc_layers);
bool was_context_lost() { return context_state_->context_lost(); }
......
......@@ -185,11 +185,13 @@ FakeSkiaOutputSurface::CreateImageContext(const gpu::MailboxHolder& holder,
holder, size, format, std::move(color_space));
}
void FakeSkiaOutputSurface::SkiaSwapBuffers(OutputSurfaceFrame frame) {
gpu::SyncToken FakeSkiaOutputSurface::SkiaSwapBuffers(OutputSurfaceFrame frame,
bool wants_sync_token) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&FakeSkiaOutputSurface::SwapBuffersAck,
weak_ptr_factory_.GetWeakPtr()));
return gpu::SyncToken();
}
SkCanvas* FakeSkiaOutputSurface::BeginPaintRenderPass(
......
......@@ -73,7 +73,8 @@ class FakeSkiaOutputSurface : public SkiaOutputSurface {
SkYUVColorSpace yuv_color_space,
sk_sp<SkColorSpace> dst_color_space,
bool has_alpha) override;
void SkiaSwapBuffers(OutputSurfaceFrame frame) override;
gpu::SyncToken SkiaSwapBuffers(OutputSurfaceFrame frame,
bool wants_sync_token) override;
SkCanvas* BeginPaintRenderPass(const RenderPassId& id,
const gfx::Size& surface_size,
ResourceFormat format,
......@@ -87,8 +88,9 @@ class FakeSkiaOutputSurface : public SkiaOutputSurface {
ResourceFormat format,
bool mipmap,
sk_sp<SkColorSpace> color_space) override;
void RemoveRenderPassResource(std::vector<RenderPassId> ids) override;
void SetEnableDCLayers(bool enable) override {}
void ScheduleDCLayers(std::vector<DCLayerOverlay> overlays) override {}
void CopyOutput(RenderPassId id,
const copy_output::RenderPassGeometry& geometry,
const gfx::ColorSpace& color_space,
......
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