1/*
2 * Copyright 2018 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/ccpr/GrCCClipPath.h"
9
10#include "src/gpu/GrOnFlushResourceProvider.h"
11#include "src/gpu/GrProxyProvider.h"
12#include "src/gpu/GrRenderTarget.h"
13#include "src/gpu/GrTexture.h"
14#include "src/gpu/ccpr/GrCCPerFlushResources.h"
15
16void GrCCClipPath::init(
17 const SkPath& deviceSpacePath, const SkIRect& accessRect,
18 GrCCAtlas::CoverageType atlasCoverageType, const GrCaps& caps) {
19 SkASSERT(!this->isInitialized());
20
21 fAtlasLazyProxy = GrCCAtlas::MakeLazyAtlasProxy(
22 [this](GrResourceProvider* resourceProvider, const GrBackendFormat& format,
23 int sampleCount) {
24 SkASSERT(fHasAtlas);
25 SkASSERT(!fHasAtlasTransform);
26
27 GrTextureProxy* textureProxy = fAtlas ? fAtlas->textureProxy() : nullptr;
28
29 if (!textureProxy || !textureProxy->instantiate(resourceProvider)) {
30 fAtlasScale = fAtlasTranslate = {0, 0};
31 SkDEBUGCODE(fHasAtlasTransform = true);
32 return GrSurfaceProxy::LazyCallbackResult();
33 }
34
35 sk_sp<GrTexture> texture = sk_ref_sp(textureProxy->peekTexture());
36 SkASSERT(texture);
37 SkASSERT(texture->backendFormat() == format);
38 SkASSERT(texture->asRenderTarget()->numSamples() == sampleCount);
39
40 fAtlasScale = {1.f / texture->width(), 1.f / texture->height()};
41 fAtlasTranslate.set(fDevToAtlasOffset.fX * fAtlasScale.x(),
42 fDevToAtlasOffset.fY * fAtlasScale.y());
43 SkDEBUGCODE(fHasAtlasTransform = true);
44
45 // We use LazyInstantiationKeyMode::kUnsynced here because CCPR clip masks are never
46 // cached, and the clip FP proxies need to ignore any unique keys that atlas
47 // textures use for path mask caching.
48 return GrSurfaceProxy::LazyCallbackResult(
49 std::move(texture), true,
50 GrSurfaceProxy::LazyInstantiationKeyMode::kUnsynced);
51 },
52 atlasCoverageType, caps, GrSurfaceProxy::UseAllocator::kYes);
53
54 fDeviceSpacePath = deviceSpacePath;
55 fDeviceSpacePath.getBounds().roundOut(&fPathDevIBounds);
56 fAccessRect = accessRect;
57}
58
59void GrCCClipPath::accountForOwnPath(GrCCPerFlushResourceSpecs* specs) const {
60 SkASSERT(this->isInitialized());
61
62 ++specs->fNumClipPaths;
63 specs->fRenderedPathStats[GrCCPerFlushResourceSpecs::kFillIdx].statPath(fDeviceSpacePath);
64
65 SkIRect ibounds;
66 if (ibounds.intersect(fAccessRect, fPathDevIBounds)) {
67 specs->fRenderedAtlasSpecs.accountForSpace(ibounds.width(), ibounds.height());
68 }
69}
70
71void GrCCClipPath::renderPathInAtlas(GrCCPerFlushResources* resources,
72 GrOnFlushResourceProvider* onFlushRP) {
73 SkASSERT(this->isInitialized());
74 SkASSERT(!fHasAtlas);
75 fAtlas = resources->renderDeviceSpacePathInAtlas(
76 fAccessRect, fDeviceSpacePath, fPathDevIBounds, GrFillRuleForSkPath(fDeviceSpacePath),
77 &fDevToAtlasOffset);
78 SkDEBUGCODE(fHasAtlas = true);
79}
80