Flutter Engine
The Flutter Engine
ProtectedSlide.cpp
Go to the documentation of this file.
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
9
10#if defined(SK_BUILD_FOR_ANDROID) && __ANDROID_API__ >= 26
11
15#include "tools/ToolUtils.h"
16#include "tools/viewer/Slide.h"
17
18#if defined(SK_GANESH)
23#endif
24
25#if defined(SK_GRAPHITE)
30
31#else
32namespace skgpu::graphite {
33 class Recorder;
34}
35#endif
36
38
39using namespace skgpu::graphite;
40
41namespace {
42
43static void release_buffer(AHardwareBuffer* buffer) {
44 if (buffer) {
45 AHardwareBuffer_release(buffer);
46 }
47}
48
49sk_sp<SkSurface> wrap_buffer(GrDirectContext* dContext,
50 Recorder* recorder,
52#if defined(SK_GANESH)
53 if (dContext) {
55 buffer,
57 /* colorSpace= */ nullptr,
58 /* surfaceProps= */ nullptr);
59 }
60#endif
61
62#if defined(SK_GRAPHITE)
63 if (recorder) {
65 buffer,
66 /* colorSpace= */ nullptr,
67 /* surfaceProps= */ nullptr);
68 }
69#endif
70
71 return nullptr;
72}
73
74sk_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,
81 ii,
82 /* sampleCount= */ 1,
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,
96 /* props= */ nullptr);
97 }
98#endif
99
100 return nullptr;
101}
102
103AHardwareBuffer* 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
133sk_sp<SkImage> create_protected_AHB_image(GrDirectContext* dContext,
134 Recorder* recorder,
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
145
146 return surf->makeImageSnapshot();
147}
148
149sk_sp<SkImage> create_protected_skia_image(GrDirectContext* dContext,
150 Recorder* recorder,
151 int width, int height,
152 SkColor color) {
155
156 sk_sp<SkSurface> tmpSurface = create_protected_render_target(dContext, recorder, ii);
157 if (!tmpSurface) {
158 return nullptr;
159 }
160
162
163 return tmpSurface->makeImageSnapshot();
164}
165
166} // anonymous namespace
167
168class ProtectedSlide : public Slide {
169public:
170 ProtectedSlide() { fName = "Protected"; }
171
172 SkISize getDimensions() const override { return {kSize, 2*kSize}; }
173
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,
203 sk_sp<SkImage> protectedSkImage = create_protected_skia_image(dContext, recorder,
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 {
216 sk_sp<SkSurface> tmpS = create_protected_render_target(dContext, recorder, ii);
217
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
234private:
235 static const int kSize = 128;
236};
237
238DEF_SLIDE( return new ProtectedSlide(); )
239
240#endif
const char * fName
struct AHardwareBuffer AHardwareBuffer
static GrDirectContext * GrAsDirectContext(GrContext_Base *base)
@ kTopLeft_GrSurfaceOrigin
Definition: GrTypes.h:148
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition: SkAlphaType.h:29
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition: SkColorType.h:24
constexpr SkColor SK_ColorMAGENTA
Definition: SkColor.h:147
uint32_t SkColor
Definition: SkColor.h:37
constexpr SkColor SK_ColorTRANSPARENT
Definition: SkColor.h:99
constexpr SkColor SK_ColorBLUE
Definition: SkColor.h:135
constexpr SkColor SK_ColorRED
Definition: SkColor.h:126
constexpr SkColor SK_ColorGREEN
Definition: SkColor.h:131
constexpr SkColor SK_ColorDKGRAY
Definition: SkColor.h:108
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
#define DEF_SLIDE(code)
Definition: Slide.h:25
SK_API bool supportsProtectedContent() const
virtual GrRecordingContext * recordingContext() const
Definition: SkCanvas.cpp:1637
virtual skgpu::graphite::Recorder * recorder() const
Definition: SkCanvas.cpp:1641
void clear(SkColor color)
Definition: SkCanvas.h:1199
void drawImage(const SkImage *image, SkScalar left, SkScalar top)
Definition: SkCanvas.h:1528
void drawCircle(SkScalar cx, SkScalar cy, SkScalar radius, const SkPaint &paint)
Definition: SkCanvas.cpp:2707
SkCanvas * getCanvas()
Definition: SkSurface.cpp:82
sk_sp< SkImage > makeImageSnapshot()
Definition: SkSurface.cpp:90
Definition: Slide.h:29
virtual SkISize getDimensions() const
Definition: Slide.h:35
virtual void draw(SkCanvas *canvas)=0
T * get() const
Definition: SkRefCnt.h:303
void reset(T *ptr=nullptr)
Definition: SkRefCnt.h:310
Protected isProtected() const
Definition: RecorderPriv.h:52
DlColor color
const uint8_t uint32_t uint32_t GError ** error
constexpr int kSize
SK_API sk_sp< SkSurface > WrapAndroidHardwareBuffer(skgpu::graphite::Recorder *recorder, AHardwareBuffer *hardwareBuffer, sk_sp< SkColorSpace > colorSpace, const SkSurfaceProps *surfaceProps, BufferReleaseProc=nullptr, ReleaseContext=nullptr, bool fromWindow=false)
SK_API sk_sp< SkSurface > RenderTarget(GrRecordingContext *context, skgpu::Budgeted budgeted, const SkImageInfo &imageInfo, int sampleCount, GrSurfaceOrigin surfaceOrigin, const SkSurfaceProps *surfaceProps, bool shouldCreateWithMips=false, bool isProtected=false)
void draw_checkerboard(SkCanvas *canvas, SkColor c1, SkColor c2, int size)
Definition: ToolUtils.cpp:174
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
int32_t height
int32_t width
Definition: SkSize.h:16
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)