• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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