blob: e8655389f016e99ae87ee3ea2182c219b3279a8a [file] [log] [blame]
Zepeng Hu94007012020-07-22 14:37:46 +00001/*
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"
Zepeng Hu94007012020-07-22 14:37:46 +00009#include "include/core/SkPaint.h"
10#include "include/core/SkSurface.h"
Zepeng Hu94007012020-07-22 14:37:46 +000011#include "include/gpu/GrDirectContext.h"
Kevin Lubick5c93acf2023-05-09 12:11:43 -040012#include "include/gpu/ganesh/SkSurfaceGanesh.h"
Kevin Lubick0bff57e2023-06-09 14:29:17 -040013#include "include/private/chromium/GrDeferredDisplayList.h"
14#include "include/private/chromium/GrDeferredDisplayListRecorder.h"
15#include "include/private/chromium/GrSurfaceCharacterization.h"
Robert Phillips59ba27b2022-04-12 09:59:38 -040016#include "include/private/gpu/ganesh/GrTypesPriv.h"
Greg Daniel719239c2022-04-07 11:20:24 -040017#include "src/gpu/ganesh/GrShaderCaps.h"
Zepeng Hu94007012020-07-22 14:37:46 +000018#include "tools/gpu/GrContextFactory.h"
19
20#include "fuzz/Fuzz.h"
21
22#include <tuple>
23
24/**
Kevin Lubick0bff57e2023-06-09 14:29:17 -040025 * The fuzzer aims to fuzz the use of GrDeferredDisplayList. It mainly consists of
Zepeng Hu94007012020-07-22 14:37:46 +000026 * three parts.
Kevin Lubick0bff57e2023-06-09 14:29:17 -040027 * 1. In create_surface_characterization, (make_characterization) Create GrSurfaceCharacterization
John Stilesba7c5252023-08-25 10:50:10 -040028 * by using GrDirectContext of ContextType::kGL as it can be applied on all platform, and
Zepeng Hu94007012020-07-22 14:37:46 +000029 * (make_surface) create a GPU backend surface of the same GrDirectContext
Kevin Lubick0bff57e2023-06-09 14:29:17 -040030 * 2. (make_ddl) Create GrDeferredDisplayListRecorder from the GrSurfaceCharacterization, and test
Zepeng Hu94007012020-07-22 14:37:46 +000031 * the recoder's corresponding canvas.
Kevin Lubick0bff57e2023-06-09 14:29:17 -040032 * 3. (make_ddl, draw_ddl) Create GrDeferredDisplayList from the SkDeferredDisplayRecorder and draw
Zepeng Hu94007012020-07-22 14:37:46 +000033 * the ddl on a GPU backend surface.
34 */
35
36static constexpr int kMaxWidth = 64;
37static constexpr int kMaxHeight = 64;
38static constexpr int kSampleCount = 1;
39
40static SkSurfaceProps gen_fuzzed_surface_props(Fuzz* fuzz) {
41 SkPixelGeometry pixel;
42 fuzz->nextEnum(&pixel, kBGR_V_SkPixelGeometry);
43 return SkSurfaceProps(0x0, pixel);
44}
45
46static 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
56static 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
Kevin Lubick0bff57e2023-06-09 14:29:17 -0400125static GrSurfaceCharacterization make_characterization(Fuzz* fuzz, GrDirectContext* dContext,
Zepeng Hu94007012020-07-22 14:37:46 +0000126 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
Kevin Lubick0bff57e2023-06-09 14:29:17 -0400145 GrSurfaceCharacterization c;
Zepeng Hu94007012020-07-22 14:37:46 +0000146 size_t maxResourceBytes = dContext->getResourceCacheLimit();
Kevin Lubickefdb8222023-12-04 17:44:11 +0000147 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);
Zepeng Hu94007012020-07-22 14:37:46 +0000157 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
Kevin Lubick0bff57e2023-06-09 14:29:17 -0400165static sk_sp<GrDeferredDisplayList> make_ddl(Fuzz* fuzz, GrDirectContext* dContext,
166 const GrSurfaceCharacterization& c) {
167 GrDeferredDisplayListRecorder r(c);
Zepeng Hu94007012020-07-22 14:37:46 +0000168 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
180static sk_sp<SkSurface> make_surface(Fuzz* fuzz, GrDirectContext* dContext, const SkImageInfo& ii,
181 GrSurfaceOrigin origin) {
Kevin Lubickecd3a2f2023-01-05 08:17:45 -0500182 skgpu::Budgeted budgeted;
183 fuzz->nextEnum(&budgeted, skgpu::Budgeted::kYes);
Zepeng Hu94007012020-07-22 14:37:46 +0000184 SkSurfaceProps surfaceProps = gen_fuzzed_surface_props(fuzz);
Kevin Lubick5c93acf2023-05-09 12:11:43 -0400185 auto surface =
186 SkSurfaces::RenderTarget(dContext, budgeted, ii, kSampleCount, origin, &surfaceProps);
Zepeng Hu94007012020-07-22 14:37:46 +0000187 return surface;
188}
189
Kevin Lubick0bff57e2023-06-09 14:29:17 -0400190static bool draw_ddl(sk_sp<SkSurface> surface, sk_sp<const GrDeferredDisplayList> ddl) {
John Stiles04a9f722023-10-19 11:46:34 -0400191 return skgpu::ganesh::DrawDDL(std::move(surface), std::move(ddl));
Zepeng Hu94007012020-07-22 14:37:46 +0000192}
193
Kevin Lubick0bff57e2023-06-09 14:29:17 -0400194using SurfaceAndChar = std::tuple<sk_sp<SkSurface>, GrSurfaceCharacterization>;
Zepeng Hu94007012020-07-22 14:37:46 +0000195static SurfaceAndChar create_surface_and_characterization(Fuzz* fuzz, GrDirectContext* dContext,
196 SkColorType surfaceType,
197 GrSurfaceOrigin origin) {
198 SkImageInfo ii = gen_fuzzed_imageinfo(fuzz, surfaceType);
Kevin Lubick0bff57e2023-06-09 14:29:17 -0400199 GrSurfaceCharacterization c = make_characterization(fuzz, dContext, ii, surfaceType, origin);
Zepeng Hu94007012020-07-22 14:37:46 +0000200 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
211DEF_FUZZ(CreateDDL, fuzz) {
212 SkColorType surfaceType;
213 GrSurfaceOrigin origin;
214 fuzz->nextEnum(&surfaceType, SkColorType::kLastEnum_SkColorType);
215 fuzz->nextEnum(&origin, GrSurfaceOrigin::kTopLeft_GrSurfaceOrigin);
Robert Phillips32df8f82020-07-31 13:21:07 -0400216
Zepeng Hu94007012020-07-22 14:37:46 +0000217 sk_gpu_test::GrContextFactory factory;
John Stilesba7c5252023-08-25 10:50:10 -0400218 auto ctxInfo = factory.getContextInfo(skgpu::ContextType::kGL);
Robert Phillips32df8f82020-07-31 13:21:07 -0400219
Zepeng Hu94007012020-07-22 14:37:46 +0000220 GrDirectContext* dContext = ctxInfo.directContext();
Robert Phillips32df8f82020-07-31 13:21:07 -0400221 if (!dContext) {
222 SkDebugf("Context creation failed");
223 return;
224 }
Zepeng Hu94007012020-07-22 14:37:46 +0000225
226 auto[surface, c] = create_surface_and_characterization(fuzz, dContext, surfaceType, origin);
227 if (!surface || !c.isValid()) {
228 return;
229 }
230
Kevin Lubick0bff57e2023-06-09 14:29:17 -0400231 sk_sp<GrDeferredDisplayList> ddl = make_ddl(fuzz, dContext, c);
Zepeng Hu94007012020-07-22 14:37:46 +0000232 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}