skia2/tests/VkProtectedContextTest.cpp
Emircan Uysaler 7697476ad2 Disable async readback from protected memory
Reading back pixel values from protected memory into cpu memory is
not allowed. This CL adds early returns so they are not attempted.

Bug: skia:9016, fuchsia:38648
Change-Id: Icc0b51a62e87b7aebd0e7cb2a061fea084e7f754
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/251000
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Greg Daniel <egdaniel@google.com>
2019-10-25 20:02:01 +00:00

495 lines
19 KiB
C++

/*
* 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)