Coverage Report

Created: 2021-08-22 09:07

/src/skia/src/gpu/gl/GrGLRenderTarget.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2011 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 "src/gpu/gl/GrGLRenderTarget.h"
9
10
#include "include/core/SkTraceMemoryDump.h"
11
#include "include/gpu/GrDirectContext.h"
12
#include "src/gpu/GrBackendUtils.h"
13
#include "src/gpu/GrDirectContextPriv.h"
14
#include "src/gpu/GrGpuResourcePriv.h"
15
#include "src/gpu/GrResourceProvider.h"
16
#include "src/gpu/gl/GrGLGpu.h"
17
#include "src/gpu/gl/GrGLUtil.h"
18
19
#define GPUGL static_cast<GrGLGpu*>(this->getGpu())
20
0
#define GL_CALL(X) GR_GL_CALL(GPUGL->glInterface(), X)
21
22
// Because this class is virtually derived from GrSurface we must explicitly call its constructor.
23
// Constructor for wrapped render targets.
24
GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu,
25
                                   const SkISize& dimensions,
26
                                   GrGLFormat format,
27
                                   int sampleCount,
28
                                   const IDs& ids,
29
                                   sk_sp<GrGLAttachment> stencil)
30
        : GrSurface(gpu, dimensions, GrProtected::kNo)
31
0
        , INHERITED(gpu, dimensions, sampleCount, GrProtected::kNo, std::move(stencil)) {
32
0
    this->init(format, ids);
33
0
    this->setFlags(gpu->glCaps(), ids);
34
0
    this->registerWithCacheWrapped(GrWrapCacheable::kNo);
35
0
}
Unexecuted instantiation: GrGLRenderTarget::GrGLRenderTarget(GrGLGpu*, SkISize const&, GrGLFormat, int, GrGLRenderTarget::IDs const&, sk_sp<GrGLAttachment>)
Unexecuted instantiation: GrGLRenderTarget::GrGLRenderTarget(GrGLGpu*, SkISize const&, GrGLFormat, int, GrGLRenderTarget::IDs const&, sk_sp<GrGLAttachment>)
36
37
GrGLRenderTarget::GrGLRenderTarget(GrGLGpu* gpu,
38
                                   const SkISize& dimensions,
39
                                   GrGLFormat format,
40
                                   int sampleCount,
41
                                   const IDs& ids)
42
        : GrSurface(gpu, dimensions, GrProtected::kNo)
