Commit 5f529dbc authored by Jonathan Backer's avatar Jonathan Backer Committed by Commit Bot

Use Skia API to manually manage backbuffer memory

This is a clean up task similar to what we did for WrappedSkImage
(https://chromium-review.googlesource.com/c/chromium/src/+/1651916):
rather than keep an SkSurface around indefinitely to keep a ref on a
GrBackendTexture, we explicitly allocate and destroy a GrBackendTexture
and create an SkSurface on demand to mutate the GrBackendTexture.

Bug: 974870
Change-Id: I0a8be55500e51d1c84312580e8b9410933dea6ea
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1742286Reviewed-by: default avatarSean Gilhuly <sgilhuly@chromium.org>
Commit-Queue: Jonathan Backer <backer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#685194}
parent 3337bebe
......@@ -6,24 +6,35 @@
#include <utility>
#include "gpu/command_buffer/service/skia_utils.h"
#include "third_party/skia/include/core/SkSurface.h"
namespace viz {
namespace {
// Some Vulkan drivers do not support kRGB_888x_SkColorType. Always use
// kRGBA_8888_SkColorType instead and initialize surface to opaque as necessary.
constexpr SkColorType kSurfaceColorType = kRGBA_8888_SkColorType;
} // namespace
SkiaOutputDeviceOffscreen::SkiaOutputDeviceOffscreen(
GrContext* gr_context,
scoped_refptr<gpu::SharedContextState> context_state,
bool flipped,
bool has_alpha,
DidSwapBufferCompleteCallback did_swap_buffer_complete_callback)
: SkiaOutputDevice(false /*need_swap_semaphore */,
did_swap_buffer_complete_callback),
gr_context_(gr_context),
context_state_(context_state),
has_alpha_(has_alpha) {
capabilities_.flipped_output_surface = flipped;
capabilities_.supports_post_sub_buffer = true;
}
SkiaOutputDeviceOffscreen::~SkiaOutputDeviceOffscreen() = default;
SkiaOutputDeviceOffscreen::~SkiaOutputDeviceOffscreen() {
DiscardBackbuffer();
}
void SkiaOutputDeviceOffscreen::Reshape(const gfx::Size& size,
float device_scale_factor,
......@@ -32,36 +43,21 @@ void SkiaOutputDeviceOffscreen::Reshape(const gfx::Size& size,
gfx::OverlayTransform transform) {
DCHECK_EQ(transform, gfx::OVERLAY_TRANSFORM_NONE);
// Some Vulkan drivers do not support kRGB_888x_SkColorType. Always use
// kRGBA_8888_SkColorType instead and initialize surface to opaque alpha.
image_info_ =
SkImageInfo::Make(size.width(), size.height(), kRGBA_8888_SkColorType,
has_alpha_ ? kPremul_SkAlphaType : kOpaque_SkAlphaType,
color_space.ToSkColorSpace());
sk_surface_ = SkSurface::MakeRenderTarget(
gr_context_, SkBudgeted::kNo, image_info_, 0 /* sampleCount */,
capabilities_.flipped_output_surface ? kTopLeft_GrSurfaceOrigin
: kBottomLeft_GrSurfaceOrigin,
nullptr /* surfaceProps */);
DCHECK(!!sk_surface_);
if (!has_alpha_) {
is_emulated_rgbx_ = true;
// Initialize alpha channel to opaque.
auto* canvas = sk_surface_->getCanvas();
canvas->clear(SkColorSetARGB(255, 0, 0, 0));
}
DiscardBackbuffer();
size_ = size;
sk_color_space_ = color_space.ToSkColorSpace();
EnsureBackbuffer();
}
void SkiaOutputDeviceOffscreen::SwapBuffers(
BufferPresentedCallback feedback,
std::vector<ui::LatencyInfo> latency_info) {
// Reshape should have been called first.
DCHECK(sk_surface_);
DCHECK(backend_texture_.isValid());
StartSwapBuffers(std::move(feedback));
FinishSwapBuffers(gfx::SwapResult::SWAP_ACK,
gfx::Size(sk_surface_->width(), sk_surface_->height()),
gfx::Size(size_.width(), size_.height()),
std::move(latency_info));
}
......@@ -73,23 +69,44 @@ void SkiaOutputDeviceOffscreen::PostSubBuffer(
}
void SkiaOutputDeviceOffscreen::EnsureBackbuffer() {
if (!image_info_.isEmpty() && !sk_surface_) {
sk_surface_ = SkSurface::MakeRenderTarget(
gr_context_, SkBudgeted::kNo, image_info_, 0 /* sampleCount */,
capabilities_.flipped_output_surface ? kTopLeft_GrSurfaceOrigin
: kBottomLeft_GrSurfaceOrigin,
nullptr /* surfaceProps */);
// Ignore EnsureBackbuffer if Reshape has not been called yet.
if (size_.IsEmpty())
return;
if (has_alpha_) {
backend_texture_ = context_state_->gr_context()->createBackendTexture(
size_.width(), size_.height(), kSurfaceColorType, GrMipMapped::kNo,
GrRenderable::kYes);
} else {
is_emulated_rgbx_ = true;
// Initialize alpha channel to opaque.
backend_texture_ = context_state_->gr_context()->createBackendTexture(
size_.width(), size_.height(), kSurfaceColorType, SkColors::kBlack,
GrMipMapped::kNo, GrRenderable::kYes);
}
DCHECK(backend_texture_.isValid());
}
void SkiaOutputDeviceOffscreen::DiscardBackbuffer() {
sk_surface_.reset();
if (backend_texture_.isValid()) {
DeleteGrBackendTexture(context_state_.get(), &backend_texture_);
backend_texture_ = GrBackendTexture();
}
}
SkSurface* SkiaOutputDeviceOffscreen::BeginPaint() {
DCHECK(backend_texture_.isValid());
sk_surface_ = SkSurface::MakeFromBackendTexture(
context_state_->gr_context(), backend_texture_,
capabilities_.flipped_output_surface ? kTopLeft_GrSurfaceOrigin
: kBottomLeft_GrSurfaceOrigin,
0 /* sampleCount */, kSurfaceColorType, sk_color_space_,
nullptr /* surfaceProps */);
return sk_surface_.get();
}
void SkiaOutputDeviceOffscreen::EndPaint(const GrBackendSemaphore& semaphore) {}
void SkiaOutputDeviceOffscreen::EndPaint(const GrBackendSemaphore& semaphore) {
sk_surface_.reset();
}
} // namespace viz
......@@ -5,18 +5,20 @@
#ifndef COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_DEVICE_OFFSCREEN_H_
#define COMPONENTS_VIZ_SERVICE_DISPLAY_EMBEDDER_SKIA_OUTPUT_DEVICE_OFFSCREEN_H_
#include <vector>
#include "base/macros.h"
#include "components/viz/service/display_embedder/skia_output_device.h"
#include "gpu/command_buffer/service/shared_context_state.h"
#include "third_party/skia/include/core/SkColorSpace.h"
#include "third_party/skia/include/core/SkImageInfo.h"
class GrContext;
namespace viz {
class SkiaOutputDeviceOffscreen : public SkiaOutputDevice {
public:
SkiaOutputDeviceOffscreen(
GrContext* gr_context,
scoped_refptr<gpu::SharedContextState> context_state,
bool flipped,
bool has_alpha,
DidSwapBufferCompleteCallback did_swap_buffer_complete_callback);
......@@ -39,13 +41,15 @@ class SkiaOutputDeviceOffscreen : public SkiaOutputDevice {
void EndPaint(const GrBackendSemaphore& semaphore) override;
protected:
GrContext* const gr_context_;
scoped_refptr<gpu::SharedContextState> context_state_;
const bool has_alpha_;
sk_sp<SkSurface> sk_surface_;
GrBackendTexture backend_texture_;
bool supports_rgbx_ = true;
private:
SkImageInfo image_info_;
gfx::Size size_;
sk_sp<SkColorSpace> sk_color_space_;
DISALLOW_COPY_AND_ASSIGN(SkiaOutputDeviceOffscreen);
};
......
......@@ -16,10 +16,10 @@
namespace viz {
SkiaOutputDeviceX11::SkiaOutputDeviceX11(
GrContext* gr_context,
scoped_refptr<gpu::SharedContextState> context_state,
gfx::AcceleratedWidget widget,
DidSwapBufferCompleteCallback did_swap_buffer_complete_callback)
: SkiaOutputDeviceOffscreen(gr_context,
: SkiaOutputDeviceOffscreen(context_state,
true /* flipped */,
true /* has_alpha */,
did_swap_buffer_complete_callback),
......
......@@ -18,7 +18,7 @@ namespace viz {
class SkiaOutputDeviceX11 final : public SkiaOutputDeviceOffscreen {
public:
SkiaOutputDeviceX11(
GrContext* gr_context,
scoped_refptr<gpu::SharedContextState> context_state,
gfx::AcceleratedWidget widget,
DidSwapBufferCompleteCallback did_swap_buffer_complete_callback);
~SkiaOutputDeviceX11() override;
......
......@@ -1144,7 +1144,7 @@ void SkiaOutputSurfaceImplOnGpu::SetCapabilitiesForTesting(
// Check that we're using an offscreen surface.
DCHECK(dependency_->IsOffscreen());
output_device_ = std::make_unique<SkiaOutputDeviceOffscreen>(
gr_context(), capabilities.flipped_output_surface,
context_state_, capabilities.flipped_output_surface,
renderer_settings_.requires_alpha_channel,
did_swap_buffer_complete_callback_);
}
......@@ -1185,7 +1185,7 @@ bool SkiaOutputSurfaceImplOnGpu::InitializeForGL() {
return false;
output_device_ = std::make_unique<SkiaOutputDeviceOffscreen>(
gr_context(), true /* flipped */,
context_state_, true /* flipped */,
renderer_settings_.requires_alpha_channel,
did_swap_buffer_complete_callback_);
supports_alpha_ = renderer_settings_.requires_alpha_channel;
......@@ -1229,7 +1229,7 @@ bool SkiaOutputSurfaceImplOnGpu::InitializeForVulkan() {
#if BUILDFLAG(ENABLE_VULKAN)
if (dependency_->IsOffscreen()) {
output_device_ = std::make_unique<SkiaOutputDeviceOffscreen>(
gr_context(), false /* flipped */,
context_state_, false /* flipped */,
renderer_settings_.requires_alpha_channel,
did_swap_buffer_complete_callback_);
supports_alpha_ = renderer_settings_.requires_alpha_channel;
......@@ -1238,7 +1238,7 @@ bool SkiaOutputSurfaceImplOnGpu::InitializeForVulkan() {
supports_alpha_ = true;
if (gpu_preferences_.disable_vulkan_surface) {
output_device_ = std::make_unique<SkiaOutputDeviceX11>(
gr_context(), dependency_->GetSurfaceHandle(),
context_state_, dependency_->GetSurfaceHandle(),
did_swap_buffer_complete_callback_);
} else {
output_device_ = std::make_unique<SkiaOutputDeviceVulkan>(
......
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