Towards issue #106

Adds notion of texture multiple stages but currently just uses 1.


git-svn-id: http://skia.googlecode.com/svn/trunk@694 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/gpu/include/GrDrawTarget.h b/gpu/include/GrDrawTarget.h
index 2823da7..3405bb5 100644
--- a/gpu/include/GrDrawTarget.h
+++ b/gpu/include/GrDrawTarget.h
@@ -34,6 +34,27 @@
 class GrDrawTarget : 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 
+     * per-vertex color or the constant color (setColor/setAlpha) if there are no
+     * per-vertex colors. For subsequent stages the input color is the output  
+     * color from the previous enabled stage. The output color of each stage is
+     * the input color modulated with the result of a texture lookup. Texture 
+     * lookups are specified by a texture (setTexture), a texture matrix
+     * (setTextureMatrix), and a sampler (setSamplerState). Texture coordinates 
+     * for each stage come from the vertices based on a GrVertexLayout bitfield.
+     * The output fragment color is the output color of the last enabled stage.
+     * The presence or absence of texture coordinates for each stage in the 
+     * vertex layout indicates whether a stage is enabled or not.
+     */
+    
+    // Currently there is just one stage but this will be changed soon.
+    enum {
+        kNumStages = 1,
+        kMaxTexCoords = kNumStages
+    };
+    
+    /**
      * Geometric primitives used for drawing.
      */
     enum PrimitiveType {
@@ -124,25 +145,20 @@
     };
 
 protected:
