code:
/*
    Copyright 2010 Google Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
 */

#ifndef GrSamplerState_DEFINED
#define GrSamplerState_DEFINED

#include "GrTypes.h"
#include "GrMatrix.h"

class GrSamplerState {
public:
    enum Filter {
        /**
         * Read the closest src texel to the sample position
         */
        kNearest_Filter,
        /**
         * Blend between closest 4 src texels to sample position (tent filter)
         */
        kBilinear_Filter,
        /**
         * Average of 4 bilinear filterings spaced +/- 1 texel from sample
         * position in x and y. Intended for averaging 16 texels in a downsample
         * pass. (rasterizing such that texture samples fall exactly halfway
         * between texels in x and y spaced 4 texels apart.)
         */
        k4x4Downsample_Filter,
    };

    /**
     * The intepretation of the texture matrix depends on the sample mode. The
     * texture matrix is applied both when the texture coordinates are explicit
     * and  when vertex positions are used as texture  coordinates. In the latter
     * case the texture matrix is applied to the pre-view-matrix position
     * values.
     *
     * kNormal_SampleMode
     *  The post-matrix texture coordinates are in normalize space with (0,0) at
     *  the top-left and (1,1) at the bottom right.
     * kRadial_SampleMode
     *  The matrix specifies the radial gradient parameters.
     *  (0,0) in the post-matrix space is center of the radial gradient.
     * kRadial2_SampleMode
     *   Matrix transforms to space where first circle is centered at the
     *   origin. The second circle will be centered (x, 0) where x may be
     *   0 and is provided by setRadial2Params. The post-matrix space is
     *   normalized such that 1 is the second radius - first radius.
     * kSweepSampleMode
     *  The angle from the origin of texture coordinates in post-matrix space
     *  determines the gradient value.
     */
    enum SampleMode {
        kNormal_SampleMode,     //!< sample color directly
        kRadial_SampleMode,     //!< treat as radial gradient
        kRadial2_SampleMode,    //!< treat as 2-point radial gradient
        kSweep_SampleMode,      //!< treat as sweep gradient
    };

    /**
     * Describes how a texture is sampled when coordinates are outside the
     * texture border
     */
    enum WrapMode {
        kClamp_WrapMode,
        kRepeat_WrapMode,
        kMirror_WrapMode
    };

    /**
     * Default sampler state is set to clamp, use normal sampling mode, be
     * unfiltered, and use identity matrix.
     */
    GrSamplerState()
    : fRadial2CenterX1()
    , fRadial2Radius0()
    , fRadial2PosRoot() {
        this->setClampNoFilter();
    }

    explicit GrSamplerState(Filter filter)
    : fRadial2CenterX1()
    , fRadial2Radius0()
    , fRadial2PosRoot() {
        fWrapX = kClamp_WrapMode;
        fWrapY = kClamp_WrapMode;
        fSampleMode = kNormal_SampleMode;
        fFilter = filter;
        fMatrix.setIdentity();
        fTextureDomain.setEmpty();
    }

    GrSamplerState(WrapMode wx, WrapMode wy, Filter filter)
    : fRadial2CenterX1()
    , fRadial2Radius0()
    , fRadial2PosRoot() {
        fWrapX = wx;
        fWrapY = wy;
        fSampleMode = kNormal_SampleMode;
        fFilter = filter;
        fMatrix.setIdentity();
        fTextureDomain.setEmpty();
    }

    GrSamplerState(WrapMode wx, WrapMode wy,
                   const GrMatrix& matrix, Filter filter)
    : fRadial2CenterX1()
    , fRadial2Radius0()
    , fRadial2PosRoot() {
        fWrapX = wx;
        fWrapY = wy;
        fSampleMode = kNormal_SampleMode;
        fFilter = filter;
        fMatrix = matrix;
        fTextureDomain.setEmpty();
    }

    GrSamplerState(WrapMode wx, WrapMode wy, SampleMode sample,
                   const GrMatrix& matrix, Filter filter)
    : fRadial2CenterX1()
    , fRadial2Radius0()
    , fRadial2PosRoot() {
        fWrapX = wx;
        fWrapY = wy;
        fSampleMode = sample;
        fMatrix = matrix;
        fFilter = filter;
        fTextureDomain.setEmpty();
    }

    WrapMode getWrapX() const { return fWrapX; }
    WrapMode getWrapY() const { return fWrapY; }
    SampleMode getSampleMode() const { return fSampleMode; }
    const GrMatrix& getMatrix() const { return fMatrix; }
    const GrRect& getTextureDomain() const { return fTextureDomain; }
    bool hasTextureDomain() const {return SkIntToScalar(0) != fTextureDomain.right();}
    Filter getFilter() const { return fFilter; }

    bool isGradient() const {
        return  kRadial_SampleMode == fSampleMode ||
                kRadial2_SampleMode == fSampleMode ||
                kSweep_SampleMode == fSampleMode;
    }

    void setWrapX(WrapMode mode) { fWrapX = mode; }
    void setWrapY(WrapMode mode) { fWrapY = mode; }
    void setSampleMode(SampleMode mode) { fSampleMode = mode; }

    /**
     * Sets the sampler's matrix. See SampleMode for explanation of
     * relationship between the matrix and sample mode.
     * @param matrix the matrix to set
     */
    void setMatrix(const GrMatrix& matrix) { fMatrix = matrix; }

    /**
     * Sets the sampler's texture coordinate domain to a
     * custom rectangle, rather than the default (0,1).
     * This option is currently only supported with kClamp_WrapMode
     */
    void setTextureDomain(const GrRect& textureDomain) { fTextureDomain = textureDomain; }

    /**
     *  Multiplies the current sampler matrix  a matrix
     *
     *  After this call M' = M*m where M is the old matrix, m is the parameter
     *  to this function, and M' is the new matrix. (We consider points to
     *  be column vectors so tex cood vector t is transformed by matrix X as
     *  t' = X*t.)
     *
     *  @param matrix   the matrix used to modify the matrix.
     */
    void preConcatMatrix(const GrMatrix& matrix) { fMatrix.preConcat(matrix); }

    /**
     * Sets filtering type.
     * @param filter    type of filtering to apply
     */
    void setFilter(Filter filter) { fFilter = filter; }

    void setClampNoFilter() {
        fWrapX = kClamp_WrapMode;
        fWrapY = kClamp_WrapMode;
        fSampleMode = kNormal_SampleMode;
        fFilter = kNearest_Filter;
        fMatrix.setIdentity();
        fTextureDomain.setEmpty();
    }

    GrScalar getRadial2CenterX1() const { return fRadial2CenterX1; }
    GrScalar getRadial2Radius0() const { return fRadial2Radius0; }
    bool     isRadial2PosRoot() const { return fRadial2PosRoot; }

    /**
     * Sets the parameters for kRadial2_SampleMode. The texture
     * matrix must be set so that the first point is at (0,0) and the second
     * point lies on the x-axis. The second radius minus the first is 1 unit.
     * The additional parameters to define the gradient are specified by this
     * function.
     */
    void setRadial2Params(GrScalar centerX1, GrScalar radius0, bool posRoot) {
        fRadial2CenterX1 = centerX1;
        fRadial2Radius0 = radius0;
        fRadial2PosRoot = posRoot;
    }

    static const GrSamplerState& ClampNoFilter() {
        return gClampNoFilter;
    }

private:
    WrapMode    fWrapX;
    WrapMode    fWrapY;
    SampleMode  fSampleMode;
    Filter      fFilter;
    GrMatrix    fMatrix;
    GrRect      fTextureDomain;

    // these are undefined unless fSampleMode == kRadial2_SampleMode
    GrScalar    fRadial2CenterX1;
    GrScalar    fRadial2Radius0;
    bool        fRadial2PosRoot;

    static const GrSamplerState gClampNoFilter;
};

#endif


code:
/*
    Copyright 2010 Google Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
 */

#ifndef GrScalar_DEFINED
#define GrScalar_DEFINED

#include "GrTypes.h"
#include "SkScalar.h"

#define GR_Int32Min         SK_NaN32
#define GR_Int32Max         SK_MaxS32

#define GR_Fixed1           SK_Fixed1
#define GR_FixedHalf        SK_FixedHalf
#define GrIntToFixed(a)     SkIntToFixed(a)
#define GrFixedToFloat(a)   SkFixedToFloat(a)
#define GrFixedFloorToInt(a)    SkFixedFloor(a)

#define GrScalar            SkScalar
#define GR_Scalar1          SK_Scalar1
#define GR_ScalarHalf       SK_ScalarHalf
#define GR_ScalarMin        SK_ScalarMin
#define GR_ScalarMax        SK_ScalarMax

#define GrIntToScalar(a)    SkIntToScalar(a)
#define GrScalarHalf(a)     SkScalarHalf(a)
#define GrScalarAve(a,b)    SkScalarAve(a,b)
#define GrMul(a,b)          SkScalarMul(a,b)
#define GrScalarDiv(a,b)    SkScalarDiv(a, b)
#define GrScalarToFloat(a)  SkScalarToFloat(a)
#define GrFloatToScalar(a)  SkScalarToFloat(a)
#define GrIntToScalar(a)    SkIntToScalar(a)
#define GrScalarAbs(a)      SkScalarAbs(a)
#define GrScalarIsInt(a)    SkScalarIsInt(a)
#define GrScalarMax(a,b)    SkScalarMax(a,b)
#define GrScalarFloorToInt(a)   SkScalarFloor(a)
#define GrScalarCeilToInt(a)    SkScalarCeil(a)
#define GrFixedToScalar(a)  SkFixedToScalar(a)

#endif

license: mit


code:
/*
    Copyright 2011 Google Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
 */

#ifndef GrStencil_DEFINED
#define GrStencil_DEFINED

#include "GrTypes.h"
/**
 * Gr uses the stencil buffer to implement complex clipping inside the
 * GrDrawTarget class. The GrDrawTarget makes a subset of the stencil buffer
 * bits available for other uses by external code (clients). Client code can
 * modify these bits. GrDrawTarget will ignore ref, mask, and writemask bits
 * provided by clients that overlap the bits used to implement clipping. The
 * client can use the getUsableStencilBits() function to find out how many
 * client accessible stencil bits are available.
 *
 * When code outside the GrDrawTarget class uses the stencil buffer the contract
 * is as follows:
 *
 * > Normal stencil funcs allow the GrGpu client to modify the client bits of
 *   the stencil buffer outside of the clip.
 * > Special functions allow a test against the clip. These are more limited
 *   than the general stencil functions.
 * > Client can assume all client bits are zero initially.
 * > Client must ensure that after all its passes are finished it has only
 *   written to the color buffer in the region inside the clip. Furthermore, it
 *   must zero all client bits that were modifed (both inside and outside the
 *   clip).
 */

/**
 * Determines which pixels pass / fail the stencil test.
 * Stencil test passes if (ref & mask) FUNC (stencil & mask) is true
 */
enum GrStencilFunc {
    kAlways_StencilFunc = 0,
    kNever_StencilFunc,
    kGreater_StencilFunc,
    kGEqual_StencilFunc,
    kLess_StencilFunc,
    kLEqual_StencilFunc,
    kEqual_StencilFunc,
    kNotEqual_StencilFunc,

    // Gr stores the current clip in the
    // stencil buffer in the high bits that
    // are not directly accessible modifiable
    // via the GrDrawTarget interface. The below
    // stencil funcs test against the current
    // clip in addition to the GrDrawTarget
    // client's stencil bits.

    // pass if inside the clip
    kAlwaysIfInClip_StencilFunc,
    kEqualIfInClip_StencilFunc,
    kLessIfInClip_StencilFunc,
    kLEqualIfInClip_StencilFunc,
    kNonZeroIfInClip_StencilFunc, // this one forces the ref to be 0

