Coverage Report

Created: 2024-09-14 07:19

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