Correctly determine whether HW AA lines can be used
Review URL: http://codereview.appspot.com/4937049/



git-svn-id: http://skia.googlecode.com/svn/trunk@2162 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/include/GrContext.h b/gpu/include/GrContext.h
index 2f98cdf..e07cf42 100644
--- a/gpu/include/GrContext.h
+++ b/gpu/include/GrContext.h
@@ -586,7 +586,7 @@
     // determines whether offscreen AA should be applied
     bool doOffscreenAA(GrDrawTarget* target, 
                        const GrPaint& paint,
-                       bool isLines) const;
+                       bool isHairLines) const;
 
     // attempts to setup offscreen AA. All paint state must be transferred to
     // target by the time this is called.
diff --git a/gpu/include/GrTypes.h b/gpu/include/GrTypes.h
index e9fb3e6..c51ee12 100644
--- a/gpu/include/GrTypes.h
+++ b/gpu/include/GrTypes.h
@@ -197,8 +197,8 @@
     kTriangleStrip_PrimitiveType,
     kTriangleFan_PrimitiveType,
     kPoints_PrimitiveType,
-    kLines_PrimitiveType,
-    kLineStrip_PrimitiveType
+    kLines_PrimitiveType,     // 1 pix wide only
+    kLineStrip_PrimitiveType  // 1 pix wide only
 };
 
 static inline bool GrIsPrimTypeLines(GrPrimitiveType type) {
diff --git a/gpu/src/GrContext.cpp b/gpu/src/GrContext.cpp
index 9c3f298..7bac3ba 100644
--- a/gpu/src/GrContext.cpp
+++ b/gpu/src/GrContext.cpp
@@ -630,16 +630,16 @@
     GrClip                         fClip;
 };
 