    // counts
    kStencilFuncCount,
    kClipStencilFuncCount = kNonZeroIfInClip_StencilFunc -
                            kAlwaysIfInClip_StencilFunc + 1,
    kBasicStencilFuncCount = kStencilFuncCount - kClipStencilFuncCount
};

/**
 * Operations to perform based on whether stencil test passed failed.
 */
enum GrStencilOp {
    kKeep_StencilOp = 0,    // preserve existing stencil value
    kReplace_StencilOp,     // replace with reference value from stencl test
    kIncWrap_StencilOp,     // increment and wrap at max
    kIncClamp_StencilOp,    // increment and clamp at max
    kDecWrap_StencilOp,     // decrement and wrap at 0
    kDecClamp_StencilOp,    // decrement and clamp at 0
    kZero_StencilOp,        // zero stencil bits
    kInvert_StencilOp,      // invert stencil bits

    kStencilOpCount
};

/**
 * Struct representing stencil state.
 */
struct GrStencilSettings {
    GrStencilOp   fFrontPassOp;     // op to perform when front faces pass
    GrStencilOp   fBackPassOp;      // op to perform when back faces pass
    GrStencilOp   fFrontFailOp;     // op to perform when front faces fail
    GrStencilOp   fBackFailOp;      // op to perform when back faces fail
    GrStencilFunc fFrontFunc;       // test function for front faces
    GrStencilFunc fBackFunc;        // test function for back faces
    unsigned int fFrontFuncMask;    // mask for front face test
    unsigned int fBackFuncMask;     // mask for back face test
    unsigned int fFrontFuncRef;     // reference value for front face test
    unsigned int fBackFuncRef;      // reference value for back face test
    unsigned int fFrontWriteMask;   // stencil write mask for front faces
    unsigned int fBackWriteMask;    // stencil write mask for back faces

    bool operator == (const GrStencilSettings& s) const {
        // make sure this is tightly packed.
        GR_STATIC_ASSERT(0 == sizeof(GrStencilOp)%4);
        GR_STATIC_ASSERT(0 == sizeof(GrStencilFunc)%4);
        GR_STATIC_ASSERT(sizeof(GrStencilSettings) ==
                        4*sizeof(GrStencilOp) +
                        2*sizeof(GrStencilFunc) +
                        6*sizeof(unsigned int));
        return 0 == memcmp(this, &s, sizeof(GrStencilSettings));
    }

    bool operator != (const GrStencilSettings& s) const {
        return !(*this == s);
    }

    GrStencilSettings& operator =(const GrStencilSettings& s) {
        memcpy(this, &s, sizeof(GrStencilSettings));
        return *this;
    }

    void setSame(GrStencilOp passOp,
                 GrStencilOp failOp,
                 GrStencilFunc func,
                 unsigned int funcMask,
                 unsigned int funcRef,
                 unsigned int writeMask) {
        fFrontPassOp        = passOp;
        fBackPassOp         = passOp;
        fFrontFailOp        = failOp;
        fBackFailOp         = failOp;
        fFrontFunc          = func;
        fBackFunc           = func;
        fFrontFuncMask      = funcMask;
        fBackFuncMask       = funcMask;
        fFrontFuncRef       = funcRef;
        fBackFuncRef        = funcRef;
        fFrontWriteMask     = writeMask;
        fBackWriteMask      = writeMask;
    }

    // canonical value for disabled stenciling
    static const GrStencilSettings gDisabled;
    void setDisabled() {
        *this = gDisabled;
    }
    bool isDisabled() const {
        return kKeep_StencilOp == fFrontPassOp   &&
               kKeep_StencilOp == fBackPassOp    &&
               kKeep_StencilOp == fFrontFailOp   &&
               kKeep_StencilOp == fBackFailOp   &&
               kAlways_StencilFunc == fFrontFunc &&
               kAlways_StencilFunc == fBackFunc;
    }
    void invalidate()  {
        // just write an illegal value to the first member
        fFrontPassOp = (GrStencilOp)-1;
    }

private:
    friend class GrGpu;

    enum {
        kMaxStencilClipPasses = 2  // maximum number of passes to add a clip
                                   // element to the stencil buffer.
    };

    /**
     * Given a thing to draw into the stencil clip, a fill type, and a set op
     * this function determines:
     *      1. Whether the thing can be draw directly to the stencil clip or
     *      needs to be drawn to the client portion of the stencil first.
     *      2. How many passes are needed.
     *      3. What those passes are.
     *      4. The fill rule that should actually be used to render (will
     *         always be non-inverted).
     *
     * @param op                the set op to combine this element with the
     *                          existing clip
     * @param stencilClipMask   mask with just the stencil bit used for clipping
     *                          enabled.
     * @param invertedFill      is this path inverted
     * @param numPasses         out: the number of passes needed to add the
     *                               element to the clip.
     * @param settings          out: the stencil settings to use for each pass
     *
     * @return true if the clip element's geometry can be drawn directly to the
     *         stencil clip bit. Will only be true if canBeDirect is true.
     *         numPasses will be 1 if return value is true.
     */
    static bool GetClipPasses(GrSetOp op,
                              bool canBeDirect,
                              unsigned int stencilClipMask,
                              bool invertedFill,
                              int* numPasses,
                              GrStencilSettings settings[kMaxStencilClipPasses]);
};

#endif


code:
/*
    Copyright 2010 Google Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
 */

#ifndef GrStopwatch_DEFINED
#define GrStopwatch_DEFINED

#include "GrTypes.h"

template <typename PLATFORM_TIMER>
/**
 * Base class for stopwatch. Relies on PLATFORM_TIMER for platform-specific
 * timer functions. PLATFORM_TIMER provides:
 *      - typename TIMESTAMP : a timestamp value that can be used with Diff()
 *      - static TIMESTAMP Now() : gets current timestamp
 *      - static double Diff(const TIMESTAMP& begin, const TIMESTAMP& end) :
 *           computes delta in seconds between two timestamps
 */
class GrStopwatchBase {
public:
    /**
     * Contructor - implicit reset()
     */
    GrStopwatchBase() {
        fRunning = false;
        fTotalElapsed = 0.0;
    }

    /**
     * begins a new lap
     */
    void start() {
        double lastLap = lapTime();
        fTotalElapsed += lastLap;
        fRunning = true;
        fLastStart = PLATFORM_TIMER::Now();
    }

    /**
     * ends current lap (or no effect if lap not started)
     */
    void stop() {
        double lastLap = lapTime();
        fTotalElapsed += lastLap;
        fRunning = false;
    }

    /**
     * ends current lap, resets total time
     */
    void reset() {
        fRunning = false;
        fTotalElapsed = 0.f;
    }

    /**
     * Computes the time of all laps since last reset() including current lap
     * if lap is still running.
     *
     * @return the sum time in seconds of all laps since last reset().
     */
    double totalTime() const {
        return fTotalElapsed + lapTime();
    }

    /**
     * Current lap time.
     *
     * @return time in seconds of current lap if one is running otherwise 0.
     */
    double lapTime() const {
        if (fRunning) {
            PLATFORM_TIMER::Timestamp now = PLATFORM_TIMER::Now();
            return PLATFORM_TIMER::Elapsed(fLastStart, now);
        }
        return 0.0;
    }

private:
    double fTotalElapsed;

    typename PLATFORM_TIMER::Timestamp fLastStart;
    bool                               fRunning;
};

#if GR_WIN32_BUILD

    #include <Windows.h>

    class GrWin32Timer {
    public:
        typedef LARGE_INTEGER Timestamp;

        static Timestamp Now() {
            LARGE_INTEGER now;
            QueryPerformanceCounter(&now);
            return now;
        }

        static double Elapsed(const Timestamp& begin, const Timestamp& end) {
            double diff = (double)(end.QuadPart - begin.QuadPart);
            return diff * Scale();
        }
    private:
        static double Scale() {
            static double scale;
            if (0.0 == scale) {
                LARGE_INTEGER freq;
                QueryPerformanceFrequency(&freq);
                GrAssert(0 != freq.QuadPart);
                scale = 1 / (double) freq.QuadPart;
            }
            return scale;
        }
    };
    typedef GrStopwatchBase<GrWin32Timer> GrStopwatch;
#else
    #error "Implement platform timer for stopwatch"
#endif

#endif


code:
/*
    Copyright 2010 Google Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
 */

#ifndef GrStringBuilder_DEFINED
#define GrStringBuilder_DEFINED

#include "SkString.h"

typedef SkString GrStringBuilder;

#endif


code:
/*
    Copyright 2010 Google Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
 */

#ifndef GrTArray_DEFINED
#define GrTArray_DEFINED

#include <new>
#include "GrTypes.h"
#include "GrTemplates.h"

