Fix line endings in Gr files and set svn eol style to LF
authorbsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Tue, 22 Feb 2011 20:59:41 +0000 (20:59 +0000)
committerbsalomon@google.com <bsalomon@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>
Tue, 22 Feb 2011 20:59:41 +0000 (20:59 +0000)
git-svn-id: http://skia.googlecode.com/svn/trunk@832 2bbb7eff-a529-9590-31e7-b0007b416f81

gpu/include/GrContext.h
gpu/include/GrContext_impl.h
gpu/include/GrDrawTarget.h
gpu/include/GrGeometryBuffer.h
gpu/include/GrPaint.h
gpu/src/GrContext.cpp
gpu/src/GrGLUtil.cpp
gpu/src/GrMatrix.cpp

index 9df7105..caba6ef 100644 (file)
-/*\r
-    Copyright 2010 Google Inc.\r
-\r
-    Licensed under the Apache License, Version 2.0 (the "License");\r
-    you may not use this file except in compliance with the License.\r
-    You may obtain a copy of the License at\r
-\r
-         http://www.apache.org/licenses/LICENSE-2.0\r
-\r
-    Unless required by applicable law or agreed to in writing, software\r
-    distributed under the License is distributed on an "AS IS" BASIS,\r
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-    See the License for the specific language governing permissions and\r
-    limitations under the License.\r
- */\r
-\r
-#ifndef GrContext_DEFINED\r
-#define GrContext_DEFINED\r
-\r
-#include "GrClip.h"\r
-#include "GrGpu.h"\r
-#include "GrTextureCache.h"\r
-#include "GrPaint.h"\r
-\r
-class GrFontCache;\r
-class GrPathIter;\r
-class GrVertexBufferAllocPool;\r
-class GrIndexBufferAllocPool;\r
-class GrInOrderDrawBuffer;\r
-class GrPathRenderer;\r
-\r
-class GrContext : public GrRefCnt {\r
-public:\r
-    /**\r
-     * Creates a GrContext from within a 3D context.\r
-     */\r
-    static GrContext* Create(GrGpu::Engine engine,\r
-                             GrGpu::Platform3DContext context3D);\r
-\r
-    /**\r
-     *  Helper to create a opengl-shader based context\r
-     */\r
-    static GrContext* CreateGLShaderContext();\r
-\r
-    virtual ~GrContext();\r
-\r
-    /**\r
-     * The GrContext normally assumes that no outsider is setting state\r
-     * within the underlying 3D API's context/device/whatever. This call informs\r
-     * the context that the state was modified and it should resend. Shouldn't\r
-     * be called frequently for good performance.\r
-     */\r
-    void resetContext();\r
-\r
-    ///////////////////////////////////////////////////////////////////////////\r
-    // Textures\r
-\r
-    /**\r
-     *  Abandons all textures. Call this if you have lost the associated GPU\r
-     *  context, and thus internal texture references/IDs are now invalid.\r
-     */\r
-    void abandonAllTextures();\r
-\r
-    /**\r
-     *  Search for an entry with the same Key. If found, "lock" it and return it.\r
-     *  If not found, return null.\r
-     */\r
-    GrTextureEntry* findAndLockTexture(GrTextureKey*,\r
-                                       const GrSamplerState&);\r
-\r
-\r
-    /**\r
-     *  Create a new entry, based on the specified key and texture, and return\r
-     *  its "locked" entry.\r
-     *\r
-     *  Ownership of the texture is transferred to the Entry, which will unref()\r
-     *  it when we are purged or deleted.\r
-     */\r
-    GrTextureEntry* createAndLockTexture(GrTextureKey* key,\r
-                                         const GrSamplerState&,\r
-                                         const GrGpu::TextureDesc&,\r
-                                         void* srcData, size_t rowBytes);\r
-\r
-    /**\r
-     *  When done with an entry, call unlockTexture(entry) on it, which returns\r
-     *  it to the cache, where it may be purged.\r
-     */\r
-    void unlockTexture(GrTextureEntry* entry);\r
-\r
-    /**\r
-     *  Removes an texture from the cache. This prevents the texture from\r
-     *  being found by a subsequent findAndLockTexture() until it is\r
-     *  reattached. The entry still counts against the cache's budget and should\r
-     *  be reattached when exclusive access is no longer needed.\r
-     */\r
-    void detachCachedTexture(GrTextureEntry*);\r
-\r
-    /**\r
-     * Reattaches a texture to the cache and unlocks it. Allows it to be found\r
-     * by a subsequent findAndLock or be purged (provided its lock count is\r
-     * now 0.)\r
-     */\r
-    void reattachAndUnlockCachedTexture(GrTextureEntry*);\r
-\r
-    /**\r
-     * Creates a texture that is outside the cache. Does not count against\r
-     * cache's budget.\r
-     */\r
-    GrTexture* createUncachedTexture(const GrGpu::TextureDesc&,\r
-                                     void* srcData,\r
-                                     size_t rowBytes);\r
-\r
-    /**\r
-     *  Returns true if the specified use of an indexed texture is supported.\r
-     */\r
-    bool supportsIndex8PixelConfig(const GrSamplerState&, int width, int height);\r
-\r
-    /**\r
-     *  Return the current texture cache limits.\r
-     *\r
-     *  @param maxTextures If non-null, returns maximum number of textures that\r
-     *                     can be held in the cache.\r
-     *  @param maxTextureBytes If non-null, returns maximum number of bytes of\r
-     *                         texture memory that can be held in the cache.\r
-     */\r
-    void getTextureCacheLimits(int* maxTextures, size_t* maxTextureBytes) const;\r
-\r
-    /**\r
-     *  Specify the texture cache limits. If the current cache exceeds either\r
-     *  of these, it will be purged (LRU) to keep the cache within these limits.\r
-     *\r
-     *  @param maxTextures The maximum number of textures that can be held in\r
-     *                     the cache.\r
-     *  @param maxTextureBytes The maximum number of bytes of texture memory\r
-     *                         that can be held in the cache.\r
-     */\r
-    void setTextureCacheLimits(int maxTextures, size_t maxTextureBytes);\r
-\r
-    /**\r
-     *  Return the max width or height of a texture supported by the current gpu\r
-     */\r
-    int getMaxTextureDimension();\r
-\r
-    ///////////////////////////////////////////////////////////////////////////\r
-    // Render targets\r
-\r
-    /**\r
-     * Wraps an externally-created rendertarget in a GrRenderTarget.\r
-     * @param platformRenderTarget  3D API-specific render target identifier\r
-     *                              e.g. in GL platforamRenderTarget is an FBO \r
-     *                              id.\r
-     * @param stencilBits           the number of stencil bits that the render\r
-     *                              target has.\r
-     * @param width                 width of the render target.\r
-     * @param height                height of the render target.\r
-     */\r
-    GrRenderTarget* createPlatformRenderTarget(intptr_t platformRenderTarget,\r
-                                               int stencilBits,\r
-                                               int width, int height);\r
-\r
-    /**\r
-     * Reads the current target object (e.g. FBO or IDirect3DSurface9*) and\r
-     * viewport state from the underlying 3D API and wraps it in a\r
-     * GrRenderTarget. The GrRenderTarget will not attempt to delete/destroy the\r
-     * underlying object in its destructor and it is up to caller to guarantee\r
-     * that it remains valid while the GrRenderTarget is used.\r
-     *\r
-     * @return the newly created GrRenderTarget\r
-     */\r
-    GrRenderTarget* createRenderTargetFrom3DApiState() {\r
-        return fGpu->createRenderTargetFrom3DApiState();\r
-    }\r
-\r
-    /**\r
-     * Sets the render target.\r
-     * @param target    the render target to set. (should not be NULL.)\r
-     */\r
-    void setRenderTarget(GrRenderTarget* target);\r
-\r
-    /**\r
-     * Gets the current render target.\r
-     * @return the currently bound render target. Should never be NULL.\r
-     */\r
-    const GrRenderTarget* getRenderTarget() const;\r
-    GrRenderTarget* getRenderTarget();\r
-\r
-    ///////////////////////////////////////////////////////////////////////////\r
-    // Matrix state\r
-\r
-    /**\r
-     * Gets the current transformation matrix.\r
-     * @return the current matrix.\r
-     */\r
-    const GrMatrix& getMatrix() const;\r
-\r
-    /**\r
-     * Sets the transformation matrix.\r
-     * @param m the matrix to set.\r
-     */\r
-    void setMatrix(const GrMatrix& m);\r
-\r
-    /**\r
-     * Concats the current matrix. The passed matrix is applied before the\r
-     * current matrix.\r
-     * @param m the matrix to concat.\r
-     */\r
-    void concatMatrix(const GrMatrix& m) const;\r
-\r
-\r
-    ///////////////////////////////////////////////////////////////////////////\r
-    // Clip state\r
-    /**\r
-     * Gets the current clip.\r
-     * @return the current clip.\r
-     */\r
-    const GrClip& getClip() const { return fGpu->getClip(); }\r
-\r
-    /**\r
-     * Sets the clip.\r
-     * @param clip  the clip to set.\r
-     */\r
-    void setClip(const GrClip& clip);\r
-\r
-    /**\r
-     * Convenience method for setting the clip to a rect.\r
-     * @param rect  the rect to set as the new clip.\r
-     */\r
-    void setClip(const GrIRect& rect);\r
-\r
-    ///////////////////////////////////////////////////////////////////////////\r
-    // Draws\r
-\r
-    /**\r
-     *  Erase the entire render target, ignoring any clips\r
-     */\r
-    void eraseColor(GrColor color);\r
-\r
-    /**\r
-     *  Draw everywhere (respecting the clip) with the paint.\r
-     */\r
-    void drawPaint(const GrPaint& paint);\r
-\r
-    /**\r
-     *  Draw the rect using a paint.\r
-     *  @param paint        describes how to color pixels.\r
-     *  @param strokeWidth  If strokeWidth < 0, then the rect is filled, else\r
-     *                      the rect is mitered stroked based on strokeWidth. If\r
-     *                      strokeWidth == 0, then the stroke is always a single\r
-     *                      pixel thick.\r
-     *  @param matrix       Optional matrix applied to the rect. Applied before\r
-     *                      context's matrix or the paint's matrix.\r
-     *  The rects coords are used to access the paint (through texture matrix)\r
-     */\r
-    void drawRect(const GrPaint& paint,\r
-                  const GrRect&,\r
-                  GrScalar strokeWidth = -1,\r
-                  const GrMatrix* matrix = NULL);\r
-\r
-    /**\r
-     * Maps a rect of paint coordinates onto the a rect of destination\r
-     * coordinates. Each rect can optionally be transformed. The srcRect\r
-     * is stretched over the dstRect. The dstRect is transformed by the\r
-     * context's matrix and the srcRect is transformed by the paint's matrix.\r
-     * Additional optional matrices can be provided by parameters.\r
-     *\r
-     * @param paint     describes how to color pixels.\r
-     * @param dstRect   the destination rect to draw.\r
-     * @param srcRect   rect of paint coordinates to be mapped onto dstRect\r
-     * @param dstMatrix Optional matrix to transform dstRect. Applied before\r
-     *                  context's matrix.\r
-     * @param srcMatrix Optional matrix to transform srcRect Applied before\r
-     *                  paint's matrix.\r
-     */\r
-    void drawRectToRect(const GrPaint& paint,\r
-                        const GrRect& dstRect,\r
-                        const GrRect& srcRect,\r
-                        const GrMatrix* dstMatrix = NULL,\r
-                        const GrMatrix* srcMatrix = NULL);\r
-\r
-    /**\r
-     * Tessellates and draws a path.\r
-     *\r
-     * @param paint         describes how to color pixels.\r
-     * @param path          the path to draw\r
-     * @param fill          the path filling rule to use.\r
-     * @param translate     optional additional translation applied to the\r
-     *                      path.\r
-     */\r
-    void drawPath(const GrPaint& paint,\r
-                  GrPathIter* path,\r
-                  GrPathFill fill,\r
-                  const GrPoint* translate = NULL);\r
-    /**\r
-     * Draws vertices with a paint.\r
-     *\r
-     * @param   paint           describes how to color pixels.\r
-     * @param   primitiveType   primitives type to draw.\r
-     * @param   vertexCount     number of vertices.\r
-     * @param   positions       array of vertex positions, required.\r
-     * @param   texCoords       optional array of texture coordinates used\r
-     *                          to access the paint.\r
-     * @param   colors          optional array of per-vertex colors, supercedes\r
-     *                          the paint's color field.\r
-     * @param   indices         optional array of indices. If NULL vertices\r
-     *                          are drawn non-indexed.\r
-     * @param   indexCount      if indices is non-null then this is the\r
-     *                          number of indices.\r
-     */\r
-    void drawVertices(const GrPaint& paint,\r
-                      GrPrimitiveType primitiveType,\r
-                      int vertexCount,\r
-                      const GrPoint positions[],\r
-                      const GrPoint texs[],\r
-                      const GrColor colors[],\r
-                      const uint16_t indices[],\r
-                      int indexCount);\r
-\r
-    /**\r
-     * Similar to drawVertices but caller provides objects that convert to Gr\r
-     * types. The count of vertices is given by posSrc.\r
-     *\r
-     * @param   paint           describes how to color pixels.\r
-     * @param   primitiveType   primitives type to draw.\r
-     * @param   posSrc          Source of vertex positions. Must implement\r
-     *                              int count() const;\r
-     *                              void writeValue(int i, GrPoint* point) const;\r
-     *                          count returns the total number of vertices and\r
-     *                          writeValue writes a vertex position to point.\r
-     * @param   texSrc          optional, pass NULL to not use explicit tex\r
-     *                          coords. If present provides tex coords with\r
-     *                          method:\r
-     *                              void writeValue(int i, GrPoint* point) const;\r
-     * @param   texSrc          optional, pass NULL to not use per-vertex colors\r
-     *                          If present provides colors with method:\r
-     *                              void writeValue(int i, GrColor* point) const;\r
-     * @param   indices         optional, pass NULL for non-indexed drawing. If\r
-     *                          present supplies indices for indexed drawing\r
-     *                          with following methods:\r
-     *                              int count() const;\r
-     *                              void writeValue(int i, uint16_t* point) const;\r
-     *                          count returns the number of indices and\r
-     *                          writeValue supplies each index.\r
-     */\r
-    template <typename POS_SRC,\r
-              typename TEX_SRC,\r
-              typename COL_SRC,\r
-              typename IDX_SRC>\r
-    void drawCustomVertices(const GrPaint& paint,\r
-                            GrPrimitiveType primitiveType,\r
-                            const POS_SRC& posSrc,\r
-                            const TEX_SRC* texCoordSrc,\r
-                            const COL_SRC* colorSrc,\r
-                            const IDX_SRC* idxSrc);\r
-    /**\r
-     * To avoid the problem of having to create a typename for NULL parameters,\r
-     * these reduced versions of drawCustomVertices are provided.\r
-     */\r
-    template <typename POS_SRC>\r
-    void drawCustomVertices(const GrPaint& paint,\r
-                            GrPrimitiveType primitiveType,\r
-                            const POS_SRC& posSrc);\r
-    template <typename POS_SRC, typename TEX_SRC>\r
-    void drawCustomVertices(const GrPaint& paint,\r
-                            GrPrimitiveType primitiveType,\r
-                            const POS_SRC& posSrc,\r
-                            const TEX_SRC* texCoordSrc);\r
-    template <typename POS_SRC, typename TEX_SRC, typename COL_SRC>\r
-    void drawCustomVertices(const GrPaint& paint,\r
-                            GrPrimitiveType primitiveType,\r
-                            const POS_SRC& posSrc,\r
-                            const TEX_SRC* texCoordSrc,\r
-                            const COL_SRC* colorSrc);\r
-\r
-\r
-    ///////////////////////////////////////////////////////////////////////////\r
-    // Misc.\r
-\r
-    /**\r
-     * Call to ensure all drawing to the context has been issued to the\r
-     * underlying 3D API.\r
-     * if flushRenderTarget is true then after the call the last\r
-     * rendertarget set will be current in the underlying 3D API, otherwise\r
-     * it may not be. It is useful to set if the caller plans to use the 3D\r
-     * context outside of Ganesh to render into the current RT.\r
-     */\r
-    void flush(bool flushRenderTarget);\r
-\r
-    /**\r
-     *  Return true on success, i.e. if we could copy the specified range of\r
-     *  pixels from the current render-target into the buffer, converting into\r
-     *  the specified pixel-config.\r
-     */\r
-    bool readPixels(int left, int top, int width, int height,\r
-                    GrTexture::PixelConfig, void* buffer);\r
-\r
-    /**\r
-     *  Copy the src pixels [buffer, stride, pixelconfig] into the current\r
-     *  render-target at the specified rectangle.\r
-     */\r
-    void writePixels(int left, int top, int width, int height,\r
-                     GrTexture::PixelConfig, const void* buffer, size_t stride);\r
-\r
-\r
-    ///////////////////////////////////////////////////////////////////////////\r
-    // Statistics\r
-\r
-    void resetStats();\r
-\r
-    const GrGpu::Stats& getStats() const;\r
-\r
-    void printStats() const;\r
-\r
-    ///////////////////////////////////////////////////////////////////////////\r
-    // Helpers\r
-\r
-    class AutoRenderTarget : ::GrNoncopyable {\r
-    public:\r
-        AutoRenderTarget(GrContext* context, GrRenderTarget* target) {\r
-            fContext = NULL;\r
-            fPrevTarget = context->getRenderTarget();\r
-            if (fPrevTarget != target) {\r
-                context->setRenderTarget(target);\r
-                fContext = context;\r
-            }\r
-        }\r
-        ~AutoRenderTarget() {\r
-            if (fContext) {\r
-                fContext->setRenderTarget(fPrevTarget);\r
-            }\r
-        }\r
-    private:\r
-        GrContext*      fContext;\r
-        GrRenderTarget* fPrevTarget;\r
-    };\r
-\r
-\r
-    ///////////////////////////////////////////////////////////////////////////\r
-    // Functions intended for internal use only.\r
-    GrGpu* getGpu() { return fGpu; }\r
-    GrFontCache* getFontCache() { return fFontCache; }\r
-    GrDrawTarget* getTextTarget(const GrPaint& paint);\r
-    void flushText();\r
-    const GrIndexBuffer* getQuadIndexBuffer() const;\r
-\r
-private:\r
-    // used to keep track of when we need to flush the draw buffer\r
-    enum DrawCategory {\r
-        kBuffered_DrawCategory,      // last draw was inserted in draw buffer\r
-        kUnbuffered_DrawCategory,    // last draw was not inserted in the draw buffer\r
-        kText_DrawCategory           // text context was last to draw\r
-    };\r
-    DrawCategory fLastDrawCategory;\r
-\r
-    GrGpu*          fGpu;\r
-    GrTextureCache* fTextureCache;\r
-    GrFontCache*    fFontCache;\r
-    GrPathRenderer* fPathRenderer;\r
-\r
-    GrVertexBufferAllocPool*    fDrawBufferVBAllocPool;\r
-    GrIndexBufferAllocPool*     fDrawBufferIBAllocPool;\r
-    GrInOrderDrawBuffer*        fDrawBuffer;\r
-\r
-    GrContext(GrGpu* gpu);\r
-    void flushDrawBuffer();\r
-\r
-    static void SetPaint(const GrPaint& paint, GrDrawTarget* target);\r
-\r
-    bool finalizeTextureKey(GrTextureKey*, const GrSamplerState&) const;\r
-    \r
-    GrDrawTarget* prepareToDraw(const GrPaint& paint, DrawCategory drawType);\r
-\r
-    void drawClipIntoStencil();\r
-};\r
-\r
-/**\r
- *  Save/restore the view-matrix in the context.\r
- */\r
-class GrAutoMatrix : GrNoncopyable {\r
-public:\r
-    GrAutoMatrix(GrContext* ctx) : fContext(ctx) {\r
-        fMatrix = ctx->getMatrix();\r
-    }\r
-    GrAutoMatrix(GrContext* ctx, const GrMatrix& matrix) : fContext(ctx) {\r
-        fMatrix = ctx->getMatrix();\r
-        ctx->setMatrix(matrix);\r
-    }\r
-    ~GrAutoMatrix() {\r
-        fContext->setMatrix(fMatrix);\r
-    }\r
-\r
-private:\r
-    GrContext*  fContext;\r
-    GrMatrix    fMatrix;\r
-};\r
-\r
-#endif\r
-\r
-#include "GrContext_impl.h"\r
+/*
+    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 "GrGpu.h"
+#include "GrTextureCache.h"
+#include "GrPaint.h"
+
+class GrFontCache;
+class GrPathIter;
+class GrVertexBufferAllocPool;
+class GrIndexBufferAllocPool;
+class GrInOrderDrawBuffer;
+class GrPathRenderer;
+
+class GrContext : public GrRefCnt {
+public:
+    /**
+     * Creates a GrContext from within a 3D context.
+     */
+    static GrContext* Create(GrGpu::Engine engine,
+                             GrGpu::Platform3DContext 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();
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Textures
+
+    /**
+     *  Abandons all textures. Call this if you have lost the associated GPU
+     *  context, and thus internal texture references/IDs are now invalid.
+     */
+    void abandonAllTextures();
+
+    /**
+     *  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 GrGpu::TextureDesc&,
+                                         void* srcData, size_t rowBytes);
+
+    /**
+     *  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);
+
+    /**
+     *  Removes an texture from the cache. This prevents the texture from
+     *  being found by a subsequent findAndLockTexture() 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 detachCachedTexture(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 reattachAndUnlockCachedTexture(GrTextureEntry*);
+
+    /**
+     * Creates a texture that is outside the cache. Does not count against
+     * cache's budget.
+     */
+    GrTexture* createUncachedTexture(const GrGpu::TextureDesc&,
+                                     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 getMaxTextureDimension();
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Render targets
+
+    /**
+     * Wraps an externally-created rendertarget in a GrRenderTarget.
+     * @param platformRenderTarget  3D API-specific render target identifier
+     *                              e.g. in GL platforamRenderTarget is an FBO 
+     *                              id.
+     * @param stencilBits           the number of stencil bits that the render
+     *                              target has.
+     * @param width                 width of the render target.
+     * @param height                height of the render target.
+     */
+    GrRenderTarget* createPlatformRenderTarget(intptr_t platformRenderTarget,
+                                               int stencilBits,
+                                               int width, int height);
+
+    /**
+     * 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.
+     *
+     * @return the newly created GrRenderTarget
+     */
+    GrRenderTarget* createRenderTargetFrom3DApiState() {
+        return fGpu->createRenderTargetFrom3DApiState();
+    }
+
+    /**
+     * 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();
+
+    ///////////////////////////////////////////////////////////////////////////
+    // 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 { return fGpu->getClip(); }
+
+    /**
+     * 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
+
+    /**
+     *  Erase the entire render target, ignoring any clips
+     */
+    void eraseColor(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);
+
+    /**
+     * Tessellates and 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,
+                  GrPathIter* 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.
+
+    /**
+     * Call to ensure all drawing to the context has been issued to the
+     * underlying 3D API.
+     * if flushRenderTarget is true then after the call the last
+     * rendertarget set will be current in the underlying 3D API, otherwise
+     * it may not be. It is useful to set if the caller plans to use the 3D
+     * context outside of Ganesh to render into the current RT.
+     */
+    void flush(bool flushRenderTarget);
+
+    /**
+     *  Return true on success, i.e. if we could copy the specified range of
+     *  pixels from the current render-target into the buffer, converting into
+     *  the specified pixel-config.
+     */
+    bool readPixels(int left, int top, int width, int height,
+                    GrTexture::PixelConfig, 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,
+                     GrTexture::PixelConfig, const void* buffer, size_t stride);
+
+
+    ///////////////////////////////////////////////////////////////////////////
+    // Statistics
+
+    void resetStats();
+
+    const GrGpu::Stats& getStats() const;
+
+    void printStats() const;
+
+    ///////////////////////////////////////////////////////////////////////////
+    // 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;
+
+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* fPathRenderer;
+
+    GrVertexBufferAllocPool*    fDrawBufferVBAllocPool;
+    GrIndexBufferAllocPool*     fDrawBufferIBAllocPool;
+    GrInOrderDrawBuffer*        fDrawBuffer;
+
+    GrContext(GrGpu* gpu);
+    void flushDrawBuffer();
+
+    static void SetPaint(const GrPaint& paint, GrDrawTarget* target);
+
+    bool finalizeTextureKey(GrTextureKey*, const GrSamplerState&) const;
+    
+    GrDrawTarget* prepareToDraw(const GrPaint& paint, DrawCategory drawType);
+
+    void drawClipIntoStencil();
+};
+
+/**
+ *  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"
index c0a2107..fdcb2b1 100644 (file)
-/*\r
-    Copyright 2011 Google Inc.\r
-\r
-    Licensed under the Apache License, Version 2.0 (the "License");\r
-    you may not use this file except in compliance with the License.\r
-    You may obtain a copy of the License at\r
-\r
-         http://www.apache.org/licenses/LICENSE-2.0\r
-\r
-    Unless required by applicable law or agreed to in writing, software\r
-    distributed under the License is distributed on an "AS IS" BASIS,\r
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-    See the License for the specific language governing permissions and\r
-    limitations under the License.\r
- */\r
-\r
-#ifndef GrContext_impl_DEFINED\r
-#define GrContext_impl_DEFINED\r
-\r
-template <typename POS_SRC, typename TEX_SRC,\r
-          typename COL_SRC, typename IDX_SRC>\r
-inline void GrContext::drawCustomVertices(const GrPaint& paint,\r
-                                          GrPrimitiveType primitiveType,\r
-                                          const POS_SRC& posSrc,\r
-                                          const TEX_SRC* texCoordSrc,\r
-                                          const COL_SRC* colorSrc,\r
-                                          const IDX_SRC* idxSrc) {\r
-\r
-    GrVertexLayout layout = 0;\r
-\r
-    GrDrawTarget::AutoReleaseGeometry geo;\r
-\r
-    GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);\r
-\r
-    if (NULL != paint.getTexture()) {\r
-        if (NULL != texCoordSrc) {\r
-            layout |= GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);\r
-        } else {\r
-            layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);\r
-        }\r
-    }\r
-\r
-    if (NULL != colorSrc) {\r
-        layout |= GrDrawTarget::kColor_VertexLayoutBit;\r
-    }\r
-\r
-    int vertexCount = posSrc.count();\r
-    int indexCount = (NULL != idxSrc) ? idxSrc->count() : 0;\r
-\r
-    if (!geo.set(target, layout, vertexCount, indexCount)) {\r
-        GrPrintf("Failed to get space for vertices!");\r
-        return;\r
-    }\r
-\r
-    int texOffsets[GrDrawTarget::kMaxTexCoords];\r
-    int colorOffset;\r
-    int vsize = GrDrawTarget::VertexSizeAndOffsetsByIdx(layout,\r
-                                                        texOffsets,\r
-                                                        &colorOffset);\r
-    void* curVertex = geo.vertices();\r
-\r
-    for (int i = 0; i < vertexCount; ++i) {\r
-        posSrc.writeValue(i, (GrPoint*)curVertex);\r
-\r
-        if (texOffsets[0] > 0) {\r
-            texCoordSrc->writeValue(i, (GrPoint*)((intptr_t)curVertex + texOffsets[0]));\r
-        }\r
-        if (colorOffset > 0) {\r
-            colorSrc->writeValue(i, (GrColor*)((intptr_t)curVertex + colorOffset));\r
-        }\r
-        curVertex = (void*)((intptr_t)curVertex + vsize);\r
-    }\r
-\r
-    uint16_t* indices = (uint16_t*) geo.indices();\r
-    for (int i = 0; i < indexCount; ++i) {\r
-        idxSrc->writeValue(i, indices + i);\r
-    }\r
-\r
-    if (NULL == idxSrc) {\r
-        target->drawNonIndexed(primitiveType, 0, vertexCount);\r
-    } else {\r
-        target->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount);\r
-    }\r
-}\r
-\r
-class GrNullTexCoordSource {\r
-public:\r
-    void writeValue(int i, GrPoint* dstCoord) const { GrAssert(false); }\r
-};\r
-\r
-class GrNullColorSource {\r
-public:\r
-    void writeValue(int i, GrColor* dstColor) const { GrAssert(false); }\r
-};\r
-\r
-class GrNullIndexSource {\r
-public:\r
-    void writeValue(int i, uint16_t* dstIndex) const { GrAssert(false); }\r
-    int count() const { GrAssert(false); return 0; }\r
-};\r
-\r
-template <typename POS_SRC>\r
-inline void GrContext::drawCustomVertices(const GrPaint& paint,\r
-                                          GrPrimitiveType primitiveType,\r
-                                          const POS_SRC& posSrc) {\r
-    this->drawCustomVertices<POS_SRC,\r
-                             GrNullTexCoordSource,\r
-                             GrNullColorSource,\r
-                             GrNullIndexSource>(paint, primitiveType, posSrc,\r
-                                                NULL, NULL, NULL);\r
-}\r
-\r
-template <typename POS_SRC, typename TEX_SRC>\r
-inline void GrContext::drawCustomVertices(const GrPaint& paint,\r
-                                          GrPrimitiveType primitiveType,\r
-                                          const POS_SRC& posSrc,\r
-                                          const TEX_SRC* texCoordSrc) {\r
-    this->drawCustomVertices<POS_SRC, TEX_SRC,\r
-                             GrNullColorSource,\r
-                             GrNullIndexSource>(paint, primitiveType, posSrc,\r
-                                                texCoordSrc, NULL, NULL);\r
-}\r
-\r
-template <typename POS_SRC, typename TEX_SRC, typename COL_SRC>\r
-inline void GrContext::drawCustomVertices(const GrPaint& paint,\r
-                                          GrPrimitiveType primitiveType,\r
-                                          const POS_SRC& posSrc,\r
-                                          const TEX_SRC* texCoordSrc,\r
-                                          const COL_SRC* colorSrc) {\r
-    drawCustomVertices<POS_SRC, TEX_SRC, COL_SRC,\r
-                       GrNullIndexSource>(paint, primitiveType, posSrc, \r
-                                          texCoordSrc, colorSrc, NULL);\r
-}\r
-\r
-#endif\r
+/*
+    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) {
+
+    GrVertexLayout layout = 0;
+
+    GrDrawTarget::AutoReleaseGeometry geo;
+
+    GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
+
+    if (NULL != paint.getTexture()) {
+        if (NULL != texCoordSrc) {
+            layout |= GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);
+        } else {
+            layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
+        }
+    }
+
+    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);
+    }
+
+    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
index 929b9ff..10c6d48 100644 (file)
@@ -210,9 +210,9 @@ public:
      * @param stage   the stage of the sampler to set
      * @param matrix  the matrix to concat
      */
