blob: ae345b2e612b0f588099cde3ad9217e691cd2711 [file] [log] [blame]
/*
* Copyright 2019 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/private/chromium/GrVkSecondaryCBDrawContext.h"
#include "include/core/SkImageInfo.h"
#include "include/gpu/GrDirectContext.h"
#include "include/gpu/GrRecordingContext.h"
#include "include/gpu/ganesh/vk/GrVkBackendSurface.h"
#include "include/gpu/vk/GrVkTypes.h"
#include "include/private/chromium/GrDeferredDisplayList.h"
#include "include/private/chromium/GrSurfaceCharacterization.h"
#include "src/core/SkSurfacePriv.h"
#include "src/gpu/ganesh/GrContextThreadSafeProxyPriv.h"
#include "src/gpu/ganesh/GrDirectContextPriv.h"
#include "src/gpu/ganesh/GrProxyProvider.h"
#include "src/gpu/ganesh/GrRecordingContextPriv.h"
#include "src/gpu/ganesh/GrRenderTarget.h"
#include "src/gpu/ganesh/GrRenderTargetProxy.h"
#include "src/gpu/ganesh/GrResourceProvider.h"
#include "src/gpu/ganesh/GrSurfaceProxyView.h"
sk_sp<GrVkSecondaryCBDrawContext> GrVkSecondaryCBDrawContext::Make(GrRecordingContext* rContext,
const SkImageInfo& imageInfo,
const GrVkDrawableInfo& vkInfo,
const SkSurfaceProps* props) {
if (!rContext) {
return nullptr;
}
if (rContext->backend() != GrBackendApi::kVulkan) {
return nullptr;
}
GrProxyProvider* gpp = rContext->priv().proxyProvider();
if (gpp->isAbandoned()) {
return nullptr;
}
GrResourceProvider* resourceProvider = gpp->resourceProvider();
if (!resourceProvider) {
return nullptr;
}
sk_sp<GrRenderTarget> rt = resourceProvider->wrapVulkanSecondaryCBAsRenderTarget(imageInfo,
vkInfo);
if (!rt) {
return nullptr;
}
SkASSERT(!rt->asTexture()); // A GrRenderTarget that's not textureable
SkASSERT(!rt->getUniqueKey().isValid());
// This proxy should be unbudgeted because we're just wrapping an external resource
SkASSERT(GrBudgetedType::kBudgeted != rt->resourcePriv().budgetedType());
GrColorType colorType = SkColorTypeToGrColorType(imageInfo.colorType());
if (!gpp->caps()->isFormatAsColorTypeRenderable(
colorType, GrBackendFormats::MakeVk(vkInfo.fFormat), /*sampleCount=*/1)) {
return nullptr;
}
sk_sp<GrRenderTargetProxy> proxy(
new GrRenderTargetProxy(std::move(rt),
GrSurfaceProxy::UseAllocator::kNo,
GrRenderTargetProxy::WrapsVkSecondaryCB::kYes));
if (!proxy) {
return nullptr;
}
SkASSERT(proxy->isInstantiated());
auto device = rContext->priv().createDevice(SkColorTypeToGrColorType(imageInfo.colorType()),
std::move(proxy),
imageInfo.refColorSpace(),
kTopLeft_GrSurfaceOrigin,
SkSurfacePropsCopyOrDefault(props),
skgpu::ganesh::Device::InitContents::kUninit);
if (!device) {
return nullptr;
}
return sk_sp<GrVkSecondaryCBDrawContext>(new GrVkSecondaryCBDrawContext(std::move(device),
props));
}
GrVkSecondaryCBDrawContext::GrVkSecondaryCBDrawContext(sk_sp<skgpu::ganesh::Device> device,
const SkSurfaceProps* props)
: fDevice(std::move(device)), fProps(SkSurfacePropsCopyOrDefault(props)) {}
GrVkSecondaryCBDrawContext::~GrVkSecondaryCBDrawContext() {
SkASSERT(!fDevice);
SkASSERT(!fCachedCanvas.get());
}
SkCanvas* GrVkSecondaryCBDrawContext::getCanvas() {
if (!fCachedCanvas) {
fCachedCanvas = std::make_unique<SkCanvas>(fDevice);
}
return fCachedCanvas.get();
}
void GrVkSecondaryCBDrawContext::flush() {
auto dContext = GrAsDirectContext(fDevice->recordingContext());
if (dContext) {
dContext->priv().flushSurface(fDevice->targetProxy());
dContext->submit();
}
}
bool GrVkSecondaryCBDrawContext::wait(int numSemaphores,
const GrBackendSemaphore waitSemaphores[],
bool deleteSemaphoresAfterWait) {
return fDevice->wait(numSemaphores, waitSemaphores, deleteSemaphoresAfterWait);
}
void GrVkSecondaryCBDrawContext::releaseResources() {
fCachedCanvas.reset();
fDevice.reset();
}
bool GrVkSecondaryCBDrawContext::characterize(GrSurfaceCharacterization* characterization) const {
auto direct = fDevice->recordingContext()->asDirectContext();
if (!direct) {
return false;
}
SkImageInfo ii = fDevice->imageInfo();
if (ii.colorType() == kUnknown_SkColorType) {
return false;
}
GrSurfaceProxyView readSurfaceView = fDevice->readSurfaceView();
size_t maxResourceBytes = direct->getResourceCacheLimit();
// We current don't support textured GrVkSecondaryCBDrawContexts.
SkASSERT(!readSurfaceView.asTextureProxy());
GrBackendFormat format = readSurfaceView.asRenderTargetProxy()->backendFormat();
int numSamples = readSurfaceView.asRenderTargetProxy()->numSamples();
GrProtected isProtected = readSurfaceView.asRenderTargetProxy()->isProtected();
characterization->set(direct->threadSafeProxy(),
maxResourceBytes,
ii,
format,
readSurfaceView.origin(),
numSamples,
GrSurfaceCharacterization::Textureable(false),
skgpu::Mipmapped::kNo,
GrSurfaceCharacterization::UsesGLFBO0(false),
GrSurfaceCharacterization::VkRTSupportsInputAttachment(false),
GrSurfaceCharacterization::VulkanSecondaryCBCompatible(true),
isProtected,
this->props());
return true;
}
bool GrVkSecondaryCBDrawContext::isCompatible(
const GrSurfaceCharacterization& characterization) const {
auto dContext = fDevice->recordingContext()->asDirectContext();
if (!dContext) {
return false;
}
if (!characterization.isValid()) {
return false;
}
if (!characterization.vulkanSecondaryCBCompatible()) {
return false;
}
if (characterization.isTextureable()) {
// We don't support textureable DDL when rendering to a GrVkSecondaryCBDrawContext.
return false;
}
if (characterization.usesGLFBO0()) {
return false;
}
SkImageInfo ii = fDevice->imageInfo();
if (ii.colorType() == kUnknown_SkColorType) {
return false;
}
GrSurfaceProxyView readSurfaceView = fDevice->readSurfaceView();
// As long as the current state in the context allows for greater or equal resources,
// we allow the DDL to be replayed.
// DDL TODO: should we just remove the resource check and ignore the cache limits on playback?
size_t maxResourceBytes = dContext->getResourceCacheLimit();
GrBackendFormat format = readSurfaceView.asRenderTargetProxy()->backendFormat();
int numSamples = readSurfaceView.asRenderTargetProxy()->numSamples();
GrProtected isProtected = readSurfaceView.asRenderTargetProxy()->isProtected();
return characterization.contextInfo() &&
characterization.contextInfo()->priv().matches(dContext) &&
characterization.cacheMaxResourceBytes() <= maxResourceBytes &&
characterization.origin() == readSurfaceView.origin() &&
characterization.backendFormat() == format &&
characterization.width() == ii.width() &&
characterization.height() == ii.height() &&
characterization.colorType() == ii.colorType() &&
characterization.sampleCount() == numSamples &&
SkColorSpace::Equals(characterization.colorSpace(), ii.colorInfo().colorSpace()) &&
characterization.isProtected() == isProtected &&
characterization.surfaceProps() == fDevice->surfaceProps();
}
#ifndef SK_DDL_IS_UNIQUE_POINTER
bool GrVkSecondaryCBDrawContext::draw(sk_sp<const GrDeferredDisplayList> ddl) {
#else
bool GrVkSecondaryCBDrawContext::draw(const GrDeferredDisplayList* ddl) {
#endif
if (!ddl || !this->isCompatible(ddl->characterization())) {
return false;
}
auto direct = fDevice->recordingContext()->asDirectContext();
if (!direct) {
return false;
}
GrSurfaceProxyView readSurfaceView = fDevice->readSurfaceView();
direct->priv().createDDLTask(std::move(ddl), readSurfaceView.asRenderTargetProxyRef());
return true;
}