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