xref: /aosp_15_r20/external/skia/fuzz/FuzzCreateDDL.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2020 Google, LLC
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurface.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrDirectContext.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/SkSurfaceGanesh.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/chromium/GrDeferredDisplayList.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/chromium/GrDeferredDisplayListRecorder.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/chromium/GrSurfaceCharacterization.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/gpu/ganesh/GrTypesPriv.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrShaderCaps.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrUtil.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "tools/gpu/GrContextFactory.h"
20*c8dee2aaSAndroid Build Coastguard Worker 
21*c8dee2aaSAndroid Build Coastguard Worker #include "fuzz/Fuzz.h"
22*c8dee2aaSAndroid Build Coastguard Worker 
23*c8dee2aaSAndroid Build Coastguard Worker #include <tuple>
24*c8dee2aaSAndroid Build Coastguard Worker 
25*c8dee2aaSAndroid Build Coastguard Worker /**
26*c8dee2aaSAndroid Build Coastguard Worker  * The fuzzer aims to fuzz the use of GrDeferredDisplayList. It mainly consists of
27*c8dee2aaSAndroid Build Coastguard Worker  * three parts.
28*c8dee2aaSAndroid Build Coastguard Worker  * 1. In create_surface_characterization, (make_characterization) Create GrSurfaceCharacterization
29*c8dee2aaSAndroid Build Coastguard Worker  * by using GrDirectContext of ContextType::kGL as it can be applied on all platform, and
30*c8dee2aaSAndroid Build Coastguard Worker  * (make_surface) create a GPU backend surface of the same GrDirectContext
31*c8dee2aaSAndroid Build Coastguard Worker  * 2. (make_ddl) Create GrDeferredDisplayListRecorder from the GrSurfaceCharacterization, and test
32*c8dee2aaSAndroid Build Coastguard Worker  * the recoder's corresponding canvas.
33*c8dee2aaSAndroid Build Coastguard Worker  * 3. (make_ddl, draw_ddl) Create GrDeferredDisplayList from the SkDeferredDisplayRecorder and draw
34*c8dee2aaSAndroid Build Coastguard Worker  * the ddl on a GPU backend surface.
35*c8dee2aaSAndroid Build Coastguard Worker  */
36*c8dee2aaSAndroid Build Coastguard Worker 
37*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kMaxWidth = 64;
38*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kMaxHeight = 64;
39*c8dee2aaSAndroid Build Coastguard Worker static constexpr int kSampleCount = 1;
40*c8dee2aaSAndroid Build Coastguard Worker 
gen_fuzzed_surface_props(Fuzz * fuzz)41*c8dee2aaSAndroid Build Coastguard Worker static SkSurfaceProps gen_fuzzed_surface_props(Fuzz* fuzz) {
42*c8dee2aaSAndroid Build Coastguard Worker     SkPixelGeometry pixel;
43*c8dee2aaSAndroid Build Coastguard Worker     fuzz->nextEnum(&pixel, kBGR_V_SkPixelGeometry);
44*c8dee2aaSAndroid Build Coastguard Worker     return SkSurfaceProps(0x0, pixel);
45*c8dee2aaSAndroid Build Coastguard Worker }
46*c8dee2aaSAndroid Build Coastguard Worker 
gen_fuzzed_skpaint(Fuzz * fuzz)47*c8dee2aaSAndroid Build Coastguard Worker static SkPaint gen_fuzzed_skpaint(Fuzz* fuzz) {
48*c8dee2aaSAndroid Build Coastguard Worker     float R, G, B, Alpha;
49*c8dee2aaSAndroid Build Coastguard Worker     fuzz->nextRange(&R, -1, 2);
50*c8dee2aaSAndroid Build Coastguard Worker     fuzz->nextRange(&G, -1, 2);
51*c8dee2aaSAndroid Build Coastguard Worker     fuzz->nextRange(&B, -1, 2);
52*c8dee2aaSAndroid Build Coastguard Worker     fuzz->nextRange(&Alpha, 0, 1);
53*c8dee2aaSAndroid Build Coastguard Worker     SkColor4f color = {R, G, B, Alpha};
54*c8dee2aaSAndroid Build Coastguard Worker     return SkPaint(color);
55*c8dee2aaSAndroid Build Coastguard Worker }
56*c8dee2aaSAndroid Build Coastguard Worker 
gen_fuzzed_imageinfo(Fuzz * fuzz,SkColorType surfaceType)57*c8dee2aaSAndroid Build Coastguard Worker static SkImageInfo gen_fuzzed_imageinfo(Fuzz* fuzz, SkColorType surfaceType) {
58*c8dee2aaSAndroid Build Coastguard Worker     int width, height;
59*c8dee2aaSAndroid Build Coastguard Worker     fuzz->nextRange(&width, 1, kMaxWidth);
60*c8dee2aaSAndroid Build Coastguard Worker     fuzz->nextRange(&height, 1, kMaxHeight);
61*c8dee2aaSAndroid Build Coastguard Worker     SkAlphaType alphaType;
62*c8dee2aaSAndroid Build Coastguard Worker     fuzz->nextEnum(&alphaType, SkAlphaType::kLastEnum_SkAlphaType);
63*c8dee2aaSAndroid Build Coastguard Worker     skcms_TransferFunction skcmsFn;
64*c8dee2aaSAndroid Build Coastguard Worker     uint8_t skcms;
65*c8dee2aaSAndroid Build Coastguard Worker     fuzz->nextRange(&skcms, 0, 5);
66*c8dee2aaSAndroid Build Coastguard Worker     switch (skcms) {
67*c8dee2aaSAndroid Build Coastguard Worker         case 0: {
68*c8dee2aaSAndroid Build Coastguard Worker             skcmsFn = SkNamedTransferFn::kSRGB;
69*c8dee2aaSAndroid Build Coastguard Worker             break;
70*c8dee2aaSAndroid Build Coastguard Worker         }
71*c8dee2aaSAndroid Build Coastguard Worker         case 1: {
72*c8dee2aaSAndroid Build Coastguard Worker             skcmsFn = SkNamedTransferFn::k2Dot2;
73*c8dee2aaSAndroid Build Coastguard Worker             break;
74*c8dee2aaSAndroid Build Coastguard Worker         }
75*c8dee2aaSAndroid Build Coastguard Worker         case 2: {
76*c8dee2aaSAndroid Build Coastguard Worker             skcmsFn = SkNamedTransferFn::kHLG;
77*c8dee2aaSAndroid Build Coastguard Worker             break;
78*c8dee2aaSAndroid Build Coastguard Worker         }
79*c8dee2aaSAndroid Build Coastguard Worker         case 3: {
80*c8dee2aaSAndroid Build Coastguard Worker             skcmsFn = SkNamedTransferFn::kLinear;
81*c8dee2aaSAndroid Build Coastguard Worker             break;
82*c8dee2aaSAndroid Build Coastguard Worker         }
83*c8dee2aaSAndroid Build Coastguard Worker         case 4: {
84*c8dee2aaSAndroid Build Coastguard Worker             skcmsFn = SkNamedTransferFn::kPQ;
85*c8dee2aaSAndroid Build Coastguard Worker             break;
86*c8dee2aaSAndroid Build Coastguard Worker         }
87*c8dee2aaSAndroid Build Coastguard Worker         case 5: {
88*c8dee2aaSAndroid Build Coastguard Worker             skcmsFn = SkNamedTransferFn::kRec2020;
89*c8dee2aaSAndroid Build Coastguard Worker             break;
90*c8dee2aaSAndroid Build Coastguard Worker         }
91*c8dee2aaSAndroid Build Coastguard Worker         default:
92*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(false);
93*c8dee2aaSAndroid Build Coastguard Worker             break;
94*c8dee2aaSAndroid Build Coastguard Worker     }
95*c8dee2aaSAndroid Build Coastguard Worker     skcms_Matrix3x3 skcmsMat;
96*c8dee2aaSAndroid Build Coastguard Worker     fuzz->nextRange(&skcms, 0, 4);
97*c8dee2aaSAndroid Build Coastguard Worker     switch (skcms) {
98*c8dee2aaSAndroid Build Coastguard Worker         case 0: {
99*c8dee2aaSAndroid Build Coastguard Worker             skcmsMat = SkNamedGamut::kAdobeRGB;
100*c8dee2aaSAndroid Build Coastguard Worker             break;
101*c8dee2aaSAndroid Build Coastguard Worker         }
102*c8dee2aaSAndroid Build Coastguard Worker         case 1: {
103*c8dee2aaSAndroid Build Coastguard Worker             skcmsMat = SkNamedGamut::kDisplayP3;
104*c8dee2aaSAndroid Build Coastguard Worker             break;
105*c8dee2aaSAndroid Build Coastguard Worker         }
106*c8dee2aaSAndroid Build Coastguard Worker         case 2: {
107*c8dee2aaSAndroid Build Coastguard Worker             skcmsMat = SkNamedGamut::kRec2020;
108*c8dee2aaSAndroid Build Coastguard Worker             break;
109*c8dee2aaSAndroid Build Coastguard Worker         }
110*c8dee2aaSAndroid Build Coastguard Worker         case 3: {
111*c8dee2aaSAndroid Build Coastguard Worker             skcmsMat = SkNamedGamut::kSRGB;
112*c8dee2aaSAndroid Build Coastguard Worker             break;
113*c8dee2aaSAndroid Build Coastguard Worker         }
114*c8dee2aaSAndroid Build Coastguard Worker         case 4: {
115*c8dee2aaSAndroid Build Coastguard Worker             skcmsMat = SkNamedGamut::kXYZ;
116*c8dee2aaSAndroid Build Coastguard Worker             break;
117*c8dee2aaSAndroid Build Coastguard Worker         }
118*c8dee2aaSAndroid Build Coastguard Worker         default:
119*c8dee2aaSAndroid Build Coastguard Worker             SkASSERT(false);
120*c8dee2aaSAndroid Build Coastguard Worker             break;
121*c8dee2aaSAndroid Build Coastguard Worker     }
122*c8dee2aaSAndroid Build Coastguard Worker     return SkImageInfo::Make(width, height, surfaceType, alphaType,
123*c8dee2aaSAndroid Build Coastguard Worker                              SkColorSpace::MakeRGB(skcmsFn, skcmsMat));
124*c8dee2aaSAndroid Build Coastguard Worker }
125*c8dee2aaSAndroid Build Coastguard Worker 
make_characterization(Fuzz * fuzz,GrDirectContext * dContext,SkImageInfo & ii,SkColorType surfaceType,GrSurfaceOrigin origin)126*c8dee2aaSAndroid Build Coastguard Worker static GrSurfaceCharacterization make_characterization(Fuzz* fuzz, GrDirectContext* dContext,
127*c8dee2aaSAndroid Build Coastguard Worker                                                        SkImageInfo& ii, SkColorType surfaceType,
128*c8dee2aaSAndroid Build Coastguard Worker                                                        GrSurfaceOrigin origin) {
129*c8dee2aaSAndroid Build Coastguard Worker     if (!dContext->colorTypeSupportedAsSurface(surfaceType)) {
130*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("Couldn't create backend texture in the backend %s",
131*c8dee2aaSAndroid Build Coastguard Worker                  GrBackendApiToStr(dContext->backend()));
132*c8dee2aaSAndroid Build Coastguard Worker         return {};
133*c8dee2aaSAndroid Build Coastguard Worker     }
134*c8dee2aaSAndroid Build Coastguard Worker 
135*c8dee2aaSAndroid Build Coastguard Worker     GrBackendFormat backendFormat = dContext->defaultBackendFormat(surfaceType,
136*c8dee2aaSAndroid Build Coastguard Worker                                                                    GrRenderable::kYes);
137*c8dee2aaSAndroid Build Coastguard Worker     if (!backendFormat.isValid()) {
138*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("Color Type is not supported in the backend %s",
139*c8dee2aaSAndroid Build Coastguard Worker                  GrBackendApiToStr(dContext->backend()));
140*c8dee2aaSAndroid Build Coastguard Worker         return {};
141*c8dee2aaSAndroid Build Coastguard Worker     }
142*c8dee2aaSAndroid Build Coastguard Worker     GrProtected protect = GrProtected::kNo;
143*c8dee2aaSAndroid Build Coastguard Worker #ifdef SK_VULKAN
144*c8dee2aaSAndroid Build Coastguard Worker     fuzz->nextEnum(&protect, GrProtected::kYes);
145*c8dee2aaSAndroid Build Coastguard Worker #endif
146*c8dee2aaSAndroid Build Coastguard Worker     GrSurfaceCharacterization c;
147*c8dee2aaSAndroid Build Coastguard Worker     size_t maxResourceBytes = dContext->getResourceCacheLimit();
148*c8dee2aaSAndroid Build Coastguard Worker     c = dContext->threadSafeProxy()->createCharacterization(maxResourceBytes,
149*c8dee2aaSAndroid Build Coastguard Worker                                                             ii,
150*c8dee2aaSAndroid Build Coastguard Worker                                                             backendFormat,
151*c8dee2aaSAndroid Build Coastguard Worker                                                             kSampleCount,
152*c8dee2aaSAndroid Build Coastguard Worker                                                             origin,
153*c8dee2aaSAndroid Build Coastguard Worker                                                             gen_fuzzed_surface_props(fuzz),
154*c8dee2aaSAndroid Build Coastguard Worker                                                             skgpu::Mipmapped::kYes,
155*c8dee2aaSAndroid Build Coastguard Worker                                                             false,
156*c8dee2aaSAndroid Build Coastguard Worker                                                             true,
157*c8dee2aaSAndroid Build Coastguard Worker                                                             protect);
158*c8dee2aaSAndroid Build Coastguard Worker     if (!c.isValid()) {
159*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("Could not create Characterization in the backend %s",
160*c8dee2aaSAndroid Build Coastguard Worker                  GrBackendApiToStr(dContext->backend()));
161*c8dee2aaSAndroid Build Coastguard Worker         return {};
162*c8dee2aaSAndroid Build Coastguard Worker     }
163*c8dee2aaSAndroid Build Coastguard Worker     return c;
164*c8dee2aaSAndroid Build Coastguard Worker }
165*c8dee2aaSAndroid Build Coastguard Worker 
make_ddl(Fuzz * fuzz,GrDirectContext * dContext,const GrSurfaceCharacterization & c)166*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<GrDeferredDisplayList> make_ddl(Fuzz* fuzz, GrDirectContext* dContext,
167*c8dee2aaSAndroid Build Coastguard Worker                                              const GrSurfaceCharacterization& c) {
168*c8dee2aaSAndroid Build Coastguard Worker     GrDeferredDisplayListRecorder r(c);
169*c8dee2aaSAndroid Build Coastguard Worker     SkCanvas* canvas = r.getCanvas();
170*c8dee2aaSAndroid Build Coastguard Worker     if (!canvas) {
171*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("Could not create canvas for backend %s", GrBackendApiToStr(dContext->backend()));
172*c8dee2aaSAndroid Build Coastguard Worker         return nullptr;
173*c8dee2aaSAndroid Build Coastguard Worker     }
174*c8dee2aaSAndroid Build Coastguard Worker     // For now we only draw a rect into the DDL. This will be scaled up to draw more varied content.
175*c8dee2aaSAndroid Build Coastguard Worker     SkRect tile;
176*c8dee2aaSAndroid Build Coastguard Worker     fuzz->next(&tile);
177*c8dee2aaSAndroid Build Coastguard Worker     canvas->drawRect(tile, gen_fuzzed_skpaint(fuzz));
178*c8dee2aaSAndroid Build Coastguard Worker     return r.detach();
179*c8dee2aaSAndroid Build Coastguard Worker }
180*c8dee2aaSAndroid Build Coastguard Worker 
make_surface(Fuzz * fuzz,GrDirectContext * dContext,const SkImageInfo & ii,GrSurfaceOrigin origin)181*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<SkSurface> make_surface(Fuzz* fuzz, GrDirectContext* dContext, const SkImageInfo& ii,
182*c8dee2aaSAndroid Build Coastguard Worker                                      GrSurfaceOrigin origin) {
183*c8dee2aaSAndroid Build Coastguard Worker     skgpu::Budgeted budgeted;
184*c8dee2aaSAndroid Build Coastguard Worker     fuzz->nextEnum(&budgeted, skgpu::Budgeted::kYes);
185*c8dee2aaSAndroid Build Coastguard Worker     SkSurfaceProps surfaceProps = gen_fuzzed_surface_props(fuzz);
186*c8dee2aaSAndroid Build Coastguard Worker     auto surface =
187*c8dee2aaSAndroid Build Coastguard Worker             SkSurfaces::RenderTarget(dContext, budgeted, ii, kSampleCount, origin, &surfaceProps);
188*c8dee2aaSAndroid Build Coastguard Worker     return surface;
189*c8dee2aaSAndroid Build Coastguard Worker }
190*c8dee2aaSAndroid Build Coastguard Worker 
draw_ddl(sk_sp<SkSurface> surface,sk_sp<const GrDeferredDisplayList> ddl)191*c8dee2aaSAndroid Build Coastguard Worker static bool draw_ddl(sk_sp<SkSurface> surface, sk_sp<const GrDeferredDisplayList> ddl) {
192*c8dee2aaSAndroid Build Coastguard Worker     return skgpu::ganesh::DrawDDL(std::move(surface), std::move(ddl));
193*c8dee2aaSAndroid Build Coastguard Worker }
194*c8dee2aaSAndroid Build Coastguard Worker 
195*c8dee2aaSAndroid Build Coastguard Worker using SurfaceAndChar = std::tuple<sk_sp<SkSurface>, GrSurfaceCharacterization>;
create_surface_and_characterization(Fuzz * fuzz,GrDirectContext * dContext,SkColorType surfaceType,GrSurfaceOrigin origin)196*c8dee2aaSAndroid Build Coastguard Worker static SurfaceAndChar create_surface_and_characterization(Fuzz* fuzz, GrDirectContext* dContext,
197*c8dee2aaSAndroid Build Coastguard Worker                                                           SkColorType surfaceType,
198*c8dee2aaSAndroid Build Coastguard Worker                                                           GrSurfaceOrigin origin) {
199*c8dee2aaSAndroid Build Coastguard Worker     SkImageInfo ii = gen_fuzzed_imageinfo(fuzz, surfaceType);
200*c8dee2aaSAndroid Build Coastguard Worker     GrSurfaceCharacterization c = make_characterization(fuzz, dContext, ii, surfaceType, origin);
201*c8dee2aaSAndroid Build Coastguard Worker     if (!c.isValid()) {
202*c8dee2aaSAndroid Build Coastguard Worker        return {};
203*c8dee2aaSAndroid Build Coastguard Worker     }
204*c8dee2aaSAndroid Build Coastguard Worker 
205*c8dee2aaSAndroid Build Coastguard Worker     auto surface = make_surface(fuzz, dContext, ii, origin);
206*c8dee2aaSAndroid Build Coastguard Worker     if (!surface) {
207*c8dee2aaSAndroid Build Coastguard Worker         return {};
208*c8dee2aaSAndroid Build Coastguard Worker     }
209*c8dee2aaSAndroid Build Coastguard Worker     return {surface, c};
210*c8dee2aaSAndroid Build Coastguard Worker }
211*c8dee2aaSAndroid Build Coastguard Worker 
DEF_FUZZ(CreateDDL,fuzz)212*c8dee2aaSAndroid Build Coastguard Worker DEF_FUZZ(CreateDDL, fuzz) {
213*c8dee2aaSAndroid Build Coastguard Worker     SkColorType surfaceType;
214*c8dee2aaSAndroid Build Coastguard Worker     GrSurfaceOrigin origin;
215*c8dee2aaSAndroid Build Coastguard Worker     fuzz->nextEnum(&surfaceType, SkColorType::kLastEnum_SkColorType);
216*c8dee2aaSAndroid Build Coastguard Worker     fuzz->nextEnum(&origin, GrSurfaceOrigin::kTopLeft_GrSurfaceOrigin);
217*c8dee2aaSAndroid Build Coastguard Worker 
218*c8dee2aaSAndroid Build Coastguard Worker     sk_gpu_test::GrContextFactory factory;
219*c8dee2aaSAndroid Build Coastguard Worker     auto ctxInfo = factory.getContextInfo(skgpu::ContextType::kGL);
220*c8dee2aaSAndroid Build Coastguard Worker 
221*c8dee2aaSAndroid Build Coastguard Worker     GrDirectContext* dContext = ctxInfo.directContext();
222*c8dee2aaSAndroid Build Coastguard Worker     if (!dContext) {
223*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("Context creation failed");
224*c8dee2aaSAndroid Build Coastguard Worker         return;
225*c8dee2aaSAndroid Build Coastguard Worker     }
226*c8dee2aaSAndroid Build Coastguard Worker 
227*c8dee2aaSAndroid Build Coastguard Worker     auto[surface, c] = create_surface_and_characterization(fuzz, dContext, surfaceType, origin);
228*c8dee2aaSAndroid Build Coastguard Worker     if (!surface || !c.isValid()) {
229*c8dee2aaSAndroid Build Coastguard Worker         return;
230*c8dee2aaSAndroid Build Coastguard Worker     }
231*c8dee2aaSAndroid Build Coastguard Worker 
232*c8dee2aaSAndroid Build Coastguard Worker     sk_sp<GrDeferredDisplayList> ddl = make_ddl(fuzz, dContext, c);
233*c8dee2aaSAndroid Build Coastguard Worker     if (!ddl) {
234*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("Could not create ddl %s", GrBackendApiToStr(dContext->backend()));
235*c8dee2aaSAndroid Build Coastguard Worker         return;
236*c8dee2aaSAndroid Build Coastguard Worker     }
237*c8dee2aaSAndroid Build Coastguard Worker     if (!draw_ddl(std::move(surface), std::move(ddl))) {
238*c8dee2aaSAndroid Build Coastguard Worker         SkDebugf("Could not draw ddl in the backend");
239*c8dee2aaSAndroid Build Coastguard Worker     }
240*c8dee2aaSAndroid Build Coastguard Worker     return;
241*c8dee2aaSAndroid Build Coastguard Worker }
242