xref: /aosp_15_r20/external/skia/tools/viewer/ProtectedSlide.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 "include/core/SkTypes.h"
9 
10 #if defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26
11 
12 #include "include/core/SkBitmap.h"
13 #include "include/core/SkCanvas.h"
14 #include "include/core/SkColorSpace.h"
15 #include "tools/ToolUtils.h"
16 #include "tools/viewer/Slide.h"
17 
18 #if defined(SK_GANESH)
19 #include "include/android/SkImageAndroid.h"
20 #include "include/android/SkSurfaceAndroid.h"
21 #include "include/gpu/ganesh/GrDirectContext.h"
22 #include "include/gpu/ganesh/SkSurfaceGanesh.h"
23 #endif
24 
25 #if defined(SK_GRAPHITE)
26 #include "include/android/graphite/SurfaceAndroid.h"
27 #include "include/gpu/graphite/Context.h"
28 #include "include/gpu/graphite/Surface.h"
29 #include "src/gpu/graphite/RecorderPriv.h"
30 
31 #else
32 namespace skgpu::graphite {
33     class Recorder;
34 }
35 #endif
36 
37 #include <android/hardware_buffer.h>
38 
39 using namespace skgpu::graphite;
40 
41 namespace {
42 
release_buffer(AHardwareBuffer * buffer)43 static void release_buffer(AHardwareBuffer* buffer) {
44     if (buffer) {
45         AHardwareBuffer_release(buffer);
46     }
47 }
48 
wrap_buffer(GrDirectContext * dContext,Recorder * recorder,AHardwareBuffer * buffer)49 sk_sp<SkSurface> wrap_buffer(GrDirectContext* dContext,
50                              Recorder* recorder,
51                              AHardwareBuffer* buffer) {
52 #if defined(SK_GANESH)
53     if (dContext) {
54         return SkSurfaces::WrapAndroidHardwareBuffer(dContext,
55                                                      buffer,
56                                                      kTopLeft_GrSurfaceOrigin,
57                                                      /* colorSpace= */ nullptr,
58                                                      /* surfaceProps= */ nullptr);
59     }
60 #endif
61 
62 #if defined(SK_GRAPHITE)
63     if (recorder) {
64         return SkSurfaces::WrapAndroidHardwareBuffer(recorder,
65                                                      buffer,
66                                                      /* colorSpace= */ nullptr,
67                                                      /* surfaceProps= */ nullptr);
68     }
69 #endif
70 
71     return nullptr;
72 }
73 
create_protected_render_target(GrDirectContext * dContext,Recorder * recorder,const SkImageInfo & ii)74 sk_sp<SkSurface> create_protected_render_target(GrDirectContext* dContext,
75                                                 Recorder* recorder,
76                                                 const SkImageInfo& ii) {
77 #if defined(SK_GANESH)
78     if (dContext) {
79         return SkSurfaces::RenderTarget(dContext,
80                                         skgpu::Budgeted::kYes,
81                                         ii,
82                                         /* sampleCount= */ 1,
83                                         kTopLeft_GrSurfaceOrigin,
84                                         /* surfaceProps= */ nullptr,
85                                         /* shouldCreateWithMips= */ false,
86                                         /* isProtected= */ true);
87     }
88 #endif
89 
90 #if defined(SK_GRAPHITE)
91     if (recorder) {
92         // Protected-ness is pulled off of the recorder
93         return SkSurfaces::RenderTarget(recorder,
94                                         ii,
95                                         skgpu::Mipmapped::kNo,
96                                         /* props= */ nullptr);
97     }
98 #endif
99 
100     return nullptr;
101 }
102 
create_protected_buffer(int width,int height)103 AHardwareBuffer* create_protected_buffer(int width, int height) {
104 
105     AHardwareBuffer* buffer = nullptr;
106 
107     AHardwareBuffer_Desc hwbDesc;
108     hwbDesc.width = width;
109     hwbDesc.height = height;
110     hwbDesc.layers = 1;
111     hwbDesc.usage = AHARDWAREBUFFER_USAGE_CPU_READ_NEVER |
112                     AHARDWAREBUFFER_USAGE_CPU_WRITE_NEVER |
113                     AHARDWAREBUFFER_USAGE_GPU_SAMPLED_IMAGE |
114                     AHARDWAREBUFFER_USAGE_GPU_COLOR_OUTPUT;
115 
116     hwbDesc.usage |= AHARDWAREBUFFER_USAGE_PROTECTED_CONTENT;
117 
118     hwbDesc.format = AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM;
119     // The following three are not used in the allocate
120     hwbDesc.stride = 0;
121     hwbDesc.rfu0= 0;
122     hwbDesc.rfu1= 0;
123 
124     if (int error = AHardwareBuffer_allocate(&hwbDesc, &buffer)) {
125         SkDebugf("Failed to allocated hardware buffer, error: %d\n", error);
126         release_buffer(buffer);
127         return nullptr;
128     }
129 
130     return buffer;
131 }
132 
create_protected_AHB_image(GrDirectContext * dContext,Recorder * recorder,AHardwareBuffer * buffer,SkColor color)133 sk_sp<SkImage> create_protected_AHB_image(GrDirectContext* dContext,
134                                           Recorder* recorder,
135                                           AHardwareBuffer* buffer,
136                                           SkColor color) {
137 
138     sk_sp<SkSurface> surf = wrap_buffer(dContext, recorder, buffer);
139     if (!surf) {
140         SkDebugf("Failed to make SkSurface.\n");
141         return nullptr;
142     }
143 
144     ToolUtils::draw_checkerboard(surf->getCanvas(), color, SK_ColorTRANSPARENT, 32);
145 
146     return surf->makeImageSnapshot();
147 }
148 
create_protected_skia_image(GrDirectContext * dContext,Recorder * recorder,int width,int height,SkColor color)149 sk_sp<SkImage> create_protected_skia_image(GrDirectContext* dContext,
150                                            Recorder* recorder,
151                                            int width, int height,
152                                            SkColor color) {
153     SkImageInfo ii = SkImageInfo::Make(width, height, kRGBA_8888_SkColorType,
154                                        kPremul_SkAlphaType);
155 
156     sk_sp<SkSurface> tmpSurface = create_protected_render_target(dContext, recorder, ii);
157     if (!tmpSurface) {
158         return nullptr;
159     }
160 
161     ToolUtils::draw_checkerboard(tmpSurface->getCanvas(), color, SK_ColorTRANSPARENT, 32);
162 
163     return tmpSurface->makeImageSnapshot();
164 }
165 
166 } // anonymous namespace
167 
168 class ProtectedSlide : public Slide {
169 public:
ProtectedSlide()170     ProtectedSlide() { fName = "Protected"; }
171 
getDimensions() const172     SkISize getDimensions() const override { return {kSize, 2*kSize}; }
173 
draw(SkCanvas * origCanvas)174     void draw(SkCanvas* origCanvas) override {
175         origCanvas->clear(SK_ColorDKGRAY);
176 
177         skgpu::graphite::Recorder* recorder = origCanvas->recorder();
178         GrDirectContext* dContext = GrAsDirectContext(origCanvas->recordingContext());
179 
180 #if defined(SK_GANESH)
181         if (dContext && !dContext->supportsProtectedContent()) {
182             origCanvas->clear(SK_ColorGREEN);
183             return;
184         }
185 #endif
186 
187 #if defined(SK_GRAPHITE)
188         if (recorder && recorder->priv().isProtected() == skgpu::Protected::kNo) {
189             origCanvas->clear(SK_ColorBLUE);
190             return;
191         }
192 #endif
193 
194         if (!dContext && !recorder) {
195             origCanvas->clear(SK_ColorRED);
196             return;
197         }
198 
199         AHardwareBuffer* buffer = create_protected_buffer(kSize, kSize);
200 
201         sk_sp<SkImage> protectedAHBImage = create_protected_AHB_image(dContext, recorder, buffer,
202                                                                       SK_ColorRED);
203         sk_sp<SkImage> protectedSkImage = create_protected_skia_image(dContext, recorder,
204                                                                       kSize, kSize, SK_ColorBLUE);
205 
206         // Pick one of the two protected images to draw. Only the protected AHB-backed image will
207         // reproduce the bug (b/242266174).
208         SkImage* imgToUse = protectedAHBImage.get();
209 //        SkImage* imgToUse = protectedSkImage.get();
210 
211         sk_sp<SkImage> indirectImg;
212 
213         {
214             SkImageInfo ii = SkImageInfo::Make(kSize, kSize, kRGBA_8888_SkColorType,
215                                                kPremul_SkAlphaType);
216             sk_sp<SkSurface> tmpS = create_protected_render_target(dContext, recorder, ii);
217 
218             tmpS->getCanvas()->clear(SK_ColorMAGENTA);
219             tmpS->getCanvas()->drawCircle(64, 64, 32, SkPaint());
220 
221             // For protected AHB-backed images this draw seems to poison all above the draws too
222             tmpS->getCanvas()->drawImage(imgToUse, 0, 0);
223             indirectImg = tmpS->makeImageSnapshot();
224         }
225 
226         origCanvas->drawImage(imgToUse, 0, 0);
227         origCanvas->drawImage(indirectImg, 0, kSize);
228 
229         protectedAHBImage.reset();
230         protectedSkImage.reset();
231         release_buffer(buffer);
232     }
233 
234 private:
235     static const int kSize = 128;
236 };
237 
238 DEF_SLIDE( return new ProtectedSlide(); )
239 
240 #endif
241