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 GrBinHashKey_DEFINED
#define GrBinHashKey_DEFINED

#include "GrTypes.h"

/**
 * Abstract base class that presents the building interface of GrBinHashKey.
 * This base class allows builder methods to not know the exact template
 * parameters of GrBinHashKey
 */
class GrBinHashKeyBuilder {
public:
    GrBinHashKeyBuilder() {}
    virtual ~GrBinHashKeyBuilder() {}
    virtual void keyData(const uint32_t *dataToAdd, size_t len) = 0;
};

/**
 *  Hash function class than can take a data stream of indeterminate length.
 *  It also has the ability to recieve data in several chunks (steamed). The
 *  hash function used is the One-at-a-Time Hash
 *  (http://burtleburtle.net/bob/hash/doobs.html).
 *
 *  Keys are built in two passes the first pass builds the key until the
 *  allocated storage for the key runs out, raw data accumulation stops, but
 *  the calculation of the 32-bit hash value and total key length continue.
 *  The second pass is only necessary if storage ran-out during the first pass.
 *  If that is the case, the heap storage portion of the key will be
 *  re-allocated so that the entire key can be stored in the second pass.
 *
 *  Code for building a key:
 *
 *      GrBinHashKey<MyEntryStruct, MyStackSize> MyKey;
 *      while( MyKey->doPass() )
 *      {
 *          MyObject->buildKey(&MyKey); //invoke a builder method
 *      }
 *
 *  All the builder method needs to do is make calls to the keyData method to
 *  append binary data to the key.
 */
template<typename Entry, size_t StackSize>
class GrBinHashKey : public GrBinHashKeyBuilder {
public:
    GrBinHashKey()
        : fA(0)
        , fLength(0)
        , fHeapData(NULL)
        , fPhysicalSize(StackSize)
        , fUseHeap(false)
        , fPass(0)
#if GR_DEBUG
        , fIsValid(true)
#endif
    {}

private:
    // Illegal: must choose explicitly between copyAndTakeOwnership
    // and deepCopyFrom.
    // Not inheriting GrNoncopyable, because it causes very obscure compiler
    // errors with template classes, which are hard to trace back to the use
    // of assignment.
    GrBinHashKey(const GrBinHashKey<Entry, StackSize>&) {}
    GrBinHashKey<Entry, StackSize>& operator=(const GrBinHashKey<Entry,
        StackSize>&) {
        return this;
    }

public:
    void copyAndTakeOwnership(GrBinHashKey<Entry, StackSize>& key) {
        GrAssert(key.fIsValid);
        copyFields(key);
        if (fUseHeap) {
            key.fHeapData = NULL;  // ownership transfer
        }
        // Consistency Checking
        // To avoid the overhead of copying or ref-counting the dynamically
        // allocated portion of the key, we use ownership transfer
        // Key usability is only tracked in debug builds.
        GR_DEBUGCODE(key.fIsValid = false;)
    }

    void deepCopyFrom(const GrBinHashKey<Entry, StackSize>& key) {
        GrAssert(key.fIsValid);
        copyFields(key);
        if (fUseHeap) {
            fHeapData = reinterpret_cast<uint8_t*>(
                GrMalloc(sizeof(uint8_t) * fPhysicalSize));
            memcpy(fHeapData, key.fHeapData, fLength);
        }
    }

    virtual ~GrBinHashKey() {
        if (fUseHeap) {
            GrFree(fHeapData);
        }
    }

    bool doPass() {
        GrAssert(fIsValid);
        if (0 == fPass) {
            fPass++;
            return true;
        }
        if (1 == fPass) {
            bool passNeeded = false;
            if (fLength > fPhysicalSize) {
                // If the first pass ran out of space the we need to
                // re-allocate and perform a second pass
                GrFree(fHeapData);
                fHeapData = reinterpret_cast<uint8_t*>(
                    GrMalloc(sizeof(uint8_t) * fLength));
                fPhysicalSize = fLength;
                fUseHeap = true;
                passNeeded = true;
                fLength = 0;
            }
            fPass++;
            return passNeeded;
        }
        return false;
    }

    void keyData(const uint32_t *dataToAdd, size_t len) {
        GrAssert(fIsValid);
        GrAssert(fPass);
        GrAssert(GrIsALIGN4(len));
        if (fUseHeap) {
            GrAssert(fHeapData);
            GrAssert(fLength + len <= fPhysicalSize);
            memcpy(&fHeapData[fLength], dataToAdd, len );
        } else {
            if (fLength + len <= StackSize) {
                memcpy(&fStackData[fLength], dataToAdd, len);
            } else {
                GrAssert(1 == fPass);
            }
        }

        fLength += len;

        if (1 == fPass) {
            uint32_t a = fA;
            while (len >= 4) {
                a += *dataToAdd++;
                a += (a << 10);
                a ^= (a >> 6);
                len -= 4;
            }
            a += (a << 3);
            a ^= (a >> 11);
            a += (a << 15);

            fA = a;
        }
    }

    int compare(const GrBinHashKey<Entry, StackSize>& key) const {
        GrAssert(fIsValid);
        if (fLength == key.fLength) {
            GrAssert(fUseHeap == key.fUseHeap);
            if(fUseHeap) {
                return memcmp(fHeapData, key.fHeapData, fLength);
            } else {
                return memcmp(fStackData, key.fStackData, fLength);
            }
        }

        return (fLength - key.fLength);
    }

    static bool
    EQ(const Entry& entry, const GrBinHashKey<Entry, StackSize>& key) {
        GrAssert(key.fIsValid);
        return 0 == entry.compare(key);
    }

    static bool
    LT(const Entry& entry, const GrBinHashKey<Entry, StackSize>& key) {
        GrAssert(key.fIsValid);
        return entry.compare(key) < 0;
    }

    uint32_t getHash() const {
        GrAssert(fIsValid);
        return fA;
    }

private:
    void copyFields(const GrBinHashKey<Entry, StackSize>& src) {
        if (fUseHeap) {
            GrFree(fHeapData);
        }
        // We do a field-by-field copy because this is a non-POD
        // class, and therefore memcpy would be bad
        fA = src.fA;
        fLength = src.fLength;
        memcpy(fStackData, src.fStackData, StackSize);
        fHeapData = src.fHeapData;
        fPhysicalSize = src.fPhysicalSize;
        fUseHeap = src.fUseHeap;
        fPass = src.fPass;
    }

    uint32_t                fA;

    // For accumulating the variable length binary key
    size_t              fLength;                // length of data accumulated so far
    uint8_t             fStackData[StackSize];  //Buffer for key storage
    uint8_t*            fHeapData;              //Dynamically allocated extended key storage
    size_t              fPhysicalSize;          //Total size available for key storage
    bool                fUseHeap;               //Using a dynamically allocated key storage
    int                 fPass;                  //Key generation pass counter

#if GR_DEBUG
public:
    bool                fIsValid;
#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 GrBufferAllocPool_DEFINED
#define GrBufferAllocPool_DEFINED

#include "GrNoncopyable.h"
#include "GrTDArray.h"
#include "GrTArray.h"
#include "GrMemory.h"

class GrGeometryBuffer;
class GrGpu;

/**
 * A pool of geometry buffers tied to a GrGpu.
 *
 * The pool allows a client to make space for geometry and then put back excess
 * space if it over allocated. When a client is ready to draw from the pool
 * it calls unlock on the pool ensure buffers are ready for drawing. The pool
 * can be reset after drawing is completed to recycle space.
 *
 * At creation time a minimum per-buffer size can be specified. Additionally,
 * a number of buffers to preallocate can be specified. These will
 * be allocated at the min size and kept around until the pool is destroyed.
 */
class GrBufferAllocPool : GrNoncopyable {

public:
    /**
     * Ensures all buffers are unlocked and have all data written to them.
     * Call before drawing using buffers from the pool.
     */
    void unlock();

    /**
     *  Invalidates all the data in the pool, unrefs non-preallocated buffers.
     */
    void reset();

    /**
     * Gets the number of preallocated buffers that are yet to be used.
     */
    int preallocatedBuffersRemaining() const;

