1 /*
2 * Copyright 2012 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 "GrProcessor.h"
9 #include "GrContext.h"
10 #include "GrGeometryProcessor.h"
11 #include "GrMemoryPool.h"
12 #include "GrSamplerParams.h"
13 #include "GrTexturePriv.h"
14 #include "GrTextureProxy.h"
15 #include "GrXferProcessor.h"
16 #include "SkSpinlock.h"
17
18 #if GR_TEST_UTILS
19
resourceProvider()20 GrResourceProvider* GrProcessorTestData::resourceProvider() {
21 return fContext->resourceProvider();
22 }
23
caps()24 const GrCaps* GrProcessorTestData::caps() {
25 return fContext->caps();
26 }
27
28 #if SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
29 class GrFragmentProcessor;
30 class GrGeometryProcessor;
31
32 /*
33 * Originally these were both in the processor unit test header, but then it seemed to cause linker
34 * problems on android.
35 */
36 template<>
37 SkTArray<GrProcessorTestFactory<GrFragmentProcessor>*, true>*
GetFactories()38 GrProcessorTestFactory<GrFragmentProcessor>::GetFactories() {
39 static SkTArray<GrProcessorTestFactory<GrFragmentProcessor>*, true> gFactories;
40 return &gFactories;
41 }
42
43 template<>
44 SkTArray<GrProcessorTestFactory<GrGeometryProcessor>*, true>*
GetFactories()45 GrProcessorTestFactory<GrGeometryProcessor>::GetFactories() {
46 static SkTArray<GrProcessorTestFactory<GrGeometryProcessor>*, true> gFactories;
47 return &gFactories;
48 }
49
GetFactories()50 SkTArray<GrXPFactoryTestFactory*, true>* GrXPFactoryTestFactory::GetFactories() {
51 static SkTArray<GrXPFactoryTestFactory*, true> gFactories;
52 return &gFactories;
53 }
54
55 /*
56 * To ensure we always have successful static initialization, before creating from the factories
57 * we verify the count is as expected. If a new factory is added, then these numbers must be
58 * manually adjusted.
59 */
60 static const int kFPFactoryCount = 42;
61 static const int kGPFactoryCount = 14;
62 static const int kXPFactoryCount = 4;
63
64 template<>
VerifyFactoryCount()65 void GrProcessorTestFactory<GrFragmentProcessor>::VerifyFactoryCount() {
66 if (kFPFactoryCount != GetFactories()->count()) {
67 SkDebugf("\nExpected %d fragment processor factories, found %d.\n",
68 kFPFactoryCount, GetFactories()->count());
69 SkFAIL("Wrong number of fragment processor factories!");
70 }
71 }
72
73 template<>
VerifyFactoryCount()74 void GrProcessorTestFactory<GrGeometryProcessor>::VerifyFactoryCount() {
75 if (kGPFactoryCount != GetFactories()->count()) {
76 SkDebugf("\nExpected %d geometry processor factories, found %d.\n",
77 kGPFactoryCount, GetFactories()->count());
78 SkFAIL("Wrong number of geometry processor factories!");
79 }
80 }
81
VerifyFactoryCount()82 void GrXPFactoryTestFactory::VerifyFactoryCount() {
83 if (kXPFactoryCount != GetFactories()->count()) {
84 SkDebugf("\nExpected %d xp factory factories, found %d.\n",
85 kXPFactoryCount, GetFactories()->count());
86 SkFAIL("Wrong number of xp factory factories!");
87 }
88 }
89
90 #endif
91 #endif
92
93
94 // We use a global pool protected by a mutex(spinlock). Chrome may use the same GrContext on
95 // different threads. The GrContext is not used concurrently on different threads and there is a
96 // memory barrier between accesses of a context on different threads. Also, there may be multiple
97 // GrContexts and those contexts may be in use concurrently on different threads.
98 namespace {
99 static SkSpinlock gProcessorSpinlock;
100 class MemoryPoolAccessor {
101 public:
102
103 // We know in the Android framework there is only one GrContext.
104 #if defined(SK_BUILD_FOR_ANDROID_FRAMEWORK)
MemoryPoolAccessor()105 MemoryPoolAccessor() {}
~MemoryPoolAccessor()106 ~MemoryPoolAccessor() {}
107 #else
108 MemoryPoolAccessor() { gProcessorSpinlock.acquire(); }
109 ~MemoryPoolAccessor() { gProcessorSpinlock.release(); }
110 #endif
111
pool() const112 GrMemoryPool* pool() const {
113 static GrMemoryPool gPool(4096, 4096);
114 return &gPool;
115 }
116 };
117 }
118
119 int32_t GrProcessor::gCurrProcessorClassID = GrProcessor::kIllegalProcessorClassID;
120
121 ///////////////////////////////////////////////////////////////////////////////
122
operator new(size_t size)123 void* GrProcessor::operator new(size_t size) { return MemoryPoolAccessor().pool()->allocate(size); }
124
operator delete(void * target)125 void GrProcessor::operator delete(void* target) {
126 return MemoryPoolAccessor().pool()->release(target);
127 }
128
129 ///////////////////////////////////////////////////////////////////////////////
130
addTextureSampler(const TextureSampler * access)131 void GrResourceIOProcessor::addTextureSampler(const TextureSampler* access) {
132 fTextureSamplers.push_back(access);
133 }
134
addBufferAccess(const BufferAccess * access)135 void GrResourceIOProcessor::addBufferAccess(const BufferAccess* access) {
136 fBufferAccesses.push_back(access);
137 }
138
addImageStorageAccess(const ImageStorageAccess * access)139 void GrResourceIOProcessor::addImageStorageAccess(const ImageStorageAccess* access) {
140 fImageStorageAccesses.push_back(access);
141 }
142
addPendingIOs() const143 void GrResourceIOProcessor::addPendingIOs() const {
144 for (const auto& sampler : fTextureSamplers) {
145 sampler->programProxy()->markPendingIO();
146 }
147 for (const auto& buffer : fBufferAccesses) {
148 buffer->programBuffer()->markPendingIO();
149 }
150 for (const auto& imageStorage : fImageStorageAccesses) {
151 imageStorage->programProxy()->markPendingIO();
152 }
153 }
154
removeRefs() const155 void GrResourceIOProcessor::removeRefs() const {
156 for (const auto& sampler : fTextureSamplers) {
157 sampler->programProxy()->removeRef();
158 }
159 for (const auto& buffer : fBufferAccesses) {
160 buffer->programBuffer()->removeRef();
161 }
162 for (const auto& imageStorage : fImageStorageAccesses) {
163 imageStorage->programProxy()->removeRef();
164 }
165 }
166
pendingIOComplete() const167 void GrResourceIOProcessor::pendingIOComplete() const {
168 for (const auto& sampler : fTextureSamplers) {
169 sampler->programProxy()->pendingIOComplete();
170 }
171 for (const auto& buffer : fBufferAccesses) {
172 buffer->programBuffer()->pendingIOComplete();
173 }
174 for (const auto& imageStorage : fImageStorageAccesses) {
175 imageStorage->programProxy()->pendingIOComplete();
176 }
177 }
178
instantiate(GrResourceProvider * resourceProvider) const179 bool GrResourceIOProcessor::instantiate(GrResourceProvider* resourceProvider) const {
180 for (const auto& sampler : fTextureSamplers) {
181 if (!sampler->instantiate(resourceProvider)) {
182 return false;
183 }
184 }
185
186 // MDB TODO: instantiate 'fBufferAccesses' here as well
187
188 for (const auto& imageStorage : fImageStorageAccesses) {
189 if (!imageStorage->instantiate(resourceProvider)) {
190 return false;
191 }
192 }
193
194 return true;
195 }
196
hasSameSamplersAndAccesses(const GrResourceIOProcessor & that) const197 bool GrResourceIOProcessor::hasSameSamplersAndAccesses(const GrResourceIOProcessor& that) const {
198 if (this->numTextureSamplers() != that.numTextureSamplers() ||
199 this->numBuffers() != that.numBuffers() ||
200 this->numImageStorages() != that.numImageStorages()) {
201 return false;
202 }
203 for (int i = 0; i < this->numTextureSamplers(); ++i) {
204 if (this->textureSampler(i) != that.textureSampler(i)) {
205 return false;
206 }
207 }
208 for (int i = 0; i < this->numBuffers(); ++i) {
209 if (this->bufferAccess(i) != that.bufferAccess(i)) {
210 return false;
211 }
212 }
213 for (int i = 0; i < this->numImageStorages(); ++i) {
214 if (this->imageStorageAccess(i) != that.imageStorageAccess(i)) {
215 return false;
216 }
217 }
218 return true;
219 }
220
221 ///////////////////////////////////////////////////////////////////////////////////////////////////
222
TextureSampler()223 GrResourceIOProcessor::TextureSampler::TextureSampler() {}
224
TextureSampler(sk_sp<GrTextureProxy> proxy,const GrSamplerParams & params)225 GrResourceIOProcessor::TextureSampler::TextureSampler(sk_sp<GrTextureProxy> proxy,
226 const GrSamplerParams& params) {
227 this->reset(std::move(proxy), params);
228 }
229
TextureSampler(sk_sp<GrTextureProxy> proxy,GrSamplerParams::FilterMode filterMode,SkShader::TileMode tileXAndY,GrShaderFlags visibility)230 GrResourceIOProcessor::TextureSampler::TextureSampler(sk_sp<GrTextureProxy> proxy,
231 GrSamplerParams::FilterMode filterMode,
232 SkShader::TileMode tileXAndY,
233 GrShaderFlags visibility) {
234 this->reset(std::move(proxy), filterMode, tileXAndY, visibility);
235 }
236
reset(sk_sp<GrTextureProxy> proxy,const GrSamplerParams & params,GrShaderFlags visibility)237 void GrResourceIOProcessor::TextureSampler::reset(sk_sp<GrTextureProxy> proxy,
238 const GrSamplerParams& params,
239 GrShaderFlags visibility) {
240 fParams = params;
241 fProxyRef.setProxy(std::move(proxy), kRead_GrIOType);
242 fParams.setFilterMode(SkTMin(params.filterMode(), this->proxy()->highestFilterMode()));
243 fVisibility = visibility;
244 }
245
reset(sk_sp<GrTextureProxy> proxy,GrSamplerParams::FilterMode filterMode,SkShader::TileMode tileXAndY,GrShaderFlags visibility)246 void GrResourceIOProcessor::TextureSampler::reset(sk_sp<GrTextureProxy> proxy,
247 GrSamplerParams::FilterMode filterMode,
248 SkShader::TileMode tileXAndY,
249 GrShaderFlags visibility) {
250 fProxyRef.setProxy(std::move(proxy), kRead_GrIOType);
251 filterMode = SkTMin(filterMode, this->proxy()->highestFilterMode());
252 fParams.reset(tileXAndY, filterMode);
253 fVisibility = visibility;
254 }
255
256 ///////////////////////////////////////////////////////////////////////////////////////////////////
257
ImageStorageAccess(sk_sp<GrTextureProxy> proxy,GrIOType ioType,GrSLMemoryModel memoryModel,GrSLRestrict restrict,GrShaderFlags visibility)258 GrResourceIOProcessor::ImageStorageAccess::ImageStorageAccess(sk_sp<GrTextureProxy> proxy,
259 GrIOType ioType,
260 GrSLMemoryModel memoryModel,
261 GrSLRestrict restrict,
262 GrShaderFlags visibility)
263 : fProxyRef(std::move(proxy), ioType) {
264 SkASSERT(fProxyRef.get());
265
266 fMemoryModel = memoryModel;
267 fRestrict = restrict;
268 fVisibility = visibility;
269 // We currently infer this from the config. However, we could allow the client to specify
270 // a format that is different but compatible with the config.
271 switch (fProxyRef.get()->config()) {
272 case kRGBA_8888_GrPixelConfig:
273 fFormat = GrImageStorageFormat::kRGBA8;
274 break;
275 case kRGBA_8888_sint_GrPixelConfig:
276 fFormat = GrImageStorageFormat::kRGBA8i;
277 break;
278 case kRGBA_half_GrPixelConfig:
279 fFormat = GrImageStorageFormat::kRGBA16f;
280 break;
281 case kRGBA_float_GrPixelConfig:
282 fFormat = GrImageStorageFormat::kRGBA32f;
283 break;
284 default:
285 SkFAIL("Config is not (yet) supported as image storage.");
286 break;
287 }
288 }
289