Commit cb024857 authored by Peng Huang's avatar Peng Huang Committed by Commit Bot

SkiaRenderer: support render pass overlay on macOS

This CL implements render pass overlay on macOS. With this
implementation, SkiaRenderer draws render passes with filters with a
DDL recorder canvas, and then stores DDL and related information in
the CALayerOverlay. The SkiaOutputSurfaceImplOnGpu will create overlay
shared images backing base on the DDL, and then replays DDL against the
backing, and then the backings will be presented as overlays.

However this CL doesn't recycle overlay shared images. It always creates
new shared images for each render pass overlay. Shared image backing
recycling will be implemented in follow-up CLs.

Since recycling is not implemented, so the the render pass overlay is
not enabled in this CL.

Bug: 1100728
Change-Id: I8389393a790b9e0fdc0dda69c60afd2566a68dd9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2388885
Commit-Queue: Peng Huang <penghuang@chromium.org>
Reviewed-by: default avatarccameron <ccameron@chromium.org>
Cr-Commit-Position: refs/heads/master@{#804832}
parent b2d65813
......@@ -14,6 +14,7 @@
#include "components/viz/common/quads/tile_draw_quad.h"
#include "components/viz/service/display/display_resource_provider.h"
#include "gpu/GLES2/gl2extchromium.h"
#include "third_party/skia/include/core/SkDeferredDisplayList.h"
namespace viz {
......@@ -296,7 +297,10 @@ CALayerOverlay::CALayerOverlay() : filter(GL_LINEAR) {}
CALayerOverlay::CALayerOverlay(const CALayerOverlay& other) = default;
CALayerOverlay::~CALayerOverlay() {}
CALayerOverlay::~CALayerOverlay() = default;
CALayerOverlay& CALayerOverlay::operator=(const CALayerOverlay& other) =
default;
bool CALayerOverlayProcessor::ProcessForCALayerOverlays(
DisplayResourceProvider* resource_provider,
......
......@@ -9,16 +9,20 @@
#include "base/containers/flat_map.h"
#include "base/memory/ref_counted.h"
#include "base/optional.h"
#include "components/viz/common/quads/aggregated_render_pass.h"
#include "components/viz/common/quads/compositor_render_pass.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 "third_party/skia/include/core/SkRefCnt.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/rrect_f.h"
#include "ui/gl/ca_renderer_layer_params.h"
class SkDeferredDisplayList;
namespace viz {
class AggregatedRenderPassDrawQuad;
class DisplayResourceProvider;
......@@ -54,6 +58,7 @@ class VIZ_SERVICE_EXPORT CALayerOverlay {
CALayerOverlay();
CALayerOverlay(const CALayerOverlay& other);
~CALayerOverlay();
CALayerOverlay& operator=(const CALayerOverlay& other);
// State that is frequently shared between consecutive CALayerOverlays.
scoped_refptr<CALayerOverlaySharedState> shared_state;
......@@ -72,10 +77,14 @@ class VIZ_SERVICE_EXPORT CALayerOverlay {
// The edge anti-aliasing mask property for the CALayer.
unsigned edge_aa_mask = 0;
// The minification and magnification filters for the CALayer.
unsigned filter;
unsigned filter = 0;
// If |rpdq| is present, then the renderer must draw the filter effects and
// copy the result into an IOSurface.
const AggregatedRenderPassDrawQuad* rpdq = nullptr;
// The DDL for generating render pass overlay buffer with SkiaRenderer.
sk_sp<SkDeferredDisplayList> ddl;
// The transform for render pass overlay.
base::Optional<SkMatrix44> transform;
};
typedef std::vector<CALayerOverlay> CALayerOverlayList;
......
......@@ -319,6 +319,11 @@ class VIZ_SERVICE_EXPORT DirectRenderer {
DCHECK(current_frame_valid_);
return &current_frame_;
}
gfx::BufferFormat reshape_buffer_format() const {
DCHECK(reshape_buffer_format_);
return reshape_buffer_format_.value();
}
gfx::ColorSpace reshape_color_space() const { return reshape_color_space_; }
// Return a bool to inform the caller if the delegated ink renderer was
// actually created or not. If the renderer doesn't support drawing delegated
......
......@@ -28,6 +28,10 @@
class SkCanvas;
class SkImage;
#if defined(OS_APPLE)
class SkDeferredDisplayList;
#endif
namespace gfx {
class ColorSpace;
} // namespace gfx
......@@ -166,6 +170,15 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurface : public OutputSurface,
base::OnceClosure callback,
std::vector<gpu::SyncToken> sync_tokens) = 0;
#if defined(OS_APPLE)
virtual SkCanvas* BeginPaintRenderPassOverlay(
const gfx::Size& size,
ResourceFormat format,
bool mipmap,
sk_sp<SkColorSpace> color_space) = 0;
virtual sk_sp<SkDeferredDisplayList> EndPaintRenderPassOverlay() = 0;
#endif
private:
DISALLOW_COPY_AND_ASSIGN(SkiaOutputSurface);
};
......
......@@ -247,6 +247,11 @@ class VIZ_SERVICE_EXPORT SkiaRenderer : public DirectRenderer {
float resource_multiplier = 1.0f);
// Returns the color filter that should be applied to the current canvas.
sk_sp<SkColorFilter> GetContentColorFilter();
#if defined(OS_APPLE)
void PrepareRenderPassOverlay(CALayerOverlay* overlay);
#endif
// A map from RenderPass id to the texture used to draw the RenderPass from.
struct RenderPassBacking {
sk_sp<SkSurface> render_pass_surface;
......
......@@ -393,10 +393,11 @@ std::vector<OutputPresenter::OverlayData> OutputPresenterGL::ScheduleOverlays(
gfx::ToEnclosingRect(overlay.shared_state->clip_rect),
overlay.shared_state->rounded_corner_bounds,
overlay.shared_state->sorting_context_id,
gfx::Transform(overlay.shared_state->transform), gl_image,
overlay.contents_rect, gfx::ToEnclosingRect(overlay.bounds_rect),
overlay.background_color, overlay.edge_aa_mask,
overlay.shared_state->opacity, overlay.filter));
gfx::Transform(overlay.transform ? *overlay.transform
: overlay.shared_state->transform),
gl_image, overlay.contents_rect,
gfx::ToEnclosingRect(overlay.bounds_rect), overlay.background_color,
overlay.edge_aa_mask, overlay.shared_state->opacity, overlay.filter));
#endif
}
#endif // defined(OS_ANDROID) || defined(OS_APPLE) || defined(USE_OZONE)
......
......@@ -76,6 +76,10 @@ SkiaOutputSurfaceImpl::ScopedPaint::ScopedPaint(
SkDeferredDisplayListRecorder* root_recorder)
: recorder_(root_recorder), render_pass_id_(0) {}
SkiaOutputSurfaceImpl::ScopedPaint::ScopedPaint(
SkSurfaceCharacterization characterization)
: ScopedPaint(characterization, AggregatedRenderPassId(0)) {}
SkiaOutputSurfaceImpl::ScopedPaint::ScopedPaint(
SkSurfaceCharacterization characterization,
AggregatedRenderPassId render_pass_id)
......@@ -503,6 +507,38 @@ SkCanvas* SkiaOutputSurfaceImpl::BeginPaintRenderPass(
return current_paint_->recorder()->getCanvas();
}
#if defined(OS_APPLE)
SkCanvas* SkiaOutputSurfaceImpl::BeginPaintRenderPassOverlay(
const gfx::Size& size,
ResourceFormat format,
bool mipmap,
sk_sp<SkColorSpace> color_space) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
// Make sure there is no unsubmitted PaintFrame or PaintRenderPass.
DCHECK(!current_paint_);
DCHECK(resource_sync_tokens_.empty());
SkSurfaceCharacterization characterization = CreateSkSurfaceCharacterization(
size, BufferFormat(format), mipmap, std::move(color_space),
true /* is_root_render_pass */);
if (!characterization.isValid())
return nullptr;
current_paint_.emplace(characterization);
return current_paint_->recorder()->getCanvas();
}
sk_sp<SkDeferredDisplayList>
SkiaOutputSurfaceImpl::EndPaintRenderPassOverlay() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK(current_paint_);
auto ddl = current_paint_->recorder()->detach();
current_paint_.reset();
return ddl;
}
#endif // defined(OS_APPLE)
gpu::SyncToken SkiaOutputSurfaceImpl::SubmitPaint(
base::OnceClosure on_finished) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
......@@ -661,8 +697,10 @@ void SkiaOutputSurfaceImpl::ScheduleOverlays(
std::vector<gpu::SyncToken> sync_tokens) {
auto task =
base::BindOnce(&SkiaOutputSurfaceImplOnGpu::ScheduleOverlays,
base::Unretained(impl_on_gpu_.get()), std::move(overlays));
base::Unretained(impl_on_gpu_.get()), std::move(overlays),
std::move(images_in_current_paint_));
ScheduleGpuTask(std::move(task), std::move(sync_tokens));
images_in_current_paint_.clear();
}
gpu::MemoryTracker* SkiaOutputSurfaceImpl::GetMemoryTracker() {
......
......@@ -131,6 +131,15 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurfaceImpl : public SkiaOutputSurface {
void AddContextLostObserver(ContextLostObserver* observer) override;
void RemoveContextLostObserver(ContextLostObserver* observer) override;
#if defined(OS_APPLE)
SkCanvas* BeginPaintRenderPassOverlay(
const gfx::Size& size,
ResourceFormat format,
bool mipmap,
sk_sp<SkColorSpace> color_space) override;
sk_sp<SkDeferredDisplayList> EndPaintRenderPassOverlay() override;
#endif
// ExternalUseClient implementation:
gpu::SyncToken ReleaseImageContexts(
std::vector<std::unique_ptr<ImageContext>> image_contexts) override;
......@@ -210,6 +219,7 @@ class VIZ_SERVICE_EXPORT SkiaOutputSurfaceImpl : public SkiaOutputSurface {
class ScopedPaint {
public:
explicit ScopedPaint(SkDeferredDisplayListRecorder* root_recorder);
explicit ScopedPaint(SkSurfaceCharacterization characterization);
ScopedPaint(SkSurfaceCharacterization characterization,
AggregatedRenderPassId render_pass_id);
~ScopedPaint();
......
......@@ -953,8 +953,84 @@ void SkiaOutputSurfaceImplOnGpu::ReleaseImageContexts(
}
void SkiaOutputSurfaceImplOnGpu::ScheduleOverlays(
SkiaOutputSurface::OverlayList overlays) {
SkiaOutputSurface::OverlayList overlays,
std::vector<ImageContextImpl*> image_contexts) {
#if defined(OS_APPLE)
std::vector<GrBackendSemaphore> begin_semaphores;
std::vector<GrBackendSemaphore> end_semaphores;
promise_image_access_helper_.BeginAccess(std::move(image_contexts),
&begin_semaphores, &end_semaphores);
// GL is used on MacOS and GL doesn't need semaphores.
DCHECK(begin_semaphores.empty());
DCHECK(end_semaphores.empty());
std::vector<gpu::Mailbox> render_pass_overlay_mailboxes;
for (auto& overlay : overlays) {
if (!overlay.ddl)
continue;
base::Optional<gpu::raster::GrShaderCache::ScopedCacheUse> cache_use;
if (dependency_->GetGrShaderCache()) {
cache_use.emplace(dependency_->GetGrShaderCache(),
gpu::kDisplayCompositorClientId);
}
constexpr auto kOverlayUsage =
gpu::SHARED_IMAGE_USAGE_SCANOUT | gpu::SHARED_IMAGE_USAGE_DISPLAY |
gpu::SHARED_IMAGE_USAGE_GLES2_FRAMEBUFFER_HINT;
const auto& characterization = overlay.ddl->characterization();
ResourceFormat resource_format;
switch (characterization.colorType()) {
case kRGBA_8888_SkColorType:
resource_format = ResourceFormat::RGBA_8888;
break;
case kBGRA_8888_SkColorType:
resource_format = ResourceFormat::BGRA_8888;
break;
case kRGBA_F16_SkColorType:
resource_format = ResourceFormat::RGBA_F16;
break;
default:
resource_format = ResourceFormat::RGBA_8888;
NOTREACHED();
}
// TODO(https://crbug.com/1100728): reuse shared images.
DCHECK(overlay.mailbox.IsZero());
overlay.mailbox = gpu::Mailbox::GenerateForSharedImage();
shared_image_factory_->CreateSharedImage(
overlay.mailbox, resource_format,
gfx::Size(characterization.width(), characterization.height()),
gfx::ColorSpace(*characterization.colorSpace()),
characterization.origin(), characterization.imageInfo().alphaType(),
gpu::kNullSurfaceHandle, kOverlayUsage);
auto representation = shared_image_representation_factory_->ProduceSkia(
overlay.mailbox, context_state_.get());
DCHECK(representation);
auto scoped_access = representation->BeginScopedWriteAccess(
/*final_msaa_count=*/0, characterization.surfaceProps(),
/*begin_semaphores=*/nullptr,
/*end_semaphores=*/nullptr,
gpu::SharedImageRepresentation::AllowUnclearedAccess::kYes);
bool result = scoped_access->surface()->draw(overlay.ddl);
DCHECK(result);
context_state_->gr_context()->flushAndSubmit();
scoped_access.reset();
representation->SetCleared();
render_pass_overlay_mailboxes.push_back(overlay.mailbox);
}
promise_image_access_helper_.EndAccess();
output_device_->ScheduleOverlays(std::move(overlays));
for (const auto& mailbox : render_pass_overlay_mailboxes) {
shared_image_factory_->DestroySharedImage(mailbox);
}
#else
DCHECK(image_contexts.empty());
output_device_->ScheduleOverlays(std::move(overlays));
#endif
}
void SkiaOutputSurfaceImplOnGpu::SetEnableDCLayers(bool enable) {
......
......@@ -168,7 +168,8 @@ class SkiaOutputSurfaceImplOnGpu
std::vector<std::unique_ptr<ExternalUseClient::ImageContext>>
image_contexts,
uint64_t sync_fence_release);
void ScheduleOverlays(SkiaOutputSurface::OverlayList overlays);
void ScheduleOverlays(SkiaOutputSurface::OverlayList overlays,
std::vector<ImageContextImpl*> image_contexts);
void SetEnableDCLayers(bool enable);
void SetGpuVSyncEnabled(bool enabled);
......
......@@ -316,6 +316,23 @@ void FakeSkiaOutputSurface::RemoveContextLostObserver(
NOTIMPLEMENTED();
}
#if defined(OS_APPLE)
SkCanvas* FakeSkiaOutputSurface::BeginPaintRenderPassOverlay(
const gfx::Size& size,
ResourceFormat format,
bool mipmap,
sk_sp<SkColorSpace> color_space) {
NOTIMPLEMENTED();
return nullptr;
}
sk_sp<SkDeferredDisplayList>
FakeSkiaOutputSurface::EndPaintRenderPassOverlay() {
NOTIMPLEMENTED();
return nullptr;
}
#endif
void FakeSkiaOutputSurface::SetOutOfOrderCallbacks(
bool out_of_order_callbacks) {
TestContextSupport* support =
......
......@@ -19,6 +19,7 @@
#include "components/viz/service/display/skia_output_surface.h"
#include "components/viz/test/test_context_provider.h"
#include "gpu/command_buffer/common/sync_token.h"
#include "third_party/skia/include/core/SkDeferredDisplayList.h"
namespace viz {
......@@ -99,6 +100,14 @@ class FakeSkiaOutputSurface : public SkiaOutputSurface {
std::unique_ptr<CopyOutputRequest> request) override;
void AddContextLostObserver(ContextLostObserver* observer) override;
void RemoveContextLostObserver(ContextLostObserver* observer) override;
#if defined(OS_APPLE)
SkCanvas* BeginPaintRenderPassOverlay(
const gfx::Size& size,
ResourceFormat format,
bool mipmap,
sk_sp<SkColorSpace> color_space) override;
sk_sp<SkDeferredDisplayList> EndPaintRenderPassOverlay() override;
#endif
// ExternalUseClient implementation:
gpu::SyncToken ReleaseImageContexts(
......
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