1 /*
2 * Copyright 2019 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 // This is a Vulkan protected memory specific test.
9
10 #include "include/core/SkTypes.h"
11
12 #if SK_SUPPORT_GPU && defined(SK_VULKAN)
13
14 #include "include/core/SkCanvas.h"
15 #include "include/core/SkMaskFilter.h"
16 #include "include/core/SkPaint.h"
17 #include "include/core/SkSurface.h"
18 #include "include/gpu/GrBackendSurface.h"
19 #include "include/gpu/vk/GrVkBackendContext.h"
20 #include "include/gpu/vk/GrVkExtensions.h"
21 #include "tests/Test.h"
22 #include "tools/gpu/GrContextFactory.h"
23 #include "tools/gpu/vk/VkTestUtils.h"
24
25 namespace {
26
27 #define DECLARE_VK_PROC(name) PFN_vk##name fVk##name
28
29 #define ACQUIRE_INST_VK_PROC(name) \
30 fVk##name = reinterpret_cast<PFN_vk##name>(getProc("vk" #name, fBackendContext.fInstance,\
31 VK_NULL_HANDLE)); \
32 if (fVk##name == nullptr) { \
33 ERRORF(reporter, "Function ptr for vk%s could not be acquired\n", #name); \
34 return false; \
35 }
36
37 #define ACQUIRE_DEVICE_VK_PROC(name) \
38 fVk##name = reinterpret_cast<PFN_vk##name>(getProc("vk" #name, VK_NULL_HANDLE, fDevice)); \
39 if (fVk##name == nullptr) { \
40 ERRORF(reporter, "Function ptr for vk%s could not be acquired\n", #name); \
41 return false; \
42 }
43
44 class VulkanTestHelper {
45 public:
VulkanTestHelper(bool isProtected)46 VulkanTestHelper(bool isProtected) : fIsProtected(isProtected) {}
47
~VulkanTestHelper()48 ~VulkanTestHelper() {
49 cleanup();
50 }
51
52 bool init(skiatest::Reporter* reporter);
53
grContext()54 GrContext* grContext() { return fGrContext.get(); }
55
56 sk_sp<SkSurface> createSkSurface(skiatest::Reporter* reporter);
57
58 private:
59 void cleanup();
60
61 DECLARE_VK_PROC(DestroyInstance);
62 DECLARE_VK_PROC(DeviceWaitIdle);
63 DECLARE_VK_PROC(DestroyDevice);
64
65 bool fIsProtected = false;
66 VkDevice fDevice = VK_NULL_HANDLE;
67
68 GrVkExtensions* fExtensions = nullptr;
69 VkPhysicalDeviceFeatures2* fFeatures = nullptr;
70 VkDebugReportCallbackEXT fDebugCallback = VK_NULL_HANDLE;
71 PFN_vkDestroyDebugReportCallbackEXT fDestroyDebugCallback = nullptr;
72 GrVkBackendContext fBackendContext;
73 sk_sp<GrContext> fGrContext;
74 };
75
76 } // namespace
77
init(skiatest::Reporter * reporter)78 bool VulkanTestHelper::init(skiatest::Reporter* reporter) {
79 PFN_vkGetInstanceProcAddr instProc;
80 PFN_vkGetDeviceProcAddr devProc;
81 if (!sk_gpu_test::LoadVkLibraryAndGetProcAddrFuncs(&instProc, &devProc)) {
82 return false;
83 }
84 auto getProc = [&instProc, &devProc](const char* proc_name,
85 VkInstance instance, VkDevice device) {
86 if (device != VK_NULL_HANDLE) {
87 return devProc(device, proc_name);
88 }
89 return instProc(instance, proc_name);
90 };
91
92 fExtensions = new GrVkExtensions();
93 fFeatures = new VkPhysicalDeviceFeatures2;
94 memset(fFeatures, 0, sizeof(VkPhysicalDeviceFeatures2));
95 fFeatures->sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
96 fFeatures->pNext = nullptr;
97
98 fBackendContext.fInstance = VK_NULL_HANDLE;
99 fBackendContext.fDevice = VK_NULL_HANDLE;
100
101 if (!sk_gpu_test::CreateVkBackendContext(getProc, &fBackendContext, fExtensions,
102 fFeatures, &fDebugCallback, nullptr,
103 sk_gpu_test::CanPresentFn(), fIsProtected)) {
104 return false;
105 }
106 fDevice = fBackendContext.fDevice;
107
108 if (fDebugCallback != VK_NULL_HANDLE) {
109 fDestroyDebugCallback = (PFN_vkDestroyDebugReportCallbackEXT) instProc(
110 fBackendContext.fInstance, "vkDestroyDebugReportCallbackEXT");
111 }
112 ACQUIRE_INST_VK_PROC(DestroyInstance)
113 ACQUIRE_INST_VK_PROC(DeviceWaitIdle)
114 ACQUIRE_INST_VK_PROC(DestroyDevice)
115
116 fGrContext = GrContext::MakeVulkan(fBackendContext);
117 if (!fGrContext) {
118 return false;
119 }
120
121 return true;
122 }
123
cleanup()124 void VulkanTestHelper::cleanup() {
125 fGrContext.reset();
126
127 fBackendContext.fMemoryAllocator.reset();
128 if (fDevice != VK_NULL_HANDLE) {
129 fVkDeviceWaitIdle(fDevice);
130 fVkDestroyDevice(fDevice, nullptr);
131 fDevice = VK_NULL_HANDLE;
132 }
133 if (fDebugCallback != VK_NULL_HANDLE) {
134 fDestroyDebugCallback(fBackendContext.fInstance, fDebugCallback, nullptr);
135 }
136
137 if (fBackendContext.fInstance != VK_NULL_HANDLE) {
138 fVkDestroyInstance(fBackendContext.fInstance, nullptr);
139 fBackendContext.fInstance = VK_NULL_HANDLE;
140 }
141
142 delete fExtensions;
143
144 sk_gpu_test::FreeVulkanFeaturesStructs(fFeatures);
145 delete fFeatures;
146 }
147
createSkSurface(skiatest::Reporter * reporter)148 sk_sp<SkSurface> VulkanTestHelper::createSkSurface(skiatest::Reporter* reporter) {
149 const int kW = 8;
150 const int kH = 8;
151 GrBackendTexture backendTex = grContext()->createBackendTexture(
152 kW, kH, kRGBA_8888_SkColorType, GrMipMapped::kNo, GrRenderable::kNo,
153 fIsProtected ? GrProtected::kYes : GrProtected::kNo);
154 REPORTER_ASSERT(reporter, backendTex.isValid());
155 REPORTER_ASSERT(reporter, backendTex.isProtected() == fIsProtected);
156
157 SkSurfaceProps surfaceProps =
158 SkSurfaceProps(0, SkSurfaceProps::kLegacyFontHost_InitType);
159 sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTextureAsRenderTarget(
160 grContext(), backendTex, kTopLeft_GrSurfaceOrigin, 1,
161 kRGBA_8888_SkColorType, nullptr, &surfaceProps);
162 REPORTER_ASSERT(reporter, surface);
163 return surface;
164 }
165
DEF_GPUTEST(VkProtectedContext_CreateNonprotectedContext,reporter,options)166 DEF_GPUTEST(VkProtectedContext_CreateNonprotectedContext, reporter, options) {
167 auto nonprotectedTestHelper = std::make_unique<VulkanTestHelper>(false);
168 REPORTER_ASSERT(reporter, nonprotectedTestHelper->init(reporter));
169 }
170
171
DEF_GPUTEST(VkProtectedContext_CreateProtectedContext,reporter,options)172 DEF_GPUTEST(VkProtectedContext_CreateProtectedContext, reporter, options) {
173 auto protectedTestHelper = std::make_unique<VulkanTestHelper>(true);
174 if (!protectedTestHelper->init(reporter)) {
175 return;
176 }
177 }
178
DEF_GPUTEST(VkProtectedContext_CreateProtectedSkSurface,reporter,options)179 DEF_GPUTEST(VkProtectedContext_CreateProtectedSkSurface, reporter, options) {
180 auto protectedTestHelper = std::make_unique<VulkanTestHelper>(true);
181 if (!protectedTestHelper->init(reporter)) {
182 return;
183 }
184 REPORTER_ASSERT(reporter, protectedTestHelper->grContext() != nullptr);
185
186 const int kW = 8;
187 const int kH = 8;
188 GrBackendTexture backendTex =
189 protectedTestHelper->grContext()->createBackendTexture(
190 kW, kH, kRGBA_8888_SkColorType, GrMipMapped::kNo, GrRenderable::kNo,
191 GrProtected::kYes);
192 REPORTER_ASSERT(reporter, backendTex.isValid());
193 REPORTER_ASSERT(reporter, backendTex.isProtected());
194
195 SkSurfaceProps surfaceProps =
196 SkSurfaceProps(0, SkSurfaceProps::kLegacyFontHost_InitType);
197 sk_sp<SkSurface> surface = SkSurface::MakeFromBackendTextureAsRenderTarget(
198 protectedTestHelper->grContext(), backendTex, kTopLeft_GrSurfaceOrigin, 1,
199 kRGBA_8888_SkColorType, nullptr, &surfaceProps);
200 REPORTER_ASSERT(reporter, surface);
201
202 protectedTestHelper->grContext()->deleteBackendTexture(backendTex);
203 }
204
DEF_GPUTEST(VkProtectedContext_CreateNonprotectedTextureInProtectedContext,reporter,options)205 DEF_GPUTEST(VkProtectedContext_CreateNonprotectedTextureInProtectedContext, reporter, options) {
206 auto protectedTestHelper = std::make_unique<VulkanTestHelper>(true);
207 if (!protectedTestHelper->init(reporter)) {
208 return;
209 }
210 REPORTER_ASSERT(reporter, protectedTestHelper->grContext() != nullptr);
211
212 const int kW = 8;
213 const int kH = 8;
214 GrBackendTexture backendTex =
215 protectedTestHelper->grContext()->createBackendTexture(
216 kW, kH, kRGBA_8888_SkColorType, GrMipMapped::kNo, GrRenderable::kNo,
217 GrProtected::kNo);
218 REPORTER_ASSERT(reporter, !backendTex.isValid());
219 }
220
DEF_GPUTEST(VkProtectedContext_CreateProtectedTextureInNonprotectedContext,reporter,options)221 DEF_GPUTEST(VkProtectedContext_CreateProtectedTextureInNonprotectedContext, reporter, options) {
222 auto protectedTestHelper = std::make_unique<VulkanTestHelper>(false);
223 if (!protectedTestHelper->init(reporter)) {
224 return;
225 }
226 REPORTER_ASSERT(reporter, protectedTestHelper->grContext() != nullptr);
227
228 const int kW = 8;
229 const int kH = 8;
230 GrBackendTexture backendTex =
231 protectedTestHelper->grContext()->createBackendTexture(
232 kW, kH, kRGBA_8888_SkColorType, GrMipMapped::kNo, GrRenderable::kNo,
233 GrProtected::kYes);
234 REPORTER_ASSERT(reporter, !backendTex.isValid());
235 }
236
DEF_GPUTEST(VkProtectedContext_ReadFromProtectedSurface,reporter,options)237 DEF_GPUTEST(VkProtectedContext_ReadFromProtectedSurface, reporter, options) {
238 auto protectedTestHelper = std::make_unique<VulkanTestHelper>(true);
239 if (!protectedTestHelper->init(reporter)) {
240 return;
241 }
242 REPORTER_ASSERT(reporter, protectedTestHelper->grContext() != nullptr);
243
244 auto surface = protectedTestHelper->createSkSurface(reporter);
245 REPORTER_ASSERT(reporter, surface);
246 REPORTER_ASSERT(reporter,
247 !surface->readPixels(SkImageInfo(), nullptr, 8, 0, 0));
248
249 protectedTestHelper->grContext()->deleteBackendTexture(
250 surface->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess));
251 }
252
DEF_GPUTEST(VkProtectedContext_DrawRectangle,reporter,options)253 DEF_GPUTEST(VkProtectedContext_DrawRectangle, reporter, options) {
254 auto protectedTestHelper = std::make_unique<VulkanTestHelper>(true);
255 if (!protectedTestHelper->init(reporter)) {
256 return;
257 }
258 REPORTER_ASSERT(reporter, protectedTestHelper->grContext() != nullptr);
259
260 auto surface = protectedTestHelper->createSkSurface(reporter);
261 REPORTER_ASSERT(reporter, surface);
262 SkCanvas* canvas = surface->getCanvas();
263 REPORTER_ASSERT(reporter, canvas);
264 SkPaint paint;
265 paint.setColor(SK_ColorBLACK);
266 canvas->drawRect(SkRect::MakeWH(4, 4), paint);
267
268 GrFlushInfo flushInfo;
269 flushInfo.fFlags = kSyncCpu_GrFlushFlag;
270 surface->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo);
271 protectedTestHelper->grContext()->deleteBackendTexture(
272 surface->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess));
273 }
274
DEF_GPUTEST(VkProtectedContext_DrawRectangleWithAntiAlias,reporter,options)275 DEF_GPUTEST(VkProtectedContext_DrawRectangleWithAntiAlias, reporter, options) {
276 auto protectedTestHelper = std::make_unique<VulkanTestHelper>(true);
277 if (!protectedTestHelper->init(reporter)) {
278 return;
279 }
280 REPORTER_ASSERT(reporter, protectedTestHelper->grContext() != nullptr);
281
282 auto surface = protectedTestHelper->createSkSurface(reporter);
283 REPORTER_ASSERT(reporter, surface);
284 SkCanvas* canvas = surface->getCanvas();
285 REPORTER_ASSERT(reporter, canvas);
286 SkPaint paint;
287 paint.setColor(SK_ColorBLACK);
288 paint.setAntiAlias(true);
289 canvas->drawRect(SkRect::MakeWH(4, 4), paint);
290
291 GrFlushInfo flushInfo;
292 flushInfo.fFlags = kSyncCpu_GrFlushFlag;
293 surface->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo);
294 protectedTestHelper->grContext()->deleteBackendTexture(
295 surface->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess));
296 }
297
DEF_GPUTEST(VkProtectedContext_DrawRectangleWithBlendMode,reporter,options)298 DEF_GPUTEST(VkProtectedContext_DrawRectangleWithBlendMode, reporter, options) {
299 auto protectedTestHelper = std::make_unique<VulkanTestHelper>(true);
300 if (!protectedTestHelper->init(reporter)) {
301 return;
302 }
303 REPORTER_ASSERT(reporter, protectedTestHelper->grContext() != nullptr);
304
305 auto surface = protectedTestHelper->createSkSurface(reporter);
306 REPORTER_ASSERT(reporter, surface);
307 SkCanvas* canvas = surface->getCanvas();
308 REPORTER_ASSERT(reporter, canvas);
309 SkPaint paint;
310 paint.setColor(SK_ColorBLACK);
311 paint.setBlendMode(SkBlendMode::kColorDodge);
312 canvas->drawRect(SkRect::MakeWH(4, 4), paint);
313
314 GrFlushInfo flushInfo;
315 flushInfo.fFlags = kSyncCpu_GrFlushFlag;
316 surface->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo);
317 protectedTestHelper->grContext()->deleteBackendTexture(
318 surface->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess));
319 }
320
DEF_GPUTEST(VkProtectedContext_DrawRectangleWithFilter,reporter,options)321 DEF_GPUTEST(VkProtectedContext_DrawRectangleWithFilter, reporter, options) {
322 auto protectedTestHelper = std::make_unique<VulkanTestHelper>(true);
323 if (!protectedTestHelper->init(reporter)) {
324 return;
325 }
326 REPORTER_ASSERT(reporter, protectedTestHelper->grContext() != nullptr);
327
328 auto surface = protectedTestHelper->createSkSurface(reporter);
329 REPORTER_ASSERT(reporter, surface);
330 SkCanvas* canvas = surface->getCanvas();
331 REPORTER_ASSERT(reporter, canvas);
332 SkPaint paint;
333 paint.setColor(SK_ColorBLACK);
334 paint.setStyle(SkPaint::kFill_Style);
335 paint.setMaskFilter(SkMaskFilter::MakeBlur(
336 SkBlurStyle::kOuter_SkBlurStyle, 1.1f));
337 canvas->drawRect(SkRect::MakeWH(4, 4), paint);
338
339 GrFlushInfo flushInfo;
340 flushInfo.fFlags = kSyncCpu_GrFlushFlag;
341 surface->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo);
342 protectedTestHelper->grContext()->deleteBackendTexture(
343 surface->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess));
344 }
345
DEF_GPUTEST(VkProtectedContext_DrawThinPath,reporter,options)346 DEF_GPUTEST(VkProtectedContext_DrawThinPath, reporter, options) {
347 auto protectedTestHelper = std::make_unique<VulkanTestHelper>(true);
348 if (!protectedTestHelper->init(reporter)) {
349 return;
350 }
351 REPORTER_ASSERT(reporter, protectedTestHelper->grContext() != nullptr);
352
353 auto surface = protectedTestHelper->createSkSurface(reporter);
354 REPORTER_ASSERT(reporter, surface);
355 SkCanvas* canvas = surface->getCanvas();
356 REPORTER_ASSERT(reporter, canvas);
357 SkPaint paint;
358 paint.setColor(SK_ColorBLACK);
359 paint.setStyle(SkPaint::kStroke_Style);
360 paint.setAntiAlias(true);
361 paint.setStrokeWidth(.4f);
362 canvas->drawPath(SkPath().moveTo(4, 4).lineTo(6, 6), paint);
363
364 GrFlushInfo flushInfo;
365 flushInfo.fFlags = kSyncCpu_GrFlushFlag;
366 surface->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo);
367 protectedTestHelper->grContext()->deleteBackendTexture(
368 surface->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess));
369 }
370
DEF_GPUTEST(VkProtectedContext_SaveLayer,reporter,options)371 DEF_GPUTEST(VkProtectedContext_SaveLayer, reporter, options) {
372 auto protectedTestHelper = std::make_unique<VulkanTestHelper>(true);
373 if (!protectedTestHelper->init(reporter)) {
374 return;
375 }
376 REPORTER_ASSERT(reporter, protectedTestHelper->grContext() != nullptr);
377
378 auto surface = protectedTestHelper->createSkSurface(reporter);
379 REPORTER_ASSERT(reporter, surface);
380 SkCanvas* canvas = surface->getCanvas();
381 REPORTER_ASSERT(reporter, canvas);
382 canvas->saveLayer(nullptr, nullptr);
383 SkPaint paint;
384 paint.setColor(SK_ColorBLACK);
385 canvas->drawRect(SkRect::MakeWH(4, 4), paint);
386 canvas->restore();
387
388 GrFlushInfo flushInfo;
389 flushInfo.fFlags = kSyncCpu_GrFlushFlag;
390 surface->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo);
391 protectedTestHelper->grContext()->deleteBackendTexture(
392 surface->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess));
393 }
394
395
DEF_GPUTEST(VkProtectedContext_DrawProtectedImageOnProtectedSurface,reporter,options)396 DEF_GPUTEST(VkProtectedContext_DrawProtectedImageOnProtectedSurface, reporter, options) {
397 auto protectedTestHelper = std::make_unique<VulkanTestHelper>(true);
398 if (!protectedTestHelper->init(reporter)) {
399 return;
400 }
401 REPORTER_ASSERT(reporter, protectedTestHelper->grContext() != nullptr);
402
403 // Create protected image.
404 auto surface1 = protectedTestHelper->createSkSurface(reporter);
405 REPORTER_ASSERT(reporter, surface1);
406 auto image = surface1->makeImageSnapshot();
407 REPORTER_ASSERT(reporter, image);
408
409 // Create protected canvas.
410 auto surface2 = protectedTestHelper->createSkSurface(reporter);
411 REPORTER_ASSERT(reporter, surface2);
412 SkCanvas* canvas = surface2->getCanvas();
413 REPORTER_ASSERT(reporter, canvas);
414
415 canvas->drawImage(image, 0, 0);
416
417 GrFlushInfo flushInfo;
418 flushInfo.fFlags = kSyncCpu_GrFlushFlag;
419 surface1->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo);
420 protectedTestHelper->grContext()->deleteBackendTexture(
421 surface1->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess));
422 surface2->flush(SkSurface::BackendSurfaceAccess::kNoAccess, flushInfo);
423 protectedTestHelper->grContext()->deleteBackendTexture(
424 surface2->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess));
425 }
426
427 //////////////////////////////////////////////////////////////////////////////////////////////////
428 // Test out DDLs using a protected Vulkan context
429
430 void DDLMakeRenderTargetTestImpl(GrContext* context, skiatest::Reporter* reporter);
431
DEF_GPUTEST(VkProtectedContext_DDLMakeRenderTargetTest,reporter,ctxInfo)432 DEF_GPUTEST(VkProtectedContext_DDLMakeRenderTargetTest, reporter, ctxInfo) {
433 auto protectedTestHelper = std::make_unique<VulkanTestHelper>(true);
434 if (!protectedTestHelper->init(reporter)) {
435 return;
436 }
437 REPORTER_ASSERT(reporter, protectedTestHelper->grContext() != nullptr);
438
439 DDLMakeRenderTargetTestImpl(protectedTestHelper->grContext(), reporter);
440 }
441
442 void DDLSurfaceCharacterizationTestImpl(GrContext* context, skiatest::Reporter* reporter);
443
DEF_GPUTEST(VkProtectedContext_DDLSurfaceCharacterizationTest,reporter,ctxInfo)444 DEF_GPUTEST(VkProtectedContext_DDLSurfaceCharacterizationTest, reporter, ctxInfo) {
445 auto protectedTestHelper = std::make_unique<VulkanTestHelper>(true);
446 if (!protectedTestHelper->init(reporter)) {
447 return;
448 }
449 REPORTER_ASSERT(reporter, protectedTestHelper->grContext() != nullptr);
450
451 DDLSurfaceCharacterizationTestImpl(protectedTestHelper->grContext(), reporter);
452 }
453
454 #endif // SK_SUPPORT_GPU && defined(SK_VULKAN)
455