blob: e676c6989fac1c582c6c2c28c97614cbd199bf66 [file] [log] [blame]
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/viz/service/display_embedder/skia_output_device_offscreen.h"
#include <utility>
#include "third_party/skia/include/core/SkSurface.h"
namespace viz {
SkiaOutputDeviceOffscreen::SkiaOutputDeviceOffscreen(
GrContext* gr_context,
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),
has_alpha_(has_alpha) {
capabilities_.flipped_output_surface = flipped;
capabilities_.supports_post_sub_buffer = true;
}
SkiaOutputDeviceOffscreen::~SkiaOutputDeviceOffscreen() = default;
void SkiaOutputDeviceOffscreen::Reshape(const gfx::Size& size,
float device_scale_factor,
const gfx::ColorSpace& color_space,
bool has_alpha) {
// 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());
draw_surface_ = SkSurface::MakeRenderTarget(
gr_context_, SkBudgeted::kNo, image_info_, 0 /* sampleCount */,
capabilities_.flipped_output_surface ? kTopLeft_GrSurfaceOrigin
: kBottomLeft_GrSurfaceOrigin,
nullptr /* surfaceProps */);
DCHECK(!!draw_surface_);
// Initialize alpha channel to opaque.
if (!has_alpha_) {
auto* canvas = draw_surface_->getCanvas();
canvas->clear(SkColorSetARGB(255, 0, 0, 0));
}
}
gfx::SwapResponse SkiaOutputDeviceOffscreen::PostSubBuffer(
const gfx::Rect& rect,
const GrBackendSemaphore& semaphore,
BufferPresentedCallback feedback) {
return SwapBuffers(semaphore, std::move(feedback));
}
gfx::SwapResponse SkiaOutputDeviceOffscreen::SwapBuffers(
const GrBackendSemaphore& semaphore,
BufferPresentedCallback feedback) {
// Reshape should have been called first.
DCHECK(draw_surface_);
StartSwapBuffers(std::move(feedback));
return FinishSwapBuffers(gfx::SwapResult::SWAP_ACK);
}
void SkiaOutputDeviceOffscreen::EnsureBackbuffer() {
if (!image_info_.isEmpty() && !draw_surface_) {
draw_surface_ = SkSurface::MakeRenderTarget(
gr_context_, SkBudgeted::kNo, image_info_, 0 /* sampleCount */,
capabilities_.flipped_output_surface ? kTopLeft_GrSurfaceOrigin
: kBottomLeft_GrSurfaceOrigin,
nullptr /* surfaceProps */);
}
}
void SkiaOutputDeviceOffscreen::DiscardBackbuffer() {
draw_surface_.reset();
}
} // namespace viz