43
0
        , INHERITED(gpu, dimensions, sampleCount, GrProtected::kNo) {
44
0
    this->init(format, ids);
45
0
    this->setFlags(gpu->glCaps(), ids);
46
0
}
Unexecuted instantiation: GrGLRenderTarget::GrGLRenderTarget(GrGLGpu*, SkISize const&, GrGLFormat, int, GrGLRenderTarget::IDs const&)
Unexecuted instantiation: GrGLRenderTarget::GrGLRenderTarget(GrGLGpu*, SkISize const&, GrGLFormat, int, GrGLRenderTarget::IDs const&)
47
48
0
inline void GrGLRenderTarget::setFlags(const GrGLCaps& glCaps, const IDs& idDesc) {
49
0
    if ((fMultisampleFBOID | fSingleSampleFBOID) == 0) {
50
0
        this->setGLRTFBOIDIs0();
51
0
    }
52
0
}
53
54
0
void GrGLRenderTarget::init(GrGLFormat format, const IDs& idDesc) {
55
0
    fMultisampleFBOID = idDesc.fMultisampleFBOID;
56
0
    fSingleSampleFBOID = idDesc.fSingleSampleFBOID;
57
0
    fMSColorRenderbufferID = idDesc.fMSColorRenderbufferID;
58
0
    fRTFBOOwnership = idDesc.fRTFBOOwnership;
59
0
    fRTFormat = format;
60
0
    fTotalMemorySamplesPerPixel = idDesc.fTotalMemorySamplesPerPixel;
61
0
}
62
63
0
GrGLFormat stencil_bits_to_format(int stencilBits) {
64
0
    SkASSERT(stencilBits);
65
0
    switch (stencilBits) {
66
0
        case 8:
67
            // We pick the packed format here so when we query total size we are at least not
68
            // underestimating the total size of the stencil buffer. However, in reality this
69
            // rarely matters since we usually don't care about the size of wrapped objects.
70
0
            return GrGLFormat::kDEPTH24_STENCIL8;
71
0
        case 16:
72
0
            return GrGLFormat::kSTENCIL_INDEX16;
73
0
        default:
74
0
            SkASSERT(false);
75
0
            return GrGLFormat::kUnknown;
76
0
    }
77
0
}
Unexecuted instantiation: stencil_bits_to_format(int)
Unexecuted instantiation: stencil_bits_to_format(int)
78
79
sk_sp<GrGLRenderTarget> GrGLRenderTarget::MakeWrapped(GrGLGpu* gpu,
80
                                                      const SkISize& dimensions,
81
                                                      GrGLFormat format,
82
                                                      int sampleCount,
83
                                                      const IDs& idDesc,
84
0
                                                      int stencilBits) {
85
0
    sk_sp<GrGLAttachment> sb;
86
0
    if (stencilBits) {
87
        // We pick a "fake" actual format that matches the number of stencil bits. When wrapping
88
        // an FBO with some number of stencil bits all we care about in the future is that we have
89
        // a format with the same number of stencil bits. We don't even directly use the format or
90
        // any other properties. Thus it is fine for us to just assign an arbitrary format that
91
        // matches the stencil bit count.
92
0
        GrGLFormat sFmt = stencil_bits_to_format(stencilBits);
93
94
        // We don't have the actual renderbufferID but we need to make an attachment for the stencil
95
        // so we just set it to an invalid value of 0 to make sure we don't explicitly use it or try
96
        // and delete it.
97
0
        sb = GrGLAttachment::MakeWrappedRenderBuffer(gpu,
98
0
                                                     /*renderbufferID=*/0,
99
0
                                                     dimensions,
100
0
                                                     GrAttachment::UsageFlags::kStencilAttachment,
101
0
                                                     sampleCount,
102
0
                                                     sFmt);
103
0
    }
104
0
    return sk_sp<GrGLRenderTarget>(
105
0
            new GrGLRenderTarget(gpu, dimensions, format, sampleCount, idDesc, std::move(sb)));
106
0
}
107
108
0
GrBackendRenderTarget GrGLRenderTarget::getBackendRenderTarget() const {
109
0
    bool useMultisampleFBO = (this->numSamples() > 1);
110
0
    GrGLFramebufferInfo fbi;
111
0
    fbi.fFBOID = (useMultisampleFBO) ? fMultisampleFBOID : fSingleSampleFBOID;
112
0
    fbi.fFormat = GrGLFormatToEnum(this->format());
113
0
    int numStencilBits = 0;
114
0
    if (GrAttachment* stencil = this->getStencilAttachment(useMultisampleFBO)) {
115
0
        numStencilBits = GrBackendFormatStencilBits(stencil->backendFormat());
116
0
    }
117
118
0
    return GrBackendRenderTarget(
119
0
            this->width(), this->height(), this->numSamples(), numStencilBits, fbi);
120
0
}
121
122
0
GrBackendFormat GrGLRenderTarget::backendFormat() const {
123
    // We should never have a GrGLRenderTarget (even a textureable one with a target that is not
124
    // texture 2D.
125
0
    return GrBackendFormat::MakeGL(GrGLFormatToEnum(fRTFormat), GR_GL_TEXTURE_2D);
126
0
}
127
128
0
size_t GrGLRenderTarget::onGpuMemorySize() const {
129
0
    return GrSurface::ComputeSize(this->backendFormat(), this->dimensions(),
130
0
                                  fTotalMemorySamplesPerPixel, GrMipmapped::kNo);
131
0
}
132
133
0
bool GrGLRenderTarget::completeStencilAttachment(GrAttachment* stencil, bool useMultisampleFBO) {
134
0
    GrGLGpu* gpu = this->getGLGpu();
135
0
    const GrGLInterface* interface = gpu->glInterface();
136
137
0
    if (this->numSamples() == 1 && useMultisampleFBO) {
138
        // We will be rendering to the dynamic msaa fbo. Make sure to initialize it first.
139
0
        if (!this->ensureDynamicMSAAAttachment()) {
140
0
            return false;
141
0
        }
142
0
    }
143
144
0
    GrGLuint stencilFBOID = (useMultisampleFBO) ? fMultisampleFBOID : fSingleSampleFBOID;
145
0
    gpu->bindFramebuffer(GR_GL_FRAMEBUFFER, stencilFBOID);
146
147
0
    if (nullptr == stencil) {
148
0
        GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
149
0
                                                      GR_GL_STENCIL_ATTACHMENT,
150
0
                                                      GR_GL_RENDERBUFFER, 0));
151
0
        GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
152
0
                                                      GR_GL_DEPTH_ATTACHMENT,
