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