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