    /**
     * gets the number of preallocated buffers
     */
    int preallocatedBufferCount() const;

    /**
     * Frees data from makeSpaces in LIFO order.
     */
    void putBack(size_t bytes);

    /**
     * Gets the GrGpu that this pool is associated with.
     */
    GrGpu* getGpu() { return fGpu; }

protected:
    /**
     * Used to determine what type of buffers to create. We could make the
     * createBuffer a virtual except that we want to use it in the cons for
     * pre-allocated buffers.
     */
    enum BufferType {
        kVertex_BufferType,
        kIndex_BufferType,
    };

    /**
     * Constructor
     *
     * @param gpu                   The GrGpu used to create the buffers.
     * @param bufferType            The type of buffers to create.
     * @param frequentResetHint     A hint that indicates that the pool
     *                              should expect frequent unlock() calls
     *                              (as opposed to many makeSpace / acquires
     *                              between resets).
     * @param bufferSize            The minimum size of created buffers.
     *                              This value will be clamped to some
     *                              reasonable minimum.
     * @param preallocBufferCnt     The pool will allocate this number of
     *                              buffers at bufferSize and keep them until it
     *                              is destroyed.
     */
     GrBufferAllocPool(GrGpu* gpu,
                       BufferType bufferType,
                       bool frequentResetHint,
                       size_t   bufferSize = 0,
                       int preallocBufferCnt = 0);

    virtual ~GrBufferAllocPool();

    /**
     * Gets the size of the preallocated buffers.
     *
     * @return the size of preallocated buffers.
     */
    size_t preallocatedBufferSize() const {
        return fPreallocBuffers.count() ? fMinBlockSize : 0;
    }

    /**
     * Returns a block of memory to hold data. A buffer designated to hold the
     * data is given to the caller. The buffer may or may not be locked. The
     * returned ptr remains valid until any of the following:
     *      *makeSpace is called again.
     *      *unlock is called.
     *      *reset is called.
     *      *this object is destroyed.
     *
     * Once unlock on the pool is called the data is guaranteed to be in the
     * buffer at the offset indicated by offset. Until that time it may be
     * in temporary storage and/or the buffer may be locked.
     *
     * @param size         the amount of data to make space for
     * @param alignment    alignment constraint from start of buffer
     * @param buffer       returns the buffer that will hold the data.
     * @param offset       returns the offset into buffer of the data.
     * @return pointer to where the client should write the data.
     */
    void* makeSpace(size_t size,
                    size_t alignment,
                    const GrGeometryBuffer** buffer,
                    size_t* offset);

    /**
     * Gets the number of items of a size that can be added to the current
     * buffer without spilling to another buffer. If the pool has been reset, or
     * the previous makeSpace completely exhausted a buffer then the returned
     * size will be the size of the next available preallocated buffer, or zero
     * if no preallocated buffer remains available. It is assumed that items
     * should be itemSize-aligned from the start of a buffer.
     *
     * @return the number of items that would fit in the current buffer.
     */
    int currentBufferItems(size_t itemSize) const;

    GrGeometryBuffer* createBuffer(size_t size);

private:

    // The GrGpu must be able to clear the ref of pools it creates as members
    friend class GrGpu;
    void releaseGpuRef();

    struct BufferBlock {
        size_t              fBytesFree;
        GrGeometryBuffer*   fBuffer;
    };

    bool createBlock(size_t requestSize);
    void destroyBlock();
    void flushCpuData(GrGeometryBuffer* buffer, size_t flushSize);
#if GR_DEBUG
    void validate(bool unusedBlockAllowed = false) const;
#endif

    size_t                          fBytesInUse;

    GrGpu*                          fGpu;
    bool                            fGpuIsReffed;
    bool                            fFrequentResetHint;
    GrTDArray<GrGeometryBuffer*>    fPreallocBuffers;
    size_t                          fMinBlockSize;
    BufferType                      fBufferType;

    GrTArray<BufferBlock>           fBlocks;
    int                             fPreallocBuffersInUse;
    int                             fFirstPreallocBuffer;
    GrAutoMalloc                    fCpuData;
    void*                       	fBufferPtr;
};

class GrVertexBuffer;

/**
 * A GrBufferAllocPool of vertex buffers
 */
class GrVertexBufferAllocPool : public GrBufferAllocPool {
public:
    /**
     * Constructor
     *
     * @param gpu                   The GrGpu used to create the vertex buffers.
     * @param frequentResetHint     A hint that indicates that the pool
     *                              should expect frequent unlock() calls
     *                              (as opposed to many makeSpace / acquires
     *                              between resets).
     * @param bufferSize            The minimum size of created VBs This value
     *                              will be clamped to some reasonable minimum.
     * @param preallocBufferCnt     The pool will allocate this number of VBs at
     *                              bufferSize and keep them until it is
     *                              destroyed.
     */
    GrVertexBufferAllocPool(GrGpu* gpu,
                            bool frequentResetHint,
                            size_t bufferSize = 0,
                            int preallocBufferCnt = 0);

    /**
     * Returns a block of memory to hold vertices. A buffer designated to hold
     * the vertices given to the caller. The buffer may or may not be locked.
     * The returned ptr remains valid until any of the following:
     *      *makeSpace is called again.
     *      *unlock is called.
     *      *reset is called.
     *      *this object is destroyed.
     *
     * Once unlock on the pool is called the vertices are guaranteed to be in
     * the buffer at the offset indicated by startVertex. Until that time they
     * may be in temporary storage and/or the buffer may be locked.
     *
     * @param layout       specifies type of vertices to allocate space for
     * @param vertexCount  number of vertices to allocate space for
     * @param buffer       returns the vertex buffer that will hold the
     *                     vertices.
     * @param startVertex  returns the offset into buffer of the first vertex.
     *                     In units of the size of a vertex from layout param.
     * @return pointer to first vertex.
     */
    void* makeSpace(GrVertexLayout layout,
                    int vertexCount,
                    const GrVertexBuffer** buffer,
                    int* startVertex);

    /**
     * Shortcut to make space and then write verts into the made space.
     */
    bool appendVertices(GrVertexLayout layout,
                        int vertexCount,
                        const void* vertices,
                        const GrVertexBuffer** buffer,
                        int* startVertex);

    /**
     * Gets the number of vertices that can be added to the current VB without
     * spilling to another VB. If the pool has been reset, or the previous
     * makeSpace completely exhausted a VB then the returned number of vertices
     * would fit in the next available preallocated buffer. If any makeSpace
     * would force a new VB to be created the return value will be zero.
     *
     * @param   the format of vertices to compute space for.
     * @return the number of vertices that would fit in the current buffer.
     */
    int currentBufferVertices(GrVertexLayout layout) const;

    /**
     * Gets the number of vertices that can fit in a  preallocated vertex buffer.
     * Zero if no preallocated buffers.
     *
     * @param   the format of vertices to compute space for.
     *
     * @return number of vertices that fit in one of the preallocated vertex
     *         buffers.
     */
    int preallocatedBufferVertices(GrVertexLayout layout) const;

private:
    typedef GrBufferAllocPool INHERITED;
};

class GrIndexBuffer;

/**
 * A GrBufferAllocPool of index buffers
 */
class GrIndexBufferAllocPool : public GrBufferAllocPool {
public:
    /**
     * Constructor
     *
     * @param gpu                   The GrGpu used to create the index buffers.
     * @param frequentResetHint     A hint that indicates that the pool
     *                              should expect frequent unlock() calls
     *                              (as opposed to many makeSpace / acquires
     *                              between resets).
     * @param bufferSize            The minimum size of created IBs This value
     *                              will be clamped to some reasonable minimum.
     * @param preallocBufferCnt     The pool will allocate this number of VBs at
     *                              bufferSize and keep them until it is
     *                              destroyed.
     */
    GrIndexBufferAllocPool(GrGpu* gpu,
                           bool frequentResetHint,
                           size_t bufferSize = 0,
                           int preallocBufferCnt = 0);

