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 20 GrResourceProvider* GrProcessorTestData::resourceProvider() { 21 return fContext->resourceProvider(); 22 } 23 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>* 38 GrProcessorTestFactory<GrFragmentProcessor>::GetFactories() { 39 static SkTArray<GrProcessorTestFactory<GrFragmentProcessor>*, true> gFactories; 40 return &gFactories; 41 } 42 43 template<> 44 SkTArray<GrProcessorTestFactory<GrGeometryProcessor>*, true>* 45 GrProcessorTestFactory<GrGeometryProcessor>::GetFactories() { 46 static SkTArray<GrProcessorTestFactory<GrGeometryProcessor>*, true> gFactories; 47 return &gFactories; 48 } 49 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<> 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<> 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 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) 105 MemoryPoolAccessor() {} 106 ~MemoryPoolAccessor() {} 107 #else 108 MemoryPoolAccessor() { gProcessorSpinlock.acquire(); } 109 ~MemoryPoolAccessor() { gProcessorSpinlock.release(); } 110 #endif 111 112 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 123 void* GrProcessor::operator new(size_t size) { return MemoryPoolAccessor().pool()->allocate(size); } 124 125 void GrProcessor::operator delete(void* target) { 126 return MemoryPoolAccessor().pool()->release(target); 127 } 128 129 /////////////////////////////////////////////////////////////////////////////// 130 131 void GrResourceIOProcessor::addTextureSampler(const TextureSampler* access) { 132 fTextureSamplers.push_back(access); 133 } 134 135 void GrResourceIOProcessor::addBufferAccess(const BufferAccess* access) { 136 fBufferAccesses.push_back(access); 137 } 138 139 void GrResourceIOProcessor::addImageStorageAccess(const ImageStorageAccess* access) { 140 fImageStorageAccesses.push_back(access); 141 } 142 143 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 155 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 167 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 179 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 197 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 223 GrResourceIOProcessor::TextureSampler::TextureSampler() {} 224 225 GrResourceIOProcessor::TextureSampler::TextureSampler(sk_sp<GrTextureProxy> proxy, 226 const GrSamplerParams& params) { 227 this->reset(std::move(proxy), params); 228 } 229 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 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 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 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