// DATA_TYPE indicates that T has a trivial cons, destructor
// and can be shallow-copied
template <typename T, bool DATA_TYPE = false> class GrTArray {
public:
    GrTArray() {
        fCount = 0;
        fReserveCount = MIN_ALLOC_COUNT;
        fAllocCount = 0;
        fMemArray = NULL;
        fPreAllocMemArray = NULL;
    }

    explicit GrTArray(int reserveCount) {
        GrAssert(reserveCount >= 0);
        fCount = 0;
        fReserveCount = reserveCount > MIN_ALLOC_COUNT ? reserveCount :
                                                         MIN_ALLOC_COUNT;
        fAllocCount = fReserveCount;
        fMemArray = GrMalloc(sizeof(T) * fReserveCount);
        fPreAllocMemArray = NULL;
    }

    template <int N>
    GrTArray(GrAlignedSTStorage<N,T>* storage) {
        GrAssert(N > 0);
        fCount              = 0;
        fReserveCount       = N;
        fAllocCount         = N;
        fMemArray           = storage->get();
        fPreAllocMemArray   = storage->get();
    }

    GrTArray(void* preAllocStorage, int preAllocCount) {
        GrAssert(preAllocCount >= 0);
        // we allow NULL,0 args and revert to the default cons. behavior
        // this makes it possible for a owner-object to use same constructor
        // to get either prealloc or nonprealloc behavior based using same line
        GrAssert((NULL == preAllocStorage) == !preAllocCount);

        fCount              = 0;
        fReserveCount       = preAllocCount > 0 ? preAllocCount :
                                                  MIN_ALLOC_COUNT;
        fAllocCount         = preAllocCount;
        fMemArray           = preAllocStorage;
        fPreAllocMemArray   = preAllocStorage;
    }

    explicit GrTArray(const GrTArray& array) {
        fCount              = array.count();
        fReserveCount       = MIN_ALLOC_COUNT;
        fAllocCount         = GrMax(fReserveCount, fCount);
        fMemArray           = GrMalloc(sizeof(T) * fAllocCount);
        fPreAllocMemArray   = NULL;

        if (DATA_TYPE) {
            memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
        } else {
            for (int i = 0; i < fCount; ++i) {
                new (fItemArray + i) T(array[i]);
            }
        }
    }

    GrTArray(const T* array, int count) {
        GrAssert(count >= 0);
        fCount              = count;
        fReserveCount       = MIN_ALLOC_COUNT;
        fAllocCount         = GrMax(fReserveCount, fCount);
        fMemArray           = GrMalloc(sizeof(T) * fAllocCount);
        fPreAllocMemArray   = NULL;
        if (DATA_TYPE) {
            memcpy(fMemArray, array, sizeof(T) * fCount);
        } else {
            for (int i = 0; i < fCount; ++i) {
                new (fItemArray + i) T(array[i]);
            }
        }
    }

    GrTArray(const GrTArray& array,
             void* preAllocStorage, int preAllocCount) {

        GrAssert(preAllocCount >= 0);

        // for same reason as non-copying cons we allow NULL, 0 for prealloc
        GrAssert((NULL == preAllocStorage) == !preAllocCount);

        fCount              = array.count();
        fReserveCount       = preAllocCount > 0 ? preAllocCount :
                                                  MIN_ALLOC_COUNT;
        fPreAllocMemArray   = preAllocStorage;

        if (fReserveCount >= fCount && preAllocCount) {
            fAllocCount = fReserveCount;
            fMemArray = preAllocStorage;
        } else {
            fAllocCount = GrMax(fCount, fReserveCount);
            fMemArray = GrMalloc(fAllocCount * sizeof(T));
        }

        if (DATA_TYPE) {
            memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
        } else {
            for (int i = 0; i < fCount; ++i) {
                new (fItemArray + i) T(array[i]);
            }
        }
    }

    GrTArray(const T* array, int count,
             void* preAllocStorage, int preAllocCount) {

        GrAssert(count >= 0);
        GrAssert(preAllocCount >= 0);

        // for same reason as non-copying cons we allow NULL, 0 for prealloc
        GrAssert((NULL == preAllocStorage) == !preAllocCount);

        fCount              = count;
        fReserveCount       = (preAllocCount > 0) ? preAllocCount :
                                                    MIN_ALLOC_COUNT;
        fPreAllocMemArray   = preAllocStorage;

        if (fReserveCount >= fCount && preAllocCount) {
            fAllocCount = fReserveCount;
            fMemArray = preAllocStorage;
        } else {
            fAllocCount = GrMax(fCount, fReserveCount);
            fMemArray = GrMalloc(fAllocCount * sizeof(T));
        }

        if (DATA_TYPE) {
            memcpy(fMemArray, array, sizeof(T) * fCount);
        } else {
            for (int i = 0; i < fCount; ++i) {
                new (fItemArray + i) T(array[i]);
            }
        }
    }

    GrTArray& operator =(const GrTArray& array) {
        for (int i = 0; i < fCount; ++i) {
            fItemArray[i].~T();
        }
        fCount = 0;
        checkRealloc((int)array.count());
        fCount = array.count();
        if (DATA_TYPE) {
            memcpy(fMemArray, array.fMemArray, sizeof(T) * fCount);
        } else {
            for (int i = 0; i < fCount; ++i) {
                new (fItemArray + i) T(array[i]);
            }
        }
        return *this;
    }

    ~GrTArray() {
        for (int i = 0; i < fCount; ++i) {
            fItemArray[i].~T();
        }
        if (fMemArray != fPreAllocMemArray) {
            GrFree(fMemArray);
        }
    }

    void reset() { this->pop_back_n(fCount); }

    int count() const { return fCount; }

    bool empty() const { return !fCount; }

    T& push_back() {
        checkRealloc(1);
        new ((char*)fMemArray+sizeof(T)*fCount) T;
        ++fCount;
        return fItemArray[fCount-1];
    }

    void push_back_n(int n) {
        GrAssert(n >= 0);
        checkRealloc(n);
        for (int i = 0; i < n; ++i) {
            new (fItemArray + fCount + i) T;
        }
        fCount += n;
    }

    void pop_back() {
        GrAssert(fCount > 0);
        --fCount;
        fItemArray[fCount].~T();
        checkRealloc(0);
    }

    void pop_back_n(int n) {
        GrAssert(n >= 0);
        GrAssert(fCount >= n);
        fCount -= n;
        for (int i = 0; i < n; ++i) {
            fItemArray[i].~T();
        }
        checkRealloc(0);
    }

    // pushes or pops from the back to resize
    void resize_back(int newCount) {
        GrAssert(newCount >= 0);

        if (newCount > fCount) {
            push_back_n(newCount - fCount);
        } else if (newCount < fCount) {
            pop_back_n(fCount - newCount);
        }
    }

    T& operator[] (int i) {
        GrAssert(i < fCount);
        GrAssert(i >= 0);
        return fItemArray[i];
    }

    const T& operator[] (int i) const {
        GrAssert(i < fCount);
        GrAssert(i >= 0);
        return fItemArray[i];
    }

    T& front() { GrAssert(fCount > 0); return fItemArray[0];}

    const T& front() const { GrAssert(fCount > 0); return fItemArray[0];}

    T& back() { GrAssert(fCount); return fItemArray[fCount - 1];}

    const T& back() const { GrAssert(fCount > 0); return fItemArray[fCount - 1];}

    T& fromBack(int i) {
        GrAssert(i >= 0);
        GrAssert(i < fCount);
        return fItemArray[fCount - i - 1];
    }

    const T& fromBack(int i) const {
        GrAssert(i >= 0);
        GrAssert(i < fCount);
        return fItemArray[fCount - i - 1];
    }

private:

    static const int MIN_ALLOC_COUNT = 8;

    inline void checkRealloc(int delta) {
        GrAssert(fCount >= 0);
        GrAssert(fAllocCount >= 0);

        GrAssert(-delta <= fCount);

        int newCount = fCount + delta;
        int fNewAllocCount = fAllocCount;

        if (newCount > fAllocCount) {
            fNewAllocCount = GrMax(newCount + ((newCount + 1) >> 1),
                                   fReserveCount);
        } else if (newCount < fAllocCount / 3) {
            fNewAllocCount = GrMax(fAllocCount / 2, fReserveCount);
        }

        if (fNewAllocCount != fAllocCount) {

            fAllocCount = fNewAllocCount;
            char* fNewMemArray;

            if (fAllocCount == fReserveCount && NULL != fPreAllocMemArray) {
                fNewMemArray = (char*) fPreAllocMemArray;
            } else {
                fNewMemArray = (char*) GrMalloc(fAllocCount*sizeof(T));
            }

            if (DATA_TYPE) {
                memcpy(fNewMemArray, fMemArray, fCount * sizeof(T));
            } else {
                for (int i = 0; i < fCount; ++i) {
                    new (fNewMemArray + sizeof(T) * i) T(fItemArray[i]);
                    fItemArray[i].~T();
                }
            }

            if (fMemArray != fPreAllocMemArray) {
                GrFree(fMemArray);
            }
            fMemArray = fNewMemArray;
        }
    }

    int fReserveCount;
    int fCount;
    int fAllocCount;
    void*    fPreAllocMemArray;
    union {
        T*       fItemArray;
        void*    fMemArray;
    };
};

#endif


code:
/*
    Copyright 2010 Google Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
 */

#ifndef GrTBSearch_DEFINED
#define GrTBSearch_DEFINED

template <typename ELEM, typename KEY>
int GrTBSearch(const ELEM array[], int count, KEY target) {
    GrAssert(count >= 0);
    if (0 == count) {
        // we should insert it at 0
        return ~0;
    }

    int high = count - 1;
    int low = 0;
    while (high > low) {
        int index = (low + high) >> 1;
        if (LT(array[index], target)) {
            low = index + 1;
        } else {
            high = index;
        }
    }

    // check if we found it
    if (EQ(array[high], target)) {
        return high;
    }

    // now return the ~ of where we should insert it
    if (LT(array[high], target)) {
        high += 1;
    }
    return ~high;
}

#endif


code:
/*
    Copyright 2010 Google Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
 */

#ifndef GrTDArray_DEFINED
#define GrTDArray_DEFINED

#include "GrTypes.h"

static int GrInitialArrayAllocationCount() {
    return 4;
}

static int GrNextArrayAllocationCount(int count) {
    return count + ((count + 1) >> 1);
}

template <typename T> class GrTDArray {
public:
    GrTDArray() : fArray(NULL), fAllocated(0), fCount(0) {}
    GrTDArray(const GrTDArray& src) {
        fCount = fAllocated = src.fCount;
        fArray = (T*)GrMalloc(fAllocated * sizeof(T));
        memcpy(fArray, src.fArray, fCount * sizeof(T));
    }
    ~GrTDArray() {
        if (fArray) {
            GrFree(fArray);
        }
    }

    bool isEmpty() const { return 0 == fCount; }
    int count() const { return fCount; }

    const T& at(int index) const {
        GrAssert((unsigned)index < (unsigned)fCount);
        return fArray[index];
    }
    T& at(int index) {
        GrAssert((unsigned)index < (unsigned)fCount);
        return fArray[index];
    }

    const T& operator[](int index) const { return this->at(index); }
    T& operator[](int index) { return this->at(index); }

    GrTDArray& operator=(const GrTDArray& src) {
        if (fAllocated < src.fCount) {
            fAllocated = src.fCount;
            GrFree(fArray);
            fArray = (T*)GrMalloc(fAllocated * sizeof(T));
        }
        fCount = src.fCount;
        memcpy(fArray, src.fArray, fCount * sizeof(T));
        return *this;
    }

    void reset() {
        if (fArray) {
            GrFree(fArray);
            fArray = NULL;
        }
        fAllocated = fCount = 0;
    }

    T* begin() const { return fArray; }
    T* end() const { return fArray + fCount; }
    T* back() const { GrAssert(fCount); return fArray + (fCount - 1); }

    T* prepend() {
        this->growAt(0);
        return fArray;
    }

    T* append() {
        this->growAt(fCount);
        return fArray + fCount - 1;
    }

    /**
     *  index may be [0..count], so that you can insert at the end (like append)
     */
    T* insert(int index) {
        GrAssert((unsigned)index <= (unsigned)fCount);
        this->growAt(index);
        return fArray + index;
    }

    void remove(int index) {
        GrAssert((unsigned)index < (unsigned)fCount);
        fCount -= 1;
        if (index < fCount) {
            int remaining = fCount - index;
            memmove(fArray + index, fArray + index + 1, remaining * sizeof(T));
        }
    }

    void removeShuffle(int index) {
        GrAssert((unsigned)index < (unsigned)fCount);
        fCount -= 1;
        if (index < fCount) {
            memmove(fArray + index, fArray + fCount, sizeof(T));
        }
    }

    // Utility iterators

    /**
     *  Calls GrFree() on each element. Assumes each is NULL or was allocated
     *  with GrMalloc().
     */
    void freeAll() {
        T* stop = this->end();
        for (T* curr = this->begin(); curr < stop; curr++) {
            GrFree(*curr);
        }
        this->reset();
    }

    /**
     *  Calls delete on each element. Assumes each is NULL or was allocated
     *  with new.
     */
    void deleteAll() {
        T* stop = this->end();
        for (T* curr = this->begin(); curr < stop; curr++) {
            delete *curr;
        }
        this->reset();
    }

    /**
     *  Calls GrSafeUnref() on each element. Assumes each is NULL or is a
     *  subclass of GrRefCnt.
     */
    void unrefAll() {
        T* stop = this->end();
        for (T* curr = this->begin(); curr < stop; curr++) {
            GrSafeUnref(*curr);
        }
        this->reset();
    }

    void visit(void visitor(T&)) const {
        T* stop = this->end();
        for (T* curr = this->begin(); curr < stop; curr++) {
            if (*curr) {
                visitor(*curr);
            }
        }
    }

    int find(const T& elem) const {
        int count = this->count();
        T* curr = this->begin();
        for (int i = 0; i < count; i++) {
            if (elem == curr[i]) {
                return i;
            }
        }
        return -1;
    }

    friend bool operator==(const GrTDArray<T>& a, const GrTDArray<T>& b) {
        return a.count() == b.count() &&
               (0 == a.count() ||
                0 == memcmp(a.begin(), b.begin(), a.count() * sizeof(T)));
    }
    friend bool operator!=(const GrTDArray<T>& a, const GrTDArray<T>& b) {
        return !(a == b);
    }

private:
    T*  fArray;
    int fAllocated, fCount;

    // growAt will increment fCount, reallocate fArray (as needed), and slide
    // the contents of fArray to make a hole for new data at index.
    void growAt(int index) {
        GrAssert(fCount <= fAllocated);
        if (0 == fAllocated) {
            fAllocated = GrInitialArrayAllocationCount();
            fArray = (T*)GrMalloc(fAllocated * sizeof(T));
        } else if (fCount == fAllocated) {
            fAllocated = GrNextArrayAllocationCount(fAllocated);
            T* newArray = (T*)GrMalloc(fAllocated * sizeof(T));
            memcpy(newArray, fArray, index * sizeof(T));
            memcpy(newArray + index + 1, fArray + index,
                   (fCount - index) * sizeof(T));
            GrFree(fArray);
            fArray = newArray;
        } else {
            // check that we're not just appending
            if (index < fCount) {
                memmove(fArray + index + 1, fArray + index,
                        (fCount - index) * sizeof(T));
            }
        }
        GrAssert(fCount < fAllocated);
        fCount += 1;
    }
};