    /**
     * Returns a block of memory to hold indices. A buffer designated to hold
     * the indices is given to the caller. The buffer may or may not be locked.
     * The returned ptr remains valid until any of the following:
     *      *makeSpace is called again.
     *      *unlock is called.
     *      *reset is called.
     *      *this object is destroyed.
     *
     * Once unlock on the pool is called the indices are guaranteed to be in the
     * buffer at the offset indicated by startIndex. Until that time they may be
     * in temporary storage and/or the buffer may be locked.
     *
     * @param indexCount   number of indices to allocate space for
     * @param buffer       returns the index buffer that will hold the indices.
     * @param startIndex   returns the offset into buffer of the first index.
     * @return pointer to first index.
     */
    void* makeSpace(int indexCount,
                    const GrIndexBuffer** buffer,
                    int* startIndex);

    /**
     * Shortcut to make space and then write indices into the made space.
     */
    bool appendIndices(int indexCount,
                       const void* indices,
                       const GrIndexBuffer** buffer,
                       int* startIndex);

    /**
     * Gets the number of indices that can be added to the current IB without
     * spilling to another IB. If the pool has been reset, or the previous
     * makeSpace completely exhausted a IB then the returned number of indices
     * would fit in the next available preallocated buffer. If any makeSpace
     * would force a new IB to be created the return value will be zero.
     */
    int currentBufferIndices() const;

    /**
     * Gets the number of indices that can fit in a preallocated index buffer.
     * Zero if no preallocated buffers.
     *
     * @return number of indices that fit in one of the preallocated index
     *         buffers.
     */
    int preallocatedBufferIndices() const;

private:
    typedef GrBufferAllocPool INHERITED;
};

#endif

license: mit


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 GrClip_DEFINED
#define GrClip_DEFINED

#include "GrClipIterator.h"
#include "GrRect.h"
#include "GrPath.h"
#include "GrTArray.h"
#include "GrTemplates.h"

class GrClip {
public:
    GrClip();
    GrClip(const GrClip& src);
    /**
     *  If specified, the conservativeBounds parameter already takes (tx,ty)
     *  into account.
     */
    GrClip(GrClipIterator* iter, GrScalar tx, GrScalar ty,
           const GrRect* conservativeBounds = NULL);
    GrClip(const GrIRect& rect);
    GrClip(const GrRect& rect);

    ~GrClip();

    GrClip& operator=(const GrClip& src);

    bool hasConservativeBounds() const { return fConservativeBoundsValid; }

    const GrRect& getConservativeBounds() const { return fConservativeBounds; }

    int getElementCount() const { return fList.count(); }

    GrClipType getElementType(int i) const { return fList[i].fType; }

    const GrPath& getPath(int i) const {
        GrAssert(kPath_ClipType == fList[i].fType);
        return fList[i].fPath;
    }

    GrPathFill getPathFill(int i) const {
        GrAssert(kPath_ClipType == fList[i].fType);
        return fList[i].fPathFill;
    }

    const GrRect& getRect(int i) const {
        GrAssert(kRect_ClipType == fList[i].fType);
        return fList[i].fRect;
    }

    GrSetOp getOp(int i) const { return fList[i].fOp; }

    bool isRect() const {
        if (1 == fList.count() && kRect_ClipType == fList[0].fType) {
            // if we determined that the clip is a single rect
            // we ought to have also used that rect as the bounds.
            GrAssert(fConservativeBoundsValid);
            GrAssert(fConservativeBounds == fList[0].fRect);
            return true;
        } else {
            return false;
        }
    }

    bool isEmpty() const { return 0 == fList.count(); }

    /**
     *  Resets this clip to be empty
     */
    void setEmpty();

    /**
     *  If specified, the bounds parameter already takes (tx,ty) into account.
     */
    void setFromIterator(GrClipIterator* iter, GrScalar tx, GrScalar ty,
                         const GrRect* conservativeBounds = NULL);
    void setFromRect(const GrRect& rect);
    void setFromIRect(const GrIRect& rect);

    friend bool operator==(const GrClip& a, const GrClip& b) {
        if (a.fList.count() != b.fList.count()) {
            return false;
        }
        int count = a.fList.count();
        for (int i = 0; i < count; ++i) {
            if (a.fList[i] != b.fList[i]) {
                return false;
            }
        }
        return true;
    }
    friend bool operator!=(const GrClip& a, const GrClip& b) {
        return !(a == b);
    }

private:
    struct Element {
        GrClipType  fType;
        GrRect      fRect;
        GrPath      fPath;
        GrPathFill  fPathFill;
        GrSetOp     fOp;
        bool operator ==(const Element& e) const {
            if (e.fType != fType || e.fOp != fOp) {
                return false;
            }
            switch (fType) {
                case kRect_ClipType:
                    return fRect == e.fRect;
                    break;
                case kPath_ClipType:
                    return fPath == e.fPath;
                default:
                    GrCrash("Unknown clip element type.");
                    return false; // suppress warning
            }
        }
        bool operator !=(const Element& e) const { return !(*this == e); }
    };

    GrRect              fConservativeBounds;
    bool                fConservativeBoundsValid;

    enum {
        kPreAllocElements = 4,
    };
    GrAlignedSTStorage<kPreAllocElements, Element>  fListStorage;
    GrTArray<Element>   fList;
};
#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 GrClipIterator_DEFINED
#define GrClipIterator_DEFINED

#include "GrPath.h"
#include "GrRect.h"

/**
 * A clip is a list of paths and/or rects with set operations to combine them.
 */
class GrClipIterator {
public:
    virtual ~GrClipIterator() {}

    /**
     *  Returns true if there are no more rects to process
     */
    virtual bool isDone() const = 0;

    /**
     *  Rewind the iterator to replay the set of clip elements again
     */
    virtual void rewind() = 0;

    /**
     * Get the type of the current clip element
     */
    virtual GrClipType getType() const = 0;

    /**
     * Return the current path. It is an error to call this when isDone() is
     * true or when getType() is kRect_Type.
     */
    virtual const GrPath* getPath() = 0;

    /**
     * Return the fill rule for the path. It is an error to call this when
     * isDone() is true or when getType is kRect_Type.
     */
    virtual GrPathFill getPathFill() const = 0;

    /**
    * Return the current rect. It is an error to call this when isDone is true
    * or when getType() is kPath_Type.
    */
    virtual void getRect(GrRect* rect) const = 0;

    /**
     * Gets the operation used to apply the current item to previously iterated
     * items. Iterators should not produce a Replace op.
     */
    virtual GrSetOp getOp() const = 0;