153
0
                                                      GR_GL_RENDERBUFFER, 0));
154
0
    } else {
155
0
        const GrGLAttachment* glStencil = static_cast<const GrGLAttachment*>(stencil);
156
0
        GrGLuint rb = glStencil->renderbufferID();
157
0
        GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
158
0
                                                      GR_GL_STENCIL_ATTACHMENT,
159
0
                                                      GR_GL_RENDERBUFFER, rb));
160
0
        if (GrGLFormatIsPackedDepthStencil(glStencil->format())) {
161
0
            GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
162
0
                                                          GR_GL_DEPTH_ATTACHMENT,
163
0
                                                          GR_GL_RENDERBUFFER, rb));
164
0
        } else {
165
0
            GR_GL_CALL(interface, FramebufferRenderbuffer(GR_GL_FRAMEBUFFER,
166
0
                                                          GR_GL_DEPTH_ATTACHMENT,
167
0
                                                          GR_GL_RENDERBUFFER, 0));
168
0
        }
169
0
    }
170
171
#ifdef SK_DEBUG
172
0
    if (!gpu->glCaps().skipErrorChecks()) {
173
0
        GrGLenum status;
174
0
        GR_GL_CALL_RET(interface, status, CheckFramebufferStatus(GR_GL_FRAMEBUFFER));
175
0
        if (status != GR_GL_FRAMEBUFFER_COMPLETE) {
176
            // This can fail if the context has been asynchronously abandoned (see skbug.com/5200).
177
0
            return false;
178
0
        }
179
0
    }
180
#endif
181
182
0
    return true;
