blob: 2283a7f38ed957e77c66d2d6cc928936926f99cd [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.
*/
// This is a Vulkan protected memory specific test.
#include "include/core/SkTypes.h"
#if SK_SUPPORT_GPU && defined(SK_VULKAN)
#include "include/core/SkCanvas.h"
#include "include/core/SkMaskFilter.h"
#include "include/core/SkPaint.h"
#include "include/core/SkSurface.h"
#include "include/gpu/GrBackendSurface.h"
#include "include/gpu/vk/GrVkBackendContext.h"
#include "include/gpu/vk/GrVkExtensions.h"
#include "tests/Test.h"
#include "tools/gpu/GrContextFactory.h"
#include "tools/gpu/vk/VkTestUtils.h"
namespace {
#define DECLARE_VK_PROC(name) PFN_vk##name fVk##name
#define ACQUIRE_INST_VK_PROC(name) \
fVk##name = reinterpret_cast<PFN_vk##name>(getProc("vk" #name, fBackendContext.fInstance,\
VK_NULL_HANDLE)); \
if (fVk##name == nullptr) { \
ERRORF(reporter, "Function ptr for vk%s could not be acquired\n", #name); \
return false; \
}
#define ACQUIRE_DEVICE_VK_PROC(name) \
fVk##name = reinterpret_cast<PFN_vk##name>(getProc("vk" #name, VK_NULL_HANDLE, fDevice)); \
if (fVk##name == nullptr) { \
ERRORF(reporter, "Function ptr for vk%s could not be acquired\n", #name); \
return false; \
}
class VulkanTestHelper {
public:
VulkanTestHelper(bool isProtected) : fIsProtected(isProtected) {}
~VulkanTestHelper() {
cleanup();
}
bool init(skiatest::Reporter* reporter);
GrContext* grContext() { return fGrContext.get(); }
sk_sp<SkSurface> createSkSurface(skiatest::Reporter* reporter);
private:
void cleanup();
DECLARE_VK_PROC(DestroyInstance);
DECLARE_VK_PROC(DeviceWaitIdle);
DECLARE_VK_PROC(DestroyDevice);
bool fIsProtected = false;
VkDevice fDevice = VK_NULL_HANDLE;
GrVkExtensions* fExtensions = nullptr;
VkPhysicalDeviceFeatures2* fFeatures = nullptr;
VkDebugReportCallbackEXT fDebugCallback = VK_NULL_HANDLE;
PFN_vkDestroyDebugReportCallbackEXT fDestroyDebugCallback = nullptr;
GrVkBackendContext fBackendContext;
sk_sp<GrContext> fGrContext;
};
} // namespace
bool VulkanTestHelper::init(skiatest::Reporter* reporter) {
PFN_vkGetInstanceProcAddr instProc;
PFN_vkGetDeviceProcAddr devProc;
if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc, &devProc)) {
return false;
}
auto getProc = [&instProc, &devProc](const char* proc_name,
VkInstance instance, VkDevice device) {
if (device != VK_NULL_HANDLE) {
return devProc(device, proc_name);
}
return instProc(instance, proc_name);
};
fExtensions = new GrVkExtensions();
fFeatures = new VkPhysicalDeviceFeatures2;
memset(fFeatures, 0, sizeof(VkPhysicalDeviceFeatures2));
fFeatures->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
fFeatures->pNext = nullptr;
fBackendContext.fInstance = VK_NULL_HANDLE;
fBackendContext.fDevice = VK_NULL_HANDLE;
if (!sk_gpu_test::CreateVkBackendContext(getProc, &fBackendContext, fExtensions,
fFeatures, &fDebugCallback, nullptr,
sk_gpu_test::CanPresentFn(), fIsProtected)) {
return false;
}
fDevice = fBackendContext.fDevice;
if (fDebugCallback != VK_NULL_HANDLE) {
fDestroyDebugCallback = (PFN_vkDestroyDebugReportCallbackEXT) instProc(
fBackendContext.fInstance, "vkDestroyDebugReportCallbackEXT");
}
ACQUIRE_INST_VK_PROC(DestroyInstance)
ACQUIRE_INST_VK_PROC(DeviceWaitIdle)
ACQUIRE_INST_VK_PROC(DestroyDevice)
fGrContext = GrContext::MakeVulkan(fBackendContext);
if (!fGrContext) {
return false;
}
return true;
}
void VulkanTestHelper::cleanup() {
fGrContext.reset();
fBackendContext.fMemoryAllocator.reset();
if (fDevice != VK_NULL_HANDLE) {
fVkDeviceWaitIdle(fDevice);
fVkDestroyDevice(fDevice, nullptr);
fDevice = VK_NULL_HANDLE;
}
if (fDebugCallback != VK_NULL_HANDLE) {
fDestroyDebugCallback(fBackendContext.fInstance, fDebugCallback, nullptr);
}
if (fBackendContext.fInstance != VK_NULL_HANDLE) {
fVkDestroyInstance(fBackendContext.fInstance, nullptr);
fBackendContext.fInstance = VK_NULL_HANDLE;
}
delete fExtensions;
sk_gpu_test::FreeVulkanFeaturesStructs(fFeatures);
delete fFeatures;
}
sk_sp<SkSurface> VulkanTestHelper::createSkSurface(skiatest::Reporter* reporter) {
const int kW = 8;
const int kH = 8;
GrBackendTexture backendTex = grContext()->createBackendTexture(
kW, kH, kRGBA_8888_SkColorType, GrMipMapped::kNo, GrRenderable::kNo,
fIsProtected ? GrProtected::kYes : GrProtected::kNo);
REPORTER_ASSERT(reporter, backendTex.isValid());
REPORTER_ASSERT(reporter, backendTex.isProtected() == fIsProtected);
SkSurfaceProps surfaceProps =
SkSurfaceProps(0, SkSurfaceProps::kLegacyFontHost_InitType);
sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTextureAsRenderTarget(
grContext(), backendTex, kTopLeft_GrSurfaceOrigin, 1,
kRGBA_8888_SkColorType, nullptr, &surfaceProps);
REPORTER_ASSERT(reporter, surface);
return surface;
}
DEF_GPUTEST(VkProtectedContext_CreateNonprotectedContext, reporter, options) {
auto nonprotectedTestHelper = std::make_unique<VulkanTestHelper>(false);
REPORTER_ASSERT(reporter, nonprotectedTestHelper->init(reporter));
}
DEF_GPUTEST(VkProtectedContext_CreateProtectedContext, reporter, options) {
auto protectedTestHelper = std::make_unique<VulkanTestHelper>(true);
if (!protectedTestHelper->init(reporter)) {
return;
}
}
DEF_GPUTEST(VkProtectedContext_CreateProtectedSkSurface, reporter, options) {
auto protectedTestHelper = std::make_unique<VulkanTestHelper>(true);
if (!protectedTestHelper->init(reporter)) {
return;
}
REPORTER_ASSERT(reporter, protectedTestHelper->grContext() != nullptr);
const int kW = 8;
const int kH = 8;
GrBackendTexture backendTex =
protectedTestHelper->grContext()->createBackendTexture(
kW, kH, kRGBA_8888_SkColorType, GrMipMapped::kNo, GrRenderable::kNo,
GrProtected::kYes);
REPORTER_ASSERT(reporter, backendTex.isValid());
REPORTER_ASSERT(reporter, backendTex.isProtected());
SkSurfaceProps surfaceProps =
SkSurfaceProps(0, SkSurfaceProps::kLegacyFontHost_InitType);
sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTextureAsRenderTarget(
protectedTestHelper->grContext(), backendTex, kTopLeft_GrSurfaceOrigin, 1,
kRGBA_8888_SkColorType, nullptr, &surfaceProps);
REPORTER_ASSERT(reporter, surface);
protectedTestHelper->grContext()->deleteBackendTexture(backendTex);
}
DEF_GPUTEST(VkProtectedContext_CreateNonprotectedTextureInProtectedContext, reporter, options) {
auto protectedTestHelper = std::make_unique<VulkanTestHelper>(true);
if (!protectedTestHelper->init(reporter)) {
return;
}
REPORTER_ASSERT(reporter, protectedTestHelper->grContext() != nullptr);
const int kW = 8;
const int kH = 8;
GrBackendTexture backendTex =
protectedTestHelper->grContext()->createBackendTexture(
kW, kH, kRGBA_8888_SkColorType, GrMipMapped::kNo, GrRenderable::kNo,
GrProtected::kNo);
REPORTER_ASSERT(reporter, !backendTex.isValid());
}
DEF_GPUTEST(VkProtectedContext_CreateProtectedTextureInNonprotectedContext, reporter, options) {
auto protectedTestHelper = std::make_unique<VulkanTestHelper>(false);
if (!protectedTestHelper->init(reporter)) {
return;
}
REPORTER_ASSERT(reporter, protectedTestHelper->grContext() != nullptr);
const int kW = 8;
const int kH = 8;
GrBackendTexture backendTex =
protectedTestHelper->grContext()->createBackendTexture(
kW, kH, kRGBA_8888_SkColorType, GrMipMapped::kNo, GrRenderable::kNo,
GrProtected::kYes);
REPORTER_ASSERT(reporter, !backendTex.isValid());
}
DEF_GPUTEST(VkProtectedContext_ReadFromProtectedSurface, reporter, options) {
auto protectedTestHelper = std::make_unique<VulkanTestHelper>(true);
if (!protectedTestHelper->init(reporter)) {
return;
}
REPORTER_ASSERT(reporter, protectedTestHelper->grContext() != nullptr);
auto surface = protectedTestHelper->createSkSurface(reporter);
REPORTER_ASSERT(reporter, surface);
REPORTER_ASSERT(reporter,
!surface->readPixels(SkImageInfo(), nullptr, 8, 0, 0));
protectedTestHelper->grContext()->deleteBackendTexture(
surface->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess));
}
namespace {
struct AsyncContext {
bool fCalled = false;
std::unique_ptr<const SkSurface::AsyncReadResult> fResult;
};
static void async_callback(void* c, std::unique_ptr<const SkSurface::AsyncReadResult> result) {
auto context = static_cast<AsyncContext*>(c);
context->fResult = std::move(result);
context->fCalled = true;
};
} // anonymous namespace
DEF_GPUTEST(VkProtectedContext_AsyncReadFromProtectedSurface, reporter, options) {
auto protectedTestHelper = std::make_unique<VulkanTestHelper>(true);
if (!protectedTestHelper->init(reporter)) {
return;
}
REPORTER_ASSERT(reporter, protectedTestHelper->grContext() != nullptr);
auto surface = protectedTestHelper->createSkSurface(reporter);
REPORTER_ASSERT(reporter, surface);
AsyncContext cbContext;
const auto image_info = SkImageInfo::Make(10, 10, kRGBA_8888_SkColorType, kPremul_SkAlphaType,
SkColorSpace::MakeSRGB());
surface->asyncRescaleAndReadPixelsYUV420(kIdentity_SkYUVColorSpace, SkColorSpace::MakeSRGB(),
image_info.bounds(), image_info.dimensions(),
SkSurface::RescaleGamma::kSrc, kNone_SkFilterQuality,
&async_callback, &cbContext);
while (!cbContext.fCalled) {
surface->getCanvas()->getGrContext()->checkAsyncWorkCompletion();
}
REPORTER_ASSERT(reporter, !cbContext.fResult);
protectedTestHelper->grContext()->deleteBackendTexture(
surface->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess));
}
DEF_GPUTEST(VkProtectedContext_DrawRectangle, reporter, options) {
auto protectedTestHelper = std::make_unique<VulkanTestHelper>(true);
if (!protectedTestHelper->init(reporter)) {
return;
}
REPORTER_ASSERT(reporter, protectedTestHelper->grContext() != nullptr);
auto surface = protectedTestHelper->createSkSurface(reporter);
REPORTER_ASSERT(reporter, surface);
SkCanvas* canvas = surface->getCanvas();
REPORTER_ASSERT(reporter, canvas);
SkPaint paint;
paint.setColor(SK_ColorBLACK);
canvas->drawRect(SkRect::MakeWH(4, 4), paint);
GrFlushInfo flushInfo;
flushInfo.fFlags = kSyncCpu_GrFlushFlag;
surface->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo);
protectedTestHelper->grContext()->deleteBackendTexture(
surface->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess));
}
DEF_GPUTEST(VkProtectedContext_DrawRectangleWithAntiAlias, reporter, options) {
auto protectedTestHelper = std::make_unique<VulkanTestHelper>(true);
if (!protectedTestHelper->init(reporter)) {
return;
}
REPORTER_ASSERT(reporter, protectedTestHelper->grContext() != nullptr);
auto surface = protectedTestHelper->createSkSurface(reporter);
REPORTER_ASSERT(reporter, surface);
SkCanvas* canvas = surface->getCanvas();
REPORTER_ASSERT(reporter, canvas);
SkPaint paint;
paint.setColor(SK_ColorBLACK);
paint.setAntiAlias(true);
canvas->drawRect(SkRect::MakeWH(4, 4), paint);
GrFlushInfo flushInfo;
flushInfo.fFlags = kSyncCpu_GrFlushFlag;
surface->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo);
protectedTestHelper->grContext()->deleteBackendTexture(
surface->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess));
}
DEF_GPUTEST(VkProtectedContext_DrawRectangleWithBlendMode, reporter, options) {
auto protectedTestHelper = std::make_unique<VulkanTestHelper>(true);
if (!protectedTestHelper->init(reporter)) {
return;
}
REPORTER_ASSERT(reporter, protectedTestHelper->grContext() != nullptr);
auto surface = protectedTestHelper->createSkSurface(reporter);
REPORTER_ASSERT(reporter, surface);
SkCanvas* canvas = surface->getCanvas();
REPORTER_ASSERT(reporter, canvas);
SkPaint paint;
paint.setColor(SK_ColorBLACK);
paint.setBlendMode(SkBlendMode::kColorDodge);
canvas->drawRect(SkRect::MakeWH(4, 4), paint);
GrFlushInfo flushInfo;
flushInfo.fFlags = kSyncCpu_GrFlushFlag;
surface->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo);
protectedTestHelper->grContext()->deleteBackendTexture(
surface->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess));
}
DEF_GPUTEST(VkProtectedContext_DrawRectangleWithFilter, reporter, options) {
auto protectedTestHelper = std::make_unique<VulkanTestHelper>(true);
if (!protectedTestHelper->init(reporter)) {
return;
}
REPORTER_ASSERT(reporter, protectedTestHelper->grContext() != nullptr);
auto surface = protectedTestHelper->createSkSurface(reporter);
REPORTER_ASSERT(reporter, surface);
SkCanvas* canvas = surface->getCanvas();
REPORTER_ASSERT(reporter, canvas);
SkPaint paint;
paint.setColor(SK_ColorBLACK);
paint.setStyle(SkPaint::kFill_Style);
paint.setMaskFilter(SkMaskFilter::MakeBlur(
SkBlurStyle::kOuter_SkBlurStyle, 1.1f));
canvas->drawRect(SkRect::MakeWH(4, 4), paint);
GrFlushInfo flushInfo;
flushInfo.fFlags = kSyncCpu_GrFlushFlag;
surface->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo);
protectedTestHelper->grContext()->deleteBackendTexture(
surface->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess));
}
DEF_GPUTEST(VkProtectedContext_DrawThinPath, reporter, options) {
auto protectedTestHelper = std::make_unique<VulkanTestHelper>(true);
if (!protectedTestHelper->init(reporter)) {
return;
}
REPORTER_ASSERT(reporter, protectedTestHelper->grContext() != nullptr);
auto surface = protectedTestHelper->createSkSurface(reporter);
REPORTER_ASSERT(reporter, surface);
SkCanvas* canvas = surface->getCanvas();
REPORTER_ASSERT(reporter, canvas);
SkPaint paint;
paint.setColor(SK_ColorBLACK);
paint.setStyle(SkPaint::kStroke_Style);
paint.setAntiAlias(true);
paint.setStrokeWidth(.4f);
canvas->drawPath(SkPath().moveTo(4, 4).lineTo(6, 6), paint);
GrFlushInfo flushInfo;
flushInfo.fFlags = kSyncCpu_GrFlushFlag;
surface->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo);
protectedTestHelper->grContext()->deleteBackendTexture(
surface->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess));
}
DEF_GPUTEST(VkProtectedContext_SaveLayer, reporter, options) {
auto protectedTestHelper = std::make_unique<VulkanTestHelper>(true);
if (!protectedTestHelper->init(reporter)) {
return;
}
REPORTER_ASSERT(reporter, protectedTestHelper->grContext() != nullptr);
auto surface = protectedTestHelper->createSkSurface(reporter);
REPORTER_ASSERT(reporter, surface);
SkCanvas* canvas = surface->getCanvas();
REPORTER_ASSERT(reporter, canvas);
canvas->saveLayer(nullptr, nullptr);
SkPaint paint;
paint.setColor(SK_ColorBLACK);
canvas->drawRect(SkRect::MakeWH(4, 4), paint);
canvas->restore();
GrFlushInfo flushInfo;
flushInfo.fFlags = kSyncCpu_GrFlushFlag;
surface->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo);
protectedTestHelper->grContext()->deleteBackendTexture(
surface->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess));
}
DEF_GPUTEST(VkProtectedContext_DrawProtectedImageOnProtectedSurface, reporter, options) {
auto protectedTestHelper = std::make_unique<VulkanTestHelper>(true);
if (!protectedTestHelper->init(reporter)) {
return;
}
REPORTER_ASSERT(reporter, protectedTestHelper->grContext() != nullptr);
// Create protected image.
auto surface1 = protectedTestHelper->createSkSurface(reporter);
REPORTER_ASSERT(reporter, surface1);
auto image = surface1->makeImageSnapshot();
REPORTER_ASSERT(reporter, image);
// Create protected canvas.
auto surface2 = protectedTestHelper->createSkSurface(reporter);
REPORTER_ASSERT(reporter, surface2);
SkCanvas* canvas = surface2->getCanvas();
REPORTER_ASSERT(reporter, canvas);
canvas->drawImage(image, 0, 0);
GrFlushInfo flushInfo;
flushInfo.fFlags = kSyncCpu_GrFlushFlag;
surface1->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo);
protectedTestHelper->grContext()->deleteBackendTexture(
surface1->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess));
surface2->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo);
protectedTestHelper->grContext()->deleteBackendTexture(
surface2->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess));
}
//////////////////////////////////////////////////////////////////////////////////////////////////
// Test out DDLs using a protected Vulkan context
void DDLMakeRenderTargetTestImpl(GrContext* context, skiatest::Reporter* reporter);
DEF_GPUTEST(VkProtectedContext_DDLMakeRenderTargetTest, reporter, ctxInfo) {
auto protectedTestHelper = std::make_unique<VulkanTestHelper>(true);
if (!protectedTestHelper->init(reporter)) {
return;
}
REPORTER_ASSERT(reporter, protectedTestHelper->grContext() != nullptr);
DDLMakeRenderTargetTestImpl(protectedTestHelper->grContext(), reporter);
}
void DDLSurfaceCharacterizationTestImpl(GrContext* context, skiatest::Reporter* reporter);
DEF_GPUTEST(VkProtectedContext_DDLSurfaceCharacterizationTest, reporter, ctxInfo) {
auto protectedTestHelper = std::make_unique<VulkanTestHelper>(true);
if (!protectedTestHelper->init(reporter)) {
return;
}
REPORTER_ASSERT(reporter, protectedTestHelper->grContext() != nullptr);
DDLSurfaceCharacterizationTestImpl(protectedTestHelper->grContext(), reporter);
}
#endif // SK_SUPPORT_GPU && defined(SK_VULKAN)