    /**
     *  Call to move to the next element in the list, previous path iter can be
     *  made invalid.
     */
    virtual void next() = 0;
};

/**
 *  Call to rewind iter, first checking to see if iter is NULL
 */
static inline void GrSafeRewind(GrClipIterator* iter) {
    if (iter) {
        iter->rewind();
    }
}

#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 GrColor_DEFINED
#define GrColor_DEFINED

#include "GrTypes.h"

/**
 *  GrColor is 4 bytes for R, G, B, A, in a compile-time specific order. The
 *  components are stored premultiplied.
 */
typedef uint32_t GrColor;

// indices for address a GrColor as an array of bytes

#define GrColor_INDEX_R     0
#define GrColor_INDEX_G     1
#define GrColor_INDEX_B     2
#define GrColor_INDEX_A     3

// shfit amount to assign a component to a GrColor int

#define GrColor_SHIFT_R     0
#define GrColor_SHIFT_G     8
#define GrColor_SHIFT_B     16
#define GrColor_SHIFT_A     24

/**
 *  Pack 4 components (RGBA) into a GrColor int
 */
static inline GrColor GrColorPackRGBA(unsigned r, unsigned g,
                                      unsigned b, unsigned a) {
    GrAssert((uint8_t)r == r);
    GrAssert((uint8_t)g == g);
    GrAssert((uint8_t)b == b);
    GrAssert((uint8_t)a == a);
    return  (r << GrColor_SHIFT_R) |
            (g << GrColor_SHIFT_G) |
            (b << GrColor_SHIFT_B) |
            (a << GrColor_SHIFT_A);
}

// extract a component (byte) from a GrColor int

#define GrColorUnpackR(color)   (((color) >> GrColor_SHIFT_R) & 0xFF)
#define GrColorUnpackG(color)   (((color) >> GrColor_SHIFT_G) & 0xFF)
#define GrColorUnpackB(color)   (((color) >> GrColor_SHIFT_B) & 0xFF)
#define GrColorUnpackA(color)   (((color) >> GrColor_SHIFT_A) & 0xFF)

/**
 *  Since premultiplied means that alpha >= color, we construct a color with
 *  each component==255 and alpha == 0 to be "illegal"
 */
#define GrColor_ILLEGAL     (~(0xFF << GrColor_SHIFT_A))

#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 GrConfig_DEFINED
#define GrConfig_DEFINED

///////////////////////////////////////////////////////////////////////////////
// preconfig section:
//
// All the work before including GrUserConfig.h should center around guessing
// what platform we're on, and defining low-level symbols based on that.
//
// A build environment may have already defined symbols, so we first check
// for that
//

// hack to ensure we know what sort of Apple platform we're on
#if defined(__APPLE_CPP__) || defined(__APPLE_CC__)
    #include <TargetConditionals.h>
#endif

/**
 *  Gr defines are set to 0 or 1, rather than being undefined or defined
 */

#if !defined(GR_ANDROID_BUILD)
    #define GR_ANDROID_BUILD    0
#endif
#if !defined(GR_IOS_BUILD)
    #define GR_IOS_BUILD        0
#endif
#if !defined(GR_LINUX_BUILD)
    #define GR_LINUX_BUILD      0
#endif
#if !defined(GR_MAC_BUILD)
    #define GR_MAC_BUILD        0
#endif
#if !defined(GR_WIN32_BUILD)
    #define GR_WIN32_BUILD      0
#endif
#if !defined(GR_QNX_BUILD)
    #define GR_QNX_BUILD        0
#endif

/**
 *  If no build target has been defined, attempt to infer.
 */
#if !GR_ANDROID_BUILD && !GR_IOS_BUILD && !GR_LINUX_BUILD && !GR_MAC_BUILD && !GR_WIN32_BUILD && !GR_QNX_BUILD
    #if defined(_WIN32)
        #undef GR_WIN32_BUILD
        #define GR_WIN32_BUILD      1
//      #error "WIN"
    #elif TARGET_OS_IPHONE || TARGET_IPHONE_SIMULATOR
        #undef GR_IOS_BUILD
        #define GR_IOS_BUILD        1
//      #error "IOS"
    #elif (defined(ANDROID_NDK) && ANDROID_NDK) || defined(ANDROID)
        #undef GR_ANDROID_BUILD
        #define GR_ANDROID_BUILD    1
//      #error "ANDROID"
    #elif TARGET_OS_MAC
        #undef GR_MAC_BUILD
        #define GR_MAC_BUILD        1
//      #error "MAC"
    #elif TARGET_OS_QNX || defined(__QNXNTO__)
        #undef GR_QNX_BUILD
        #define GR_QNX_BUILD        1
//      #error "QNX"
    #else
        #undef GR_LINUX_BUILD
        #define GR_LINUX_BUILD      1
//      #error "LINUX"
    #endif
#endif

// we need both GR_DEBUG and GR_RELEASE to be defined as 0 or 1
//
#ifndef GR_DEBUG
    #ifdef GR_RELEASE
        #define GR_DEBUG !GR_RELEASE
    #else
        #ifdef NDEBUG
            #define GR_DEBUG    0
        #else
            #define GR_DEBUG    1
        #endif
    #endif
#endif

#ifndef GR_RELEASE
    #define GR_RELEASE  !GR_DEBUG
#endif

#if GR_DEBUG == GR_RELEASE
    #error "GR_DEBUG and GR_RELEASE must not be the same"
#endif

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

#if GR_WIN32_BUILD
// VC8 doesn't support stdint.h, so we define those types here.
typedef signed char int8_t;
typedef unsigned char uint8_t;
typedef short int16_t;
typedef unsigned short uint16_t;
typedef int int32_t;
typedef unsigned uint32_t;
typedef __int64 int64_t;
typedef unsigned __int64 uint64_t;
#else
/*
 *  Include stdint.h with defines that trigger declaration of C99 limit/const
 *  macros here before anyone else has a chance to include stdint.h without
 *  these.
 */
#define __STDC_LIMIT_MACROS
#define __STDC_CONSTANT_MACROS
#include <stdint.h>
#endif

/*
 *  The "user config" file can be empty, and everything should work. It is
 *  meant to store a given platform/client's overrides of our guess-work.
 *
 *  A alternate user config file can be specified by defining
 *  GR_USER_CONFIG_FILE. It should be defined relative to GrConfig.h
 *
 *  e.g. it can specify GR_DEBUG/GR_RELEASE as it please, change the BUILD
 *  target, or supply its own defines for anything else (e.g. GR_SCALAR)
 */
#if !defined(GR_USER_CONFIG_FILE)
    #include "GrUserConfig.h"
#else
    #include GR_USER_CONFIG_FILE
#endif

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
// postconfig section:
//

// GR_IMPLEMENTATION should be define to 1 when building Gr and 0 when including
// it in another dependent build. The Gr makefile/ide-project should define this
// to 1.
#if !defined(GR_IMPLEMENTATION)
    #define GR_IMPLEMENTATION 0
#endif

// If Gr is built as a shared library then GR_DLL should be defined to 1 (both
// when building Gr and when including its headers in dependent builds). Only
// currently supported minimally for Chrome's Win32 Multi-DLL build (TODO:
// correctly exort all of the public API correctly and support shared lib on
// other platforms).
#if !defined(GR_DLL)
    #define GR_DLL 0
#endif

#if defined(WIN32) && defined(SKIA_DLL)
    #if GR_IMPLEMENTATION
        #if defined(__GNUC__)
            #define GR_API __attribute__((dllexport))
        #else
            #define GR_API __declspec(dllexport)
        #endif
    #else
        #if defined(__GNUC__)
            #define GR_API __attribute__((dllimport))
        #else
            #define GR_API __declspec(dllimport)
        #endif
    #endif
#elif __GNUC__ >= 4
    #if GR_IMPLEMENTATION
        #define GR_API __attribute__((visibility("default")))
    #else
        #define GR_API
    #endif
#else
    #define GR_API
#endif

// By now we must have a GR_..._BUILD symbol set to 1, and a decision about
// debug -vs- release
//

extern GR_API void GrPrintf(const char format[], ...);

/**
 *  GR_STRING makes a string of X where X is expanded before conversion to a string
 *  if X itself contains macros.
 */
#define GR_STRING(X) GR_STRING_IMPL(X)
#define GR_STRING_IMPL(X) #X

/**
 *  GR_CONCAT concatenates X and Y  where each is expanded before
 *  contanenation if either contains macros.
 */
#define GR_CONCAT(X,Y) GR_CONCAT_IMPL(X,Y)
#define GR_CONCAT_IMPL(X,Y) X##Y

/**
 *  Creates a string of the form "<filename>(<linenumber>) : "
 */
#define GR_FILE_AND_LINE_STR __FILE__ "(" GR_STRING(__LINE__) ") : "

/**
 *  Compilers have different ways of issuing warnings. This macro
 *  attempts to abstract them, but may need to be specialized for your
 *  particular compiler.
 *  To insert compiler warnings use "#pragma message GR_WARN(<string>)"
 */
#if defined(_MSC_VER) && _MSC_VER
    #define GR_WARN(MSG) (GR_FILE_AND_LINE_STR "WARNING: " MSG)
#else//__GNUC__ - may need other defines for different compilers
    #define GR_WARN(MSG) ("WARNING: " MSG)
#endif

/**
 *  GR_ALWAYSBREAK is an unconditional break in all builds.
 */
#if !defined(GR_ALWAYSBREAK)
    #if     GR_WIN32_BUILD
        #define GR_ALWAYSBREAK __debugbreak()
    #else
        // TODO: do other platforms really not have continuable breakpoints?
        // sign extend for 64bit architectures to be sure this is
        // in the high address range
        #define GR_ALWAYSBREAK *((int*)(int64_t)(int32_t)0xbeefcafe) = 0;
    #endif
#endif

/**
 *  GR_DEBUGBREAK is an unconditional break in debug builds.
 */
#if !defined(GR_DEBUGBREAK)
    #if GR_DEBUG
        #define GR_DEBUGBREAK GR_ALWAYSBREAK
    #else
        #define GR_DEBUGBREAK
    #endif
#endif

/**
 *  GR_ALWAYSASSERT is an assertion in all builds.
 */
#if !defined(GR_ALWAYSASSERT)
    #define GR_ALWAYSASSERT(COND)                                        \
        do {                                                             \
            if (!(COND)) {                                               \
                GrPrintf("%s %s failed\n", GR_FILE_AND_LINE_STR, #COND); \
                GR_ALWAYSBREAK;                                          \
            }                                                            \
        } while (false)
#endif

/**
 *  GR_DEBUGASSERT is an assertion in debug builds only.
 */
#if !defined(GR_DEBUGASSERT)
    #if GR_DEBUG
        #define GR_DEBUGASSERT(COND) GR_ALWAYSASSERT(COND)
    #else
        #define GR_DEBUGASSERT(COND)
    #endif
#endif

/**
 *  Prettier forms of the above macros.
 */
#define GrAssert(COND) GR_DEBUGASSERT(COND)
#define GrAlwaysAssert(COND) GR_ALWAYSASSERT(COND)

/**
 * Crash from unrecoverable condition, optionally with a message.
 */
inline void GrCrash() { GrAlwaysAssert(false); }
inline void GrCrash(const char* msg) { GrPrintf(msg); GrAlwaysAssert(false); }

/**
 *  GR_DEBUGCODE compiles the code X in debug builds only
 */
#if !defined(GR_DEBUGCODE)
    #if GR_DEBUG
        #define GR_DEBUGCODE(X) X
    #else
        #define GR_DEBUGCODE(X)
    #endif
#endif

/**
 *  GR_STATIC_ASSERT is a compile time assertion. Depending on the platform
 *  it may print the message in the compiler log. Obviously, the condition must
 *  be evaluatable at compile time.
 */
// VS 2010 and GCC compiled with c++0x or gnu++0x support the new
// static_assert.
#if !defined(GR_STATIC_ASSERT)
    #if (defined(_MSC_VER) && _MSC_VER >= 1600) || (defined(__GXX_EXPERIMENTAL_CXX0X__) && __GXX_EXPERIMENTAL_CXX0X__)
        #define GR_STATIC_ASSERT(CONDITION) static_assert(CONDITION, "bug")
    #else
        template <bool> class GR_STATIC_ASSERT_FAILURE;
        template <> class GR_STATIC_ASSERT_FAILURE<true> {};
        #define GR_STATIC_ASSERT(CONDITION) \
            enum {GR_CONCAT(X,__LINE__) = \
            sizeof(GR_STATIC_ASSERT_FAILURE<CONDITION>)}
    #endif
#endif

#if !defined(GR_SCALAR_IS_FLOAT)
    #define GR_SCALAR_IS_FLOAT   0
#endif
#if !defined(GR_SCALAR_IS_FIXED)
    #define GR_SCALAR_IS_FIXED   0
#endif

#if !defined(GR_TEXT_SCALAR_TYPE_IS_USHORT)
    #define GR_TEXT_SCALAR_TYPE_IS_USHORT  0
#endif
#if !defined(GR_TEXT_SCALAR_TYPE_IS_FLOAT)
    #define GR_TEXT_SCALAR_TYPE_IS_FLOAT   0
#endif
#if !defined(GR_TEXT_SCALAR_TYPE_IS_FIXED)
    #define GR_TEXT_SCALAR_TYPE_IS_FIXED   0
#endif

#ifndef GR_DUMP_TEXTURE_UPLOAD
    #define GR_DUMP_TEXTURE_UPLOAD  0
#endif

/**
 *  GR_COLLECT_STATS controls whether the GrGpu class collects stats.
 *  If not already defined then collect in debug build but not release.
 */
#if !defined(GR_COLLECT_STATS)
    #define GR_COLLECT_STATS GR_DEBUG
#endif

/**
 *  GR_STATIC_RECT_VB controls whether rects are drawn by issuing a vertex
 *  for each corner or using a static vb that is positioned by modifying the
 *  view / texture matrix.
 */
#if !defined(GR_STATIC_RECT_VB)
    #define GR_STATIC_RECT_VB 1
#endif

/**
 *  GR_AGGRESSIVE_SHADER_OPTS controls how aggressively shaders are optimized
 *  for special cases. On systems where program changes are expensive this
 *  may not be advantageous. Consecutive draws may no longer use the same
 *  program.
 */
#if !defined(GR_AGGRESSIVE_SHADER_OPTS)
    #define GR_AGGRESSIVE_SHADER_OPTS 1
#endif

/**
 * GR_GEOM_BUFFER_LOCK_THRESHOLD gives a threshold (in bytes) for when Gr should
 * lock a GrGeometryBuffer to update its contents. It will use Lock() if the
 * size of the udpated region is greater than the threshold. Otherwise it will
 * use updateData() or updateSubData().
 */
#if !defined(GR_GEOM_BUFFER_LOCK_THRESHOLD)
    #define GR_GEOM_BUFFER_LOCK_THRESHOLD (1 << 15)
#endif

/**
 * Enables/disables use of offscreen AA
 */
#if !defined(GR_USE_OFFSCREEN_AA)
    #define GR_USE_OFFSCREEN_AA 0
#endif

/**
 * GR_MAX_OFFSCREEN_AA_SIZE controls the size at which offscreen AA will tile.
 * Tiling saves GPU memory by limiting the size of the offscreen buffer. The
 * max offscreen may be as large as (4*GR_MAX_OFFSCREEN_AA_SIZE)^2 pixels.
 */
#if !defined(GR_MAX_OFFSCREEN_AA_SIZE)
    #define GR_MAX_OFFSCREEN_AA_SIZE    256
#endif

///////////////////////////////////////////////////////////////////////////////
// tail section:
//
// Now we just assert if we are missing some required define, or if we detect
// and inconsistent combination of defines
//

/**
 *  Only one build target macro should be 1 and the rest should be 0.
 */
#define GR_BUILD_SUM    (GR_WIN32_BUILD + GR_MAC_BUILD + GR_IOS_BUILD + GR_ANDROID_BUILD + GR_LINUX_BUILD + GR_QNX_BUILD)
#if 0 == GR_BUILD_SUM
    #error "Missing a GR_BUILD define"
#elif 1 != GR_BUILD_SUM
    #error "More than one GR_BUILD defined"
#endif

#if !GR_SCALAR_IS_FLOAT && !GR_SCALAR_IS_FIXED
    #undef  GR_SCALAR_IS_FLOAT
    #define GR_SCALAR_IS_FLOAT              1
    #pragma message GR_WARN("Scalar type not defined, defaulting to float")
#endif

#if !GR_TEXT_SCALAR_IS_FLOAT && \
    !GR_TEXT_SCALAR_IS_FIXED && \
    !GR_TEXT_SCALAR_IS_USHORT
    #undef  GR_TEXT_SCALAR_IS_FLOAT
    #define GR_TEXT_SCALAR_IS_FLOAT         1
    #pragma message GR_WARN("Text scalar type not defined, defaulting to float")
#endif

#if 0
#if GR_WIN32_BUILD
//    #pragma message GR_WARN("GR_WIN32_BUILD")
#endif
#if GR_MAC_BUILD
//    #pragma message GR_WARN("GR_MAC_BUILD")
#endif
#if GR_IOS_BUILD
//    #pragma message GR_WARN("GR_IOS_BUILD")
#endif
#if GR_ANDROID_BUILD
//    #pragma message GR_WARN("GR_ANDROID_BUILD")
#endif
#if GR_LINUX_BUILD
//    #pragma message GR_WARN("GR_LINUX_BUILD")
#endif
#if GR_QNX_BUILD
//    #pragma message GR_WARN("GR_QNX_BUILD")
#endif
#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 GrContext_DEFINED
#define GrContext_DEFINED

#include "GrClip.h"
#include "GrTextureCache.h"
#include "GrPaint.h"
#include "GrPathRenderer.h"

class GrFontCache;
class GrGpu;
struct GrGpuStats;
class GrVertexBufferAllocPool;
class GrIndexBufferAllocPool;
class GrInOrderDrawBuffer;

class GR_API GrContext : public GrRefCnt {
public:
    /**
     * Creates a GrContext from within a 3D context.
     */
    static GrContext* Create(GrEngine engine,
                             GrPlatform3DContext context3D);

    /**
     *  Helper to create a opengl-shader based context
     */
    static GrContext* CreateGLShaderContext();

    virtual ~GrContext();

    /**
     * The GrContext normally assumes that no outsider is setting state
     * within the underlying 3D API's context/device/whatever. This call informs
     * the context that the state was modified and it should resend. Shouldn't
     * be called frequently for good performance.
     */
    void resetContext();

    /**
     * Abandons all gpu resources, assumes 3D API state is unknown. Call this
     * if you have lost the associated GPU context, and thus internal texture,
     * buffer, etc. references/IDs are now invalid. Should be called even when
     * GrContext is no longer going to be used for two reasons:
     *  1) ~GrContext will not try to free the objects in the 3D API.
     *  2) If you've created GrResources that outlive the GrContext they will
     *     be marked as invalid (GrResource::isValid()) and won't attempt to
     *     free their underlying resource in the 3D API.
     * Content drawn since the last GrContext::flush() may be lost.
     */
    void contextLost();

    /**
     * Similar to contextLost, but makes no attempt to reset state.
     * Use this method when GrContext destruction is pending, but
     * the graphics context is destroyed first.
     */
    void contextDestroyed();

    /**
     * Frees gpu created by the context. Can be called to reduce GPU memory
     * pressure.
     */
    void freeGpuResources();

    ///////////////////////////////////////////////////////////////////////////
    // Textures

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

    /**
     *  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* createAndLockTexture(GrTextureKey* key,
                                         const GrSamplerState&,
                                         const GrTextureDesc&,
                                         void* srcData, size_t rowBytes);

    /**
     * Returns a texture matching the desc. It's contents are unknown. Subsequent
     * requests with the same descriptor are not guaranteed to return the same
     * texture. The same texture is guaranteed not be returned again until it is
     * unlocked.
     *
     * Textures created by createAndLockTexture() hide the complications of
     * tiling non-power-of-two textures on APIs that don't support this (e.g.
     * unextended GLES2). Tiling a npot texture created by lockKeylessTexture on
     * such an API will create gaps in the tiling pattern. This includes clamp
     * mode. (This may be addressed in a future update.)
     */
    GrTextureEntry* lockKeylessTexture(const GrTextureDesc& desc);

    /**
     * Finds a texture that approximately matches the descriptor. Will be
     * at least as large in width and height as desc specifies. If desc
     * specifies that texture is a render target then result will be a
     * render target. If desc specifies a render target and doesn't set the
     * no stencil flag then result will have a stencil. Format and aa level
     * will always match.
     */
    GrTextureEntry* findApproximateKeylessTexture(const GrTextureDesc& desc);

    /**
     *  When done with an entry, call unlockTexture(entry) on it, which returns
     *  it to the cache, where it may be purged.
     */
    void unlockTexture(GrTextureEntry* entry);

    /**
     * Creates a texture that is outside the cache. Does not count against
     * cache's budget.
     */
    GrTexture* createUncachedTexture(const GrTextureDesc&,
                                     void* srcData,
                                     size_t rowBytes);

    /**
     *  Returns true if the specified use of an indexed texture is supported.
     */
    bool supportsIndex8PixelConfig(const GrSamplerState&, int width, int height);

    /**
     *  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 getTextureCacheLimits(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 setTextureCacheLimits(int maxTextures, size_t maxTextureBytes);

    /**
     *  Return the max width or height of a texture supported by the current gpu
     */
    int getMaxTextureSize() const;

    /**
     * Return the max width or height of a render target supported by the
     * current gpu
     */
    int getMaxRenderTargetSize() const;

    ///////////////////////////////////////////////////////////////////////////
    // Render targets

    /**
     * Sets the render target.
     * @param target    the render target to set. (should not be NULL.)
     */
    void setRenderTarget(GrRenderTarget* target);

    /**
     * Gets the current render target.
     * @return the currently bound render target. Should never be NULL.
     */
    const GrRenderTarget* getRenderTarget() const;
    GrRenderTarget* getRenderTarget();

    ///////////////////////////////////////////////////////////////////////////
    // Platform Surfaces

    // GrContext provides an interface for wrapping externally created textures
    // and rendertargets in their Gr-equivalents.

    /**
     * Wraps an existing 3D API surface in a GrObject. desc.fFlags determines
     * the type of object returned. If kIsTexture is set the returned object
     * will be a GrTexture*. Otherwise, it will be a GrRenderTarget*. If both
     * are set the render target object is accessible by
     * GrTexture::asRenderTarget().
     *
     * GL: if the object is a texture Gr may change its GL texture parameters
     *     when it is drawn.
     *
     * @param   desc    description of the object to create.
     * @return either a GrTexture* or GrRenderTarget* depending on desc. NULL
     *         on failure.
     */
    GrResource* createPlatformSurface(const GrPlatformSurfaceDesc& desc);
    /**
     * Reads the current target object (e.g. FBO or IDirect3DSurface9*) and
     * viewport state from the underlying 3D API and wraps it in a
     * GrRenderTarget. The GrRenderTarget will not attempt to delete/destroy the
     * underlying object in its destructor and it is up to caller to guarantee
     * that it remains valid while the GrRenderTarget is used.
     *
     * Will not detect that the render target is also a texture. If you need
     * to also use the render target as a GrTexture use createPlatformSurface.
     *
     * @return the newly created GrRenderTarget
     */
    GrRenderTarget* createRenderTargetFrom3DApiState();

    ///////////////////////////////////////////////////////////////////////////
    // Matrix state

    /**
     * Gets the current transformation matrix.
     * @return the current matrix.
     */
    const GrMatrix& getMatrix() const;

    /**
     * Sets the transformation matrix.
     * @param m the matrix to set.
     */
    void setMatrix(const GrMatrix& m);

    /**
     * Concats the current matrix. The passed matrix is applied before the
     * current matrix.
     * @param m the matrix to concat.
     */
    void concatMatrix(const GrMatrix& m) const;

    ///////////////////////////////////////////////////////////////////////////
    // Clip state
    /**
     * Gets the current clip.
     * @return the current clip.
     */
    const GrClip& getClip() const;

    /**
     * Sets the clip.
     * @param clip  the clip to set.
     */
    void setClip(const GrClip& clip);

    /**
     * Convenience method for setting the clip to a rect.
     * @param rect  the rect to set as the new clip.
     */
    void setClip(const GrIRect& rect);

    ///////////////////////////////////////////////////////////////////////////
    // Draws

    /**
     * Clear the entire or rect of the render target, ignoring any clips.
     * @param rect  the rect to clear or the whole thing if rect is NULL.
     * @param color the color to clear to.
     */
    void clear(const GrIRect* rect, GrColor color);

    /**
     *  Draw everywhere (respecting the clip) with the paint.
     */
    void drawPaint(const GrPaint& paint);

    /**
     *  Draw the rect using a paint.
     *  @param paint        describes how to color pixels.
     *  @param strokeWidth  If strokeWidth < 0, then the rect is filled, else
     *                      the rect is mitered stroked based on strokeWidth. If
     *                      strokeWidth == 0, then the stroke is always a single
     *                      pixel thick.
     *  @param matrix       Optional matrix applied to the rect. Applied before
     *                      context's matrix or the paint's matrix.
     *  The rects coords are used to access the paint (through texture matrix)
     */
    void drawRect(const GrPaint& paint,
                  const GrRect&,
                  GrScalar strokeWidth = -1,
                  const GrMatrix* matrix = NULL);

    /**
     * Maps a rect of paint coordinates onto the a rect of destination
     * coordinates. Each rect can optionally be transformed. The srcRect
     * is stretched over the dstRect. The dstRect is transformed by the
     * context's matrix and the srcRect is transformed by the paint's matrix.
     * Additional optional matrices can be provided by parameters.
     *
     * @param paint     describes how to color pixels.
     * @param dstRect   the destination rect to draw.
     * @param srcRect   rect of paint coordinates to be mapped onto dstRect
     * @param dstMatrix Optional matrix to transform dstRect. Applied before
     *                  context's matrix.
     * @param srcMatrix Optional matrix to transform srcRect Applied before
     *                  paint's matrix.
     */
    void drawRectToRect(const GrPaint& paint,
                        const GrRect& dstRect,
                        const GrRect& srcRect,
                        const GrMatrix* dstMatrix = NULL,
                        const GrMatrix* srcMatrix = NULL);

    /**
     * Draws a path.
     *
     * @param paint         describes how to color pixels.
     * @param path          the path to draw
     * @param fill          the path filling rule to use.
     * @param translate     optional additional translation applied to the
     *                      path.
     */
    void drawPath(const GrPaint& paint, const GrPath& path, GrPathFill fill,
                  const GrPoint* translate = NULL);

    /**
     * Draws vertices with a paint.
     *
     * @param   paint           describes how to color pixels.
     * @param   primitiveType   primitives type to draw.
     * @param   vertexCount     number of vertices.
     * @param   positions       array of vertex positions, required.
     * @param   texCoords       optional array of texture coordinates used
     *                          to access the paint.
     * @param   colors          optional array of per-vertex colors, supercedes
     *                          the paint's color field.
     * @param   indices         optional array of indices. If NULL vertices
     *                          are drawn non-indexed.
     * @param   indexCount      if indices is non-null then this is the
     *                          number of indices.
     */
    void drawVertices(const GrPaint& paint,
                      GrPrimitiveType primitiveType,
                      int vertexCount,
                      const GrPoint positions[],
                      const GrPoint texs[],
                      const GrColor colors[],
                      const uint16_t indices[],
                      int indexCount);

    /**
     * Similar to drawVertices but caller provides objects that convert to Gr
     * types. The count of vertices is given by posSrc.
     *
     * @param   paint           describes how to color pixels.
     * @param   primitiveType   primitives type to draw.
     * @param   posSrc          Source of vertex positions. Must implement
     *                              int count() const;
     *                              void writeValue(int i, GrPoint* point) const;
     *                          count returns the total number of vertices and
     *                          writeValue writes a vertex position to point.
     * @param   texSrc          optional, pass NULL to not use explicit tex
     *                          coords. If present provides tex coords with
     *                          method:
     *                              void writeValue(int i, GrPoint* point) const;
     * @param   texSrc          optional, pass NULL to not use per-vertex colors
     *                          If present provides colors with method:
     *                              void writeValue(int i, GrColor* point) const;
     * @param   indices         optional, pass NULL for non-indexed drawing. If
     *                          present supplies indices for indexed drawing
     *                          with following methods:
     *                              int count() const;
     *                              void writeValue(int i, uint16_t* point) const;
     *                          count returns the number of indices and
     *                          writeValue supplies each index.
     */
    template <typename POS_SRC,
              typename TEX_SRC,
              typename COL_SRC,
              typename IDX_SRC>
    void drawCustomVertices(const GrPaint& paint,
                            GrPrimitiveType primitiveType,
                            const POS_SRC& posSrc,
                            const TEX_SRC* texCoordSrc,
                            const COL_SRC* colorSrc,
                            const IDX_SRC* idxSrc);
    /**
     * To avoid the problem of having to create a typename for NULL parameters,
     * these reduced versions of drawCustomVertices are provided.
     */
    template <typename POS_SRC>
    void drawCustomVertices(const GrPaint& paint,
                            GrPrimitiveType primitiveType,
                            const POS_SRC& posSrc);
    template <typename POS_SRC, typename TEX_SRC>
    void drawCustomVertices(const GrPaint& paint,
                            GrPrimitiveType primitiveType,
                            const POS_SRC& posSrc,
                            const TEX_SRC* texCoordSrc);
    template <typename POS_SRC, typename TEX_SRC, typename COL_SRC>
    void drawCustomVertices(const GrPaint& paint,
                            GrPrimitiveType primitiveType,
                            const POS_SRC& posSrc,
                            const TEX_SRC* texCoordSrc,
                            const COL_SRC* colorSrc);

    ///////////////////////////////////////////////////////////////////////////
    // Misc.

    /**
     * Flags that affect flush() behavior.
     */
    enum FlushBits {
        /**
         * A client may want Gr to bind a GrRenderTarget in the 3D API so that
         * it can be rendered to directly. However, Gr lazily sets state. Simply
         * calling setRenderTarget() followed by flush() without flags may not
         * bind the render target. This flag forces the context to bind the last
         * set render target in the 3D API.
         */
        kForceCurrentRenderTarget_FlushBit   = 0x1,
        /**
         * A client may reach a point where it has partially rendered a frame
         * through a GrContext that it knows the user will never see. This flag
         * causes the flush to skip submission of deferred content to the 3D API
         * during the flush.
         */
        kDiscard_FlushBit                    = 0x2,
    };

    /**
     * Call to ensure all drawing to the context has been issued to the
     * underlying 3D API.
     * @param flagsBitfield     flags that control the flushing behavior. See
     *                          FlushBits.
     */
    void flush(int flagsBitfield = 0);

    /**
     * Reads a rectangle of pixels from a render target.
     * @param renderTarget  the render target to read from. NULL means the
     *                      current 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 or because no render
     *              target is currently set.
     */
    bool readRenderTargetPixels(GrRenderTarget* target,
                                int left, int top, int width, int height,
                                GrPixelConfig config, void* buffer);

    /**
     * Reads a rectangle of pixels from a texture.
     * @param texture       the render target to read from.
     * @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 readTexturePixels(GrTexture* target,
                           int left, int top, int width, int height,
                           GrPixelConfig config, void* buffer);

    /**
     *  Copy the src pixels [buffer, stride, pixelconfig] into the current
     *  render-target at the specified rectangle.
     */
    void writePixels(int left, int top, int width, int height,
                     GrPixelConfig, const void* buffer, size_t stride);

    ///////////////////////////////////////////////////////////////////////////
    // Helpers

    class AutoRenderTarget : ::GrNoncopyable {
    public:
        AutoRenderTarget(GrContext* context, GrRenderTarget* target) {
            fContext = NULL;
            fPrevTarget = context->getRenderTarget();
            if (fPrevTarget != target) {
                context->setRenderTarget(target);
                fContext = context;
            }
        }
        ~AutoRenderTarget() {
            if (fContext) {
                fContext->setRenderTarget(fPrevTarget);
            }
        }
    private:
        GrContext*      fContext;
        GrRenderTarget* fPrevTarget;
    };

    ///////////////////////////////////////////////////////////////////////////
    // Functions intended for internal use only.
    GrGpu* getGpu() { return fGpu; }
    GrFontCache* getFontCache() { return fFontCache; }
    GrDrawTarget* getTextTarget(const GrPaint& paint);
    void flushText();
    const GrIndexBuffer* getQuadIndexBuffer() const;
    void resetStats();
    const GrGpuStats& getStats() const;
    void printStats() const;

private:
    // used to keep track of when we need to flush the draw buffer
    enum DrawCategory {
        kBuffered_DrawCategory,      // last draw was inserted in draw buffer
        kUnbuffered_DrawCategory,    // last draw was not inserted in the draw buffer
        kText_DrawCategory           // text context was last to draw
    };
    DrawCategory fLastDrawCategory;

    GrGpu*          fGpu;
    GrTextureCache* fTextureCache;
    GrFontCache*    fFontCache;

    GrPathRenderer*         fCustomPathRenderer;
    GrDefaultPathRenderer   fDefaultPathRenderer;

    GrVertexBufferAllocPool*    fDrawBufferVBAllocPool;
    GrIndexBufferAllocPool*     fDrawBufferIBAllocPool;
    GrInOrderDrawBuffer*        fDrawBuffer;

    GrIndexBuffer*              fAAFillRectIndexBuffer;
    GrIndexBuffer*              fAAStrokeRectIndexBuffer;
    int                         fMaxOffscreenAASize;

    GrContext(GrGpu* gpu);

    void fillAARect(GrDrawTarget* target,
                    const GrPaint& paint,
                    const GrRect& devRect);

    void strokeAARect(GrDrawTarget* target,
                      const GrPaint& paint,
                      const GrRect& devRect,
                      const GrVec& devStrokeSize);

    inline int aaFillRectIndexCount() const;
    GrIndexBuffer* aaFillRectIndexBuffer();

    inline int aaStrokeRectIndexCount() const;
    GrIndexBuffer* aaStrokeRectIndexBuffer();

    void setupDrawBuffer();

    void flushDrawBuffer();

    static void SetPaint(const GrPaint& paint, GrDrawTarget* target);

    bool finalizeTextureKey(GrTextureKey*,
                            const GrSamplerState&,
                            bool keyless) const;

    GrDrawTarget* prepareToDraw(const GrPaint& paint, DrawCategory drawType);

    void drawClipIntoStencil();

    GrPathRenderer* getPathRenderer(const GrDrawTarget*, const GrPath&, GrPathFill);

    struct OffscreenRecord;

    // determines whether offscreen AA should be applied
    bool doOffscreenAA(GrDrawTarget* target,
                       const GrPaint& paint,
                       bool isLines) const;

    // attempts to setup offscreen AA. All paint state must be transferred to
    // target by the time this is called.
    bool prepareForOffscreenAA(GrDrawTarget* target,
                               bool requireStencil,
                               const GrIRect& boundRect,
                               GrPathRenderer* pr,
                               OffscreenRecord* record);

    // sets up target to draw coverage to the supersampled render target
    void setupOffscreenAAPass1(GrDrawTarget* target,
                               const GrIRect& boundRect,
                               int tileX, int tileY,
                               OffscreenRecord* record);

    // sets up target to sample coverage of supersampled render target back
    // to the main render target using stage kOffscreenStage.
    void doOffscreenAAPass2(GrDrawTarget* target,
                            const GrPaint& paint,
                            const GrIRect& boundRect,
                            int tileX, int tileY,
                            OffscreenRecord* record);

    // restored the draw target state and releases offscreen target to cache
    void cleanupOffscreenAA(GrDrawTarget* target,
                            GrPathRenderer* pr,
                            OffscreenRecord* record);

    // computes vertex layout bits based on the paint. If paint expresses
    // a texture for a stage, the stage coords will be bound to postitions
    // unless hasTexCoords[s]==true in which case stage s's input coords
    // are bound to tex coord index s. hasTexCoords == NULL is a shortcut
    // for an array where all the values are false.
    static int PaintStageVertexLayoutBits(
                                    const GrPaint& paint,
                                    const bool hasTexCoords[GrPaint::kTotalStages]);

};

/**
 *  Save/restore the view-matrix in the context.
 */
class GrAutoMatrix : GrNoncopyable {
public:
    GrAutoMatrix(GrContext* ctx) : fContext(ctx) {
        fMatrix = ctx->getMatrix();
    }
    GrAutoMatrix(GrContext* ctx, const GrMatrix& matrix) : fContext(ctx) {
        fMatrix = ctx->getMatrix();
        ctx->setMatrix(matrix);
    }
    ~GrAutoMatrix() {
        fContext->setMatrix(fMatrix);
    }

private:
    GrContext*  fContext;
    GrMatrix    fMatrix;
};

#endif

#include "GrContext_impl.h"


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 GrContext_impl_DEFINED
#define GrContext_impl_DEFINED

template <typename POS_SRC, typename TEX_SRC,
          typename COL_SRC, typename IDX_SRC>
inline void GrContext::drawCustomVertices(const GrPaint& paint,
                                          GrPrimitiveType primitiveType,
                                          const POS_SRC& posSrc,
                                          const TEX_SRC* texCoordSrc,
                                          const COL_SRC* colorSrc,
                                          const IDX_SRC* idxSrc) {

    GrDrawTarget::AutoReleaseGeometry geo;

    GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);

    bool hasTexCoords[GrPaint::kTotalStages] = {
        NULL != texCoordSrc, // texCoordSrc provides explicit stage 0 coords
        0                    // remaining stages use positions
    };
    GrVertexLayout layout = PaintStageVertexLayoutBits(paint, hasTexCoords);

    if (NULL != colorSrc) {
        layout |= GrDrawTarget::kColor_VertexLayoutBit;
    }

    int vertexCount = posSrc.count();
    int indexCount = (NULL != idxSrc) ? idxSrc->count() : 0;

    if (!geo.set(target, layout, vertexCount, indexCount)) {
        GrPrintf("Failed to get space for vertices!");
        return;
    }

    int texOffsets[GrDrawTarget::kMaxTexCoords];
    int colorOffset;
    int vsize = GrDrawTarget::VertexSizeAndOffsetsByIdx(layout,
                                                        texOffsets,
                                                        &colorOffset);
    void* curVertex = geo.vertices();

    for (int i = 0; i < vertexCount; ++i) {
        posSrc.writeValue(i, (GrPoint*)curVertex);

        if (texOffsets[0] > 0) {
            texCoordSrc->writeValue(i, (GrPoint*)((intptr_t)curVertex + texOffsets[0]));
        }
        if (colorOffset > 0) {
            colorSrc->writeValue(i, (GrColor*)((intptr_t)curVertex + colorOffset));
        }
        curVertex = (void*)((intptr_t)curVertex + vsize);
    }

    uint16_t* indices = (uint16_t*) geo.indices();
    for (int i = 0; i < indexCount; ++i) {
        idxSrc->writeValue(i, indices + i);
    }

    // we don't currently apply offscreen AA to this path. Need improved
    // management of GrDrawTarget's geometry to avoid copying points per-tile.

    if (NULL == idxSrc) {
        target->drawNonIndexed(primitiveType, 0, vertexCount);
    } else {
        target->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount);
    }
}

