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 "GrCoordTransform.h" 11 #include "GrGeometryProcessor.h" 12 #include "GrInvariantOutput.h" 13 #include "GrMemoryPool.h" 14 #include "GrXferProcessor.h" 15 #include "SkSpinlock.h" 16 17 #if SK_ALLOW_STATIC_GLOBAL_INITIALIZERS 18 19 class GrFragmentProcessor; 20 class GrGeometryProcessor; 21 22 /* 23 * Originally these were both in the processor unit test header, but then it seemed to cause linker 24 * problems on android. 25 */ 26 template<> 27 SkTArray<GrProcessorTestFactory<GrFragmentProcessor>*, true>* 28 GrProcessorTestFactory<GrFragmentProcessor>::GetFactories() { 29 static SkTArray<GrProcessorTestFactory<GrFragmentProcessor>*, true> gFactories; 30 return &gFactories; 31 } 32 33 template<> 34 SkTArray<GrProcessorTestFactory<GrXPFactory>*, true>* 35 GrProcessorTestFactory<GrXPFactory>::GetFactories() { 36 static SkTArray<GrProcessorTestFactory<GrXPFactory>*, true> gFactories; 37 return &gFactories; 38 } 39 40 template<> 41 SkTArray<GrProcessorTestFactory<GrGeometryProcessor>*, true>* 42 GrProcessorTestFactory<GrGeometryProcessor>::GetFactories() { 43 static SkTArray<GrProcessorTestFactory<GrGeometryProcessor>*, true> gFactories; 44 return &gFactories; 45 } 46 47 /* 48 * To ensure we always have successful static initialization, before creating from the factories 49 * we verify the count is as expected. If a new factory is added, then these numbers must be 50 * manually adjusted. 51 */ 52 static const int kFPFactoryCount = 37; 53 static const int kGPFactoryCount = 14; 54 static const int kXPFactoryCount = 5; 55 56 template<> 57 void GrProcessorTestFactory<GrFragmentProcessor>::VerifyFactoryCount() { 58 if (kFPFactoryCount != GetFactories()->count()) { 59 SkFAIL("Wrong number of fragment processor factories!"); 60 } 61 } 62 63 template<> 64 void GrProcessorTestFactory<GrGeometryProcessor>::VerifyFactoryCount() { 65 if (kGPFactoryCount != GetFactories()->count()) { 66 SkFAIL("Wrong number of geometry processor factories!"); 67 } 68 } 69 70 template<> 71 void GrProcessorTestFactory<GrXPFactory>::VerifyFactoryCount() { 72 if (kXPFactoryCount != GetFactories()->count()) { 73 SkFAIL("Wrong number of xp factory factories!"); 74 } 75 } 76 77 #endif 78 79 80 // We use a global pool protected by a mutex(spinlock). Chrome may use the same GrContext on 81 // different threads. The GrContext is not used concurrently on different threads and there is a 82 // memory barrier between accesses of a context on different threads. Also, there may be multiple 83 // GrContexts and those contexts may be in use concurrently on different threads. 84 namespace { 85 SK_DECLARE_STATIC_SPINLOCK(gProcessorSpinlock); 86 class MemoryPoolAccessor { 87 public: 88 MemoryPoolAccessor() { gProcessorSpinlock.acquire(); } 89 90 ~MemoryPoolAccessor() { gProcessorSpinlock.release(); } 91 92 GrMemoryPool* pool() const { 93 static GrMemoryPool gPool(4096, 4096); 94 return &gPool; 95 } 96 }; 97 } 98 99 int32_t GrProcessor::gCurrProcessorClassID = GrProcessor::kIllegalProcessorClassID; 100 101 /////////////////////////////////////////////////////////////////////////////// 102 103 GrProcessor::~GrProcessor() {} 104 105 void GrProcessor::addTextureAccess(const GrTextureAccess* access) { 106 fTextureAccesses.push_back(access); 107 this->addGpuResource(access->getProgramTexture()); 108 } 109 110 void* GrProcessor::operator new(size_t size) { 111 return MemoryPoolAccessor().pool()->allocate(size); 112 } 113 114 void GrProcessor::operator delete(void* target) { 115 return MemoryPoolAccessor().pool()->release(target); 116 } 117 118 bool GrProcessor::hasSameTextureAccesses(const GrProcessor& that) const { 119 if (this->numTextures() != that.numTextures()) { 120 return false; 121 } 122 for (int i = 0; i < this->numTextures(); ++i) { 123 if (this->textureAccess(i) != that.textureAccess(i)) { 124 return false; 125 } 126 } 127 return true; 128 } 129 130 /////////////////////////////////////////////////////////////////////////////////////////////////// 131 132 void GrFragmentProcessor::addCoordTransform(const GrCoordTransform* transform) { 133 fCoordTransforms.push_back(transform); 134 fUsesLocalCoords = fUsesLocalCoords || transform->sourceCoords() == kLocal_GrCoordSet; 135 SkDEBUGCODE(transform->setInProcessor();) 136 } 137 138 bool GrFragmentProcessor::hasSameTransforms(const GrFragmentProcessor& that) const { 139 if (fCoordTransforms.count() != that.fCoordTransforms.count()) { 140 return false; 141 } 142 int count = fCoordTransforms.count(); 143 for (int i = 0; i < count; ++i) { 144 if (*fCoordTransforms[i] != *that.fCoordTransforms[i]) { 145 return false; 146 } 147 } 148 return true; 149 } 150 151 void GrFragmentProcessor::computeInvariantOutput(GrInvariantOutput* inout) const { 152 this->onComputeInvariantOutput(inout); 153 } 154 155 /////////////////////////////////////////////////////////////////////////////////////////////////// 156 157 // Initial static variable from GrXPFactory 158 int32_t GrXPFactory::gCurrXPFClassID = 159 GrXPFactory::kIllegalXPFClassID; 160