blob: e6be1da33a6e43159e636201a4770122186e6dd6 [file] [log] [blame]
tomhudson@google.com168e6342012-04-18 17:49:20 +00001/*
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
joshualittb0a8a372014-09-23 09:50:21 -07008#include "GrProcessor.h"
bsalomon@google.com2eaaefd2012-10-29 19:51:22 +00009#include "GrContext.h"
bsalomon@google.com77af6802013-10-02 13:04:56 +000010#include "GrCoordTransform.h"
joshualitt2e3b3e32014-12-09 13:31:14 -080011#include "GrGeometryProcessor.h"
egdaniel605dd0f2014-11-12 08:35:25 -080012#include "GrInvariantOutput.h"
tomhudson@google.comdcba4c22012-07-24 21:36:16 +000013#include "GrMemoryPool.h"
egdaniel915187b2014-12-05 12:58:28 -080014#include "GrXferProcessor.h"
joshualitt23ac62c2015-03-30 09:53:47 -070015#include "SkSpinlock.h"
wangyixb1daa862015-08-18 11:29:31 -070016#include "gl/GrGLFragmentProcessor.h"
tomhudson@google.com168e6342012-04-18 17:49:20 +000017
joshualitt9e87fa72014-10-09 13:12:35 -070018#if SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
19
joshualitteb2a6762014-12-04 11:35:33 -080020class GrFragmentProcessor;
21class GrGeometryProcessor;
22
joshualitt9e87fa72014-10-09 13:12:35 -070023/*
24 * Originally these were both in the processor unit test header, but then it seemed to cause linker
25 * problems on android.
26 */
27template<>
28SkTArray<GrProcessorTestFactory<GrFragmentProcessor>*, true>*
29GrProcessorTestFactory<GrFragmentProcessor>::GetFactories() {
30 static SkTArray<GrProcessorTestFactory<GrFragmentProcessor>*, true> gFactories;
31 return &gFactories;
32}
33
34template<>
egdanielc2304142014-12-11 13:15:13 -080035SkTArray<GrProcessorTestFactory<GrXPFactory>*, true>*
36GrProcessorTestFactory<GrXPFactory>::GetFactories() {
37 static SkTArray<GrProcessorTestFactory<GrXPFactory>*, true> gFactories;
egdaniel378092f2014-12-03 10:40:13 -080038 return &gFactories;
39}
40
41template<>
joshualitt9e87fa72014-10-09 13:12:35 -070042SkTArray<GrProcessorTestFactory<GrGeometryProcessor>*, true>*
43GrProcessorTestFactory<GrGeometryProcessor>::GetFactories() {
44 static SkTArray<GrProcessorTestFactory<GrGeometryProcessor>*, true> gFactories;
45 return &gFactories;
46}
47
48/*
49 * To ensure we always have successful static initialization, before creating from the factories
50 * we verify the count is as expected. If a new factory is added, then these numbers must be
51 * manually adjusted.
52 */
Brian Salomon3905c372015-09-22 10:08:47 -040053static const int kFPFactoryCount = 38;
joshualitt4973d9d2014-11-08 09:24:25 -080054static const int kGPFactoryCount = 14;
egdaniel54f0e9d2015-01-16 06:29:47 -080055static const int kXPFactoryCount = 5;
joshualitt9e87fa72014-10-09 13:12:35 -070056
57template<>
58void GrProcessorTestFactory<GrFragmentProcessor>::VerifyFactoryCount() {
59 if (kFPFactoryCount != GetFactories()->count()) {
60 SkFAIL("Wrong number of fragment processor factories!");
61 }
62}
63
64template<>
65void GrProcessorTestFactory<GrGeometryProcessor>::VerifyFactoryCount() {
66 if (kGPFactoryCount != GetFactories()->count()) {
67 SkFAIL("Wrong number of geometry processor factories!");
68 }
69}
70
egdaniel378092f2014-12-03 10:40:13 -080071template<>
egdanielc2304142014-12-11 13:15:13 -080072void GrProcessorTestFactory<GrXPFactory>::VerifyFactoryCount() {
egdaniel378092f2014-12-03 10:40:13 -080073 if (kXPFactoryCount != GetFactories()->count()) {
egdanielc2304142014-12-11 13:15:13 -080074 SkFAIL("Wrong number of xp factory factories!");
egdaniel378092f2014-12-03 10:40:13 -080075 }
76}
77
joshualitt9e87fa72014-10-09 13:12:35 -070078#endif
79
bsalomon5baedd62015-03-09 12:15:53 -070080
joshualitt23ac62c2015-03-30 09:53:47 -070081// We use a global pool protected by a mutex(spinlock). Chrome may use the same GrContext on
82// different threads. The GrContext is not used concurrently on different threads and there is a
83// memory barrier between accesses of a context on different threads. Also, there may be multiple
bsalomon5baedd62015-03-09 12:15:53 -070084// GrContexts and those contexts may be in use concurrently on different threads.
85namespace {
joshualitt23ac62c2015-03-30 09:53:47 -070086SK_DECLARE_STATIC_SPINLOCK(gProcessorSpinlock);
bsalomon5baedd62015-03-09 12:15:53 -070087class MemoryPoolAccessor {
tomhudson@google.comdcba4c22012-07-24 21:36:16 +000088public:
joshualitt23ac62c2015-03-30 09:53:47 -070089 MemoryPoolAccessor() { gProcessorSpinlock.acquire(); }
tomhudson@google.comdcba4c22012-07-24 21:36:16 +000090
joshualitt23ac62c2015-03-30 09:53:47 -070091 ~MemoryPoolAccessor() { gProcessorSpinlock.release(); }
tomhudson@google.comdcba4c22012-07-24 21:36:16 +000092
bsalomon5baedd62015-03-09 12:15:53 -070093 GrMemoryPool* pool() const {
94 static GrMemoryPool gPool(4096, 4096);
95 return &gPool;
tomhudson@google.comdcba4c22012-07-24 21:36:16 +000096 }
97};
bsalomon5baedd62015-03-09 12:15:53 -070098}
tomhudson@google.comdcba4c22012-07-24 21:36:16 +000099
bsalomon5baedd62015-03-09 12:15:53 -0700100int32_t GrProcessor::gCurrProcessorClassID = GrProcessor::kIllegalProcessorClassID;
tomhudson@google.com168e6342012-04-18 17:49:20 +0000101
bsalomon@google.com0ac6af42013-01-16 15:16:18 +0000102///////////////////////////////////////////////////////////////////////////////
103
joshualittb0a8a372014-09-23 09:50:21 -0700104GrProcessor::~GrProcessor() {}
tomhudson@google.com168e6342012-04-18 17:49:20 +0000105
joshualittb0a8a372014-09-23 09:50:21 -0700106void GrProcessor::addTextureAccess(const GrTextureAccess* access) {
bsalomon@google.com50db75c2013-01-11 13:54:30 +0000107 fTextureAccesses.push_back(access);
bsalomonf96ba022014-09-17 08:05:40 -0700108 this->addGpuResource(access->getProgramTexture());
twiz@google.coma5e65ec2012-08-02 15:15:16 +0000109}
110
joshualittb0a8a372014-09-23 09:50:21 -0700111void* GrProcessor::operator new(size_t size) {
bsalomon5baedd62015-03-09 12:15:53 -0700112 return MemoryPoolAccessor().pool()->allocate(size);
tomhudson@google.comdcba4c22012-07-24 21:36:16 +0000113}
114
joshualittb0a8a372014-09-23 09:50:21 -0700115void GrProcessor::operator delete(void* target) {
bsalomon5baedd62015-03-09 12:15:53 -0700116 return MemoryPoolAccessor().pool()->release(target);
tomhudson@google.comdcba4c22012-07-24 21:36:16 +0000117}
bsalomon@google.com77af6802013-10-02 13:04:56 +0000118
bsalomon420d7e92014-10-16 09:18:09 -0700119bool GrProcessor::hasSameTextureAccesses(const GrProcessor& that) const {
120 if (this->numTextures() != that.numTextures()) {
121 return false;
bsalomon@google.com77af6802013-10-02 13:04:56 +0000122 }
bsalomon420d7e92014-10-16 09:18:09 -0700123 for (int i = 0; i < this->numTextures(); ++i) {
124 if (this->textureAccess(i) != that.textureAccess(i)) {
125 return false;
126 }
127 }
128 return true;
bsalomon@google.com77af6802013-10-02 13:04:56 +0000129}
egdaniel1a8ecdf2014-10-03 06:24:12 -0700130
joshualitta5305a12014-10-10 17:47:00 -0700131///////////////////////////////////////////////////////////////////////////////////////////////////
132
bsalomonac856c92015-08-27 06:30:17 -0700133GrFragmentProcessor::~GrFragmentProcessor() {
bsalomon42048002015-08-27 16:43:48 -0700134 // If we got here then our ref count must have reached zero, so we will have converted refs
135 // to pending executions for all children.
bsalomonac856c92015-08-27 06:30:17 -0700136 for (int i = 0; i < fChildProcessors.count(); ++i) {
bsalomon42048002015-08-27 16:43:48 -0700137 fChildProcessors[i]->completedExecution();
bsalomonac856c92015-08-27 06:30:17 -0700138 }
139}
140
wangyix54017d72015-08-18 07:39:33 -0700141bool GrFragmentProcessor::isEqual(const GrFragmentProcessor& that,
142 bool ignoreCoordTransforms) const {
143 if (this->classID() != that.classID() ||
144 !this->hasSameTextureAccesses(that)) {
145 return false;
146 }
147 if (ignoreCoordTransforms) {
148 if (this->numTransforms() != that.numTransforms()) {
149 return false;
150 }
151 } else if (!this->hasSameTransforms(that)) {
152 return false;
153 }
154 if (!this->onIsEqual(that)) {
155 return false;
156 }
157 if (this->numChildProcessors() != that.numChildProcessors()) {
158 return false;
159 }
160 for (int i = 0; i < this->numChildProcessors(); ++i) {
161 if (!this->childProcessor(i).isEqual(that.childProcessor(i), ignoreCoordTransforms)) {
162 return false;
163 }
164 }
165 return true;
166}
167
wangyixb1daa862015-08-18 11:29:31 -0700168GrGLFragmentProcessor* GrFragmentProcessor::createGLInstance() const {
169 GrGLFragmentProcessor* glFragProc = this->onCreateGLInstance();
170 glFragProc->fChildProcessors.push_back_n(fChildProcessors.count());
171 for (int i = 0; i < fChildProcessors.count(); ++i) {
bsalomonac856c92015-08-27 06:30:17 -0700172 glFragProc->fChildProcessors[i] = fChildProcessors[i]->createGLInstance();
wangyixb1daa862015-08-18 11:29:31 -0700173 }
174 return glFragProc;
175}
176
wangyix93ab2542015-08-19 08:23:12 -0700177void GrFragmentProcessor::addTextureAccess(const GrTextureAccess* textureAccess) {
178 // Can't add texture accesses after registering any children since their texture accesses have
179 // already been bubbled up into our fTextureAccesses array
180 SkASSERT(fChildProcessors.empty());
181
182 INHERITED::addTextureAccess(textureAccess);
183 fNumTexturesExclChildren++;
184}
185
joshualitta5305a12014-10-10 17:47:00 -0700186void GrFragmentProcessor::addCoordTransform(const GrCoordTransform* transform) {
wangyix93ab2542015-08-19 08:23:12 -0700187 // Can't add transforms after registering any children since their transforms have already been
188 // bubbled up into our fCoordTransforms array
189 SkASSERT(fChildProcessors.empty());
190
joshualitta5305a12014-10-10 17:47:00 -0700191 fCoordTransforms.push_back(transform);
joshualitt290c09b2014-12-19 13:45:20 -0800192 fUsesLocalCoords = fUsesLocalCoords || transform->sourceCoords() == kLocal_GrCoordSet;
bsalomonf2765412014-10-15 18:34:46 -0700193 SkDEBUGCODE(transform->setInProcessor();)
wangyix93ab2542015-08-19 08:23:12 -0700194 fNumTransformsExclChildren++;
joshualitta5305a12014-10-10 17:47:00 -0700195}
bsalomonde258cd2014-10-15 19:06:21 -0700196
wangyix58d890b2015-08-12 09:40:47 -0700197int GrFragmentProcessor::registerChildProcessor(const GrFragmentProcessor* child) {
198 // Append the child's transforms to our transforms array and the child's textures array to our
199 // textures array
200 if (!child->fCoordTransforms.empty()) {
201 fCoordTransforms.push_back_n(child->fCoordTransforms.count(),
202 child->fCoordTransforms.begin());
203 }
204 if (!child->fTextureAccesses.empty()) {
205 fTextureAccesses.push_back_n(child->fTextureAccesses.count(),
206 child->fTextureAccesses.begin());
207 }
208
209 int index = fChildProcessors.count();
bsalomonac856c92015-08-27 06:30:17 -0700210 fChildProcessors.push_back(SkRef(child));
wangyix58d890b2015-08-12 09:40:47 -0700211
wangyix7ef45a12015-08-13 06:51:35 -0700212 if (child->willReadFragmentPosition()) {
wangyix58d890b2015-08-12 09:40:47 -0700213 this->setWillReadFragmentPosition();
wangyix7ef45a12015-08-13 06:51:35 -0700214 }
wangyix58d890b2015-08-12 09:40:47 -0700215
wangyixa71170c2015-08-21 06:56:49 -0700216 if (child->usesLocalCoords()) {
217 fUsesLocalCoords = true;
218 }
219
wangyix58d890b2015-08-12 09:40:47 -0700220 return index;
wangyix4b3050b2015-08-04 07:59:37 -0700221}
222
bsalomon42048002015-08-27 16:43:48 -0700223void GrFragmentProcessor::notifyRefCntIsZero() const {
224 // See comment above GrProgramElement for a detailed explanation of why we do this.
225 for (int i = 0; i < fChildProcessors.count(); ++i) {
226 fChildProcessors[i]->addPendingExecution();
227 fChildProcessors[i]->unref();
228 }
229}
230
bsalomonde258cd2014-10-15 19:06:21 -0700231bool GrFragmentProcessor::hasSameTransforms(const GrFragmentProcessor& that) const {
wangyix58d890b2015-08-12 09:40:47 -0700232 if (this->numTransforms() != that.numTransforms()) {
bsalomonde258cd2014-10-15 19:06:21 -0700233 return false;
234 }
wangyix58d890b2015-08-12 09:40:47 -0700235 int count = this->numTransforms();
bsalomonde258cd2014-10-15 19:06:21 -0700236 for (int i = 0; i < count; ++i) {
wangyix58d890b2015-08-12 09:40:47 -0700237 if (this->coordTransform(i) != that.coordTransform(i)) {
bsalomonde258cd2014-10-15 19:06:21 -0700238 return false;
239 }
240 }
241 return true;
242}
joshualittc07379d2014-11-20 14:50:39 -0800243
bsalomon87ba62e2015-09-22 06:41:59 -0700244#include "effects/GrXfermodeFragmentProcessor.h"
245
246const GrFragmentProcessor* GrFragmentProcessor::MulOuputByInputAlpha(
247 const GrFragmentProcessor* fp) {
248 return GrXfermodeFragmentProcessor::CreateFromDstProcessor(fp, SkXfermode::kDstIn_Mode);
249}
250
joshualittc07379d2014-11-20 14:50:39 -0800251///////////////////////////////////////////////////////////////////////////////////////////////////
252
egdaniel915187b2014-12-05 12:58:28 -0800253// Initial static variable from GrXPFactory
254int32_t GrXPFactory::gCurrXPFClassID =
255 GrXPFactory::kIllegalXPFClassID;