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/BackendSurfaceFactory.h"
23#include "tools/gpu/GrContextFactory.h"
24#include "tools/gpu/vk/VkTestHelper.h"
25
26static sk_sp<SkSurface> create_protected_sksurface(GrDirectContext* dContext,
27                                                   skiatest::Reporter* reporter,
28                                                   bool textureable = true) {
29    const int kW = 8;
30    const int kH = 8;
31    SkSurfaceProps surfaceProps = SkSurfaceProps(0, kRGB_H_SkPixelGeometry);
32    sk_sp<SkSurface> surface;
33    if (textureable) {
34        surface = sk_gpu_test::MakeBackendTextureSurface(dContext,
35                                                         {kW, kH},
36                                                         kTopLeft_GrSurfaceOrigin,
37                                                         1,
38                                                         kRGBA_8888_SkColorType,
39                                                         /* color space */ nullptr,
40                                                         GrMipmapped::kNo,
41                                                         GrProtected::kYes,
42                                                         &surfaceProps);
43    } else {
44        surface = sk_gpu_test::MakeBackendRenderTargetSurface(dContext,
45                                                              {kW, kH},
46                                                              kTopLeft_GrSurfaceOrigin,
47                                                              1,
48                                                              kRGBA_8888_SkColorType,
49                                                              /* color space */ nullptr,
50                                                              GrProtected::kYes,
51                                                              &surfaceProps);
52    }
53    if (!surface) {
54        ERRORF(reporter, "Could not create protected surface.");
55        return nullptr;
56    }
57    if (textureable) {
58        GrBackendTexture backendTex =
59                surface->getBackendTexture(SkSurface::kFlushRead_BackendHandleAccess);
60        REPORTER_ASSERT(reporter, backendTex.isValid());
61        REPORTER_ASSERT(reporter, backendTex.isProtected());
62    } else {
63        GrBackendRenderTarget backendRT =
64                surface->getBackendRenderTarget(SkSurface::kFlushRead_BackendHandleAccess);
65        REPORTER_ASSERT(reporter, backendRT.isValid());
66        REPORTER_ASSERT(reporter, backendRT.isProtected());
67    }
68    return surface;
69}
70
71DEF_GPUTEST(VkProtectedContext_CreateNonprotectedContext, reporter, options) {
72    auto nonprotectedTestHelper = std::make_unique<VkTestHelper>(false);
73    REPORTER_ASSERT(reporter, nonprotectedTestHelper->init());
74}
75
76DEF_GPUTEST(VkProtectedContext_CreateProtectedContext, reporter, options) {
77    auto protectedTestHelper = std::make_unique<VkTestHelper>(true);
78    if (!protectedTestHelper->init()) {
79        return;
80    }
81}
82
83DEF_GPUTEST(VkProtectedContext_CreateProtectedSkSurface, reporter, options) {
84    auto protectedTestHelper = std::make_unique<VkTestHelper>(true);
85    if (!protectedTestHelper->init()) {
86        return;
87    }
88
89    auto dContext = protectedTestHelper->directContext();
90    REPORTER_ASSERT(reporter, dContext != nullptr);
91    create_protected_sksurface(dContext, reporter, /*textureable*/ true);
92    create_protected_sksurface(dContext, reporter, /*textureable*/ false);
93}
94
95DEF_GPUTEST(VkProtectedContext_CreateNonprotectedTextureInProtectedContext, reporter, options) {
96    auto protectedTestHelper = std::make_unique<VkTestHelper>(true);
97    if (!protectedTestHelper->init()) {
98        return;
99    }
100    REPORTER_ASSERT(reporter, protectedTestHelper->directContext() != nullptr);
101
102    const int kW = 8;
103    const int kH = 8;
104    GrBackendTexture backendTex =
105        protectedTestHelper->directContext()->createBackendTexture(
106            kW, kH, kRGBA_8888_SkColorType, GrMipmapped::kNo, GrRenderable::kNo,
107            GrProtected::kNo);
108    REPORTER_ASSERT(reporter, !backendTex.isValid());
109}
110
111DEF_GPUTEST(VkProtectedContext_CreateProtectedTextureInNonprotectedContext, reporter, options) {
112    auto protectedTestHelper = std::make_unique<VkTestHelper>(false);
113    if (!protectedTestHelper->init()) {
114        return;
115    }
116    REPORTER_ASSERT(reporter, protectedTestHelper->directContext() != nullptr);
117
118    const int kW = 8;
119    const int kH = 8;
120    GrBackendTexture backendTex =
121        protectedTestHelper->directContext()->createBackendTexture(
122            kW, kH, kRGBA_8888_SkColorType, GrMipmapped::kNo, GrRenderable::kNo,
123            GrProtected::kYes);
124    REPORTER_ASSERT(reporter, !backendTex.isValid());
125}
126
127DEF_GPUTEST(VkProtectedContext_ReadFromProtectedSurface, reporter, options) {
128    auto protectedTestHelper = std::make_unique<VkTestHelper>(true);
129    if (!protectedTestHelper->init()) {
130        return;
131    }
132    REPORTER_ASSERT(reporter, protectedTestHelper->directContext() != nullptr);
133
134    auto surface = create_protected_sksurface(protectedTestHelper->directContext(), reporter);
135    REPORTER_ASSERT(reporter, surface);
136    REPORTER_ASSERT(reporter, !surface->readPixels(SkImageInfo(), nullptr, 8, 0, 0));
137}
138
139namespace {
140
141struct AsyncContext {
142    bool fCalled = false;
143    std::unique_ptr<const SkSurface::AsyncReadResult> fResult;
144};
145
146static void async_callback(void* c, std::unique_ptr<const SkSurface::AsyncReadResult> result) {
147    auto context = static_cast<AsyncContext*>(c);
148    context->fResult = std::move(result);
149    context->fCalled = true;
150};
151
152}  // anonymous namespace
153
154DEF_GPUTEST(VkProtectedContext_AsyncReadFromProtectedSurface, reporter, options) {
155    auto protectedTestHelper = std::make_unique<VkTestHelper>(true);
156    if (!protectedTestHelper->init()) {
157        return;
158    }
159
160    auto dContext = protectedTestHelper->directContext();
161
162    REPORTER_ASSERT(reporter, dContext != nullptr);
163
164    auto surface = create_protected_sksurface(dContext, reporter);
165    REPORTER_ASSERT(reporter, surface);
166    AsyncContext cbContext;
167    const auto image_info = SkImageInfo::Make(10, 10, kRGBA_8888_SkColorType, kPremul_SkAlphaType,
168                                      SkColorSpace::MakeSRGB());
169    surface->asyncRescaleAndReadPixelsYUV420(kIdentity_SkYUVColorSpace, SkColorSpace::MakeSRGB(),
170                                             image_info.bounds(), image_info.dimensions(),
171                                             SkSurface::RescaleGamma::kSrc,
172                                             SkSurface::RescaleMode::kNearest,
173                                             &async_callback, &cbContext);
174    dContext->submit();
175    while (!cbContext.fCalled) {
176        dContext->checkAsyncWorkCompletion();
177    }
178    REPORTER_ASSERT(reporter, !cbContext.fResult);
179}
180
181DEF_GPUTEST(VkProtectedContext_DrawRectangle, reporter, options) {
182    auto protectedTestHelper = std::make_unique<VkTestHelper>(true);
183    if (!protectedTestHelper->init()) {
184        return;
185    }
186    REPORTER_ASSERT(reporter, protectedTestHelper->directContext() != nullptr);
187
188    auto surface = create_protected_sksurface(protectedTestHelper->directContext(), reporter);
189    REPORTER_ASSERT(reporter, surface);
190    SkCanvas* canvas = surface->getCanvas();
191    REPORTER_ASSERT(reporter, canvas);
192    SkPaint paint;
193    paint.setColor(SK_ColorBLACK);
194    canvas->drawRect(SkRect::MakeWH(4, 4), paint);
195}
196
197DEF_GPUTEST(VkProtectedContext_DrawRectangleWithAntiAlias, reporter, options) {
198    auto protectedTestHelper = std::make_unique<VkTestHelper>(true);
199    if (!protectedTestHelper->init()) {
200        return;
201    }
202    REPORTER_ASSERT(reporter, protectedTestHelper->directContext() != nullptr);
203
204    auto surface = create_protected_sksurface(protectedTestHelper->directContext(), reporter);
205    REPORTER_ASSERT(reporter, surface);
206    SkCanvas* canvas = surface->getCanvas();
207    REPORTER_ASSERT(reporter, canvas);
208    SkPaint paint;
209    paint.setColor(SK_ColorBLACK);
210    paint.setAntiAlias(true);
211    canvas->drawRect(SkRect::MakeWH(4, 4), paint);
212}
213
214DEF_GPUTEST(VkProtectedContext_DrawRectangleWithBlendMode, reporter, options) {
215    auto protectedTestHelper = std::make_unique<VkTestHelper>(true);
216    if (!protectedTestHelper->init()) {
217        return;
218    }
219    REPORTER_ASSERT(reporter, protectedTestHelper->directContext() != nullptr);
220
221    auto surface = create_protected_sksurface(protectedTestHelper->directContext(), reporter);
222    REPORTER_ASSERT(reporter, surface);
223    SkCanvas* canvas = surface->getCanvas();
224    REPORTER_ASSERT(reporter, canvas);
225    SkPaint paint;
226    paint.setColor(SK_ColorBLACK);
227    paint.setBlendMode(SkBlendMode::kColorDodge);
228    canvas->drawRect(SkRect::MakeWH(4, 4), paint);
229}
230
231DEF_GPUTEST(VkProtectedContext_DrawRectangleWithFilter, reporter, options) {
232    auto protectedTestHelper = std::make_unique<VkTestHelper>(true);
233    if (!protectedTestHelper->init()) {
234        return;
235    }
236    REPORTER_ASSERT(reporter, protectedTestHelper->directContext() != nullptr);
237
238    auto surface = create_protected_sksurface(protectedTestHelper->directContext(), reporter);
239    REPORTER_ASSERT(reporter, surface);
240    SkCanvas* canvas = surface->getCanvas();
241    REPORTER_ASSERT(reporter, canvas);
242    SkPaint paint;
243    paint.setColor(SK_ColorBLACK);
244    paint.setStyle(SkPaint::kFill_Style);
245    paint.setMaskFilter(SkMaskFilter::MakeBlur(
246          SkBlurStyle::kOuter_SkBlurStyle, 1.1f));
247    canvas->drawRect(SkRect::MakeWH(4, 4), paint);
248}
249
250DEF_GPUTEST(VkProtectedContext_DrawThinPath, reporter, options) {
251    auto protectedTestHelper = std::make_unique<VkTestHelper>(true);
252    if (!protectedTestHelper->init()) {
253        return;
254    }
255    REPORTER_ASSERT(reporter, protectedTestHelper->directContext() != nullptr);
256
257    auto surface = create_protected_sksurface(protectedTestHelper->directContext(), reporter);
258    REPORTER_ASSERT(reporter, surface);
259    SkCanvas* canvas = surface->getCanvas();
260    REPORTER_ASSERT(reporter, canvas);
261    SkPaint paint;
262    paint.setColor(SK_ColorBLACK);
263    paint.setStyle(SkPaint::kStroke_Style);
264    paint.setAntiAlias(true);
265    paint.setStrokeWidth(.4f);
266    canvas->drawPath(SkPath().moveTo(4, 4).lineTo(6, 6), paint);
267}
268
269DEF_GPUTEST(VkProtectedContext_SaveLayer, reporter, options) {
270    auto protectedTestHelper = std::make_unique<VkTestHelper>(true);
271    if (!protectedTestHelper->init()) {
272        return;
273    }
274    REPORTER_ASSERT(reporter, protectedTestHelper->directContext() != nullptr);
275
276    auto surface = create_protected_sksurface(protectedTestHelper->directContext(), reporter);
277    REPORTER_ASSERT(reporter, surface);
278    SkCanvas* canvas = surface->getCanvas();
279    REPORTER_ASSERT(reporter, canvas);
280    canvas->saveLayer(nullptr, nullptr);
281    SkPaint paint;
282    paint.setColor(SK_ColorBLACK);
283    canvas->drawRect(SkRect::MakeWH(4, 4), paint);
284    canvas->restore();
285}
286
287
288DEF_GPUTEST(VkProtectedContext_DrawProtectedImageOnProtectedSurface, reporter, options) {
289    auto protectedTestHelper = std::make_unique<VkTestHelper>(true);
290    if (!protectedTestHelper->init()) {
291        return;
292    }
293    REPORTER_ASSERT(reporter, protectedTestHelper->directContext() != nullptr);
294
295    // Create protected image.
296    auto surface1 = create_protected_sksurface(protectedTestHelper->directContext(), reporter);
297    REPORTER_ASSERT(reporter, surface1);
298    auto image = surface1->makeImageSnapshot();
299    REPORTER_ASSERT(reporter, image);
300
301    // Create protected canvas.
302    auto surface2 = create_protected_sksurface(protectedTestHelper->directContext(), reporter);
303    REPORTER_ASSERT(reporter, surface2);
304    SkCanvas* canvas = surface2->getCanvas();
305    REPORTER_ASSERT(reporter, canvas);
306
307    canvas->drawImage(image, 0, 0);
308}
309
310//////////////////////////////////////////////////////////////////////////////////////////////////
311// Test out DDLs using a protected Vulkan context
312
313void DDLMakeRenderTargetTestImpl(GrDirectContext*, skiatest::Reporter*);
314
315DEF_GPUTEST(VkProtectedContext_DDLMakeRenderTargetTest, reporter, ctxInfo) {
316    auto protectedTestHelper = std::make_unique<VkTestHelper>(true);
317    if (!protectedTestHelper->init()) {
318        return;
319    }
320    REPORTER_ASSERT(reporter, protectedTestHelper->directContext() != nullptr);
321
322    DDLMakeRenderTargetTestImpl(protectedTestHelper->directContext(), reporter);
323}
324
325void DDLSurfaceCharacterizationTestImpl(GrDirectContext*, skiatest::Reporter*);
326
327DEF_GPUTEST(VkProtectedContext_DDLSurfaceCharacterizationTest, reporter, ctxInfo) {
328    auto protectedTestHelper = std::make_unique<VkTestHelper>(true);
329    if (!protectedTestHelper->init()) {
330        return;
331    }
332    REPORTER_ASSERT(reporter, protectedTestHelper->directContext() != nullptr);
333
334    DDLSurfaceCharacterizationTestImpl(protectedTestHelper->directContext(), reporter);
335}
336
337#endif  // SK_SUPPORT_GPU && defined(SK_VULKAN)
338