extern void* GrTDArray_growAt(void*, int* allocated, int& count, int index,
                              size_t);

#endif


code:
/*
    Copyright 2010 Google Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
 */

#ifndef GrTHashCache_DEFINED
#define GrTHashCache_DEFINED

#include "GrTDArray.h"

/**
 *  Key needs
 *      static bool EQ(const Entry&, const HashKey&);
 *      static bool LT(const Entry&, const HashKey&);
 *      uint32_t getHash() const;
 *
 *  Allows duplicate key entries but on find you may get
 *  any of the duplicate entries returned.
 */
template <typename T, typename Key, size_t kHashBits> class GrTHashTable {
public:
    GrTHashTable() { Gr_bzero(fHash, sizeof(fHash)); }
    ~GrTHashTable() {}

    int count() const { return fSorted.count(); }
    T*  find(const Key&) const;
    // return true if key was unique when inserted.
    bool insert(const Key&, T*);
    void remove(const Key&, const T*);
    T* removeAt(int index, uint32_t hash);
    void removeAll();
    void deleteAll();
    void unrefAll();

    /**
     *  Return the index for the element, using a linear search.
     */
    int slowFindIndex(T* elem) const { return fSorted.find(elem); }

#if GR_DEBUG
    void validate() const;
    bool contains(T*) const;
#endif

    // testing
    const GrTDArray<T*>& getArray() const { return fSorted; }
private:
    enum {
        kHashCount = 1 << kHashBits,
        kHashMask  = kHashCount - 1
    };
    static unsigned hash2Index(uint32_t hash) {
        hash ^= hash >> 16;
        if (kHashBits <= 8) {
            hash ^= hash >> 8;
        }
        return hash & kHashMask;
    }

    mutable T* fHash[kHashCount];
    GrTDArray<T*> fSorted;

    // search fSorted, and return the found index, or ~index of where it
    // should be inserted
    int searchArray(const Key&) const;
};

///////////////////////////////////////////////////////////////////////////////

template <typename T, typename Key, size_t kHashBits>
int GrTHashTable<T, Key, kHashBits>::searchArray(const Key& key) const {
    int count = fSorted.count();
    if (0 == count) {
        // we should insert it at 0
        return ~0;
    }

    const T* const* array = fSorted.begin();
    int high = count - 1;
    int low = 0;
    while (high > low) {
        int index = (low + high) >> 1;
        if (Key::LT(*array[index], key)) {
            low = index + 1;
        } else {
            high = index;
        }
    }

    // check if we found it
    if (Key::EQ(*array[high], key)) {
        // above search should have found the first occurrence if there
        // are multiple.
        GrAssert(0 == high || Key::LT(*array[high - 1], key));
        return high;
    }

    // now return the ~ of where we should insert it
    if (Key::LT(*array[high], key)) {
        high += 1;
    }
    return ~high;
}

template <typename T, typename Key, size_t kHashBits>
T* GrTHashTable<T, Key, kHashBits>::find(const Key& key) const {
    int hashIndex = hash2Index(key.getHash());
    T* elem = fHash[hashIndex];

    if (NULL == elem || !Key::EQ(*elem, key)) {
        // bsearch for the key in our sorted array
        int index = this->searchArray(key);
        if (index < 0) {
            return NULL;
        }
        elem = fSorted[index];
        // update the hash
        fHash[hashIndex] = elem;
    }
    return elem;
}

template <typename T, typename Key, size_t kHashBits>
bool GrTHashTable<T, Key, kHashBits>::insert(const Key& key, T* elem) {
    int index = this->searchArray(key);
    bool first = index < 0;
    if (first) {
        // turn it into the actual index
        index = ~index;
    }
    // add it to our array
    *fSorted.insert(index) = elem;
    // update our hash table (overwrites any dupe's position in the hash)
    fHash[hash2Index(key.getHash())] = elem;
    return first;
}

template <typename T, typename Key, size_t kHashBits>
void GrTHashTable<T, Key, kHashBits>::remove(const Key& key, const T* elem) {
    int index = hash2Index(key.getHash());
    if (fHash[index] == elem) {
        fHash[index] = NULL;
    }

    // remove from our sorted array
    index = this->searchArray(key);
    GrAssert(index >= 0);
    // if there are multiple matches searchArray will give us the first match
    // march forward until we find elem.
    while (elem != fSorted[index]) {
        ++index;
        GrAssert(index < fSorted.count());
    }
    GrAssert(elem == fSorted[index]);
    fSorted.remove(index);
}

template <typename T, typename Key, size_t kHashBits>
T* GrTHashTable<T, Key, kHashBits>::removeAt(int elemIndex, uint32_t hash) {
    int hashIndex = hash2Index(hash);
    if (fHash[hashIndex] == fSorted[elemIndex]) {
        fHash[hashIndex] = NULL;
    }
    // remove from our sorted array
    T* elem = fSorted[elemIndex];
    fSorted.remove(elemIndex);
    return elem;
}

template <typename T, typename Key, size_t kHashBits>
void GrTHashTable<T, Key, kHashBits>::removeAll() {
    fSorted.reset();
    Gr_bzero(fHash, sizeof(fHash));
}

template <typename T, typename Key, size_t kHashBits>
void GrTHashTable<T, Key, kHashBits>::deleteAll() {
    fSorted.deleteAll();
    Gr_bzero(fHash, sizeof(fHash));
}

template <typename T, typename Key, size_t kHashBits>
void GrTHashTable<T, Key, kHashBits>::unrefAll() {
    fSorted.unrefAll();
    Gr_bzero(fHash, sizeof(fHash));
}

#if GR_DEBUG
template <typename T, typename Key, size_t kHashBits>
void GrTHashTable<T, Key, kHashBits>::validate() const {
    for (size_t i = 0; i < GR_ARRAY_COUNT(fHash); i++) {
        if (fHash[i]) {
            unsigned hashIndex = hash2Index(Key::GetHash(*fHash[i]));
            GrAssert(hashIndex == i);
        }
    }

    int count = fSorted.count();
    for (int i = 1; i < count; i++) {
        GrAssert(Key::LT(*fSorted[i - 1], *fSorted[i]) ||
                 Key::EQ(*fSorted[i - 1], *fSorted[i]));
    }
}

template <typename T, typename Key, size_t kHashBits>
bool GrTHashTable<T, Key, kHashBits>::contains(T* elem) const {
    int index = fSorted.find(elem);
    return index >= 0;
}

#endif

#endif


code:
/*
    Copyright 2010 Google Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
 */

#ifndef GrTLList_DEFINED
#define GrTLList_DEFINED

#include "GrNoncopyable.h"

template <typename T> class GrTLList : GrNoncopyable {
public:
    class Entry {
        Entry*  fPrev;
        Entry*  fNext;
    };

    GrTLList() : fHead(NULL), fTail(NULL) {}
#if GR_DEBUG
    ~GrTLList() {
        GrAssert(NULL == fHead);
        GrAssert(NULL == ftail);
    }
#endif

    T*  head() const { return fHead; }
    T*  tail() const { return fTail; }

    void addToHead(T*);
    void addToTail(T*);
    void removeFromList(T*);

private:
    Entry*  fHead;
    Entry*  fTail;

    friend class Entry;
};

class Parent {
    GrTDLList<Child>    fList;
};

class Child : public GrTLList::Entry<Child> {
};

#endif


code:
/*
    Copyright 2010 Google Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
 */

#ifndef GrTemplates_DEFINED
#define GrTemplates_DEFINED

#include "GrNoncopyable.h"

/**
 *  Use to cast a ptr to a different type, and maintain strict-aliasing
 */
template <typename Dst, typename Src> Dst GrTCast(Src src) {
    union {
        Src src;
        Dst dst;
    } data;
    data.src = src;
    return data.dst;
}

/**
 * Reserves memory that is aligned on double and pointer boundaries.
 * Hopefully this is sufficient for all practical purposes.
 */
template <size_t N> class GrAlignedSStorage : GrNoncopyable {
public:
    void* get() { return fData; }
private:
    union {
        void*   fPtr;
        double  fDouble;
        char    fData[N];
    };
};

/**
 * Reserves memory that is aligned on double and pointer boundaries.
 * Hopefully this is sufficient for all practical purposes. Otherwise,
 * we have to do some arcane trickery to determine alignment of non-POD
 * types. Lifetime of the memory is the lifetime of the object.
 */
template <int N, typename T> class GrAlignedSTStorage : GrNoncopyable {
public:
    /**
     * Returns void* because this object does not initialize the
     * memory. Use placement new for types that require a cons.
     */
    void* get() { return fStorage.get(); }
private:
    GrAlignedSStorage<sizeof(T)*N> fStorage;
};

/**
 * saves value of T* in and restores in destructor
 * e.g.:
 * {
 *      GrAutoTPtrValueRestore<int*> autoCountRestore;
 *      if (useExtra) {
 *          autoCountRestore.save(&fCount);
 *          fCount += fExtraCount;
 *      }
 *      ...
 * }  // fCount is restored
 */
template <typename T> class GrAutoTPtrValueRestore : public GrNoncopyable {
public:
    GrAutoTPtrValueRestore() : fPtr(NULL), fVal() {}

    GrAutoTPtrValueRestore(T* ptr) {
        fPtr = ptr;
        if (NULL != ptr) {
            fVal = *ptr;
        }
    }

    ~GrAutoTPtrValueRestore() {
        if (NULL != fPtr) {
            *fPtr = fVal;
        }
    }

    // restores previously saved value (if any) and saves value for passed T*
    void save(T* ptr) {
        if (NULL != fPtr) {
            *fPtr = fVal;
        }
        fPtr = ptr;
        fVal = *ptr;
    }
private:
    T* fPtr;
    T  fVal;
};

#endif


code:
/*
    Copyright 2011 Google Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
 */

#ifndef GrTesselatedPathRenderer_DEFINED
#define GrTesselatedPathRenderer_DEFINED

#include "GrPathRenderer.h"

class GrTesselatedPathRenderer : public GrPathRenderer {
public:
    GrTesselatedPathRenderer();

    virtual void drawPath(GrDrawTarget* target,
                          GrDrawTarget::StageBitfield stages,
                          const GrPath& path,
                          GrPathFill fill,
                          const GrPoint* translate);
    virtual bool canDrawPath(const GrDrawTarget* target,
                             const GrPath& path,
                             GrPathFill fill) const;

    virtual bool requiresStencilPass(const GrDrawTarget* target,
                                     const GrPath& path,
                                     GrPathFill fill) const { return false; }
    virtual void drawPathToStencil(GrDrawTarget* target,
                                   const GrPath& path,
                                   GrPathFill fill,
                                   const GrPoint* translate);
    virtual bool supportsAA(GrDrawTarget* target,
                            const GrPath& path,
                            GrPathFill fill);
};

