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