blob: d4faa9163940a5613c2d669ed9399846a65c4964 [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 "gpu/command_buffer/service/external_vk_image_skia_representation.h"
#include <limits>
#include <utility>
#include "base/trace_event/trace_event.h"
#include "gpu/vulkan/vulkan_fence_helper.h"
#include "gpu/vulkan/vulkan_function_pointers.h"
#include "gpu/vulkan/vulkan_util.h"
#include "third_party/skia/include/core/SkPromiseImageTexture.h"
#include "third_party/skia/include/gpu/GrBackendSemaphore.h"
namespace gpu {
ExternalVkImageSkiaRepresentation::ExternalVkImageSkiaRepresentation(
SharedImageManager* manager,
SharedImageBacking* backing,
MemoryTypeTracker* tracker)
: SharedImageRepresentationSkia(manager, backing, tracker) {
}
ExternalVkImageSkiaRepresentation::~ExternalVkImageSkiaRepresentation() {
DCHECK_EQ(access_mode_, kNone) << "Previoud access hasn't end yet";
DCHECK(end_access_semaphore_ == VK_NULL_HANDLE);
}
sk_sp<SkSurface> ExternalVkImageSkiaRepresentation::BeginWriteAccess(
int final_msaa_count,
const SkSurfaceProps& surface_props,
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores) {
DCHECK_EQ(access_mode_, kNone) << "Previous access hasn't ended yet";
DCHECK(!surface_);
auto promise_texture =
BeginAccess(false /* readonly */, begin_semaphores, end_semaphores);
if (!promise_texture)
return nullptr;
SkColorType sk_color_type = viz::ResourceFormatToClosestSkColorType(
true /* gpu_compositing */, format());
surface_ = SkSurface::MakeFromBackendTextureAsRenderTarget(
backing_impl()->context_state()->gr_context(),
promise_texture->backendTexture(), kTopLeft_GrSurfaceOrigin,
final_msaa_count, sk_color_type,
backing_impl()->color_space().ToSkColorSpace(), &surface_props);
access_mode_ = kWrite;
return surface_;
}
void ExternalVkImageSkiaRepresentation::EndWriteAccess(
sk_sp<SkSurface> surface) {
DCHECK_EQ(access_mode_, kWrite)
<< "EndWriteAccess is called before BeginWriteAccess";
DCHECK(surface_);
surface_ = nullptr;
EndAccess(false /* readonly */);
access_mode_ = kNone;
}
sk_sp<SkPromiseImageTexture> ExternalVkImageSkiaRepresentation::BeginReadAccess(
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores) {
// TODO(penghuang): provide begin and end semaphores.
DCHECK_EQ(access_mode_, kNone) << "Previous access hasn't ended yet";
DCHECK(!surface_);
auto promise_texture =
BeginAccess(true /* readonly */, begin_semaphores, end_semaphores);
if (!promise_texture)
return nullptr;
access_mode_ = kRead;
return promise_texture;
}
void ExternalVkImageSkiaRepresentation::EndReadAccess() {
DCHECK_EQ(access_mode_, kRead)
<< "EndReadAccess is called before BeginReadAccess";
EndAccess(true /* readonly */);
access_mode_ = kNone;
}
sk_sp<SkPromiseImageTexture> ExternalVkImageSkiaRepresentation::BeginAccess(
bool readonly,
std::vector<GrBackendSemaphore>* begin_semaphores,
std::vector<GrBackendSemaphore>* end_semaphores) {
DCHECK_EQ(access_mode_, kNone);
DCHECK(end_access_semaphore_ == VK_NULL_HANDLE);
std::vector<SemaphoreHandle> handles;
if (!backing_impl()->BeginAccess(readonly, &handles, false /* is_gl */))
return nullptr;
for (auto& handle : handles) {
DCHECK(handle.is_valid());
VkSemaphore semaphore = vk_implementation()->ImportSemaphoreHandle(
vk_device(), std::move(handle));
DCHECK(semaphore != VK_NULL_HANDLE);
// The ownership of semaphore is passed to caller.
begin_semaphores->emplace_back();
begin_semaphores->back().initVulkan(semaphore);
}
if (backing_impl()->need_sychronization()) {
// Create an |end_access_semaphore_| which will be signalled by the caller.
end_access_semaphore_ =
vk_implementation()->CreateExternalSemaphore(backing_impl()->device());
DCHECK(end_access_semaphore_ != VK_NULL_HANDLE);
end_semaphores->emplace_back();
end_semaphores->back().initVulkan(end_access_semaphore_);
}
return SkPromiseImageTexture::Make(backing_impl()->backend_texture());
}
void ExternalVkImageSkiaRepresentation::EndAccess(bool readonly) {
DCHECK_NE(access_mode_, kNone);
SemaphoreHandle handle;
if (backing_impl()->need_sychronization()) {
DCHECK(end_access_semaphore_ != VK_NULL_HANDLE);
handle = vk_implementation()->GetSemaphoreHandle(vk_device(),
end_access_semaphore_);
DCHECK(handle.is_valid());
// We're done with the semaphore, enqueue deferred cleanup.
fence_helper()->EnqueueSemaphoreCleanupForSubmittedWork(
end_access_semaphore_);
end_access_semaphore_ = VK_NULL_HANDLE;
} else {
DCHECK(end_access_semaphore_ == VK_NULL_HANDLE);
}
backing_impl()->EndAccess(readonly, std::move(handle), false /* is_gl */);
}
} // namespace gpu