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 = 41; 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 GrProcessor::~GrProcessor() {} 124 125 void GrProcessor::addTextureSampler(const TextureSampler* access) { 126 fTextureSamplers.push_back(access); 127 } 128 129 void GrProcessor::addBufferAccess(const BufferAccess* access) { 130 fBufferAccesses.push_back(access); 131 } 132 133 void GrProcessor::addImageStorageAccess(const ImageStorageAccess* access) { 134 fImageStorageAccesses.push_back(access); 135 } 136 137 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 149 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 161 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 173 void* GrProcessor::operator new(size_t size) { 174 return MemoryPoolAccessor().pool()->allocate(size); 175 } 176 177 void GrProcessor::operator delete(void* target) { 178 return MemoryPoolAccessor().pool()->release(target); 179 } 180 181 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 207 GrProcessor::TextureSampler::TextureSampler() {} 208 209 GrProcessor::TextureSampler::TextureSampler(GrTexture* texture, const GrSamplerParams& params) { 210 this->reset(texture, params); 211 } 212 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 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 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 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 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 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 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 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