#endif


code:
/*
    Copyright 2010 Google Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
 */

#ifndef GrTextContext_DEFINED
#define GrTextContext_DEFINED

#include "GrGlyph.h"
#include "GrPaint.h"
#include "GrMatrix.h"

struct GrGpuTextVertex;
class GrContext;
class GrTextStrike;
class GrFontScaler;
class GrDrawTarget;

class GrTextContext {
public:
    GrTextContext(GrContext*,
                  const GrPaint& paint,
                  const GrMatrix* extMatrix = NULL);
    ~GrTextContext();

    void drawPackedGlyph(GrGlyph::PackedID, GrFixed left, GrFixed top,
                         GrFontScaler*);

    void flush();   // optional; automatically called by destructor

private:
    GrPaint         fPaint;
    GrVertexLayout  fVertexLayout;
    GrContext*      fContext;
    GrDrawTarget*   fDrawTarget;

    GrMatrix        fExtMatrix;
    GrFontScaler*   fScaler;
    GrTextStrike*   fStrike;

    inline void flushGlyphs();
    void setupDrawTarget();

    enum {
        kMinRequestedGlyphs      = 1,
        kDefaultRequestedGlyphs  = 64,
        kMinRequestedVerts       = kMinRequestedGlyphs * 4,
        kDefaultRequestedVerts   = kDefaultRequestedGlyphs * 4,
    };

    GrGpuTextVertex* fVertices;

    int32_t     fMaxVertices;
    GrTexture*  fCurrTexture;
    int         fCurrVertex;

    GrIRect     fClipRect;
    GrMatrix    fOrigViewMatrix;    // restore previous viewmatrix
};

#endif


code:
/*
    Copyright 2010 Google Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
 */

#ifndef GrTextStrike_DEFINED
#define GrTextStrike_DEFINED

#include "GrAllocPool.h"
#include "GrFontScaler.h"
#include "GrTHashCache.h"
#include "GrPoint.h"
#include "GrGlyph.h"

class GrAtlasMgr;
class GrFontCache;
class GrGpu;
class GrFontPurgeListener;

/**
 *  The textcache maps a hostfontscaler instance to a dictionary of
 *  glyphid->strike
 */
class GrTextStrike {
public:
    GrTextStrike(GrFontCache*, const GrKey* fontScalerKey, GrMaskFormat,
                 GrAtlasMgr*);
    ~GrTextStrike();

    const GrKey* getFontScalerKey() const { return fFontScalerKey; }
    GrFontCache* getFontCache() const { return fFontCache; }
    GrMaskFormat getMaskFormat() const { return fMaskFormat; }

    inline GrGlyph* getGlyph(GrGlyph::PackedID, GrFontScaler*);
    bool getGlyphAtlas(GrGlyph*, GrFontScaler*);

    // testing
    int countGlyphs() const { return fCache.getArray().count(); }
    const GrGlyph* glyphAt(int index) const {
        return fCache.getArray()[index];
    }
    GrAtlas* getAtlas() const { return fAtlas; }

public:
    // for LRU
    GrTextStrike*   fPrev;
    GrTextStrike*   fNext;

private:
    class Key;
    GrTHashTable<GrGlyph, Key, 7> fCache;
    const GrKey* fFontScalerKey;
    GrTAllocPool<GrGlyph> fPool;

    GrFontCache*    fFontCache;
    GrAtlasMgr*     fAtlasMgr;
    GrAtlas*        fAtlas;     // linklist

    GrMaskFormat fMaskFormat;

    GrGlyph* generateGlyph(GrGlyph::PackedID packed, GrFontScaler* scaler);
    // returns true if after the purge, the strike is empty
    bool purgeAtlasAtY(GrAtlas* atlas, int yCoord);

    friend class GrFontCache;
};

class GrFontCache {
public:
    GrFontCache(GrGpu*);
    ~GrFontCache();

    inline GrTextStrike* getStrike(GrFontScaler*);

    void freeAll();

    void purgeExceptFor(GrTextStrike*);

    // testing
    int countStrikes() const { return fCache.getArray().count(); }
    const GrTextStrike* strikeAt(int index) const {
        return fCache.getArray()[index];
    }
    GrTextStrike* getHeadStrike() const { return fHead; }

#if GR_DEBUG
    void validate() const;
#else
    void validate() const {}
#endif

private:
    friend class GrFontPurgeListener;

    class Key;
    GrTHashTable<GrTextStrike, Key, 8> fCache;
    // for LRU
    GrTextStrike* fHead;
    GrTextStrike* fTail;

    GrGpu*      fGpu;
    GrAtlasMgr* fAtlasMgr;

    GrTextStrike* generateStrike(GrFontScaler*, const Key&);
    inline void detachStrikeFromList(GrTextStrike*);
};

#endif


code:
/*
    Copyright 2010 Google Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
 */

#ifndef GrTextStrike_impl_DEFINED
#define GrTextStrike_impl_DEFINED

class GrFontCache::Key {
public:
    Key(GrFontScaler* scaler) {
        fFontScalerKey = scaler->getKey();
    }

    uint32_t getHash() const { return fFontScalerKey->getHash(); }

    static bool LT(const GrTextStrike& strike, const Key& key) {
        return *strike.getFontScalerKey() < *key.fFontScalerKey;
    }
    static bool EQ(const GrTextStrike& strike, const Key& key) {
        return *strike.getFontScalerKey() == *key.fFontScalerKey;
    }

private:
    const GrKey* fFontScalerKey;
};

void GrFontCache::detachStrikeFromList(GrTextStrike* strike) {
    if (strike->fPrev) {
        GrAssert(fHead != strike);
        strike->fPrev->fNext = strike->fNext;
    } else {
        GrAssert(fHead == strike);
        fHead = strike->fNext;
    }

    if (strike->fNext) {
        GrAssert(fTail != strike);
        strike->fNext->fPrev = strike->fPrev;
    } else {
        GrAssert(fTail == strike);
        fTail = strike->fPrev;
    }
}

GrTextStrike* GrFontCache::getStrike(GrFontScaler* scaler) {
    this->validate();

    Key key(scaler);
    GrTextStrike* strike = fCache.find(key);
    if (NULL == strike) {
        strike = this->generateStrike(scaler, key);
    } else if (strike->fPrev) {
        // Need to put the strike at the head of its dllist, since that is how
        // we age the strikes for purging (we purge from the back of the list
        this->detachStrikeFromList(strike);
        // attach at the head
        fHead->fPrev = strike;
        strike->fNext = fHead;
        strike->fPrev = NULL;
        fHead = strike;
    }

    this->validate();
    return strike;
}

///////////////////////////////////////////////////////////////////////////////

/**
 *  This Key just wraps a glyphID, and matches the protocol need for
 *  GrTHashTable
 */
class GrTextStrike::Key {
public:
    Key(GrGlyph::PackedID id) : fPackedID(id) {}

    uint32_t getHash() const { return fPackedID; }

    static bool LT(const GrGlyph& glyph, const Key& key) {
        return glyph.fPackedID < key.fPackedID;
    }
    static bool EQ(const GrGlyph& glyph, const Key& key) {
        return glyph.fPackedID == key.fPackedID;
    }

private:
    GrGlyph::PackedID fPackedID;
};

GrGlyph* GrTextStrike::getGlyph(GrGlyph::PackedID packed,
                                GrFontScaler* scaler) {
    GrGlyph* glyph = fCache.find(packed);
    if (NULL == glyph) {
        glyph = this->generateGlyph(packed, scaler);
    }
    return glyph;
}

#endif


code:
/*
    Copyright 2011 Google Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
 */

#ifndef GrTexture_DEFINED
#define GrTexture_DEFINED

#include "GrRefCnt.h"
#include "GrClip.h"
#include "GrResource.h"

class GrTexture;

/**
 * GrRenderTarget represents a 2D buffer of pixels that can be rendered to.
 * A context's render target is set by setRenderTarget(). Render targets are
 * created by a createTexture with the kRenderTarget_TextureFlag flag.
 * Additionally, GrContext provides methods for creating GrRenderTargets
 * that wrap externally created render targets.
 */
class GrRenderTarget : public GrResource {

public:
    /**
     * @return the width of the rendertarget
     */
    int width() const { return fWidth; }
    /**
     * @return the height of the rendertarget
     */
    int height() const { return fHeight; }

    /**
     * @return the number of stencil bits in the rendertarget
     */
    int stencilBits() const { return fStencilBits; }

    /**
     * @return the texture associated with the rendertarget, may be NULL.
     */
    GrTexture* asTexture() {return fTexture;}

    /**
     * @return true if the render target is multisampled, false otherwise
     */
    bool isMultisampled() { return fIsMultisampled; }

    /**
     * Call to indicate the multisample contents were modified such that the
     * render target needs to be resolved before it can be used as texture. Gr
     * tracks this for its own drawing and thus this only needs to be called
     * when the render target has been modified outside of Gr. Only meaningful
     * for Gr-created RT/Textures and Platform RT/Textures created with the
     * kGrCanResolve flag.
     * @param rect  a rect bounding the area needing resolve. NULL indicates
     *              the whole RT needs resolving.
     */
    void flagAsNeedingResolve(const GrIRect* rect = NULL);

    /**
     * Call to override the region that needs to be resolved.
     */
    void overrideResolveRect(const GrIRect rect);

    /**
     * Call to indicate that GrRenderTarget was externally resolved. This may
     * allow Gr to skip a redundant resolve step.
     */
    void flagAsResolved() { fResolveRect.setLargestInverted(); }

    /**
     * @return true if the GrRenderTarget requires MSAA resolving
     */
    bool needsResolve() const { return !fResolveRect.isEmpty(); }

    /**
     * Returns a rect bounding the region needing resolving.
     */
    const GrIRect& getResolveRect() const { return fResolveRect; }

    /**
     * Reads a rectangle of pixels from the render target.
     * @param left          left edge of the rectangle to read (inclusive)
     * @param top           top edge of the rectangle to read (inclusive)
     * @param width         width of rectangle to read in pixels.
     * @param height        height of rectangle to read in pixels.
     * @param config        the pixel config of the destination buffer
     * @param buffer        memory to read the rectangle into.
     *
     * @return true if the read succeeded, false if not. The read can fail
     *              because of a unsupported pixel config.
     */
    bool readPixels(int left, int top, int width, int height,
                    GrPixelConfig config, void* buffer);

    // a MSAA RT may require explicit resolving , it may auto-resolve (e.g. FBO
    // 0 in GL), or be unresolvable because the client didn't give us the
    // resolve destination.
    enum ResolveType {
        kCanResolve_ResolveType,
        kAutoResolves_ResolveType,
        kCantResolve_ResolveType,
    };
    virtual ResolveType getResolveType() const = 0;

protected:
    GrRenderTarget(GrGpu* gpu,
                   GrTexture* texture,
                   int width,
                   int height,
                   int stencilBits,
                   bool isMultisampled)
        : INHERITED(gpu)
        , fTexture(texture)
        , fWidth(width)
        , fHeight(height)
        , fStencilBits(stencilBits)
        , fIsMultisampled(isMultisampled)
    {
        fResolveRect.setLargestInverted();
    }

    friend class GrTexture;
    // When a texture unrefs an owned rendertarget this func
    // removes the back pointer. This could be done called from
    // texture's destructor but would have to be done in derived
    // class. By the time of texture base destructor it has already
    // lost its pointer to the rt.
    void onTextureReleaseRenderTarget() {
        GrAssert(NULL != fTexture);
        fTexture = NULL;
    }

private:
    GrTexture* fTexture; // not ref'ed
    int        fWidth;
    int        fHeight;
    int        fStencilBits;
    bool       fIsMultisampled;
    GrIRect    fResolveRect;