-bool GrContext::doOffscreenAA(GrDrawTarget* target, 
+bool GrContext::doOffscreenAA(GrDrawTarget* target,
                               const GrPaint& paint,
-                              bool isLines) const {
+                              bool isHairLines) const {
 #if !GR_USE_OFFSCREEN_AA
     return false;
 #else
     if (!paint.fAntiAlias) {
         return false;
     }
-    if (isLines && fGpu->supportsAALines()) {
+    if (isHairLines && target->willUseHWAALines()) {
         return false;
     }
     if (target->getRenderTarget()->isMultisampled()) {
@@ -1114,7 +1114,6 @@
 }
 
 static bool apply_aa_to_rect(GrDrawTarget* target,
-                             GrGpu* gpu,
                              const GrPaint& paint,
                              const GrRect& rect,
                              GrScalar width, 
@@ -1134,7 +1133,7 @@
         return false;
     }
 
-    if (0 == width && gpu->supportsAALines()) {
+    if (0 == width && target->willUseHWAALines()) {
         return false;
     }
 
@@ -1174,7 +1173,7 @@
 
     GrRect devRect = rect;
     GrMatrix combinedMatrix;
-    bool doAA = apply_aa_to_rect(target, fGpu, paint, rect, width, matrix, 
+    bool doAA = apply_aa_to_rect(target, paint, rect, width, matrix, 
                                  &combinedMatrix, &devRect);
 
     if (doAA) {
@@ -1769,7 +1768,8 @@
                                    DRAW_BUFFER_IBPOOL_BUFFER_SIZE,
                                    DRAW_BUFFER_IBPOOL_PREALLOC_BUFFERS);
 
-    fDrawBuffer = new GrInOrderDrawBuffer(fDrawBufferVBAllocPool,
+    fDrawBuffer = new GrInOrderDrawBuffer(fGpu,
+                                          fDrawBufferVBAllocPool,
                                           fDrawBufferIBAllocPool);
 #endif
 
diff --git a/gpu/src/GrDrawTarget.cpp b/gpu/src/GrDrawTarget.cpp
index 7efe381..29a37a4 100644
--- a/gpu/src/GrDrawTarget.cpp
+++ b/gpu/src/GrDrawTarget.cpp
@@ -695,47 +695,47 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
-bool GrDrawTarget::canDisableBlend() const {
+bool GrDrawTarget::CanDisableBlend(GrVertexLayout layout, const DrState& state) {
     // If we compute a coverage value (using edge AA or a coverage stage) then
     // we can't force blending off.
-    if (fCurrDrawState.fEdgeAANumEdges > 0) {
+    if (state.fEdgeAANumEdges > 0) {
         return false;
     }
-    for (int s = fCurrDrawState.fFirstCoverageStage; s < kNumStages; ++s) {
-        if (this->isStageEnabled(s)) {
+    for (int s = state.fFirstCoverageStage; s < kNumStages; ++s) {
+        if (StageWillBeUsed(s, layout, state)) {
             return false;
         }
     }
 
-    if ((kOne_BlendCoeff == fCurrDrawState.fSrcBlend) &&
-        (kZero_BlendCoeff == fCurrDrawState.fDstBlend)) {
+    if ((kOne_BlendCoeff == state.fSrcBlend) &&
+        (kZero_BlendCoeff == state.fDstBlend)) {
             return true;
     }
 
     // If we have vertex color without alpha then we can't force blend off
-    if ((this->getGeomSrc().fVertexLayout & kColor_VertexLayoutBit) ||
-         0xff != GrColorUnpackA(fCurrDrawState.fColor)) {
+    if ((layout & kColor_VertexLayoutBit) ||
+         0xff != GrColorUnpackA(state.fColor)) {
         return false;
     }
 
     // If the src coef will always be 1...
-    if (kSA_BlendCoeff != fCurrDrawState.fSrcBlend &&
-        kOne_BlendCoeff != fCurrDrawState.fSrcBlend) {
+    if (kSA_BlendCoeff != state.fSrcBlend &&
+        kOne_BlendCoeff != state.fSrcBlend) {
         return false;
     }
 
     // ...and the dst coef is always 0...
-    if (kISA_BlendCoeff != fCurrDrawState.fDstBlend &&
-        kZero_BlendCoeff != fCurrDrawState.fDstBlend) {
+    if (kISA_BlendCoeff != state.fDstBlend &&
+        kZero_BlendCoeff != state.fDstBlend) {
         return false;
     }
 
     // ...and there isn't a texture stage with an alpha channel...
-    for (int s = 0; s < fCurrDrawState.fFirstCoverageStage; ++s) {
-        if (this->isStageEnabled(s)) {
-            GrAssert(NULL != fCurrDrawState.fTextures[s]);
+    for (int s = 0; s < state.fFirstCoverageStage; ++s) {
+        if (StageWillBeUsed(s, layout, state)) {
+            GrAssert(NULL != state.fTextures[s]);
 
-            GrPixelConfig config = fCurrDrawState.fTextures[s]->config();
+            GrPixelConfig config = state.fTextures[s]->config();
 
             if (!GrPixelConfigIsOpaque(config)) {
                 return false;
@@ -746,7 +746,7 @@
     // ...and there isn't an interesting color filter...
     // TODO: Consider being more aggressive with regards to disabling
     // blending when a color filter is used.
-    if (SkXfermode::kDst_Mode != fCurrDrawState.fColorFilterXfermode) {
+    if (SkXfermode::kDst_Mode != state.fColorFilterXfermode) {
         return false;
     }
 
@@ -754,7 +754,21 @@
     return true;
 }
 
+bool GrDrawTarget::CanUseHWAALines(GrVertexLayout layout, const DrState& state) {
+    // there is a conflict between using smooth lines and our use of
+    // premultiplied alpha. Smooth lines tweak the incoming alpha value
+    // but not in a premul-alpha way. So we only use them when our alpha
+    // is 0xff.
+    return (kAntialias_StateBit & state.fFlagBits) &&
+           CanDisableBlend(layout, state);
+}
+
+bool GrDrawTarget::canDisableBlend() const {
+    return CanDisableBlend(this->getGeomSrc().fVertexLayout, fCurrDrawState);
+}
+
 ///////////////////////////////////////////////////////////////////////////////
+
 void GrDrawTarget::setEdgeAAData(const Edge* edges, int numEdges) {
     GrAssert(numEdges <= kMaxEdges);
     memcpy(fCurrDrawState.fEdgeAAEdges, edges, numEdges * sizeof(Edge));
diff --git a/gpu/src/GrDrawTarget.h b/gpu/src/GrDrawTarget.h
index 8196beb..f170fda 100644
--- a/gpu/src/GrDrawTarget.h
+++ b/gpu/src/GrDrawTarget.h
@@ -536,6 +536,13 @@
     bool canDisableBlend() const;
 
     /**
+     * Given the current draw state, vertex layout, and hw support, will HW AA
+     * lines be used (if line primitive type is drawn)? (Note that lines are
+     * always 1 pixel wide)
+     */
+    virtual bool willUseHWAALines() const = 0;
+
+    /**
      * Sets the edge data required for edge antialiasing.
      *
      * @param edges       3 * 6 float values, representing the edge
@@ -1142,7 +1149,13 @@
     static void VertexLayoutUnitTest();
 
 protected:
-    
+
+    // determines whether HW blending can be disabled or not
+    static bool CanDisableBlend(GrVertexLayout layout, const DrState& state);
+
+    // determines whether HW AA lines can be used or not
+    static bool CanUseHWAALines(GrVertexLayout layout, const DrState& state);
+
     enum GeometrySrcType {
         kNone_GeometrySrcType,     //<! src has not been specified
         kReserved_GeometrySrcType, //<! src was set using reserve*Space
diff --git a/gpu/src/GrGpu.cpp b/gpu/src/GrGpu.cpp
index 24950c4..b492952 100644
--- a/gpu/src/GrGpu.cpp
+++ b/gpu/src/GrGpu.cpp
@@ -142,6 +142,13 @@
 
 ////////////////////////////////////////////////////////////////////////////////
 
+bool GrGpu::willUseHWAALines() const {
+    return (kAntialias_StateBit & fCurrDrawState.fFlagBits) &&
+           CanUseHWAALines(this->getGeomSrc().fVertexLayout, fCurrDrawState);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+
 GrTexture* GrGpu::createTexture(const GrTextureDesc& desc,
                                 const void* srcData, size_t rowBytes) {
     this->handleDirtyContext();
diff --git a/gpu/src/GrGpu.h b/gpu/src/GrGpu.h
index deaba67..1e9505b 100644
--- a/gpu/src/GrGpu.h
+++ b/gpu/src/GrGpu.h
@@ -181,7 +181,7 @@
      * Does the 3D API support anti-aliased lines. If so then line primitive
      * types will use this functionality when the AA state flag is set.
      */
-    bool supportsAALines() const { return fAALineSupport; }
+    bool supportsHWAALines() const { return fAALineSupport; }
 
     /**
      * Does the subclass support GrSamplerState::k4x4Downsample_Filter
@@ -319,6 +319,9 @@
      */
     void removeResource(GrResource* resource);
 
+    // GrDrawTarget overrides
+    virtual bool willUseHWAALines() const;
+
 protected:
     enum PrivateStateBits {
         kFirstBit = (kLastPublicStateBit << 1),
diff --git a/gpu/src/GrGpuGL.cpp b/gpu/src/GrGpuGL.cpp
index ba7615d..936ada3 100644
--- a/gpu/src/GrGpuGL.cpp
+++ b/gpu/src/GrGpuGL.cpp
@@ -1813,18 +1813,6 @@
     }
 }
 
-bool GrGpuGL::useSmoothLines() {
-    // there is a conflict between using smooth lines and our use of
-    // premultiplied alpha. Smooth lines tweak the incoming alpha value
-    // but not in a premul-alpha way. So we only use them when our alpha
-    // is 0xff.
-
-    // TODO: write a smarter line frag shader.
-
-    return (kAntialias_StateBit & fCurrDrawState.fFlagBits) &&
-           canDisableBlend();
-}
-
 void GrGpuGL::flushAAState(GrPrimitiveType type) {
     if (kDesktop_GrGLBinding == this->glBinding()) {
         // ES doesn't support toggling GL_MULTISAMPLE and doesn't have
@@ -1833,7 +1821,7 @@
         // we prefer smooth lines over multisampled lines
         // msaa should be disabled if drawing smooth lines.
         if (GrIsPrimTypeLines(type)) {
-            bool smooth = useSmoothLines();
+            bool smooth = this->willUseHWAALines();
             if (!fHWAAState.fSmoothLineEnabled && smooth) {
                 GL_CALL(Enable(GR_GL_LINE_SMOOTH));
                 fHWAAState.fSmoothLineEnabled = true;
@@ -1863,7 +1851,7 @@
 void GrGpuGL::flushBlend(GrPrimitiveType type, 
                          GrBlendCoeff srcCoeff, 
                          GrBlendCoeff dstCoeff) {
-    if (GrIsPrimTypeLines(type) && useSmoothLines()) {
+    if (GrIsPrimTypeLines(type) && this->willUseHWAALines()) {
         if (fHWBlendDisabled) {
             GL_CALL(Enable(GR_GL_BLEND));
             fHWBlendDisabled = false;
diff --git a/gpu/src/GrGpuGL.h b/gpu/src/GrGpuGL.h
index b45928f..30a50e1 100644
--- a/gpu/src/GrGpuGL.h
+++ b/gpu/src/GrGpuGL.h
@@ -164,8 +164,6 @@
 
     void setSpareTextureUnit();
 
-    bool useSmoothLines();
-
     // bound is region that may be modified and therefore has to be resolved.
     // NULL means whole target. Can be an empty rect.
     void flushRenderTarget(const GrIRect* bound);
diff --git a/gpu/src/GrInOrderDrawBuffer.cpp b/gpu/src/GrInOrderDrawBuffer.cpp
index 39bf275..85af430 100644
--- a/gpu/src/GrInOrderDrawBuffer.cpp
+++ b/gpu/src/GrInOrderDrawBuffer.cpp
@@ -15,9 +15,11 @@
 #include "GrVertexBuffer.h"
 #include "GrGpu.h"
 
-GrInOrderDrawBuffer::GrInOrderDrawBuffer(GrVertexBufferAllocPool* vertexPool,
+GrInOrderDrawBuffer::GrInOrderDrawBuffer(const GrGpu* gpu,
+                                         GrVertexBufferAllocPool* vertexPool,
                                          GrIndexBufferAllocPool* indexPool)
-    : fDraws(&fDrawStorage)
+    : fGpu(gpu)
+    , fDraws(&fDrawStorage)
     , fStates(&fStateStorage)
     , fClears(&fClearStorage)
     , fClips(&fClipStorage)
@@ -35,6 +37,8 @@
     GrAssert(NULL != vertexPool);
     GrAssert(NULL != indexPool);
 
+    gpu->ref();
+
     GeometryPoolState& poolState = fGeoPoolStateStack.push_back();
     poolState.fUsedPoolVertexBytes = 0;
     poolState.fUsedPoolIndexBytes = 0;
@@ -49,6 +53,7 @@
 GrInOrderDrawBuffer::~GrInOrderDrawBuffer() {
     this->reset();
     GrSafeUnref(fQuadIndexBuffer);
+    fGpu->unref();
 }
 
 void GrInOrderDrawBuffer::initializeDrawStateAndClip(const GrDrawTarget& target) {
@@ -620,3 +625,9 @@
     INHERITED::clipWillBeSet(newClip);
     fClipSet = true;
 }
+
+bool GrInOrderDrawBuffer::willUseHWAALines() const {
+    return fGpu->supportsHWAALines() &&
+           CanUseHWAALines(this->getGeomSrc().fVertexLayout, fCurrDrawState);
+}
+
diff --git a/gpu/src/GrInOrderDrawBuffer.h b/gpu/src/GrInOrderDrawBuffer.h
index 2a3bddb..dbf6144 100644
--- a/gpu/src/GrInOrderDrawBuffer.h
+++ b/gpu/src/GrInOrderDrawBuffer.h
@@ -16,8 +16,9 @@
 #include "GrAllocator.h"
 #include "GrClip.h"
 
-class GrVertexBufferAllocPool;
+class GrGpu;
 class GrIndexBufferAllocPool;
+class GrVertexBufferAllocPool;
 
 /**
  * GrInOrderDrawBuffer is an implementation of GrDrawTarget that queues up
@@ -37,12 +38,16 @@
     /**
      * Creates a GrInOrderDrawBuffer
      *
+     * @param gpu        the gpu object where this will be played back
+     *                   (possible indirectly). GrResources used with the draw
+     *                   buffer are created by this gpu object.
      * @param vertexPool pool where vertices for queued draws will be saved when
      *                   the vertex source is either reserved or array.
      * @param indexPool  pool where indices for queued draws will be saved when
      *                   the index source is either reserved or array.
      */
-    GrInOrderDrawBuffer(GrVertexBufferAllocPool* vertexPool,
+    GrInOrderDrawBuffer(const GrGpu* gpu,
+                        GrVertexBufferAllocPool* vertexPool,
                         GrIndexBufferAllocPool* indexPool);
 
     virtual ~GrInOrderDrawBuffer();
@@ -86,6 +91,8 @@
 
     virtual void clear(const GrIRect* rect, GrColor color);
 
+    virtual bool willUseHWAALines() const;
+
 private:
 
     struct Draw {
@@ -138,6 +145,7 @@
     void pushState();
     void pushClip();
 
+    const GrGpu*                    fGpu;
     GrTAllocator<Draw>              fDraws;
     GrTAllocator<SavedDrawState>    fStates;
     GrTAllocator<Clear>             fClears;