xref: /aosp_15_r20/external/skia/tests/ProtectedTest.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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/SkCanvas.h"
14 #include "include/core/SkColorSpace.h"
15 #include "include/core/SkPaint.h"
16 #include "include/core/SkSurface.h"
17 #include "include/gpu/ganesh/GrBackendSurface.h"
18 #include "include/gpu/ganesh/GrDirectContext.h"
19 #include "include/gpu/ganesh/SkImageGanesh.h"
20 #include "include/gpu/ganesh/SkSurfaceGanesh.h"
21 #include "tests/CtsEnforcement.h"
22 #include "tools/gpu/ProtectedUtils.h"
23 
24 static const int kSize = 8;
25 
DEF_GANESH_TEST_FOR_ALL_CONTEXTS(Protected_SmokeTest,reporter,ctxInfo,CtsEnforcement::kNever)26 DEF_GANESH_TEST_FOR_ALL_CONTEXTS(Protected_SmokeTest, reporter, ctxInfo, CtsEnforcement::kNever) {
27     auto dContext = ctxInfo.directContext();
28 
29     if (!dContext->supportsProtectedContent()) {
30         // Protected content not supported
31         return;
32     }
33 
34     for (bool textureable : { true, false }) {
35         for (bool isProtected : { true, false }) {
36             if (!isProtected && GrBackendApi::kVulkan == dContext->backend()) {
37                 continue;
38             }
39 
40             sk_sp<SkSurface> surface = ProtectedUtils::CreateProtectedSkSurface(dContext,
41                                                                                 { kSize, kSize },
42                                                                                 textureable,
43                                                                                 isProtected);
44             if (!surface) {
45                 continue;
46             }
47 
48             sk_sp<SkImage> image = surface->makeImageSnapshot();
49             if (!image) {
50                 ERRORF(reporter, "Could not makeImageSnapshot from a %s surface.",
51                        isProtected ? "protected" : "unprotected");
52                 continue;
53             }
54 
55             dContext->submit(GrSyncCpu::kYes);
56 
57             REPORTER_ASSERT(reporter, image->isProtected() == isProtected);
58             ProtectedUtils::CheckImageBEProtection(image.get(), isProtected);
59         }
60     }
61 
62     for (bool isProtected : { true, false }) {
63         if (!isProtected && GrBackendApi::kVulkan == dContext->backend()) {
64             continue;
65         }
66 
67         sk_sp<SkImage> image = ProtectedUtils::CreateProtectedSkImage(dContext,
68                                                                       { kSize, kSize },
69                                                                       SkColors::kBlue,
70                                                                       isProtected);
71         if (!image) {
72             continue;
73         }
74 
75         dContext->submit(GrSyncCpu::kYes);
76 
77         REPORTER_ASSERT(reporter, image->isProtected() == isProtected);
78         ProtectedUtils::CheckImageBEProtection(image.get(), isProtected);
79     }
80 
81     for (bool renderable : { true, false }) {
82         for (bool isProtected : { true, false }) {
83             GrBackendTexture beTex = dContext->createBackendTexture(16,
84                                                                     16,
85                                                                     kRGBA_8888_SkColorType,
86                                                                     SkColors::kTransparent,
87                                                                     skgpu::Mipmapped::kNo,
88                                                                     GrRenderable(renderable),
89                                                                     GrProtected(isProtected));
90 
91             REPORTER_ASSERT(reporter, beTex.isValid());
92             REPORTER_ASSERT(reporter, beTex.isProtected() == isProtected);
93 
94             dContext->flushAndSubmit(GrSyncCpu::kYes);
95 
96             {
97                 sk_sp<SkImage> img = SkImages::BorrowTextureFrom(dContext, beTex,
98                                                                  kTopLeft_GrSurfaceOrigin,
99                                                                  kRGBA_8888_SkColorType,
100                                                                  kPremul_SkAlphaType,
101                                                                  /* colorSpace= */ nullptr);
102 
103                 REPORTER_ASSERT(reporter, img->isProtected() == isProtected);
104             }
105 
106             if (beTex.isValid()) {
107                 dContext->deleteBackendTexture(beTex);
108             }
109         }
110     }
111 }
112 
113 // Verify that readPixels fails on protected surfaces
DEF_GANESH_TEST_FOR_ALL_CONTEXTS(Protected_readPixelsFromSurfaces,reporter,ctxInfo,CtsEnforcement::kNever)114 DEF_GANESH_TEST_FOR_ALL_CONTEXTS(Protected_readPixelsFromSurfaces, reporter, ctxInfo,
115                                  CtsEnforcement::kNever) {
116     auto dContext = ctxInfo.directContext();
117 
118     if (!dContext->supportsProtectedContent()) {
119         // Protected content not supported
120         return;
121     }
122 
123     sk_sp<SkSurface> surface = ProtectedUtils::CreateProtectedSkSurface(dContext,
124                                                                         { kSize, kSize },
125                                                                         /* textureable= */ true,
126                                                                         /* isProtected= */ true);
127     if (!surface) {
128         return;
129     }
130 
131     SkBitmap readback;
132     readback.allocPixels(surface->imageInfo());
133     REPORTER_ASSERT(reporter, !surface->readPixels(readback, 0, 0));
134 }
135 
136 // Graphite does not perform Copy-on-Write which is why there is no DEF_GRAPHITE_TEST correlate
DEF_GANESH_TEST_FOR_ALL_CONTEXTS(Protected_CopyOnWrite,reporter,ctxInfo,CtsEnforcement::kNever)137 DEF_GANESH_TEST_FOR_ALL_CONTEXTS(Protected_CopyOnWrite, reporter, ctxInfo, CtsEnforcement::kNever) {
138     auto dContext = ctxInfo.directContext();
139 
140     if (!dContext->supportsProtectedContent()) {
141         // Protected content not supported
142         return;
143     }
144 
145     SkImageInfo ii = SkImageInfo::Make({ kSize, kSize },
146                                        kRGBA_8888_SkColorType,
147                                        kPremul_SkAlphaType);
148 
149     // We can't use ProtectedUtils::CreateProtectedSkSurface here bc that will wrap a backend
150     // texture which blocks the copy-on-write-behavior
151     sk_sp<SkSurface> surface = SkSurfaces::RenderTarget(dContext,
152                                                         skgpu::Budgeted::kNo,
153                                                         ii,
154                                                         /* sampleCount= */ 1,
155                                                         kBottomLeft_GrSurfaceOrigin,
156                                                         /* surfaceProps= */ nullptr,
157                                                         /* shouldCreateWithMips= */ false,
158                                                         /* isProtected= */ true);
159     if (!surface) {
160         return;
161     }
162 
163     SkCanvas* canvas = surface->getCanvas();
164     REPORTER_ASSERT(reporter, canvas);
165 
166     sk_sp<SkImage> imageBefore = surface->makeImageSnapshot();
167     REPORTER_ASSERT(reporter, imageBefore);
168     REPORTER_ASSERT(reporter, imageBefore->isProtected());
169 
170     SkPaint paint;
171     paint.setColor(SK_ColorBLACK);
172     canvas->drawRect(SkRect::MakeWH(4, 4), paint);
173 
174     sk_sp<SkImage> imageAfter = surface->makeImageSnapshot();
175     REPORTER_ASSERT(reporter, imageAfter);
176     REPORTER_ASSERT(reporter, imageAfter->isProtected());
177 
178     REPORTER_ASSERT(reporter, imageBefore != imageAfter);
179 
180     SkBitmap readback;
181     readback.allocPixels(imageAfter->imageInfo());
182     REPORTER_ASSERT(reporter, !imageAfter->readPixels(dContext, readback.pixmap(), 0, 0));
183 }
184 
185 
186 namespace {
187 
188 struct AsyncContext {
189     bool fCalled = false;
190     std::unique_ptr<const SkSurface::AsyncReadResult> fResult;
191 };
192 
async_callback(void * c,std::unique_ptr<const SkSurface::AsyncReadResult> result)193 static void async_callback(void* c, std::unique_ptr<const SkSurface::AsyncReadResult> result) {
194     auto context = static_cast<AsyncContext*>(c);
195     context->fResult = std::move(result);
196     context->fCalled = true;
197 }
198 
199 }  // anonymous namespace
200 
201 // Verify that asyncRescaleAndReadPixels fails on protected surfaces
DEF_GANESH_TEST_FOR_ALL_CONTEXTS(Protected_asyncRescaleAndReadPixelsFromSurfaces,reporter,ctxInfo,CtsEnforcement::kNever)202 DEF_GANESH_TEST_FOR_ALL_CONTEXTS(Protected_asyncRescaleAndReadPixelsFromSurfaces, reporter, ctxInfo,
203                                  CtsEnforcement::kNever) {
204     auto dContext = ctxInfo.directContext();
205 
206     if (!dContext->supportsProtectedContent()) {
207         // Protected content not supported
208         return;
209     }
210 
211     sk_sp<SkSurface> surface = ProtectedUtils::CreateProtectedSkSurface(dContext,
212                                                                         { kSize, kSize },
213                                                                         /* textureable= */ true,
214                                                                         /* isProtected= */ true);
215     if (!surface) {
216         return;
217     }
218 
219     AsyncContext cbContext;
220 
221     surface->asyncRescaleAndReadPixels(surface->imageInfo(),
222                                        SkIRect::MakeWH(surface->width(), surface->height()),
223                                        SkSurface::RescaleGamma::kSrc,
224                                        SkSurface::RescaleMode::kNearest,
225                                        async_callback, &cbContext);
226     dContext->submit();
227     while (!cbContext.fCalled) {
228         dContext->checkAsyncWorkCompletion();
229     }
230     REPORTER_ASSERT(reporter, !cbContext.fResult);
231 }
232 
233 #endif  // defined(SK_GANESH)
234