    // GrGpu keeps a cached clip in the render target to avoid redundantly
    // rendering the clip into the same stencil buffer.
    friend class GrGpu;
    GrClip     fLastStencilClip;

    typedef GrResource INHERITED;
};

class GrTexture : public GrResource {

public:
    /**
     * Retrieves the width of the texture.
     *
     * @return the width in texels
     */
    int width() const { return fWidth; }

    /**
     * Retrieves the height of the texture.
     *
     * @return the height in texels
     */
    int height() const { return fHeight; }

    /**
     * Convert from texels to normalized texture coords for POT textures
     * only.
     */
    GrFixed normalizeFixedX(GrFixed x) const { GrAssert(GrIsPow2(fWidth));
                                               return x >> fShiftFixedX; }
    GrFixed normalizeFixedY(GrFixed y) const { GrAssert(GrIsPow2(fHeight));
                                               return y >> fShiftFixedY; }

    /**
     * Retrieves the pixel config specified when the texture was created.
     */
    GrPixelConfig config() const { return fConfig; }

    /**
     *  Approximate number of bytes used by the texture
     */
    size_t sizeInBytes() const {
        return fWidth * fHeight * GrBytesPerPixel(fConfig);
    }

    /**
     * Updates a subrectangle of texels in the texture.
     *
     * @param x       left edge of rectangle to update
     * @param y       top edge of rectangle to update
     * @param width   width of rectangle to update
     * @param height  height of rectangle to update
     * @param srcData width*height texels of data in same format that was used
     *                at texture creation.
     */
    virtual void uploadTextureData(int x,
                                   int y,
                                   int width,
                                   int height,
                                   const void* srcData) = 0;

    /**
     * Reads a rectangle of pixels from the texture.
     * @param left          left edge of the rectangle to read (inclusive)
     * @param top           top edge of the rectangle to read (inclusive)
     * @param width         width of rectangle to read in pixels.
     * @param height        height of rectangle to read in pixels.
     * @param config        the pixel config of the destination buffer
     * @param buffer        memory to read the rectangle into.
     *
     * @return true if the read succeeded, false if not. The read can fail
     *              because of a unsupported pixel config.
     */
    bool readPixels(int left, int top, int width, int height,
                    GrPixelConfig config, void* buffer);

    /**
     * Retrieves the render target underlying this texture that can be passed to
     * GrGpu::setRenderTarget().
     *
     * @return    handle to render target or NULL if the texture is not a
     *            render target
     */
    GrRenderTarget* asRenderTarget() { return fRenderTarget; }

    /**
     * Removes the reference on the associated GrRenderTarget held by this
     * texture. Afterwards asRenderTarget() will return NULL. The
     * GrRenderTarget survives the release if another ref is held on it.
     */
    void releaseRenderTarget() {
        if (NULL != fRenderTarget) {
            GrAssert(fRenderTarget->asTexture() == this);
            fRenderTarget->onTextureReleaseRenderTarget();
            fRenderTarget->unref();
            fRenderTarget = NULL;
        }
    }

    /**
     *  Return the native ID or handle to the texture, depending on the
     *  platform. e.g. on opengl, return the texture ID.
     */
    virtual intptr_t getTextureHandle() = 0;

#if GR_DEBUG
    void validate() const {
        this->INHERITED::validate();
    }
#else
    void validate() const {}
#endif

protected:
    GrRenderTarget* fRenderTarget; // texture refs its rt representation
                                   // base class cons sets to NULL
                                   // subclass cons can create and set

    GrTexture(GrGpu* gpu,
              int width,
              int height,
              GrPixelConfig config)
    : INHERITED(gpu)
    , fRenderTarget(NULL)
    , fWidth(width)
    , fHeight(height)
    , fConfig(config) {
        // only make sense if alloc size is pow2
        fShiftFixedX = 31 - Gr_clz(fWidth);
        fShiftFixedY = 31 - Gr_clz(fHeight);
    }

    // GrResource overrides
    virtual void onRelease() {
        releaseRenderTarget();
    }

    virtual void onAbandon() {
        if (NULL != fRenderTarget) {
            fRenderTarget->abandon();
        }
    }

private:
    int fWidth;
    int fHeight;
    // these two shift a fixed-point value into normalized coordinates
    // for this texture if the texture is power of two sized.
    int      fShiftFixedX;
    int      fShiftFixedY;

    GrPixelConfig fConfig;

    typedef GrResource INHERITED;
};

#endif


code:
/*
    Copyright 2010 Google Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
 */

#ifndef GrTextureCache_DEFINED
#define GrTextureCache_DEFINED

#include "GrTypes.h"
#include "GrTHashCache.h"

class GrTexture;

// return true if a<b, or false if b<a
//
#define RET_IF_LT_OR_GT(a, b)   \
    do {                        \
        if ((a) < (b)) {        \
            return true;        \
        }                       \
        if ((b) < (a)) {        \
            return false;       \
        }                       \
    } while (0)

/**
 *  Helper class for GrTextureCache, the Key is used to identify src data for
 *  a texture. It is identified by 2 32bit data fields which can hold any
 *  data (uninterpreted by the cache) and a width/height.
 */
class GrTextureKey {
public:
    enum {
        kHashBits   = 7,
        kHashCount  = 1 << kHashBits,
        kHashMask   = kHashCount - 1
    };

    GrTextureKey(uint32_t p0, uint32_t p1, uint16_t width, uint16_t height) {
        fP0 = p0;
        fP1 = p1;
        fP2 = width | (height << 16);
        GR_DEBUGCODE(fHashIndex = -1);
    }

    GrTextureKey(const GrTextureKey& src) {
        fP0 = src.fP0;
        fP1 = src.fP1;
        fP2 = src.fP2;
        finalize(src.fPrivateBits);
    }

    //!< returns hash value [0..kHashMask] for the key
    int hashIndex() const { return fHashIndex; }

    friend bool operator==(const GrTextureKey& a, const GrTextureKey& b) {
        GR_DEBUGASSERT(-1 != a.fHashIndex && -1 != b.fHashIndex);
        return a.fP0 == b.fP0 && a.fP1 == b.fP1 && a.fP2 == b.fP2 &&
               a.fPrivateBits == b.fPrivateBits;
    }

    friend bool operator!=(const GrTextureKey& a, const GrTextureKey& b) {
        GR_DEBUGASSERT(-1 != a.fHashIndex && -1 != b.fHashIndex);
        return !(a == b);
    }

    friend bool operator<(const GrTextureKey& a, const GrTextureKey& b) {
        RET_IF_LT_OR_GT(a.fP0, b.fP0);
        RET_IF_LT_OR_GT(a.fP1, b.fP1);
        RET_IF_LT_OR_GT(a.fP2, b.fP2);
        return a.fPrivateBits < b.fPrivateBits;
    }

private:
    void finalize(uint32_t privateBits) {
        fPrivateBits = privateBits;
        this->computeHashIndex();
    }

    uint16_t width() const { return fP2 & 0xffff; }
    uint16_t height() const { return (fP2 >> 16); }

    uint32_t getPrivateBits() const { return fPrivateBits; }

    static uint32_t rol(uint32_t x) {
        return (x >> 24) | (x << 8);
    }
    static uint32_t ror(uint32_t x) {
        return (x >> 8) | (x << 24);
    }
    static uint32_t rohalf(uint32_t x) {
        return (x >> 16) | (x << 16);
    }

    void computeHashIndex() {
        uint32_t hash = fP0 ^ rol(fP1) ^ ror(fP2) ^ rohalf(fPrivateBits);
        // this way to mix and reduce hash to its index may have to change
        // depending on how many bits we allocate to the index
        hash ^= hash >> 16;
        hash ^= hash >> 8;
        fHashIndex = hash & kHashMask;
    }

    uint32_t    fP0;
    uint32_t    fP1;
    uint32_t    fP2;
    uint32_t    fPrivateBits;

    // this is computed from the fP... fields
    int         fHashIndex;

    friend class GrContext;
};

///////////////////////////////////////////////////////////////////////////////

class GrTextureEntry {
public:
    GrTexture* texture() const { return fTexture; }
    const GrTextureKey& key() const { return fKey; }

#if GR_DEBUG
    GrTextureEntry* next() const { return fNext; }
    GrTextureEntry* prev() const { return fPrev; }
#endif

#if GR_DEBUG
    void validate() const;
#else
    void validate() const {}
#endif

private:
    GrTextureEntry(const GrTextureKey& key, GrTexture* texture);
    ~GrTextureEntry();

    bool isLocked() const { return fLockCount != 0; }
    void lock() { ++fLockCount; }
    void unlock() {
        GrAssert(fLockCount > 0);
        --fLockCount;
    }

    GrTextureKey    fKey;
    GrTexture*      fTexture;

    // track if we're in use, used when we need to purge
    // we only purge unlocked entries
    int fLockCount;

    // we're a dlinklist
    GrTextureEntry* fPrev;
    GrTextureEntry* fNext;

    friend class GrTextureCache;
};

///////////////////////////////////////////////////////////////////////////////

#include "GrTHashCache.h"

/**
 *  Cache of GrTexture objects.
 *
 *  These have a corresponding GrTextureKey, built from 96bits identifying the
 *  texture/bitmap.
 *
 *  The cache stores the entries in a double-linked list, which is its LRU.
 *  When an entry is "locked" (i.e. given to the caller), it is moved to the
 *  head of the list. If/when we must purge some of the entries, we walk the
 *  list backwards from the tail, since those are the least recently used.
 *
 *  For fast searches, we maintain a sorted array (based on the GrTextureKey)
 *  which we can bsearch. When a new entry is added, it is inserted into this
 *  array.
 *
 *  For even faster searches, a hash is computed from the Key. If there is
 *  a collision between two keys with the same hash, we fall back on the
 *  bsearch, and update the hash to reflect the most recent Key requested.
 */
class GrTextureCache {
public:
    GrTextureCache(int maxCount, size_t maxBytes);
    ~GrTextureCache();

    /**
     *  Return the current texture cache limits.
     *
     *  @param maxTextures If non-null, returns maximum number of textures that
     *                     can be held in the cache.
     *  @param maxTextureBytes If non-null, returns maximum number of bytes of
     *                         texture memory that can be held in the cache.
     */
    void getLimits(int* maxTextures, size_t* maxTextureBytes) const;

    /**
     *  Specify the texture cache limits. If the current cache exceeds either
     *  of these, it will be purged (LRU) to keep the cache within these limits.
     *
     *  @param maxTextures The maximum number of textures that can be held in
     *                     the cache.
     *  @param maxTextureBytes The maximum number of bytes of texture memory
     *                         that can be held in the cache.
     */
    void setLimits(int maxTextures, size_t maxTextureBytes);

    /**
     *  Search for an entry with the same Key. If found, "lock" it and return it.
     *  If not found, return null.
     */
    GrTextureEntry* findAndLock(const GrTextureKey&);

    /**
     *  Create a new entry, based on the specified key and texture, and return
     *  its "locked" entry.
     *
     *  Ownership of the texture is transferred to the Entry, which will unref()
     *  it when we are purged or deleted.
     */
    GrTextureEntry* createAndLock(const GrTextureKey&, GrTexture*);

    /**
     * Detach removes an entry from the cache. This prevents the entry from
     * being found by a subsequent findAndLock() until it is reattached. The
     * entry still counts against the cache's budget and should be reattached
     * when exclusive access is no longer needed.
     */
    void detach(GrTextureEntry*);

    /**
     * Reattaches a texture to the cache and unlocks it. Allows it to be found
     * by a subsequent findAndLock or be purged (provided its lock count is
     * now 0.)
     */
    void reattachAndUnlock(GrTextureEntry*);

