Make GrDrawState ref counted. (Small step towards a perf improvement.)

Review URL: http://codereview.appspot.com/5905069/




git-svn-id: http://skia.googlecode.com/svn/trunk@3498 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/gpu/GrDrawState.h b/src/gpu/GrDrawState.h
index 92ee2cb..dd63d6e 100644
--- a/src/gpu/GrDrawState.h
+++ b/src/gpu/GrDrawState.h
@@ -11,6 +11,7 @@
 #include "GrColor.h"
 #include "GrMatrix.h"
 #include "GrNoncopyable.h"
+#include "GrRefCnt.h"
 #include "GrSamplerState.h"
 #include "GrStencil.h"
 
@@ -19,8 +20,9 @@
 class GrRenderTarget;
 class GrTexture;
 
-struct GrDrawState {
+class GrDrawState : public GrRefCnt {
 
+public:
     /**
      * Number of texture stages. Each stage takes as input a color and
      * 2D texture coordinates. The color input to the first enabled stage is the
@@ -62,10 +64,8 @@
         // all GrDrawState members should default to something valid by the
         // the memset except those initialized individually below. There should
         // be no padding between the individually initialized members.
-        static const size_t kMemsetSize =
-            reinterpret_cast<intptr_t>(&fColor) -
-            reinterpret_cast<intptr_t>(this);
-        memset(this, 0, kMemsetSize);
+        memset(this->podStart(), 0, this->memsetSize());
+
         // pedantic assertion that our ptrs will
         // be NULL (0 ptr is mem addr 0)
         GrAssert((intptr_t)(void*)NULL == 0LL);
@@ -83,11 +83,10 @@
 
         // ensure values that will be memcmp'ed in == but not memset in reset()
         // are tightly packed
-        GrAssert(kMemsetSize +  sizeof(fColor) + sizeof(fCoverage) +
+        GrAssert(this->memsetSize() +  sizeof(fColor) + sizeof(fCoverage) +
                  sizeof(fFirstCoverageStage) + sizeof(fColorFilterMode) +
                  sizeof(fSrcBlend) + sizeof(fDstBlend) ==
-                 reinterpret_cast<uintptr_t>(&fViewMatrix) -
-                 reinterpret_cast<uintptr_t>(this));
+                 this->podSize());
 
         fEdgeAANumEdges = 0;
     }
@@ -740,7 +739,7 @@
     // Most stages are usually not used, so conditionals here
     // reduce the expected number of bytes touched by 50%.
     bool operator ==(const GrDrawState& s) const {
-        if (memcmp(this, &s, this->leadingBytes())) {
+        if (memcmp(this->podStart(), s.podStart(), this->podSize())) {
             return false;
         }
 
@@ -770,7 +769,7 @@
     // Most stages are usually not used, so conditionals here 
     // reduce the expected number of bytes touched by 50%.
     GrDrawState& operator =(const GrDrawState& s) {
-        memcpy(this, &s, this->leadingBytes());
+        memcpy(this->podStart(), s.podStart(), this->podSize());
 
         fViewMatrix = s.fViewMatrix;
 
@@ -788,25 +787,57 @@
     }
 
 private:
+
+    const void* podStart() const {
+        return reinterpret_cast<const void*>(&fPodStartMarker);
+    }
+    void* podStart() {
+        return reinterpret_cast<void*>(&fPodStartMarker);
+    }
+    size_t memsetSize() const {
+        return reinterpret_cast<size_t>(&fMemsetEndMarker) -
+               reinterpret_cast<size_t>(&fPodStartMarker) +
+               sizeof(fMemsetEndMarker);
+    }
+    size_t podSize() const {
+        // Can't use offsetof() with non-POD types, so stuck with pointer math.
+        // TODO: ignores GrTesselatedPathRenderer data structures. We don't
+        // have a compile-time flag that lets us know if it's being used, and
+        // checking at runtime seems to cost 5% performance.
+        return reinterpret_cast<size_t>(&fPodEndMarker) -
+               reinterpret_cast<size_t>(&fPodStartMarker) +
+               sizeof(fPodEndMarker);
+    }
+
     static const StageMask kIllegalStageMaskBits = ~((1 << kNumStages)-1);
     // @{ these fields can be initialized with memset to 0
-    GrColor             fBlendConstant;
+    union {
+        GrColor             fBlendConstant;
+        GrColor             fPodStartMarker;
+    };
     GrTexture*          fTextures[kNumStages];
     GrColor             fColorFilterColor;
     uint32_t            fFlagBits;
     DrawFace            fDrawFace; 
     VertexEdgeType      fVertexEdgeType;
     GrStencilSettings   fStencilSettings;
-    GrRenderTarget*     fRenderTarget;
+    union {
+        GrRenderTarget* fRenderTarget;
+        GrRenderTarget* fMemsetEndMarker;
+    };
     // @}
 
-    // @{ Initialized to values other than zero
+    // @{ Initialized to values other than zero, but memcmp'ed in operator==
+    // and memcpy'ed in operator=.
     GrColor             fColor;
     GrColor             fCoverage;
     int                 fFirstCoverageStage;
     SkXfermode::Mode    fColorFilterMode;
     GrBlendCoeff        fSrcBlend;
-    GrBlendCoeff        fDstBlend;
+    union {
+        GrBlendCoeff    fDstBlend;
+        GrBlendCoeff    fPodEndMarker;
+    };
     // @}
 
     GrMatrix            fViewMatrix;
@@ -824,15 +855,6 @@
     // only compared if the color matrix enable flag is set
     float               fColorMatrix[20];       // 5 x 4 matrix
 
-    size_t leadingBytes() const {
-        // Can't use offsetof() with non-POD types, so stuck with pointer math.
-        // TODO: ignores GrTesselatedPathRenderer data structures. We don't
-        // have a compile-time flag that lets us know if it's being used, and
-        // checking at runtime seems to cost 5% performance.
-        return (size_t) ((unsigned char*)&fViewMatrix -
-                         (unsigned char*)&fBlendConstant);
-    }
-
 };
 
 #endif