1168e63418cadba4018aadf95c091d40d9deb13b9tomhudson@google.com/* 2168e63418cadba4018aadf95c091d40d9deb13b9tomhudson@google.com * Copyright 2012 Google Inc. 3168e63418cadba4018aadf95c091d40d9deb13b9tomhudson@google.com * 4168e63418cadba4018aadf95c091d40d9deb13b9tomhudson@google.com * Use of this source code is governed by a BSD-style license that can be 5168e63418cadba4018aadf95c091d40d9deb13b9tomhudson@google.com * found in the LICENSE file. 6168e63418cadba4018aadf95c091d40d9deb13b9tomhudson@google.com */ 7168e63418cadba4018aadf95c091d40d9deb13b9tomhudson@google.com 8b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#ifndef GrProcessor_DEFINED 9b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#define GrProcessor_DEFINED 10168e63418cadba4018aadf95c091d40d9deb13b9tomhudson@google.com 11371e105da5d9fdfff3b4242b37ff6fc09214c8c8bsalomon@google.com#include "GrColor.h" 12b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt#include "GrProcessorUnitTest.h" 1395740981c36266e4595ddde2264aa38e3c7e2d02bsalomon#include "GrProgramElement.h" 14047696c1c67b2e0a73f2b951ce23ff5b155111bbbsalomon@google.com#include "GrTextureAccess.h" 159e4d6d180fcfbbe2ea242196cc0affd45b7ed7aeegdaniel#include "SkMath.h" 1607eecdca3e331eb4066c53a29305aeea6d692961tomhudson@google.com 17168e63418cadba4018aadf95c091d40d9deb13b9tomhudson@google.comclass GrContext; 1877af6805e5faea1e2a5c0220098aec9082f3a6e5bsalomon@google.comclass GrCoordTransform; 19605dd0fbce9dbb2a0d3313e13e161f2bd54870d7egdanielclass GrInvariantOutput; 2095740981c36266e4595ddde2264aa38e3c7e2d02bsalomon 21eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt/** 22eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt * Used by processors to build their keys. It incorporates each per-processor key into a larger 23eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt * shader key. 24eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt */ 25eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualittclass GrProcessorKeyBuilder { 26eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualittpublic: 27eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt GrProcessorKeyBuilder(SkTArray<unsigned char, true>* data) : fData(data), fCount(0) { 28eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt SkASSERT(0 == fData->count() % sizeof(uint32_t)); 29eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt } 30eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 31eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt void add32(uint32_t v) { 32eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt ++fCount; 33eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt fData->push_back_n(4, reinterpret_cast<uint8_t*>(&v)); 34eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt } 35eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 36eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt /** Inserts count uint32_ts into the key. The returned pointer is only valid until the next 37eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt add*() call. */ 38eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt uint32_t* SK_WARN_UNUSED_RESULT add32n(int count) { 39eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt SkASSERT(count > 0); 40eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt fCount += count; 41eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt return reinterpret_cast<uint32_t*>(fData->push_back_n(4 * count)); 42eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt } 43eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 44eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt size_t size() const { return sizeof(uint32_t) * fCount; } 45eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 46eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualittprivate: 47eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt SkTArray<uint8_t, true>* fData; // unowned ptr to the larger key. 48eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt int fCount; // number of uint32_ts added to fData by the processor. 49eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt}; 50eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 5198b33ebe6f66ed59b023cf16a09c0a40eb4510cebsalomon/** Provides custom shader code to the Ganesh shading pipeline. GrProcessor objects *must* be 5298b33ebe6f66ed59b023cf16a09c0a40eb4510cebsalomon immutable: after being constructed, their fields may not change. 530ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com 54b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt Dynamically allocated GrProcessors are managed by a per-thread memory pool. The ref count of an 5598b33ebe6f66ed59b023cf16a09c0a40eb4510cebsalomon processor must reach 0 before the thread terminates and the pool is destroyed. To create a 5698b33ebe6f66ed59b023cf16a09c0a40eb4510cebsalomon static processor use the helper macro GR_CREATE_STATIC_PROCESSOR declared below. 5798b33ebe6f66ed59b023cf16a09c0a40eb4510cebsalomon */ 58b0a8a377f832c59cee939ad721e1f87d378b7142joshualittclass GrProcessor : public GrProgramElement { 59168e63418cadba4018aadf95c091d40d9deb13b9tomhudson@google.compublic: 60b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt SK_DECLARE_INST_COUNT(GrProcessor) 6115e9d3e66e161ce23df30bc13f8a0c87d196b463robertphillips@google.com 62b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt virtual ~GrProcessor(); 63168e63418cadba4018aadf95c091d40d9deb13b9tomhudson@google.com 6498b33ebe6f66ed59b023cf16a09c0a40eb4510cebsalomon /** Human-meaningful string to identify this prcoessor; may be embedded 65a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com in generated shader code. */ 66eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt virtual const char* name() const = 0; 67289efe014ad7628de7cf2c5177a42cacd1e335adbsalomon@google.com 6850db75c871b203081a32190ab173f13c785a147fbsalomon@google.com int numTextures() const { return fTextureAccesses.count(); } 69168e63418cadba4018aadf95c091d40d9deb13b9tomhudson@google.com 706d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com /** Returns the access pattern for the texture at index. index must be valid according to 716d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com numTextures(). */ 7250db75c871b203081a32190ab173f13c785a147fbsalomon@google.com const GrTextureAccess& textureAccess(int index) const { return *fTextureAccesses[index]; } 736d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com 746d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com /** Shortcut for textureAccess(index).texture(); */ 756d003d1ddced3e71684b8b3785d1e5a16255688dbsalomon@google.com GrTexture* texture(int index) const { return this->textureAccess(index).getTexture(); } 76a5e65ec434fed44dc616e4f64950b835b541181btwiz@google.com 7798b33ebe6f66ed59b023cf16a09c0a40eb4510cebsalomon /** Will this processor read the fragment position? */ 788d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org bool willReadFragmentPosition() const { return fWillReadFragmentPosition; } 79ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org 80dcba4c2cc30cc64f08def991376c6dab65cfb51ctomhudson@google.com void* operator new(size_t size); 81dcba4c2cc30cc64f08def991376c6dab65cfb51ctomhudson@google.com void operator delete(void* target); 82dcba4c2cc30cc64f08def991376c6dab65cfb51ctomhudson@google.com 83d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com void* operator new(size_t size, void* placement) { 84d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com return ::operator new(size, placement); 85d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com } 86d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com void operator delete(void* target, void* placement) { 87d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com ::operator delete(target, placement); 88d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com } 89d42aca31b9ddc1cb9a81522b4c73a9fe550450bcbsalomon@google.com 9049586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt /** 91b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt * Helper for down-casting to a GrProcessor subclass 9249586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt */ 9349586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt template <typename T> const T& cast() const { return *static_cast<const T*>(this); } 9449586bec7383d4ccb81f85f8e2dc4162e2d4f6a8joshualitt 95eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt uint32_t classID() const { SkASSERT(kIllegalProcessorClassID != fClassID); return fClassID; } 96eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 9750db75c871b203081a32190ab173f13c785a147fbsalomon@google.comprotected: 98eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt GrProcessor() : fClassID(kIllegalProcessorClassID), fWillReadFragmentPosition(false) {} 99420d7e9a79358908850c74192b4949375563449absalomon 10050db75c871b203081a32190ab173f13c785a147fbsalomon@google.com /** 10198b33ebe6f66ed59b023cf16a09c0a40eb4510cebsalomon * Subclasses call this from their constructor to register GrTextureAccesses. The processor 10291a798f121a2238639f8e2d08cc776d4f0236cebcommit-bot@chromium.org * subclass manages the lifetime of the accesses (this function only stores a pointer). The 103b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt * GrTextureAccess is typically a member field of the GrProcessor subclass. This must only be 104b0a8a377f832c59cee939ad721e1f87d378b7142joshualitt * called from the constructor because GrProcessors are immutable. 10550db75c871b203081a32190ab173f13c785a147fbsalomon@google.com */ 10650db75c871b203081a32190ab173f13c785a147fbsalomon@google.com void addTextureAccess(const GrTextureAccess* textureAccess); 10750db75c871b203081a32190ab173f13c785a147fbsalomon@google.com 108420d7e9a79358908850c74192b4949375563449absalomon bool hasSameTextureAccesses(const GrProcessor&) const; 1098d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org 1108d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org /** 11198b33ebe6f66ed59b023cf16a09c0a40eb4510cebsalomon * If the prcoessor will generate a backend-specific processor that will read the fragment 11298b33ebe6f66ed59b023cf16a09c0a40eb4510cebsalomon * position in the FS then it must call this method from its constructor. Otherwise, the 11398b33ebe6f66ed59b023cf16a09c0a40eb4510cebsalomon * request to access the fragment position will be denied. 1148d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org */ 1158d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org void setWillReadFragmentPosition() { fWillReadFragmentPosition = true; } 11626e18b593ab65e4d92dfbce92579d8bc180d4c2cbsalomon@google.com 117eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt template <typename PROC_SUBCLASS> void initClassID() { 118eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt static uint32_t kClassID = GenClassID(); 119eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt fClassID = kClassID; 120eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt } 121eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 122eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt uint32_t fClassID; 123eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 1240e08fc17e4718f7ce4e38f793695896473e96948bsalomonprivate: 125eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt static uint32_t GenClassID() { 126eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt // fCurrProcessorClassID has been initialized to kIllegalProcessorClassID. The 127eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt // atomic inc returns the old value not the incremented value. So we add 128eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt // 1 to the returned value. 129eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt uint32_t id = static_cast<uint32_t>(sk_atomic_inc(&gCurrProcessorClassID)) + 1; 130eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt if (!id) { 131eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt SkFAIL("This should never wrap as it should only be called once for each GrProcessor " 132eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt "subclass."); 133eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt } 134eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt return id; 135eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt } 136eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt 137eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt enum { 138eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt kIllegalProcessorClassID = 0, 139eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt }; 140eb2a6761654307e8aeeeaabdd63c6bf9ab0411e9joshualitt static int32_t gCurrProcessorClassID; 1410ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com 142ff6ea2663f76aa85ec55ddd0f00ca7906f1bc4e3commit-bot@chromium.org SkSTArray<4, const GrTextureAccess*, true> fTextureAccesses; 1438d47ddc19a40d1984bf1f384d711d36ab59fd1c0commit-bot@chromium.org bool fWillReadFragmentPosition; 1440ac6af49975c54c2debf41e9200af416ecd2d973bsalomon@google.com 14595740981c36266e4595ddde2264aa38e3c7e2d02bsalomon typedef GrProgramElement INHERITED; 146168e63418cadba4018aadf95c091d40d9deb13b9tomhudson@google.com}; 147168e63418cadba4018aadf95c091d40d9deb13b9tomhudson@google.com 14898b33ebe6f66ed59b023cf16a09c0a40eb4510cebsalomon/** 14998b33ebe6f66ed59b023cf16a09c0a40eb4510cebsalomon * This creates a processor outside of the memory pool. The processor's destructor will be called 15098b33ebe6f66ed59b023cf16a09c0a40eb4510cebsalomon * at global destruction time. NAME will be the name of the created instance. 15198b33ebe6f66ed59b023cf16a09c0a40eb4510cebsalomon */ 15298b33ebe6f66ed59b023cf16a09c0a40eb4510cebsalomon#define GR_CREATE_STATIC_PROCESSOR(NAME, PROC_CLASS, ARGS) \ 15398b33ebe6f66ed59b023cf16a09c0a40eb4510cebsalomonstatic SkAlignedSStorage<sizeof(PROC_CLASS)> g_##NAME##_Storage; \ 15498b33ebe6f66ed59b023cf16a09c0a40eb4510cebsalomonstatic PROC_CLASS* NAME SkNEW_PLACEMENT_ARGS(g_##NAME##_Storage.get(), PROC_CLASS, ARGS); \ 15598b33ebe6f66ed59b023cf16a09c0a40eb4510cebsalomonstatic SkAutoTDestroy<GrProcessor> NAME##_ad(NAME); 15698b33ebe6f66ed59b023cf16a09c0a40eb4510cebsalomon 157168e63418cadba4018aadf95c091d40d9deb13b9tomhudson@google.com#endif 158