1/*
2 * Copyright 2016 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// This is a GPU-backend specific test.
9
10#include "Test.h"
11
12#if SK_SUPPORT_GPU
13#include "GrContextPriv.h"
14#include "GrGpuResourceRef.h"
15#include "GrProxyProvider.h"
16#include "GrRenderTargetProxy.h"
17#include "GrResourceProvider.h"
18#include "GrSurfaceProxy.h"
19#include "GrTexture.h"
20#include "GrTextureProxy.h"
21
22int32_t GrIORefProxy::getProxyRefCnt_TestOnly() const {
23    return fRefCnt;
24}
25
26int32_t GrIORefProxy::getBackingRefCnt_TestOnly() const {
27    if (fTarget) {
28        return fTarget->fRefCnt;
29    }
30
31    return fRefCnt;
32}
33
34int32_t GrIORefProxy::getPendingReadCnt_TestOnly() const {
35    if (fTarget) {
36        return fTarget->fPendingReads;
37    }
38
39    return fPendingReads;
40}
41
42int32_t GrIORefProxy::getPendingWriteCnt_TestOnly() const {
43    if (fTarget) {
44        return fTarget->fPendingWrites;
45    }
46
47    return fPendingWrites;
48}
49
50static const int kWidthHeight = 128;
51
52static void check_refs(skiatest::Reporter* reporter,
53                       GrTextureProxy* proxy,
54                       int32_t expectedProxyRefs,
55                       int32_t expectedBackingRefs,
56                       int32_t expectedNumReads,
57                       int32_t expectedNumWrites) {
58    REPORTER_ASSERT(reporter, proxy->getProxyRefCnt_TestOnly() == expectedProxyRefs);
59    REPORTER_ASSERT(reporter, proxy->getBackingRefCnt_TestOnly() == expectedBackingRefs);
60    REPORTER_ASSERT(reporter, proxy->getPendingReadCnt_TestOnly() == expectedNumReads);
61    REPORTER_ASSERT(reporter, proxy->getPendingWriteCnt_TestOnly() == expectedNumWrites);
62
63    SkASSERT(proxy->getProxyRefCnt_TestOnly() == expectedProxyRefs);
64    SkASSERT(proxy->getBackingRefCnt_TestOnly() == expectedBackingRefs);
65    SkASSERT(proxy->getPendingReadCnt_TestOnly() == expectedNumReads);
66    SkASSERT(proxy->getPendingWriteCnt_TestOnly() == expectedNumWrites);
67}
68
69static sk_sp<GrTextureProxy> make_deferred(GrProxyProvider* proxyProvider) {
70    GrSurfaceDesc desc;
71    desc.fFlags = kRenderTarget_GrSurfaceFlag;
72    desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
73    desc.fWidth = kWidthHeight;
74    desc.fHeight = kWidthHeight;
75    desc.fConfig = kRGBA_8888_GrPixelConfig;
76
77    return proxyProvider->createProxy(desc, SkBackingFit::kApprox, SkBudgeted::kYes,
78                                      GrResourceProvider::kNoPendingIO_Flag);
79}
80
81static sk_sp<GrTextureProxy> make_wrapped(GrProxyProvider* proxyProvider) {
82    GrSurfaceDesc desc;
83    desc.fFlags = kRenderTarget_GrSurfaceFlag;
84    desc.fOrigin = kBottomLeft_GrSurfaceOrigin;
85    desc.fWidth = kWidthHeight;
86    desc.fHeight = kWidthHeight;
87    desc.fConfig = kRGBA_8888_GrPixelConfig;
88
89    return proxyProvider->createInstantiatedProxy(desc, SkBackingFit::kExact, SkBudgeted::kNo);
90}
91
92DEF_GPUTEST_FOR_RENDERING_CONTEXTS(ProxyRefTest, reporter, ctxInfo) {
93    GrProxyProvider* proxyProvider = ctxInfo.grContext()->contextPriv().proxyProvider();
94    GrResourceProvider* resourceProvider = ctxInfo.grContext()->contextPriv().resourceProvider();
95
96    for (auto make : { make_deferred, make_wrapped }) {
97        // A single write
98        {
99            sk_sp<GrTextureProxy> proxy((*make)(proxyProvider));
100            if (proxy.get()) {
101                GrPendingIOResource<GrSurfaceProxy, kWrite_GrIOType> fWrite(proxy.get());
102
103                static const int kExpectedReads = 0;
104                static const int kExpectedWrites = 1;
105
106                check_refs(reporter, proxy.get(), 1, 1, kExpectedReads, kExpectedWrites);
107
108                proxy->instantiate(resourceProvider);
109
110                // In the deferred case, this checks that the refs transfered to the GrSurface
111                check_refs(reporter, proxy.get(), 1, 1, kExpectedReads, kExpectedWrites);
112            }
113        }
114
115        // A single read
116        {
117            sk_sp<GrTextureProxy> proxy((*make)(proxyProvider));
118            if (proxy.get()) {
119                GrPendingIOResource<GrSurfaceProxy, kRead_GrIOType> fRead(proxy.get());
120
121                static const int kExpectedReads = 1;
122                static const int kExpectedWrites = 0;
123
124                check_refs(reporter, proxy.get(), 1, 1, kExpectedReads, kExpectedWrites);
125
126                proxy->instantiate(resourceProvider);
127
128                // In the deferred case, this checks that the refs transfered to the GrSurface
129                check_refs(reporter, proxy.get(), 1, 1, kExpectedReads, kExpectedWrites);
130            }
131        }
132
133        // A single read/write pair
134        {
135            sk_sp<GrTextureProxy> proxy((*make)(proxyProvider));
136            if (proxy.get()) {
137                GrPendingIOResource<GrSurfaceProxy, kRW_GrIOType> fRW(proxy.get());
138
139                static const int kExpectedReads = 1;
140                static const int kExpectedWrites = 1;
141
142                check_refs(reporter, proxy.get(), 1, 1, kExpectedReads, kExpectedWrites);
143
144                proxy->instantiate(resourceProvider);
145
146                // In the deferred case, this checks that the refs transferred to the GrSurface
147                check_refs(reporter, proxy.get(), 1, 1, kExpectedReads, kExpectedWrites);
148            }
149        }
150
151        // Multiple normal refs
152        {
153            sk_sp<GrTextureProxy> proxy((*make)(proxyProvider));
154            if (proxy.get()) {
155                proxy->ref();
156                proxy->ref();
157
158                static const int kExpectedReads = 0;
159                static const int kExpectedWrites = 0;
160
161                check_refs(reporter, proxy.get(), 3, 3,kExpectedReads, kExpectedWrites);
162
163                proxy->instantiate(resourceProvider);
164
165                // In the deferred case, this checks that the refs transferred to the GrSurface
166                check_refs(reporter, proxy.get(), 3, 3, kExpectedReads, kExpectedWrites);
167
168                proxy->unref();
169                proxy->unref();
170            }
171        }
172
173        // Continue using (reffing) proxy after instantiation
174        {
175            sk_sp<GrTextureProxy> proxy((*make)(proxyProvider));
176            if (proxy.get()) {
177                proxy->ref();
178
179                GrPendingIOResource<GrSurfaceProxy, kWrite_GrIOType> fWrite(proxy.get());
180
181                static const int kExpectedWrites = 1;
182
183                check_refs(reporter, proxy.get(), 2, 2, 0, kExpectedWrites);
184
185                proxy->instantiate(resourceProvider);
186
187                // In the deferred case, this checks that the refs transfered to the GrSurface
188                check_refs(reporter, proxy.get(), 2, 2, 0, kExpectedWrites);
189
190                proxy->unref();
191                check_refs(reporter, proxy.get(), 1, 1, 0, kExpectedWrites);
192
193                GrPendingIOResource<GrSurfaceProxy, kRead_GrIOType> fRead(proxy.get());
194                check_refs(reporter, proxy.get(), 1, 1, 1, kExpectedWrites);
195            }
196        }
197    }
198}
199
200#endif
201