Coverage Report

Created: 2021-08-22 09:07

/src/skia/src/core/SkDeferredDisplayListRecorder.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2017 Google Inc.
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/SkDeferredDisplayListRecorder.h"
9
10
#include "include/core/SkDeferredDisplayList.h"
11
#include "include/core/SkSurface.h"
12
#include "include/core/SkSurfaceCharacterization.h"
13
#include "src/core/SkMessageBus.h"
14
15
#if !SK_SUPPORT_GPU
16
SkDeferredDisplayListRecorder::SkDeferredDisplayListRecorder(const SkSurfaceCharacterization&) {}
17
18
SkDeferredDisplayListRecorder::~SkDeferredDisplayListRecorder() {}
19
20
bool SkDeferredDisplayListRecorder::init() { return false; }
21
22
SkCanvas* SkDeferredDisplayListRecorder::getCanvas() { return nullptr; }
23
24
sk_sp<SkDeferredDisplayList> SkDeferredDisplayListRecorder::detach() { return nullptr; }
25
26
sk_sp<SkImage> SkDeferredDisplayListRecorder::makePromiseTexture(
27
        const GrBackendFormat& backendFormat,
28
        int width,
29
        int height,
30
        GrMipmapped mipMapped,
31
        GrSurfaceOrigin origin,
32
        SkColorType colorType,
33
        SkAlphaType alphaType,
34
        sk_sp<SkColorSpace> colorSpace,
35
        PromiseImageTextureFulfillProc textureFulfillProc,
36
        PromiseImageTextureReleaseProc textureReleaseProc,
37
        PromiseImageTextureContext textureContext) {
38
    return nullptr;
39
}
40
41
sk_sp<SkImage> SkDeferredDisplayListRecorder::makeYUVAPromiseTexture(
42
        const GrYUVABackendTextureInfo& yuvaBackendTextureInfo,
43
        sk_sp<SkColorSpace> imageColorSpace,
44
        PromiseImageTextureFulfillProc textureFulfillProc,
45
        PromiseImageTextureReleaseProc textureReleaseProc,
46
        PromiseImageTextureContext textureContexts[]) {
47
    return nullptr;
48
}
49
50
#else
51
52
#include "include/core/SkPromiseImageTexture.h"
53
#include "include/gpu/GrRecordingContext.h"
54
#include "include/gpu/GrYUVABackendTextures.h"
55
#include "src/gpu/GrProxyProvider.h"
56
#include "src/gpu/GrRecordingContextPriv.h"
57
#include "src/gpu/GrTexture.h"
58
#include "src/gpu/SkGr.h"
59
#include "src/image/SkImage_Gpu.h"
60
#include "src/image/SkImage_GpuYUVA.h"
61
#include "src/image/SkSurface_Gpu.h"
62
63
SkDeferredDisplayListRecorder::SkDeferredDisplayListRecorder(const SkSurfaceCharacterization& c)
64
0
        : fCharacterization(c) {
65
0
    if (fCharacterization.isValid()) {
66
0
        fContext = GrRecordingContextPriv::MakeDDL(fCharacterization.refContextInfo());
67
0
    }
68
0
}
69
70
0
SkDeferredDisplayListRecorder::~SkDeferredDisplayListRecorder() {
71
0
    if (fContext) {
72
0
        auto proxyProvider = fContext->priv().proxyProvider();
73
74
        // This allows the uniquely keyed proxies to keep their keys but removes their back
75
        // pointer to the about-to-be-deleted proxy provider. The proxies will use their
76
        // unique key to reattach to cached versions of themselves or to appropriately tag new
77
        // resources (if a cached version was not found). This system operates independent of
78
        // the replaying context's proxy provider (i.e., these uniquely keyed proxies will not
79
        // appear in the replaying proxy providers uniquely keyed proxy map). This should be fine
80
        // since no one else should be trying to reconnect to the orphaned proxies and orphaned
81
        // proxies from different DDLs that share the same key should simply reconnect to the
82
        // same cached resource.
83
0
        proxyProvider->orphanAllUniqueKeys();
84
0
    }
85
0
}
86
87
0
bool SkDeferredDisplayListRecorder::init() {
88
0
    SkASSERT(fContext);
89
0
    SkASSERT(!fTargetProxy);
90
0
    SkASSERT(!fLazyProxyData);
91
0
    SkASSERT(!fSurface);
92
93
0
    if (!fCharacterization.isValid()) {
94
0
        return false;
95
0
    }
96
97
0
    fLazyProxyData = sk_sp<SkDeferredDisplayList::LazyProxyData>(
98
0
                                                    new SkDeferredDisplayList::LazyProxyData);
99
100
0
    auto proxyProvider = fContext->priv().proxyProvider();
101
0
    const GrCaps* caps = fContext->priv().caps();
102
103
0
    bool usesGLFBO0 = fCharacterization.usesGLFBO0();
104
0
    if (usesGLFBO0) {
105
0
        if (GrBackendApi::kOpenGL != fContext->backend() ||
106
0
            fCharacterization.isTextureable()) {
107
0
            return false;
108
0
        }
109
0
    }
110
111
0
    bool vkRTSupportsInputAttachment = fCharacterization.vkRTSupportsInputAttachment();
112
0
    if (vkRTSupportsInputAttachment && GrBackendApi::kVulkan != fContext->backend()) {
113
0
        return false;
114
0
    }
115
116
0
    if (fCharacterization.vulkanSecondaryCBCompatible()) {
117
        // Because of the restrictive API allowed for a GrVkSecondaryCBDrawContext, we know ahead
118
        // of time that we don't be able to support certain parameter combinations. Specifically we
119
        // fail on usesGLFBO0 since we can't mix GL and Vulkan. We can't have a texturable object.
120
        // We can't use it as in input attachment since we don't control the render pass this will
121
        // be played into and thus can't force it to have an input attachment and the correct
122
        // dependencies. And finally the GrVkSecondaryCBDrawContext always assumes a top left
123
        // origin.
124
0
        if (usesGLFBO0 ||
125
0
            vkRTSupportsInputAttachment ||
126
0
            fCharacterization.isTextureable() ||
127
0
            fCharacterization.origin() == kBottomLeft_GrSurfaceOrigin) {
128
0
            return false;
129
0
        }
130
0
    }
131
132
0
    GrColorType grColorType = SkColorTypeToGrColorType(fCharacterization.colorType());
133
134
    // What we're doing here is we're creating a lazy proxy to back the SkSurface. The lazy
135
    // proxy, when instantiated, will use the GrRenderTarget that backs the SkSurface that the
136
    // DDL is being replayed into.
137
138
0
    GrInternalSurfaceFlags surfaceFlags = GrInternalSurfaceFlags::kNone;
139
0
    if (usesGLFBO0) {
140
0
        surfaceFlags |= GrInternalSurfaceFlags::kGLRTFBOIDIs0;
141
0
    } else if (fCharacterization.sampleCount() > 1 && !caps->msaaResolvesAutomatically() &&
142
0
               fCharacterization.isTextureable()) {
143
0
        surfaceFlags |= GrInternalSurfaceFlags::kRequiresManualMSAAResolve;
144
0
    }
145
146
0
    if (vkRTSupportsInputAttachment) {
147
0
        surfaceFlags |= GrInternalSurfaceFlags::kVkRTSupportsInputAttachment;
148
0
    }
149
150
    // FIXME: Why do we use GrMipmapped::kNo instead of SkSurfaceCharacterization::fIsMipMapped?
151
0
    static constexpr GrProxyProvider::TextureInfo kTextureInfo{GrMipmapped::kNo,
152
0
                                                               GrTextureType::k2D};
153
0
    const GrProxyProvider::TextureInfo* optionalTextureInfo = nullptr;
154
0
    if (fCharacterization.isTextureable()) {
155
0
        optionalTextureInfo = &kTextureInfo;
156
0
    }
157
158
0
    fTargetProxy = proxyProvider->createLazyRenderTargetProxy(
159
0
            [lazyProxyData = fLazyProxyData](GrResourceProvider* resourceProvider,
160
0
                                             const GrSurfaceProxy::LazySurfaceDesc&) {
161
                // The proxy backing the destination surface had better have been instantiated
162
                // prior to this one (i.e., the proxy backing the DDL's surface).
163
                // Fulfill this lazy proxy with the destination surface's GrRenderTarget.
164
0
                SkASSERT(lazyProxyData->fReplayDest->peekSurface());
165
0
                auto surface = sk_ref_sp<GrSurface>(lazyProxyData->fReplayDest->peekSurface());
166
0
                return GrSurfaceProxy::LazyCallbackResult(std::move(surface));
167
0
            },
168
0
            fCharacterization.backendFormat(),
169
0
            fCharacterization.dimensions(),
170
0
            fCharacterization.sampleCount(),
171
0
            surfaceFlags,
172
0
            optionalTextureInfo,
173
0
            GrMipmapStatus::kNotAllocated,
174
0
            SkBackingFit::kExact,
175
0
            SkBudgeted::kYes,
176
0
            fCharacterization.isProtected(),
177
0
            fCharacterization.vulkanSecondaryCBCompatible(),
178
0
            GrSurfaceProxy::UseAllocator::kYes);
179
180
0
    if (!fTargetProxy) {
181
0
        return false;
182
0
    }
183
0
    fTargetProxy->priv().setIsDDLTarget();
184
185
0
    auto device = fContext->priv().createDevice(grColorType,
186
0
                                                fTargetProxy,
187
0
                                                fCharacterization.refColorSpace(),
188
0
                                                fCharacterization.origin(),
189
0
                                                fCharacterization.surfaceProps(),
190
0
                                                skgpu::BaseDevice::kUninit_InitContents);
191
0
    if (!device) {
192
0
        return false;
193
0
    }
194
195
0
    fSurface = sk_make_sp<SkSurface_Gpu>(std::move(device));
196
0
    return SkToBool(fSurface.get());
197
0
}
198
199
0
SkCanvas* SkDeferredDisplayListRecorder::getCanvas() {
200
0
    if (!fContext) {
201
0
        return nullptr;
202
0
    }
203
204
0
    if (!fSurface && !this->init()) {
205
0
        return nullptr;
206
0
    }
207
208
0
    return fSurface->getCanvas();
209
0
}
210
211
0
sk_sp<SkDeferredDisplayList> SkDeferredDisplayListRecorder::detach() {
212
0
    if (!fContext || !fTargetProxy) {
213
0
        return nullptr;
214
0
    }
215
216
0
    if (fSurface) {
217
0
        SkCanvas* canvas = fSurface->getCanvas();
218
219
0
        canvas->restoreToCount(0);
220
0
    }
221
222
0
    auto ddl = sk_sp<SkDeferredDisplayList>(new SkDeferredDisplayList(fCharacterization,
223
0
                                                                      std::move(fTargetProxy),
224
0
                                                                      std::move(fLazyProxyData)));
225
226
0
    fContext->priv().moveRenderTasksToDDL(ddl.get());
227
228
    // We want a new lazy proxy target for each recorded DDL so force the (lazy proxy-backed)
229
    // SkSurface to be regenerated for each DDL.
230
0
    fSurface = nullptr;
231
0
    return ddl;
232
0
}
233
234
#ifndef SK_MAKE_PROMISE_TEXTURE_DISABLE_LEGACY_API
235
sk_sp<SkImage> SkDeferredDisplayListRecorder::makePromiseTexture(
236
        const GrBackendFormat& backendFormat,
237
        int width,
238
        int height,
239
        GrMipmapped mipMapped,
240
        GrSurfaceOrigin origin,
241
        SkColorType colorType,
242
        SkAlphaType alphaType,
243
        sk_sp<SkColorSpace> colorSpace,
244
        PromiseImageTextureFulfillProc textureFulfillProc,
245
        PromiseImageTextureReleaseProc textureReleaseProc,
246
0
        PromiseImageTextureContext textureContext) {
247
0
    if (!fContext) {
248
0
        return nullptr;
249
0
    }
250
0
    return SkImage::MakePromiseTexture(fContext->threadSafeProxy(),
251
0
                                       backendFormat,
252
0
                                       {width, height},
253
0
                                       mipMapped,
254
0
                                       origin,
255
0
                                       colorType,
256
0
                                       alphaType,
257
0
                                       std::move(colorSpace),
258
0
                                       textureFulfillProc,
259
0
                                       textureReleaseProc,
260
0
                                       textureContext);
261
0
}
262
263
sk_sp<SkImage> SkDeferredDisplayListRecorder::makeYUVAPromiseTexture(
264
        const GrYUVABackendTextureInfo& backendTextureInfo,
265
        sk_sp<SkColorSpace> imageColorSpace,
266
        PromiseImageTextureFulfillProc textureFulfillProc,
267
        PromiseImageTextureReleaseProc textureReleaseProc,
268
0
        PromiseImageTextureContext textureContexts[]) {
269
0
    if (!fContext) {
270
0
        return nullptr;
271
0
    }
272
0
    return SkImage::MakePromiseYUVATexture(fContext->threadSafeProxy(),
273
0
                                           backendTextureInfo,
274
0
                                           std::move(imageColorSpace),
275
0
                                           textureFulfillProc,
276
0
                                           textureReleaseProc,
277
0
                                           textureContexts);
278
0
}
279
#endif // !SK_MAKE_PROMISE_TEXTURE_DISABLE_LEGACY_API
280
281
#endif