-    enum MatrixMode {
-        kModelView_MatrixMode = 0,
-        kTexture_MatrixMode,
-
-        kMatrixModeCount
-    };
 
     struct DrState {
         uint32_t                fFlagBits;
         BlendCoeff          	fSrcBlend;
         BlendCoeff          	fDstBlend;
-        GrTexture*          	fTexture;
-        GrSamplerState        	fSamplerState;
+        GrTexture*          	fTextures[kNumStages];
+        GrSamplerState        	fSamplerStates[kNumStages];
         GrRenderTarget*     	fRenderTarget;
         GrColor             	fColor;
         float               	fPointSize;
         StencilPass             fStencilPass;
         bool                    fReverseFill;
-        GrMatrix                fMatrixModeCache[kMatrixModeCount];
+        GrMatrix                fViewMatrix;
+        GrMatrix                fTextureMatrices[kNumStages];
         bool operator ==(const DrState& s) const {
             return 0 == memcmp(this, &s, sizeof(DrState));
         }
@@ -172,10 +188,12 @@
     /**
      * Sets the texture used at the next drawing call
      *
+     * @param stage The texture stage for which the texture will be set
+     *
      * @param texture The texture to set. Can be NULL though there is no advantage
      * to settings a NULL texture if doing non-textured drawing
      */
-    void setTexture(GrTexture* texture);
+    void setTexture(int stage, GrTexture* texture);
 
     /**
      * Retrieves the currently set texture.
@@ -184,7 +202,7 @@
      *            texture has been set, NULL was most recently passed to
      *            setTexture, or the last setTexture was destroyed.
      */
-    GrTexture* currentTexture() const;
+    GrTexture* currentTexture(int stage) const;
 
     /**
      * Sets the rendertarget used at the next drawing call
@@ -210,10 +228,10 @@
      *
      * @param samplerState    Specifies the sampler state.
      */
-    void setSamplerState(const GrSamplerState& samplerState);
+    void setSamplerState(int stage, const GrSamplerState& samplerState);
 
     /**
-     * Sets the matrix applied to texture coordinates.
+     * Sets the matrix applied to texture coordinates for a stage.
      *
      * The post-matrix texture coordinates in the square [0,1]^2 cover the
      * entire area of the texture. This means the full POT width when a NPOT
@@ -223,11 +241,10 @@
      * coordinates. In the latter case the texture matrix is applied to the
      * pre-modelview position values.
      *
-     * @param m the matrix used to transform the texture coordinates.
+     * @param stage the stage for which to set a matrix.
+     * @param m     the matrix used to transform the texture coordinates.
      */
-    void setTextureMatrix(const GrMatrix& m) {
-        this->loadMatrix(m, kTexture_MatrixMode);
-    }
+    void setTextureMatrix(int stage, const GrMatrix& m);
 
     /**
      * Sets the matrix applied to veretx positions.
@@ -238,9 +255,7 @@
      *
      * @param m the matrix used to transform the vertex positions.
      */
-    void setViewMatrix(const GrMatrix& m) {
-        this->loadMatrix(m, kModelView_MatrixMode);
-    }
+    void setViewMatrix(const GrMatrix& m);
 
     /**
      *  Multiplies the current view matrix by a matrix
@@ -379,38 +394,77 @@
     void copyDrawState(const GrDrawTarget& srcTarget);
 
     /**
-     * Flags that indicate the layout of vertex data.
+     * The format of vertices is represented as a bitfield of flags.
+     * Flags that indicate the layout of vertex data. Vertices always contain
+     * positions and may also contain up to kMaxTexCoords sets of 2D texture 
+     * coordinates and per-vertex colors. Each stage can use any of the texture
+     * coordinates as its input texture coordinates or it may use the positions.
      *
-     * kSeparateTexCoord_VertexLayoutBit is incompatible with
-     * kPositionAsTexCoord_VertexLayoutBit. kTextFormat_VertexLayoutBit is
-     * incompatible with any other flags.
+     * If no texture coordinates are specified for a stage then the stage is
+     * disabled.
      *
-     * When kTextFormat_VertexLayoutBit is set:
-     *      Texture coordinates are separate.
-     *      Positions and Texture coordinates are SkGpuTextVertex.
-     * For non-text vertices:
-     *      Position and texture coordinates are GrPoints.
-     *      Colors are GrColors.
+     * Only one type of texture coord can be specified per stage. For
+     * example StageTexCoordVertexLayoutBit(0, 2) and 
+     * StagePosAsTexCoordVertexLayoutBit(0) cannot both be specified.
      *
-     * The order is always positions, texture coords, colors.
+     * The order in memory is always (position, texture coord 0, ..., color) 
+     * with any unused fields omitted. Note that this means that if only texture
+     * coordinates 1 is referenced then there is no texture coordinates 0 and 
+     * the order would be (position, texture coordinate 1[, color]).
+     */
+    
+    /**
+     * Generates a bit indicating that a texture stage uses texture coordinates
+     * 
+     * @param stage       the stage that will use texture coordinates.
+     * @param texCoordIdx the index of the texture coordinates to use
+     *
+     * @return the bit to add to a GrVertexLayout bitfield.
+     */
+    static int StageTexCoordVertexLayoutBit(int stage, int texCoordIdx) {
+        GrAssert(stage < kNumStages);
+        GrAssert(texCoordIdx < kMaxTexCoords);
+        return 1 << (stage + (texCoordIdx * kNumStages));
+    }
+private:
+    static const int TEX_COORD_BIT_CNT = kNumStages*kMaxTexCoords;
+public:
+    /**
+     * Generates a bit indicating that a texture stage uses the position
+     * as its texture coordinate.
+     *
+     * @param stage       the stage that will use position as texture 
+     *                    coordinates.
+     *
+     * @return the bit to add to a GrVertexLayout bitfield.
+     */
+    static int StagePosAsTexCoordVertexLayoutBit(int stage) {
+        GrAssert(stage < kNumStages);
+        return (1 << (TEX_COORD_BIT_CNT + stage)); 
+    }
+private:
+    static const int STAGE_BIT_CNT = TEX_COORD_BIT_CNT + kNumStages;
+    
+public:
+    
+    /**
+     * Additional Bits that can be specified in GrVertexLayout.
      */
     enum VertexLayoutBits {
-        kSeparateTexCoord_VertexLayoutBit   = 0x1, //<! vertices have texture
-                                                   //   coords that are not
-                                                   //   inferred from the
-                                                   //   positions
-        kPositionAsTexCoord_VertexLayoutBit = 0x2, //<! vertices use positions
-                                                   //   as texture coords.
-        kColor_VertexLayoutBit              = 0x4, //<! vertices have colors
-        kTextFormat_VertexLayoutBit         = 0x8, //<! vertices represent glyphs
-                                                   //   and therefore contain
-                                                   //   two GrGpuTextVertexs.
-                                                   //   One for pos and one for
-                                                   //   text coords.
+        
+        kColor_VertexLayoutBit              = 1 << (STAGE_BIT_CNT + 0),
+                                                //<! vertices have colors
+        kTextFormat_VertexLayoutBit         = 1 << (STAGE_BIT_CNT + 1),
+                                                //<! use text vertices. (Pos
+                                                //   and tex coords may be
+                                                //   a different type for 
+                                                //   text [GrGpuTextVertex vs
+                                                //   GrPoint].)
         // for below assert
         kDummy,
         kHighVertexLayoutBit = kDummy - 1
     };
+    // make sure we haven't exceeded the number of bits in GrVertexLayout.
     GR_STATIC_ASSERT(kHighVertexLayoutBit < (1 << 8*sizeof(GrVertexLayout)));
 
     /**
@@ -619,19 +673,35 @@
     };
 
     ////////////////////////////////////////////////////////////////////////////
-
+    // Helpers for picking apart vertex layouts
+    
     /**
      * Helper function to compute the size of a vertex from a vertex layout
      * @return size of a single vertex.
      */
     static size_t VertexSize(GrVertexLayout vertexLayout);
+    
+    /**
+     * Helper function for determining the index of texture coordinates that
+     * is input for a texture stage. Note that a stage may instead use positions
+     * as texture coordinates, in which case the result of the function is
+     * indistinguishable from the case when the stage is disabled.
+     *
+     * @param stage         the stage to query
+     * @param vertexLayout  layout to query
+     *
+     * @return the texture coordinate index or -1 if the stage doesn't use
+     *         separate (non-position) texture coordinates.
+     */
+    static int VertexTexCoordsForStage(int stage, GrVertexLayout vertexLayout);
 
     /**
      * Helper function to compute the offset of texture coordinates in a vertex
      * @return offset of texture coordinates in vertex layout or -1 if the
-     *         layout has no texture coordinates.
+     *         layout has no texture coordinates. Will be 0 if positions are 
+     *         used as texture coordinates for the stage.
      */
-    static int VertexTexCoordOffset(GrVertexLayout vertexLayout);
+    static int VertexStageCoordOffset(int stage, GrVertexLayout vertexLayout);
 
     /**
      * Helper function to compute the offset of the color in a vertex
@@ -641,27 +711,64 @@
     static int VertexColorOffset(GrVertexLayout vertexLayout);
 
     /**
-     * Helper function to compute vertex size and component offsets.
-     * @param texCoordOffset  after return it is the offset of texture coords
-     *                        in vertex layout or -1 if the layout has no
-     *                        texture coords.
-     * @param colorOffset     after return it is the offset of color in vertex
-     *                        layout or -1 if the layout has no color.
-     * @return size of a single vertex.
+     * Helper function to determine if vertex layout contains explicit texture 
+     * coordinates of some index.
+     *
+     * @param coordIndex    the tex coord index to query
+     * @param vertexLayout  layout to query
+     *
+     * @return true if vertex specifies texture coordinates for the index, 
+     *              false otherwise.
      */
-    static int VertexSizeAndOffsets(GrVertexLayout vertexLayout,
-                                    int* texCoordOffset,
-                                    int* colorOffset);
+    static bool VertexUsesTexCoordIdx(int coordIndex, 
+                                      GrVertexLayout vertexLayout);
+    
     /**
      * Helper function to determine if vertex layout contains either explicit or
-     * implicit texture coordinates.
+     * implicit texture coordinates for a stage.
      *
-     * @return true if vertex specifies texture coordinates, false otherwise.
+     * @param stage         the stage to query
+     * @param vertexLayout  layout to query
+     *
+     * @return true if vertex specifies texture coordinates for the stage, 
+     *              false otherwise.
      */
-    static bool VertexHasTexCoords(GrVertexLayout vertexLayout);
+    static bool VertexUsesStage(int stage, GrVertexLayout vertexLayout);
 
+    /**
+     * Helper function to compute the size of each vertex and the offsets of 
+     * texture coordinates and color. Determines tex coord offsets by tex coord 
+     * index rather than by stage. (Each stage can be mapped to any t.c. index 
+     * by StageTexCoordVertexLayoutBit.)
+     *
+     * @param vertexLayout          the layout to query
+     * @param texCoordOffsetsByIdx  after return it is the offset of each
+     *                              tex coord index in the vertex or -1 if
+     *                              index isn't used.
+     * @return size of a single vertex
+     */
+    static int VertexSizeAndOffsetsByIdx(GrVertexLayout vertexLayout,
+                                         int texCoordOffsetsByIdx[kMaxTexCoords],
+                                         int *colorOffset);
+    
+    /**
+     * Helper function to compute the size of each vertex and the offsets of 
+     * texture coordinates and color. Determines tex coord offsets by stage 
+     * rather than by index. (Each stage can be mapped to any t.c. index 
+     * by StageTexCoordVertexLayoutBit.) If a stage uses positions for 
+     * tex coords then that stage's offset will be 0 (positions are always at 0).
+     *
+     * @param vertexLayout              the layout to query
+     * @param texCoordOffsetsByStage    after return it is the offset of each
+     *                                  tex coord index in the vertex or -1 if
+     *                                  index isn't used.
+     * @return size of a single vertex
+     */
+    static int VertexSizeAndOffsetsByStage(GrVertexLayout vertexLayout,
+                                           int texCoordOffsetsByStage[kNumStages],
+                                           int *colorOffset);
 protected:
-
+    
     // Helpers for GrDrawTarget subclasses that won't have private access to
     // SavedDrawState but need to peek at the state values.
     static DrState& accessSavedDrawState(SavedDrawState& sds)
@@ -708,9 +815,6 @@
 
     DrState fCurrDrawState;
 
-    // set texture or modelview matrix
-    void loadMatrix(const GrMatrix&, MatrixMode);
-
     // not meant for outside usage. Could cause problems if calls between
     // the save and restore mess with reserved geometry state.
     class AutoGeometrySrcRestore {
@@ -731,6 +835,8 @@
         AutoGeometrySrcRestore& operator =(AutoGeometrySrcRestore&);
     };
 
+private:
+    void VertexLayoutUnitTest();
 };
 
 #endif