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 = 41;
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 
~GrProcessor()123 GrProcessor::~GrProcessor() {}
124 
addTextureSampler(const TextureSampler * access)125 void GrProcessor::addTextureSampler(const TextureSampler* access) {
126     fTextureSamplers.push_back(access);
127 }
128 
addBufferAccess(const BufferAccess * access)129 void GrProcessor::addBufferAccess(const BufferAccess* access) {
130     fBufferAccesses.push_back(access);
131 }
132 
addImageStorageAccess(const ImageStorageAccess * access)133 void GrProcessor::addImageStorageAccess(const ImageStorageAccess* access) {
134     fImageStorageAccesses.push_back(access);
135 }
136 
addPendingIOs() const137 void GrProcessor::addPendingIOs() const {
138     for (const auto& sampler : fTextureSamplers) {
139         sampler->programTexture()->markPendingIO();
140     }
141     for (const auto& buffer : fBufferAccesses) {
142         buffer->programBuffer()->markPendingIO();
143     }
144     for (const auto& imageStorage : fImageStorageAccesses) {
145         imageStorage->programTexture()->markPendingIO();
146     }
147 }
148 
removeRefs() const149 void GrProcessor::removeRefs() const {
150     for (const auto& sampler : fTextureSamplers) {
151         sampler->programTexture()->removeRef();
152     }
153     for (const auto& buffer : fBufferAccesses) {
154         buffer->programBuffer()->removeRef();
155     }
156     for (const auto& imageStorage : fImageStorageAccesses) {
157         imageStorage->programTexture()->removeRef();
158     }
159 }
160 
pendingIOComplete() const161 void GrProcessor::pendingIOComplete() const {
162     for (const auto& sampler : fTextureSamplers) {
163         sampler->programTexture()->pendingIOComplete();
164     }
165     for (const auto& buffer : fBufferAccesses) {
166         buffer->programBuffer()->pendingIOComplete();
167     }
168     for (const auto& imageStorage : fImageStorageAccesses) {
169         imageStorage->programTexture()->pendingIOComplete();
170     }
171 }
172 
operator new(size_t size)173 void* GrProcessor::operator new(size_t size) {
174     return MemoryPoolAccessor().pool()->allocate(size);
175 }
176 
operator delete(void * target)177 void GrProcessor::operator delete(void* target) {
178     return MemoryPoolAccessor().pool()->release(target);
179 }
180 
hasSameSamplersAndAccesses(const GrProcessor & that) const181 bool GrProcessor::hasSameSamplersAndAccesses(const GrProcessor &that) const {
182     if (this->numTextureSamplers() != that.numTextureSamplers() ||
183         this->numBuffers() != that.numBuffers() ||
184         this->numImageStorages() != that.numImageStorages()) {
185         return false;
186     }
187     for (int i = 0; i < this->numTextureSamplers(); ++i) {
188         if (this->textureSampler(i) != that.textureSampler(i)) {
189             return false;
190         }
191     }
192     for (int i = 0; i < this->numBuffers(); ++i) {
193         if (this->bufferAccess(i) != that.bufferAccess(i)) {
194             return false;
195         }
196     }
197     for (int i = 0; i < this->numImageStorages(); ++i) {
198         if (this->imageStorageAccess(i) != that.imageStorageAccess(i)) {
199             return false;
200         }
201     }
202     return true;
203 }
204 
205 ///////////////////////////////////////////////////////////////////////////////////////////////////
206 
TextureSampler()207 GrProcessor::TextureSampler::TextureSampler() {}
208 
TextureSampler(GrTexture * texture,const GrSamplerParams & params)209 GrProcessor::TextureSampler::TextureSampler(GrTexture* texture, const GrSamplerParams& params) {
210     this->reset(texture, params);
211 }
212 
TextureSampler(GrTexture * texture,GrSamplerParams::FilterMode filterMode,SkShader::TileMode tileXAndY,GrShaderFlags visibility)213 GrProcessor::TextureSampler::TextureSampler(GrTexture* texture,
214                                             GrSamplerParams::FilterMode filterMode,
215                                             SkShader::TileMode tileXAndY,
216                                             GrShaderFlags visibility) {
217     this->reset(texture, filterMode, tileXAndY, visibility);
218 }
219 
TextureSampler(GrResourceProvider * resourceProvider,sk_sp<GrTextureProxy> proxy,const GrSamplerParams & params)220 GrProcessor::TextureSampler::TextureSampler(GrResourceProvider* resourceProvider,
221                                             sk_sp<GrTextureProxy> proxy,
222                                             const GrSamplerParams& params) {
223     this->reset(resourceProvider, std::move(proxy), params);
224 }
225 
TextureSampler(GrResourceProvider * resourceProvider,sk_sp<GrTextureProxy> proxy,GrSamplerParams::FilterMode filterMode,SkShader::TileMode tileXAndY,GrShaderFlags visibility)226 GrProcessor::TextureSampler::TextureSampler(GrResourceProvider* resourceProvider,
227                                             sk_sp<GrTextureProxy> proxy,
228                                             GrSamplerParams::FilterMode filterMode,
229                                             SkShader::TileMode tileXAndY,
230                                             GrShaderFlags visibility) {
231     this->reset(resourceProvider, std::move(proxy), filterMode, tileXAndY, visibility);
232 }
233 
reset(GrTexture * texture,const GrSamplerParams & params,GrShaderFlags visibility)234 void GrProcessor::TextureSampler::reset(GrTexture* texture,
235                                         const GrSamplerParams& params,
236                                         GrShaderFlags visibility) {
237     SkASSERT(texture);
238     fTexture.set(SkRef(texture), kRead_GrIOType);
239     fParams = params;
240     fParams.setFilterMode(SkTMin(params.filterMode(), texture->texturePriv().highestFilterMode()));
241     fVisibility = visibility;
242 }
243 
reset(GrTexture * texture,GrSamplerParams::FilterMode filterMode,SkShader::TileMode tileXAndY,GrShaderFlags visibility)244 void GrProcessor::TextureSampler::reset(GrTexture* texture,
245                                         GrSamplerParams::FilterMode filterMode,
246                                         SkShader::TileMode tileXAndY,
247                                         GrShaderFlags visibility) {
248     SkASSERT(texture);
249     fTexture.set(SkRef(texture), kRead_GrIOType);
250     filterMode = SkTMin(filterMode, texture->texturePriv().highestFilterMode());
251     fParams.reset(tileXAndY, filterMode);
252     fVisibility = visibility;
253 }
254 
reset(GrResourceProvider * resourceProvider,sk_sp<GrTextureProxy> proxy,const GrSamplerParams & params,GrShaderFlags visibility)255 void GrProcessor::TextureSampler::reset(GrResourceProvider* resourceProvider,
256                                         sk_sp<GrTextureProxy> proxy,
257                                         const GrSamplerParams& params,
258                                         GrShaderFlags visibility) {
259     // For now, end the deferral at this time. Once all the TextureSamplers are swapped over
260     // to taking a GrSurfaceProxy just use the IORefs on the proxy
261     GrTexture* texture = proxy->instantiate(resourceProvider);
262     SkASSERT(texture);
263     fTexture.set(SkRef(texture), kRead_GrIOType);
264     fParams = params;
265     fParams.setFilterMode(SkTMin(params.filterMode(), texture->texturePriv().highestFilterMode()));
266     fVisibility = visibility;
267 }
268 
reset(GrResourceProvider * resourceProvider,sk_sp<GrTextureProxy> proxy,GrSamplerParams::FilterMode filterMode,SkShader::TileMode tileXAndY,GrShaderFlags visibility)269 void GrProcessor::TextureSampler::reset(GrResourceProvider* resourceProvider,
270                                         sk_sp<GrTextureProxy> proxy,
271                                         GrSamplerParams::FilterMode filterMode,
272                                         SkShader::TileMode tileXAndY,
273                                         GrShaderFlags visibility) {
274     // For now, end the deferral at this time. Once all the TextureSamplers are swapped over
275     // to taking a GrSurfaceProxy just use the IORefs on the proxy
276     GrTexture* texture = proxy->instantiate(resourceProvider);
277     SkASSERT(texture);
278     fTexture.set(SkRef(texture), kRead_GrIOType);
279     filterMode = SkTMin(filterMode, texture->texturePriv().highestFilterMode());
280     fParams.reset(tileXAndY, filterMode);
281     fVisibility = visibility;
282 }
283 
284 ///////////////////////////////////////////////////////////////////////////////////////////////////
285 
ImageStorageAccess(sk_sp<GrTexture> texture,GrIOType ioType,GrSLMemoryModel memoryModel,GrSLRestrict restrict,GrShaderFlags visibility)286 GrProcessor::ImageStorageAccess::ImageStorageAccess(sk_sp<GrTexture> texture, GrIOType ioType,
287                                                     GrSLMemoryModel memoryModel,
288                                                     GrSLRestrict restrict,
289                                                     GrShaderFlags visibility) {
290     SkASSERT(texture);
291     fTexture.set(texture.release(), ioType);
292     fMemoryModel = memoryModel;
293     fRestrict = restrict;
294     fVisibility = visibility;
295     // We currently infer this from the config. However, we could allow the client to specify
296     // a format that is different but compatible with the config.
297     switch (fTexture.get()->config()) {
298         case kRGBA_8888_GrPixelConfig:
299             fFormat = GrImageStorageFormat::kRGBA8;
300             break;
301         case kRGBA_8888_sint_GrPixelConfig:
302             fFormat = GrImageStorageFormat::kRGBA8i;
303             break;
304         case kRGBA_half_GrPixelConfig:
305             fFormat = GrImageStorageFormat::kRGBA16f;
306             break;
307         case kRGBA_float_GrPixelConfig:
308             fFormat = GrImageStorageFormat::kRGBA32f;
309             break;
310         default:
311             SkFAIL("Config is not (yet) supported as image storage.");
312             break;
313     }
314 }
315