    /**
     *  When done with an entry, call unlock(entry) on it, which returns it to
     *  a purgable state.
     */
    void unlock(GrTextureEntry*);

    void removeAll();

#if GR_DEBUG
    void validate() const;
#else
    void validate() const {}
#endif

private:
    void internalDetach(GrTextureEntry*, bool);
    void attachToHead(GrTextureEntry*, bool);
    void purgeAsNeeded();   // uses kFreeTexture_DeleteMode

    class Key;
    GrTHashTable<GrTextureEntry, Key, 8> fCache;

    // manage the dlink list
    GrTextureEntry* fHead;
    GrTextureEntry* fTail;

    // our budget, used in purgeAsNeeded()
    int fMaxCount;
    size_t fMaxBytes;

    // our current stats, related to our budget
    int fEntryCount;
    size_t fEntryBytes;
    int fClientDetachedCount;
    size_t fClientDetachedBytes;
};

///////////////////////////////////////////////////////////////////////////////

#if GR_DEBUG
    class GrAutoTextureCacheValidate {
    public:
        GrAutoTextureCacheValidate(GrTextureCache* cache) : fCache(cache) {
            cache->validate();
        }
        ~GrAutoTextureCacheValidate() {
            fCache->validate();
        }
    private:
        GrTextureCache* fCache;
    };
#else
    class GrAutoTextureCacheValidate {
    public:
        GrAutoTextureCacheValidate(GrTextureCache*) {}
    };
#endif

#endif


code:
#ifndef GrTouchGesture_DEFINED
#define GrTouchGesture_DEFINED

#include "GrTypes.h"
#include "SkTDArray.h"
#include "SkMatrix.h"

#include "FlingState.h"

class GrTouchGesture {
public:
    GrTouchGesture();
    ~GrTouchGesture();

    void touchBegin(void* owner, float x, float y);
    void touchMoved(void* owner, float x, float y);
    void touchEnd(void* owner);
    void reset();

    const SkMatrix& localM();
    const SkMatrix& globalM() const { return fGlobalM; }

private:
    enum State {
        kEmpty_State,
        kTranslate_State,
        kZoom_State,
    };

    struct Rec {
        void*   fOwner;
        float   fStartX, fStartY;
        float   fPrevX, fPrevY;
        float   fLastX, fLastY;
        SkMSec  fPrevT, fLastT;
    };
    SkTDArray<Rec> fTouches;

    State    fState;
    SkMatrix fLocalM, fGlobalM;
    FlingState  fFlinger;
    SkMSec  fLastUpT;
    SkPoint fLastUpP;

    void flushLocalM();
    int findRec(void* owner) const;
    void appendNewRec(void* owner, float x, float y);
    float computePinch(const Rec&, const Rec&);
    float limitTotalZoom(float scale) const;
    bool handleDblTap(float, float);
};

#endif


code:
/*
    Copyright 2010 Google Inc.

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

         http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.
 */

#ifndef GrTypes_DEFINED
#define GrTypes_DEFINED

#include "SkTypes.h"
#include "GrConfig.h"

////////////////////////////////////////////////////////////////////////////////

/**
 * Defines overloaded bitwise operators to make it easier to use an enum as a
 * bitfield.
 */
#define GR_MAKE_BITFIELD_OPS(X) \
    static inline X operator | (X a, X b) { \
        return (X) (+a | +b); \
    } \
    \
    static inline X operator & (X a, X b) { \
        return (X) (+a & +b); \
    } \
    template <typename T> \
    static inline X operator & (T a, X b) { \
        return (X) (+a & +b); \
    } \
    template <typename T> \
    static inline X operator & (X a, T b) { \
        return (X) (+a & +b); \
    } \

////////////////////////////////////////////////////////////////////////////////

/**
 *  Macro to round n up to the next multiple of 4, or return it unchanged if
 *  n is already a multiple of 4
 */
#define GrALIGN4(n)     SkAlign4(n)
#define GrIsALIGN4(n)   (((n) & 3) == 0)

template <typename T> const T& GrMin(const T& a, const T& b) {
	return (a < b) ? a : b;
}

template <typename T> const T& GrMax(const T& a, const T& b) {
	return (b < a) ? a : b;
}

// compile time versions of min/max
#define GR_CT_MAX(a, b) (((b) < (a)) ? (a) : (b))
#define GR_CT_MIN(a, b) (((b) < (a)) ? (b) : (a))

/**
 *  divide, rounding up
 */
static inline int32_t GrIDivRoundUp(int x, int y) {
    GrAssert(y > 0);
    return (x + (y-1)) / y;
}
static inline uint32_t GrUIDivRoundUp(uint32_t x, uint32_t y) {
    return (x + (y-1)) / y;
}
static inline size_t GrSizeDivRoundUp(size_t x, uint32_t y) {
    return (x + (y-1)) / y;
}

/**
 *  align up
 */
static inline uint32_t GrUIAlignUp(uint32_t x, uint32_t alignment) {
    return GrUIDivRoundUp(x, alignment) * alignment;
}
static inline uint32_t GrSizeAlignUp(size_t x, uint32_t alignment) {
    return GrSizeDivRoundUp(x, alignment) * alignment;
}

/**
 * amount of pad needed to align up
 */
static inline uint32_t GrUIAlignUpPad(uint32_t x, uint32_t alignment) {
    return (alignment - x % alignment) % alignment;
}
static inline size_t GrSizeAlignUpPad(size_t x, uint32_t alignment) {
    return (alignment - x % alignment) % alignment;
}

/**
 *  align down
 */
static inline uint32_t GrUIAlignDown(uint32_t x, uint32_t alignment) {
    return (x / alignment) * alignment;
}
static inline uint32_t GrSizeAlignDown(size_t x, uint32_t alignment) {
    return (x / alignment) * alignment;
}

/**
 *  Count elements in an array
 */
#define GR_ARRAY_COUNT(array)  SK_ARRAY_COUNT(array)

//!< allocate a block of memory, will never return NULL
extern void* GrMalloc(size_t bytes);

//!< free block allocated by GrMalloc. ptr may be NULL
extern void GrFree(void* ptr);

static inline void Gr_bzero(void* dst, size_t size) {
    memset(dst, 0, size);
}

///////////////////////////////////////////////////////////////////////////////

/**
 *  Return the number of leading zeros in n
 */
extern int Gr_clz(uint32_t n);

/**
 *  Return true if n is a power of 2
 */
static inline bool GrIsPow2(unsigned n) {
    return n && 0 == (n & (n - 1));
}

/**
 *  Return the next power of 2 >= n.
 */
static inline uint32_t GrNextPow2(uint32_t n) {
    return n ? (1 << (32 - Gr_clz(n - 1))) : 1;
}

static inline int GrNextPow2(int n) {
    GrAssert(n >= 0); // this impl only works for non-neg.
    return n ? (1 << (32 - Gr_clz(n - 1))) : 1;
}

///////////////////////////////////////////////////////////////////////////////

/**
 *  16.16 fixed point type
 */
typedef int32_t GrFixed;

#if GR_DEBUG

static inline int16_t GrToS16(intptr_t x) {
    GrAssert((int16_t)x == x);
    return (int16_t)x;
}

#else

#define GrToS16(x)  x

#endif

///////////////////////////////////////////////////////////////////////////////

/**
 * Possible 3D APIs that may be used by Ganesh.
 */
enum GrEngine {
    kOpenGL_Shaders_GrEngine,
    kOpenGL_Fixed_GrEngine,
    kDirect3D9_GrEngine
};

/**
 * Engine-specific 3D context handle
 *      Unused for GL.
 *      IDirect3DDevice9* for D3D9
 */
typedef intptr_t GrPlatform3DContext;

///////////////////////////////////////////////////////////////////////////////

/**
 * Type used to describe format of vertices in arrays
 * Values are defined in GrDrawTarget
 */
typedef int GrVertexLayout;

/**
* Geometric primitives used for drawing.
*/
enum GrPrimitiveType {
    kTriangles_PrimitiveType,
    kTriangleStrip_PrimitiveType,
    kTriangleFan_PrimitiveType,
    kPoints_PrimitiveType,
    kLines_PrimitiveType,
    kLineStrip_PrimitiveType
};

static inline bool GrIsPrimTypeLines(GrPrimitiveType type) {
    return kLines_PrimitiveType == type || kLineStrip_PrimitiveType == type;
}

static inline bool GrIsPrimTypeTris(GrPrimitiveType type) {
    return kTriangles_PrimitiveType == type     ||
           kTriangleStrip_PrimitiveType == type ||
           kTriangleFan_PrimitiveType == type;
}

/**
 * Coeffecients for alpha-blending.
 */
enum GrBlendCoeff {
    kZero_BlendCoeff,    //<! 0
    kOne_BlendCoeff,     //<! 1
    kSC_BlendCoeff,      //<! src color
    kISC_BlendCoeff,     //<! one minus src color
    kDC_BlendCoeff,      //<! dst color
    kIDC_BlendCoeff,     //<! one minus dst color
    kSA_BlendCoeff,      //<! src alpha
    kISA_BlendCoeff,     //<! one minus src alpha
    kDA_BlendCoeff,      //<! dst alpha
    kIDA_BlendCoeff,     //<! one minus dst alpha
    kConstC_BlendCoeff,  //<! constant color
    kIConstC_BlendCoeff, //<! one minus constant color
    kConstA_BlendCoeff,  //<! constant color alpha
    kIConstA_BlendCoeff, //<! one minus constant color alpha

    kPublicBlendCoeffCount
};

/**
 *  Formats for masks, used by the font cache.
 *  Important that these are 0-based.
 */
enum GrMaskFormat {
    kA8_GrMaskFormat,    //!< 1-byte per pixel
    kA565_GrMaskFormat,  //!< 2-bytes per pixel
    kA888_GrMaskFormat,  //!< 4-bytes per pixel

    kCount_GrMaskFormats //!< used to allocate arrays sized for mask formats
};

/**
 *  Return the number of bytes-per-pixel for the specified mask format.
 */
static inline int GrMaskFormatBytesPerPixel(GrMaskFormat format) {
    GrAssert((unsigned)format <= 1);
    return (int)format + 1;
}

/**
 * Pixel configurations.
 */
enum GrPixelConfig {
    kUnknown_GrPixelConfig,
    kAlpha_8_GrPixelConfig,
    kIndex_8_GrPixelConfig,
    kRGB_565_GrPixelConfig,
    kRGBA_4444_GrPixelConfig, //!< premultiplied
    kRGBA_8888_GrPixelConfig, //!< premultiplied
    kRGBX_8888_GrPixelConfig, //!< treat the alpha channel as opaque
};

static inline size_t GrBytesPerPixel(GrPixelConfig config) {
    switch (config) {
        case kAlpha_8_GrPixelConfig:
        case kIndex_8_GrPixelConfig:
            return 1;
        case kRGB_565_GrPixelConfig:
        case kRGBA_4444_GrPixelConfig:
            return 2;
        case kRGBA_8888_GrPixelConfig:
        case kRGBX_8888_GrPixelConfig:
            return 4;
        default:
            return 0;
    }
}

static inline bool GrPixelConfigIsOpaque(GrPixelConfig config) {
    switch (config) {
        case kRGB_565_GrPixelConfig:
        case kRGBX_8888_GrPixelConfig:
            return true;
        default:
            return false;
    }
}

static inline bool GrPixelConfigIsAlphaOnly(GrPixelConfig config) {
    switch (config) {
        case kAlpha_8_GrPixelConfig:
            return true;
        default:
            return false;
    }
}