183
0
}
Unexecuted instantiation: GrGLRenderTarget::completeStencilAttachment(GrAttachment*, bool)
Unexecuted instantiation: GrGLRenderTarget::completeStencilAttachment(GrAttachment*, bool)
184
185
0
bool GrGLRenderTarget::ensureDynamicMSAAAttachment() {
186
0
    SkASSERT(this->numSamples() == 1);
187
0
    if (fMultisampleFBOID) {
188
0
        return true;
189
0
    }
190
0
    SkASSERT(!fDynamicMSAAAttachment);
191
192
0
    GrResourceProvider* resourceProvider = this->getContext()->priv().resourceProvider();
193
0
    const GrCaps& caps = *this->getGpu()->caps();
194
195
0
    int internalSampleCount = caps.internalMultisampleCount(this->backendFormat());
196
0
    if (internalSampleCount <= 1) {
197
0
        return false;
198
0
    }
199
200
0
    GL_CALL(GenFramebuffers(1, &fMultisampleFBOID));
201
0
    if (!fMultisampleFBOID) {
202
0
        return false;
203
0
    }
204
205
0
    this->getGLGpu()->bindFramebuffer(GR_GL_FRAMEBUFFER, fMultisampleFBOID);
206
207
0
    if (resourceProvider->caps()->msaaResolvesAutomatically()) {
208
0
        if (GrGLTexture* glTex = static_cast<GrGLTexture*>(this->asTexture())) {
209
0
            GL_CALL(FramebufferTexture2DMultisample(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0,
210
0
                                                    glTex->target(), glTex->textureID(),
211
0
                                                    0 /*mipMapLevel*/, internalSampleCount));
212
0
            return true;
213
0
        }
214
0
    }
215
216
0
    fDynamicMSAAAttachment.reset(
217
0
            static_cast<GrGLAttachment*>(resourceProvider->getDiscardableMSAAAttachment(
218
0
                    this->dimensions(), this->backendFormat(), internalSampleCount,
219
0
                    GrProtected(this->isProtected())).release()));
220
0
    if (!fDynamicMSAAAttachment) {
221
0
        return false;
222
0
    }
223
224
0
    GL_CALL(FramebufferRenderbuffer(GR_GL_FRAMEBUFFER, GR_GL_COLOR_ATTACHMENT0, GR_GL_RENDERBUFFER,
225
0
                                    fDynamicMSAAAttachment->renderbufferID()));
226
0
    return true;
227
0
}
Unexecuted instantiation: GrGLRenderTarget::ensureDynamicMSAAAttachment()
Unexecuted instantiation: GrGLRenderTarget::ensureDynamicMSAAAttachment()
228
229
0
void GrGLRenderTarget::onRelease() {
230
0
    if (GrBackendObjectOwnership::kBorrowed != fRTFBOOwnership) {
231
0
        GrGLGpu* gpu = this->getGLGpu();
232
0
        if (fSingleSampleFBOID) {
233
0
            SkASSERT(fSingleSampleFBOID != fMultisampleFBOID);
234
0
            gpu->deleteFramebuffer(fSingleSampleFBOID);
235
0
        }
236
0
        if (fMultisampleFBOID) {
237
0
            SkASSERT(fMultisampleFBOID != fSingleSampleFBOID);
238
0
            gpu->deleteFramebuffer(fMultisampleFBOID);
239
0
        }
240
0
        if (fMSColorRenderbufferID) {
241
0
            GL_CALL(DeleteRenderbuffers(1, &fMSColorRenderbufferID));
242
0
        }
243
0
    }
244
0
    fMultisampleFBOID       = 0;
245
0
    fSingleSampleFBOID      = 0;
246
0
    fMSColorRenderbufferID  = 0;
247
0
    INHERITED::onRelease();
248
0
}
Unexecuted instantiation: GrGLRenderTarget::onRelease()
Unexecuted instantiation: GrGLRenderTarget::onRelease()
249
250
0
void GrGLRenderTarget::onAbandon() {
251
0
    fMultisampleFBOID       = 0;
252
0
    fSingleSampleFBOID      = 0;
253
0
    fMSColorRenderbufferID  = 0;
254
0
    INHERITED::onAbandon();
255
0
}
256
257
0
GrGLGpu* GrGLRenderTarget::getGLGpu() const {
258
0
    SkASSERT(!this->wasDestroyed());
259
0
    return static_cast<GrGLGpu*>(this->getGpu());
260
0
}
Unexecuted instantiation: GrGLRenderTarget::getGLGpu() const
Unexecuted instantiation: GrGLRenderTarget::getGLGpu() const
261
262
0
bool GrGLRenderTarget::canAttemptStencilAttachment(bool useMultisampleFBO) const {
263
    // This cap should have been handled at a higher level.
264
0
    SkASSERT(!this->getGpu()->getContext()->priv().caps()->avoidStencilBuffers());
265
    // Only modify the FBO's attachments if we have created the FBO. Public APIs do not currently
266
    // allow for borrowed FBO ownership, so we can safely assume that if an object is owned,
267
    // Skia created it.
268
0
    return this->fRTFBOOwnership == GrBackendObjectOwnership::kOwned ||
269
           // The dmsaa attachment is always owned and always supports adding stencil.
270
0
           (this->numSamples() == 1 && useMultisampleFBO);
271
0
}
Unexecuted instantiation: GrGLRenderTarget::canAttemptStencilAttachment(bool) const
Unexecuted instantiation: GrGLRenderTarget::canAttemptStencilAttachment(bool) const
272
273
0
void GrGLRenderTarget::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const {
274
    // Don't check this->fRefsWrappedObjects, as we might be the base of a GrGLTextureRenderTarget
275
    // which is multiply inherited from both ourselves and a texture. In these cases, one part
276
    // (texture, rt) may be wrapped, while the other is owned by Skia.
277
0
    bool refsWrappedRenderTargetObjects =
278
0
            this->fRTFBOOwnership == GrBackendObjectOwnership::kBorrowed;
279
0
    if (refsWrappedRenderTargetObjects && !traceMemoryDump->shouldDumpWrappedObjects()) {
280
0
        return;
281
0
    }
282
283
0
    int numSamplesNotInTexture = fTotalMemorySamplesPerPixel;
284
0
    if (this->asTexture()) {
285
0
        --numSamplesNotInTexture;  // GrGLTexture::dumpMemoryStatistics accounts for 1 sample.
286
0
    }
287
0
    if (numSamplesNotInTexture >= 1) {
288
0
        size_t size = GrSurface::ComputeSize(this->backendFormat(), this->dimensions(),
289
0
                                             numSamplesNotInTexture, GrMipmapped::kNo);
290
291
        // Due to this resource having both a texture and a renderbuffer component, dump as
292
        // skia/gpu_resources/resource_#/renderbuffer
293
0
        SkString resourceName = this->getResourceName();
294
0
        resourceName.append("/renderbuffer");
295
296
0
        this->dumpMemoryStatisticsPriv(traceMemoryDump, resourceName, "RenderTarget", size);
297
298
0
        SkString renderbuffer_id;
299
0
        renderbuffer_id.appendU32(fMSColorRenderbufferID);
300
0
        traceMemoryDump->setMemoryBacking(resourceName.c_str(), "gl_renderbuffer",
301
0
                                          renderbuffer_id.c_str());
302
0
    }
303
0
}