1 /*
2 * Copyright 2023 Google LLC
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 #include "tests/Test.h"
9
10 #if defined(SK_GANESH)
11
12 #include "include/core/SkBitmap.h"
13 #include "include/core/SkColorSpace.h"
14 #include "include/core/SkSurface.h"
15 #include "include/gpu/GrBackendSurface.h"
16 #include "include/gpu/GrDirectContext.h"
17 #include "include/gpu/ganesh/SkImageGanesh.h"
18 #include "tests/CtsEnforcement.h"
19 #include "tools/gpu/ProtectedUtils.h"
20
21 static const int kSize = 8;
22
DEF_GANESH_TEST_FOR_ALL_CONTEXTS(Protected_SmokeTest,reporter,ctxInfo,CtsEnforcement::kNever)23 DEF_GANESH_TEST_FOR_ALL_CONTEXTS(Protected_SmokeTest, reporter, ctxInfo, CtsEnforcement::kNever) {
24 auto dContext = ctxInfo.directContext();
25
26 if (!dContext->supportsProtectedContent()) {
27 // Protected content not supported
28 return;
29 }
30
31 for (bool textureable : { true, false }) {
32 for (bool isProtected : { true, false }) {
33 if (!isProtected && GrBackendApi::kVulkan == dContext->backend()) {
34 continue;
35 }
36
37 sk_sp<SkSurface> surface = ProtectedUtils::CreateProtectedSkSurface(dContext,
38 { kSize, kSize },
39 textureable,
40 isProtected);
41 if (!surface) {
42 continue;
43 }
44
45 sk_sp<SkImage> image = surface->makeImageSnapshot();
46 if (!image) {
47 ERRORF(reporter, "Could not makeImageSnapshot from a %s surface.",
48 isProtected ? "protected" : "unprotected");
49 continue;
50 }
51
52 dContext->submit(GrSyncCpu::kYes);
53
54 REPORTER_ASSERT(reporter, image->isProtected() == isProtected);
55 ProtectedUtils::CheckImageBEProtection(image.get(), isProtected);
56 }
57 }
58
59 for (bool isProtected : { true, false }) {
60 if (!isProtected && GrBackendApi::kVulkan == dContext->backend()) {
61 continue;
62 }
63
64 sk_sp<SkImage> image = ProtectedUtils::CreateProtectedSkImage(dContext,
65 { kSize, kSize },
66 SkColors::kBlue,
67 isProtected);
68 if (!image) {
69 continue;
70 }
71
72 dContext->submit(GrSyncCpu::kYes);
73
74 REPORTER_ASSERT(reporter, image->isProtected() == isProtected);
75 ProtectedUtils::CheckImageBEProtection(image.get(), isProtected);
76 }
77
78 for (bool renderable : { true, false }) {
79 for (bool isProtected : { true, false }) {
80 GrBackendTexture beTex = dContext->createBackendTexture(16,
81 16,
82 kRGBA_8888_SkColorType,
83 SkColors::kTransparent,
84 skgpu::Mipmapped::kNo,
85 GrRenderable(renderable),
86 GrProtected(isProtected));
87
88 REPORTER_ASSERT(reporter, beTex.isValid());
89 REPORTER_ASSERT(reporter, beTex.isProtected() == isProtected);
90
91 dContext->flushAndSubmit(GrSyncCpu::kYes);
92
93 {
94 sk_sp<SkImage> img = SkImages::BorrowTextureFrom(dContext, beTex,
95 kTopLeft_GrSurfaceOrigin,
96 kRGBA_8888_SkColorType,
97 kPremul_SkAlphaType,
98 /* colorSpace= */ nullptr);
99
100 REPORTER_ASSERT(reporter, img->isProtected() == isProtected);
101 }
102
103 if (beTex.isValid()) {
104 dContext->deleteBackendTexture(beTex);
105 }
106 }
107 }
108 }
109
110 // Verify that readPixels fails on protected surfaces
DEF_GANESH_TEST_FOR_ALL_CONTEXTS(Protected_readPixelsFromSurfaces,reporter,ctxInfo,CtsEnforcement::kNever)111 DEF_GANESH_TEST_FOR_ALL_CONTEXTS(Protected_readPixelsFromSurfaces, reporter, ctxInfo,
112 CtsEnforcement::kNever) {
113 auto dContext = ctxInfo.directContext();
114
115 if (!dContext->supportsProtectedContent()) {
116 // Protected content not supported
117 return;
118 }
119
120 for (bool isProtected : { true, false }) {
121 if (!isProtected && GrBackendApi::kVulkan == dContext->backend()) {
122 continue;
123 }
124
125 sk_sp<SkSurface> surface = ProtectedUtils::CreateProtectedSkSurface(dContext,
126 { kSize, kSize },
127 /* textureable= */ true,
128 isProtected);
129 if (!surface) {
130 continue;
131 }
132
133 SkBitmap readback;
134 readback.allocPixels(surface->imageInfo());
135 REPORTER_ASSERT(reporter, isProtected != surface->readPixels(readback, 0, 0));
136 }
137 }
138
139 namespace {
140
141 struct AsyncContext {
142 bool fCalled = false;
143 std::unique_ptr<const SkSurface::AsyncReadResult> fResult;
144 };
145
async_callback(void * c,std::unique_ptr<const SkSurface::AsyncReadResult> result)146 static 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
154 // Verify that asyncRescaleAndReadPixels fails on protected surfaces
DEF_GANESH_TEST_FOR_ALL_CONTEXTS(Protected_asyncRescaleAndReadPixelsFromSurfaces,reporter,ctxInfo,CtsEnforcement::kNever)155 DEF_GANESH_TEST_FOR_ALL_CONTEXTS(Protected_asyncRescaleAndReadPixelsFromSurfaces, reporter, ctxInfo,
156 CtsEnforcement::kNever) {
157 auto dContext = ctxInfo.directContext();
158
159 if (!dContext->supportsProtectedContent()) {
160 // Protected content not supported
161 return;
162 }
163
164 for (bool isProtected : { true, false }) {
165 if (!isProtected && GrBackendApi::kVulkan == dContext->backend()) {
166 continue;
167 }
168
169 sk_sp<SkSurface> surface = ProtectedUtils::CreateProtectedSkSurface(dContext,
170 { kSize, kSize },
171 /* textureable= */ true,
172 isProtected);
173 if (!surface) {
174 continue;
175 }
176
177 AsyncContext cbContext;
178
179 surface->asyncRescaleAndReadPixels(surface->imageInfo(),
180 SkIRect::MakeWH(surface->width(), surface->height()),
181 SkSurface::RescaleGamma::kSrc,
182 SkSurface::RescaleMode::kNearest,
183 async_callback, &cbContext);
184 dContext->submit();
185 while (!cbContext.fCalled) {
186 dContext->checkAsyncWorkCompletion();
187 }
188 REPORTER_ASSERT(reporter, isProtected != SkToBool(cbContext.fResult));
189 }
190 }
191
192 #endif // defined(SK_GANESH)
193