/**
    * Used to control the level of antialiasing available for a rendertarget.
    * Anti-alias quality levels depend on the underlying API/GPU capabilities.
    */
enum GrAALevels {
    kNone_GrAALevel, //<! No antialiasing available.
    kLow_GrAALevel,  //<! Low quality antialiased rendering. Actual
                     //   interpretation is platform-dependent.
    kMed_GrAALevel,  //<! Medium quality antialiased rendering. Actual
                     //   interpretation is platform-dependent.
    kHigh_GrAALevel, //<! High quality antialiased rendering. Actual
                     //   interpretation is platform-dependent.
};

/**
 * Optional bitfield flags that can be passed to createTexture.
 */
enum GrTextureFlags {
    kNone_GrTextureFlags            = 0x0,
    /**
     * Creates a texture that can be rendered to as a GrRenderTarget. Use
     * GrTexture::asRenderTarget() to access.
     */
    kRenderTarget_GrTextureFlagBit  = 0x1,
    /**
     * By default all render targets have an associated stencil buffer that
     * may be required for path filling. This flag overrides stencil buffer
     * creation.
     * MAKE THIS PRIVATE?
     */
    kNoStencil_GrTextureFlagBit     = 0x2,
    /**
     * Hint that the CPU may modify this texture after creation.
     */
    kDynamicUpdate_GrTextureFlagBit = 0x4,
};

GR_MAKE_BITFIELD_OPS(GrTextureFlags)

enum {
   /**
    *  For Index8 pixel config, the colortable must be 256 entries
    */
    kGrColorTableSize = 256 * 4 //sizeof(GrColor)
};

/**
 * Describes a texture to be created.
 */
struct GrTextureDesc {
    GrTextureFlags         fFlags;  //!< bitfield of TextureFlags
    /**
     * The level of antialiasing available for a rendertarget texture. Only used
     * fFlags contains kRenderTarget_GrTextureFlag.
     */
    GrAALevels             fAALevel;
    int                    fWidth;  //!< Width of the texture
    int                    fHeight; //!< Height of the texture
    /**
     * Format of source data of the texture. Not guaraunteed to be the same as
     * internal format used by 3D API.
     */
    GrPixelConfig          fFormat;
};

/**
 * Set Operations used to construct clips.
 */
enum GrSetOp {
    kReplace_SetOp,
    kIntersect_SetOp,
    kUnion_SetOp,
    kXor_SetOp,
    kDifference_SetOp,
    kReverseDifference_SetOp,
};

/**
 * Clips are composed from these objects.
 */
enum GrClipType {
    kRect_ClipType,
    kPath_ClipType
};

/**
 * Commands used to describe a path. Each command
 * is accompanied by some number of points.
 */
enum GrPathCmd {
    kMove_PathCmd,      //!< Starts a new subpath at
                        //   at the returned point
                        // 1 point
    kLine_PathCmd,      //!< Adds a line segment
                        // 2 points
    kQuadratic_PathCmd, //!< Adds a quadratic segment
                        // 3 points
    kCubic_PathCmd,     //!< Adds a cubic segment
                        // 4 points
    kClose_PathCmd,     //!< Closes the current subpath
                        //   by connecting a line to the
                        //   starting point.
                        // 0 points
    kEnd_PathCmd        //!< Indicates the end of the last subpath
                        //   when iterating
                        // 0 points.
};

/**
 * Gets the number of points associated with a path command.
 */
static int inline NumPathCmdPoints(GrPathCmd cmd) {
    static const int gNumPoints[] = {
        1, 2, 3, 4, 0, 0
    };
    return gNumPoints[cmd];
}

/**
 * Path filling rules
 */
enum GrPathFill {
    kWinding_PathFill,
    kEvenOdd_PathFill,
    kInverseWinding_PathFill,
    kInverseEvenOdd_PathFill,
    kHairLine_PathFill,

    kPathFillCount
};

static inline GrPathFill NonInvertedFill(GrPathFill fill) {
    static const GrPathFill gNonInvertedFills[] = {
        kWinding_PathFill, // kWinding_PathFill
        kEvenOdd_PathFill, // kEvenOdd_PathFill
        kWinding_PathFill, // kInverseWinding_PathFill
        kEvenOdd_PathFill, // kInverseEvenOdd_PathFill
        kHairLine_PathFill,// kHairLine_PathFill
    };
    GR_STATIC_ASSERT(0 == kWinding_PathFill);
    GR_STATIC_ASSERT(1 == kEvenOdd_PathFill);
    GR_STATIC_ASSERT(2 == kInverseWinding_PathFill);
    GR_STATIC_ASSERT(3 == kInverseEvenOdd_PathFill);
    GR_STATIC_ASSERT(4 == kHairLine_PathFill);
    GR_STATIC_ASSERT(5 == kPathFillCount);
    return gNonInvertedFills[fill];
}

static inline bool IsFillInverted(GrPathFill fill) {
    static const bool gIsFillInverted[] = {
        false, // kWinding_PathFill
        false, // kEvenOdd_PathFill
        true,  // kInverseWinding_PathFill
        true,  // kInverseEvenOdd_PathFill
        false, // kHairLine_PathFill
    };
    GR_STATIC_ASSERT(0 == kWinding_PathFill);
    GR_STATIC_ASSERT(1 == kEvenOdd_PathFill);
    GR_STATIC_ASSERT(2 == kInverseWinding_PathFill);
    GR_STATIC_ASSERT(3 == kInverseEvenOdd_PathFill);
    GR_STATIC_ASSERT(4 == kHairLine_PathFill);
    GR_STATIC_ASSERT(5 == kPathFillCount);
    return gIsFillInverted[fill];
}

/**
 * Hints provided about a path's convexity (or lack thereof).
 */
enum GrConvexHint {
    kNone_ConvexHint,                         //<! No hint about convexity
                                              //   of the path
    kConvex_ConvexHint,                       //<! Path is one convex piece
    kNonOverlappingConvexPieces_ConvexHint,   //<! Multiple convex pieces,
                                              //   pieces are known to be
                                              //   disjoint
    kSameWindingConvexPieces_ConvexHint,      //<! Multiple convex pieces,
                                              //   may or may not intersect,
                                              //   either all wind cw or all
                                              //   wind ccw.
    kConcave_ConvexHint                       //<! Path is known to be
                                              //   concave
};

///////////////////////////////////////////////////////////////////////////////

enum GrPlatformSurfaceType {
    /**
     * Specifies that the object being created is a render target.
     */
    kRenderTarget_GrPlatformSurfaceType,
    /**
     * Specifies that the object being created is a texture.
     */
    kTexture_GrPlatformSurfaceType,
    /**
     * Specifies that the object being created is a texture and a render
     * target.
     */
    kTextureRenderTarget_GrPlatformSurfaceType,
};

enum GrPlatformRenderTargetFlags {
    kNone_GrPlatformRenderTargetFlagBit             = 0x0,
    /**
     * Specifies that the object being created is multisampled.
     */
    kIsMultisampled_GrPlatformRenderTargetFlagBit   = 0x1,
    /**
     * Gives permission to Gr to perform the downsample-resolve of a
     * multisampled render target. If this is not set then read pixel
     * operations may fail. If the object is both a texture and render target
     * then this *must* be set. Otherwise, if the client wants do its own
     * resolves it must create separate GrRenderTarget and GrTexture objects
     * and insert appropriate flushes and resolves betweeen data hazards.
     * GrRenderTarget has a flagForResolve()
     */
    kGrCanResolve_GrPlatformRenderTargetFlagBit     = 0x2,
};

GR_MAKE_BITFIELD_OPS(GrPlatformRenderTargetFlags)

// opaque type for 3D API object handles
typedef intptr_t GrPlatform3DObject;

/**
 * Description of platform surface to create. See below for GL example.
 */
struct GrPlatformSurfaceDesc {
    GrPlatformSurfaceType           fSurfaceType;   // type of surface to create
    /**
     * Flags for kRenderTarget and kTextureRenderTarget surface types
     */
    GrPlatformRenderTargetFlags     fRenderTargetFlags;

    int                             fWidth;         // width in pixels
    int                             fHeight;        // height in pixels
    GrPixelConfig                   fConfig;        // color format
    /**
     * Number of per sample stencil buffer. Only relevant if kIsRenderTarget is
     * set in fFlags.
     */
    int                             fStencilBits;
    /**
     * Texture object in 3D API. Only relevant if fSurfaceType is kTexture or
     * kTextureRenderTarget.
     * GL: this is a texture object (glGenTextures)
     */
    GrPlatform3DObject              fPlatformTexture;
    /**
     * Render target object in 3D API. Only relevant if fSurfaceType is
     * kRenderTarget or kTextureRenderTarget
     * GL: this is a FBO object (glGenFramebuffers)
     */
    GrPlatform3DObject              fPlatformRenderTarget;
    /**
     * 3D API object used as destination of resolve. Only relevant if
     * fSurfaceType is kRenderTarget or kTextureRenderTarget and
     * kGrCanResolve is set in fRenderTargetFlags.
     * fFlags.
     * GL: this is a FBO object (glGenFramebuffers)
     */
    GrPlatform3DObject              fPlatformResolveDestination;

    void reset() { memset(this, 0, sizeof(GrPlatformSurfaceDesc)); }
};

/**
 * Example of how to wrap render-to-texture-with-MSAA GL objects with a GrPlatformSurace
 *
 * GLint colorBufferID;
 * glGenRenderbuffers(1, &colorID);
 * glBindRenderbuffer(GL_RENDERBUFFER, colorBufferID);
 * glRenderbufferStorageMultisample(GL_RENDERBUFFER, S, GL_RGBA, W, H);
 *
 * GLint stencilBufferID;
 * glGenRenderBuffers(1, &stencilBufferID);
 * glBindRenderbuffer(GL_RENDERBUFFER, stencilBufferID);
 * glRenderbufferStorageMultisample(GL_RENDERBUFFER, S, GL_STENCIL_INDEX8, W, H);
 *
 * GLint drawFBOID;
 * glGenFramebuffers(1, &drawFBOID);
 * glBindFramebuffer(GL_FRAMEBUFFER, drawFBOID);
 * glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBufferID);
 * glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, stencilBufferID);
 *
 * GLint textureID;
 * glGenTextures(1, &textureID);
 * glBindTexture(GL_TEXTURE_2D, textureID);
 * glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, W, H, ...);
 *
 * GLint readFBOID;
 * glGenFramebuffers(1, &readFBOID);
 * glBindFramebuffer(GL_FRAMEBUFFER, readFBOID);
 * glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, textureID, 0);
 *
 * GrPlatformSurfaceDesc renderTargetTextureDesc;
 * renderTargetTextureDesc.fSurfaceType       = kTextureRenderTarget_GrPlatformSurfaceType;
 * renderTargetTextureDesc.fRenderTargetFlags = (kIsMultisampled_GrPlatformRenderTargetFlagBit | kGrCanResolve_GrPlatformRenderTargetFlagBit);
 * renderTargetTextureDesc.fWidth = W;
 * renderTargetTextureDesc.fHeight = H;
 * renderTargetTextureDesc.fConfig = kRGBA_8888_GrPixelConfig
 * renderTargetTextureDesc.fStencilBits = 8;
 * renderTargetTextureDesc.fPlatformTexture = textureID;
 * renderTargetTextureDesc.fPlatformRenderTarget = drawFBOID;
 * renderTargetTextureDesc.fPlatformResolveDestination = readFBOID;
 *
 * GrTexture* texture = static_cast<GrTexture*>(grContext->createPlatrformSurface(renderTargetTextureDesc));
 */

///////////////////////////////////////////////////////////////////////////////

// this is included only to make it easy to use this debugging facility
#include "GrInstanceCounter.h"

#endif