-    void preConcatSamplerMatrix(int stage, const GrMatrix& matrix)  {\r
-        GrAssert(stage >= 0 && stage < kNumStages);\r
-        fCurrDrawState.fSamplerStates[stage].preConcatMatrix(matrix);\r
+    void preConcatSamplerMatrix(int stage, const GrMatrix& matrix)  {
+        GrAssert(stage >= 0 && stage < kNumStages);
+        fCurrDrawState.fSamplerStates[stage].preConcatMatrix(matrix);
     }
 
     /**
index af6eed5..1447e73 100644 (file)
-/*\r
- Copyright 2011 Google Inc.\r
\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
\r
- http://www.apache.org/licenses/LICENSE-2.0\r
\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
- */\r
-\r
-#ifndef GrGeometryBuffer_DEFINED\r
-#define GrGeometryBuffer_DEFINED\r
-\r
-#include "GrRefCnt.h"\r
-\r
-/**\r
- * Parent class for vertex and index buffers\r
- */\r
-class GrGeometryBuffer : public GrRefCnt {\r
-public:\r
-    virtual ~GrGeometryBuffer() {}\r
-    \r
-    /**\r
-     * Retrieves the size of the buffer\r
-     *\r
-     * @return the size of the buffer in bytes\r
-     */\r
-    size_t size() const { return fSizeInBytes; }\r
-    \r
-    /**\r
-     *Retrieves whether the buffer was created with the dynamic flag\r
-     *\r
-     * @return true if the buffer was created with the dynamic flag\r
-     */\r
-    bool dynamic() const { return fDynamic; }\r
-    \r
-    /**\r
-     * Indicates that GPU context in which this veretx buffer was created is \r
-     * destroyed and that Ganesh should not attempt to free the buffer in the\r
-     * underlying API.\r
-     */\r
-    virtual void abandon() = 0;\r
-    \r
-    /**\r
-     * Locks the buffer to be written by the CPU.\r
-     * \r
-     * The previous content of the buffer is invalidated. It is an error\r
-     * to draw from the buffer while it is locked. It is an error to call lock\r
-     * on an already locked buffer.\r
-     * \r
-     * @return a pointer to the data or NULL if the lock fails.\r
-     */\r
-    virtual void* lock() = 0;\r
-    \r
-    /**\r
-     * Returns the same ptr that lock() returned at time of lock or NULL if the\r
-     * is not locked.\r
-     *\r
-     * @return ptr to locked buffer data or undefined if buffer is not locked.\r
-     */\r
-    virtual void* lockPtr() const = 0;\r
-    \r
-    /** \r
-     * Unlocks the buffer. \r
-     * \r
-     * The pointer returned by the previous lock call will no longer be valid.\r
-     */\r
-    virtual void unlock() = 0;\r
-    \r
-    /** \r
-     Queries whether the buffer has been locked.\r
-     \r
-     @return true if the buffer is locked, false otherwise.\r
-     */\r
-    virtual bool isLocked() const = 0;\r
-    \r
-    /**\r
-     * Updates the buffer data. \r
-     *  \r
-     * The size of the buffer will be preserved. The src data will be \r
-     * placed at the begining of the buffer and any remaining contents will\r
-     * be undefined.\r
-     * \r
-     * @return returns true if the update succeeds, false otherwise.\r
-     */\r
-    virtual bool updateData(const void* src, size_t srcSizeInBytes) = 0;\r
-    \r
-    /**\r
-     * Updates a portion of the buffer data. \r
-     * \r
-     * The contents of the buffer outside the update region are preserved.\r
-     * \r
-     * @return returns true if the update succeeds, false otherwise.\r
-     */\r
-    virtual bool updateSubData(const void* src, \r
-                               size_t srcSizeInBytes, \r
-                               size_t offset) = 0;\r
-protected:\r
-    GrGeometryBuffer(size_t sizeInBytes, bool dynamic) : \r
-        fSizeInBytes(sizeInBytes),\r
-        fDynamic(dynamic) {}\r
-\r
-private:\r
-    size_t   fSizeInBytes;\r
-    bool     fDynamic;\r
-\r
-    typedef GrRefCnt INHERITED;\r
-};\r
-\r
-#endif\r
+/*
+ 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 GrGeometryBuffer_DEFINED
+#define GrGeometryBuffer_DEFINED
+
+#include "GrRefCnt.h"
+
+/**
+ * Parent class for vertex and index buffers
+ */
+class GrGeometryBuffer : public GrRefCnt {
+public:
+    virtual ~GrGeometryBuffer() {}
+    
+    /**
+     * Retrieves the size of the buffer
+     *
+     * @return the size of the buffer in bytes
+     */
+    size_t size() const { return fSizeInBytes; }
+    
+    /**
+     *Retrieves whether the buffer was created with the dynamic flag
+     *
+     * @return true if the buffer was created with the dynamic flag
+     */
+    bool dynamic() const { return fDynamic; }
+    
+    /**
+     * Indicates that GPU context in which this veretx buffer was created is 
+     * destroyed and that Ganesh should not attempt to free the buffer in the
+     * underlying API.
+     */
+    virtual void abandon() = 0;
+    
+    /**
+     * Locks the buffer to be written by the CPU.
+     * 
+     * The previous content of the buffer is invalidated. It is an error
+     * to draw from the buffer while it is locked. It is an error to call lock
+     * on an already locked buffer.
+     * 
+     * @return a pointer to the data or NULL if the lock fails.
+     */
+    virtual void* lock() = 0;
+    
+    /**
+     * Returns the same ptr that lock() returned at time of lock or NULL if the
+     * is not locked.
+     *
+     * @return ptr to locked buffer data or undefined if buffer is not locked.
+     */
+    virtual void* lockPtr() const = 0;
+    
+    /** 
+     * Unlocks the buffer. 
+     * 
+     * The pointer returned by the previous lock call will no longer be valid.
+     */
+    virtual void unlock() = 0;
+    
+    /** 
+     Queries whether the buffer has been locked.
+     
+     @return true if the buffer is locked, false otherwise.
+     */
+    virtual bool isLocked() const = 0;
+    
+    /**
+     * Updates the buffer data. 
+     *  
+     * The size of the buffer will be preserved. The src data will be 
+     * placed at the begining of the buffer and any remaining contents will
+     * be undefined.
+     * 
+     * @return returns true if the update succeeds, false otherwise.
+     */
+    virtual bool updateData(const void* src, size_t srcSizeInBytes) = 0;
+    
+    /**
+     * Updates a portion of the buffer data. 
+     * 
+     * The contents of the buffer outside the update region are preserved.
+     * 
+     * @return returns true if the update succeeds, false otherwise.
+     */
+    virtual bool updateSubData(const void* src, 
+                               size_t srcSizeInBytes, 
+                               size_t offset) = 0;
+protected:
+    GrGeometryBuffer(size_t sizeInBytes, bool dynamic) : 
+        fSizeInBytes(sizeInBytes),
+        fDynamic(dynamic) {}
+
+private:
+    size_t   fSizeInBytes;
+    bool     fDynamic;
+
+    typedef GrRefCnt INHERITED;
+};
+
+#endif
index a34cbaf..9402209 100644 (file)
-/*\r
-    Copyright 2011 Google Inc.\r
-\r
-    Licensed under the Apache License, Version 2.0 (the "License");\r
-    you may not use this file except in compliance with the License.\r
-    You may obtain a copy of the License at\r
-\r
-         http://www.apache.org/licenses/LICENSE-2.0\r
-\r
-    Unless required by applicable law or agreed to in writing, software\r
-    distributed under the License is distributed on an "AS IS" BASIS,\r
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-    See the License for the specific language governing permissions and\r
-    limitations under the License.\r
- */\r
-\r
-#ifndef GrPaint_DEFINED\r
-#define GrPaint_DEFINED\r
-\r
-#include "GrTexture.h"\r
-#include "GrColor.h"\r
-#include "GrSamplerState.h"\r
-\r
-/**\r
- * The paint describes how pixels are colored when the context draws to\r
- * them.\r
- */\r
-class GrPaint {\r
-public:\r
-\r
-    // All the paint fields are public except texture (it's ref-counted)\r
-    GrBlendCoeff                fSrcBlendCoeff;\r
-    GrBlendCoeff                fDstBlendCoeff;\r
-    bool                        fAntiAlias;\r
-    bool                        fDither;\r
-\r
-    GrColor                     fColor;\r
-\r
-    GrSamplerState              fSampler;\r
-\r
-    void setTexture(GrTexture* texture) {\r
-        GrSafeRef(texture);\r
-        GrSafeUnref(fTexture);\r
-        fTexture = texture;\r
-    }\r
-\r
-    GrTexture* getTexture() const { return fTexture; }\r
-\r
-    // uninitialized\r
-    GrPaint() {\r
-        fTexture = NULL;\r
-    }\r
-\r
-    GrPaint(const GrPaint& paint) {\r
-        fSrcBlendCoeff = paint.fSrcBlendCoeff;\r
-        fDstBlendCoeff = paint.fDstBlendCoeff;\r
-        fAntiAlias = paint.fAntiAlias;\r
-        fDither = paint.fDither;\r
-\r
-        fColor = paint.fColor;\r
-\r
-        fSampler = paint.fSampler;\r
-        fTexture = paint.fTexture;\r
-        GrSafeRef(fTexture);\r
-    }\r
-\r
-    ~GrPaint() {\r
-        GrSafeUnref(fTexture);\r
-    }\r
-\r
-    // sets paint to src-over, solid white, no texture\r
-    void reset() {\r
-        resetBlend();\r
-        resetOptions();\r
-        resetColor();\r
-        resetTexture();\r
-    }\r
-\r
-private:\r
-    GrTexture*      fTexture;\r
-\r
-    void resetBlend() {\r
-        fSrcBlendCoeff = kOne_BlendCoeff;\r
-        fDstBlendCoeff = kZero_BlendCoeff;\r
-    }\r
-\r
-    void resetOptions() {\r
-        fAntiAlias = false;\r
-        fDither = false;\r
-    }\r
-\r
-    void resetColor() {\r
-        fColor = GrColorPackRGBA(0xff, 0xff, 0xff, 0xff);\r
-    }\r
-\r
-    void resetTexture() {\r
-        setTexture(NULL);\r
-        fSampler.setClampNoFilter();\r
-    }\r
-\r
-};\r
-\r
-#endif\r
+/*
+    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 GrPaint_DEFINED
+#define GrPaint_DEFINED
+
+#include "GrTexture.h"
+#include "GrColor.h"
+#include "GrSamplerState.h"
+
+/**
+ * The paint describes how pixels are colored when the context draws to
+ * them.
+ */
+class GrPaint {
+public:
+
+    // All the paint fields are public except texture (it's ref-counted)
+    GrBlendCoeff                fSrcBlendCoeff;
+    GrBlendCoeff                fDstBlendCoeff;
+    bool                        fAntiAlias;
+    bool                        fDither;
+
+    GrColor                     fColor;
+
+    GrSamplerState              fSampler;
+
+    void setTexture(GrTexture* texture) {
+        GrSafeRef(texture);
+        GrSafeUnref(fTexture);
+        fTexture = texture;
+    }
+
+    GrTexture* getTexture() const { return fTexture; }
+
+    // uninitialized
+    GrPaint() {
+        fTexture = NULL;
+    }
+
+    GrPaint(const GrPaint& paint) {
+        fSrcBlendCoeff = paint.fSrcBlendCoeff;
+        fDstBlendCoeff = paint.fDstBlendCoeff;
+        fAntiAlias = paint.fAntiAlias;
+        fDither = paint.fDither;
+
+        fColor = paint.fColor;
+
+        fSampler = paint.fSampler;
+        fTexture = paint.fTexture;
+        GrSafeRef(fTexture);
+    }
+
+    ~GrPaint() {
+        GrSafeUnref(fTexture);
+    }
+
+    // sets paint to src-over, solid white, no texture
+    void reset() {
+        resetBlend();
+        resetOptions();
+        resetColor();
+        resetTexture();
+    }
+
+private:
+    GrTexture*      fTexture;
+
+    void resetBlend() {
+        fSrcBlendCoeff = kOne_BlendCoeff;
+        fDstBlendCoeff = kZero_BlendCoeff;
+    }
+
+    void resetOptions() {
+        fAntiAlias = false;
+        fDither = false;
+    }
+
+    void resetColor() {
+        fColor = GrColorPackRGBA(0xff, 0xff, 0xff, 0xff);
+    }
+
+    void resetTexture() {
+        setTexture(NULL);
+        fSampler.setClampNoFilter();
+    }
+
+};
+
+#endif
index dbc7f6c..d14f374 100644 (file)
-/*\r
-    Copyright 2010 Google Inc.\r
-\r
-    Licensed under the Apache License, Version 2.0 (the "License");\r
-    you may not use this file except in compliance with the License.\r
-    You may obtain a copy of the License at\r
-\r
-         http://www.apache.org/licenses/LICENSE-2.0\r
-\r
-    Unless required by applicable law or agreed to in writing, software\r
-    distributed under the License is distributed on an "AS IS" BASIS,\r
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-    See the License for the specific language governing permissions and\r
-    limitations under the License.\r
- */\r
-\r
-#include "GrContext.h"\r
-#include "GrTypes.h"\r
-#include "GrTextureCache.h"\r
-#include "GrTextStrike.h"\r
-#include "GrMemory.h"\r
-#include "GrPathIter.h"\r
-#include "GrClipIterator.h"\r
-#include "GrIndexBuffer.h"\r
-#include "GrInOrderDrawBuffer.h"\r
-#include "GrBufferAllocPool.h"\r
-#include "GrPathRenderer.h"\r
-\r
-#define DEFER_TEXT_RENDERING 1\r
-\r
-#define BATCH_RECT_TO_RECT (1 && !GR_STATIC_RECT_VB)\r
-\r
-static const size_t MAX_TEXTURE_CACHE_COUNT = 128;\r
-static const size_t MAX_TEXTURE_CACHE_BYTES = 8 * 1024 * 1024;\r
-\r
-static const size_t DRAW_BUFFER_VBPOOL_BUFFER_SIZE = 1 << 18;\r
-static const int DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS = 4;\r
-\r
-// We are currently only batching Text and drawRectToRect, both\r
-// of which use the quad index buffer.\r
-static const size_t DRAW_BUFFER_IBPOOL_BUFFER_SIZE = 0;\r
-static const int DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS = 0;\r
-\r
-GrContext* GrContext::Create(GrGpu::Engine engine,\r
-                             GrGpu::Platform3DContext context3D) {\r
-    GrContext* ctx = NULL;\r
-    GrGpu* fGpu = GrGpu::Create(engine, context3D);\r
-    if (NULL != fGpu) {\r
-        ctx = new GrContext(fGpu);\r
-        fGpu->unref();\r
-    }\r
-    return ctx;\r
-}\r
-\r
-GrContext* GrContext::CreateGLShaderContext() {\r
-    return GrContext::Create(GrGpu::kOpenGL_Shaders_Engine, NULL);\r
-}\r
-\r
-GrContext::~GrContext() {\r
-    fGpu->unref();\r
-    delete fTextureCache;\r
-    delete fFontCache;\r
-    delete fDrawBuffer;\r
-    delete fDrawBufferVBAllocPool;\r
-    delete fDrawBufferVBAllocPool;\r
-    delete fPathRenderer;\r
-}\r
-\r
-void GrContext::abandonAllTextures() {\r
-    fTextureCache->deleteAll(GrTextureCache::kAbandonTexture_DeleteMode);\r
-    fFontCache->abandonAll();\r
-}\r
-\r
-GrTextureEntry* GrContext::findAndLockTexture(GrTextureKey* key,\r
-                                              const GrSamplerState& sampler) {\r
-    finalizeTextureKey(key, sampler);\r
-    return fTextureCache->findAndLock(*key);\r
-}\r
-\r
-static void stretchImage(void* dst,\r
-                         int dstW,\r
-                         int dstH,\r
-                         void* src,\r
-                         int srcW,\r
-                         int srcH,\r
-                         int bpp) {\r
-    GrFixed dx = (srcW << 16) / dstW;\r
-    GrFixed dy = (srcH << 16) / dstH;\r
-\r
-    GrFixed y = dy >> 1;\r
-\r
-    int dstXLimit = dstW*bpp;\r
-    for (int j = 0; j < dstH; ++j) {\r
-        GrFixed x = dx >> 1;\r
-        void* srcRow = (uint8_t*)src + (y>>16)*srcW*bpp;\r
-        void* dstRow = (uint8_t*)dst + j*dstW*bpp;\r
-        for (int i = 0; i < dstXLimit; i += bpp) {\r
-            memcpy((uint8_t*) dstRow + i,\r
-                   (uint8_t*) srcRow + (x>>16)*bpp,\r
-                   bpp);\r
-            x += dx;\r
-        }\r
-        y += dy;\r
-    }\r
-}\r
-\r
-GrTextureEntry* GrContext::createAndLockTexture(GrTextureKey* key,\r
-                                                const GrSamplerState& sampler,\r
-                                                const GrGpu::TextureDesc& desc,\r
-                                                void* srcData, size_t rowBytes) {\r
-    GrAssert(key->width() == desc.fWidth);\r
-    GrAssert(key->height() == desc.fHeight);\r
-\r
-#if GR_DUMP_TEXTURE_UPLOAD\r
-    GrPrintf("GrContext::createAndLockTexture [%d %d]\n", desc.fWidth, desc.fHeight);\r
-#endif\r
-\r
-    GrTextureEntry* entry = NULL;\r
-    bool special = finalizeTextureKey(key, sampler);\r
-    if (special) {\r
-        GrTextureEntry* clampEntry;\r
-        GrTextureKey clampKey(*key);\r
-        clampEntry = findAndLockTexture(&clampKey, GrSamplerState::ClampNoFilter());\r
-\r
-        if (NULL == clampEntry) {\r
-            clampEntry = createAndLockTexture(&clampKey,\r
-                                              GrSamplerState::ClampNoFilter(),\r
-                                              desc, srcData, rowBytes);\r
-            GrAssert(NULL != clampEntry);\r
-            if (NULL == clampEntry) {\r
-                return NULL;\r
-            }\r
-        }\r
-        GrGpu::TextureDesc rtDesc = desc;\r
-        rtDesc.fFlags |= GrGpu::kRenderTarget_TextureFlag |\r
-                         GrGpu::kNoPathRendering_TextureFlag;\r
-        rtDesc.fWidth  = GrNextPow2(GrMax<int>(desc.fWidth,\r
-                                               fGpu->minRenderTargetWidth()));\r
-        rtDesc.fHeight = GrNextPow2(GrMax<int>(desc.fHeight,\r
-                                               fGpu->minRenderTargetHeight()));\r
-\r
-        GrTexture* texture = fGpu->createTexture(rtDesc, NULL, 0);\r
-\r
-        if (NULL != texture) {\r
-            GrDrawTarget::AutoStateRestore asr(fGpu);\r
-            fGpu->setRenderTarget(texture->asRenderTarget());\r
-            fGpu->setTexture(0, clampEntry->texture());\r
-            fGpu->setStencilPass(GrDrawTarget::kNone_StencilPass);\r
-            fGpu->setViewMatrix(GrMatrix::I());\r
-            fGpu->setAlpha(0xff);\r
-            fGpu->setBlendFunc(kOne_BlendCoeff, kZero_BlendCoeff);\r
-            fGpu->disableState(GrDrawTarget::kDither_StateBit |\r
-                               GrDrawTarget::kClip_StateBit   |\r
-                               GrDrawTarget::kAntialias_StateBit);\r
-            GrSamplerState stretchSampler(GrSamplerState::kClamp_WrapMode,\r
-                                          GrSamplerState::kClamp_WrapMode,\r
-                                          sampler.isFilter());\r
-            fGpu->setSamplerState(0, stretchSampler);\r
-\r
-            static const GrVertexLayout layout =\r
-                                GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);\r
-            GrDrawTarget::AutoReleaseGeometry arg(fGpu, layout, 4, 0);\r
-\r
-            if (arg.succeeded()) {\r
-                GrPoint* verts = (GrPoint*) arg.vertices();\r
-                verts[0].setIRectFan(0, 0,\r
-                                     texture->width(),\r
-                                     texture->height(),\r
-                                     2*sizeof(GrPoint));\r
-                verts[1].setIRectFan(0, 0, 1, 1, 2*sizeof(GrPoint));\r
-                fGpu->drawNonIndexed(kTriangleFan_PrimitiveType,\r
-                                     0, 4);\r
-                entry = fTextureCache->createAndLock(*key, texture);\r
-            }\r
-            texture->removeRenderTarget();\r
-        } else {\r
-            // TODO: Our CPU stretch doesn't filter. But we create separate\r
-            // stretched textures when the sampler state is either filtered or\r
-            // not. Either implement filtered stretch blit on CPU or just create\r
-            // one when FBO case fails.\r
-\r
-            rtDesc.fFlags = 0;\r
-            // no longer need to clamp at min RT size.\r
-            rtDesc.fWidth  = GrNextPow2(desc.fWidth);\r
-            rtDesc.fHeight = GrNextPow2(desc.fHeight);\r
-            int bpp = GrTexture::BytesPerPixel(desc.fFormat);\r
-            GrAutoSMalloc<128*128*4> stretchedPixels(bpp *\r
-                                                     rtDesc.fWidth *\r
-                                                     rtDesc.fHeight);\r
-            stretchImage(stretchedPixels.get(), rtDesc.fWidth, rtDesc.fHeight,\r
-                         srcData, desc.fWidth, desc.fHeight, bpp);\r
-\r
-            size_t stretchedRowBytes = rtDesc.fWidth * bpp;\r
-\r
-            GrTexture* texture = fGpu->createTexture(rtDesc,\r
-                                                     stretchedPixels.get(),\r
-                                                     stretchedRowBytes);\r
-            GrAssert(NULL != texture);\r
-            entry = fTextureCache->createAndLock(*key, texture);\r
-        }\r
-        fTextureCache->unlock(clampEntry);\r
-\r
-    } else {\r
-        GrTexture* texture = fGpu->createTexture(desc, srcData, rowBytes);\r
-        if (NULL != texture) {\r
-            entry = fTextureCache->createAndLock(*key, texture);\r
-        } else {\r
-            entry = NULL;\r
-        }\r
-    }\r
-    return entry;\r
-}\r
-\r
-void GrContext::unlockTexture(GrTextureEntry* entry) {\r
-    fTextureCache->unlock(entry);\r
-}\r
-\r
-void GrContext::detachCachedTexture(GrTextureEntry* entry) {\r
-    fTextureCache->detach(entry);\r
-}\r
-\r
-void GrContext::reattachAndUnlockCachedTexture(GrTextureEntry* entry) {\r
-    fTextureCache->reattachAndUnlock(entry);\r
-}\r
-\r
-GrTexture* GrContext::createUncachedTexture(const GrGpu::TextureDesc& desc,\r
-                                            void* srcData,\r
-                                            size_t rowBytes) {\r
-    return fGpu->createTexture(desc, srcData, rowBytes);\r
-}\r
-\r
-void GrContext::getTextureCacheLimits(int* maxTextures,\r
-                                      size_t* maxTextureBytes) const {\r
-    fTextureCache->getLimits(maxTextures, maxTextureBytes);\r
-}\r
-\r
-void GrContext::setTextureCacheLimits(int maxTextures, size_t maxTextureBytes) {\r
-    fTextureCache->setLimits(maxTextures, maxTextureBytes);\r
-}\r
-\r
-int GrContext::getMaxTextureDimension() {\r
-    return fGpu->maxTextureDimension();\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-GrRenderTarget* GrContext::createPlatformRenderTarget(\r
-                                                intptr_t platformRenderTarget,\r
-                                                int stencilBits,\r
-                                                int width, int height) {\r
-    return fGpu->createPlatformRenderTarget(platformRenderTarget, stencilBits,\r
-                                            width, height);\r
-}\r
-\r
-bool GrContext::supportsIndex8PixelConfig(const GrSamplerState& sampler,\r
-                                          int width, int height) {\r
-    if (!fGpu->supports8BitPalette()) {\r
-        return false;\r
-    }\r
-\r
-\r
-    bool isPow2 = GrIsPow2(width) && GrIsPow2(height);\r
-\r
-    if (!isPow2) {\r
-        if (!fGpu->npotTextureSupport()) {\r
-            return false;\r
-        }\r
-\r
-        bool tiled = sampler.getWrapX() != GrSamplerState::kClamp_WrapMode ||\r
-                     sampler.getWrapY() != GrSamplerState::kClamp_WrapMode;\r
-        if (tiled && !fGpu->npotTextureTileSupport()) {\r
-            return false;\r
-        }\r
-    }\r
-    return true;\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-\r
-void GrContext::setClip(const GrClip& clip) {\r
-    fGpu->setClip(clip);\r
-    fGpu->enableState(GrDrawTarget::kClip_StateBit);\r
-}\r
-\r
-void GrContext::setClip(const GrIRect& rect) {\r
-    GrClip clip;\r
-    clip.setRect(rect);\r
-    fGpu->setClip(clip);\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-\r
-void GrContext::eraseColor(GrColor color) {\r
-    fGpu->eraseColor(color);\r
-}\r
-\r
-void GrContext::drawPaint(const GrPaint& paint) {\r
-    // set rect to be big enough to fill the space, but not super-huge, so we\r
-    // don't overflow fixed-point implementations\r
-    GrRect r(fGpu->getClip().getBounds());\r
-    GrMatrix inverse;\r
-    if (fGpu->getViewInverse(&inverse)) {\r
-        inverse.mapRect(&r);\r
-    } else {\r
-        GrPrintf("---- fGpu->getViewInverse failed\n");\r
-    }\r
-    this->drawRect(paint, r);\r
-}\r
-\r
-/*  create a triangle strip that strokes the specified triangle. There are 8\r
- unique vertices, but we repreat the last 2 to close up. Alternatively we\r
- could use an indices array, and then only send 8 verts, but not sure that\r
- would be faster.\r
- */\r
-static void setStrokeRectStrip(GrPoint verts[10], const GrRect& rect,\r
-                               GrScalar width) {\r
-    const GrScalar rad = GrScalarHalf(width);\r
-\r
-    verts[0].set(rect.fLeft + rad, rect.fTop + rad);\r
-    verts[1].set(rect.fLeft - rad, rect.fTop - rad);\r
-    verts[2].set(rect.fRight - rad, rect.fTop + rad);\r
-    verts[3].set(rect.fRight + rad, rect.fTop - rad);\r
-    verts[4].set(rect.fRight - rad, rect.fBottom - rad);\r
-    verts[5].set(rect.fRight + rad, rect.fBottom + rad);\r
-    verts[6].set(rect.fLeft + rad, rect.fBottom - rad);\r
-    verts[7].set(rect.fLeft - rad, rect.fBottom + rad);\r
-    verts[8] = verts[0];\r
-    verts[9] = verts[1];\r
-}\r
-\r
-void GrContext::drawRect(const GrPaint& paint,\r
-                         const GrRect& rect,\r
-                         GrScalar width,\r
-                         const GrMatrix* matrix) {\r
-\r
-    bool textured = NULL != paint.getTexture();\r
-\r
-    GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);\r
-\r
-    if (width >= 0) {\r
-        // TODO: consider making static vertex buffers for these cases.\r
-        // Hairline could be done by just adding closing vertex to\r
-        // unitSquareVertexBuffer()\r
-        GrVertexLayout layout = (textured) ?\r
-                                 GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0) :\r
-                                 0;\r
-        static const int worstCaseVertCount = 10;\r
-        GrDrawTarget::AutoReleaseGeometry geo(target, layout, worstCaseVertCount, 0);\r
-\r
-        if (!geo.succeeded()) {\r
-            return;\r
-        }\r
-\r
-        GrPrimitiveType primType;\r
-        int vertCount;\r
-        GrPoint* vertex = geo.positions();\r
-\r
-        if (width > 0) {\r
-            vertCount = 10;\r
-            primType = kTriangleStrip_PrimitiveType;\r
-            setStrokeRectStrip(vertex, rect, width);\r
-        } else {\r
-            // hairline\r
-            vertCount = 5;\r
-            primType = kLineStrip_PrimitiveType;\r
-            vertex[0].set(rect.fLeft, rect.fTop);\r
-            vertex[1].set(rect.fRight, rect.fTop);\r
-            vertex[2].set(rect.fRight, rect.fBottom);\r
-            vertex[3].set(rect.fLeft, rect.fBottom);\r
-            vertex[4].set(rect.fLeft, rect.fTop);\r
-        }\r
-\r
-        GrDrawTarget::AutoViewMatrixRestore avmr;\r
-        if (NULL != matrix) {\r
-            avmr.set(target);\r
-            target->preConcatViewMatrix(*matrix);\r
-            target->preConcatSamplerMatrix(0, *matrix);\r
-        }\r
-\r
-        target->drawNonIndexed(primType, 0, vertCount);\r
-    } else {\r
-        #if GR_STATIC_RECT_VB\r
-            GrVertexLayout layout = (textured) ?\r
-                            GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0) :\r
-                            0;\r
-            target->setVertexSourceToBuffer(layout, \r
-                                            fGpu->getUnitSquareVertexBuffer());\r
-            GrDrawTarget::AutoViewMatrixRestore avmr(target);\r
-            GrMatrix m;\r
-            m.setAll(rect.width(), 0,             rect.fLeft,\r
-                     0,            rect.height(), rect.fTop,\r
-                     0,            0,             GrMatrix::I()[8]);\r
-\r
-            if (NULL != matrix) {\r
-                m.postConcat(*matrix);\r
-            }\r
-\r
-            target->preConcatViewMatrix(m);\r
-\r
-            if (textured) {\r
-                target->preConcatSamplerMatrix(0, m);\r
-            }\r
-            target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);\r
-        #else\r
-            target->drawSimpleRect(rect, matrix, textured ? 1 : 0);\r
-        #endif\r
-    }\r
-}\r
-\r
-void GrContext::drawRectToRect(const GrPaint& paint,\r
-                               const GrRect& dstRect,\r
-                               const GrRect& srcRect,\r
-                               const GrMatrix* dstMatrix,\r
-                               const GrMatrix* srcMatrix) {\r
-\r
-    if (NULL == paint.getTexture()) {\r
-        drawRect(paint, dstRect, -1, dstMatrix);\r
-        return;\r
-    }\r
-    \r
-    GR_STATIC_ASSERT(!BATCH_RECT_TO_RECT || !GR_STATIC_RECT_VB);\r
-\r
-#if GR_STATIC_RECT_VB\r
-    GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);\r
-\r
-    GrVertexLayout layout = GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);\r
-    GrDrawTarget::AutoViewMatrixRestore avmr(target);\r
-\r
-    GrMatrix m;\r
-\r
-    m.setAll(dstRect.width(), 0,                dstRect.fLeft,\r
-             0,               dstRect.height(), dstRect.fTop,\r
-             0,               0,                GrMatrix::I()[8]);\r
-    if (NULL != dstMatrix) {\r
-        m.postConcat(*dstMatrix);\r
-    }\r
-    target->preConcatViewMatrix(m);\r
-\r
-    m.setAll(srcRect.width(), 0,                srcRect.fLeft,\r
-             0,               srcRect.height(), srcRect.fTop,\r
-             0,               0,                GrMatrix::I()[8]);\r
-    if (NULL != srcMatrix) {\r
-        m.postConcat(*srcMatrix);\r
-    }\r
-    target->preConcatSamplerMatrix(0, m);\r
-\r
-    target->setVertexSourceToBuffer(layout, fGpu->getUnitSquareVertexBuffer());\r
-    target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);\r
-#else\r
-\r
-    GrDrawTarget* target;\r
-#if BATCH_RECT_TO_RECT \r
-    target = this->prepareToDraw(paint, kBuffered_DrawCategory);\r
-#else \r
-    target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);\r
-#endif\r
-\r
-    const GrRect* srcRects[GrDrawTarget::kNumStages] = {NULL};\r
-    const GrMatrix* srcMatrices[GrDrawTarget::kNumStages] = {NULL};\r
-    srcRects[0] = &srcRect;\r
-    srcMatrices[0] = srcMatrix;\r
-\r
-    target->drawRect(dstRect, dstMatrix, 1, srcRects, srcMatrices);\r
-#endif\r
-}\r
-\r
-void GrContext::drawVertices(const GrPaint& paint,\r
-                             GrPrimitiveType primitiveType,\r
-                             int vertexCount,\r
-                             const GrPoint positions[],\r
-                             const GrPoint texCoords[],\r
-                             const GrColor colors[],\r
-                             const uint16_t indices[],\r
-                             int indexCount) {\r
-    GrVertexLayout layout = 0;\r
-    int vertexSize = sizeof(GrPoint);\r
-\r
-    GrDrawTarget::AutoReleaseGeometry geo;\r
-\r
-    GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);\r
-\r
-    if (NULL != paint.getTexture()) {\r
-        if (NULL == texCoords) {\r
-            layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);\r
-        } else {\r
-            layout |= GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);\r
-            vertexSize += sizeof(GrPoint);\r
-        }\r
-    }\r
-\r
-    if (NULL != colors) {\r
-        layout |= GrDrawTarget::kColor_VertexLayoutBit;\r
-        vertexSize += sizeof(GrColor);\r
-    }\r
-\r
-    if (sizeof(GrPoint) != vertexSize) {\r
-        if (!geo.set(target, layout, vertexCount, 0)) {\r
-            GrPrintf("Failed to get space for vertices!");\r
-            return;\r
-        }\r
-        int texOffsets[GrDrawTarget::kMaxTexCoords];\r
-        int colorOffset;\r
-        int vsize = GrDrawTarget::VertexSizeAndOffsetsByIdx(layout,\r
-                                                            texOffsets,\r
-                                                            &colorOffset);\r
-        void* curVertex = geo.vertices();\r
-\r
-        for (int i = 0; i < vertexCount; ++i) {\r
-            *((GrPoint*)curVertex) = positions[i];\r
-\r
-            if (texOffsets[0] > 0) {\r
-                *(GrPoint*)((intptr_t)curVertex + texOffsets[0]) = texCoords[i];\r
-            }\r
-            if (colorOffset > 0) {\r
-                *(GrColor*)((intptr_t)curVertex + colorOffset) = colors[i];\r
-            }\r
-            curVertex = (void*)((intptr_t)curVertex + vsize);\r
-        }\r
-    } else {\r
-        target->setVertexSourceToArray(layout, positions, vertexCount);\r
-    }\r
-\r
-    if (NULL != indices) {\r
-        target->setIndexSourceToArray(indices, indexCount);\r
-        target->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount);\r
-    } else {\r
-        target->drawNonIndexed(primitiveType, 0, vertexCount);\r
-    }\r
-}\r
-\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-\r
-void GrContext::drawPath(const GrPaint& paint,\r
-                         GrPathIter* path,\r
-                         GrPathFill fill,\r
-                         const GrPoint* translate) {\r
-\r
-\r
-    GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);\r
-\r
-    GrDrawTarget::StageBitfield enabledStages = 0;\r
-    if (NULL != paint.getTexture()) {\r
-        enabledStages |= 1;\r
-    }\r
-    fPathRenderer->drawPath(target, enabledStages, path, fill, translate);\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-\r
-void GrContext::flush(bool flushRenderTarget) {\r
-    flushDrawBuffer();\r
-    if (flushRenderTarget) {\r
-        fGpu->forceRenderTargetFlush();\r
-    }\r
-}\r
-\r
-void GrContext::flushText() {\r
-    if (kText_DrawCategory == fLastDrawCategory) {\r
-        flushDrawBuffer();\r
-    }\r
-}\r
-\r
-void GrContext::flushDrawBuffer() {\r
-#if BATCH_RECT_TO_RECT || DEFER_TEXT_RENDERING\r
-    fDrawBuffer->playback(fGpu);\r
-    fDrawBuffer->reset();\r
-#endif\r
-}\r
-\r
-bool GrContext::readPixels(int left, int top, int width, int height,\r
-                           GrTexture::PixelConfig config, void* buffer) {\r
-    this->flush(true);\r
-    return fGpu->readPixels(left, top, width, height, config, buffer);\r
-}\r
-\r
-void GrContext::writePixels(int left, int top, int width, int height,\r
-                            GrTexture::PixelConfig config, const void* buffer,\r
-                            size_t stride) {\r
-\r
-    // TODO: when underlying api has a direct way to do this we should use it\r
-    // (e.g. glDrawPixels on desktop GL).\r
-\r
-    const GrGpu::TextureDesc desc = {\r
-        0, GrGpu::kNone_AALevel, width, height, config\r
-    };\r
-    GrTexture* texture = fGpu->createTexture(desc, buffer, stride);\r
-    if (NULL == texture) {\r
-        return;\r
-    }\r
-\r
-    this->flush(true);\r
-\r
-    GrAutoUnref                     aur(texture);\r
-    GrDrawTarget::AutoStateRestore  asr(fGpu);\r
-\r
-    GrMatrix matrix;\r
-    matrix.setTranslate(GrIntToScalar(left), GrIntToScalar(top));\r
-    fGpu->setViewMatrix(matrix);\r
-\r
-    fGpu->disableState(GrDrawTarget::kClip_StateBit);\r
-    fGpu->setAlpha(0xFF);\r
-    fGpu->setBlendFunc(kOne_BlendCoeff,\r
-                       kZero_BlendCoeff);\r
-    fGpu->setTexture(0, texture);\r
-\r
-    GrSamplerState sampler;\r
-    sampler.setClampNoFilter();\r
-    matrix.setScale(GR_Scalar1 / width, GR_Scalar1 / height);\r
-    sampler.setMatrix(matrix);\r
-    fGpu->setSamplerState(0, sampler);\r
-\r
-    GrVertexLayout layout = GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);\r
-    static const int VCOUNT = 4;\r
-\r
-    GrDrawTarget::AutoReleaseGeometry geo(fGpu, layout, VCOUNT, 0);\r
-    if (!geo.succeeded()) {\r
-        return;\r
-    }\r
-    ((GrPoint*)geo.vertices())->setIRectFan(0, 0, width, height);\r
-    fGpu->drawNonIndexed(kTriangleFan_PrimitiveType, 0, VCOUNT);\r
-}\r
-////////////////////////////////////////////////////////////////////////////////\r
-\r
-void GrContext::SetPaint(const GrPaint& paint, GrDrawTarget* target) {\r
-    target->setTexture(0, paint.getTexture());\r
-    target->setSamplerState(0, paint.fSampler);\r
-    target->setColor(paint.fColor);\r
-\r
-    if (paint.fDither) {\r
-        target->enableState(GrDrawTarget::kDither_StateBit);\r
-    } else {\r
-        target->disableState(GrDrawTarget::kDither_StateBit);\r
-    }\r
-    if (paint.fAntiAlias) {\r
-        target->enableState(GrDrawTarget::kAntialias_StateBit);\r
-    } else {\r
-        target->disableState(GrDrawTarget::kAntialias_StateBit);\r
-    }\r
-    target->setBlendFunc(paint.fSrcBlendCoeff, paint.fDstBlendCoeff);\r
-}\r
-\r
-GrDrawTarget* GrContext::prepareToDraw(const GrPaint& paint, \r
-                                       DrawCategory category) {\r
-    if (category != fLastDrawCategory) {\r
-        flushDrawBuffer();\r
-        fLastDrawCategory = category;\r
-    }\r
-    SetPaint(paint, fGpu);\r
-    GrDrawTarget* target = fGpu;\r
-    switch (category) {\r
-    case kText_DrawCategory:\r
-#if DEFER_TEXT_RENDERING\r
-        target = fDrawBuffer;\r
-        fDrawBuffer->initializeDrawStateAndClip(*fGpu);\r
-#else\r
-        target = fGpu;\r
-#endif\r
-        break;\r
-    case kUnbuffered_DrawCategory:\r
-        target = fGpu;\r
-        break;\r
-    case kBuffered_DrawCategory:\r
-        target = fDrawBuffer;\r
-        fDrawBuffer->initializeDrawStateAndClip(*fGpu);\r
-        break;\r
-    }\r
-    return target;\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-\r
-void GrContext::resetContext() {\r
-    fGpu->resetContext();\r
-}\r
-\r
-void GrContext::setRenderTarget(GrRenderTarget* target) {\r
-    flush(false);\r
-    fGpu->setRenderTarget(target);\r
-}\r
-\r
-GrRenderTarget* GrContext::getRenderTarget() {\r
-    return fGpu->getRenderTarget();\r
-}\r
-\r
-const GrRenderTarget* GrContext::getRenderTarget() const {\r
-    return fGpu->getRenderTarget();\r
-}\r
-\r
-const GrMatrix& GrContext::getMatrix() const {\r
-    return fGpu->getViewMatrix();\r
-}\r
-\r
-void GrContext::setMatrix(const GrMatrix& m) {\r
-    fGpu->setViewMatrix(m);\r
-}\r
-\r
-void GrContext::concatMatrix(const GrMatrix& m) const {\r
-    fGpu->preConcatViewMatrix(m);\r
-}\r
-\r
-static inline intptr_t setOrClear(intptr_t bits, int shift, intptr_t pred) {\r
-    intptr_t mask = 1 << shift;\r
-    if (pred) {\r
-        bits |= mask;\r
-    } else {\r
-        bits &= ~mask;\r
-    }\r
-    return bits;\r
-}\r
-\r
-void GrContext::resetStats() {\r
-    fGpu->resetStats();\r
-}\r
-\r
-const GrGpu::Stats& GrContext::getStats() const {\r
-    return fGpu->getStats();\r
-}\r
-\r
-void GrContext::printStats() const {\r
-    fGpu->printStats();\r
-}\r
-\r
-GrContext::GrContext(GrGpu* gpu) {\r
-    fGpu = gpu;\r
-    fGpu->ref();\r
-    fTextureCache = new GrTextureCache(MAX_TEXTURE_CACHE_COUNT,\r
-                                       MAX_TEXTURE_CACHE_BYTES);\r
-    fFontCache = new GrFontCache(fGpu);\r
-\r
-    fLastDrawCategory = kUnbuffered_DrawCategory;\r
-\r
-#if DEFER_TEXT_RENDERING || BATCH_RECT_TO_RECT\r
-    fDrawBufferVBAllocPool = \r
-        new GrVertexBufferAllocPool(gpu, false,\r
-                                    DRAW_BUFFER_VBPOOL_BUFFER_SIZE,\r
-                                    DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS);\r
-    fDrawBufferIBAllocPool = \r
-        new GrIndexBufferAllocPool(gpu, false,\r
-                                   DRAW_BUFFER_IBPOOL_BUFFER_SIZE, \r
-                                   DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS);\r
-\r
-    fDrawBuffer = new GrInOrderDrawBuffer(fDrawBufferVBAllocPool,\r
-                                          fDrawBufferIBAllocPool);\r
-#else\r
-    fDrawBuffer = NULL;\r
-    fDrawBufferVBAllocPool = NULL;\r
-    fDrawBufferIBAllocPool = NULL;\r
-#endif\r
-\r
-#if BATCH_RECT_TO_RECT\r
-    fDrawBuffer->setQuadIndexBuffer(this->getQuadIndexBuffer());\r
-#endif\r
-    fPathRenderer = new GrDefaultPathRenderer(fGpu->supportsSingleStencilPassWinding());\r
-}\r
-\r
-bool GrContext::finalizeTextureKey(GrTextureKey* key,\r
-                                   const GrSamplerState& sampler) const {\r
-    uint32_t bits = 0;\r
-    uint16_t width = key->width();\r
-    uint16_t height = key->height();\r
-\r
-\r
-    if (!fGpu->npotTextureTileSupport()) {\r
-        bool isPow2 = GrIsPow2(width) && GrIsPow2(height);\r
-\r
-        bool tiled = (sampler.getWrapX() != GrSamplerState::kClamp_WrapMode) ||\r
-                     (sampler.getWrapY() != GrSamplerState::kClamp_WrapMode);\r
-\r
-        if (tiled && !isPow2) {\r
-            bits |= 1;\r
-            bits |= sampler.isFilter() ? 2 : 0;\r
-        }\r
-    }\r
-    key->finalize(bits);\r
-    return 0 != bits;\r
-}\r
-\r
-GrDrawTarget* GrContext::getTextTarget(const GrPaint& paint) {\r
-    GrDrawTarget* target;\r
-#if DEFER_TEXT_RENDERING\r
-    target = prepareToDraw(paint, kText_DrawCategory);\r
-#else\r
-    target = prepareToDraw(paint, kUnbuffered_DrawCategory);\r
-#endif\r
-    SetPaint(paint, target);\r
-    return target;\r
-}\r
-\r
-const GrIndexBuffer* GrContext::getQuadIndexBuffer() const {\r
-    return fGpu->getQuadIndexBuffer();\r
-}\r
+/*
+    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.
+ */
+
+#include "GrContext.h"
+#include "GrTypes.h"
+#include "GrTextureCache.h"
+#include "GrTextStrike.h"
+#include "GrMemory.h"
+#include "GrPathIter.h"
+#include "GrClipIterator.h"
+#include "GrIndexBuffer.h"
+#include "GrInOrderDrawBuffer.h"
+#include "GrBufferAllocPool.h"
+#include "GrPathRenderer.h"
+
+#define DEFER_TEXT_RENDERING 1
+
+#define BATCH_RECT_TO_RECT (1 && !GR_STATIC_RECT_VB)
+
+static const size_t MAX_TEXTURE_CACHE_COUNT = 128;
+static const size_t MAX_TEXTURE_CACHE_BYTES = 8 * 1024 * 1024;
+
+static const size_t DRAW_BUFFER_VBPOOL_BUFFER_SIZE = 1 << 18;
+static const int DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS = 4;
+
+// We are currently only batching Text and drawRectToRect, both
+// of which use the quad index buffer.
+static const size_t DRAW_BUFFER_IBPOOL_BUFFER_SIZE = 0;
+static const int DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS = 0;
+
+GrContext* GrContext::Create(GrGpu::Engine engine,
+                             GrGpu::Platform3DContext context3D) {
+    GrContext* ctx = NULL;
+    GrGpu* fGpu = GrGpu::Create(engine, context3D);
+    if (NULL != fGpu) {
+        ctx = new GrContext(fGpu);
+        fGpu->unref();
+    }
+    return ctx;
+}
+
+GrContext* GrContext::CreateGLShaderContext() {
+    return GrContext::Create(GrGpu::kOpenGL_Shaders_Engine, NULL);
+}
+
+GrContext::~GrContext() {
+    fGpu->unref();
+    delete fTextureCache;
+    delete fFontCache;
+    delete fDrawBuffer;
+    delete fDrawBufferVBAllocPool;
+    delete fDrawBufferVBAllocPool;
+    delete fPathRenderer;
+}
+
+void GrContext::abandonAllTextures() {
+    fTextureCache->deleteAll(GrTextureCache::kAbandonTexture_DeleteMode);
+    fFontCache->abandonAll();
+}
+
+GrTextureEntry* GrContext::findAndLockTexture(GrTextureKey* key,
+                                              const GrSamplerState& sampler) {
+    finalizeTextureKey(key, sampler);
+    return fTextureCache->findAndLock(*key);
+}
+
+static void stretchImage(void* dst,
+                         int dstW,
+                         int dstH,
+                         void* src,
+                         int srcW,
+                         int srcH,
+                         int bpp) {
+    GrFixed dx = (srcW << 16) / dstW;
+    GrFixed dy = (srcH << 16) / dstH;
+
+    GrFixed y = dy >> 1;
+
+    int dstXLimit = dstW*bpp;
+    for (int j = 0; j < dstH; ++j) {
+        GrFixed x = dx >> 1;
+        void* srcRow = (uint8_t*)src + (y>>16)*srcW*bpp;
+        void* dstRow = (uint8_t*)dst + j*dstW*bpp;
+        for (int i = 0; i < dstXLimit; i += bpp) {
+            memcpy((uint8_t*) dstRow + i,
+                   (uint8_t*) srcRow + (x>>16)*bpp,
+                   bpp);
+            x += dx;
+        }
+        y += dy;
+    }
+}
+
+GrTextureEntry* GrContext::createAndLockTexture(GrTextureKey* key,
+                                                const GrSamplerState& sampler,
+                                                const GrGpu::TextureDesc& desc,
+                                                void* srcData, size_t rowBytes) {
+    GrAssert(key->width() == desc.fWidth);
+    GrAssert(key->height() == desc.fHeight);
+
+#if GR_DUMP_TEXTURE_UPLOAD
+    GrPrintf("GrContext::createAndLockTexture [%d %d]\n", desc.fWidth, desc.fHeight);
+#endif
+
+    GrTextureEntry* entry = NULL;
+    bool special = finalizeTextureKey(key, sampler);
+    if (special) {
+        GrTextureEntry* clampEntry;
+        GrTextureKey clampKey(*key);
+        clampEntry = findAndLockTexture(&clampKey, GrSamplerState::ClampNoFilter());
+
+        if (NULL == clampEntry) {
+            clampEntry = createAndLockTexture(&clampKey,
+                                              GrSamplerState::ClampNoFilter(),
+                                              desc, srcData, rowBytes);
+            GrAssert(NULL != clampEntry);
+            if (NULL == clampEntry) {
+                return NULL;
+            }
+        }
+        GrGpu::TextureDesc rtDesc = desc;
+        rtDesc.fFlags |= GrGpu::kRenderTarget_TextureFlag |
+                         GrGpu::kNoPathRendering_TextureFlag;
+        rtDesc.fWidth  = GrNextPow2(GrMax<int>(desc.fWidth,
+                                               fGpu->minRenderTargetWidth()));
+        rtDesc.fHeight = GrNextPow2(GrMax<int>(desc.fHeight,
+                                               fGpu->minRenderTargetHeight()));
+
+        GrTexture* texture = fGpu->createTexture(rtDesc, NULL, 0);
+
+        if (NULL != texture) {
+            GrDrawTarget::AutoStateRestore asr(fGpu);
+            fGpu->setRenderTarget(texture->asRenderTarget());
+            fGpu->setTexture(0, clampEntry->texture());
+            fGpu->setStencilPass(GrDrawTarget::kNone_StencilPass);
+            fGpu->setViewMatrix(GrMatrix::I());
+            fGpu->setAlpha(0xff);
+            fGpu->setBlendFunc(kOne_BlendCoeff, kZero_BlendCoeff);
+            fGpu->disableState(GrDrawTarget::kDither_StateBit |
+                               GrDrawTarget::kClip_StateBit   |
+                               GrDrawTarget::kAntialias_StateBit);
+            GrSamplerState stretchSampler(GrSamplerState::kClamp_WrapMode,
+                                          GrSamplerState::kClamp_WrapMode,
+                                          sampler.isFilter());
+            fGpu->setSamplerState(0, stretchSampler);
+
+            static const GrVertexLayout layout =
+                                GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);
+            GrDrawTarget::AutoReleaseGeometry arg(fGpu, layout, 4, 0);
+
+            if (arg.succeeded()) {
+                GrPoint* verts = (GrPoint*) arg.vertices();
+                verts[0].setIRectFan(0, 0,
+                                     texture->width(),
+                                     texture->height(),
+                                     2*sizeof(GrPoint));
+                verts[1].setIRectFan(0, 0, 1, 1, 2*sizeof(GrPoint));
+                fGpu->drawNonIndexed(kTriangleFan_PrimitiveType,
+                                     0, 4);
+                entry = fTextureCache->createAndLock(*key, texture);
+            }
+            texture->removeRenderTarget();
+        } else {
+            // TODO: Our CPU stretch doesn't filter. But we create separate
+            // stretched textures when the sampler state is either filtered or
+            // not. Either implement filtered stretch blit on CPU or just create
+            // one when FBO case fails.
+
+            rtDesc.fFlags = 0;
+            // no longer need to clamp at min RT size.
+            rtDesc.fWidth  = GrNextPow2(desc.fWidth);
+            rtDesc.fHeight = GrNextPow2(desc.fHeight);
+            int bpp = GrTexture::BytesPerPixel(desc.fFormat);
+            GrAutoSMalloc<128*128*4> stretchedPixels(bpp *
+                                                     rtDesc.fWidth *
+                                                     rtDesc.fHeight);
+            stretchImage(stretchedPixels.get(), rtDesc.fWidth, rtDesc.fHeight,
+                         srcData, desc.fWidth, desc.fHeight, bpp);
+
+            size_t stretchedRowBytes = rtDesc.fWidth * bpp;
+
+            GrTexture* texture = fGpu->createTexture(rtDesc,
+                                                     stretchedPixels.get(),
+                                                     stretchedRowBytes);
+            GrAssert(NULL != texture);
+            entry = fTextureCache->createAndLock(*key, texture);
+        }
+        fTextureCache->unlock(clampEntry);
+
+    } else {
+        GrTexture* texture = fGpu->createTexture(desc, srcData, rowBytes);
+        if (NULL != texture) {
+            entry = fTextureCache->createAndLock(*key, texture);
+        } else {
+            entry = NULL;
+        }
+    }
+    return entry;
+}
+
+void GrContext::unlockTexture(GrTextureEntry* entry) {
+    fTextureCache->unlock(entry);
+}
+
+void GrContext::detachCachedTexture(GrTextureEntry* entry) {
+    fTextureCache->detach(entry);
+}
+
+void GrContext::reattachAndUnlockCachedTexture(GrTextureEntry* entry) {
+    fTextureCache->reattachAndUnlock(entry);
+}
+
+GrTexture* GrContext::createUncachedTexture(const GrGpu::TextureDesc& desc,
+                                            void* srcData,
+                                            size_t rowBytes) {
+    return fGpu->createTexture(desc, srcData, rowBytes);
+}
+
+void GrContext::getTextureCacheLimits(int* maxTextures,
+                                      size_t* maxTextureBytes) const {
+    fTextureCache->getLimits(maxTextures, maxTextureBytes);
+}
+
+void GrContext::setTextureCacheLimits(int maxTextures, size_t maxTextureBytes) {
+    fTextureCache->setLimits(maxTextures, maxTextureBytes);
+}
+
+int GrContext::getMaxTextureDimension() {
+    return fGpu->maxTextureDimension();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+GrRenderTarget* GrContext::createPlatformRenderTarget(
+                                                intptr_t platformRenderTarget,
+                                                int stencilBits,
+                                                int width, int height) {
+    return fGpu->createPlatformRenderTarget(platformRenderTarget, stencilBits,
+                                            width, height);
+}
+
+bool GrContext::supportsIndex8PixelConfig(const GrSamplerState& sampler,
+                                          int width, int height) {
+    if (!fGpu->supports8BitPalette()) {
+        return false;
+    }
+
+
+    bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
+
+    if (!isPow2) {
+        if (!fGpu->npotTextureSupport()) {
+            return false;
+        }
+
+        bool tiled = sampler.getWrapX() != GrSamplerState::kClamp_WrapMode ||
+                     sampler.getWrapY() != GrSamplerState::kClamp_WrapMode;
+        if (tiled && !fGpu->npotTextureTileSupport()) {
+            return false;
+        }
+    }
+    return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+void GrContext::setClip(const GrClip& clip) {
+    fGpu->setClip(clip);
+    fGpu->enableState(GrDrawTarget::kClip_StateBit);
+}
+
+void GrContext::setClip(const GrIRect& rect) {
+    GrClip clip;
+    clip.setRect(rect);
+    fGpu->setClip(clip);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+void GrContext::eraseColor(GrColor color) {
+    fGpu->eraseColor(color);
+}
+
+void GrContext::drawPaint(const GrPaint& paint) {
+    // set rect to be big enough to fill the space, but not super-huge, so we
+    // don't overflow fixed-point implementations
+    GrRect r(fGpu->getClip().getBounds());
+    GrMatrix inverse;
+    if (fGpu->getViewInverse(&inverse)) {
+        inverse.mapRect(&r);
+    } else {
+        GrPrintf("---- fGpu->getViewInverse failed\n");
+    }
+    this->drawRect(paint, r);
+}
+
+/*  create a triangle strip that strokes the specified triangle. There are 8
+ unique vertices, but we repreat the last 2 to close up. Alternatively we
+ could use an indices array, and then only send 8 verts, but not sure that
+ would be faster.
+ */
+static void setStrokeRectStrip(GrPoint verts[10], const GrRect& rect,
+                               GrScalar width) {
+    const GrScalar rad = GrScalarHalf(width);
+
+    verts[0].set(rect.fLeft + rad, rect.fTop + rad);
+    verts[1].set(rect.fLeft - rad, rect.fTop - rad);
+    verts[2].set(rect.fRight - rad, rect.fTop + rad);
+    verts[3].set(rect.fRight + rad, rect.fTop - rad);
+    verts[4].set(rect.fRight - rad, rect.fBottom - rad);
+    verts[5].set(rect.fRight + rad, rect.fBottom + rad);
+    verts[6].set(rect.fLeft + rad, rect.fBottom - rad);
+    verts[7].set(rect.fLeft - rad, rect.fBottom + rad);
+    verts[8] = verts[0];
+    verts[9] = verts[1];
+}
+
+void GrContext::drawRect(const GrPaint& paint,
+                         const GrRect& rect,
+                         GrScalar width,
+                         const GrMatrix* matrix) {
+
+    bool textured = NULL != paint.getTexture();
+
+    GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
+
+    if (width >= 0) {
+        // TODO: consider making static vertex buffers for these cases.
+        // Hairline could be done by just adding closing vertex to
+        // unitSquareVertexBuffer()
+        GrVertexLayout layout = (textured) ?
+                                 GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0) :
+                                 0;
+        static const int worstCaseVertCount = 10;
+        GrDrawTarget::AutoReleaseGeometry geo(target, layout, worstCaseVertCount, 0);
+
+        if (!geo.succeeded()) {
+            return;
+        }
+
+        GrPrimitiveType primType;
+        int vertCount;
+        GrPoint* vertex = geo.positions();
+
+        if (width > 0) {
+            vertCount = 10;
+            primType = kTriangleStrip_PrimitiveType;
+            setStrokeRectStrip(vertex, rect, width);
+        } else {
+            // hairline
+            vertCount = 5;
+            primType = kLineStrip_PrimitiveType;
+            vertex[0].set(rect.fLeft, rect.fTop);
+            vertex[1].set(rect.fRight, rect.fTop);
+            vertex[2].set(rect.fRight, rect.fBottom);
+            vertex[3].set(rect.fLeft, rect.fBottom);
+            vertex[4].set(rect.fLeft, rect.fTop);
+        }
+
+        GrDrawTarget::AutoViewMatrixRestore avmr;
+        if (NULL != matrix) {
+            avmr.set(target);
+            target->preConcatViewMatrix(*matrix);
+            target->preConcatSamplerMatrix(0, *matrix);
+        }
+
+        target->drawNonIndexed(primType, 0, vertCount);
+    } else {
+        #if GR_STATIC_RECT_VB
+            GrVertexLayout layout = (textured) ?
+                            GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0) :
+                            0;
+            target->setVertexSourceToBuffer(layout, 
+                                            fGpu->getUnitSquareVertexBuffer());
+            GrDrawTarget::AutoViewMatrixRestore avmr(target);
+            GrMatrix m;
+            m.setAll(rect.width(), 0,             rect.fLeft,
+                     0,            rect.height(), rect.fTop,
+                     0,            0,             GrMatrix::I()[8]);
+
+            if (NULL != matrix) {
+                m.postConcat(*matrix);
+            }
+
+            target->preConcatViewMatrix(m);
+
+            if (textured) {
+                target->preConcatSamplerMatrix(0, m);
+            }
+            target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
+        #else
+            target->drawSimpleRect(rect, matrix, textured ? 1 : 0);
+        #endif
+    }
+}
+
+void GrContext::drawRectToRect(const GrPaint& paint,
+                               const GrRect& dstRect,
+                               const GrRect& srcRect,
+                               const GrMatrix* dstMatrix,
+                               const GrMatrix* srcMatrix) {
+
+    if (NULL == paint.getTexture()) {
+        drawRect(paint, dstRect, -1, dstMatrix);
+        return;
+    }
+    
+    GR_STATIC_ASSERT(!BATCH_RECT_TO_RECT || !GR_STATIC_RECT_VB);
+
+#if GR_STATIC_RECT_VB
+    GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
+
+    GrVertexLayout layout = GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
+    GrDrawTarget::AutoViewMatrixRestore avmr(target);
+
+    GrMatrix m;
+
+    m.setAll(dstRect.width(), 0,                dstRect.fLeft,
+             0,               dstRect.height(), dstRect.fTop,
+             0,               0,                GrMatrix::I()[8]);
+    if (NULL != dstMatrix) {
+        m.postConcat(*dstMatrix);
+    }
+    target->preConcatViewMatrix(m);
+
+    m.setAll(srcRect.width(), 0,                srcRect.fLeft,
+             0,               srcRect.height(), srcRect.fTop,
+             0,               0,                GrMatrix::I()[8]);
+    if (NULL != srcMatrix) {
+        m.postConcat(*srcMatrix);
+    }
+    target->preConcatSamplerMatrix(0, m);
+
+    target->setVertexSourceToBuffer(layout, fGpu->getUnitSquareVertexBuffer());
+    target->drawNonIndexed(kTriangleFan_PrimitiveType, 0, 4);
+#else
+
+    GrDrawTarget* target;
+#if BATCH_RECT_TO_RECT 
+    target = this->prepareToDraw(paint, kBuffered_DrawCategory);
+#else 
+    target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
+#endif
+
+    const GrRect* srcRects[GrDrawTarget::kNumStages] = {NULL};
+    const GrMatrix* srcMatrices[GrDrawTarget::kNumStages] = {NULL};
+    srcRects[0] = &srcRect;
+    srcMatrices[0] = srcMatrix;
+
+    target->drawRect(dstRect, dstMatrix, 1, srcRects, srcMatrices);
+#endif
+}
+
+void GrContext::drawVertices(const GrPaint& paint,
+                             GrPrimitiveType primitiveType,
+                             int vertexCount,
+                             const GrPoint positions[],
+                             const GrPoint texCoords[],
+                             const GrColor colors[],
+                             const uint16_t indices[],
+                             int indexCount) {
+    GrVertexLayout layout = 0;
+    int vertexSize = sizeof(GrPoint);
+
+    GrDrawTarget::AutoReleaseGeometry geo;
+
+    GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
+
+    if (NULL != paint.getTexture()) {
+        if (NULL == texCoords) {
+            layout |= GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
+        } else {
+            layout |= GrDrawTarget::StageTexCoordVertexLayoutBit(0,0);
+            vertexSize += sizeof(GrPoint);
+        }
+    }
+
+    if (NULL != colors) {
+        layout |= GrDrawTarget::kColor_VertexLayoutBit;
+        vertexSize += sizeof(GrColor);
+    }
+
+    if (sizeof(GrPoint) != vertexSize) {
+        if (!geo.set(target, layout, vertexCount, 0)) {
+            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) {
+            *((GrPoint*)curVertex) = positions[i];
+
+            if (texOffsets[0] > 0) {
+                *(GrPoint*)((intptr_t)curVertex + texOffsets[0]) = texCoords[i];
+            }
+            if (colorOffset > 0) {
+                *(GrColor*)((intptr_t)curVertex + colorOffset) = colors[i];
+            }
+            curVertex = (void*)((intptr_t)curVertex + vsize);
+        }
+    } else {
+        target->setVertexSourceToArray(layout, positions, vertexCount);
+    }
+
+    if (NULL != indices) {
+        target->setIndexSourceToArray(indices, indexCount);
+        target->drawIndexed(primitiveType, 0, 0, vertexCount, indexCount);
+    } else {
+        target->drawNonIndexed(primitiveType, 0, vertexCount);
+    }
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+void GrContext::drawPath(const GrPaint& paint,
+                         GrPathIter* path,
+                         GrPathFill fill,
+                         const GrPoint* translate) {
+
+
+    GrDrawTarget* target = this->prepareToDraw(paint, kUnbuffered_DrawCategory);
+
+    GrDrawTarget::StageBitfield enabledStages = 0;
+    if (NULL != paint.getTexture()) {
+        enabledStages |= 1;
+    }
+    fPathRenderer->drawPath(target, enabledStages, path, fill, translate);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+void GrContext::flush(bool flushRenderTarget) {
+    flushDrawBuffer();
+    if (flushRenderTarget) {
+        fGpu->forceRenderTargetFlush();
+    }
+}
+
+void GrContext::flushText() {
+    if (kText_DrawCategory == fLastDrawCategory) {
+        flushDrawBuffer();
+    }
+}
+
+void GrContext::flushDrawBuffer() {
+#if BATCH_RECT_TO_RECT || DEFER_TEXT_RENDERING
+    fDrawBuffer->playback(fGpu);
+    fDrawBuffer->reset();
+#endif
+}
+
+bool GrContext::readPixels(int left, int top, int width, int height,
+                           GrTexture::PixelConfig config, void* buffer) {
+    this->flush(true);
+    return fGpu->readPixels(left, top, width, height, config, buffer);
+}
+
+void GrContext::writePixels(int left, int top, int width, int height,
+                            GrTexture::PixelConfig config, const void* buffer,
+                            size_t stride) {
+
+    // TODO: when underlying api has a direct way to do this we should use it
+    // (e.g. glDrawPixels on desktop GL).
+
+    const GrGpu::TextureDesc desc = {
+        0, GrGpu::kNone_AALevel, width, height, config
+    };
+    GrTexture* texture = fGpu->createTexture(desc, buffer, stride);
+    if (NULL == texture) {
+        return;
+    }
+
+    this->flush(true);
+
+    GrAutoUnref                     aur(texture);
+    GrDrawTarget::AutoStateRestore  asr(fGpu);
+
+    GrMatrix matrix;
+    matrix.setTranslate(GrIntToScalar(left), GrIntToScalar(top));
+    fGpu->setViewMatrix(matrix);
+
+    fGpu->disableState(GrDrawTarget::kClip_StateBit);
+    fGpu->setAlpha(0xFF);
+    fGpu->setBlendFunc(kOne_BlendCoeff,
+                       kZero_BlendCoeff);
+    fGpu->setTexture(0, texture);
+
+    GrSamplerState sampler;
+    sampler.setClampNoFilter();
+    matrix.setScale(GR_Scalar1 / width, GR_Scalar1 / height);
+    sampler.setMatrix(matrix);
+    fGpu->setSamplerState(0, sampler);
+
+    GrVertexLayout layout = GrDrawTarget::StagePosAsTexCoordVertexLayoutBit(0);
+    static const int VCOUNT = 4;
+
+    GrDrawTarget::AutoReleaseGeometry geo(fGpu, layout, VCOUNT, 0);
+    if (!geo.succeeded()) {
+        return;
+    }
+    ((GrPoint*)geo.vertices())->setIRectFan(0, 0, width, height);
+    fGpu->drawNonIndexed(kTriangleFan_PrimitiveType, 0, VCOUNT);
+}
+////////////////////////////////////////////////////////////////////////////////
+
+void GrContext::SetPaint(const GrPaint& paint, GrDrawTarget* target) {
+    target->setTexture(0, paint.getTexture());
+    target->setSamplerState(0, paint.fSampler);
+    target->setColor(paint.fColor);
+
+    if (paint.fDither) {
+        target->enableState(GrDrawTarget::kDither_StateBit);
+    } else {
+        target->disableState(GrDrawTarget::kDither_StateBit);
+    }
+    if (paint.fAntiAlias) {
+        target->enableState(GrDrawTarget::kAntialias_StateBit);
+    } else {
+        target->disableState(GrDrawTarget::kAntialias_StateBit);
+    }
+    target->setBlendFunc(paint.fSrcBlendCoeff, paint.fDstBlendCoeff);
+}
+
+GrDrawTarget* GrContext::prepareToDraw(const GrPaint& paint, 
+                                       DrawCategory category) {
+    if (category != fLastDrawCategory) {
+        flushDrawBuffer();
+        fLastDrawCategory = category;
+    }
+    SetPaint(paint, fGpu);
+    GrDrawTarget* target = fGpu;
+    switch (category) {
+    case kText_DrawCategory:
+#if DEFER_TEXT_RENDERING
+        target = fDrawBuffer;
+        fDrawBuffer->initializeDrawStateAndClip(*fGpu);
+#else
+        target = fGpu;
+#endif
+        break;
+    case kUnbuffered_DrawCategory:
+        target = fGpu;
+        break;
+    case kBuffered_DrawCategory:
+        target = fDrawBuffer;
+        fDrawBuffer->initializeDrawStateAndClip(*fGpu);
+        break;
+    }
+    return target;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
+void GrContext::resetContext() {
+    fGpu->resetContext();
+}
+
+void GrContext::setRenderTarget(GrRenderTarget* target) {
+    flush(false);
+    fGpu->setRenderTarget(target);
+}
+
+GrRenderTarget* GrContext::getRenderTarget() {
+    return fGpu->getRenderTarget();
+}
+
+const GrRenderTarget* GrContext::getRenderTarget() const {
+    return fGpu->getRenderTarget();
+}
+
+const GrMatrix& GrContext::getMatrix() const {
+    return fGpu->getViewMatrix();
+}
+
+void GrContext::setMatrix(const GrMatrix& m) {
+    fGpu->setViewMatrix(m);
+}
+
+void GrContext::concatMatrix(const GrMatrix& m) const {
+    fGpu->preConcatViewMatrix(m);
+}
+
+static inline intptr_t setOrClear(intptr_t bits, int shift, intptr_t pred) {
+    intptr_t mask = 1 << shift;
+    if (pred) {
+        bits |= mask;
+    } else {
+        bits &= ~mask;
+    }
+    return bits;
+}
+
+void GrContext::resetStats() {
+    fGpu->resetStats();
+}
+
+const GrGpu::Stats& GrContext::getStats() const {
+    return fGpu->getStats();
+}
+
+void GrContext::printStats() const {
+    fGpu->printStats();
+}
+
+GrContext::GrContext(GrGpu* gpu) {
+    fGpu = gpu;
+    fGpu->ref();
+    fTextureCache = new GrTextureCache(MAX_TEXTURE_CACHE_COUNT,
+                                       MAX_TEXTURE_CACHE_BYTES);
+    fFontCache = new GrFontCache(fGpu);
+
+    fLastDrawCategory = kUnbuffered_DrawCategory;
+
+#if DEFER_TEXT_RENDERING || BATCH_RECT_TO_RECT
+    fDrawBufferVBAllocPool = 
+        new GrVertexBufferAllocPool(gpu, false,
+                                    DRAW_BUFFER_VBPOOL_BUFFER_SIZE,
+                                    DRAW_BUFFER_VBPOOL_PREALLOC_BUFFERS);
+    fDrawBufferIBAllocPool = 
+        new GrIndexBufferAllocPool(gpu, false,
+                                   DRAW_BUFFER_IBPOOL_BUFFER_SIZE, 
+                                   DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS);
+
+    fDrawBuffer = new GrInOrderDrawBuffer(fDrawBufferVBAllocPool,
+                                          fDrawBufferIBAllocPool);
+#else
+    fDrawBuffer = NULL;
+    fDrawBufferVBAllocPool = NULL;
+    fDrawBufferIBAllocPool = NULL;
+#endif
+
+#if BATCH_RECT_TO_RECT
+    fDrawBuffer->setQuadIndexBuffer(this->getQuadIndexBuffer());
+#endif
+    fPathRenderer = new GrDefaultPathRenderer(fGpu->supportsSingleStencilPassWinding());
+}
+
+bool GrContext::finalizeTextureKey(GrTextureKey* key,
+                                   const GrSamplerState& sampler) const {
+    uint32_t bits = 0;
+    uint16_t width = key->width();
+    uint16_t height = key->height();
+
+
+    if (!fGpu->npotTextureTileSupport()) {
+        bool isPow2 = GrIsPow2(width) && GrIsPow2(height);
+
+        bool tiled = (sampler.getWrapX() != GrSamplerState::kClamp_WrapMode) ||
+                     (sampler.getWrapY() != GrSamplerState::kClamp_WrapMode);
+
+        if (tiled && !isPow2) {
+            bits |= 1;
+            bits |= sampler.isFilter() ? 2 : 0;
+        }
+    }
+    key->finalize(bits);
+    return 0 != bits;
+}
+
+GrDrawTarget* GrContext::getTextTarget(const GrPaint& paint) {
+    GrDrawTarget* target;
+#if DEFER_TEXT_RENDERING
+    target = prepareToDraw(paint, kText_DrawCategory);
+#else
+    target = prepareToDraw(paint, kUnbuffered_DrawCategory);
+#endif
+    SetPaint(paint, target);
+    return target;
+}
+
+const GrIndexBuffer* GrContext::getQuadIndexBuffer() const {
+    return fGpu->getQuadIndexBuffer();
+}
index f531a6b..e128d35 100644 (file)
-/*\r
- Copyright 2010 Google Inc.\r
-\r
- Licensed under the Apache License, Version 2.0 (the "License");\r
- you may not use this file except in compliance with the License.\r
- You may obtain a copy of the License at\r
-\r
- http://www.apache.org/licenses/LICENSE-2.0\r
-\r
- Unless required by applicable law or agreed to in writing, software\r
- distributed under the License is distributed on an "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- See the License for the specific language governing permissions and\r
- limitations under the License.\r
- */\r
-\r
-#include "GrGLConfig.h"\r
-#include "GrTypes.h"\r
-#include <stdio.h>\r
-\r
-bool has_gl_extension(const char* ext) {\r
-    const char* glstr = (const char*) glGetString(GL_EXTENSIONS);\r
-\r
-    int extLength = strlen(ext);\r
-\r
-    while (true) {\r
-        int n = strcspn(glstr, " ");\r
-        if (n == extLength && 0 == strncmp(ext, glstr, n)) {\r
-            return true;\r
-        }\r
-        if (0 == glstr[n]) {\r
-            return false;\r
-        }\r
-        glstr += n+1;\r
-    }\r
-}\r
-\r
-void gl_version(int* major, int* minor) {\r
-    const char* v = (const char*) glGetString(GL_VERSION);\r
-    if (NULL == v) {\r
-        GrAssert(0);\r
-        *major = 0;\r
-        *minor = 0;\r
-        return;\r
-    }\r
-#if GR_SUPPORT_GLDESKTOP\r
-    int n = sscanf(v, "%d.%d", major, minor);\r
-    if (n != 2) {\r
-        GrAssert(0);\r
-        *major = 0;\r
-        *minor = 0;\r
-        return;\r
-    }\r
-#else\r
-    char profile[2];\r
-    int n = sscanf(v, "OpenGL ES-%c%c %d.%d", profile, profile+1, major, minor);\r
-    bool ok = 4 == n;\r
-    if (!ok) {\r
-        int n = sscanf(v, "OpenGL ES %d.%d", major, minor);\r
-        ok = 2 == n;\r
-    }\r
-    if (!ok) {\r
-        GrAssert(0);\r
-        *major = 0;\r
-        *minor = 0;\r
-        return;\r
-    }\r
-#endif\r
-}\r
-\r
-#if defined(GR_GL_PROC_ADDRESS_HEADER)\r
-    #include GR_GL_PROC_ADDRESS_HEADER\r
-#endif\r
-\r
-typedef void (*glProc)(void);\r
-\r
-#define GET_PROC(EXT_STRUCT, PROC_NAME) \\r
-    *(GrTCast<glProc*>(&(EXT_STRUCT-> PROC_NAME))) = (glProc)GR_GL_PROC_ADDRESS((gl ## PROC_NAME)); \\r
-    GrAssert(NULL != EXT_STRUCT-> PROC_NAME)\r
-\r
-#define GET_SUFFIX_PROC(EXT_STRUCT, PROC_NAME, SUFFIX) \\r
-    *(GrTCast<glProc*>(&(EXT_STRUCT-> PROC_NAME))) = (glProc)GR_GL_PROC_ADDRESS((gl ## PROC_NAME ## SUFFIX)); \\r
-    GrAssert(NULL != EXT_STRUCT-> PROC_NAME)\r
-\r
-extern void GrGLInitExtensions(GrGLExts* exts) {\r
-    exts->GenFramebuffers                   = NULL;\r
-    exts->BindFramebuffer                   = NULL;\r
-    exts->FramebufferTexture2D              = NULL;\r
-    exts->CheckFramebufferStatus            = NULL;\r
-    exts->DeleteFramebuffers                = NULL;\r
-    exts->RenderbufferStorage               = NULL;\r
-    exts->GenRenderbuffers                  = NULL;\r
-    exts->DeleteRenderbuffers               = NULL;\r
-    exts->FramebufferRenderbuffer           = NULL;\r
-    exts->BindRenderbuffer                  = NULL;\r
-    exts->RenderbufferStorageMultisample    = NULL;\r
-    exts->BlitFramebuffer                   = NULL;\r
-    exts->ResolveMultisampleFramebuffer     = NULL;\r
-    exts->FramebufferTexture2DMultisample   = NULL;\r
-    exts->MapBuffer                         = NULL;\r
-    exts->UnmapBuffer                       = NULL;\r
-\r
-    GLint major, minor;\r
-    gl_version(&major, &minor);\r
-\r
-    bool fboFound = false;\r
-#if GR_SUPPORT_GLDESKTOP\r
-    #if defined(GL_VERSION_3_0) && GL_VERSION_3_0\r
-    if (!fboFound && major >= 3) { // all of ARB_fbo is in 3.x\r
-        exts->GenFramebuffers                   = glGenFramebuffers;\r
-        exts->BindFramebuffer                   = glBindFramebuffer;\r
-        exts->FramebufferTexture2D              = glFramebufferTexture2D;\r
-        exts->CheckFramebufferStatus            = glCheckFramebufferStatus;\r
-        exts->DeleteFramebuffers                = glDeleteFramebuffers;\r
-        exts->RenderbufferStorage               = glRenderbufferStorage;\r
-        exts->GenRenderbuffers                  = glGenRenderbuffers;\r
-        exts->DeleteRenderbuffers               = glDeleteRenderbuffers;\r
-        exts->FramebufferRenderbuffer           = glFramebufferRenderbuffer;\r
-        exts->BindRenderbuffer                  = glBindRenderbuffer;\r
-        exts->RenderbufferStorageMultisample    = glRenderbufferStorageMultisample;\r
-        exts->BlitFramebuffer                   = glBlitFramebuffer;\r
-        fboFound = true;\r
-    }\r
-    #endif\r
-    #if GL_ARB_framebuffer_object\r
-    if (!fboFound && has_gl_extension("GL_ARB_framebuffer_object")) {\r
-        // GL_ARB_framebuffer_object doesn't use ARB suffix.\r
-        GET_PROC(exts, GenFramebuffers);\r
-        GET_PROC(exts, BindFramebuffer);\r
-        GET_PROC(exts, FramebufferTexture2D);\r
-        GET_PROC(exts, CheckFramebufferStatus);\r
-        GET_PROC(exts, DeleteFramebuffers);\r
-        GET_PROC(exts, RenderbufferStorage);\r
-        GET_PROC(exts, GenRenderbuffers);\r
-        GET_PROC(exts, DeleteRenderbuffers);\r
-        GET_PROC(exts, FramebufferRenderbuffer);\r
-        GET_PROC(exts, BindRenderbuffer);\r
-        GET_PROC(exts, RenderbufferStorageMultisample);\r
-        GET_PROC(exts, BlitFramebuffer);\r
-        fboFound = true;\r
-    }\r
-    #endif\r
-    // Mac doesn't declare prototypes for EXT FBO extensions\r
-    #if GL_EXT_framebuffer_object && !GR_MAC_BUILD\r
-    if (!fboFound && has_gl_extension("GL_EXT_framebuffer_object")) {\r
-        GET_SUFFIX_PROC(exts, GenFramebuffers, EXT);\r
-        GET_SUFFIX_PROC(exts, BindFramebuffer, EXT);\r
-        GET_SUFFIX_PROC(exts, FramebufferTexture2D, EXT);\r
-        GET_SUFFIX_PROC(exts, CheckFramebufferStatus, EXT);\r
-        GET_SUFFIX_PROC(exts, DeleteFramebuffers, EXT);\r
-        GET_SUFFIX_PROC(exts, RenderbufferStorage, EXT);\r
-        GET_SUFFIX_PROC(exts, GenRenderbuffers, EXT);\r
-        GET_SUFFIX_PROC(exts, DeleteRenderbuffers, EXT);\r
-        GET_SUFFIX_PROC(exts, FramebufferRenderbuffer, EXT);\r
-        GET_SUFFIX_PROC(exts, BindRenderbuffer, EXT);\r
-        fboFound = true;\r
-        // check for fbo ms and fbo blit\r
-        #if GL_EXT_framebuffer_multisample\r
-        if (has_gl_extension("GL_EXT_framebuffer_multisample")) {\r
-            GET_SUFFIX_PROC(exts, RenderbufferStorageMultisample, EXT);\r
-        }\r
-        #endif\r
-        #if GL_EXT_framebuffer_blit\r
-        if (has_gl_extension("GL_EXT_framebuffer_blit")) {\r
-            GET_SUFFIX_PROC(exts, BlitFramebuffer, EXT);\r
-        }\r
-        #endif\r
-    }\r
-    #endif\r
-    if (!fboFound) {\r
-        // we require some form of FBO\r
-        GrAssert(!"No FBOs supported?");\r
-    }\r
-    // we assume we have at least GL 1.5 or higher (VBOs introduced in 1.5)\r
-    exts->MapBuffer     = glMapBuffer;\r
-    exts->UnmapBuffer   = glUnmapBuffer;\r
-#else // !GR_SUPPORT_GLDESKTOP\r
-    #if GR_SUPPORT_GLES2\r
-    if (!fboFound && major >= 2) {// ES 2.0 supports FBO\r
-        exts->GenFramebuffers                   = glGenFramebuffers;\r
-        exts->BindFramebuffer                   = glBindFramebuffer;\r
-        exts->FramebufferTexture2D              = glFramebufferTexture2D;\r
-        exts->CheckFramebufferStatus            = glCheckFramebufferStatus;\r
-        exts->DeleteFramebuffers                = glDeleteFramebuffers;\r
-        exts->RenderbufferStorage               = glRenderbufferStorage;\r
-        exts->GenRenderbuffers                  = glGenRenderbuffers;\r
-        exts->DeleteRenderbuffers               = glDeleteRenderbuffers;\r
-        exts->FramebufferRenderbuffer           = glFramebufferRenderbuffer;\r
-        exts->BindRenderbuffer                  = glBindRenderbuffer;\r
-        fboFound = true;\r
-    }\r
-    #endif\r
-    #if GL_OES_framebuffer_object\r
-    if (!fboFound && has_gl_extension("GL_OES_framebuffer_object")) {\r
-        GET_SUFFIX_PROC(exts, GenFramebuffers, OES);\r
-        GET_SUFFIX_PROC(exts, BindFramebuffer, OES);\r
-        GET_SUFFIX_PROC(exts, FramebufferTexture2D, OES);\r
-        GET_SUFFIX_PROC(exts, CheckFramebufferStatus, OES);\r
-        GET_SUFFIX_PROC(exts, DeleteFramebuffers, OES);\r
-        GET_SUFFIX_PROC(exts, RenderbufferStorage, OES);\r
-        GET_SUFFIX_PROC(exts, GenRenderbuffers, OES);\r
-        GET_SUFFIX_PROC(exts, DeleteRenderbuffers, OES);\r
-        GET_SUFFIX_PROC(exts, FramebufferRenderbuffer, OES);\r
-        GET_SUFFIX_PROC(exts, BindRenderbuffer, OES);\r
-    }\r
-    #endif\r
-\r
-    if (!fboFound) {\r
-        // we require some form of FBO\r
-        GrAssert(!"No FBOs supported?");\r
-    }\r
-\r
-    #if GL_APPLE_framebuffer_multisample\r
-    if (has_gl_extension("GL_APPLE_framebuffer_multisample")) {\r
-        GET_SUFFIX_PROC(exts, ResolveMultisampleFramebuffer, APPLE);\r
-    }\r
-    #endif\r
-\r
-    #if GL_IMG_multisampled_render_to_texture\r
-    if (has_gl_extension("GL_IMG_multisampled_render_to_texture")) {\r
-        GET_SUFFIX_PROC(exts, FramebufferTexture2DMultisample, IMG);\r
-    }\r
-    #endif\r
-\r
-    #if GL_OES_mapbuffer\r
-    if (has_gl_extension("GL_OES_mapbuffer")) {\r
-        GET_SUFFIX_PROC(exts, MapBuffer, OES);\r
-        GET_SUFFIX_PROC(exts, UnmapBuffer, OES);\r
-    }\r
-    #endif\r
-#endif // !GR_SUPPORT_GLDESKTOP\r
-}\r
-\r
-\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-void GrGLCheckErr(const char* location, const char* call) {\r
-    uint32_t err =  glGetError();\r
-    if (GL_NO_ERROR != err) {\r
-        GrPrintf("---- glGetError %x", err);\r
-        if (NULL != location) {\r
-            GrPrintf(" at\n\t%s", location);\r
-        }\r
-        if (NULL != call) {\r
-            GrPrintf("\n\t\t%s", call);\r
-        }\r
-        GrPrintf("\n");\r
-    }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-bool gLogCallsGL = !!(GR_GL_LOG_CALLS_START);\r
-\r
-bool gCheckErrorGL = !!(GR_GL_CHECK_ERROR_START);\r
+/*
+ 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.
+ */
+
+#include "GrGLConfig.h"
+#include "GrTypes.h"
+#include <stdio.h>
+
+bool has_gl_extension(const char* ext) {
+    const char* glstr = (const char*) glGetString(GL_EXTENSIONS);
+
+    int extLength = strlen(ext);
+
+    while (true) {
+        int n = strcspn(glstr, " ");
+        if (n == extLength && 0 == strncmp(ext, glstr, n)) {
+            return true;
+        }
+        if (0 == glstr[n]) {
+            return false;
+        }
+        glstr += n+1;
+    }
+}
+
+void gl_version(int* major, int* minor) {
+    const char* v = (const char*) glGetString(GL_VERSION);
+    if (NULL == v) {
+        GrAssert(0);
+        *major = 0;
+        *minor = 0;
+        return;
+    }
+#if GR_SUPPORT_GLDESKTOP
+    int n = sscanf(v, "%d.%d", major, minor);
+    if (n != 2) {
+        GrAssert(0);
+        *major = 0;
+        *minor = 0;
+        return;
+    }
+#else
+    char profile[2];
+    int n = sscanf(v, "OpenGL ES-%c%c %d.%d", profile, profile+1, major, minor);
+    bool ok = 4 == n;
+    if (!ok) {
+        int n = sscanf(v, "OpenGL ES %d.%d", major, minor);
+        ok = 2 == n;
+    }
+    if (!ok) {
+        GrAssert(0);
+        *major = 0;
+        *minor = 0;
+        return;
+    }
+#endif
+}
+
+#if defined(GR_GL_PROC_ADDRESS_HEADER)
+    #include GR_GL_PROC_ADDRESS_HEADER
+#endif
+
+typedef void (*glProc)(void);
+
+#define GET_PROC(EXT_STRUCT, PROC_NAME) \
+    *(GrTCast<glProc*>(&(EXT_STRUCT-> PROC_NAME))) = (glProc)GR_GL_PROC_ADDRESS((gl ## PROC_NAME)); \
+    GrAssert(NULL != EXT_STRUCT-> PROC_NAME)
+
+#define GET_SUFFIX_PROC(EXT_STRUCT, PROC_NAME, SUFFIX) \
+    *(GrTCast<glProc*>(&(EXT_STRUCT-> PROC_NAME))) = (glProc)GR_GL_PROC_ADDRESS((gl ## PROC_NAME ## SUFFIX)); \
+    GrAssert(NULL != EXT_STRUCT-> PROC_NAME)
+
+extern void GrGLInitExtensions(GrGLExts* exts) {
+    exts->GenFramebuffers                   = NULL;
+    exts->BindFramebuffer                   = NULL;
+    exts->FramebufferTexture2D              = NULL;
+    exts->CheckFramebufferStatus            = NULL;
+    exts->DeleteFramebuffers                = NULL;
+    exts->RenderbufferStorage               = NULL;
+    exts->GenRenderbuffers                  = NULL;
+    exts->DeleteRenderbuffers               = NULL;
+    exts->FramebufferRenderbuffer           = NULL;
+    exts->BindRenderbuffer                  = NULL;
+    exts->RenderbufferStorageMultisample    = NULL;
+    exts->BlitFramebuffer                   = NULL;
+    exts->ResolveMultisampleFramebuffer     = NULL;
+    exts->FramebufferTexture2DMultisample   = NULL;
+    exts->MapBuffer                         = NULL;
+    exts->UnmapBuffer                       = NULL;
+
+    GLint major, minor;
+    gl_version(&major, &minor);
+
+    bool fboFound = false;
+#if GR_SUPPORT_GLDESKTOP
+    #if defined(GL_VERSION_3_0) && GL_VERSION_3_0
+    if (!fboFound && major >= 3) { // all of ARB_fbo is in 3.x
+        exts->GenFramebuffers                   = glGenFramebuffers;
+        exts->BindFramebuffer                   = glBindFramebuffer;
+        exts->FramebufferTexture2D              = glFramebufferTexture2D;
+        exts->CheckFramebufferStatus            = glCheckFramebufferStatus;
+        exts->DeleteFramebuffers                = glDeleteFramebuffers;
+        exts->RenderbufferStorage               = glRenderbufferStorage;
+        exts->GenRenderbuffers                  = glGenRenderbuffers;
+        exts->DeleteRenderbuffers               = glDeleteRenderbuffers;
+        exts->FramebufferRenderbuffer           = glFramebufferRenderbuffer;
+        exts->BindRenderbuffer                  = glBindRenderbuffer;
+        exts->RenderbufferStorageMultisample    = glRenderbufferStorageMultisample;
+        exts->BlitFramebuffer                   = glBlitFramebuffer;
+        fboFound = true;
+    }
+    #endif
+    #if GL_ARB_framebuffer_object
+    if (!fboFound && has_gl_extension("GL_ARB_framebuffer_object")) {
+        // GL_ARB_framebuffer_object doesn't use ARB suffix.
+        GET_PROC(exts, GenFramebuffers);
+        GET_PROC(exts, BindFramebuffer);
+        GET_PROC(exts, FramebufferTexture2D);
+        GET_PROC(exts, CheckFramebufferStatus);
+        GET_PROC(exts, DeleteFramebuffers);
+        GET_PROC(exts, RenderbufferStorage);
+        GET_PROC(exts, GenRenderbuffers);
+        GET_PROC(exts, DeleteRenderbuffers);
+        GET_PROC(exts, FramebufferRenderbuffer);
+        GET_PROC(exts, BindRenderbuffer);
+        GET_PROC(exts, RenderbufferStorageMultisample);
+        GET_PROC(exts, BlitFramebuffer);
+        fboFound = true;
+    }
+    #endif
+    // Mac doesn't declare prototypes for EXT FBO extensions
+    #if GL_EXT_framebuffer_object && !GR_MAC_BUILD
+    if (!fboFound && has_gl_extension("GL_EXT_framebuffer_object")) {
+        GET_SUFFIX_PROC(exts, GenFramebuffers, EXT);
+        GET_SUFFIX_PROC(exts, BindFramebuffer, EXT);
+        GET_SUFFIX_PROC(exts, FramebufferTexture2D, EXT);
+        GET_SUFFIX_PROC(exts, CheckFramebufferStatus, EXT);
+        GET_SUFFIX_PROC(exts, DeleteFramebuffers, EXT);
+        GET_SUFFIX_PROC(exts, RenderbufferStorage, EXT);
+        GET_SUFFIX_PROC(exts, GenRenderbuffers, EXT);
+        GET_SUFFIX_PROC(exts, DeleteRenderbuffers, EXT);
+        GET_SUFFIX_PROC(exts, FramebufferRenderbuffer, EXT);
+        GET_SUFFIX_PROC(exts, BindRenderbuffer, EXT);
+        fboFound = true;
+        // check for fbo ms and fbo blit
+        #if GL_EXT_framebuffer_multisample
+        if (has_gl_extension("GL_EXT_framebuffer_multisample")) {
+            GET_SUFFIX_PROC(exts, RenderbufferStorageMultisample, EXT);
+        }
+        #endif
+        #if GL_EXT_framebuffer_blit
+        if (has_gl_extension("GL_EXT_framebuffer_blit")) {
+            GET_SUFFIX_PROC(exts, BlitFramebuffer, EXT);
+        }
+        #endif
+    }
+    #endif
+    if (!fboFound) {
+        // we require some form of FBO
+        GrAssert(!"No FBOs supported?");
+    }
+    // we assume we have at least GL 1.5 or higher (VBOs introduced in 1.5)
+    exts->MapBuffer     = glMapBuffer;
+    exts->UnmapBuffer   = glUnmapBuffer;
+#else // !GR_SUPPORT_GLDESKTOP
+    #if GR_SUPPORT_GLES2
+    if (!fboFound && major >= 2) {// ES 2.0 supports FBO
+        exts->GenFramebuffers                   = glGenFramebuffers;
+        exts->BindFramebuffer                   = glBindFramebuffer;
+        exts->FramebufferTexture2D              = glFramebufferTexture2D;
+        exts->CheckFramebufferStatus            = glCheckFramebufferStatus;
+        exts->DeleteFramebuffers                = glDeleteFramebuffers;
+        exts->RenderbufferStorage               = glRenderbufferStorage;
+        exts->GenRenderbuffers                  = glGenRenderbuffers;
+        exts->DeleteRenderbuffers               = glDeleteRenderbuffers;
+        exts->FramebufferRenderbuffer           = glFramebufferRenderbuffer;
+        exts->BindRenderbuffer                  = glBindRenderbuffer;
+        fboFound = true;
+    }
+    #endif
+    #if GL_OES_framebuffer_object
+    if (!fboFound && has_gl_extension("GL_OES_framebuffer_object")) {
+        GET_SUFFIX_PROC(exts, GenFramebuffers, OES);
+        GET_SUFFIX_PROC(exts, BindFramebuffer, OES);
+        GET_SUFFIX_PROC(exts, FramebufferTexture2D, OES);
+        GET_SUFFIX_PROC(exts, CheckFramebufferStatus, OES);
+        GET_SUFFIX_PROC(exts, DeleteFramebuffers, OES);
+        GET_SUFFIX_PROC(exts, RenderbufferStorage, OES);
+        GET_SUFFIX_PROC(exts, GenRenderbuffers, OES);
+        GET_SUFFIX_PROC(exts, DeleteRenderbuffers, OES);
+        GET_SUFFIX_PROC(exts, FramebufferRenderbuffer, OES);
+        GET_SUFFIX_PROC(exts, BindRenderbuffer, OES);
+    }
+    #endif
+
+    if (!fboFound) {
+        // we require some form of FBO
+        GrAssert(!"No FBOs supported?");
+    }
+
+    #if GL_APPLE_framebuffer_multisample
+    if (has_gl_extension("GL_APPLE_framebuffer_multisample")) {
+        GET_SUFFIX_PROC(exts, ResolveMultisampleFramebuffer, APPLE);
+    }
+    #endif
+
+    #if GL_IMG_multisampled_render_to_texture
+    if (has_gl_extension("GL_IMG_multisampled_render_to_texture")) {
+        GET_SUFFIX_PROC(exts, FramebufferTexture2DMultisample, IMG);
+    }
+    #endif
+
+    #if GL_OES_mapbuffer
+    if (has_gl_extension("GL_OES_mapbuffer")) {
+        GET_SUFFIX_PROC(exts, MapBuffer, OES);
+        GET_SUFFIX_PROC(exts, UnmapBuffer, OES);
+    }
+    #endif
+#endif // !GR_SUPPORT_GLDESKTOP
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+void GrGLCheckErr(const char* location, const char* call) {
+    uint32_t err =  glGetError();
+    if (GL_NO_ERROR != err) {
+        GrPrintf("---- glGetError %x", err);
+        if (NULL != location) {
+            GrPrintf(" at\n\t%s", location);
+        }
+        if (NULL != call) {
+            GrPrintf("\n\t\t%s", call);
+        }
+        GrPrintf("\n");
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool gLogCallsGL = !!(GR_GL_LOG_CALLS_START);
+
+bool gCheckErrorGL = !!(GR_GL_CHECK_ERROR_START);
index ee20679..0a2d1b2 100644 (file)
-/*\r
-    Copyright 2010 Google Inc.\r
-\r
-    Licensed under the Apache License, Version 2.0 (the "License");\r
-    you may not use this file except in compliance with the License.\r
-    You may obtain a copy of the License at\r
-\r
-         http://www.apache.org/licenses/LICENSE-2.0\r
-\r
-    Unless required by applicable law or agreed to in writing, software\r
-    distributed under the License is distributed on an "AS IS" BASIS,\r
-    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
-    See the License for the specific language governing permissions and\r
-    limitations under the License.\r
- */\r
-\r
-\r
-#include "GrMatrix.h"\r
-#include "GrRect.h"\r
-#include <stddef.h>\r
-\r
-#if GR_SCALAR_IS_FLOAT\r
-    const GrScalar GrMatrix::gRESCALE(GR_Scalar1);\r
-#else\r
-    GR_STATIC_ASSERT(GR_SCALAR_IS_FIXED);\r
-    // fixed point isn't supported right now\r
-    GR_STATIC_ASSERT(false);\r
-const GrScalar GrMatrix::gRESCALE(1 << 30);\r
-#endif\r
-\r
-const GrMatrix::MapProc GrMatrix::gMapProcs[] = {\r
-// Scales are not both zero\r
-    &GrMatrix::mapIdentity,\r
-    &GrMatrix::mapScale,\r
-    &GrMatrix::mapTranslate,\r
-    &GrMatrix::mapScaleAndTranslate,\r
-    &GrMatrix::mapSkew,\r
-    &GrMatrix::mapScaleAndSkew,\r
-    &GrMatrix::mapSkewAndTranslate,\r
-    &GrMatrix::mapNonPerspective,\r
-    // no optimizations for perspective matrices\r
-    &GrMatrix::mapPerspective,\r
-    &GrMatrix::mapPerspective,\r
-    &GrMatrix::mapPerspective,\r
-    &GrMatrix::mapPerspective,\r
-    &GrMatrix::mapPerspective,\r
-    &GrMatrix::mapPerspective,\r
-    &GrMatrix::mapPerspective,\r
-    &GrMatrix::mapPerspective,\r
-\r
-// Scales are zero (every other is invalid because kScale_TypeBit must be set if\r
-// kZeroScale_TypeBit is set)\r
-    &GrMatrix::mapInvalid,\r
-    &GrMatrix::mapZero,\r
-    &GrMatrix::mapInvalid,\r
-    &GrMatrix::mapSetToTranslate,\r
-    &GrMatrix::mapInvalid,\r
-    &GrMatrix::mapSwappedScale,\r
-    &GrMatrix::mapInvalid,\r
-    &GrMatrix::mapSwappedScaleAndTranslate,\r
-\r
-    // no optimizations for perspective matrices\r
-    &GrMatrix::mapInvalid,\r
-    &GrMatrix::mapZero,\r
-    &GrMatrix::mapInvalid,\r
-    &GrMatrix::mapPerspective,\r
-    &GrMatrix::mapInvalid,\r
-    &GrMatrix::mapPerspective,\r
-    &GrMatrix::mapInvalid,\r
-    &GrMatrix::mapPerspective,\r
-};\r
-\r
-void GrMatrix::setIdentity() {\r
-    fM[0] = GR_Scalar1; fM[1] = 0;          fM[2] = 0;\r
-    fM[3] = 0;          fM[4] = GR_Scalar1; fM[5] = 0;\r
-    fM[6] = 0;          fM[7] = 0;          fM[8] = gRESCALE;\r
-    fTypeMask = 0;\r
-}\r
-\r
-void GrMatrix::setTranslate(GrScalar dx, GrScalar dy) {\r
-    fM[0] = GR_Scalar1; fM[1] = 0;          fM[2] = dx;\r
-    fM[3] = 0;          fM[4] = GR_Scalar1; fM[5] = dy;\r
-    fM[6] = 0;          fM[7] = 0;          fM[8] = gRESCALE;\r
-    fTypeMask = (0 != dx || 0 != dy) ? kTranslate_TypeBit : 0;\r
-}\r
-\r
-void GrMatrix::setScale(GrScalar sx, GrScalar sy) {\r
-    fM[0] = sx; fM[1] = 0;  fM[2] = 0;\r
-    fM[3] = 0;  fM[4] = sy; fM[5] = 0;\r
-    fM[6] = 0;  fM[7] = 0;  fM[8] = gRESCALE;\r
-    fTypeMask = (GR_Scalar1 != sx || GR_Scalar1 != sy) ? kScale_TypeBit : 0;\r
-}\r
-\r
-void GrMatrix::setSkew(GrScalar skx, GrScalar sky) {\r
-    fM[0] = GR_Scalar1; fM[1] = skx;        fM[2] = 0;\r
-    fM[3] = sky;        fM[4] = GR_Scalar1; fM[5] = 0;\r
-    fM[6] = 0;          fM[7] = 0;          fM[8] = gRESCALE;\r
-    fTypeMask = (0 != skx || 0 != sky) ? kSkew_TypeBit : 0;\r
-}\r
-\r
-void GrMatrix::setConcat(const GrMatrix& a, const GrMatrix& b) {\r
-    if (a.isIdentity()) {\r
-        if (this != &b) {\r
-            for (int i = 0; i < 9; ++i) {\r
-                fM[i] = b.fM[i];\r
-            }\r
-            fTypeMask = b.fTypeMask;\r
-        }\r
-        return;\r
-    }\r
-\r
-    if (b.isIdentity()) {\r
-        GrAssert(!a.isIdentity());\r
-        if (this != &a) {\r
-            for (int i = 0; i < 9; ++i) {\r
-                    fM[i] = a.fM[i];\r
-            }\r
-            fTypeMask = a.fTypeMask;\r
-        }\r
-        return;\r
-    }\r
-\r
-    // a and/or b could be this\r
-    GrMatrix tmp;\r
-\r
-    // could do more optimizations based on type bits. Hopefully this call is\r
-    // low frequency.\r
-    // TODO: make this work for fixed point\r
-    if (!((b.fTypeMask | a.fTypeMask) & kPerspective_TypeBit)) {\r
-        tmp.fM[0] = a.fM[0] * b.fM[0] + a.fM[1] * b.fM[3];\r
-        tmp.fM[1] = a.fM[0] * b.fM[1] + a.fM[1] * b.fM[4];\r
-        tmp.fM[2] = a.fM[0] * b.fM[2] + a.fM[1] * b.fM[5] + a.fM[2] * gRESCALE;\r
-\r
-        tmp.fM[3] = a.fM[3] * b.fM[0] + a.fM[4] * b.fM[3];\r
-        tmp.fM[4] = a.fM[3] * b.fM[1] + a.fM[4] * b.fM[4];\r
-        tmp.fM[5] = a.fM[3] * b.fM[2] + a.fM[4] * b.fM[5] + a.fM[5] * gRESCALE;\r
-\r
-        tmp.fM[6] = 0;\r
-        tmp.fM[7] = 0;\r
-        tmp.fM[8] = gRESCALE * gRESCALE;\r
-    } else {\r
-        tmp.fM[0] = a.fM[0] * b.fM[0] + a.fM[1] * b.fM[3] + a.fM[2] * b.fM[6];\r
-        tmp.fM[1] = a.fM[0] * b.fM[1] + a.fM[1] * b.fM[4] + a.fM[2] * b.fM[7];\r
-        tmp.fM[2] = a.fM[0] * b.fM[2] + a.fM[1] * b.fM[5] + a.fM[2] * b.fM[8];\r
-\r
-        tmp.fM[3] = a.fM[3] * b.fM[0] + a.fM[4] * b.fM[3] + a.fM[5] * b.fM[6];\r
-        tmp.fM[4] = a.fM[3] * b.fM[1] + a.fM[4] * b.fM[4] + a.fM[5] * b.fM[7];\r
-        tmp.fM[5] = a.fM[3] * b.fM[2] + a.fM[4] * b.fM[5] + a.fM[5] * b.fM[8];\r
-\r
-        tmp.fM[6] = a.fM[6] * b.fM[0] + a.fM[7] * b.fM[3] + a.fM[8] * b.fM[6];\r
-        tmp.fM[7] = a.fM[6] * b.fM[1] + a.fM[7] * b.fM[4] + a.fM[8] * b.fM[7];\r
-        tmp.fM[8] = a.fM[6] * b.fM[2] + a.fM[7] * b.fM[5] + a.fM[8] * b.fM[8];\r
-    }\r
-    *this = tmp;\r
-    this->computeTypeMask();\r
-}\r
-\r
-void GrMatrix::preConcat(const GrMatrix& m) {\r
-    setConcat(*this, m);\r
-}\r
-\r
-void GrMatrix::postConcat(const GrMatrix& m) {\r
-    setConcat(m, *this);\r
-}\r
-\r
-double GrMatrix::determinant() const {\r
-    if (fTypeMask & kPerspective_TypeBit) {\r
-        return  fM[0]*((double)fM[4]*fM[8] - (double)fM[5]*fM[7]) +\r
-                fM[1]*((double)fM[5]*fM[6] - (double)fM[3]*fM[8]) +\r
-                fM[2]*((double)fM[3]*fM[7] - (double)fM[4]*fM[6]);\r
-    } else {\r
-        return (double)fM[0]*fM[4]*gRESCALE -\r
-               (double)fM[1]*fM[3]*gRESCALE;\r
-    }\r
-}\r
-\r
-bool GrMatrix::invert(GrMatrix* inverted) const {\r
-\r
-    if (isIdentity()) {\r
-        if (inverted != this) {\r
-            inverted->setIdentity();\r
-        }\r
-        return true;\r
-    }\r
-    static const double MIN_DETERMINANT_SQUARED = 1.e-16;\r
-\r
-    // could do more optimizations based on type bits. Hopefully this call is\r
-    // low frequency.\r
-\r
-    double det = determinant();\r
-\r
-    // check if we can't be inverted\r
-    if (det*det <= MIN_DETERMINANT_SQUARED) {\r
-        return false;\r
-    } else if (NULL == inverted) {\r
-        return true;\r
-    }\r
-\r
-    double t[9];\r
-\r
-    if (fTypeMask & kPerspective_TypeBit) {\r
-        t[0] = ((double)fM[4]*fM[8] - (double)fM[5]*fM[7]);\r
-        t[1] = ((double)fM[2]*fM[7] - (double)fM[1]*fM[8]);\r
-        t[2] = ((double)fM[1]*fM[5] - (double)fM[2]*fM[4]);\r
-        t[3] = ((double)fM[5]*fM[6] - (double)fM[3]*fM[8]);\r
-        t[4] = ((double)fM[0]*fM[8] - (double)fM[2]*fM[6]);\r
-        t[5] = ((double)fM[2]*fM[3] - (double)fM[0]*fM[5]);\r
-        t[6] = ((double)fM[3]*fM[7] - (double)fM[4]*fM[6]);\r
-        t[7] = ((double)fM[1]*fM[6] - (double)fM[0]*fM[7]);\r
-        t[8] = ((double)fM[0]*fM[4] - (double)fM[1]*fM[3]);\r
-        det = 1.0 / det;\r
-        for (int i = 0; i < 9; ++i) {\r
-            inverted->fM[i] = (GrScalar)(t[i] * det);\r
-        }\r
-    } else {\r
-        t[0] =  (double)fM[4]*gRESCALE;\r
-        t[1] = -(double)fM[1]*gRESCALE;\r
-        t[2] =  (double)fM[1]*fM[5] - (double)fM[2]*fM[4];\r
-        t[3] = -(double)fM[3]*gRESCALE;\r
-        t[4] =  (double)fM[0]*gRESCALE;\r
-        t[5] =  (double)fM[2]*fM[3] - (double)fM[0]*fM[5];\r
-        //t[6] = 0.0;\r
-        //t[7] = 0.0;\r
-        t[8] = (double)fM[0]*fM[4] - (double)fM[1]*fM[3];\r
-        det = 1.0 / det;\r
-        for (int i = 0; i < 6; ++i) {\r
-            inverted->fM[i] = (GrScalar)(t[i] * det);\r
-        }\r
-        inverted->fM[6] = 0;\r
-        inverted->fM[7] = 0;\r
-        inverted->fM[8] = (GrScalar)(t[8] * det);\r
-    }\r
-    inverted->computeTypeMask();\r
-    return true;\r
-}\r
-\r
-void GrMatrix::mapRect(GrRect* dst, const GrRect& src) const {\r
-    GrPoint srcPts[4], dstPts[4];\r
-    srcPts[0].set(src.fLeft, src.fTop);\r
-    srcPts[1].set(src.fRight, src.fTop);\r
-    srcPts[2].set(src.fRight, src.fBottom);\r
-    srcPts[3].set(src.fLeft, src.fBottom);\r
-    this->mapPoints(dstPts, srcPts, 4);\r
-    dst->setBounds(dstPts, 4);\r
-}\r
-\r
-bool GrMatrix::hasPerspective() const {\r
-    GrAssert(!!(kPerspective_TypeBit & fTypeMask) ==\r
-             (fM[kPersp0] != 0 || fM[kPersp1] != 0 || fM[kPersp2] != gRESCALE));\r
-    return 0 != (kPerspective_TypeBit & fTypeMask);\r
-}\r
-\r
-bool GrMatrix::isIdentity() const {\r
-    GrAssert((0 == fTypeMask) ==\r
-             (GR_Scalar1 == fM[kScaleX] && 0          == fM[kSkewX]  && 0          == fM[kTransX] &&\r
-              0          == fM[kSkewY]  && GR_Scalar1 == fM[kScaleY] && 0          == fM[kTransY] &&\r
-              0          == fM[kPersp0] && 0          == fM[kPersp1] && gRESCALE == fM[kPersp2]));\r
-    return (0 == fTypeMask);\r
-}\r
-\r
-\r
-GrScalar GrMatrix::getMaxStretch() const {\r
-\r
-    if (fTypeMask & kPerspective_TypeBit) {\r
-        return -GR_Scalar1;\r
-    }\r
-\r
-    GrScalar stretch;\r
-\r
-    if (isIdentity()) {\r
-        stretch = GR_Scalar1;\r
-    } else if (!(fTypeMask & kSkew_TypeBit)) {\r
-        stretch = GrMax(GrScalarAbs(fM[kScaleX]), GrScalarAbs(fM[kScaleY]));\r
-    } else if (fTypeMask & kZeroScale_TypeBit) {\r
-        stretch = GrMax(GrScalarAbs(fM[kSkewX]), GrScalarAbs(fM[kSkewY]));\r
-    } else {\r
-        // ignore the translation part of the matrix, just look at 2x2 portion.\r
-        // compute singular values, take largest abs value.\r
-        // [a b; b c] = A^T*A\r
-        GrScalar a = GrMul(fM[kScaleX], fM[kScaleX]) + GrMul(fM[kSkewY],  fM[kSkewY]);\r
-        GrScalar b = GrMul(fM[kScaleX], fM[kSkewX]) +  GrMul(fM[kScaleY], fM[kSkewY]);\r
-        GrScalar c = GrMul(fM[kSkewX],  fM[kSkewX]) +  GrMul(fM[kScaleY], fM[kScaleY]);\r
-        // eigenvalues of A^T*A are the squared singular values of A.\r
-        // characteristic equation is det((A^T*A) - l*I) = 0\r
-        // l^2 - (a + c)l + (ac-b^2)\r
-        // solve using quadratic equation (divisor is non-zero since l^2 has 1 coeff\r
-        // and roots are guaraunteed to be pos and real).\r
-        GrScalar largerRoot;\r
-        GrScalar bSqd = GrMul(b,b);\r
-        // TODO: fixed point tolerance value.\r
-        if (bSqd < 1e-10) { // will be true if upper left 2x2 is orthogonal, which is common, so save some math\r
-            largerRoot = GrMax(a, c);\r
-        } else {\r
-            GrScalar aminusc = a - c;\r
-            GrScalar apluscdiv2 = (a + c) / 2;\r
-            GrScalar x = sqrtf(GrMul(aminusc,aminusc) + GrMul(4,(bSqd))) / 2;\r
-            largerRoot = apluscdiv2 + x;\r
-        }\r
-\r
-        stretch = sqrtf(largerRoot);\r
-    }\r
-#if GR_DEBUG && 0\r
-    // test a bunch of vectors. None should be scaled by more than stretch\r
-    // (modulo some error) and we should find a vector that is scaled by almost\r
-    // stretch.\r
-    GrPoint pt;\r
-    GrScalar max = 0;\r
-    for (int i = 0; i < 1000; ++i) {\r
-        GrScalar x = (float)rand() / RAND_MAX;\r
-        GrScalar y = sqrtf(1 - (x*x));\r
-        pt.fX = fM[kScaleX]*x + fM[kSkewX]*y;\r
-        pt.fY = fM[kSkewY]*x + fM[kScaleY]*y;\r
-        GrScalar d = pt.distanceToOrigin();\r
-        GrAssert(d <= (1.0001 * stretch));\r
-        max = GrMax(max, pt.distanceToOrigin());\r
-    }\r
-    GrAssert((stretch - max) < .05*stretch);\r
-#endif\r
-    return stretch;\r
-}\r
-\r
-bool GrMatrix::operator == (const GrMatrix& m) const {\r
-    if (fTypeMask != m.fTypeMask) {\r
-        return false;\r
-    }\r
-    if (!fTypeMask) {\r
-        return true;\r
-    }\r
-    for (int i = 0; i < 9; ++i) {\r
-        if (m.fM[i] != fM[i]) {\r
-            return false;\r
-        }\r
-    }\r
-    return true;\r
-}\r
-\r
-bool GrMatrix::operator != (const GrMatrix& m) const {\r
-    return !(*this == m);\r
-}\r
-\r
-////////////////////////////////////////////////////////////////////////////////\r
-// Matrix transformation procs\r
-//////\r
-\r
-void GrMatrix::mapIdentity(GrPoint* dst, const GrPoint* src, uint32_t count) const {\r
-    if (src != dst) {\r
-        for (uint32_t i = 0; i < count; ++i) {\r
-            dst[i] = src[i];\r
-        }\r
-    }\r
-}\r
-\r
-void GrMatrix::mapScale(GrPoint* dst, const GrPoint* src, uint32_t count) const {\r
-    for (uint32_t i = 0; i < count; ++i) {\r
-        dst[i].fX = GrMul(src[i].fX, fM[kScaleX]);\r
-        dst[i].fY = GrMul(src[i].fY, fM[kScaleY]);\r
-    }\r
-}\r
-\r
-\r
-void GrMatrix::mapTranslate(GrPoint* dst, const GrPoint* src, uint32_t count) const {\r
-    for (uint32_t i = 0; i < count; ++i) {\r
-        dst[i].fX = src[i].fX + fM[kTransX];\r
-        dst[i].fY = src[i].fY + fM[kTransY];\r
-    }\r
-}\r
-\r
-void GrMatrix::mapScaleAndTranslate(GrPoint* dst, const GrPoint* src, uint32_t count) const {\r
-    for (uint32_t i = 0; i < count; ++i) {\r
-        dst[i].fX = GrMul(src[i].fX, fM[kScaleX]) + fM[kTransX];\r
-        dst[i].fY = GrMul(src[i].fY, fM[kScaleY]) + fM[kTransY];\r
-    }\r
-}\r
-\r
-void GrMatrix::mapSkew(GrPoint* dst, const GrPoint* src, uint32_t count) const {\r
-    if (src != dst) {\r
-        for (uint32_t i = 0; i < count; ++i) {\r
-            dst[i].fX = src[i].fX + GrMul(src[i].fY, fM[kSkewX]);\r
-            dst[i].fY = src[i].fY + GrMul(src[i].fX, fM[kSkewY]);\r
-        }\r
-    } else {\r
-        for (uint32_t i = 0; i < count; ++i) {\r
-            GrScalar newX = src[i].fX + GrMul(src[i].fY, fM[kSkewX]);\r
-            dst[i].fY = src[i].fY + GrMul(src[i].fX, fM[kSkewY]);\r
-            dst[i].fX = newX;\r
-        }\r
-    }\r
-}\r
-\r
-void GrMatrix::mapScaleAndSkew(GrPoint* dst, const GrPoint* src, uint32_t count) const {\r
-    if (src != dst) {\r
-        for (uint32_t i = 0; i < count; ++i) {\r
-            dst[i].fX = GrMul(src[i].fX, fM[kScaleX]) + GrMul(src[i].fY, fM[kSkewX]);\r
-            dst[i].fY = GrMul(src[i].fY, fM[kScaleY]) + GrMul(src[i].fX, fM[kSkewY]);\r
-        }\r
-    } else {\r
-        for (uint32_t i = 0; i < count; ++i) {\r
-            GrScalar newX = GrMul(src[i].fX, fM[kScaleX]) + GrMul(src[i].fY, fM[kSkewX]);\r
-            dst[i].fY = GrMul(src[i].fY, fM[kScaleY]) + GrMul(src[i].fX, fM[kSkewY]);\r
-            dst[i].fX = newX;\r
-        }\r
-    }\r
-}\r
-\r
-void GrMatrix::mapSkewAndTranslate(GrPoint* dst, const GrPoint* src, uint32_t count) const {\r
-    if (src != dst) {\r
-        for (uint32_t i = 0; i < count; ++i) {\r
-            dst[i].fX = src[i].fX + GrMul(src[i].fY, fM[kSkewX]) + fM[kTransX];\r
-            dst[i].fY = src[i].fY + GrMul(src[i].fX, fM[kSkewY]) + fM[kTransY];\r
-        }\r
-    } else {\r
-        for (uint32_t i = 0; i < count; ++i) {\r
-            GrScalar newX = src[i].fX + GrMul(src[i].fY, fM[kSkewX]) + fM[kTransX];\r
-            dst[i].fY = src[i].fY + GrMul(src[i].fX, fM[kSkewY]) + fM[kTransY];\r
-            dst[i].fX = newX;\r
-        }\r
-    }\r
-}\r
-\r
-void GrMatrix::mapNonPerspective(GrPoint* dst, const GrPoint* src, uint32_t count) const {\r
-    if (src != dst) {\r
-        for (uint32_t i = 0; i < count; ++i) {\r
-            dst[i].fX = GrMul(fM[kScaleX], src[i].fX) + GrMul(fM[kSkewX], src[i].fY) + fM[kTransX];\r
-            dst[i].fY = GrMul(fM[kSkewY], src[i].fX) + GrMul(fM[kScaleY], src[i].fY) + fM[kTransY];\r
-        }\r
-    } else {\r
-        for (uint32_t i = 0; i < count; ++i) {\r
-            GrScalar newX = GrMul(fM[kScaleX], src[i].fX) + GrMul(fM[kSkewX], src[i].fY) + fM[kTransX];\r
-            dst[i].fY = GrMul(fM[kSkewY], src[i].fX) + GrMul(fM[kScaleY], src[i].fY) + fM[kTransY];\r
-            dst[i].fX = newX;\r
-        }\r
-    }\r
-}\r
-\r
-void GrMatrix::mapPerspective(GrPoint* dst, const GrPoint* src, uint32_t count) const {\r
-    for (uint32_t i = 0; i < count; ++i) {\r
-        GrScalar x, y, w;\r
-        x = GrMul(fM[kScaleX], src[i].fX) + GrMul(fM[kSkewX], src[i].fY) + fM[kTransX];\r
-        y = GrMul(fM[kSkewY], src[i].fX) + GrMul(fM[kScaleY], src[i].fY) + fM[kTransY];\r
-        w = GrMul(fM[kPersp0], src[i].fX) + GrMul(fM[kPersp1], src[i].fY) + fM[kPersp2];\r
-        // TODO need fixed point invert\r
-        if (w) {\r
-            w = 1 / w;\r
-        }\r
-        dst[i].fX = GrMul(x, w);\r
-        dst[i].fY = GrMul(y, w);\r
-    }\r
-}\r
-\r
-void GrMatrix::mapInvalid(GrPoint* dst, const GrPoint* src, uint32_t count) const {\r
-    GrAssert(0);\r
-}\r
-\r
-void GrMatrix::mapZero(GrPoint* dst, const GrPoint* src, uint32_t count) const {\r
-    memset(dst, 0, sizeof(GrPoint)*count);\r
-}\r
-\r
-void GrMatrix::mapSetToTranslate(GrPoint* dst, const GrPoint* src, uint32_t count) const {\r
-    for (uint32_t i = 0; i < count; ++i) {\r
-        dst[i].fX = fM[kTransX];\r
-        dst[i].fY = fM[kTransY];\r
-    }\r
-}\r
-\r
-void GrMatrix::mapSwappedScale(GrPoint* dst, const GrPoint* src, uint32_t count) const {\r
-    if (src != dst) {\r
-        for (uint32_t i = 0; i < count; ++i) {\r
-            dst[i].fX = GrMul(src[i].fY, fM[kSkewX]);\r
-            dst[i].fY = GrMul(src[i].fX, fM[kSkewY]);\r
-        }\r
-    } else {\r
-        for (uint32_t i = 0; i < count; ++i) {\r
-            GrScalar newX = GrMul(src[i].fY, fM[kSkewX]);\r
-            dst[i].fY = GrMul(src[i].fX, fM[kSkewY]);\r
-            dst[i].fX = newX;\r
-        }\r
-    }\r
-}\r
-\r
-void GrMatrix::mapSwappedScaleAndTranslate(GrPoint* dst, const GrPoint* src, uint32_t count) const {\r
-    if (src != dst) {\r
-        for (uint32_t i = 0; i < count; ++i) {\r
-            dst[i].fX = GrMul(src[i].fY, fM[kSkewX]) + fM[kTransX];\r
-            dst[i].fY = GrMul(src[i].fX, fM[kSkewY]) + fM[kTransY];\r
-        }\r
-    } else {\r
-        for (uint32_t i = 0; i < count; ++i) {\r
-            GrScalar newX = GrMul(src[i].fY, fM[kSkewX]) + fM[kTransX];\r
-            dst[i].fY = GrMul(src[i].fX, fM[kSkewY]) + fM[kTransY];\r
-            dst[i].fX = newX;\r
-        }\r
-    }\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////////\r
-// Unit test\r
-//////\r
-\r
-#include "GrRandom.h"\r
-\r
-#if GR_DEBUG\r
-enum MatrixType {\r
-    kRotate_MatrixType,\r
-    kScaleX_MatrixType,\r
-    kScaleY_MatrixType,\r
-    kSkewX_MatrixType,\r
-    kSkewY_MatrixType,\r
-    kTranslateX_MatrixType,\r
-    kTranslateY_MatrixType,\r
-    kSwapScaleXY_MatrixType,\r
-    kPersp_MatrixType,\r
-\r
-    kMatrixTypeCount\r
-};\r
-\r
-static void create_matrix(GrMatrix* matrix, GrRandom& rand) {\r
-    MatrixType type = (MatrixType)(rand.nextU() % kMatrixTypeCount);\r
-    switch (type) {\r
-        case kRotate_MatrixType: {\r
-            float angle = rand.nextF() * 2 *3.14159265358979323846f;\r
-            GrScalar cosa = GrFloatToScalar(cosf(angle));\r
-            GrScalar sina = GrFloatToScalar(sinf(angle));\r
-            matrix->setAll(cosa,      -sina,           0,\r
-                           sina,       cosa,           0,\r
-                           0,          0,              GrMatrix::I()[8]);\r
-        } break;\r
-        case kScaleX_MatrixType: {\r
-            GrScalar scale = GrFloatToScalar(rand.nextF(-2, 2));\r
-            matrix->setAll(scale,      0,              0,\r
-                           0,          GR_Scalar1,     0,\r
-                           0,          0,              GrMatrix::I()[8]);\r
-        } break;\r
-        case kScaleY_MatrixType: {\r
-            GrScalar scale = GrFloatToScalar(rand.nextF(-2, 2));\r
-            matrix->setAll(GR_Scalar1, 0,              0,\r
-                           0,          scale,          0,\r
-                           0,          0,              GrMatrix::I()[8]);\r
-        } break;\r
-        case kSkewX_MatrixType: {\r
-            GrScalar skew = GrFloatToScalar(rand.nextF(-2, 2));\r
-            matrix->setAll(GR_Scalar1, skew,           0,\r
-                           0,          GR_Scalar1,     0,\r
-                           0,          0,              GrMatrix::I()[8]);\r
-        } break;\r
-        case kSkewY_MatrixType: {\r
-            GrScalar skew = GrFloatToScalar(rand.nextF(-2, 2));\r
-            matrix->setAll(GR_Scalar1, 0,              0,\r
-                           skew,       GR_Scalar1,     0,\r
-                           0,          0,              GrMatrix::I()[8]);\r
-        } break;\r
-        case kTranslateX_MatrixType: {\r
-            GrScalar trans = GrFloatToScalar(rand.nextF(-10, 10));\r
-            matrix->setAll(GR_Scalar1, 0,              trans,\r
-                           0,          GR_Scalar1,     0,\r
-                           0,          0,              GrMatrix::I()[8]);\r
-        } break;\r
-        case kTranslateY_MatrixType: {\r
-            GrScalar trans = GrFloatToScalar(rand.nextF(-10, 10));\r
-            matrix->setAll(GR_Scalar1, 0,              0,\r
-                           0,          GR_Scalar1,     trans,\r
-                           0,          0,              GrMatrix::I()[8]);\r
-        } break;\r
-        case kSwapScaleXY_MatrixType: {\r
-            GrScalar xy = GrFloatToScalar(rand.nextF(-2, 2));\r
-            GrScalar yx = GrFloatToScalar(rand.nextF(-2, 2));\r
-            matrix->setAll(0,          xy,             0,\r
-                           yx,         0,              0,\r
-                           0,          0,              GrMatrix::I()[8]);\r
-        } break;\r
-        case kPersp_MatrixType: {\r
-            GrScalar p0 = GrFloatToScalar(rand.nextF(-2, 2));\r
-            GrScalar p1 = GrFloatToScalar(rand.nextF(-2, 2));\r
-            GrScalar p2 = GrFloatToScalar(rand.nextF(-0.5f, 0.75f));\r
-            matrix->setAll(GR_Scalar1, 0,              0,\r
-                           0,          GR_Scalar1,     0,\r
-                           p0,         p1,             GrMul(p2,GrMatrix::I()[8]));\r
-        } break;\r
-        default:\r
-            GrAssert(0);\r
-            break;\r
-    }\r
-}\r
-#endif\r
-\r
-void GrMatrix::UnitTest() {\r
-    GrRandom rand;\r
-\r
-    // Create a bunch of matrices and test point mapping, max stretch calc,\r
-    // inversion and multiply-by-inverse.\r
-#if GR_DEBUG\r
-    for (int i = 0; i < 10000; ++i) {\r
-        GrMatrix a, b;\r
-        a.setIdentity();\r
-        int num = rand.nextU() % 6;\r
-        // force testing of I and swapXY\r
-        if (0 == i) {\r
-            num = 0;\r
-            GrAssert(a.isIdentity());\r
-        } else if (1 == i) {\r
-            num = 0;\r
-            a.setAll(0, GR_Scalar1, 0,\r
-                     GR_Scalar1, 0, 0,\r
-                     0, 0, I()[8]);\r
-        }\r
-        for (int j = 0; j < num; ++j) {\r
-            create_matrix(&b, rand);\r
-            a.preConcat(b);\r
-        }\r
-\r
-        GrScalar maxStretch = a.getMaxStretch();\r
-        if (maxStretch > 0) {\r
-            maxStretch = GrMul(GR_Scalar1 + GR_Scalar1 / 100, maxStretch);\r
-        }\r
-        GrPoint origin = a.mapPoint(GrPoint(0,0));\r
-\r
-        for (int j = 0; j < 9; ++j) {\r
-            int mask, origMask = a.fTypeMask;\r
-            GrScalar old = a[j];\r
-\r
-            a.set(j, GR_Scalar1);\r
-            mask = a.fTypeMask;\r
-            a.computeTypeMask();\r
-            GrAssert(mask == a.fTypeMask);\r
-\r
-            a.set(j, 0);\r
-            mask = a.fTypeMask;\r
-            a.computeTypeMask();\r
-            GrAssert(mask == a.fTypeMask);\r
-\r
-            a.set(j, 10 * GR_Scalar1);\r
-            mask = a.fTypeMask;\r
-            a.computeTypeMask();\r
-            GrAssert(mask == a.fTypeMask);\r
-\r
-            a.set(j, old);\r
-            GrAssert(a.fTypeMask == origMask);\r
-        }\r
-\r
-        for (int j = 0; j < 100; ++j) {\r
-            GrPoint pt;\r
-            pt.fX = GrFloatToScalar(rand.nextF(-10, 10));\r
-            pt.fY = GrFloatToScalar(rand.nextF(-10, 10));\r
-\r
-            GrPoint t0, t1, t2;\r
-            t0 = a.mapPoint(pt);             // map to a new point\r
-            t1 = pt;\r
-            a.mapPoints(&t1, &t1, 1);        // in place\r
-            a.mapPerspective(&t2, &pt, 1);   // full mult\r
-            GrAssert(t0 == t1 && t1 == t2);\r
-            if (maxStretch >= 0.f) {\r
-                GrVec vec;\r
-                vec.setBetween(t0, origin);\r
-                GrScalar stretch = vec.length() / pt.distanceToOrigin();\r
-                GrAssert(stretch <= maxStretch);\r
-            }\r
-        }\r
-        double det = a.determinant();\r
-        if (fabs(det) > 1e-3 && a.invert(&b)) {\r
-            GrMatrix c;\r
-            c.setConcat(a,b);\r
-            for (int i = 0; i < 9; ++i) {\r
-                GrScalar diff = GrScalarAbs(c[i] - I()[i]);\r
-                GrAssert(diff < (5*GR_Scalar1 / 100));\r
-            }\r
-        }\r
-    }\r
-#endif\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////////\r
-\r
-int Gr_clz(uint32_t n) {\r
-    if (0 == n) {\r
-        return 32;\r
-    }\r
-\r
-    int count = 0;\r
-    if (0 == (n & 0xFFFF0000)) {\r
-        count += 16;\r
-        n <<= 16;\r
-    }\r
-    if (0 == (n & 0xFF000000)) {\r
-        count += 8;\r
-        n <<= 8;\r
-    }\r
-    if (0 == (n & 0xF0000000)) {\r
-        count += 4;\r
-        n <<= 4;\r
-    }\r
-    if (0 == (n & 0xC0000000)) {\r
-        count += 2;\r
-        n <<= 2;\r
-    }\r
-    if (0 == (n & 0x80000000)) {\r
-        count += 1;\r
-    }\r
-    return count;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////////////\r
-#include "GrRect.h"\r
-\r
-void GrRect::setBounds(const GrPoint pts[], int count) {\r
-    if (count <= 0) {\r
-        this->setEmpty();\r
-    } else {\r
-        GrScalar L, R, T, B;\r
-        L = R = pts[0].fX;\r
-        T = B = pts[0].fY;\r
-        for (int i = 1; i < count; i++) {\r
-            GrScalar x = pts[i].fX;\r
-            GrScalar y = pts[i].fY;\r
-            if (x < L) {\r
-                L = x;\r
-            } else if (x > R) {\r
-                R = x;\r
-            }\r
-            if (y < T) {\r
-                T = y;\r
-            } else if (y > B) {\r
-                B = y;\r
-            }\r
-        }\r
-        this->setLTRB(L, T, R, B);\r
-    }\r
-}\r
-\r
-\r
-\r
+/*
+    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.
+ */
+
+
+#include "GrMatrix.h"
+#include "GrRect.h"
+#include <stddef.h>
+
+#if GR_SCALAR_IS_FLOAT
+    const GrScalar GrMatrix::gRESCALE(GR_Scalar1);
+#else
+    GR_STATIC_ASSERT(GR_SCALAR_IS_FIXED);
+    // fixed point isn't supported right now
+    GR_STATIC_ASSERT(false);
+const GrScalar GrMatrix::gRESCALE(1 << 30);
+#endif
+
+const GrMatrix::MapProc GrMatrix::gMapProcs[] = {
+// Scales are not both zero
+    &GrMatrix::mapIdentity,
+    &GrMatrix::mapScale,
+    &GrMatrix::mapTranslate,
+    &GrMatrix::mapScaleAndTranslate,
+    &GrMatrix::mapSkew,
+    &GrMatrix::mapScaleAndSkew,
+    &GrMatrix::mapSkewAndTranslate,
+    &GrMatrix::mapNonPerspective,
+    // no optimizations for perspective matrices
+    &GrMatrix::mapPerspective,
+    &GrMatrix::mapPerspective,
+    &GrMatrix::mapPerspective,
+    &GrMatrix::mapPerspective,
+    &GrMatrix::mapPerspective,
+    &GrMatrix::mapPerspective,
+    &GrMatrix::mapPerspective,
+    &GrMatrix::mapPerspective,
+
+// Scales are zero (every other is invalid because kScale_TypeBit must be set if
+// kZeroScale_TypeBit is set)
+    &GrMatrix::mapInvalid,
+    &GrMatrix::mapZero,
+    &GrMatrix::mapInvalid,
+    &GrMatrix::mapSetToTranslate,
+    &GrMatrix::mapInvalid,
+    &GrMatrix::mapSwappedScale,
+    &GrMatrix::mapInvalid,
+    &GrMatrix::mapSwappedScaleAndTranslate,
+
+    // no optimizations for perspective matrices
+    &GrMatrix::mapInvalid,
+    &GrMatrix::mapZero,
+    &GrMatrix::mapInvalid,
+    &GrMatrix::mapPerspective,
+    &GrMatrix::mapInvalid,
+    &GrMatrix::mapPerspective,
+    &GrMatrix::mapInvalid,
+    &GrMatrix::mapPerspective,
+};
+
+void GrMatrix::setIdentity() {
+    fM[0] = GR_Scalar1; fM[1] = 0;          fM[2] = 0;
+    fM[3] = 0;          fM[4] = GR_Scalar1; fM[5] = 0;
+    fM[6] = 0;          fM[7] = 0;          fM[8] = gRESCALE;
+    fTypeMask = 0;
+}
+
+void GrMatrix::setTranslate(GrScalar dx, GrScalar dy) {
+    fM[0] = GR_Scalar1; fM[1] = 0;          fM[2] = dx;
+    fM[3] = 0;          fM[4] = GR_Scalar1; fM[5] = dy;
+    fM[6] = 0;          fM[7] = 0;          fM[8] = gRESCALE;
+    fTypeMask = (0 != dx || 0 != dy) ? kTranslate_TypeBit : 0;
+}
+
+void GrMatrix::setScale(GrScalar sx, GrScalar sy) {
+    fM[0] = sx; fM[1] = 0;  fM[2] = 0;
+    fM[3] = 0;  fM[4] = sy; fM[5] = 0;
+    fM[6] = 0;  fM[7] = 0;  fM[8] = gRESCALE;
+    fTypeMask = (GR_Scalar1 != sx || GR_Scalar1 != sy) ? kScale_TypeBit : 0;
+}
+
+void GrMatrix::setSkew(GrScalar skx, GrScalar sky) {
+    fM[0] = GR_Scalar1; fM[1] = skx;        fM[2] = 0;
+    fM[3] = sky;        fM[4] = GR_Scalar1; fM[5] = 0;
+    fM[6] = 0;          fM[7] = 0;          fM[8] = gRESCALE;
+    fTypeMask = (0 != skx || 0 != sky) ? kSkew_TypeBit : 0;
+}
+
+void GrMatrix::setConcat(const GrMatrix& a, const GrMatrix& b) {
+    if (a.isIdentity()) {
+        if (this != &b) {
+            for (int i = 0; i < 9; ++i) {
+                fM[i] = b.fM[i];
+            }
+            fTypeMask = b.fTypeMask;
+        }
+        return;
+    }
+
+    if (b.isIdentity()) {
+        GrAssert(!a.isIdentity());
+        if (this != &a) {
+            for (int i = 0; i < 9; ++i) {
+                    fM[i] = a.fM[i];
+            }
+            fTypeMask = a.fTypeMask;
+        }
+        return;
+    }
+
+    // a and/or b could be this
+    GrMatrix tmp;
+
+    // could do more optimizations based on type bits. Hopefully this call is
+    // low frequency.
+    // TODO: make this work for fixed point
+    if (!((b.fTypeMask | a.fTypeMask) & kPerspective_TypeBit)) {
+        tmp.fM[0] = a.fM[0] * b.fM[0] + a.fM[1] * b.fM[3];
+        tmp.fM[1] = a.fM[0] * b.fM[1] + a.fM[1] * b.fM[4];
+        tmp.fM[2] = a.fM[0] * b.fM[2] + a.fM[1] * b.fM[5] + a.fM[2] * gRESCALE;
+
+        tmp.fM[3] = a.fM[3] * b.fM[0] + a.fM[4] * b.fM[3];
+        tmp.fM[4] = a.fM[3] * b.fM[1] + a.fM[4] * b.fM[4];
+        tmp.fM[5] = a.fM[3] * b.fM[2] + a.fM[4] * b.fM[5] + a.fM[5] * gRESCALE;
+
+        tmp.fM[6] = 0;
+        tmp.fM[7] = 0;
+        tmp.fM[8] = gRESCALE * gRESCALE;
+    } else {
+        tmp.fM[0] = a.fM[0] * b.fM[0] + a.fM[1] * b.fM[3] + a.fM[2] * b.fM[6];
+        tmp.fM[1] = a.fM[0] * b.fM[1] + a.fM[1] * b.fM[4] + a.fM[2] * b.fM[7];
+        tmp.fM[2] = a.fM[0] * b.fM[2] + a.fM[1] * b.fM[5] + a.fM[2] * b.fM[8];
+
+        tmp.fM[3] = a.fM[3] * b.fM[0] + a.fM[4] * b.fM[3] + a.fM[5] * b.fM[6];
+        tmp.fM[4] = a.fM[3] * b.fM[1] + a.fM[4] * b.fM[4] + a.fM[5] * b.fM[7];
+        tmp.fM[5] = a.fM[3] * b.fM[2] + a.fM[4] * b.fM[5] + a.fM[5] * b.fM[8];
+
+        tmp.fM[6] = a.fM[6] * b.fM[0] + a.fM[7] * b.fM[3] + a.fM[8] * b.fM[6];
+        tmp.fM[7] = a.fM[6] * b.fM[1] + a.fM[7] * b.fM[4] + a.fM[8] * b.fM[7];
+        tmp.fM[8] = a.fM[6] * b.fM[2] + a.fM[7] * b.fM[5] + a.fM[8] * b.fM[8];
+    }
+    *this = tmp;
+    this->computeTypeMask();
+}
+
+void GrMatrix::preConcat(const GrMatrix& m) {
+    setConcat(*this, m);
+}
+
+void GrMatrix::postConcat(const GrMatrix& m) {
+    setConcat(m, *this);
+}
+
+double GrMatrix::determinant() const {
+    if (fTypeMask & kPerspective_TypeBit) {
+        return  fM[0]*((double)fM[4]*fM[8] - (double)fM[5]*fM[7]) +
+                fM[1]*((double)fM[5]*fM[6] - (double)fM[3]*fM[8]) +
+                fM[2]*((double)fM[3]*fM[7] - (double)fM[4]*fM[6]);
+    } else {
+        return (double)fM[0]*fM[4]*gRESCALE -
+               (double)fM[1]*fM[3]*gRESCALE;
+    }
+}
+
+bool GrMatrix::invert(GrMatrix* inverted) const {
+
+    if (isIdentity()) {
+        if (inverted != this) {
+            inverted->setIdentity();
+        }
+        return true;
+    }
+    static const double MIN_DETERMINANT_SQUARED = 1.e-16;
+
+    // could do more optimizations based on type bits. Hopefully this call is
+    // low frequency.
+
+    double det = determinant();
+
+    // check if we can't be inverted
+    if (det*det <= MIN_DETERMINANT_SQUARED) {
+        return false;
+    } else if (NULL == inverted) {
+        return true;
+    }
+
+    double t[9];
+
+    if (fTypeMask & kPerspective_TypeBit) {
+        t[0] = ((double)fM[4]*fM[8] - (double)fM[5]*fM[7]);
+        t[1] = ((double)fM[2]*fM[7] - (double)fM[1]*fM[8]);
+        t[2] = ((double)fM[1]*fM[5] - (double)fM[2]*fM[4]);
+        t[3] = ((double)fM[5]*fM[6] - (double)fM[3]*fM[8]);
+        t[4] = ((double)fM[0]*fM[8] - (double)fM[2]*fM[6]);
+        t[5] = ((double)fM[2]*fM[3] - (double)fM[0]*fM[5]);
+        t[6] = ((double)fM[3]*fM[7] - (double)fM[4]*fM[6]);
+        t[7] = ((double)fM[1]*fM[6] - (double)fM[0]*fM[7]);
+        t[8] = ((double)fM[0]*fM[4] - (double)fM[1]*fM[3]);
+        det = 1.0 / det;
+        for (int i = 0; i < 9; ++i) {
+            inverted->fM[i] = (GrScalar)(t[i] * det);
+        }
+    } else {
+        t[0] =  (double)fM[4]*gRESCALE;
+        t[1] = -(double)fM[1]*gRESCALE;
+        t[2] =  (double)fM[1]*fM[5] - (double)fM[2]*fM[4];
+        t[3] = -(double)fM[3]*gRESCALE;
+        t[4] =  (double)fM[0]*gRESCALE;
+        t[5] =  (double)fM[2]*fM[3] - (double)fM[0]*fM[5];
+        //t[6] = 0.0;
+        //t[7] = 0.0;
+        t[8] = (double)fM[0]*fM[4] - (double)fM[1]*fM[3];
+        det = 1.0 / det;
+        for (int i = 0; i < 6; ++i) {
+            inverted->fM[i] = (GrScalar)(t[i] * det);
+        }
+        inverted->fM[6] = 0;
+        inverted->fM[7] = 0;
+        inverted->fM[8] = (GrScalar)(t[8] * det);
+    }
+    inverted->computeTypeMask();
+    return true;
+}
+
+void GrMatrix::mapRect(GrRect* dst, const GrRect& src) const {
+    GrPoint srcPts[4], dstPts[4];
+    srcPts[0].set(src.fLeft, src.fTop);
+    srcPts[1].set(src.fRight, src.fTop);
+    srcPts[2].set(src.fRight, src.fBottom);
+    srcPts[3].set(src.fLeft, src.fBottom);
+    this->mapPoints(dstPts, srcPts, 4);
+    dst->setBounds(dstPts, 4);
+}
+
+bool GrMatrix::hasPerspective() const {
+    GrAssert(!!(kPerspective_TypeBit & fTypeMask) ==
+             (fM[kPersp0] != 0 || fM[kPersp1] != 0 || fM[kPersp2] != gRESCALE));
+    return 0 != (kPerspective_TypeBit & fTypeMask);
+}
+
+bool GrMatrix::isIdentity() const {
+    GrAssert((0 == fTypeMask) ==
+             (GR_Scalar1 == fM[kScaleX] && 0          == fM[kSkewX]  && 0          == fM[kTransX] &&
+              0          == fM[kSkewY]  && GR_Scalar1 == fM[kScaleY] && 0          == fM[kTransY] &&
+              0          == fM[kPersp0] && 0          == fM[kPersp1] && gRESCALE == fM[kPersp2]));
+    return (0 == fTypeMask);
+}
+
+
+GrScalar GrMatrix::getMaxStretch() const {
+
+    if (fTypeMask & kPerspective_TypeBit) {
+        return -GR_Scalar1;
+    }
+
+    GrScalar stretch;
+
+    if (isIdentity()) {
+        stretch = GR_Scalar1;
+    } else if (!(fTypeMask & kSkew_TypeBit)) {
+        stretch = GrMax(GrScalarAbs(fM[kScaleX]), GrScalarAbs(fM[kScaleY]));
+    } else if (fTypeMask & kZeroScale_TypeBit) {
+        stretch = GrMax(GrScalarAbs(fM[kSkewX]), GrScalarAbs(fM[kSkewY]));
+    } else {
+        // ignore the translation part of the matrix, just look at 2x2 portion.
+        // compute singular values, take largest abs value.
+        // [a b; b c] = A^T*A
+        GrScalar a = GrMul(fM[kScaleX], fM[kScaleX]) + GrMul(fM[kSkewY],  fM[kSkewY]);
+        GrScalar b = GrMul(fM[kScaleX], fM[kSkewX]) +  GrMul(fM[kScaleY], fM[kSkewY]);
+        GrScalar c = GrMul(fM[kSkewX],  fM[kSkewX]) +  GrMul(fM[kScaleY], fM[kScaleY]);
+        // eigenvalues of A^T*A are the squared singular values of A.
+        // characteristic equation is det((A^T*A) - l*I) = 0
+        // l^2 - (a + c)l + (ac-b^2)
+        // solve using quadratic equation (divisor is non-zero since l^2 has 1 coeff
+        // and roots are guaraunteed to be pos and real).
+        GrScalar largerRoot;
+        GrScalar bSqd = GrMul(b,b);
+        // TODO: fixed point tolerance value.
+        if (bSqd < 1e-10) { // will be true if upper left 2x2 is orthogonal, which is common, so save some math
+            largerRoot = GrMax(a, c);
+        } else {
+            GrScalar aminusc = a - c;
+            GrScalar apluscdiv2 = (a + c) / 2;
+            GrScalar x = sqrtf(GrMul(aminusc,aminusc) + GrMul(4,(bSqd))) / 2;
+            largerRoot = apluscdiv2 + x;
+        }
+
+        stretch = sqrtf(largerRoot);
+    }
+#if GR_DEBUG && 0
+    // test a bunch of vectors. None should be scaled by more than stretch
+    // (modulo some error) and we should find a vector that is scaled by almost
+    // stretch.
+    GrPoint pt;
+    GrScalar max = 0;
+    for (int i = 0; i < 1000; ++i) {
+        GrScalar x = (float)rand() / RAND_MAX;
+        GrScalar y = sqrtf(1 - (x*x));
+        pt.fX = fM[kScaleX]*x + fM[kSkewX]*y;
+        pt.fY = fM[kSkewY]*x + fM[kScaleY]*y;
+        GrScalar d = pt.distanceToOrigin();
+        GrAssert(d <= (1.0001 * stretch));
+        max = GrMax(max, pt.distanceToOrigin());
+    }
+    GrAssert((stretch - max) < .05*stretch);
+#endif
+    return stretch;
+}
+
+bool GrMatrix::operator == (const GrMatrix& m) const {
+    if (fTypeMask != m.fTypeMask) {
+        return false;
+    }
+    if (!fTypeMask) {
+        return true;
+    }
+    for (int i = 0; i < 9; ++i) {
+        if (m.fM[i] != fM[i]) {
+            return false;
+        }
+    }
+    return true;
+}
+
+bool GrMatrix::operator != (const GrMatrix& m) const {
+    return !(*this == m);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Matrix transformation procs
+//////
+
+void GrMatrix::mapIdentity(GrPoint* dst, const GrPoint* src, uint32_t count) const {
+    if (src != dst) {
+        for (uint32_t i = 0; i < count; ++i) {
+            dst[i] = src[i];
+        }
+    }
+}
+
+void GrMatrix::mapScale(GrPoint* dst, const GrPoint* src, uint32_t count) const {
+    for (uint32_t i = 0; i < count; ++i) {
+        dst[i].fX = GrMul(src[i].fX, fM[kScaleX]);
+        dst[i].fY = GrMul(src[i].fY, fM[kScaleY]);
+    }
+}
+
+
+void GrMatrix::mapTranslate(GrPoint* dst, const GrPoint* src, uint32_t count) const {
+    for (uint32_t i = 0; i < count; ++i) {
+        dst[i].fX = src[i].fX + fM[kTransX];
+        dst[i].fY = src[i].fY + fM[kTransY];
+    }
+}
+
+void GrMatrix::mapScaleAndTranslate(GrPoint* dst, const GrPoint* src, uint32_t count) const {
+    for (uint32_t i = 0; i < count; ++i) {
+        dst[i].fX = GrMul(src[i].fX, fM[kScaleX]) + fM[kTransX];
+        dst[i].fY = GrMul(src[i].fY, fM[kScaleY]) + fM[kTransY];
+    }
+}
+
+void GrMatrix::mapSkew(GrPoint* dst, const GrPoint* src, uint32_t count) const {
+    if (src != dst) {
+        for (uint32_t i = 0; i < count; ++i) {
+            dst[i].fX = src[i].fX + GrMul(src[i].fY, fM[kSkewX]);
+            dst[i].fY = src[i].fY + GrMul(src[i].fX, fM[kSkewY]);
+        }
+    } else {
+        for (uint32_t i = 0; i < count; ++i) {
+            GrScalar newX = src[i].fX + GrMul(src[i].fY, fM[kSkewX]);
+            dst[i].fY = src[i].fY + GrMul(src[i].fX, fM[kSkewY]);
+            dst[i].fX = newX;
+        }
+    }
+}
+
+void GrMatrix::mapScaleAndSkew(GrPoint* dst, const GrPoint* src, uint32_t count) const {
+    if (src != dst) {
+        for (uint32_t i = 0; i < count; ++i) {
+            dst[i].fX = GrMul(src[i].fX, fM[kScaleX]) + GrMul(src[i].fY, fM[kSkewX]);
+            dst[i].fY = GrMul(src[i].fY, fM[kScaleY]) + GrMul(src[i].fX, fM[kSkewY]);
+        }
+    } else {
+        for (uint32_t i = 0; i < count; ++i) {
+            GrScalar newX = GrMul(src[i].fX, fM[kScaleX]) + GrMul(src[i].fY, fM[kSkewX]);
+            dst[i].fY = GrMul(src[i].fY, fM[kScaleY]) + GrMul(src[i].fX, fM[kSkewY]);
+            dst[i].fX = newX;
+        }
+    }
+}
+
+void GrMatrix::mapSkewAndTranslate(GrPoint* dst, const GrPoint* src, uint32_t count) const {
+    if (src != dst) {
+        for (uint32_t i = 0; i < count; ++i) {
+            dst[i].fX = src[i].fX + GrMul(src[i].fY, fM[kSkewX]) + fM[kTransX];
+            dst[i].fY = src[i].fY + GrMul(src[i].fX, fM[kSkewY]) + fM[kTransY];
+        }
+    } else {
+        for (uint32_t i = 0; i < count; ++i) {
+            GrScalar newX = src[i].fX + GrMul(src[i].fY, fM[kSkewX]) + fM[kTransX];
+            dst[i].fY = src[i].fY + GrMul(src[i].fX, fM[kSkewY]) + fM[kTransY];
+            dst[i].fX = newX;
+        }
+    }
+}
+
+void GrMatrix::mapNonPerspective(GrPoint* dst, const GrPoint* src, uint32_t count) const {
+    if (src != dst) {
+        for (uint32_t i = 0; i < count; ++i) {
+            dst[i].fX = GrMul(fM[kScaleX], src[i].fX) + GrMul(fM[kSkewX], src[i].fY) + fM[kTransX];
+            dst[i].fY = GrMul(fM[kSkewY], src[i].fX) + GrMul(fM[kScaleY], src[i].fY) + fM[kTransY];
+        }
+    } else {
+        for (uint32_t i = 0; i < count; ++i) {
+            GrScalar newX = GrMul(fM[kScaleX], src[i].fX) + GrMul(fM[kSkewX], src[i].fY) + fM[kTransX];
+            dst[i].fY = GrMul(fM[kSkewY], src[i].fX) + GrMul(fM[kScaleY], src[i].fY) + fM[kTransY];
+            dst[i].fX = newX;
+        }
+    }
+}
+
+void GrMatrix::mapPerspective(GrPoint* dst, const GrPoint* src, uint32_t count) const {
+    for (uint32_t i = 0; i < count; ++i) {
+        GrScalar x, y, w;
+        x = GrMul(fM[kScaleX], src[i].fX) + GrMul(fM[kSkewX], src[i].fY) + fM[kTransX];
+        y = GrMul(fM[kSkewY], src[i].fX) + GrMul(fM[kScaleY], src[i].fY) + fM[kTransY];
+        w = GrMul(fM[kPersp0], src[i].fX) + GrMul(fM[kPersp1], src[i].fY) + fM[kPersp2];
+        // TODO need fixed point invert
+        if (w) {
+            w = 1 / w;
+        }
+        dst[i].fX = GrMul(x, w);
+        dst[i].fY = GrMul(y, w);
+    }
+}
+
+void GrMatrix::mapInvalid(GrPoint* dst, const GrPoint* src, uint32_t count) const {
+    GrAssert(0);
+}
+
+void GrMatrix::mapZero(GrPoint* dst, const GrPoint* src, uint32_t count) const {
+    memset(dst, 0, sizeof(GrPoint)*count);
+}
+
+void GrMatrix::mapSetToTranslate(GrPoint* dst, const GrPoint* src, uint32_t count) const {
+    for (uint32_t i = 0; i < count; ++i) {
+        dst[i].fX = fM[kTransX];
+        dst[i].fY = fM[kTransY];
+    }
+}
+
+void GrMatrix::mapSwappedScale(GrPoint* dst, const GrPoint* src, uint32_t count) const {
+    if (src != dst) {
+        for (uint32_t i = 0; i < count; ++i) {
+            dst[i].fX = GrMul(src[i].fY, fM[kSkewX]);
+            dst[i].fY = GrMul(src[i].fX, fM[kSkewY]);
+        }
+    } else {
+        for (uint32_t i = 0; i < count; ++i) {
+            GrScalar newX = GrMul(src[i].fY, fM[kSkewX]);
+            dst[i].fY = GrMul(src[i].fX, fM[kSkewY]);
+            dst[i].fX = newX;
+        }
+    }
+}
+
+void GrMatrix::mapSwappedScaleAndTranslate(GrPoint* dst, const GrPoint* src, uint32_t count) const {
+    if (src != dst) {
+        for (uint32_t i = 0; i < count; ++i) {
+            dst[i].fX = GrMul(src[i].fY, fM[kSkewX]) + fM[kTransX];
+            dst[i].fY = GrMul(src[i].fX, fM[kSkewY]) + fM[kTransY];
+        }
+    } else {
+        for (uint32_t i = 0; i < count; ++i) {
+            GrScalar newX = GrMul(src[i].fY, fM[kSkewX]) + fM[kTransX];
+            dst[i].fY = GrMul(src[i].fX, fM[kSkewY]) + fM[kTransY];
+            dst[i].fX = newX;
+        }
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// Unit test
+//////
+
+#include "GrRandom.h"
+
+#if GR_DEBUG
+enum MatrixType {
+    kRotate_MatrixType,
+    kScaleX_MatrixType,
+    kScaleY_MatrixType,
+    kSkewX_MatrixType,
+    kSkewY_MatrixType,
+    kTranslateX_MatrixType,
+    kTranslateY_MatrixType,
+    kSwapScaleXY_MatrixType,
+    kPersp_MatrixType,
+
+    kMatrixTypeCount
+};
+
+static void create_matrix(GrMatrix* matrix, GrRandom& rand) {
+    MatrixType type = (MatrixType)(rand.nextU() % kMatrixTypeCount);
+    switch (type) {
+        case kRotate_MatrixType: {
+            float angle = rand.nextF() * 2 *3.14159265358979323846f;
+            GrScalar cosa = GrFloatToScalar(cosf(angle));
+            GrScalar sina = GrFloatToScalar(sinf(angle));
+            matrix->setAll(cosa,      -sina,           0,
+                           sina,       cosa,           0,
+                           0,          0,              GrMatrix::I()[8]);
+        } break;
+        case kScaleX_MatrixType: {
+            GrScalar scale = GrFloatToScalar(rand.nextF(-2, 2));
+            matrix->setAll(scale,      0,              0,
+                           0,          GR_Scalar1,     0,
+                           0,          0,              GrMatrix::I()[8]);
+        } break;
+        case kScaleY_MatrixType: {
+            GrScalar scale = GrFloatToScalar(rand.nextF(-2, 2));
+            matrix->setAll(GR_Scalar1, 0,              0,
+                           0,          scale,          0,
+                           0,          0,              GrMatrix::I()[8]);
+        } break;
+        case kSkewX_MatrixType: {
+            GrScalar skew = GrFloatToScalar(rand.nextF(-2, 2));
+            matrix->setAll(GR_Scalar1, skew,           0,
+                           0,          GR_Scalar1,     0,
+                           0,          0,              GrMatrix::I()[8]);
+        } break;
+        case kSkewY_MatrixType: {
+            GrScalar skew = GrFloatToScalar(rand.nextF(-2, 2));
+            matrix->setAll(GR_Scalar1, 0,              0,
+                           skew,       GR_Scalar1,     0,
+                           0,          0,              GrMatrix::I()[8]);
+        } break;
+        case kTranslateX_MatrixType: {
+            GrScalar trans = GrFloatToScalar(rand.nextF(-10, 10));
+            matrix->setAll(GR_Scalar1, 0,              trans,
+                           0,          GR_Scalar1,     0,
+                           0,          0,              GrMatrix::I()[8]);
+        } break;
+        case kTranslateY_MatrixType: {
+            GrScalar trans = GrFloatToScalar(rand.nextF(-10, 10));
+            matrix->setAll(GR_Scalar1, 0,              0,
+                           0,          GR_Scalar1,     trans,
+                           0,          0,              GrMatrix::I()[8]);
+        } break;
+        case kSwapScaleXY_MatrixType: {
+            GrScalar xy = GrFloatToScalar(rand.nextF(-2, 2));
+            GrScalar yx = GrFloatToScalar(rand.nextF(-2, 2));
+            matrix->setAll(0,          xy,             0,
+                           yx,         0,              0,
+                           0,          0,              GrMatrix::I()[8]);
+        } break;
+        case kPersp_MatrixType: {
+            GrScalar p0 = GrFloatToScalar(rand.nextF(-2, 2));
+            GrScalar p1 = GrFloatToScalar(rand.nextF(-2, 2));
+            GrScalar p2 = GrFloatToScalar(rand.nextF(-0.5f, 0.75f));
+            matrix->setAll(GR_Scalar1, 0,              0,
+                           0,          GR_Scalar1,     0,
+                           p0,         p1,             GrMul(p2,GrMatrix::I()[8]));
+        } break;
+        default:
+            GrAssert(0);
+            break;
+    }
+}
+#endif
+
+void GrMatrix::UnitTest() {
+    GrRandom rand;
+
+    // Create a bunch of matrices and test point mapping, max stretch calc,
+    // inversion and multiply-by-inverse.
+#if GR_DEBUG
+    for (int i = 0; i < 10000; ++i) {
+        GrMatrix a, b;
+        a.setIdentity();
+        int num = rand.nextU() % 6;
+        // force testing of I and swapXY
+        if (0 == i) {
+            num = 0;
+            GrAssert(a.isIdentity());
+        } else if (1 == i) {
+            num = 0;
+            a.setAll(0, GR_Scalar1, 0,
+                     GR_Scalar1, 0, 0,
+                     0, 0, I()[8]);
+        }
+        for (int j = 0; j < num; ++j) {
+            create_matrix(&b, rand);
+            a.preConcat(b);
+        }
+
+        GrScalar maxStretch = a.getMaxStretch();
+        if (maxStretch > 0) {
+            maxStretch = GrMul(GR_Scalar1 + GR_Scalar1 / 100, maxStretch);
+        }
+        GrPoint origin = a.mapPoint(GrPoint(0,0));
+
+        for (int j = 0; j < 9; ++j) {
+            int mask, origMask = a.fTypeMask;
+            GrScalar old = a[j];
+
+            a.set(j, GR_Scalar1);
+            mask = a.fTypeMask;
+            a.computeTypeMask();
+            GrAssert(mask == a.fTypeMask);
+
+            a.set(j, 0);
+            mask = a.fTypeMask;
+            a.computeTypeMask();
+            GrAssert(mask == a.fTypeMask);
+
+            a.set(j, 10 * GR_Scalar1);
+            mask = a.fTypeMask;
+            a.computeTypeMask();
+            GrAssert(mask == a.fTypeMask);
+
+            a.set(j, old);
+            GrAssert(a.fTypeMask == origMask);
+        }
+
+        for (int j = 0; j < 100; ++j) {
+            GrPoint pt;
+            pt.fX = GrFloatToScalar(rand.nextF(-10, 10));
+            pt.fY = GrFloatToScalar(rand.nextF(-10, 10));
+
+            GrPoint t0, t1, t2;
+            t0 = a.mapPoint(pt);             // map to a new point
+            t1 = pt;
+            a.mapPoints(&t1, &t1, 1);        // in place
+            a.mapPerspective(&t2, &pt, 1);   // full mult
+            GrAssert(t0 == t1 && t1 == t2);
+            if (maxStretch >= 0.f) {
+                GrVec vec;
+                vec.setBetween(t0, origin);
+                GrScalar stretch = vec.length() / pt.distanceToOrigin();
+                GrAssert(stretch <= maxStretch);
+            }
+        }
+        double det = a.determinant();
+        if (fabs(det) > 1e-3 && a.invert(&b)) {
+            GrMatrix c;
+            c.setConcat(a,b);
+            for (int i = 0; i < 9; ++i) {
+                GrScalar diff = GrScalarAbs(c[i] - I()[i]);
+                GrAssert(diff < (5*GR_Scalar1 / 100));
+            }
+        }
+    }
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+int Gr_clz(uint32_t n) {
+    if (0 == n) {
+        return 32;
+    }
+
+    int count = 0;
+    if (0 == (n & 0xFFFF0000)) {
+        count += 16;
+        n <<= 16;
+    }
+    if (0 == (n & 0xFF000000)) {
+        count += 8;
+        n <<= 8;
+    }
+    if (0 == (n & 0xF0000000)) {
+        count += 4;
+        n <<= 4;
+    }
+    if (0 == (n & 0xC0000000)) {
+        count += 2;
+        n <<= 2;
+    }
+    if (0 == (n & 0x80000000)) {
+        count += 1;
+    }
+    return count;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+#include "GrRect.h"
+
+void GrRect::setBounds(const GrPoint pts[], int count) {
+    if (count <= 0) {
+        this->setEmpty();
+    } else {
+        GrScalar L, R, T, B;
+        L = R = pts[0].fX;
+        T = B = pts[0].fY;
+        for (int i = 1; i < count; i++) {
+            GrScalar x = pts[i].fX;
+            GrScalar y = pts[i].fY;
+            if (x < L) {
+                L = x;
+            } else if (x > R) {
+                R = x;
+            }
+            if (y < T) {
+                T = y;
+            } else if (y > B) {
+                B = y;
+            }
+        }
+        this->setLTRB(L, T, R, B);
+    }
+}
+
+
+