class GrNullTexCoordSource {
public:
    void writeValue(int i, GrPoint* dstCoord) const { GrAssert(false); }
};

class GrNullColorSource {
public:
    void writeValue(int i, GrColor* dstColor) const { GrAssert(false); }
};

class GrNullIndexSource {
public:
    void writeValue(int i, uint16_t* dstIndex) const { GrAssert(false); }
    int count() const { GrAssert(false); return 0; }
};

template <typename POS_SRC>
inline void GrContext::drawCustomVertices(const GrPaint& paint,
                                          GrPrimitiveType primitiveType,
                                          const POS_SRC& posSrc) {
    this->drawCustomVertices<POS_SRC,
                             GrNullTexCoordSource,
                             GrNullColorSource,
                             GrNullIndexSource>(paint, primitiveType, posSrc,
                                                NULL, NULL, NULL);
}

template <typename POS_SRC, typename TEX_SRC>
inline void GrContext::drawCustomVertices(const GrPaint& paint,
                                          GrPrimitiveType primitiveType,
                                          const POS_SRC& posSrc,
                                          const TEX_SRC* texCoordSrc) {
    this->drawCustomVertices<POS_SRC, TEX_SRC,
                             GrNullColorSource,
                             GrNullIndexSource>(paint, primitiveType, posSrc,
                                                texCoordSrc, NULL, NULL);
}

template <typename POS_SRC, typename TEX_SRC, typename COL_SRC>
inline void GrContext::drawCustomVertices(const GrPaint& paint,
                                          GrPrimitiveType primitiveType,
                                          const POS_SRC& posSrc,
                                          const TEX_SRC* texCoordSrc,
                                          const COL_SRC* colorSrc) {
    drawCustomVertices<POS_SRC, TEX_SRC, COL_SRC,
                       GrNullIndexSource>(paint, primitiveType, posSrc,
                                          texCoordSrc, colorSrc, NULL);
}

#endif