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>*
GetFactories()28 GrProcessorTestFactory<GrFragmentProcessor>::GetFactories() {
29     static SkTArray<GrProcessorTestFactory<GrFragmentProcessor>*, true> gFactories;
30     return &gFactories;
31 }
32 
33 template<>
34 SkTArray<GrProcessorTestFactory<GrXPFactory>*, true>*
GetFactories()35 GrProcessorTestFactory<GrXPFactory>::GetFactories() {
36     static SkTArray<GrProcessorTestFactory<GrXPFactory>*, true> gFactories;
37     return &gFactories;
38 }
39 
40 template<>
41 SkTArray<GrProcessorTestFactory<GrGeometryProcessor>*, true>*
GetFactories()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<>
VerifyFactoryCount()57 void GrProcessorTestFactory<GrFragmentProcessor>::VerifyFactoryCount() {
58     if (kFPFactoryCount != GetFactories()->count()) {
59         SkFAIL("Wrong number of fragment processor factories!");
60     }
61 }
62 
63 template<>
VerifyFactoryCount()64 void GrProcessorTestFactory<GrGeometryProcessor>::VerifyFactoryCount() {
65     if (kGPFactoryCount != GetFactories()->count()) {
66         SkFAIL("Wrong number of geometry processor factories!");
67     }
68 }
69 
70 template<>
VerifyFactoryCount()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:
MemoryPoolAccessor()88     MemoryPoolAccessor() { gProcessorSpinlock.acquire(); }
89 
~MemoryPoolAccessor()90     ~MemoryPoolAccessor() { gProcessorSpinlock.release(); }
91 
pool() const92     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 
~GrProcessor()103 GrProcessor::~GrProcessor() {}
104 
addTextureAccess(const GrTextureAccess * access)105 void GrProcessor::addTextureAccess(const GrTextureAccess* access) {
106     fTextureAccesses.push_back(access);
107     this->addGpuResource(access->getProgramTexture());
108 }
109 
operator new(size_t size)110 void* GrProcessor::operator new(size_t size) {
111     return MemoryPoolAccessor().pool()->allocate(size);
112 }
113 
operator delete(void * target)114 void GrProcessor::operator delete(void* target) {
115     return MemoryPoolAccessor().pool()->release(target);
116 }
117 
hasSameTextureAccesses(const GrProcessor & that) const118 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 
addCoordTransform(const GrCoordTransform * transform)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 
hasSameTransforms(const GrFragmentProcessor & that) const138 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 
computeInvariantOutput(GrInvariantOutput * inout) const151 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